/**
* 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.laserpointer.config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLStreamException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squidy.manager.commander.ControlClient;
import org.squidy.manager.commander.command.impl.WhiteScreen;
import org.squidy.manager.commander.command.utility.Switch;
import org.squidy.manager.util.CommanderUtils;
import org.squidy.nodes.ir.ConfigManagable;
import org.squidy.nodes.laserpointer.config.xml.Camera;
import org.squidy.nodes.laserpointer.config.xml.Configuration;
import org.squidy.nodes.laserpointer.config.xml.Display;
import org.squidy.nodes.laserpointer.config.xml.Property;
import org.squidy.nodes.plugin.PatternScreen;
/**
*
* @author Werner Koenig, werner.koenig@uni-konstanz.de, University of Konstanz
*
*/
public class ConfigManager {
// Logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(ConfigManager.class);
private static final String CONFIG_XML = "laserConfig.xml";
private Configuration configuration;
private static JAXBContext context;
/**
* Returns the JAXB context and if it is not initialized already it will be initialized
* once.
*
* @return The JAXB context.
* @throws JAXBException
*/
public static JAXBContext getJAXBContext() throws JAXBException {
if (context == null) {
context = JAXBContext.newInstance("org.squidy.nodes.laserpointer.config.xml");
}
return context;
}
private ConfigServer conigServer;
private List<ConfigConnection> cameraConnections = new ArrayList<ConfigConnection>();
private List<ConfigConnection> configClientConnections = new ArrayList<ConfigConnection>();
private Camera calibCam = null;
private ConfigManagable configManagable;
public ConfigManager(ConfigManagable configManagable, int port) {
this.configManagable = configManagable;
try {
loadConfiguration();
}
catch (Exception e) {
LOG.fatal("Couldn't load xml configuration file: " + CONFIG_XML);
return;
}
conigServer = new ConfigServer(this, port);
}
/**
* @throws JAXBException
* @throws FileNotFoundException
*/
private synchronized void loadConfiguration() throws JAXBException, FileNotFoundException {
// Set configuration as empty.
configuration = null;
Unmarshaller u = getJAXBContext().createUnmarshaller();
configuration = (Configuration) u.unmarshal(new File(CONFIG_XML));
}
/**
* @param configuration
*/
private synchronized void saveConfiguration(Configuration configuration) {
if (configuration != null) {
this.configuration = configuration;
configManagable.notifyUpdateConfig();
if (configManagable.isConfigXmlReadOnly()) {
return;
}
File configXmlFile = new File(CONFIG_XML);
try {
configXmlFile.renameTo(new File(CONFIG_XML + ".bak"));
}
catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't create a backup of " + configXmlFile);
}
}
saveConfiguration(configuration, configXmlFile);
}
}
/**
* @param configuration
* @param configXmlFile
*/
public synchronized void saveConfiguration(Configuration configuration, File configXmlFile) {
if (configuration != null) {
try {
Marshaller marshaller = getJAXBContext().createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(configuration, new FileOutputStream(configXmlFile));
if (LOG.isDebugEnabled()) {
LOG.debug("Saved configuration to " + configXmlFile);
}
}
catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't save configuration to " + configXmlFile);
}
}
}
}
public void close() {
if (conigServer != null) {
conigServer.close();
}
}
public Configuration getConfig() {
return configuration;
}
public Camera getCalibrationCamera() {
return calibCam;
}
public synchronized void attachConnection(ConfigConnection connection) {
if (connection.isConnectionToConfigClient()) {
for (ConfigConnection configClientConnection : configClientConnections) {
if (configClientConnection != null && configClientConnection.getIdentifier().equals(connection.getIdentifier())) {
configClientConnections.remove(configClientConnection);
break;
}
}
configClientConnections.add(connection);
if (LOG.isInfoEnabled()) {
LOG.info("Laserpointer client " + connection.getIdentifier() + " attached.");
}
}
else {
// if camera is already inside
for (ConfigConnection cameraConnection : cameraConnections) {
if (cameraConnection != null && cameraConnection.getIdentifier().equals(connection.getIdentifier())) {
cameraConnections.remove(cameraConnection);
break;
}
}
cameraConnections.add(connection);
for (Camera cam : configuration.getCameras()) {
if (connection != null && connection.getIdentifier().equals(cam.getId())) {
cam.setOnline(true);
}
}
if (LOG.isInfoEnabled()) {
LOG.info("Laserpointer camera #" + connection.getIdentifier() + " attached (" + cameraConnections.size()
+ " cameras connected)");
}
}
}
/**
* @param configConnection
*/
public synchronized void detach(ConfigConnection configConnection) {
for (Camera camera : configuration.getCameras()) {
if (configConnection != null && configConnection.getIdentifier().equals(camera.getId())) {
camera.setOnline(false);
}
}
cameraConnections.remove(configConnection);
configClientConnections.remove(configConnection);
if (LOG.isInfoEnabled()) {
LOG.info("Laserpointer " + configConnection.getIdentifier() + " detached.");
}
}
/**
* @param connection
* @param configuration
*/
public synchronized void updateConfig(ConfigConnection connection, Configuration configuration) {
String host = configManagable.getRemoteAddress();
int port = configManagable.getRemotePort();
ControlClient client = CommanderUtils.getCommanderClient(host, port);
if (connection.isConnectionToConfigClient()) {
for (Display display : configuration.getDisplays()) {
if (display.getMsg() != null && display.getMsg().length() > 0) {
display.setMsg(null);
Collection<Property> properties = display.getProperties();
for (Property property : properties) {
property.setMsg(null);
}
saveConfiguration(configuration);
return;
}
}
// For all cameras in config
for (Camera cam : configuration.getCameras()) {
// if there is a message for camera
if (cam.getMsg() != null && cam.getMsg().length() > 0) {
if (LOG.isDebugEnabled()) {
LOG.debug("Update configuration action: " + cam.getMsg() + " (" + cameraConnections.size() + " cameras connected)");
}
boolean found = false;
// find connection for camera
for (ConfigConnection configConnection : cameraConnections) {
if (configConnection.getIdentifier().equals(cam.getId())) {
calibCam = cam;
// just refresh
if (cam.getMsg().equalsIgnoreCase("refresh")) {
cam.setMsg("");
}
if (cam.getMsg().equalsIgnoreCase("start_calibration")) {
try {
int patternW = Integer.parseInt(cam.getPropertyHashtable().get("patternW").getContent());
int patternH = Integer.parseInt(cam.getPropertyHashtable().get("patternH").getContent());
int displayPosX = Integer.parseInt(cam.getPropertyHashtable().get("displayPosX").getContent());
int displayPosY = Integer.parseInt(cam.getPropertyHashtable().get("displayPosY").getContent());
int displayPosWidth = Integer.parseInt(cam.getPropertyHashtable().get("displayPosWidth").getContent());
int displayPosHeight = Integer.parseInt(cam.getPropertyHashtable().get("displayPosHeight").getContent());
boolean startPatternWhite = (Integer.parseInt(cam.getPropertyHashtable().get("startPatternWhite").getContent()) == 1) ? true : false;
int displayWidth = 0;
int displayHeight = 0;
for (Display display : configuration.getDisplays()) {
displayWidth = Integer.parseInt(display.getPropertyHashtable().get("size_x").getContent());
displayHeight = Integer.parseInt(display.getPropertyHashtable().get("size_y").getContent());
break;
}
showWhiteScreen(client, false);
showPatternScreen(client, true, displayWidth, displayHeight, patternW, patternH);
// calibFrame.openPattern(patternW, patternH, displayPosX, displayPosY,
// displayPosWidth, displayPosHeight, startPatternWhite, displayWidth,
// displayHeight);
if (LOG.isDebugEnabled()) {
LOG.debug("Open calibration pattern for camera #" + cam.getId());
}
}
catch (NumberFormatException e) {
if (LOG.isErrorEnabled()) {
LOG.error("Couldn't parse String to integer: xml properties cam #"
+ cam.getId());
}
}
}
if (cam.getMsg().equalsIgnoreCase("showWhite")) {
if (LOG.isDebugEnabled()) {
LOG.debug("Show white for camera #" + cam.getId());
}
showWhiteScreen(client, true);
}
if (cam.getMsg().equalsIgnoreCase("start_tracking")) {
if (LOG.isDebugEnabled()) {
LOG.debug("Close calibration pattern for camera #" + cam.getId());
}
showPatternScreen(client, false);
showWhiteScreen(client, true);
}
cam.setOnline(true);
// update connected camera
try {
configuration = configConnection.updateCamera(configuration);
found = true;
}
catch (JAXBException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e.getMessage(), e);
}
getConfig().getCameraHashtable().get(cam.getId()).setMsg("Error_Server: JAXBException: " + e.getMessage());
detach(configConnection);
return;
}
catch (XMLStreamException e) {
if (LOG.isErrorEnabled()) {
LOG.error(e.getMessage(), e);
}
getConfig().getCameraHashtable().get(cam.getId()).setMsg("Error_Server: XMLStreamException: " + e.getMessage());
return;
}
break;
}
}
if (found) {
cam.setOnline(true);
saveConfiguration(configuration);
}
else {
getConfig().getCameraHashtable().get(cam.getId()).setOnline(false);
return;
}
}
}
}
showPatternScreen(client, false);
showWhiteScreen(client, false);
client.close();
}
/**
* @param show
*/
private void showWhiteScreen(ControlClient client, boolean show) {
WhiteScreen whiteScreen = new WhiteScreen();
whiteScreen.setState(show ? Switch.ON : Switch.OFF);
System.out.println("SENDING WHITE SCREEN");
client.send(whiteScreen);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param show
* @param params
*/
private void showPatternScreen(ControlClient client, boolean show, int... params) {
PatternScreen patternScreen;
if (params.length == 4) {
patternScreen = new PatternScreen("\\Display0", params[0], params[1], params[2], params[3]);
}
else {
patternScreen = new PatternScreen();
}
System.out.println("SENDING PATTERN SCREEN");
patternScreen.setState(show ? Switch.ON : Switch.OFF);
client.send(patternScreen);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}