/**
* Copyright (c) 2006 - 2012 Smaxe Ltd (www.smaxe.com).
* All rights reserved.
*/
import com.smaxe.uv.media.core.VideoFrame;
import com.smaxe.uv.media.java.fx.JfxVideoScreen;
import com.smaxe.uv.na.WebcamFactory;
import com.smaxe.uv.na.webcam.IWebcam;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
/**
* <code>ExJfxNativeAccessWebcam</code> - {@link IWebcam} usage example in JavaFx environment.
*
* @author Andrei Sochirca
* @see <a href="http://www.smaxe.com/product.jsf?id=juv-webcam-sdk" target="_blank">JUV Webcam SDK</a>
*/
public final class ExJfxNativeAccessWebcam extends Application
{
/**
* Entry point.
*
* @param args
* @throws Exception if an exception occurred
*/
public static void main(final String[] args) throws Exception
{
launch(args);
}
/**
* <code>EnumerateWebcamsEventHandler</code> - 'Enumerqtes Webcams' event handler.
*/
private final class EnumerateWebcamsEventHandler extends Object implements EventHandler<ActionEvent>
{
public void handle(final ActionEvent event)
{
executor.execute(new Runnable()
{
public void run()
{
final List<IWebcam> webcams = WebcamFactory.getWebcams();
Platform.runLater(new Runnable()
{
public void run()
{
webcamChoiceBox.getItems().setAll(webcams);
}
});
}
});
}
};
/**
* <code>SetWebcamFrameFormatEventHandler</code> - 'Open Webcam' event handler.
*/
private final class SetWebcamFrameFormatEventHandler extends Object implements EventHandler<ActionEvent>
{
// fields
private final Executor executor;
private final IWebcam webcam;
private final IWebcam.FrameFormat format;
/**
* Constructor.
*
* @param executor
* @param webcam
* @param format
*/
public SetWebcamFrameFormatEventHandler(final Executor executor, final IWebcam webcam, final IWebcam.FrameFormat format)
{
this.executor = executor;
this.webcam = webcam;
this.format = format;
}
// EventHandler implementation
public void handle(final ActionEvent event)
{
executor.execute(new Runnable()
{
public void run()
{
webcam.setFrameFormat(format);
}
});
}
}
/**
* <code>OpenWebcamEventHandler</code> - 'Open Webcam' event handler.
*/
private final class OpenWebcamEventHandler extends Object implements EventHandler<ActionEvent>
{
public void handle(final ActionEvent event)
{
final IWebcam webcam = webcamChoiceBox.getSelectionModel().getSelectedItem();
if (webcam == null) return;
final AtomicReference<Stage> stageRef = new AtomicReference<Stage>();
final JfxVideoScreen videoScreen = new JfxVideoScreen();
videoScreen.setAutoScaleOnResize(false);
executor.execute(new Runnable()
{
public void run()
{
final AtomicReference<VideoFrame> lastFrameRef = new AtomicReference<VideoFrame>();
try
{
webcam.open(new IWebcam.FrameFormat(320, 240), new IWebcam.IListenerX()
{
private VideoFrame lastFrame = new VideoFrame(0, 0, null);
public void onVideoFrame(final VideoFrame frame)
{
Platform.runLater(new Runnable()
{
public void run()
{
videoScreen.setFrame(frame);
if (lastFrame.width != frame.width || lastFrame.height != frame.height)
{
final Stage stage = stageRef.get();
if (stage != null)
{
stage.sizeToScene();
}
}
lastFrame = frame;
lastFrameRef.set(lastFrame);
}
});
}
public void onVideoFrameTimeout(final long timeout)
{
System.out.println("onVideoFrameTimeout: " + timeout + "ms");
}
public void onVideoInfo(final float frameRate, final long frames)
{
System.out.println("onVideoInfo: frameRate=" + frameRate + ", frames=" + frames);
}
});
final IWebcam.FrameFormat[] supportedFormats = webcam.getFormats();
if (supportedFormats != null)
{
System.out.println("Webcam: " + webcam.getName());
System.out.println("Supported formats: ");
for (IWebcam.FrameFormat format : supportedFormats)
{
System.out.println("=> " + format);
}
}
webcam.startCapture();
Platform.runLater(new Runnable()
{
public void run()
{
final Stage stage = new Stage();
stage.setResizable(false);
stage.setScene(new Scene(new BorderPane(videoScreen)));
stage.setTitle(webcam.getName());
stageRef.set(stage);
videoScreen.setOnMouseClicked(new EventHandler<MouseEvent>()
{
public void handle(final MouseEvent event)
{
if (event.getClickCount() != 1) return;
if (event.getButton() != MouseButton.SECONDARY) return;
ContextMenu popup = new ContextMenu();
MenuItem takeSnapshot = new MenuItem("Take Snapshot");
takeSnapshot.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(final ActionEvent e)
{
}
});
MenuItem mirror = new MenuItem("Mirror");
mirror.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(final ActionEvent e)
{
videoScreen.mirror(!videoScreen.getMirrorFlag());
}
});
MenuItem flip = new MenuItem("Flip");
flip.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(final ActionEvent e)
{
videoScreen.flip(!videoScreen.getFlipFlag());
}
});
ObservableList<MenuItem> items = popup.getItems();
items.add(takeSnapshot);
items.add(new SeparatorMenuItem());
items.add(mirror);
items.add(flip);
items.add(new SeparatorMenuItem());
for (IWebcam.FrameFormat format : supportedFormats)
{
MenuItem mi = new MenuItem("" + format.width + "x" + format.height);
mi.setOnAction(new SetWebcamFrameFormatEventHandler(executor, webcam, format));
items.add(mi);
}
popup.setAutoHide(true);
popup.setHideOnEscape(true);
popup.show(videoScreen, event.getScreenX(), event.getScreenY());
}
});
stage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
public void handle(final WindowEvent event)
{
webcam.close();
}
});
stage.show();
}
});
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
});
}
};
// fields
private ExecutorService executor = null;
// ui
private ChoiceBox<IWebcam> webcamChoiceBox;
// Application implementation
/**
* Constructor.
*/
public ExJfxNativeAccessWebcam()
{
}
@Override
public void init() throws Exception
{
super.init();
executor = Executors.newSingleThreadExecutor();
}
@Override
public void start(Stage stage) throws Exception
{
Scene scene = new Scene(createComponents());
stage.setResizable(false);
stage.setScene(scene);
stage.setTitle("Webcam capture options");
new EnumerateWebcamsEventHandler().handle(null);
stage.sizeToScene();
stage.show();
}
@Override
public void stop() throws Exception
{
executor.shutdown();
super.stop();
}
// inner use methods
/**
* Creates and places components(class fields) in the container.
*
* @return components container
*/
private Parent createComponents()
{
webcamChoiceBox = new ChoiceBox<IWebcam>();
webcamChoiceBox.setFocusTraversable(false);
webcamChoiceBox.setPrefWidth(240);
BorderPane layout = new BorderPane();
Button webcamsButton = new Button("Webcams");
Button openButton = new Button("Open");
webcamsButton.setFocusTraversable(false);
webcamsButton.setOnAction(new EnumerateWebcamsEventHandler());
openButton.setFocusTraversable(false);
openButton.setOnAction(new OpenWebcamEventHandler());
BorderPane.setMargin(webcamsButton, new Insets(8, 8, 8, 8));
BorderPane.setMargin(openButton, new Insets(8, 8, 8, 8));
layout.setLeft(webcamsButton);
layout.setCenter(webcamChoiceBox);
layout.setRight(openButton);
return layout;
}
}