/**
* 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.tracking;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Hashtable;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squidy.manager.data.impl.DataButton;
import org.squidy.manager.data.impl.DataPosition2D;
import org.squidy.nodes.Laserpointer;
import org.squidy.nodes.ir.ConfigManagable;
import org.squidy.nodes.tracking.config.ConfigNotifier;
import org.squidy.nodes.tracking.config.xml.Camera;
import org.squidy.nodes.tracking.config.xml.Display;
import org.squidy.nodes.tracking.config.xml.Property;
/**
*
* @author Werner Koenig, werner.koenig@uni-konstanz.de, University of Konstanz
*
*/
public class LaserConnection extends Thread implements ConfigNotifier {
// Logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(LaserConnection.class);
private Socket socket = null;
private String line;
private String identifier = "";
private ConfigManagable configManagable;
private boolean running = true;
private double displaySizeX, displaySizeY, displayPosX, displayPosY, displayPosWidth, displayPosHeight = 0;
private boolean isCaptureBackside, isCaptureHorizontal = false;
public LaserConnection(ConfigManagable configManagable, Socket socket) {
this.socket = socket;
this.configManagable = configManagable;
configManagable.attachNotifier(this);
start();
}
public void close() {
LOG.info("Close socket");
running = false;
configManagable.detachNotifier(this);
try {
socket.close();
}
catch (IOException e) {
LOG.error("Couldn't close socket");
}
}
public void updateConfig() {
for (Display display : configManagable.getConfig().getDisplays()) {
// TODO for zkm use the first one - later multi-display-support
displaySizeX = Integer.parseInt(display.getPropertyHashtable().get("size_x").getContent());
displaySizeY = Integer.parseInt(display.getPropertyHashtable().get("size_y").getContent());
break;
}
for (Camera camera : configManagable.getConfig().getCameras()) {
if (identifier.equals(camera.getId())) {
try {
Hashtable<String, Property> properties = camera.getPropertyHashtable();
displayPosX = Integer.parseInt(properties.get("displayPosX").getContent());
displayPosY = Integer.parseInt(properties.get("displayPosY").getContent());
displayPosWidth = Integer.parseInt(properties.get("displayPosWidth").getContent());
displayPosHeight = Integer.parseInt(properties.get("displayPosHeight").getContent());
// TODO change to boolean
isCaptureBackside = (Integer.parseInt(properties.get("isCaptureBackside").getContent()) == 1) ? true
: false;
// TODO change to boolean
isCaptureHorizontal = (Integer.parseInt(properties.get("isCaptureHorizontal").getContent()) == 1) ? true
: false;
}
catch (NumberFormatException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't parse string property to integer value for camera #" + camera.getId());
}
}
break;
}
}
}
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
public void run() {
try {
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
socket.setTcpNoDelay(true);
while (running && (line = input.readLine()) != null) {
if (line.indexOf("|") != -1) {
// laser-pointer-koordinaten
StringTokenizer str = new StringTokenizer(line, "|");
if (configManagable != null && (str.countTokens() == 2 || str.countTokens() == 3)) {
double cx = 0;
double cy = 0;
try {
cx = Double.parseDouble(str.nextToken());
cy = Double.parseDouble(str.nextToken());
}
catch (NumberFormatException e) {
LOG.error("Parse error occured");
continue;
}
if (str.countTokens() == 1) {
boolean button = Boolean.parseBoolean(str.nextToken());
// TODO [RR]: FIXME
configManagable
.publish(new DataButton(Laserpointer.class, 1, button));
}
if (isCaptureHorizontal) {
double tmp = cx;
cx = cy;
cy = tmp;
}
if (isCaptureBackside) {
cx = 1.0f - cx;
}
double rx = (displayPosWidth / displaySizeX * cx) + (displayPosX / displaySizeX);
double ry = (displayPosHeight / displaySizeY * cy) + (displayPosY / displaySizeY);
// TODO [RR]: FIXME
configManagable.publish(new DataPosition2D(Laserpointer.class, rx, ry));
}
else {
LOG.info("unknown packet: " + line);
}
}
else {
if (line.indexOf("#") != -1) {
// kamera name, width, height
StringTokenizer str = new StringTokenizer(line, "#");
identifier = str.nextToken();
LOG.info("Camera \"" + identifier + "\" connected!");
updateConfig();
}
else {
LOG.info("unknown packet: " + line);
close();
}
}
}
input.close();
}
catch (IOException ex) {
LOG.error("Connection error occured.");
close();
}
}
}