/**
* Squidy Interaction Library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Squidy Interaction Library is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Squidy Interaction Library. If not, see
* <http://www.gnu.org/licenses/>.
*
* 2009 Human-Computer Interaction Group, University of Konstanz.
* <http://hci.uni-konstanz.de>
*
* Please contact info@squidy-lib.de or visit our website
* <http://www.squidy-lib.de> for further information.
*/
package org.squidy.nodes;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squidy.designer.Designer;
import org.squidy.manager.ProcessException;
import org.squidy.manager.commander.ControlClient;
import org.squidy.manager.commander.command.SwitchableCommand;
import org.squidy.manager.commander.command.utility.Switch;
import org.squidy.manager.controls.CheckBox;
import org.squidy.manager.controls.ComboBox;
import org.squidy.manager.controls.Slider;
import org.squidy.manager.controls.TextField;
import org.squidy.manager.controls.ComboBoxControl.ComboBoxItemWrapper;
import org.squidy.manager.data.DataConstant;
import org.squidy.manager.data.IDataContainer;
import org.squidy.manager.data.Processor;
import org.squidy.manager.data.Property;
import org.squidy.manager.data.Processor.Status;
import org.squidy.manager.data.domainprovider.DomainProvider;
import org.squidy.manager.data.domainprovider.impl.EndianDomainProvider;
import org.squidy.manager.data.impl.DataPosition2D;
import org.squidy.manager.model.AbstractNode;
import org.squidy.manager.util.DataUtility;
import org.squidy.nodes.plugin.PatternScreen;
import org.squidy.nodes.tracking.CameraCallback;
import org.squidy.nodes.tracking.CameraConfigComm;
import org.squidy.nodes.tracking.LaserServer;
import org.squidy.nodes.tracking.config.ConfigNotifier;
import org.squidy.nodes.tracking.proxy.ProxyServer;
import com.illposed.osc.Endian;
import com.illposed.osc.OSCBundle;
import com.illposed.osc.OSCListener;
import com.illposed.osc.OSCMessage;
import com.illposed.osc.OSCPortIn;
import com.illposed.osc.OSCPortOut;
/**
* <code>MultiTouch</code>.
*
* <pre>
* Date: Feb 28, 2008
* Time: 3:34:49 PM
* </pre>
*
* @author Werner Koenig, werner.koenig@uni-konstanz.de, University of Konstanz
* @author Roman Rädle, <a
* href="mailto:Roman.Raedle@uni-konstanz.de">Roman.
* Raedle@uni-konstanz.de</a>, University of Konstanz
* @author Toni Schmidt, <a href="mailto:Toni.Schmidt@uni-konstanz.de">Toni.
* Schmidt@uni-konstanz.de</a>, University of Konstanz
* @version $Id
* @since 1.0
*
*/
@XmlType(name = "MultiTouch")
@Processor(name = "Multi-Touch", icon = "/org/squidy/nodes/image/48x48/multitouch-icon.png", description = "/org/squidy/nodes/html/MultiTouch.html", types = { Processor.Type.INPUT }, tags = {
"multi", "touch", "multi-touch", "multitouch", "tracking" }, status = Status.STABLE)
public class MultiTouch extends AbstractNode implements CameraCallback {
// Logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(MultiTouch.class);
// ################################################################################
// BEGIN OF DATA CONSTANTS
// ################################################################################
// ################################################################################
// BEGIN OF TUIO DEFINED PARAMETERS
// ################################################################################
public static final DataConstant TUIO_ORIGIN_ADDRESS = DataConstant.get(
String.class, "TUIO_ORIGIN_ADDRESS");
public static final DataConstant TUIO_MOVEMENT_VECTOR_X = DataConstant.get(
Float.class, "TUIO_MOVEMENT_VECTOR_X");
public static final DataConstant TUIO_MOVEMENT_VECTOR_Y = DataConstant.get(
Float.class, "TUIO_MOVEMENT_VECTOR_Y");
public static final DataConstant TUIO_MOTION_ACCELERATION = DataConstant
.get(Float.class, "TUIO_MOTION_ACCELERATION");
public static final DataConstant TUIO_ANGLE_A = DataConstant.get(
Float.class, "TUIO_ANGLE_A");
public static final DataConstant TUIO_ANGLE_B = DataConstant.get(
Float.class, "TUIO_ANGLE_B");
public static final DataConstant TUIO_ANGLE_C = DataConstant.get(
Float.class, "TUIO_ANGLE_C");
public static final DataConstant SOURCE = DataConstant.get(Integer.class,
"SOURCE");
// ################################################################################
// END OF TUIO DEFINED PARAMETERS
// ################################################################################
// ################################################################################
// BEGIN OF FREE DEFINED PARAMETERS
// ################################################################################
public static final DataConstant TUIO_HAND_WIDTH = DataConstant.get(
Float.class, "TUIO_HAND_WIDTH");
public static final DataConstant TUIO_HAND_HEIGHT = DataConstant.get(
Float.class, "TUIO_HAND_HEIGHT");
// ################################################################################
// END OF FREE DEFINED PARAMETERS
// ################################################################################
// ################################################################################
// BEGIN OF ADJUSTABLES
// ################################################################################
/*
* @XmlAttribute(name = "tracking-sensitivity")
*
* @Property(name = "Tracking Sensitivity", group = "Camera Configuration",
* description = "Tracking Sensitivity")
*
* @Slider(type = Integer.class, minimumValue = 0, maximumValue = 200,
* showLabels = true, showTicks = true, majorTicks = 100, minorTicks = 10,
* snapToTicks = false) private int trackingSensitivity = 200;
*
*
* public int getTrackingSensitivity() { return trackingSensitivity; }
*
* public void setTrackingSensitivity(int trackingSensitivity) { float
* fSensitivity = (float)trackingSensitivity / 10.0f;
* this.trackingSensitivity = trackingSensitivity;
* cameraConfigComm.sendParameter("tracking-sensitivity", "float",
* Float.toString(fSensitivity)); }
*/
@XmlAttribute(name = "tracking-sensitivity")
@Property(name = "Tracking Sensitivity", group = "Camera Configuration", description = "Tracking Sensitivity")
@TextField
private int trackingSensitivity = 200;
public int getTrackingSensitivity() {
return trackingSensitivity;
}
public void setTrackingSensitivity(int trackingSensitivity) {
float fSensitivity = (float) trackingSensitivity / 10.0f;
this.trackingSensitivity = trackingSensitivity;
cameraConfigComm.sendParameter("tracking-sensitivity", "float", Float
.toString(fSensitivity));
}
@XmlAttribute(name = "pixelclock")
@Property(name = "Pixelclock", group = "Camera Configuration", description = "Pixelclock")
@Slider(type = Integer.class, minimumValue = 0, maximumValue = 60, showLabels = true, showTicks = true, majorTicks = 10, minorTicks = 1, snapToTicks = false)
private int pixelclock = 60;
public int getPixelclock() {
return pixelclock;
}
public void setPixelclock(int pixelclock) {
this.pixelclock = pixelclock;
cameraConfigComm.sendParameter("pixelclock", "int", Integer
.toString(pixelclock));
cameraConfigComm
.sendParameter("exposure", "int", Integer.toString(200));
cameraConfigComm.sendParameter("framerate", "int", Integer
.toString(120));
}
public void refreshPixelclock(int pixelclock) {
fireStatusChange("pixelclock", getPixelclock(), pixelclock);
this.pixelclock = pixelclock;
}
@XmlAttribute(name = "framerate")
@Property(name = "Framerate", group = "Camera Configuration", description = "Framerate")
@Slider(type = Integer.class, minimumValue = 0, maximumValue = 200, showLabels = true, showTicks = true, majorTicks = 50, minorTicks = 10, snapToTicks = false)
private int framerate = 120;
public int getFramerate() {
return framerate;
}
public void setFramerate(int framerate) {
this.framerate = framerate;
// cameraConfigComm.sendParameter("pixelclock", "int",
// Integer.toString(pixelclock));
cameraConfigComm.sendParameter("framerate", "int", Integer
.toString(framerate));
// cameraConfigComm.sendParameter("exposure", "int",
// Integer.toString(exposure));
}
public void refreshFramerate(int framerate) {
fireStatusChange("framerate", getFramerate(), framerate);
this.framerate = framerate;
}
@XmlAttribute(name = "exposure")
@Property(name = "Exposure", group = "Camera Configuration", description = "Exposure")
@Slider(type = Integer.class, minimumValue = 0, maximumValue = 200, showLabels = true, showTicks = true, majorTicks = 50, minorTicks = 10, snapToTicks = false)
private int exposure = 9;
public int getExposure() {
return exposure;
}
public void setExposure(int exposure) {
this.exposure = exposure;
// cameraConfigComm.sendParameter("pixelclock", "int",
// Integer.toString(pixelclock));
// cameraConfigComm.sendParameter("framerate", "int",
// Integer.toString(framerate));
cameraConfigComm.sendParameter("exposure", "int", Integer
.toString(exposure));
}
public void refreshExposure(int exposure) {
fireStatusChange("exposure", getExposure(), exposure);
this.exposure = exposure;
}
@XmlAttribute(name = "dynamic-backdiff")
@Property(name = "Dynamic Background Subtraction", group = "Camera Configuration", description = "Turn dynamic background subtraction on/off")
@CheckBox
private boolean dynamicBackdiff = false;
public boolean isDynamicBackdiff() {
return dynamicBackdiff;
}
public void setDynamicBackdiff(boolean dynamicBackdiff) {
this.dynamicBackdiff = dynamicBackdiff;
cameraConfigComm.sendParameter("dynamic-backdiff", "bool", Boolean
.toString(dynamicBackdiff));
}
@XmlAttribute(name = "backdiff-tresh")
@Property(name = "Background Subtraction Treshold", group = "Camera Configuration", description = "All pixels brighter (i.e. larger) than the background subtraction treshold will be set to 255 (i.e. pure white)")
@Slider(type = Integer.class, minimumValue = 0, maximumValue = 255, showLabels = true, showTicks = true, majorTicks = 50, minorTicks = 10, snapToTicks = false)
private int backdiffTresh = 100;
public int getBackdiffTresh() {
return backdiffTresh;
}
public void setBackdiffTresh(int backdiffTresh) {
this.backdiffTresh = backdiffTresh;
cameraConfigComm.sendParameter("backdiff-tresh", "int", Integer
.toString(backdiffTresh));
}
@XmlAttribute(name = "dynamic-backdiff-speed")
@Property(name = "Dynamic Background Subtraction Frequency", group = "Camera Configuration", description = "Camera ID", suffix = "ms")
@TextField
private int dynamicBackdiffSpeed = 1000;
public int getDynamicBackdiffSpeed() {
return dynamicBackdiffSpeed;
}
public void setDynamicBackdiffSpeed(int dynamicBackdiffSpeed) {
this.dynamicBackdiffSpeed = dynamicBackdiffSpeed;
cameraConfigComm.sendParameter("dynamic-backdiff-speed", "int", Integer
.toString(dynamicBackdiffSpeed));
}
@XmlAttribute(name = "track-fingers")
@Property(name = "Track Fingers", group = "Camera Configuration", description = "Turn finger tracking on/off")
@CheckBox
private boolean trackFingers = false;
public boolean isTrackFingers() {
return trackFingers;
}
public void setTrackFingers(boolean trackFingers) {
this.trackFingers = trackFingers;
if (trackFingers == true) {
sendAllTrackingParams();
setPixelclock(getPixelclock());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
cameraConfigComm.sendParameter("track-fingers", "bool", Boolean
.toString(trackFingers));
setPixelclock(getPixelclock());
} else
cameraConfigComm.sendParameter("track-fingers", "bool", Boolean
.toString(trackFingers));
}
@XmlAttribute(name = "track-contours")
@Property(name = "Track Contours", group = "Camera Configuration", description = "Turn contour tracking on/off")
@CheckBox
private boolean trackContours = false;
public boolean isTrackContours() {
return trackContours;
}
public void setTrackContours(boolean trackContours) {
this.trackContours = trackContours;
cameraConfigComm.sendParameter("track-contours", "bool", Boolean
.toString(trackContours));
}
/*
* @XmlAttribute(name = "remote-squidy-port")
*
* @Property(name = "Remote Port", group = "Camera Calibration", description
* = "Remote port of Squidy Coontroller")
*
* @TextField private int remoteSquidyPort = 9999; public int
* getRemoteSquidyPort() { return remoteSquidyPort; }
*
* public void setRemoteSquidyPort(int remoteSquidyPort) {
* this.remoteSquidyPort = remoteSquidyPort; }
*/
@XmlAttribute(name = "pattern-width")
@Property(name = "Pattern Width", group = "Camera Calibration", description = "Calibration Pattern Width")
@TextField
private int patternW = 5;
public int getPatternW() {
return patternW;
}
public void setPatternW(int patternW) {
this.patternW = patternW;
if (imageDisplay != null) {
imageDisplay.setRequiredCornerPoints(patternW * patternH);
}
cameraConfigComm.sendParameter("pattern-width", "int", Integer
.toString(patternW));
}
@XmlAttribute(name = "pattern-height")
@Property(name = "Pattern Height", group = "Camera Calibration", description = "Calibration Pattern Height")
@TextField
private int patternH = 5;
public int getPatternH() {
return patternH;
}
public void setPatternH(int patternH) {
this.patternH = patternH;
if (imageDisplay != null) {
imageDisplay.setRequiredCornerPoints(patternW * patternH);
}
cameraConfigComm.sendParameter("pattern-height", "int", Integer
.toString(patternH));
}
@XmlAttribute(name = "screen-res-w")
@Property(name = "Screen Resolution Width", group = "Camera Calibration", description = "Screen pixel width")
@TextField
private int screenResW = 1920;
public int getScreenResW() {
return screenResW;
}
public void setScreenResW(int screenResW) {
this.screenResW = screenResW;
}
@XmlAttribute(name = "screen-res-h")
@Property(name = "Screen Resolution Height", group = "Camera Calibration", description = "Screen pixel height")
@TextField
private int screenResH = 1080;
public int getScreenResH() {
return screenResH;
}
public void setScreenResH(int screenResH) {
this.screenResH = screenResH;
}
@XmlAttribute(name = "image-stream-mode")
@Property(name = "Image Stream Mode", group = "Camera Configuration")
@ComboBox(domainProvider = ModeDomainProvider.class)
private int mode = MODE_OFF;
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
if (mode == MODE_OFF) {
cameraConfigComm.sendParameter("stream_image", "bool", "false");
frame.setVisible(false);
} else {
frame.setVisible(true);
cameraConfigComm.sendParameter("stream_image", "bool", "true");
cameraConfigComm.sendParameter("image-stream-mode", "int", Integer
.toString(mode));
}
}
@XmlAttribute(name = "pattern-device")
@Property(name = "Screen", group = "Camera Calibration")
@ComboBox(domainProvider = PatternDomainProvider.class)
private int patternDevice = 0;
public int getPatternDevice() {
return patternDevice;
}
public void setPatternDevice(int patternDevice) {
this.patternDevice = patternDevice;
}
@XmlAttribute(name = "display-pattern")
@Property(name = "Display Pattern", group = "Camera Calibration", description = "Turn calibration pattern on/off")
@CheckBox
private boolean displayPattern = false;
public boolean isDisplayPattern() {
return displayPattern;
}
public void setDisplayPattern(boolean displayPattern) {
InetAddress address = null;
try {
address = InetAddress.getByName(getRemoteAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
/*
* if (client != null) { client.close(); client = null; }
*/
if (client == null) {
System.out.println("Create new Control Client");
client = new ControlClient(address, getRemotePort());
}
} catch (IOException e) {
e.printStackTrace();
}
String id = Integer.toString(getPatternDevice());
String deviceId = "\\Display" + id;
SwitchableCommand command = new PatternScreen(deviceId,
getScreenResW(), getScreenResH(), getPatternW() - 1,
getPatternH() - 1);
command.setState(displayPattern ? Switch.ON : Switch.OFF);
client.send(command);
Designer.getInstance().requestFocus();
this.displayPattern = displayPattern;
}
@XmlAttribute(name = "remote-address")
@Property(name = "Remote address", group = "Remote Connection")
@TextField
private String remoteAddress = "127.0.0.1";
/**
* @return the remoteAddress
*/
public final String getRemoteAddress() {
return remoteAddress;
}
/**
* @param remoteAddress
* the remoteAddress to set
*/
public final void setRemoteAddress(String remoteAddress) {
this.remoteAddress = remoteAddress;
cameraConfigComm.sendParameter("remote-address", "String",
remoteAddress);
}
// ################################################################################
private static final int REMOTE_PORT_OFFSET = 4200; //offsets relative to cameraID
private static final int OSC_PORT_OUT_OFFSET = 4000;
private static final int OSC_PORT_IN_OFFSET = 4100;
@XmlAttribute(name = "remote-port")
@Property(name = "Remote port", group = "Remote Connection")
@TextField
private int remotePort = REMOTE_PORT_OFFSET;
/**
* @return the remotePort
*/
public final int getRemotePort() {
return remotePort;
}
/**
* @param remotePort
* the remotePort to set
*/
public final void setRemotePort(int remotePort) {
if (remotePort != this.remotePort) {
//do not change port number
//but show message ...
publishNotification("The Remote Port number depends on the Camera ID field.");
//... and reset displayed value
refreshRemotePort(cameraID + REMOTE_PORT_OFFSET);
}
}
public final void refreshRemotePort(int remotePort) {
fireStatusChange("remotePort", "", ((Integer)remotePort).toString());
this.remotePort = remotePort;
}
@XmlAttribute(name = "osc-port-out")
@Property(name = "OSC Port Out", group = "Remote Connection")
@TextField
private int oscPortConfigOut = OSC_PORT_OUT_OFFSET;
public int getOscPortConfigOut() {
return oscPortConfigOut;
}
public void setOscPortConfigOut(int oscPortConfigOut) {
if (oscPortConfigOut != this.oscPortConfigOut) {
//do not change port number
//but show message ...
publishNotification("OSC Port Out depends on the Camera ID field.");
//... and reset displayed value
refreshOscPortConfigOut(cameraID + OSC_PORT_OUT_OFFSET);
}
}
public void refreshOscPortConfigOut(int oscPortConfigOut) {
fireStatusChange("oscPortConfigOut", "", ((Integer)oscPortConfigOut).toString());
this.oscPortConfigOut = oscPortConfigOut;
if (cameraConfigComm != null) {
cameraConfigComm.setPortOutgoing(oscPortConfigOut);
cameraConfigComm.sendParameter("osc-port-out", "int", Integer
.toString(oscPortConfigOut));
}
}
@XmlAttribute(name = "osc-port-in")
@Property(name = "OSC Port In", group = "Remote Connection")
@TextField
private int oscPortConfigIn = OSC_PORT_IN_OFFSET;
public int getOscPortConfigIn() {
return oscPortConfigIn;
}
public void setOscPortConfigIn(int oscPortConfigIn) {
if (oscPortConfigIn != this.oscPortConfigIn) {
//do not change port number
//but show message ...
publishNotification("OSC Port In depends on the Camera ID field.");
//... and reset displayed value
refreshOscPortConfigIn(cameraID + OSC_PORT_IN_OFFSET);
}
}
public void refreshOscPortConfigIn(int oscPortConfigIn) {
fireStatusChange("oscPortConfigIn", "", ((Integer)oscPortConfigIn).toString());
this.oscPortConfigIn = oscPortConfigIn;
if (cameraConfigComm != null) {
cameraConfigComm.setPortIncoming(oscPortConfigIn);
cameraConfigComm.sendParameter("osc-port-in", "int", Integer
.toString(oscPortConfigIn));
}
}
@XmlAttribute(name = "image-server-port")
@Property(name = "Image Streaming Port", group = "Remote Connection")
@TextField
private int imageServerPort = 7777;
public int getImageServerPort() {
return imageServerPort;
}
public void setImageServerPort(int imageServerPort) {
this.imageServerPort = imageServerPort;
cameraConfigComm.setImageServerPort(imageServerPort);
cameraConfigComm.sendParameter("image-server-port", "int", Integer
.toString(imageServerPort));
}
@XmlAttribute(name = "show-pattern")
@Property(name = "Show pattern", description = "Whether a pattern should be shown for calibration frame or not.")
@CheckBox
private boolean showPattern = true;
/**
* @return the showPattern
*/
public final boolean isShowPattern() {
return showPattern;
}
/**
* @param showPattern
* the showPattern to set
*/
public final void setShowPattern(boolean showPattern) {
this.showPattern = showPattern;
}
// ################################################################################
@XmlAttribute(name = "show-white")
@Property(name = "Show white", description = "Whether a white fullscreen image should be shown for background subtraction when cameras get started.")
@CheckBox
private boolean showWhite = true;
/**
* @return the showWhite
*/
public final boolean isShowWhite() {
return showWhite;
}
/**
* @param showWhite
* the showWhite to set
*/
public final void setShowWhite(boolean showWhite) {
this.showWhite = showWhite;
}
@XmlAttribute(name = "corner-points")
public String cornerPointsStr = "";
public String getCornerPointsStr() {
return cornerPointsStr;
}
public void setCornerPointsStr(String cornerPointsStr) {
this.cornerPointsStr = cornerPointsStr;
}
// ################################################################################
public final void setPortIncoming(int portIncoming) {
this.portIncoming = portIncoming;
cameraConfigComm.sendParameter("port-tuio", "int", Integer
.toString(portIncoming));
}
@XmlAttribute(name = "repaint-img")
@Property(name = "Show live image in camera window", group = "Camera Configuration", description = "Show live image in camera window on/off")
@CheckBox
private boolean repaintImg = false;
public boolean isRepaintImg() {
return repaintImg;
}
public void setRepaintImg(boolean repaintImg) {
this.repaintImg = repaintImg;
cameraConfigComm.sendParameter("repaint-img", "bool", Boolean
.toString(repaintImg));
}
@XmlAttribute(name = "print-fps")
@Property(name = "Print Camera FPS", group = "Camera Configuration", description = "Print camera fps to console on/off")
@CheckBox
private boolean printFPS = false;
public boolean isPrintFPS() {
return printFPS;
}
public void setPrintFPS(boolean printFPS) {
this.printFPS = printFPS;
cameraConfigComm.sendParameter("print-fps", "bool", Boolean
.toString(printFPS));
}
@XmlAttribute(name = "start-tracking-automatically")
@Property(name = "Start camera automatically", group = "Camera Configuration", description = "Start Tracking software automatically on/off")
@CheckBox
private boolean startTrackingAutomatically = false;
public boolean isStartTrackingAutomatically() {
return startTrackingAutomatically;
}
public void setStartTrackingAutomatically(boolean startTrackingAutomatically) {
this.startTrackingAutomatically = startTrackingAutomatically;
}
@XmlAttribute(name = "camera-id")
@Property(name = "Camera ID", group = "Advanced Configuration", description = "Camera ID")
@TextField
private int cameraID = 37;
public int getCameraID() {
return cameraID;
}
public void setCameraID(int cameraID) {
this.cameraID = cameraID;
refreshRemotePort(cameraID + REMOTE_PORT_OFFSET);
this.refreshOscPortConfigOut(cameraID + OSC_PORT_OUT_OFFSET);
this.refreshOscPortConfigIn(cameraID + OSC_PORT_IN_OFFSET);
}
@XmlAttribute(name = "homogenization")
@Property(name = "Homogenization", group = "Advanced Configuration", description = "Turn homogenization on/off")
@CheckBox
private boolean homogenization = false;
public boolean isHomogenization() {
return homogenization;
}
public void setHomogenization(boolean homogenization) {
this.homogenization = homogenization;
cameraConfigComm.sendParameter("homogenization", "bool", Boolean
.toString(homogenization));
}
@XmlAttribute(name = "backdiff")
@Property(name = "Background Subtraction", group = "Advanced Configuration", description = "Turn initial background subtraction on/off")
@CheckBox
private boolean backdiff = false;
public boolean isBackdiff() {
return backdiff;
}
public void setBackdiff(boolean backdiff) {
this.backdiff = backdiff;
cameraConfigComm.sendParameter("backdiff", "bool", Boolean
.toString(backdiff));
}
@XmlAttribute(name = "subsampling")
@Property(name = "Subsampling", group = "Advanced Configuration", description = "Camera Subsampling property")
@TextField
private int subsampling = 3;
public int getSubsampling() {
return subsampling;
}
public void setSubsampling(int subsampling) {
this.subsampling = subsampling;
cameraConfigComm.sendParameter("subsampling", "int", Integer
.toString(subsampling));
}
@XmlAttribute(name = "backdiff-scale-tresh")
@Property(name = "Backdiff Scale Treshold", group = "Advanced Configuration", description = "All image points above this treshold will be scaled up according to the parameter Upscale Factor")
@TextField
private int backdiffScaleTresh = 2;
public int getBackdiffScaleTresh() {
return backdiffScaleTresh;
}
public void setBackdiffScaleTresh(int backdiffScaleTresh) {
this.backdiffScaleTresh = backdiffScaleTresh;
cameraConfigComm.sendParameter("backdiff-scale-tresh", "int", Integer
.toString(backdiffScaleTresh));
}
@XmlAttribute(name = "upscale-factor")
@Property(name = "Upscale Factor", group = "Advanced Configuration", description = "Upscale Factor for the Background Image")
@TextField
private float upscaleFactor = 12.0f;
public float getUpscaleFactor() {
return upscaleFactor;
}
public void setUpscaleFactor(float upscaleFactor) {
this.upscaleFactor = upscaleFactor;
cameraConfigComm.sendParameter("upscale-factor", "float", Float
.toString(upscaleFactor));
}
@XmlAttribute(name = "downscale-factor")
@Property(name = "Downscale Factor", group = "Advanced Configuration", description = "Downscale Factor for the Background Image")
@TextField
private float downscaleFactor = 4.0f;
public float getDownscaleFactor() {
return downscaleFactor;
}
public void setDownscaleFactor(float downscaleFactor) {
this.downscaleFactor = downscaleFactor;
cameraConfigComm.sendParameter("downscale-factor", "float", Float
.toString(downscaleFactor));
}
@XmlAttribute(name = "erode-dist")
@Property(name = "Erode Distance", group = "Advanced Configuration", description = "Distance of the Erode Filter")
@TextField
private int erodeDist = 2;
public int getErodeDist() {
return erodeDist;
}
public void setErodeDist(int erodeDist) {
this.erodeDist = erodeDist;
cameraConfigComm.sendParameter("erode-dist", "int", Integer
.toString(erodeDist));
}
@XmlAttribute(name = "dilate-dist")
@Property(name = "Dilate Distance", group = "Advanced Configuration", description = "Distance of the Dilate Filter")
@TextField
private int dilateDist = 2;
public int getDilateDist() {
return dilateDist;
}
public void setDilateDist(int dilateDist) {
this.dilateDist = dilateDist;
cameraConfigComm.sendParameter("dilate-dist", "int", Integer
.toString(dilateDist));
}
@XmlAttribute(name = "erode-tresh")
@Property(name = "Erode Treshold", group = "Advanced Configuration", description = "Treshold of the Erode Filter")
@TextField
private int erodeTresh = 12;
public int getErodeTresh() {
return erodeTresh;
}
public void setErodeTresh(int erodeTresh) {
this.erodeTresh = erodeTresh;
cameraConfigComm.sendParameter("erode-tresh", "int", Integer
.toString(erodeTresh));
}
@XmlAttribute(name = "dilate-tresh")
@Property(name = "Dilate Treshold", group = "Advanced Configuration", description = "Treshold of the Dilate Filter")
@TextField
private int dilateTresh = 12;
public int getDilateTresh() {
return dilateTresh;
}
public void setDilateTresh(int dilateTresh) {
this.dilateTresh = dilateTresh;
cameraConfigComm.sendParameter("dilate-tresh", "int", Integer
.toString(dilateTresh));
}
@XmlAttribute(name = "upscale-factor-2")
@Property(name = "Upscale Factor 2", group = "Advanced Configuration", description = "Final Upscale Factor")
@TextField
private float upscaleFactor2 = 12.0f;
public float getUpscaleFactor2() {
return upscaleFactor2;
}
public void setUpscaleFactor2(float upscaleFactor2) {
this.upscaleFactor2 = upscaleFactor2;
cameraConfigComm.sendParameter("upscale-factor-2", "float", Float
.toString(upscaleFactor2));
}
@XmlAttribute(name = "simple-tracking")
@Property(name = "Simple Tracking", group = "Advanced Configuration", description = "Turn on for Laserpointer-Tracking")
@CheckBox
private boolean simpleTracking = false;
public boolean isSimpleTracking() {
return simpleTracking;
}
public void setSimpleTracking(boolean simpleTracking) {
this.simpleTracking = simpleTracking;
cameraConfigComm.sendParameter("simple-tracking", "bool", Boolean
.toString(simpleTracking));
}
@XmlAttribute(name = "min-blob-size")
@Property(name = "Minimum Blob Size", group = "Advanced Configuration", description = "")
@Slider(type = Integer.class, minimumValue = 0, maximumValue = 30, showLabels = true, showTicks = true, majorTicks = 10, minorTicks = 1, snapToTicks = false)
private int minBlobSize = 4;
public int getMinBlobSize() {
return minBlobSize;
}
public void setMinBlobSize(int minBlobSize) {
this.minBlobSize = minBlobSize;
cameraConfigComm.sendParameter("min-blob-size", "int", Integer
.toString(minBlobSize));
}
@XmlAttribute(name = "x-from")
@Property(name = "X From", group = "Coordinates Range", description = "")
@TextField
public float xFrom = 0.0f;
public float getxFrom() {
return xFrom;
}
public void setxFrom(float xFrom) {
this.xFrom = xFrom;
}
@XmlAttribute(name = "x-end")
@Property(name = "X End", group = "Coordinates Range", description = "")
@TextField
public float xEnd = 1.0f;
public float getxEnd() {
return xEnd;
}
public void setxEnd(float xEnd) {
this.xEnd = xEnd;
}
@XmlAttribute(name = "y-from")
@Property(name = "Y From", group = "Coordinates Range", description = "")
@TextField
public float yFrom = 0.0f;
public float getyFrom() {
return yFrom;
}
public void setyFrom(float yFrom) {
this.yFrom = yFrom;
}
@XmlAttribute(name = "y-end")
@Property(name = "Y End", group = "Coordinates Range", description = "")
@TextField
public float yEnd = 1.0f;
public float getyEnd() {
return yEnd;
}
public void setyEnd(float yEnd) {
this.yEnd = yEnd;
}
@XmlAttribute(name = "address-outgoing")
@Property(name = "Address outgoing", group = "Connection Settings", description = "The outgoing address for the TUIO server.")
@TextField
private String addressOutgoing = "127.0.0.1";
/**
* @return the addressOutgoing
*/
public final String getAddressOutgoing() {
return addressOutgoing;
}
/**
* @param addressOutgoing
* the addressOutgoing to set
*/
public final void setAddressOutgoing(String addressOutgoing) {
this.addressOutgoing = addressOutgoing;
}
@XmlAttribute(name = "port-outgoing")
@Property(name = "Port outgoing", group = "Connection Settings", description = "The outgoing port for the TUIO server.")
@TextField
private int portOutgoing = 3333;
/**
* @return the portOutgoing
*/
public final int getPortOutgoing() {
return portOutgoing;
}
/**
* @param portOutgoing
* the portOutgoing to set
*/
public final void setPortOutgoing(int portOutgoing) {
this.portOutgoing = portOutgoing;
}
@XmlAttribute(name = "port-incoming")
@Property(name = "Port incoming", group = "Connection Settings", description = "The incoming port for the TUIO server.")
@TextField
protected int portIncoming = 3333;
/**
* @return the portIncoming
*/
public final int getPortIncoming() {
return portIncoming;
}
@XmlAttribute(name = "endian")
@Property(name = "Endian", description = "Indicates which endian strategy will be used to identify bytes or not.")
@ComboBox(domainProvider = EndianDomainProvider.class)
private Endian endian = Endian.LITTLE_ENDIAN;
/**
* @return the endian
*/
public final Endian getEndian() {
return endian;
}
/**
* @param endian
* the endian to set
*/
public final void setEndian(Endian endian) {
this.endian = endian;
if (isProcessing()) {
// Restart the osc server with new endian strategy.
stopOSCServer();
startOSCServer();
}
}
/*
*
* @XmlAttribute(name = "camera-image")
*
* @Property(name = "Camera Image")
*
* @ImagePanel private boolean blub = true; public boolean isBlub() { return
* blub; } public void setBlub(boolean blub) { this.blub = blub; }
*/
// ################################################################################
// END OF ADJUSTABLES
// ################################################################################
private LaserServer laserServer;
private ControlClient client;
// private ConfigManager configManager;
private ProxyServer proxy;
private ProxyServer imageServer;
private Socket trackerSocket;
public static int MODE_OFF = 0;
public static int MODE_INPUT_IMAGE = 1;
public static int MODE_PROCESSED_IMAGE = 2;
public static int MODE_BACKDIFF = 3;
// public static final int MODE_POINT_VELOCITY = 2;
private CameraConfigComm cameraConfigComm;// = new
// CameraConfigComm(remoteAddress,
// 4444, 4445,
// Endian.LITTLE_ENDIAN, this);
private Vector<ConfigNotifier> configUpdate = new Vector<ConfigNotifier>();
private int aoix = 0;
private int aoiy = 0;
private int aoiw = 0;
private int aoih = 0;
private Collection<Process> cameraProcesses = new ArrayList<Process>();
private int camerasReady = 0;
private boolean isTracking = false;
// private LaserConfigClient laserConfigClient;
private ImageDisplay imageDisplay;
private JFrame frame;
private boolean connectedToTracker = false;
private OSCPortOut oscPortOut;
private OSCPortIn oscPortIn;
/**
*
*/
protected void startOSCServer() {
try {
oscPortOut = new OSCPortOut(InetAddress.getByName(addressOutgoing),
portOutgoing);
} catch (SocketException e) {
throw new ProcessException(e.getMessage(), e);
} catch (UnknownHostException e) {
throw new ProcessException(e.getMessage(), e);
}
try {
oscPortIn = new OSCPortIn(portIncoming, endian);
} catch (SocketException e) {
throw new ProcessException(e.getMessage(), e);
}
oscPortIn.addListener("/tuio/2Dcur", new OSCListener() {
/*
* (non-Javadoc)
*
* @see com.illposed.osc.OSCListener#acceptMessages(java.util.Date,
* com.illposed.osc.OSCMessage[])
*/
public void acceptMessages(Date time, OSCMessage[] messages) {
List<DataPosition2D> cursors = new ArrayList<DataPosition2D>(1);
int fseq = -1;
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("fseq".equals(arguments[0])) {
fseq = (Integer) arguments[1];
// System.out.println(fseq);
}
}
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("set".equals(arguments[0])) {
int sessionId = (Integer) arguments[1];
float x = (Float) arguments[2];
float y = (Float) arguments[3];
float movementVectorX = (Float) arguments[4];
float movementVectorY = (Float) arguments[5];
float motionAcceleration = (Float) arguments[6];
float xFactor = getxEnd() - getxFrom();
x = x * xFactor + getxFrom();
float yFactor = getyEnd() - getyFrom();
y = y * yFactor + getyFrom();
DataPosition2D dataPosition2D = new DataPosition2D(
TUIO.class, x, y);
dataPosition2D.setAttribute(TUIO_ORIGIN_ADDRESS,
"/tuio/2Dcur");
dataPosition2D.setAttribute(
DataConstant.FRAME_SEQUENCE_ID, fseq);
dataPosition2D.setAttribute(DataConstant.SESSION_ID,
sessionId);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_X,
movementVectorX);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_Y,
movementVectorY);
dataPosition2D.setAttribute(TUIO_MOTION_ACCELERATION,
motionAcceleration);
dataPosition2D.setAttribute(SOURCE, getCameraID());
cursors.add(dataPosition2D);
}
}
publish(cursors);
}
});
oscPortIn.addListener("/tuio/_sxyXYmaPP", new OSCListener() {
public void acceptMessages(Date time, OSCMessage[] messages) {
List<DataPosition2D> cursors = new ArrayList<DataPosition2D>(1);
int fseq = -1;
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("fseq".equals(arguments[0])) {
fseq = (Integer) arguments[1];
}
}
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("set".equals(arguments[0])) {
int sessionId = (Integer) arguments[1];
float x = (Float) arguments[2];
float y = (Float) arguments[3];
float movementVectorX = (Float) arguments[4];
float movementVectorY = (Float) arguments[5];
float motionAcceleration = (Float) arguments[6];
float angleA = (Float) arguments[6];
float handWidth = (Float) arguments[6];
float handHeight = (Float) arguments[6];
DataPosition2D dataPosition2D = new DataPosition2D(
TUIO.class, x, y);
dataPosition2D.setAttribute(TUIO_ORIGIN_ADDRESS,
"/tuio/_sxyXYmaPP");
dataPosition2D.setAttribute(
DataConstant.FRAME_SEQUENCE_ID, fseq);
dataPosition2D.setAttribute(DataConstant.SESSION_ID,
sessionId);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_X,
movementVectorX);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_Y,
movementVectorY);
dataPosition2D.setAttribute(TUIO_MOTION_ACCELERATION,
motionAcceleration);
dataPosition2D.setAttribute(TUIO_ANGLE_A, angleA);
dataPosition2D.setAttribute(TUIO_HAND_WIDTH, handWidth);
dataPosition2D.setAttribute(TUIO_HAND_HEIGHT,
handHeight);
cursors.add(dataPosition2D);
}
}
publish(cursors);
}
});
oscPortIn.addListener("/tuio/_sxyXYma", new OSCListener() {
/*
* (non-Javadoc)
*
* @see com.illposed.osc.OSCListener#acceptMessages(java.util.Date,
* com.illposed.osc.OSCMessage[])
*/
public void acceptMessages(Date time, OSCMessage[] messages) {
List<DataPosition2D> cursors = new ArrayList<DataPosition2D>(1);
int fseq = -1;
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("fseq".equals(arguments[0])) {
fseq = (Integer) arguments[1];
}
}
for (OSCMessage message : messages) {
Object[] arguments = message.getArguments();
if ("set".equals(arguments[0])) {
int sessionId = (Integer) arguments[1];
float x = (Float) arguments[2];
float y = (Float) arguments[3];
float movementVectorX = (Float) arguments[4];
float movementVectorY = (Float) arguments[5];
float motionAcceleration = (Float) arguments[6];
float angleA = (Float) arguments[7];
DataPosition2D dataPosition2D = new DataPosition2D(
TUIO.class, x, y);
dataPosition2D.setAttribute(TUIO_ORIGIN_ADDRESS,
"/tuio/_sxyXYma");
dataPosition2D.setAttribute(
DataConstant.FRAME_SEQUENCE_ID, fseq);
dataPosition2D.setAttribute(DataConstant.SESSION_ID,
sessionId);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_X,
movementVectorX);
dataPosition2D.setAttribute(TUIO_MOVEMENT_VECTOR_Y,
movementVectorY);
dataPosition2D.setAttribute(TUIO_MOTION_ACCELERATION,
motionAcceleration);
dataPosition2D.setAttribute(TUIO_ANGLE_A, angleA);
cursors.add(dataPosition2D);
}
}
publish(cursors);
}
});
oscPortIn.startListening();
}
/**
*
*/
protected void stopOSCServer() {
if (oscPortIn != null) {
oscPortIn.stopListening();
oscPortIn.close();
oscPortIn = null;
}
}
@XmlAttribute(name = "display-blob-detector")
@Property(name = "Display BlobDetector", group = "Filter Display Settings", description = "Activates/Deactivates window showing the identified (finger) blobs.")
@CheckBox
private boolean displayBlobDetector = false;
public boolean isDisplayBlobDetector() {
return displayBlobDetector;
}
public void setDisplayBlobDetector(boolean displayBlobDetector) {
this.displayBlobDetector = displayBlobDetector;
cameraConfigComm.sendParameter("display-blob-detector", "bool", Boolean
.toString(displayBlobDetector));
}
@XmlAttribute(name = "update-background-image")
@Property(name = "Update Background Image", group = "Testing", description = "Changing this property refreshes the background image.")
@CheckBox
private boolean updateBackgroundImage = false;
public boolean isUpdateBackgroundImage() {
return updateBackgroundImage;
}
public void setUpdateBackgroundImage(boolean updateBackgroundImage) {
this.updateBackgroundImage = updateBackgroundImage;
cameraConfigComm.sendParameter("update-background-image", "bool",
"true");// always true
}
// ################################################################################
// BEGIN OF Processing
// ################################################################################
/*
* (non-Javadoc)
*
* @see org.squidy.manager.data.logic.ReflectionProcessable#
* beforeDataContainerProcessing
* (org.squidy.manager.data.IDataContainer)
*/
@Override
public IDataContainer preProcess(IDataContainer dataContainer) {
List<DataPosition2D> dataPositions2D = DataUtility.getDataOfType(
DataPosition2D.class, dataContainer);
if (dataPositions2D.size() <= 0) {
return super.preProcess(dataContainer);
}
OSCBundle bundle = new OSCBundle(new Date(dataContainer.getTimestamp()));
OSCMessage fseq2DCur = new OSCMessage("/tuio/2Dcur");
fseq2DCur.addArgument("fseq");
bundle.addPacket(fseq2DCur);
OSCMessage alive2DCur = new OSCMessage("/tuio/2Dcur");
alive2DCur.addArgument("alive");
bundle.addPacket(alive2DCur);
OSCMessage fseq_sxyXYmaPP = new OSCMessage("/tuio/_sxyXYmaPP");
fseq_sxyXYmaPP.addArgument("fseq");
bundle.addPacket(fseq_sxyXYmaPP);
OSCMessage alive_sxyXYmaPP = new OSCMessage("/tuio/_sxyXYmaPP");
alive_sxyXYmaPP.addArgument("alive");
bundle.addPacket(alive_sxyXYmaPP);
OSCMessage fseq_sxyXYma = new OSCMessage("/tuio/_sxyXYma");
fseq_sxyXYma.addArgument("fseq");
bundle.addPacket(fseq_sxyXYma);
OSCMessage alive_sxyXYma = new OSCMessage("/tuio/_sxyXYma");
alive_sxyXYma.addArgument("alive");
bundle.addPacket(alive_sxyXYma);
/*
* OSCMessage fseq = new OSCMessage("/tuio/2Dcur");
* fseq.addArgument("fseq"); bundle.addPacket(fseq);
*
* OSCMessage alive = new OSCMessage("/tuio/2Dcur");
* alive.addArgument("alive"); bundle.addPacket(alive);
*/
// Iterate 2D cursors.
for (DataPosition2D dataPosition2D : dataPositions2D) {
String originAddress = (String) dataPosition2D
.getAttribute(TUIO_ORIGIN_ADDRESS);
// Set frame sequence id
/*
* if (fseq.getArguments().length < 2) {
* fseq.addArgument(dataPosition2D
* .getAttribute(DataConstant.FRAME_SEQUENCE_ID)); }
* alive.addArgument
* (dataPosition2D.getAttribute(DataConstant.SESSION_ID));
*/
OSCMessage set;
if ("/tuio/_sxyXYmaPP".equals(originAddress)) {
if (fseq_sxyXYmaPP.getArguments().length < 2) {
fseq_sxyXYmaPP.addArgument(dataPosition2D
.getAttribute(DataConstant.FRAME_SEQUENCE_ID));
}
alive_sxyXYmaPP.addArgument(dataPosition2D
.getAttribute(DataConstant.SESSION_ID));
set = prepare_sxyXYmaPP(dataPosition2D);
} else if ("/tuio/_sxyXYma".equals(originAddress)) {
if (fseq_sxyXYma.getArguments().length < 2) {
fseq_sxyXYma.addArgument(dataPosition2D
.getAttribute(DataConstant.FRAME_SEQUENCE_ID));
}
alive_sxyXYma.addArgument(dataPosition2D
.getAttribute(DataConstant.SESSION_ID));
set = prepare_sxyXYma(dataPosition2D);
}
// /tuio/2DCur
else {
if (fseq2DCur.getArguments().length < 2) {
fseq2DCur.addArgument(dataPosition2D
.getAttribute(DataConstant.FRAME_SEQUENCE_ID));
}
alive2DCur.addArgument(dataPosition2D
.getAttribute(DataConstant.SESSION_ID));
set = prepare2DCur(dataPosition2D);
}
bundle.addPacket(set);
}
try {
oscPortOut.send(bundle);
} catch (IOException e) {
throw new ProcessException(e.getMessage(), e);
}
return super.preProcess(dataContainer);
}
/**
* @param dataPosition2D
* @return
*/
private OSCMessage prepare2DCur(DataPosition2D dataPosition2D) {
OSCMessage set = new OSCMessage("/tuio/2Dcur");
set.addArgument("set");
set.addArgument(dataPosition2D.getAttribute(DataConstant.SESSION_ID));
set.addArgument((float) dataPosition2D.getX());
set.addArgument((float) dataPosition2D.getY());
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_X));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_Y));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOTION_ACCELERATION));
return set;
}
/**
* @param dataPosition2D
* @return
*/
private OSCMessage prepare_sxyXYmaPP(DataPosition2D dataPosition2D) {
OSCMessage set = new OSCMessage("/tuio/_sxyXYmaPP");
set.addArgument("set");
set.addArgument(dataPosition2D.getAttribute(DataConstant.SESSION_ID));
set.addArgument((float) dataPosition2D.getX());
set.addArgument((float) dataPosition2D.getY());
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_X));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_Y));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOTION_ACCELERATION));
set.addArgument(dataPosition2D.getAttribute(TUIO_ANGLE_A));
set.addArgument(dataPosition2D.getAttribute(TUIO_HAND_WIDTH));
set.addArgument(dataPosition2D.getAttribute(TUIO_HAND_HEIGHT));
return set;
}
/**
* @param dataPosition2D
* @return
*/
private OSCMessage prepare_sxyXYma(DataPosition2D dataPosition2D) {
OSCMessage set = new OSCMessage("/tuio/_sxyXYma");
set.addArgument("set");
set.addArgument(dataPosition2D.getAttribute(DataConstant.SESSION_ID));
set.addArgument((float) dataPosition2D.getX());
set.addArgument((float) dataPosition2D.getY());
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_X));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOVEMENT_VECTOR_Y));
set.addArgument(dataPosition2D.getAttribute(TUIO_MOTION_ACCELERATION));
set.addArgument(dataPosition2D.getAttribute(TUIO_ANGLE_A));
return set;
}
public static class PatternDomainProvider implements DomainProvider {
public Object[] getValues() {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment
.getLocalGraphicsEnvironment();
ComboBoxItemWrapper[] values = new ComboBoxItemWrapper[graphicsEnvironment
.getScreenDevices().length];
int cntr = 0;
for (final GraphicsDevice device : graphicsEnvironment
.getScreenDevices()) {
String idStr = device.getIDstring();
values[cntr] = new ComboBoxItemWrapper(cntr, idStr);
cntr++;
}
return values;
}
}
public static class ModeDomainProvider implements DomainProvider {
/*
* (non-Javadoc)
*
* @see
* org.squidy.manager.data.domainprovider.DomainProvider#getValues
* ()
*/
public Object[] getValues() {
ComboBoxItemWrapper[] values = new ComboBoxItemWrapper[5];
values[0] = new ComboBoxItemWrapper(MODE_OFF, "Off");
values[1] = new ComboBoxItemWrapper(MODE_INPUT_IMAGE,
"Camera Input Image");
values[2] = new ComboBoxItemWrapper(MODE_PROCESSED_IMAGE,
"Processed Image");
values[3] = new ComboBoxItemWrapper(MODE_BACKDIFF,
"Background Image");
// values[2] = new ComboBoxItemWrapper(MODE_POINT_VELOCITY,
// "Dynamic Model");
// values[3] = new ComboBoxItemWrapper(MODE_MULTI_WEIGHTED,
// "Weighted Combination");
// values[4] = new ComboBoxItemWrapper(MODE_MULIT_CHOICE,
// "Best Choice (XOR)");
return values;
}
}
@SuppressWarnings("serial")
class ImageDisplay extends JComponent implements MouseListener,
MouseMotionListener {
private ArrayList<Point> cornerPoints;
private Dimension circleDim = new Dimension(6, 6);
private BufferedImage img = null;
private final Stroke CIRCLE_STROKE = new BasicStroke(1.5f);
private int requiredCornerPoints;
public int getRequiredCornerPoints() {
return requiredCornerPoints;
}
public void setRequiredCornerPoints(int requiredCornerPoints) {
this.requiredCornerPoints = requiredCornerPoints;
setTitle("Image Display (" + cornerPoints.size() + " of "
+ requiredCornerPoints + " corner points)");
}
public int getNumberOfCornerPoints() {
if (cornerPoints == null)
return 0;
return cornerPoints.size();
}
public ImageDisplay() {
cornerPoints = new ArrayList<Point>();
if (cornerPointsStr == null)
return;
StringTokenizer tokens = new StringTokenizer(cornerPointsStr, ",");
while (tokens.hasMoreTokens()) {
int x = Integer.parseInt((String) tokens.nextElement());
int y = Integer.parseInt((String) tokens.nextElement());
Point p = new Point(x, y);
cornerPoints.add(p);
}
addMouseListener(this);
addMouseMotionListener(this);
repaint();
}
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
// if (e.getButton() == MouseEvent.BUTTON0) {
Point p = e.getPoint();
p.x += aoix;
p.y += aoiy;
if (isPointInArr(p)) {
Point existingPoint = getPoint(p);
existingPoint.x = p.x;
existingPoint.y = p.y;
repaint();
}
// }
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Point p = e.getPoint();
p.x += aoix;
p.y += aoiy;
if (isPointInArr(p)) {
Point existingPoint = getPoint(p);
existingPoint.x = p.x;
existingPoint.y = p.y;
setCornerPointsStr(arrToStr());
sendCornerPoints();
repaint();
}
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Point p = e.getPoint();
p.x += aoix;
p.y += aoiy;
if (!isPointInArr(p)) {
cornerPoints.add(p);
setTitle("Image Display (" + cornerPoints.size() + " of "
+ requiredCornerPoints + " corner points)");
setCornerPointsStr(arrToStr());
sendCornerPoints();
repaint();
}
}
if (e.getButton() == MouseEvent.BUTTON3) {
Point p = e.getPoint();
p.x += aoix;
p.y += aoiy;
if (isPointInArr(p)) {
Point existingPoint = getPoint(p);
cornerPoints.remove(existingPoint);
setTitle("Image Display (" + cornerPoints.size() + " of "
+ requiredCornerPoints + " corner points)");
setCornerPointsStr(arrToStr());
sendCornerPoints();
// cornerPointsStr = arrToStr();
repaint();
}
}
}
private void setTitle(String title) {
Container c = getParent();
while (c != null && !(c instanceof JFrame)) {
c = c.getParent();
}
if (c != null) {
((JFrame) c).setTitle(title);
}
}
public void sendCornerPoints() {
int strSize = cornerPoints.size() * 2;
String[] cornerArr = new String[strSize];
int cntr = 0;
for (int i = 0; i < strSize; i += 2) {
Point p = cornerPoints.get(cntr);
cornerArr[i] = Integer.toString(p.x);
cornerArr[i + 1] = Integer.toString(p.y);
cntr++;
}
if (cameraConfigComm != null) {
cameraConfigComm.sendMultipleParameters("corner_point", "int",
cornerArr, strSize);
}
}
public String arrToStr() {
String str = "";
for (int i = 0; i < cornerPoints.size(); i++) {
Point curPoint = cornerPoints.get(i);
str = str + curPoint.x + "," + curPoint.y + ",";
}
return str;
}
public void setImage(BufferedImage img) {
this.img = img;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
// super.paintComponent(g);
if (connectedToTracker == false) {
// this.setSize(600,600);
// this.setPreferredSize(new Dimension(600, 600));
g.drawString("Not Connected to Touch Tracker", 2, 100);
} else {
if (this.img != null) {
g.drawImage(this.img, 0, 0, this);
}
g2d.setStroke(CIRCLE_STROKE);
if (cornerPoints.size() != requiredCornerPoints) {
g.setColor(Color.RED);
} else {
g.setColor(Color.GREEN);
}
for (int i = 0; i < cornerPoints.size(); i++) {
Point p = (Point) cornerPoints.get(i);
g.drawOval(p.x - circleDim.width / 2 - aoix, p.y
- circleDim.height / 2 - aoiy, circleDim.width,
circleDim.height);
}
}
}
private boolean isPointInArr(Point p) {
for (int i = 0; i < cornerPoints.size(); i++) {
Point curPoint = (Point) cornerPoints.get(i);
if ((p.x <= curPoint.x + circleDim.width + 2 / 2 && p.x >= curPoint.x
- circleDim.width + 2 / 2)
&& (p.y <= curPoint.y + circleDim.height + 2 / 2 && p.y >= curPoint.y
- circleDim.height + 2 / 2)) {
return true;
}
}
return false;
}
public Point getPoint(Point p) {
for (int i = 0; i < cornerPoints.size(); i++) {
Point curPoint = (Point) cornerPoints.get(i);
if ((p.x <= curPoint.x + circleDim.width + 2 / 2 && p.x >= curPoint.x
- circleDim.width + 2 / 2)
&& (p.y <= curPoint.y + circleDim.height + 2 / 2 && p.y >= curPoint.y
- circleDim.height + 2 / 2)) {
return curPoint;
}
}
return null;
}
public void deleteAllCornerPoints() {
cornerPoints.clear();
setTitle("Image Display (" + cornerPoints.size() + " of "
+ requiredCornerPoints + " corner points)");
setCornerPointsStr(arrToStr());
sendCornerPoints();
repaint();
}
}
public void sendAllTrackingParams() {
setImageServerPort(getImageServerPort());
setSubsampling(getSubsampling());
setPrintFPS(isPrintFPS());
setPatternH(getPatternH());
setPatternW(getPatternW());
setPortIncoming(getPortIncoming());
imageDisplay.sendCornerPoints();
setPixelclock(getPixelclock());
setMode(getMode());
setTrackContours(isTrackContours());
setBackdiff(isBackdiff());
setHomogenization(isHomogenization());
setDynamicBackdiff(isDynamicBackdiff());
setDynamicBackdiffSpeed(getDynamicBackdiffSpeed());
setBackdiffTresh(getBackdiffTresh());
setRepaintImg(isRepaintImg());
setBackdiffScaleTresh(getBackdiffScaleTresh());
setDownscaleFactor(getDownscaleFactor());
setUpscaleFactor(getUpscaleFactor());
setUpscaleFactor2(getUpscaleFactor2());
setErodeDist(getErodeDist());
setDilateDist(getDilateDist());
setErodeTresh(getErodeTresh());
setDilateTresh(getDilateTresh());
setTrackingSensitivity(getTrackingSensitivity());
setMinBlobSize(getMinBlobSize());
setSimpleTracking(isSimpleTracking());
}
private static final String trackerProgramName = "SquidyVision.exe";
/*
* (non-Javadoc)
*
* @see org.squidy.nodes.TUIO#onStart()
*/
@Override
public final void onStart() {
super.onStart();
startOSCServer();
fireStatusChange("pixelclock", getPixelclock(), pixelclock);
int camID = getCameraID();
int portOut = 4000 + camID;
int portIn = 4100 + camID;
setOscPortConfigIn(portIn);
setOscPortConfigOut(portOut);
fireStatusChange("osc-port-in", getOscPortConfigIn(), portIn);
fireStatusChange("osc-port-out", getOscPortConfigOut(), portOut);
if (cameraConfigComm != null)
cameraConfigComm.closeConnections();
cameraConfigComm = new CameraConfigComm(remoteAddress,
getOscPortConfigOut(), getOscPortConfigIn(),
getImageServerPort(), Endian.LITTLE_ENDIAN, this);
// laserServer = new LaserServer(this, laserPositionPort);
// configManager = new ConfigManager(this, laserConfigurationPort);
// proxy = new ProxyServer(this, proxyConfigurationPort, true);
// imageServer = new ProxyServer(this, proxyCameraPort, false);
frame = new JFrame("Image Display");
frame.setLayout(new BorderLayout());
// frame.setSize(new Dimension(800, 800));
// frame.setPreferredSize(new Dimension(800, 800));
// //frame.setResizable(false);
imageDisplay = new ImageDisplay();
imageDisplay.setBackground(Color.BLACK);
imageDisplay.setSize(200, 200);
imageDisplay.setPreferredSize(new Dimension(200, 200));
imageDisplay.setRequiredCornerPoints(patternW * patternH);
frame.setBackground(Color.BLACK);
frame.add(imageDisplay, BorderLayout.CENTER);
JButton clearCorners = new JButton("Delete All Corner Points");
clearCorners.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int option = JOptionPane.showConfirmDialog(frame,
"Would you like to remove all corner points?",
"Remove corner points", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (option == JOptionPane.YES_OPTION) {
imageDisplay.deleteAllCornerPoints();
}
}
});
frame.add(clearCorners, BorderLayout.SOUTH);
// frame.add(imageDisplay);
// Insets insets = frame.getInsets();
frame.pack();
frame.validate();
if (getMode() != MODE_OFF)
frame.setVisible(true);
new Thread() {
public void run() {
super.run();
while (isProcessing()) {
try {
trackerSocket = new Socket(remoteAddress, remotePort);
System.out.println("Connected to Touch Tracker");
connectedToTracker = true;
cameraConfigComm.setStopped(false);
if (isTrackFingers() == true)
setTrackFingers(isTrackFingers());
else
sendAllTrackingParams();
//close SquidyVision windows
if (!displayBlobDetector)
cameraConfigComm.sendParameter("display-blob-detector", "bool", "false");
BufferedReader in = new BufferedReader(
new InputStreamReader(trackerSocket
.getInputStream()));
in.readLine();
} catch (UnknownHostException e1) {
System.out
.println("Connection to Touch Tracker closed. Retrying...");
imageDisplay.repaint();
connectedToTracker = false;
cameraConfigComm.setStopped(true);
} catch (IOException e1) {
System.out
.println("Connection to Touch Tracker closed. Retrying...");
imageDisplay.repaint();
connectedToTracker = false;
cameraConfigComm.setStopped(true);
}
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
if (isStartTrackingAutomatically() && !connectedToTracker) {
new Thread() {
/**
*
*/
@Override
public void run() {
super.run();
String curDir = System.getProperty("user.dir");
System.out.println("Java Working Directory: " + curDir);
// if the tracker isn't running
if (!connectedToTracker && !trackerRunning()) {
ProcessBuilder pb = new ProcessBuilder(
new String[] { "ext/" + trackerProgramName,
Integer.toString(getCameraID()) });
pb.directory(new File(".", "ext"));
Process process = null;
try {
process = pb.start();
// camerasReady++;
// if (camerasReady == cameras && !isTracking) {
// new Thread() {
// public void run() {
// try {
// sleep(6000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// if (laserConfigClient == null) {
// laserConfigClient = new LaserConfigClient();
// }
// // laserConfigClient.startAllTracking();
// };
// }.start();
// }
processInputStreamReading(process);
} catch (IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e.getMessage(), e);
}
publishFailure(e);
}
if (process != null) {
cameraProcesses.add(process);
}
}
}
}.start();
}
// check number of set corner points
final int difference = imageDisplay.getRequiredCornerPoints()
- imageDisplay.getNumberOfCornerPoints();
if (difference != 0) {
if (difference > 0)
ReacTIVision.showErrorPopUp("Too few corner points set.");
else
ReacTIVision.showErrorPopUp("Too many corner points set.");
}
}
/**
* Returns <code>true</code> if an instance of
* <code>NLaserTracker.exe</code> is already running.
* <p>
* This requires <code>tasklist.exe</code>, which doesn't come with the HOME
* editions of Windows, but can be found on the web for free.
*
* @return <code>true</code> if an instance of
* <code>NLaserTracker.exe</code> is already running,
* <code>false</code> otherwise
*/
private final boolean trackerRunning() {
// TODO
/*
* try { String line; Process p =
* Runtime.getRuntime().exec("tasklist.exe /fo csv /nh"); BufferedReader
* input = new BufferedReader (new
* InputStreamReader(p.getInputStream()));
*
* while ((line = input.readLine()) != null) { if
* (!line.trim().equals("")) { // keep only the process name line =
* line.substring(1); if (line.substring(0,
* line.indexOf("\"")).equals(trackerProgramName)) return true; } }
* input.close(); } catch (Exception err) { err.printStackTrace(); }
*/
return false;
}
/*
* (non-Javadoc)
*
* @see org.squidy.nodes.TUIO#onStop()
*/
@Override
public final void onStop() {
stopOSCServer();
if (connectedToTracker) {
cameraConfigComm.sendParameter("kill", "bool", "true");
}
cameraConfigComm.sendParameter("stream_image", "bool", "false");
if (frame != null) {
frame.setVisible(false);
frame.dispose();
}
cameraConfigComm.setStopped(true);
cameraConfigComm.closeConnections();
// if (laserConfigClient != null) {
// laserConfigClient.stopAllTracking();
// laserConfigClient = null;
// }
isTracking = false;
camerasReady = 0;
// for (Process p : cameraProcesses) {
// p.destroy();
// }
if (laserServer != null) {
laserServer.close();
}
/*
* if (configManager != null) { configManager.close(); }
*/
if (proxy != null) {
proxy.close();
}
if (imageServer != null) {
imageServer.close();
}
super.onStop();
}
/**
* @param process
*/
private void processInputStreamReading(final Process process) {
new Thread() {
/**
*
*/
@Override
public void run() {
super.run();
try {
String cameraId = "";
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("Camera ID: ")) {
cameraId = line.substring(11, line.length());
}
// if ("Initialization completed".equals(line)) {
// camerasReady++;
//
// if (cameras == camerasReady && !isTracking) {
// if (false) {
// // if (laserConfigClient == null) {
// // laserConfigClient = new LaserConfigClient();
// // }
// // laserConfigClient.startAllTracking();
// isTracking = true;
// }
// }
// }
// if ("Number of corners not matching".equals(line)) {
// JOptionPane
// .showMessageDialog(
// Designer.getInstance(),
// line
// +
// "\n\nUse laserConfig.xml backup or recalibrate camera.",
// "Tracking error",
// JOptionPane.ERROR_MESSAGE);
// publishFailure(new ProcessException(line));
// }
System.out.println("Camera " + cameraId + ": " + line);
}
} catch (IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e.getMessage(), e);
}
publishFailure(e);
}
}
}.start();
}
public void imageUpdate(BufferedImage img) {
imageDisplay.setImage(img);
if (img.getWidth() != imageDisplay.getWidth()
|| img.getHeight() != imageDisplay.getHeight()) {
Dimension newDim = new Dimension(img.getWidth(), img.getHeight());
imageDisplay.setSize(newDim);
imageDisplay.setPreferredSize(newDim);
frame.pack();
}
// imageDisplay.setSize(newDim);
}
public void configUpdate(String name, String type, String value) {
String f = "framerate";
if (name.equals(f)) {
refreshFramerate(Integer.parseInt(value));
}
if (name.equals("exposure")) {
refreshExposure(Integer.parseInt(value));
}
if (name.equals("pixelclock")) {
refreshPixelclock(Integer.parseInt(value));
}
if (name.equals("aoix")) {
aoix = Integer.parseInt(value);
}
if (name.equals("aoiy")) {
aoiy = Integer.parseInt(value);
}
if (name.equals("aoiw")) {
aoiw = Integer.parseInt(value);
}
if (name.equals("aoih")) {
aoih = Integer.parseInt(value);
}
// notifyUpdateConfig();
}
/*
*
* public void attachNotifier(ConfigNotifier configNotifier) {
* configUpdate.add(configNotifier); }
*
*
* public void detachNotifier(ConfigNotifier configNotifier) {
* configUpdate.remove(configNotifier); }
*
*
* public void notifyUpdateConfig() { for (ConfigNotifier configNotifier :
* configUpdate) { configNotifier.updateConfig(); } }
*
*
* public Camera getCalibrationCamera() { return
* configManager.getCalibrationCamera(); }
*
*
* public Configuration getConfig() { return configManager.getConfig(); }
*/
}