Skip to content

Commit

Permalink
Deallocate devices on TERM signal (experimental feature)
Browse files Browse the repository at this point in the history
closes #10
  • Loading branch information
sarxos committed Jan 7, 2013
1 parent 064efa2 commit 9c8acf3
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 56 deletions.
34 changes: 17 additions & 17 deletions .project
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>webcam-capture</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>webcam-capture-parent</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
57 changes: 26 additions & 31 deletions webcam-capture-examples/webcam-capture-manycams/.classpath
@@ -1,31 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
35 changes: 31 additions & 4 deletions webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java
Expand Up @@ -23,13 +23,13 @@ public class Webcam {

private static final Logger LOG = LoggerFactory.getLogger(Webcam.class);

//@formatter:off
// @formatter:off
private static final String[] DRIVERS_DEFAULT = new String[] {
"com.github.sarxos.webcam.ds.openimaj.OpenImajDriver",
"com.github.sarxos.webcam.ds.civil.LtiCivilDriver",
"com.github.sarxos.webcam.ds.jmf.JmfDriver",
};
//@formatter:on
// @formatter:on

private static final List<String> DRIVERS_LIST = new ArrayList<String>(Arrays.asList(DRIVERS_DEFAULT));
private static final List<Class<?>> DRIVERS_CLASS_LIST = new ArrayList<Class<?>>();
Expand All @@ -54,6 +54,11 @@ public void run() {
private static WebcamDriver driver = null;
private static List<Webcam> webcams = null;

/**
* Is automated deallocation on TERM signal enabled.
*/
private static volatile boolean deallocOnTermSignal = false;

/**
* Webcam listeners.
*/
Expand Down Expand Up @@ -144,7 +149,7 @@ public synchronized void close() {
}

/**
* Close webcam.
* Close webcam (internal impl).
*/
private void close0() {

Expand Down Expand Up @@ -285,7 +290,14 @@ public static List<Webcam> getWebcams() {
driver = new WebcamDefaultDriver();
}

for (WebcamDevice device : driver.getDevices()) {
List<WebcamDevice> devices = driver.getDevices();

if (deallocOnTermSignal) {
LOG.warn("Automated deallocation on TERM signal is enabled!");
WebcamDeallocator.store(devices.toArray(new WebcamDevice[devices.size()]));
}

for (WebcamDevice device : devices) {
webcams.add(new Webcam(device));
}

Expand Down Expand Up @@ -462,4 +474,19 @@ protected void dispose() {
device.close();
device.dispose();
}

/**
* <b>CAUTION!!!</b><br>
* <br>
* This is experimental feature to be used mostly in in development phase.
* After you set handle term signal to true, and fetch capture devices,
* Webcam Capture API will listen for TERM signal and try to close all
* devices after it has been received. <b>This feature can be unstable on
* some systems!</b>
*
* @param on
*/
public static void handleTermSignal(boolean on) {
deallocOnTermSignal = on;
}
}
@@ -0,0 +1,68 @@
package com.github.sarxos.webcam;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Observable;
import java.util.Observer;



/**
* Deallocator which goal is to release all devices resources when SIGTERM
* signal is detected.
*
* @author Bartosz Firyn (SarXos)
*/
class WebcamDeallocator implements Observer {

private WebcamDevice[] devices = null;
private WebcamSignalHandler handler = new WebcamSignalHandler();

/**
* This constructor is used internally to create new deallocator for the
* given devices array.
*
* @param devices the devices to be stored in deallocator
*/
private WebcamDeallocator(WebcamDevice[] devices) {
if (devices != null && devices.length > 0) {
this.devices = devices;
this.handler.listen("TERM", this);
}
}

/**
* Store devices to be deallocated when TERM signal has been received.
*
* @param devices the devices array to be stored by deallocator
*/
protected static final void store(WebcamDevice[] devices) {
new WebcamDeallocator(devices);
}

@Override
public void update(Observable observable, Object object) {
for (WebcamDevice device : devices) {
try {
device.close();
} catch (Throwable t) {
caugh(t);
}
}
}

public void caugh(Throwable e) {
File f = new File(String.format("webcam-capture-hs-%s", System.currentTimeMillis()));
PrintStream ps = null;
try {
e.printStackTrace(ps = new PrintStream(f));
} catch (FileNotFoundException e2) {
// ignore, stdout is not working, cannot do anything more
} finally {
if (ps != null) {
ps.close();
}
}
}
}
@@ -0,0 +1,42 @@
package com.github.sarxos.webcam;

import java.util.Observable;
import java.util.Observer;

import sun.misc.Signal;
import sun.misc.SignalHandler;


/**
* Primitive signal handler. This class is using undocumented classes from
* sun.misc.* and therefore should be used with caution.
*
* @author Bartosz Firyn (SarXos)
*/
@SuppressWarnings("restriction")
class WebcamSignalHandler extends Observable implements SignalHandler {

private SignalHandler handler = null;

public void listen(String signal, Observer observer) throws IllegalArgumentException {
addObserver(observer);
handler = Signal.handle(new Signal(signal), this);
}

@Override
public void handle(final sun.misc.Signal signal) {

// do nothing on "signal default" or "signal ignore"
if (handler == SIG_DFL || handler == SIG_IGN) {
return;
}

setChanged();

try {
notifyObservers(signal);
} finally {
handler.handle(signal);
}
}
}
Expand Up @@ -50,7 +50,7 @@ public class WebcamDefaultDevice implements WebcamDevice {
* Artificial view sizes. I'm really not sure if will fit into other webcams
* but hope that OpenIMAJ can handle this.
*/
//@formatter:off
// @formatter:off
private final static Dimension[] DIMENSIONS = new Dimension[] {
SIZE_QQVGA,
SIZE_QVGA,
Expand All @@ -59,7 +59,7 @@ public class WebcamDefaultDevice implements WebcamDevice {
SIZE_VGA,
SIZE_XGA,
};
//@formatter:on
// @formatter:on

/**
* RGB offsets.
Expand Down
Expand Up @@ -3,17 +3,38 @@
import com.github.sarxos.webcam.ds.buildin.natives.OpenIMAJGrabber;


/**
* Abstract webcam processor class.
*
* @author Bartosz Firyn (SarXos)
*/
public abstract class WebcamGrabberTask {

/**
* Native grabber.
*/
protected volatile OpenIMAJGrabber grabber = null;

protected void process(WebcamGrabberProcessor grabber) {
grabber.process(this);
/**
* Process task by processor thread.
*
* @param processor the processor to be used to process this task
*/
protected void process(WebcamGrabberProcessor processor) {
processor.process(this);
}

/**
* Set grabber connected with specific device.
*
* @param grabber the grabber to be set
*/
public void setGrabber(OpenIMAJGrabber grabber) {
this.grabber = grabber;
}

/**
* Method to be called from inside of the processor thread.
*/
protected abstract void handle();
}
Expand Up @@ -4,14 +4,30 @@
import com.github.sarxos.webcam.ds.buildin.WebcamGrabberTask;


/**
* This task is to close grabber session.
*
* @author Bartosz Firyn (SarXos)
*/
public class CloseSessionTask extends WebcamGrabberTask {

/**
* Grabber processor.
*/
private WebcamGrabberProcessor processor = null;

/**
* Create task closing session of grabber connected with specific device.
*
* @param processor
*/
public CloseSessionTask(WebcamGrabberProcessor processor) {
this.processor = processor;
}

/**
* Method to be called from outside of the processor thread.
*/
public void closeSession() {
process(processor);
}
Expand Down

0 comments on commit 9c8acf3

Please sign in to comment.