View Javadoc

1   /*
2   	TUIO Java backend - part of the reacTIVision project
3   	http://reactivision.sourceforge.net/
4   
5   	Copyright (c) 2005-2009 Martin Kaltenbrunner <mkalten@iua.upf.edu>
6   
7       This program is free software; you can redistribute it and/or modify
8       it under the terms of the GNU General Public License as published by
9       the Free Software Foundation; either version 2 of the License, or
10      (at your option) any later version.
11  
12      This program is distributed in the hope that it will be useful,
13      but WITHOUT ANY WARRANTY; without even the implied warranty of
14      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15      GNU General Public License for more details.
16  
17      You should have received a copy of the GNU General Public License
18      along with this program; if not, write to the Free Software
19      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21  package org.ximtec.igesture.io.tuio;
22  
23  import com.illposed.osc.*;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.net.SocketException;
28  import java.util.*;
29  import java.util.logging.Level;
30  import java.util.logging.Logger;
31  
32  import javax.xml.parsers.DocumentBuilder;
33  import javax.xml.parsers.DocumentBuilderFactory;
34  import javax.xml.parsers.ParserConfigurationException;
35  
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.Node;
39  import org.w3c.dom.NodeList;
40  import org.ximtec.igesture.io.tuio.handler.AbstractTuioHandler;
41  import org.xml.sax.SAXException;
42  
43  
44  /**
45   * @author Martin Kaltenbrunner
46   * @author Bjorn Puype, bpuype@gmail.com
47   * @version 1.4
48   */ 
49  public class TuioConnection implements OSCListener {
50  	
51  	private static final Logger LOGGER = Logger.getLogger(TuioConnection.class.getName());
52  	
53  	/** port number to listen to */
54  	private int port = TuioConstants.DEFAULT_PORT;
55  	/** OSC port */
56  	private OSCPortIn oscPort;
57  	/** connection status */
58  	private boolean connected = false;
59  	/** time */
60  	private TuioTime currentTime;
61  	
62  	/** Mapping of the TUIO profiles on the TUIO handlers */
63  	private Map<String, AbstractTuioHandler> profileToHandler = new HashMap<String, AbstractTuioHandler>();
64  	
65  	/**
66  	 * Default constructor
67  	 */
68  	public TuioConnection()
69  	{
70  		this(TuioConstants.DEFAULT_PORT);
71  	}
72  	
73  	/**
74  	 * This constructor creates a client that listens to the provided port
75  	 *
76  	 * @param  port  the listening port number
77  	 */
78  	public TuioConnection(int port) {
79  		this.port = port;
80  	}
81  		
82  	/**
83  	 * The TuioClient starts listening to TUIO messages on the configured UDP port
84  	 * All received TUIO messages are decoded and the resulting TUIO events are broadcasted to all registered TuioListener(3D)s
85  	 */
86  	public void connect() {
87  
88  		//setup timing information
89  		TuioTime.initSession();
90  		currentTime = new TuioTime();
91  		currentTime.reset();
92  		
93  		try {		
94  			//create OSC port to listen to
95  			oscPort = new OSCPortIn(port);
96  			
97  			//create handlers
98  			initProfiles();
99  						
100 			//add listener for each profile
101 			Set<String> keys = profileToHandler.keySet();
102 			for(String key : keys)
103 			{
104 				oscPort.addListener(key, this);
105 			}
106 			
107 			//start listening for messages
108 			oscPort.startListening();
109 			connected = true;
110 			LOGGER.log(Level.INFO,"Connected to port "+port);
111 		} catch (SocketException e) {
112 			LOGGER.log(Level.SEVERE,"Failed to connect to port "+port,e);
113 			connected = false;
114 		} catch (Exception e) {
115 			LOGGER.log(Level.SEVERE,"Could not parse "+TuioConstants.XML_TUIO_PROFILES,e);
116 			disconnect();
117 		}
118 	}
119 	
120 	/**
121 	 * Initialize the TUIO profiles.
122 	 * @throws ParserConfigurationException
123 	 * @throws SAXException
124 	 * @throws IOException
125 	 */
126 	private void initProfiles() throws ParserConfigurationException, SAXException, IOException
127 	{
128 		//location of the profiles file
129 		File file = new File(System.getProperty("user.dir")+System.getProperty("file.separator")+TuioConstants.XML_TUIO_PROFILES);
130 			//TODO it should get the file from the framework not the tool
131 		//create a XML parser
132 		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
133 		DocumentBuilder db;
134 		db = dbf.newDocumentBuilder();
135 		//parse the XML file and create a DOM tree
136 		Document doc = db.parse(file);
137 		
138 		doc.getDocumentElement().normalize();
139 		//get all the association elements
140 		NodeList nodeList = doc.getElementsByTagName("association");
141 
142 		//for all associations, create the mapping TUIO profile on TUIO handler
143 		for (int i = 0; i < nodeList.getLength(); i++) 
144 		{
145 		    Node node = nodeList.item(i);
146 		    
147 		    if (node.getNodeType() == Node.ELEMENT_NODE) 
148 		    {
149 		      NodeList profiles = ((Element)node).getElementsByTagName("profile");
150 		      NodeList p = ((Element) profiles.item(0)).getChildNodes();
151 //		      System.out.println("Profile : "  + ((Node) p.item(0)).getNodeValue());
152 		      
153 		      NodeList handlers = ((Element)node).getElementsByTagName("handler");
154 		      NodeList h = ((Element) handlers.item(0)).getChildNodes();
155 //		      System.out.println("Handler : " + ((Node) h.item(0)).getNodeValue());
156 		      
157 		      try {
158 		    	  //use reflection to create an instance through the class name
159 			      Class c = Class.forName(((Node) h.item(0)).getNodeValue());
160 			      profileToHandler.put(((Node) p.item(0)).getNodeValue(), (AbstractTuioHandler) c.newInstance());
161 		      } 
162 		      catch (Exception e) {
163 				LOGGER.log(Level.SEVERE,"Could not find class: "+((Node) h.item(0)).getNodeValue(),e);
164 		      }
165 		    }	    
166 		}
167 	}
168 	
169 	/**
170 	 * The TuioClient stops listening to TUIO messages on the configured UDP port
171 	 */
172 	public void disconnect() {
173 		LOGGER.log(Level.INFO,"Disconnecting from port "+port);
174 		oscPort.stopListening();
175 		try { Thread.sleep(100); }
176 		catch (Exception e) {};
177 		oscPort.close();
178 		connected = false;
179 	}
180 
181 	/**
182 	 * Returns true if this TuioClient is currently connected.
183 	 * @return	true if this TuioClient is currently connected
184 	 */
185 	public boolean isConnected() { return connected; }
186 
187 	/**
188 	 * Adds the provided TuioListener to the list of registered TUIO event listeners
189 	 *
190 	 * @param  	listener  the TuioListener to add
191 	 * @param	modifiers	the desired TUIO profiles	
192 	 */
193 	public void addTuioListener(TuioListener listener, Set<String> modifiers)
194 	{
195 		for(String s : modifiers)
196 		{
197 			if(profileToHandler.containsKey(s))
198 			{
199 				profileToHandler.get(s).addTuioListener(listener);
200 			}
201 			else
202 			{
203 				LOGGER.log(Level.WARNING,this.getClass().getName()+": Incorrect modifiers");
204 			}
205 		}
206 	}
207 	
208 	/**
209 	 * Removes the provided TuioListener from the list of registered TUIO event listeners
210 	 *
211 	 * @param  listener  the TuioListener to remove
212 	 * @param	modifiers	the desired TUIO profiles
213 	 */
214 	public void removeTuioListener(TuioListener listener, Set<String> modifiers)
215 	{
216 		for(String s : modifiers)
217 		{
218 			if(profileToHandler.containsKey(s))
219 			{
220 				profileToHandler.get(s).removeTuioListener(listener);
221 			}
222 			else
223 			{
224 				LOGGER.log(Level.WARNING,this.getClass().getName()+": Incorrect modifiers");
225 			}
226 		}
227 	}	
228 	
229 	/**
230 	 * Removes all TuioListeners from the list of registered TUIO event listeners
231 	 * @param	modifiers	the desired TUIO profiles
232 	 */
233 	public void removeAllTuioListener(Set<String> modifiers)
234 	{
235 		for(String s : modifiers)
236 		{
237 			if(profileToHandler.containsKey(s))
238 			{
239 				profileToHandler.get(s).removeAllTuioListeners();
240 			}
241 			else
242 			{
243 				LOGGER.log(Level.WARNING,this.getClass().getName()+": Incorrect modifiers");
244 			}
245 		}
246 	}
247 	
248 	/**
249 	 * The OSC callback method where all TUIO messages are received and decoded
250 	 * and where the TUIO event callbacks are dispatched
251 	 *
252 	 * @param  date	the time stamp of the OSC bundle
253 	 * @param  message	the received OSC message
254 	 */
255 	public void acceptMessage(Date date, OSCMessage message) {
256 	
257 		String address = message.getAddress();
258 
259 		//delegate the message to the corresponding handler
260 		if(profileToHandler.containsKey(address))
261 			profileToHandler.get(address).acceptMessage(message, currentTime);
262 	}
263 }
264