Просмотр исходного кода

Touch events in Input core, TUIO module and multiple monitor support in Cocoa

Ivan Safrin 13 лет назад
Родитель
Сommit
dc006132ba
50 измененных файлов с 8338 добавлено и 12 удалено
  1. 2 1
      Core/Contents/Include/PolyCocoaCore.h
  2. 5 2
      Core/Contents/Include/PolyCore.h
  3. 5 2
      Core/Contents/Include/PolyCoreInput.h
  4. 2 1
      Core/Contents/Include/PolyCoreServices.h
  5. 13 0
      Core/Contents/Include/PolyInputEvent.h
  6. 6 0
      Core/Contents/Include/PolyModule.h
  7. 15 5
      Core/Contents/Source/PolyCocoaCore.mm
  8. 3 1
      Core/Contents/Source/PolyCore.cpp
  9. 19 0
      Core/Contents/Source/PolyCoreInput.cpp
  10. 9 0
      Core/Contents/Source/PolyCoreServices.cpp
  11. 5 0
      Core/Contents/Source/PolyModule.cpp
  12. 1 0
      Modules/Contents/CMakeLists.txt
  13. 69 0
      Modules/Contents/TUIO/CMakeLists.txt
  14. 45 0
      Modules/Contents/TUIO/Include/TUIOInputModule.h
  15. 211 0
      Modules/Contents/TUIO/Include/TuioClient.h
  16. 344 0
      Modules/Contents/TUIO/Include/TuioContainer.h
  17. 96 0
      Modules/Contents/TUIO/Include/TuioCursor.h
  18. 105 0
      Modules/Contents/TUIO/Include/TuioListener.h
  19. 260 0
      Modules/Contents/TUIO/Include/TuioObject.h
  20. 271 0
      Modules/Contents/TUIO/Include/TuioPoint.h
  21. 433 0
      Modules/Contents/TUIO/Include/TuioServer.h
  22. 244 0
      Modules/Contents/TUIO/Include/TuioTime.h
  23. 74 0
      Modules/Contents/TUIO/Include/ip/IpEndpointName.h
  24. 49 0
      Modules/Contents/TUIO/Include/ip/NetworkingUtils.h
  25. 43 0
      Modules/Contents/TUIO/Include/ip/PacketListener.h
  26. 40 0
      Modules/Contents/TUIO/Include/ip/TimerListener.h
  27. 158 0
      Modules/Contents/TUIO/Include/ip/UdpSocket.h
  28. 73 0
      Modules/Contents/TUIO/Include/osc/MessageMappingOscPacketListener.h
  29. 54 0
      Modules/Contents/TUIO/Include/osc/OscException.h
  30. 69 0
      Modules/Contents/TUIO/Include/osc/OscHostEndianness.h
  31. 142 0
      Modules/Contents/TUIO/Include/osc/OscOutboundPacketStream.h
  32. 72 0
      Modules/Contents/TUIO/Include/osc/OscPacketListener.h
  33. 50 0
      Modules/Contents/TUIO/Include/osc/OscPrintReceivedElements.h
  34. 486 0
      Modules/Contents/TUIO/Include/osc/OscReceivedElements.h
  35. 178 0
      Modules/Contents/TUIO/Include/osc/OscTypes.h
  36. 28 0
      Modules/Contents/TUIO/OSCPACK_LICENSE.txt
  37. 81 0
      Modules/Contents/TUIO/Source/IpEndpointName.cpp
  38. 639 0
      Modules/Contents/TUIO/Source/OscOutboundPacketStream.cpp
  39. 240 0
      Modules/Contents/TUIO/Source/OscPrintReceivedElements.cpp
  40. 722 0
      Modules/Contents/TUIO/Source/OscReceivedElements.cpp
  41. 40 0
      Modules/Contents/TUIO/Source/OscTypes.cpp
  42. 123 0
      Modules/Contents/TUIO/Source/TUIOInputModule.cpp
  43. 567 0
      Modules/Contents/TUIO/Source/TuioClient.cpp
  44. 636 0
      Modules/Contents/TUIO/Source/TuioServer.cpp
  45. 52 0
      Modules/Contents/TUIO/Source/TuioTime.cpp
  46. 57 0
      Modules/Contents/TUIO/Source/posix/NetworkingUtils.cpp
  47. 551 0
      Modules/Contents/TUIO/Source/posix/UdpSocket.cpp
  48. 88 0
      Modules/Contents/TUIO/Source/win32/NetworkingUtils.cpp
  49. 523 0
      Modules/Contents/TUIO/Source/win32/UdpSocket.cpp
  50. 340 0
      Modules/Contents/TUIO/TUIO_LICENSE.txt

+ 2 - 1
Core/Contents/Include/PolyCocoaCore.h

@@ -23,6 +23,7 @@
 #pragma once
 #include "PolyString.h"
 #include "PolyGlobals.h"
+#include "PolyLogger.h"
 #include "PolyCore.h"
 #include "PolyString.h"
 #include "PolyRectangle.h"
@@ -97,7 +98,7 @@ namespace Polycode {
 	class _PolyExport CocoaCore : public Core {		
 	public:
 		
-		CocoaCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate);
+		CocoaCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex=-1);
 		virtual ~CocoaCore();
 		
 		void enableMouse(bool newval);

+ 5 - 2
Core/Contents/Include/PolyCore.h

@@ -75,8 +75,9 @@ namespace Polycode {
 		* @param fullScreen True to launch in fullscreen, false to launch in window.
 		* @param aaLevel Level of anti-aliasing. Possible values are 2,4 and 6.
 		* @param frameRate Frame rate that the core will update and render at.
+		* @param monitorIndex If fullScreen is true, the monitor index to fullscreen to. Pass -1 to use primary monitor.
 		*/			
-		Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate);
+		Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex);
 		virtual ~Core();
 		
 		virtual bool Update() = 0;
@@ -311,7 +312,9 @@ namespace Polycode {
 		unsigned int lastSleepFrameTicks;
 		
 		int xRes;
-		int yRes;		
+		int yRes;	
+		
+		int monitorIndex;
 		
 		int frames;
 		

+ 5 - 2
Core/Contents/Include/PolyCoreInput.h

@@ -39,6 +39,7 @@ namespace Polycode {
 	};
 	
 	class InputEvent;
+	class TouchInfo;
 
 	/**
 	* User input event dispatcher. The Core input class is where all of the input events originate. You can add event listeners to this class to listen for user input events or poll it manually to check the state of user input.
@@ -107,8 +108,10 @@ namespace Polycode {
 		void setKeyState(PolyKEY keyCode, wchar_t code, bool newState, int ticks);
 		void setDeltaPosition(int x, int y);
 		
-		
-		
+		void touchesBegan(std::vector<TouchInfo> touches);
+		void touchesMoved(std::vector<TouchInfo> touches);
+		void touchesEnded(std::vector<TouchInfo> touches);
+				
 		static InputEvent *createEvent(Event *event){ return (InputEvent*)event; }
 		
 	protected:

+ 2 - 1
Core/Contents/Include/PolyCoreServices.h

@@ -160,7 +160,8 @@ namespace Polycode {
 			static CoreMutex *renderMutex;
 		
 			std::vector<PolycodeModule*> modules;
-		
+			std::vector<PolycodeModule*> updateModules;
+					
 			Core *core;
 			Config *config;
 			MaterialManager *materialManager;

+ 13 - 0
Core/Contents/Include/PolyInputEvent.h

@@ -28,6 +28,12 @@ THE SOFTWARE.
 
 namespace Polycode {
 
+	class TouchInfo { 
+		public:			
+			int id;
+			Vector2 position;
+	};	
+
 	/**
 	* Event dispatched by CoreInput. This event is dispatched by CoreInput when input happens.
 	*/
@@ -63,6 +69,11 @@ namespace Polycode {
 		static const int EVENT_JOYDEVICE_ATTACHED = 18;
 		static const int EVENT_JOYDEVICE_DETACHED = 19;
 		
+		static const int EVENT_TOUCHES_BEGAN = 20;
+		static const int EVENT_TOUCHES_MOVED = 21;
+		static const int EVENT_TOUCHES_ENDED =2;
+		
+		
 		//@}
 		// ----------------------------------------------------------------------------------------------------------------
 		
@@ -95,6 +106,8 @@ namespace Polycode {
 		wchar_t charCode;
 		int timestamp;
 		
+		std::vector<TouchInfo> touches;
+		
 		unsigned int joystickDeviceID;
 		float joystickAxisValue;
 		unsigned int joystickButton;

+ 6 - 0
Core/Contents/Include/PolyModule.h

@@ -30,8 +30,14 @@ namespace Polycode {
 		
 		static const int TYPE_GENERIC = 0;
 		static const int TYPE_SHADER = 0;
+		
+		virtual void Update(Number elapsed) {}
+		
+		bool requiresUpdate();
+		
 	protected:
 		int type;
+		bool _requiresUpdate;
 	};
 	
 	class _PolyExport PolycodeShaderModule : public PolycodeModule {

+ 15 - 5
Core/Contents/Source/PolyCocoaCore.mm

@@ -30,7 +30,7 @@ long getThreadID() {
 	return (long)pthread_self();
 }
 
-CocoaCore::CocoaCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate) : Core(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, frameRate) {	
+CocoaCore::CocoaCore(PolycodeView *view, int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex) : Core(xRes, yRes, fullScreen, vSync, aaLevel, anisotropyLevel, frameRate, monitorIndex) {	
 
 	hidManager = NULL;
 	initGamepad();
@@ -200,10 +200,20 @@ void CocoaCore::setVideoMode(int xRes, int yRes, bool fullScreen, bool vSync, in
 //		CGDisplaySwitchToMode (kCGDirectMainDisplay, CGDisplayBestModeForParameters (kCGDirectMainDisplay, 32, xRes, yRes, NULL) );						
 //	}
 	if(fullScreen) {	
-		CGDisplaySwitchToMode (kCGDirectMainDisplay, CGDisplayBestModeForParameters (kCGDirectMainDisplay, 32, xRes, yRes, NULL) );						
-//		[glView enterFullScreenMode:[NSScreen mainScreen] withOptions:[NSDictionary dictionaryWithObjectsAndKeys: nil]];
-		[glView enterFullScreenMode:[[NSScreen screens] objectAtIndex:1] withOptions:[NSDictionary dictionaryWithObjectsAndKeys: nil]];
-
+		CGDisplaySwitchToMode (kCGDirectMainDisplay, CGDisplayBestModeForParameters (kCGDirectMainDisplay, 32, xRes, yRes, NULL) );			
+		
+		if(monitorIndex > -1) {
+			if(monitorIndex > [[NSScreen screens] count]-1) {
+				Logger::log("Requested monitor index above available screens.\n");
+				monitorIndex = -1;
+			}
+		}
+		
+	    if(monitorIndex == -1) {		
+			[glView enterFullScreenMode:[NSScreen mainScreen] withOptions:[NSDictionary dictionaryWithObjectsAndKeys: nil]];
+		} else {
+			[glView enterFullScreenMode:[[NSScreen screens] objectAtIndex:1] withOptions:[NSDictionary dictionaryWithObjectsAndKeys: nil]];
+		}
 
 		
 	}

+ 3 - 1
Core/Contents/Source/PolyCore.cpp

@@ -31,7 +31,7 @@
 
 namespace Polycode {
 	
-	Core::Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate) : EventDispatcher() {
+	Core::Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex) : EventDispatcher() {
 		services = CoreServices::getInstance();
 		input = new CoreInput();
 		services->setCore(this);
@@ -46,6 +46,8 @@ namespace Polycode {
 		mouseEnabled = true;
 		lastSleepFrameTicks = 0;
 		
+		this->monitorIndex = monitorIndex;
+		
 		refreshInterval = 1000 / frameRate;
 	}
 	

+ 19 - 0
Core/Contents/Source/PolyCoreInput.cpp

@@ -182,4 +182,23 @@ namespace Polycode {
 			dispatchEvent(evt, InputEvent::EVENT_KEYUP);
 		}
 	}
+	
+	void CoreInput::touchesBegan(std::vector<TouchInfo> touches) {
+		InputEvent *evt = new InputEvent();
+		evt->touches = touches;
+		dispatchEvent(evt, InputEvent::EVENT_TOUCHES_BEGAN);
+	}
+	
+	void CoreInput::touchesMoved(std::vector<TouchInfo> touches) {
+		InputEvent *evt = new InputEvent();
+		evt->touches = touches;
+		dispatchEvent(evt, InputEvent::EVENT_TOUCHES_MOVED);	
+	}
+	
+	void CoreInput::touchesEnded(std::vector<TouchInfo> touches) {
+		InputEvent *evt = new InputEvent();
+		evt->touches = touches;
+		dispatchEvent(evt, InputEvent::EVENT_TOUCHES_ENDED);	
+	}
+	
 }

+ 9 - 0
Core/Contents/Source/PolyCoreServices.cpp

@@ -98,6 +98,10 @@ Config *CoreServices::getConfig() {
 
 void CoreServices::installModule(PolycodeModule *module)  {
 	modules.push_back(module);
+	if(module->requiresUpdate()) {
+		updateModules.push_back(module);
+	}
+	
 	switch(module->getType()) {
 		case PolycodeModule::TYPE_SHADER:
 //			renderer->addShaderModule((ShaderModule*)module);
@@ -183,6 +187,11 @@ Renderer *CoreServices::getRenderer() {
 }
 
 void CoreServices::Update(int elapsed) {
+	
+	for(int i=0; i < updateModules.size(); i++) {
+		updateModules[i]->Update(elapsed);
+	}
+
 	timerManager->Update();
 	tweenManager->Update();
 	materialManager->Update(elapsed);

+ 5 - 0
Core/Contents/Source/PolyModule.cpp

@@ -26,12 +26,17 @@ using namespace Polycode;
 
 PolycodeModule::PolycodeModule() {
 	type = TYPE_GENERIC;
+	_requiresUpdate = false;
 }
 
 PolycodeModule::~PolycodeModule() {
 	
 }
 
+bool PolycodeModule::requiresUpdate() {
+	return _requiresUpdate;
+}
+
 PolycodeShaderModule::PolycodeShaderModule() : PolycodeModule() {
 	type = TYPE_SHADER;
 }

+ 1 - 0
Modules/Contents/CMakeLists.txt

@@ -17,3 +17,4 @@ ENDIF(FREENECT_FOUND)
  
 ADD_SUBDIRECTORY(UI)
 ADD_SUBDIRECTORY(Networking)
+ADD_SUBDIRECTORY(TUIO)

+ 69 - 0
Modules/Contents/TUIO/CMakeLists.txt

@@ -0,0 +1,69 @@
+INCLUDE(PolycodeIncludes)
+
+SET(polycodeTUIO_SRCS
+    Source/IpEndpointName.cpp
+    Source/OscOutboundPacketStream.cpp
+    Source/OscPrintReceivedElements.cpp
+    Source/OscReceivedElements.cpp
+    Source/OscTypes.cpp
+    Source/TuioClient.cpp
+    Source/TUIOInputModule.cpp
+    Source/TuioServer.cpp
+    Source/TuioTime.cpp
+)
+
+SET(polycodeTUIO_HDRS
+    Include/TuioClient.h
+    Include/TuioContainer.h
+    Include/TuioCursor.h
+    Include/TUIOInputModule.h
+    Include/TuioListener.h
+    Include/TuioObject.h
+    Include/TuioPoint.h
+    Include/TuioServer.h
+    Include/TuioTime.h
+)
+
+IF(MSVC)
+    LIST(APPEND polycodeTUIO_SRCS Source/win32/NetworkingUtils.cpp)
+    LIST(APPEND polycodeTUIO_SRCS Source/win32/UdpSocket.cpp) 
+ELSE(MSVC)
+    LIST(APPEND polycodeTUIO_SRCS Source/posix/NetworkingUtils.cpp)
+    LIST(APPEND polycodeTUIO_SRCS Source/posix/UdpSocket.cpp) 
+ENDIF(MSVC)
+
+
+INCLUDE_DIRECTORIES(
+    Include
+    Include/osc
+    Include/ip
+)
+
+SET(CMAKE_DEBUG_POSTFIX "_d")
+
+ADD_LIBRARY(PolycodeTUIO ${polycodeTUIO_SRCS} ${polycodeTUIO_HDRS})
+
+TARGET_LINK_LIBRARIES(PolycodeTUIO
+    Polycore 
+    ${BOX2D_LIBRARIES}
+    ${OPENGL_LIBRARIES}
+    ${OPENAL_LIBRARY}
+    ${PNG_LIBRARIES}
+    ${FREETYPE_LIBRARIES}
+    ${PHYSFS_LIBRARY}
+    ${VORBISFILE_LIBRARY})
+IF(APPLE)
+    TARGET_LINK_LIBRARIES(PolycodeTUIO "-framework Cocoa")
+ENDIF(APPLE)
+
+IF(POLYCODE_INSTALL_FRAMEWORK)
+    
+    # install headers
+    INSTALL(FILES ${polycodeTUIO_HDRS} DESTINATION Modules/include)
+    INSTALL(DIRECTORY Include/ip DESTINATION Modules/include)
+    INSTALL(DIRECTORY Include/osc DESTINATION Modules/include)    
+    # install libraries
+    INSTALL(TARGETS PolycodeTUIO DESTINATION Modules/lib)
+    
+ENDIF(POLYCODE_INSTALL_FRAMEWORK)
+

+ 45 - 0
Modules/Contents/TUIO/Include/TUIOInputModule.h

@@ -0,0 +1,45 @@
+
+#pragma once
+
+#include <PolyInputEvent.h>
+#include <PolyCore.h>
+#include <PolyModule.h>
+
+#include "TuioListener.h"
+#include "TuioClient.h"
+#include "TuioObject.h"
+#include "TuioCursor.h"
+#include "TuioPoint.h"
+
+using namespace TUIO;
+using namespace Polycode;
+
+class TUIOEvent {
+	public:
+		std::vector<TouchInfo> touches;		
+		unsigned int type;
+};
+
+class TUIOInputModule : public PolycodeModule, TuioListener {
+	public:
+		TUIOInputModule(int port);
+		virtual ~TUIOInputModule();
+		
+		void addTuioObject(TuioObject *tobj);
+		void updateTuioObject(TuioObject *tobj);
+		void removeTuioObject(TuioObject *tobj);
+	
+		void addTuioCursor(TuioCursor *tcur);
+		void updateTuioCursor(TuioCursor *tcur);
+		void removeTuioCursor(TuioCursor *tcur);
+	
+		void refresh(TuioTime frameTime);
+		
+		void Update(Number elapsed);
+		
+	protected:
+	
+		CoreMutex *eventMutex;
+		TuioClient *tuioClient;
+		std::vector<TUIOEvent> events;
+};

+ 211 - 0
Modules/Contents/TUIO/Include/TuioClient.h

@@ -0,0 +1,211 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOCLIENT_H
+#define INCLUDED_TUIOCLIENT_H
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#else
+#include <windows.h>
+#endif
+
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <cstring>
+
+#include "osc/OscReceivedElements.h"
+#include "osc/OscPrintReceivedElements.h"
+
+#include "ip/UdpSocket.h"
+#include "ip/PacketListener.h"
+
+#include "TuioListener.h"
+#include "TuioObject.h"
+#include "TuioCursor.h"
+
+namespace TUIO {
+	
+	/**
+	 * <p>The TuioClient class is the central TUIO protocol decoder component. It provides a simple callback infrastructure using the {@link TuioListener} interface.
+	 * In order to receive and decode TUIO messages an instance of TuioClient needs to be created. The TuioClient instance then generates TUIO events
+	 * which are broadcasted to all registered classes that implement the {@link TuioListener} interface.</p> 
+	 * <p><code>
+	 * TuioClient *client = new TuioClient();<br/>
+	 * client->addTuioListener(myTuioListener);<br/>
+	 * client->connect();<br/>
+	 * </code></p>
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioClient : public PacketListener { 
+		
+	public:
+		/**
+		 * This constructor creates a TuioClient that listens to the provided port
+		 *
+		 * @param  port  the incoming TUIO UDP port number, defaults to 3333 if no argument is provided
+		 */
+		TuioClient(int port=3333);
+
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioClient();
+		
+		/**
+		 * The TuioClient starts listening to TUIO messages on the configured UDP port
+		 * All received TUIO messages are decoded and the resulting TUIO events are broadcasted to all registered TuioListeners
+		 *
+		 * @param  lock  running in the background if set to false (default)
+		 */
+		void connect(bool lock=false);
+
+		/**
+		 * The TuioClient stops listening to TUIO messages on the configured UDP port
+		 */
+		void disconnect();
+
+		/**
+		 * Returns true if this TuioClient is currently connected.
+		 * @return	true if this TuioClient is currently connected
+		 */
+		bool isConnected() { return connected; }
+				
+		/**
+		 * Adds the provided TuioListener to the list of registered TUIO event listeners
+		 *
+		 * @param  listener  the TuioListener to add
+		 */
+		void addTuioListener(TuioListener *listener);
+
+		/**
+		 * Removes the provided TuioListener from the list of registered TUIO event listeners
+		 *
+		 * @param  listener  the TuioListener to remove
+		 */
+		void removeTuioListener(TuioListener *listener);
+
+		/**
+		 * Removes all TuioListener from the list of registered TUIO event listeners
+		 */
+		void removeAllTuioListeners() {	
+			listenerList.clear();
+		}
+
+		/**
+		 * Returns a List of all currently active TuioObjects
+		 *
+		 * @return  a List of all currently active TuioObjects
+		 */
+		std::list<TuioObject*> getTuioObjects();
+		
+		/**
+		 * Returns a List of all currently active TuioCursors
+		 *
+		 * @return  a List of all currently active TuioCursors
+		 */
+		std::list<TuioCursor*> getTuioCursors();
+
+		/**
+		 * Returns the TuioObject corresponding to the provided Session ID
+		 * or NULL if the Session ID does not refer to an active TuioObject
+		 *
+		 * @return  an active TuioObject corresponding to the provided Session ID or NULL
+		 */
+		TuioObject* getTuioObject(long s_id);
+
+		/**
+		 * Returns the TuioCursor corresponding to the provided Session ID
+		 * or NULL if the Session ID does not refer to an active TuioCursor
+		 *
+		 * @return  an active TuioCursor corresponding to the provided Session ID or NULL
+		 */
+		TuioCursor* getTuioCursor(long s_id);
+
+		/**
+		 * Locks the TuioObject list in order to avoid updates during access
+		 */
+		void lockObjectList();
+
+		/**
+		 * Releases the lock of the TuioObject list
+		 */
+		void unlockObjectList();
+
+		/**
+		 * Locks the TuioCursor list in order to avoid updates during access
+		 */
+		void lockCursorList();
+
+		/**
+		 * Releases the lock of the TuioCursor list
+		 */
+		void unlockCursorList();
+
+		void ProcessPacket( const char *data, int size, const IpEndpointName &remoteEndpoint );
+		UdpListeningReceiveSocket *socket;
+				
+	protected:
+		void ProcessBundle( const osc::ReceivedBundle& b, const IpEndpointName& remoteEndpoint);
+		
+		/**
+		 * The OSC callback method where all TUIO messages are received and decoded
+		 * and where the TUIO event callbacks are dispatched
+		 *
+		 * @param  message		the received OSC message
+		 * @param  remoteEndpoint	the received OSC message origin
+		 */
+		void ProcessMessage( const osc::ReceivedMessage& message, const IpEndpointName& remoteEndpoint);
+		
+	private:
+		std::list<TuioListener*> listenerList;
+		
+		std::list<TuioObject*> objectList, frameObjects;
+		std::list<long> aliveObjectList;
+		std::list<TuioCursor*> cursorList, frameCursors;
+		std::list<long> aliveCursorList;
+		
+		osc::int32 currentFrame;
+		TuioTime currentTime;
+			
+		std::list<TuioCursor*> freeCursorList, freeCursorBuffer;
+		int maxCursorID;
+		
+#ifndef WIN32
+		pthread_t thread;
+		pthread_mutex_t objectMutex;
+		pthread_mutex_t cursorMutex;
+		//pthread_mutexattr_t attr_p;
+#else
+		HANDLE thread;
+		HANDLE objectMutex;
+		HANDLE cursorMutex;
+#endif	
+				
+		bool locked;
+		bool connected;
+	};
+};
+#endif /* INCLUDED_TUIOCLIENT_H */

+ 344 - 0
Modules/Contents/TUIO/Include/TuioContainer.h

@@ -0,0 +1,344 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOCONTAINER_H
+#define INCLUDED_TUIOCONTAINER_H
+
+#include <list>
+#include <math.h>
+#include "TuioPoint.h"
+#include <iostream>
+
+#define TUIO_ADDED 0
+#define TUIO_ACCELERATING 1
+#define TUIO_DECELERATING 2
+#define TUIO_STOPPED 3
+#define TUIO_REMOVED 4
+
+namespace TUIO {
+	
+	/**
+	 * The abstract TuioContainer class defines common attributes that apply to both subclasses {@link TuioObject} and {@link TuioCursor}.
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioContainer: public TuioPoint {
+		
+	protected:
+		/**
+		 * The unique session ID number that is assigned to each TUIO object or cursor.
+		 */ 
+		long session_id;
+		/**
+		 * The X-axis velocity value.
+		 */ 
+		float x_speed;
+		/**
+		 * The Y-axis velocity value.
+		 */ 
+		float y_speed;
+		/**
+		 * The motion speed value.
+		 */ 
+		float motion_speed;
+		/**
+		 * The motion acceleration value.
+		 */ 
+		float motion_accel;
+		/**
+		 * A List of TuioPoints containing all the previous positions of the TUIO component.
+		 */ 
+		std::list<TuioPoint> path;
+		/**
+		 * Reflects the current state of the TuioComponent
+		 */ 
+		int state;
+		
+	public:
+		/**
+		 * This constructor takes a TuioTime argument and assigns it along with the provided 
+		 * Session ID, X and Y coordinate to the newly created TuioContainer.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	si	the Session ID to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		TuioContainer (TuioTime ttime, long si, float xp, float yp):TuioPoint(ttime, xp,yp) {
+			session_id = si;
+			x_speed = 0.0f;
+			y_speed = 0.0f;
+			motion_speed = 0.0f;
+			motion_accel = 0.0f;			
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			state = TUIO_ADDED;
+		};
+
+		/**
+		 * This constructor takes the provided Session ID, X and Y coordinate 
+		 * and assigs these values to the newly created TuioContainer.
+		 *
+		 * @param	si	the Session ID to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		TuioContainer (long si, float xp, float yp):TuioPoint(xp,yp) {
+			session_id = si;
+			x_speed = 0.0f;
+			y_speed = 0.0f;
+			motion_speed = 0.0f;
+			motion_accel = 0.0f;			
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			state = TUIO_ADDED;
+		};
+		
+		/**
+		 * This constructor takes the atttibutes of the provided TuioContainer 
+		 * and assigs these values to the newly created TuioContainer.
+		 *
+		 * @param	tcon	the TuioContainer to assign
+		 */
+		TuioContainer (TuioContainer *tcon):TuioPoint(tcon) {
+			session_id = tcon->getSessionID();
+			x_speed = 0.0f;
+			y_speed = 0.0f;
+			motion_speed = 0.0f;
+			motion_accel = 0.0f;
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			state = TUIO_ADDED;
+		};
+		
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		virtual ~TuioContainer(){};
+		
+		/**
+		 * Takes a TuioTime argument and assigns it along with the provided 
+		 * X and Y coordinate to the private TuioContainer attributes.
+		 * The speed and accleration values are calculated accordingly.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		virtual void update (TuioTime ttime, float xp, float yp) {
+			TuioPoint lastPoint = path.back();
+			TuioPoint::update(ttime,xp, yp);
+			
+			TuioTime diffTime = currentTime - lastPoint.getTuioTime();
+			float dt = diffTime.getTotalMilliseconds()/1000.0f;
+			float dx = xpos - lastPoint.getX();
+			float dy = ypos - lastPoint.getY();
+			float dist = sqrt(dx*dx+dy*dy);
+			float last_motion_speed = motion_speed;
+			
+			x_speed = dx/dt;
+			y_speed = dy/dt;
+			motion_speed = dist/dt;
+			motion_accel = (motion_speed - last_motion_speed)/dt;
+			
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			if (motion_accel>0) state = TUIO_ACCELERATING;
+			else if (motion_accel<0) state = TUIO_DECELERATING;
+			else state = TUIO_STOPPED;
+		};
+
+		
+		/**
+		 * This method is used to calculate the speed and acceleration values of
+		 * TuioContainers with unchanged positions.
+		 */
+		virtual void stop(TuioTime ttime) {
+			update(ttime,xpos,ypos);
+		};
+
+		/**
+		 * Takes a TuioTime argument and assigns it along with the provided 
+		 * X and Y coordinate, X and Y velocity and acceleration
+		 * to the private TuioContainer attributes.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	xs	the X velocity to assign
+		 * @param	ys	the Y velocity to assign
+		 * @param	ma	the acceleration to assign
+		 */
+		virtual void update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma) {
+			TuioPoint::update(ttime,xp, yp);
+			x_speed = xs;
+			y_speed = ys;
+			motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
+			motion_accel = ma;
+			
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			if (motion_accel>0) state = TUIO_ACCELERATING;
+			else if (motion_accel<0) state = TUIO_DECELERATING;
+			else state = TUIO_STOPPED;
+		};
+		
+		/**
+		 * Assigns the provided X and Y coordinate, X and Y velocity and acceleration
+		 * to the private TuioContainer attributes. The TuioTime time stamp remains unchanged.
+		 *
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	xs	the X velocity to assign
+		 * @param	ys	the Y velocity to assign
+		 * @param	ma	the acceleration to assign
+		 */
+		virtual void update (float xp, float yp, float xs, float ys, float ma) {
+			TuioPoint::update(xp,yp);
+			x_speed = xs;
+			y_speed = ys;
+			motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
+			motion_accel = ma;
+			
+			path.pop_back();
+			TuioPoint p(currentTime,xpos,ypos);
+			path.push_back(p);
+			
+			if (motion_accel>0) state = TUIO_ACCELERATING;
+			else if (motion_accel<0) state = TUIO_DECELERATING;
+			else state = TUIO_STOPPED;
+		};
+		
+		/**
+		 * Takes the atttibutes of the provided TuioContainer 
+		 * and assigs these values to this TuioContainer.
+		 * The TuioTime time stamp of this TuioContainer remains unchanged.
+		 *
+		 * @param	tcon	the TuioContainer to assign
+		 */
+		virtual void update (TuioContainer *tcon) {
+			TuioPoint::update(tcon);
+			x_speed = tcon->getXSpeed();
+			y_speed =  tcon->getYSpeed();
+			motion_speed =  tcon->getMotionSpeed();
+			motion_accel = tcon->getMotionAccel();
+			
+			TuioPoint p(tcon->getTuioTime(),xpos,ypos);
+			path.push_back(p);
+			
+			if (motion_accel>0) state = TUIO_ACCELERATING;
+			else if (motion_accel<0) state = TUIO_DECELERATING;
+			else state = TUIO_STOPPED;
+		};
+		
+		/**
+		 * Assigns the REMOVE state to this TuioContainer and sets
+		 * its TuioTime time stamp to the provided TuioTime argument.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 */
+		virtual void remove(TuioTime ttime) {
+			currentTime = ttime;
+			state = TUIO_REMOVED;
+		}
+
+		/**
+		 * Returns the Session ID of this TuioContainer.
+		 * @return	the Session ID of this TuioContainer
+		 */
+		virtual long getSessionID() { 
+			return session_id;
+		};
+		
+		/**
+		 * Returns the X velocity of this TuioContainer.
+		 * @return	the X velocity of this TuioContainer
+		 */
+		virtual float getXSpeed() { 
+			return x_speed;
+		};
+
+		/**
+		 * Returns the Y velocity of this TuioContainer.
+		 * @return	the Y velocity of this TuioContainer
+		 */
+		virtual float getYSpeed() { 
+			return y_speed;
+		};
+		
+		/**
+		 * Returns the position of this TuioContainer.
+		 * @return	the position of this TuioContainer
+		 */
+		virtual TuioPoint getPosition() {
+			TuioPoint p(xpos,ypos);
+			return p;
+		};
+		
+		/**
+		 * Returns the path of this TuioContainer.
+		 * @return	the path of this TuioContainer
+		 */
+		virtual std::list<TuioPoint> getPath() {
+			return path;
+		};
+		
+		/**
+		 * Returns the motion speed of this TuioContainer.
+		 * @return	the motion speed of this TuioContainer
+		 */
+		virtual float getMotionSpeed() {
+			return motion_speed;
+		};
+		
+		/**
+		 * Returns the motion acceleration of this TuioContainer.
+		 * @return	the motion acceleration of this TuioContainer
+		 */
+		virtual float getMotionAccel() {
+			return motion_accel;
+		};
+		
+		/**
+		 * Returns the TUIO state of this TuioContainer.
+		 * @return	the TUIO state of this TuioContainer
+		 */
+		virtual int getTuioState() { 
+			return state;
+		};	
+		
+		/**
+		 * Returns true of this TuioContainer is moving.
+		 * @return	true of this TuioContainer is moving
+		 */
+		virtual bool isMoving() { 
+			if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING)) return true;
+			else return false;
+		};
+	};
+};
+#endif

+ 96 - 0
Modules/Contents/TUIO/Include/TuioCursor.h

@@ -0,0 +1,96 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOCURSOR_H
+#define INCLUDED_TUIOCURSOR_H
+
+#include <math.h>
+#include "TuioContainer.h"
+
+namespace TUIO {
+	
+	/**
+	 * The TuioCursor class encapsulates /tuio/2Dcur TUIO cursors.
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioCursor: public TuioContainer {
+		
+	protected:
+		/**
+		 * The individual cursor ID number that is assigned to each TuioCursor.
+		 */ 
+		int cursor_id;
+		
+	public:
+		/**
+		 * This constructor takes a TuioTime argument and assigns it along with the provided 
+		 * Session ID, Cursor ID, X and Y coordinate to the newly created TuioCursor.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	si	the Session ID  to assign
+		 * @param	ci	the Cursor ID  to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		TuioCursor (TuioTime ttime, long si, int ci, float xp, float yp):TuioContainer(ttime,si,xp,yp) {
+			cursor_id = ci;
+		};
+
+		/**
+		 * This constructor takes the provided Session ID, Cursor ID, X and Y coordinate 
+		 * and assigs these values to the newly created TuioCursor.
+		 *
+		 * @param	si	the Session ID  to assign
+		 * @param	ci	the Cursor ID  to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		TuioCursor (long si, int ci, float xp, float yp):TuioContainer(si,xp,yp) {
+			cursor_id = ci;
+		};
+		
+		/**
+		 * This constructor takes the atttibutes of the provided TuioCursor 
+		 * and assigs these values to the newly created TuioCursor.
+		 *
+		 * @param	tcur	the TuioCursor to assign
+		 */
+		TuioCursor (TuioCursor *tcur):TuioContainer(tcur) {
+			cursor_id = tcur->getCursorID();
+		};
+		
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioCursor(){};
+		
+		/**
+		 * Returns the Cursor ID of this TuioCursor.
+		 * @return	the Cursor ID of this TuioCursor
+		 */
+		int getCursorID() {
+			return cursor_id;
+		};
+	};
+};
+#endif

+ 105 - 0
Modules/Contents/TUIO/Include/TuioListener.h

@@ -0,0 +1,105 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOLISTENER_H
+#define INCLUDED_TUIOLISTENER_H
+
+#include "TuioObject.h"
+#include "TuioCursor.h"
+
+namespace TUIO {
+	
+	/**
+	 * <p>The TuioListener interface provides a simple callback infrastructure which is used by the {@link TuioClient} class 
+	 * to dispatch TUIO events to all registered instances of classes that implement the TuioListener interface defined here.</p> 
+	 * <p>Any class that implements the TuioListener interface is required to implement all of the callback methods defined here.
+	 * The {@link TuioClient} makes use of these interface methods in order to dispatch TUIO events to all registered TuioListener implementations.</p>
+	 * <p><code>
+	 * public class MyTuioListener implements TuioListener<br/>
+	 * ...</code><p><code>
+	 * MyTuioListener listener = new MyTuioListener();<br/>
+	 * TuioClient client = new TuioClient();<br/>
+	 * client.addTuioListener(listener);<br/>
+	 * client.start();<br/>
+	 * </code></p>
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */
+	class TuioListener { 
+		
+	public:
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		virtual ~TuioListener(){};
+		
+		/**
+		 * This callback method is invoked by the TuioClient when a new TuioObject is added to the session.   
+		 *
+		 * @param  tobj  the TuioObject reference associated to the addTuioObject event
+		 */
+		virtual void addTuioObject(TuioObject *tobj)=0;
+
+		/**
+		 * This callback method is invoked by the TuioClient when an existing TuioObject is updated during the session.   
+		 *
+		 * @param  tobj  the TuioObject reference associated to the updateTuioObject event
+		 */
+		virtual void updateTuioObject(TuioObject *tobj)=0;
+		
+		/**
+		 * This callback method is invoked by the TuioClient when an existing TuioObject is removed from the session.   
+		 *
+		 * @param  tobj  the TuioObject reference associated to the removeTuioObject event
+		 */
+		virtual void removeTuioObject(TuioObject *tobj)=0;
+		
+		/**
+		 * This callback method is invoked by the TuioClient when a new TuioCursor is added to the session.   
+		 *
+		 * @param  tcur  the TuioCursor reference associated to the addTuioCursor event
+		 */
+		virtual void addTuioCursor(TuioCursor *tcur)=0;
+
+		/**
+		 * This callback method is invoked by the TuioClient when an existing TuioCursor is updated during the session.   
+		 *
+		 * @param  tcur  the TuioCursor reference associated to the updateTuioCursor event
+		 */
+		virtual void updateTuioCursor(TuioCursor *tcur)=0;
+
+		/**
+		 * This callback method is invoked by the TuioClient when an existing TuioCursor is removed from the session.   
+		 *
+		 * @param  tcur  the TuioCursor reference associated to the removeTuioCursor event
+		 */
+		virtual void removeTuioCursor(TuioCursor *tcur)=0;
+		
+		/**
+		 * This callback method is invoked by the TuioClient to mark the end of a received TUIO message bundle.   
+		 *
+		 * @param  ftime  the TuioTime associated to the current TUIO message bundle
+		 */
+		virtual void refresh(TuioTime ftime)=0;
+	};
+};
+#endif /* INCLUDED_TUIOLISTENER_H */

+ 260 - 0
Modules/Contents/TUIO/Include/TuioObject.h

@@ -0,0 +1,260 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOOBJECT_H
+#define INCLUDED_TUIOOBJECT_H
+
+#include <math.h>
+#include "TuioContainer.h"
+
+#define TUIO_ROTATING 5
+
+namespace TUIO {
+	
+	/**
+	 * The TuioObject class encapsulates /tuio/2Dobj TUIO objects.
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioObject: public TuioContainer {
+		
+	protected:
+		/**
+		 * The individual symbol ID number that is assigned to each TuioObject.
+		 */ 
+		int symbol_id;
+		/**
+		 * The rotation angle value.
+		 */ 
+		float angle;
+		/**
+		 * The rotation speed value.
+		 */ 
+		float rotation_speed;
+		/**
+		 * The rotation acceleration value.
+		 */ 
+		float rotation_accel;
+		
+	public:
+		/**
+		 * This constructor takes a TuioTime argument and assigns it along with the provided 
+		 * Session ID, Symbol ID, X and Y coordinate and angle to the newly created TuioObject.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	si	the Session ID  to assign
+		 * @param	sym	the Symbol ID  to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle to assign
+		 */
+		TuioObject (TuioTime ttime, long si, int sym, float xp, float yp, float a):TuioContainer(ttime, si, xp, yp) {
+			symbol_id = sym;
+			angle = a;
+			rotation_speed = 0.0f;
+			rotation_accel = 0.0f;
+		};
+
+		/**
+		 * This constructor takes the provided Session ID, Symbol ID, X and Y coordinate 
+		 * and angle, and assigs these values to the newly created TuioObject.
+		 *
+		 * @param	si	the Session ID  to assign
+		 * @param	sym	the Symbol ID  to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle to assign
+		 */	
+		TuioObject (long si, int sym, float xp, float yp, float a):TuioContainer(si, xp, yp) {
+			symbol_id = sym;
+			angle = a;
+			rotation_speed = 0.0f;
+			rotation_accel = 0.0f;
+		};
+		
+		/**
+		 * This constructor takes the atttibutes of the provided TuioObject 
+		 * and assigs these values to the newly created TuioObject.
+		 *
+		 * @param	tobj	the TuioObject to assign
+		 */
+		TuioObject (TuioObject *tobj):TuioContainer(tobj) {
+			symbol_id = tobj->getSymbolID();
+			angle = tobj->getAngle();
+			rotation_speed = 0.0f;
+			rotation_accel = 0.0f;
+		};
+		
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioObject() {};
+		
+		/**
+		 * Takes a TuioTime argument and assigns it along with the provided 
+		 * X and Y coordinate, angle, X and Y velocity, motion acceleration,
+		 * rotation speed and rotation acceleration to the private TuioObject attributes.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle coordinate to assign
+		 * @param	xs	the X velocity to assign
+		 * @param	ys	the Y velocity to assign
+		 * @param	rs	the rotation velocity to assign
+		 * @param	ma	the motion acceleration to assign
+		 * @param	ra	the rotation acceleration to assign
+		 */
+		void update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
+			TuioContainer::update(ttime,xp,yp,xs,ys,ma);
+			angle = a;
+			rotation_speed = rs;
+			rotation_accel = ra;
+			if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
+		};
+
+		/**
+		 * Assigns the provided X and Y coordinate, angle, X and Y velocity, motion acceleration
+		 * rotation velocity and rotation acceleration to the private TuioContainer attributes.
+		 * The TuioTime time stamp remains unchanged.
+		 *
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle coordinate to assign
+		 * @param	xs	the X velocity to assign
+		 * @param	ys	the Y velocity to assign
+		 * @param	rs	the rotation velocity to assign
+		 * @param	ma	the motion acceleration to assign
+		 * @param	ra	the rotation acceleration to assign
+		 */
+		void update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
+			TuioContainer::update(xp,yp,xs,ys,ma);
+			angle = a;
+			rotation_speed = rs;
+			rotation_accel = ra;
+			if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
+		};
+		
+		/**
+		 * Takes a TuioTime argument and assigns it along with the provided 
+		 * X and Y coordinate and angle to the private TuioObject attributes.
+		 * The speed and accleration values are calculated accordingly.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle coordinate to assign
+		 */
+		void update (TuioTime ttime, float xp, float yp, float a) {
+			TuioPoint lastPoint = path.back();
+			TuioContainer::update(ttime,xp,yp);
+			
+			TuioTime diffTime = currentTime - lastPoint.getTuioTime();
+			float dt = diffTime.getTotalMilliseconds()/1000.0f;
+			float last_angle = angle;
+			float last_rotation_speed = rotation_speed;
+			angle = a;
+			
+			double da = (angle-last_angle)/(2*M_PI);
+			if (da>M_PI*1.5) da-=(2*M_PI);
+			else if (da<M_PI*1.5) da+=(2*M_PI);
+			
+			rotation_speed = (float)da/dt;
+			rotation_accel =  (rotation_speed - last_rotation_speed)/dt;
+			
+			if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
+		};
+
+		/**
+		 * This method is used to calculate the speed and acceleration values of a
+		 * TuioObject with unchanged position and angle.
+		 */
+		void stop (TuioTime ttime) {
+			update(ttime,xpos,ypos,angle);
+		};
+		
+		/**
+		 * Takes the atttibutes of the provided TuioObject 
+		 * and assigs these values to this TuioObject.
+		 * The TuioTime time stamp of this TuioContainer remains unchanged.
+		 *
+		 * @param	tobj	the TuioContainer to assign
+		 */	
+		void update (TuioObject *tobj) {
+			TuioContainer::update(tobj);
+			angle = tobj->getAngle();
+			rotation_speed = tobj->getRotationSpeed();
+			rotation_accel = tobj->getRotationAccel();
+			if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
+		};
+		
+		/**
+		 * Returns the symbol ID of this TuioObject.
+		 * @return	the symbol ID of this TuioObject
+		 */
+		int getSymbolID() { 
+			return symbol_id;
+		};
+		
+		/**
+		 * Returns the rotation angle of this TuioObject.
+		 * @return	the rotation angle of this TuioObject
+		 */
+		float getAngle() {
+			return angle;
+		};
+		
+		/**
+		 * Returns the rotation angle in degrees of this TuioObject.
+		 * @return	the rotation angle in degrees of this TuioObject
+		 */
+		float getAngleDegrees() { 
+			return (float)(angle/M_PI*180);
+		};
+		
+		/**
+		 * Returns the rotation speed of this TuioObject.
+		 * @return	the rotation speed of this TuioObject
+		 */
+		float getRotationSpeed() { 
+			return rotation_speed;
+		};
+		
+		/**
+		 * Returns the rotation acceleration of this TuioObject.
+		 * @return	the rotation acceleration of this TuioObject
+		 */
+		float getRotationAccel() {
+			return rotation_accel;
+		};
+
+		/**
+		 * Returns true of this TuioObject is moving.
+		 * @return	true of this TuioObject is moving
+		 */
+		virtual bool isMoving() { 
+			if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING) || (state==TUIO_ROTATING)) return true;
+			else return false;
+		};
+	};
+};
+#endif

+ 271 - 0
Modules/Contents/TUIO/Include/TuioPoint.h

@@ -0,0 +1,271 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOPOINT_H
+#define INCLUDED_TUIOPOINT_H
+#include "TuioTime.h"
+#include <iostream>
+
+#ifndef M_PI
+#define M_PI	3.14159265358979323846
+
+#endif
+
+namespace TUIO {
+	
+	/**
+	 * The TuioPoint class on the one hand is a simple container and utility class to handle TUIO positions in general, 
+	 * on the other hand the TuioPoint is the base class for the TuioCursor and TuioObject classes.
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioPoint {
+		
+	protected:
+		/**
+		 * X coordinate, representated as a floating point value in a range of 0..1  
+		 */
+		float xpos;
+		/**
+		 * X coordinate, representated as a floating point value in a range of 0..1  
+		 */
+		float ypos;
+		/**
+		 * The time stamp of the last update represented as TuioTime (time since session start)
+		 */
+		TuioTime currentTime;
+		/**
+		 * The creation time of this TuioPoint represented as TuioTime (time since session start)
+		 */
+		TuioTime startTime;
+		
+	public:
+		/**
+		 * The default constructor takes no arguments and sets   
+		 * its coordinate attributes to zero and its time stamp to the current session time.
+		 */
+		TuioPoint (float xp, float yp) {
+			xpos = xp;
+			ypos = yp;
+			currentTime = TuioTime::getSessionTime();
+			startTime = currentTime;
+		};
+	
+		/**
+		 * This constructor takes a TuioTime object and two floating point coordinate arguments and sets   
+		 * its coordinate attributes to these values and its time stamp to the provided TUIO time object.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		TuioPoint (TuioTime ttime, float xp, float yp) {
+			xpos = xp;
+			ypos = yp;
+			currentTime = ttime;
+			startTime = currentTime;
+		};
+		
+		/**
+		 * This constructor takes a TuioPoint argument and sets its coordinate attributes 
+		 * to the coordinates of the provided TuioPoint and its time stamp to the current session time.
+		 *
+		 * @param	tpoint	the TuioPoint to assign
+		 */
+		TuioPoint (TuioPoint *tpoint) {
+			xpos = tpoint->getX();
+			ypos = tpoint->getY();
+			currentTime = TuioTime::getSessionTime();
+			startTime = currentTime;
+		};
+		
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioPoint(){};
+		
+		/**
+		 * Takes a TuioPoint argument and updates its coordinate attributes 
+		 * to the coordinates of the provided TuioPoint and leaves its time stamp unchanged.
+		 *
+		 * @param	tpoint	the TuioPoint to assign
+		 */
+		void update (TuioPoint *tpoint) {
+			xpos = tpoint->getX();
+			ypos = tpoint->getY();
+		};
+		
+		/**
+		 * Takes two floating point coordinate arguments and updates its coordinate attributes 
+		 * to the coordinates of the provided TuioPoint and leaves its time stamp unchanged.
+		 *
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */		
+		void update (float xp, float yp) {
+			xpos = xp;
+			ypos = yp;
+		};		
+		
+		/**
+		 * Takes a TuioTime object and two floating point coordinate arguments and updates its coordinate attributes 
+		 * to the coordinates of the provided TuioPoint and its time stamp to the provided TUIO time object.
+		 *
+		 * @param	ttime	the TuioTime to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		void update (TuioTime ttime, float xp, float yp) {
+			xpos = xp;
+			ypos = yp;
+			currentTime = ttime;
+		};
+
+		
+		/**
+		 * Returns the X coordinate of this TuioPoint. 
+		 * @return	the X coordinate of this TuioPoint
+		 */
+		float getX() { 
+			return xpos;
+		};
+		
+		/**
+		 * Returns the Y coordinate of this TuioPoint. 
+		 * @return	the Y coordinate of this TuioPoint
+		 */
+		float getY() {
+			return ypos;
+		};
+		
+		/**
+		 * Returns the distance to the provided coordinates 
+		 *
+		 * @param	xp	the X coordinate of the distant point
+		 * @param	yp	the Y coordinate of the distant point
+		 * @return	the distance to the provided coordinates
+		 */
+		float getDistance(float xp, float yp) {
+			float dx = xpos-xp;
+			float dy = ypos-yp;
+			return sqrtf(dx*dx+dy*dy);
+		}
+		
+		/**
+		 * Returns the distance to the provided TuioPoint 
+		 *
+		 * @param	tpoint	the distant TuioPoint
+		 * @return	the distance to the provided TuioPoint
+		 */
+		float getDistance(TuioPoint *tpoint) {
+			return getDistance(tpoint->getX(),tpoint->getY());
+		}
+		
+		/**
+		 * Returns the angle to the provided coordinates 
+		 *
+		 * @param	xp	the X coordinate of the distant point
+		 * @param	yp	the Y coordinate of the distant point
+		 * @return	the angle to the provided coordinates
+		 */
+		 float getAngle(float xp, float yp) {
+			float side = xpos-xp;
+			float height = ypos-yp;
+			float distance = getDistance(xp,yp);
+			
+			float angle = (float)(asin(side/distance)+M_PI/2);
+			if (height<0) angle = 2.0f*(float)M_PI-angle;
+			
+			return angle;
+		}
+		
+		/**
+		 * Returns the angle to the provided TuioPoint 
+		 *
+		 * @param	tpoint	the distant TuioPoint
+		 * @return	the angle to the provided TuioPoint
+		 */
+		float getAngle(TuioPoint *tpoint) {
+			return getAngle(tpoint->getX(),tpoint->getY());
+		}
+
+		/**
+		 * Returns the angle in degrees to the provided coordinates 
+		 *
+		 * @param	xp	the X coordinate of the distant point
+		 * @param	yp	the Y coordinate of the distant point
+		 * @return	the angle in degrees to the provided TuioPoint
+		 */
+		float getAngleDegrees(float xp, float yp) {
+			return ((getAngle(xp,yp)/(float)M_PI)*180.0f);
+		}
+
+		/**
+		 * Returns the angle in degrees to the provided TuioPoint 
+		 *
+		 * @param	tpoint	the distant TuioPoint
+		 * @return	the angle in degrees to the provided TuioPoint
+		 */
+		float getAngleDegrees(TuioPoint *tpoint) {
+			return ((getAngle(tpoint)/(float)M_PI)*180.0f);
+		}
+		
+		/**
+		 * Returns the X coordinate in pixels relative to the provided screen width. 
+		 *
+		 * @param	width	the screen width
+		 * @return	the X coordinate of this TuioPoint in pixels relative to the provided screen width
+		 */
+		int getScreenX(int width) { 
+			return (int)floor(xpos*width+0.5f);
+		};
+		
+		/**
+		 * Returns the Y coordinate in pixels relative to the provided screen height. 
+		 *
+		 * @param	height	the screen height
+		 * @return	the Y coordinate of this TuioPoint in pixels relative to the provided screen height
+		 */
+		int getScreenY(int height) {
+			return (int)floor(ypos*height+0.5f);
+		};
+		
+		/**
+		 * Returns current time stamp of this TuioPoint as TuioTime 
+		 *
+		 * @return	the  time stamp of this TuioPoint as TuioTime
+		 */
+		TuioTime getTuioTime() { 
+			return currentTime;
+		};
+		
+		/**
+		 * Returns the start time of this TuioPoint as TuioTime. 
+		 *
+		 * @return	the start time of this TuioPoint as TuioTime
+		 */
+		TuioTime getStartTime() {
+			return startTime;
+		};
+	};
+};
+#endif

+ 433 - 0
Modules/Contents/TUIO/Include/TuioServer.h

@@ -0,0 +1,433 @@
+/*
+ TUIO Server Component - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TuioServer_H
+#define INCLUDED_TuioServer_H
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#else
+#include <windows.h>
+#endif
+
+#include <iostream>
+#include <list>
+#include <algorithm>
+
+#include "osc/OscOutboundPacketStream.h"
+#include "ip/NetworkingUtils.h"
+#include "ip/UdpSocket.h"
+
+#include "TuioObject.h"
+#include "TuioCursor.h"
+
+#define IP_MTU_SIZE 1500
+#define MAX_UDP_SIZE 65536
+#define MIN_UDP_SIZE 576
+#define OBJ_MESSAGE_SIZE 108	// setMessage + seqMessage size
+#define CUR_MESSAGE_SIZE 88
+
+namespace TUIO {
+	/**
+	 * <p>The TuioServer class is the central TUIO protocol encoder component.
+	 * In order to encode and send TUIO messages an instance of TuioServer needs to be created. The TuioServer instance then generates TUIO messaged
+	 * which are sent via OSC over UDP to the configured IP address and port.</p> 
+	 * <p>During runtime the each frame is marked with the initFrame and commitFrame methods, 
+	 * while the currently present TuioObjects are managed by the server with ADD, UPDATE and REMOVE methods in analogy to the TuioClient's TuioListener interface.</p> 
+	 * <p><code>
+	 * TuioClient *server = new TuioServer();<br/>
+	 * ...<br/>
+	 * server->initFrame(TuioTime::getSessionTime());<br/>
+	 * TuioObject *tobj = server->addTuioObject(xpos,ypos, angle);<br/>
+	 * TuioCursor *tcur = server->addTuioObject(xpos,ypos);<br/>
+	 * server->commitFrame();<br/>
+	 * ...<br/>
+	 * server->initFrame(TuioTime::getSessionTime());<br/>
+	 * server->updateTuioObject(tobj, xpos,ypos, angle);<br/>
+	 * server->updateTuioCursor(tcur, xpos,ypos);<br/>
+	 * server->commitFrame();<br/>
+	 * ...<br/>
+	 * server->initFrame(TuioTime::getSessionTime());<br/>
+	 * server->removeTuioObject(tobj);<br/>
+	 * server->removeTuioCursor(tcur);<br/>
+	 * server->commitFrame();<br/>
+	 * </code></p>
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioServer { 
+		
+	public:
+
+		/**
+		 * The default constructor creates a TuioServer that sends to the default TUIO port 3333 on localhost
+		 * using the maximum packet size of 65536 bytes to use single packets on the loopback device
+		 */
+		TuioServer();
+
+		/**
+		 * This constructor creates a TuioServer that sends to the provided port on the the given host
+		 * using a default packet size of 1492 bytes to deliver unfragmented UDP packets on a LAN
+		 *
+		 * @param  host  the receiving host name
+		 * @param  port  the outgoing TUIO UDP port number
+		 */
+		TuioServer(const char *host, int port);
+
+		/**
+		 * This constructor creates a TuioServer that sends to the provided port on the the given host
+		 * the packet UDP size can be set to a value between 576 and 65536 bytes
+		 *
+		 * @param  host  the receiving host name
+		 * @param  port  the outgoing TUIO UDP port number
+		 * @param  size  the maximum UDP packet size
+		 */
+		TuioServer(const char *host, int port, int size);
+
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioServer();
+		
+		/**
+		 * Creates a new TuioObject based on the given arguments.
+		 * The new TuioObject is added to the TuioServer's internal list of active TuioObjects 
+		 * and a reference is returned to the caller.
+		 *
+		 * @param	sym	the Symbol ID  to assign
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle to assign
+		 * @return	reference to the created TuioObject
+		 */
+		TuioObject* addTuioObject(int sym, float xp, float yp, float a);
+
+		/**
+		 * Updates the referenced TuioObject based on the given arguments.
+		 *
+		 * @param	tobj	the TuioObject to update
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @param	a	the angle to assign
+		 */
+		void updateTuioObject(TuioObject *tobj, float xp, float yp, float a);
+
+		/**
+		 * Removes the referenced TuioObject from the TuioServer's internal list of TuioObjects
+		 * and deletes the referenced TuioObject afterwards
+		 *
+		 * @param	tobj	the TuioObject to remove
+		 */
+		void removeTuioObject(TuioObject *tobj);
+
+		/**
+		 * Adds an externally managed TuioObject to the TuioServer's internal list of active TuioObjects 
+		 *
+		 * @param	tobj	the TuioObject to add
+		 */
+		void addExternalTuioObject(TuioObject *tobj);
+
+		/**
+		 * Updates an externally managed TuioObject 
+		 *
+		 * @param	tobj	the TuioObject to update
+		 */
+		void updateExternalTuioObject(TuioObject *tobj);
+
+		/**
+		 * Removes an externally managed TuioObject from the TuioServer's internal list of TuioObjects
+		 * The referenced TuioObject is not deleted
+		 *
+		 * @param	tobj	the TuioObject to remove
+		 */
+		void removeExternalTuioObject(TuioObject *tobj);
+		
+		/**
+		 * Creates a new TuioCursor based on the given arguments.
+		 * The new TuioCursor is added to the TuioServer's internal list of active TuioCursors 
+		 * and a reference is returned to the caller.
+		 *
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 * @return	reference to the created TuioCursor
+		 */
+		TuioCursor* addTuioCursor(float xp, float yp);
+
+		/**
+		 * Updates the referenced TuioCursor based on the given arguments.
+		 *
+		 * @param	tcur	the TuioObject to update
+		 * @param	xp	the X coordinate to assign
+		 * @param	yp	the Y coordinate to assign
+		 */
+		void updateTuioCursor(TuioCursor *tcur, float xp, float yp);
+
+		/**
+		 * Removes the referenced TuioCursor from the TuioServer's internal list of TuioCursors
+		 * and deletes the referenced TuioCursor afterwards
+		 *
+		 * @param	tcur	the TuioCursor to remove
+		 */
+		void removeTuioCursor(TuioCursor *tcur);
+
+		/**
+		 * Updates an externally managed TuioCursor 
+		 *
+		 * @param	tcur	the TuioCursor to update
+		 */
+		void addExternalTuioCursor(TuioCursor *tcur);
+
+		/**
+		 * Updates an externally managed TuioCursor 
+		 *
+		 * @param	tcur	the TuioCursor to update
+		 */
+		void updateExternalTuioCursor(TuioCursor *tcur);
+
+		/**
+		 * Removes an externally managed TuioCursor from the TuioServer's internal list of TuioCursor
+		 * The referenced TuioCursor is not deleted
+		 *
+		 * @param	tcur	the TuioCursor to remove
+		 */
+		void removeExternalTuioCursor(TuioCursor *tcur);
+		
+		/**
+		 * Initializes a new frame with the given TuioTime
+		 *
+		 * @param	ttime	the frame time
+		 */
+		void initFrame(TuioTime ttime);
+		
+		/**
+		 * Commits the current frame.
+		 * Generates and sends TUIO messages of all currently active and updated TuioObjects and TuioCursors.
+		 */
+		void commitFrame();
+
+		/**
+		 * Returns the next available Session ID for external use.
+		 * @return	the next available Session ID for external use
+		 */
+		long getSessionID();
+
+		/**
+		 * Returns the current frame ID for external use.
+		 * @return	the current frame ID for external use
+		 */
+		long getFrameID();
+		
+		/**
+		 * Returns the current frame ID for external use.
+		 * @return	the current frame ID for external use
+		 */
+		TuioTime getFrameTime();
+
+		/**
+		 * Generates and sends TUIO messages of all currently active TuioObjects and TuioCursors.
+		 */
+		void sendFullMessages();		
+
+		/**
+		 * Disables the periodic full update of all currently active TuioObjects and TuioCursors 
+		 *
+		 * @param	interval	update interval in seconds, defaults to one second
+		 */
+		void enablePeriodicMessages(int interval=1);
+
+		/**
+		 * Disables the periodic full update of all currently active and inactive TuioObjects and TuioCursors 
+		 */
+		void disablePeriodicMessages();
+
+		/**
+		 * Enables the full update of all currently active and inactive TuioObjects and TuioCursors 
+		 *
+		 */
+		void enableFullUpdate()  {
+			full_update = true;
+		}
+		
+		/**
+		 * Disables the full update of all currently active and inactive TuioObjects and TuioCursors 
+		 */
+		void disableFullUpdate() {
+			full_update = false;
+		}
+		
+		/**
+		 * Returns true if the periodic full update of all currently active TuioObjects and TuioCursors is enabled.
+		 * @return	true if the periodic full update of all currently active TuioObjects and TuioCursors is enabled
+		 */
+		bool periodicMessagesEnabled() {
+			return periodic_update;
+		}
+	
+		/**
+		 * Returns the periodic update interval in seconds.
+		 * @return	the periodic update interval in seconds
+		 */
+		int getUpdateInterval() {
+			return update_interval;
+		}
+		
+		/**
+		 * Returns a List of all currently inactive TuioObjects
+		 *
+		 * @return  a List of all currently inactive TuioObjects
+		 */
+		std::list<TuioObject*> getUntouchedObjects();
+
+		/**
+		 * Returns a List of all currently inactive TuioCursors
+		 *
+		 * @return  a List of all currently inactive TuioCursors
+		 */
+		std::list<TuioCursor*> getUntouchedCursors();
+		
+		/**
+		 * Calculates speed and acceleration values for all currently inactive TuioObjects
+		 */
+		void stopUntouchedMovingObjects();
+
+		/**
+		 * Calculates speed and acceleration values for all currently inactive TuioCursors
+		 */
+		void stopUntouchedMovingCursors();
+		
+		/**
+		 * Removes all currently inactive TuioObjects from the TuioServer's internal list of TuioObjects
+		 */
+		void removeUntouchedStoppedObjects();
+
+		/**
+		 * Removes all currently inactive TuioCursors from the TuioServer's internal list of TuioCursors
+		 */
+		void removeUntouchedStoppedCursors();
+
+		/**
+		 * Returns a List of all currently active TuioObjects
+		 *
+		 * @return  a List of all currently active TuioObjects
+		 */
+		std::list<TuioObject*> getTuioObjects();
+		
+		
+		/**
+		 * Returns a List of all currently active TuioCursors
+		 *
+		 * @return  a List of all currently active TuioCursors
+		 */
+		std::list<TuioCursor*> getTuioCursors();
+		
+		/**
+		 * Returns the TuioObject corresponding to the provided Session ID
+		 * or NULL if the Session ID does not refer to an active TuioObject
+		 *
+		 * @return  an active TuioObject corresponding to the provided Session ID or NULL
+		 */
+		TuioObject* getTuioObject(long s_id);
+		
+		/**
+		 * Returns the TuioCursor corresponding to the provided Session ID
+		 * or NULL if the Session ID does not refer to an active TuioCursor
+		 *
+		 * @return  an active TuioCursor corresponding to the provided Session ID or NULL
+		 */
+		TuioCursor* getTuioCursor(long s_id);
+
+		/**
+		 * Returns the TuioObject closest to the provided coordinates
+		 * or NULL if there isn't any active TuioObject
+		 *
+		 * @return  the closest TuioObject to the provided coordinates or NULL
+		 */
+		TuioObject* getClosestTuioObject(float xp, float yp);
+		
+		/**
+		 * Returns the TuioCursor closest to the provided coordinates
+		 * or NULL if there isn't any active TuioCursor
+		 *
+		 * @return  the closest TuioCursor corresponding to the provided coordinates or NULL
+		 */
+		TuioCursor* getClosestTuioCursor(float xp, float yp);
+		
+		/**
+		 * Returns true if this TuioServer is currently connected.
+		 * @return	true if this TuioServer is currently connected
+		 */
+		bool isConnected() { return connected; }
+		
+		/**
+		 * The TuioServer prints verbose TUIO event messages to the console if set to true.
+		 * @param	verbose	verbose message output if set to true
+		 */
+		void setVerbose(bool verbose) { this->verbose=verbose; }
+		
+	private:
+		std::list<TuioObject*> objectList;
+		std::list<TuioCursor*> cursorList;
+		
+		int maxCursorID;
+		std::list<TuioCursor*> freeCursorList;
+		std::list<TuioCursor*> freeCursorBuffer;
+		
+		UdpTransmitSocket *socket;	
+		osc::OutboundPacketStream  *oscPacket;
+		char *oscBuffer; 
+		osc::OutboundPacketStream  *fullPacket;
+		char *fullBuffer; 
+		
+		void initialize(const char *host, int port, int size);
+
+		void sendEmptyCursorBundle();
+		void startCursorBundle();
+		void addCursorMessage(TuioCursor *tcur);
+		void sendCursorBundle(long fseq);
+		
+		void sendEmptyObjectBundle();
+		void startObjectBundle();
+		void addObjectMessage(TuioObject *tobj);
+		void sendObjectBundle(long fseq);
+		
+		bool full_update;
+		int update_interval;
+		bool periodic_update;
+
+		long currentFrame;
+		TuioTime currentFrameTime;
+		bool updateObject, updateCursor;
+		long lastCursorUpdate, lastObjectUpdate;
+
+		long sessionID;
+		bool verbose;
+
+#ifndef WIN32
+		pthread_t thread;
+#else
+		HANDLE thread;
+#endif	
+		bool connected;
+	};
+};
+#endif /* INCLUDED_TuioServer_H */

+ 244 - 0
Modules/Contents/TUIO/Include/TuioTime.h

@@ -0,0 +1,244 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef INCLUDED_TUIOTIME_H
+#define INCLUDED_TUIOTIME_H
+
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#else
+#include <windows.h>
+#endif
+
+#define MSEC_SECOND 1000
+#define USEC_SECOND 1000000
+#define USEC_MILLISECOND 1000
+
+namespace TUIO {
+	
+	/**
+	 * The TuioTime class is a simple structure that is used to reprent the time that has elapsed since the session start.
+	 * The time is internally represented as seconds and fractions of microseconds which should be more than sufficient for gesture related timing requirements.
+	 * Therefore at the beginning of a typical TUIO session the static method initSession() will set the reference time for the session. 
+	 * Another important static method getSessionTime will return a TuioTime object representing the time elapsed since the session start.
+	 * The class also provides various addtional convience method, which allow some simple time arithmetics.
+	 *
+	 * @author Martin Kaltenbrunner
+	 * @version 1.4
+	 */ 
+	class TuioTime {
+		
+	private:
+		long seconds, micro_seconds;
+		static long start_seconds, start_micro_seconds;
+		
+	public:
+
+		/**
+		 * The default constructor takes no arguments and sets   
+		 * the Seconds and Microseconds attributes of the newly created TuioTime both to zero.
+		 */
+		TuioTime () {
+			seconds = 0;
+			micro_seconds = 0;
+		};
+
+		/**
+		 * The destructor is doing nothing in particular. 
+		 */
+		~TuioTime() {}
+		
+		/**
+		 * This constructor takes the provided time represented in total Milliseconds 
+		 * and assigs this value to the newly created TuioTime.
+		 *
+		 * @param  msec  the total time in Millseconds
+		 */
+		TuioTime (long msec) {
+			seconds = msec/MSEC_SECOND;
+			micro_seconds = USEC_MILLISECOND*(msec%MSEC_SECOND);
+		};
+		
+		/**
+		 * This constructor takes the provided time represented in Seconds and Microseconds   
+		 * and assigs these value to the newly created TuioTime.
+		 *
+		 * @param  sec  the total time in seconds
+		 * @param  usec	the microseconds time component
+		 */	
+		TuioTime (long sec, long usec) {
+			seconds = sec;
+			micro_seconds = usec;
+		};
+
+		/**
+		 * Sums the provided time value represented in total Microseconds to this TuioTime.
+		 *
+		 * @param  us	the total time to add in Microseconds
+		 * @return the sum of this TuioTime with the provided argument in microseconds
+		 */	
+		TuioTime operator+(long us) {
+			long sec = seconds + us/USEC_SECOND;
+			long usec = micro_seconds + us%USEC_SECOND;
+			return TuioTime(sec,usec);
+		};
+		
+		/**
+		 * Sums the provided TuioTime to the private Seconds and Microseconds attributes.  
+		 *
+		 * @param  ttime	the TuioTime to add
+		 * @return the sum of this TuioTime with the provided TuioTime argument
+		 */
+		TuioTime operator+(TuioTime ttime) {
+			long sec = seconds + ttime.getSeconds();
+			long usec = micro_seconds + ttime.getMicroseconds();
+			sec += usec/USEC_SECOND;
+			usec = usec%USEC_SECOND;
+			return TuioTime(sec,usec);
+		};
+
+		/**
+		 * Subtracts the provided time represented in Microseconds from the private Seconds and Microseconds attributes.
+		 *
+		 * @param  us	the total time to subtract in Microseconds
+		 * @return the subtraction result of this TuioTime minus the provided time in Microseconds
+		 */		
+		TuioTime operator-(long us) {
+			long sec = seconds - us/USEC_SECOND;
+			long usec = micro_seconds - us%USEC_SECOND;
+			
+			if (usec<0) {
+				usec += USEC_SECOND;
+				sec--;
+			}			
+			
+			return TuioTime(sec,usec);
+		};
+
+		/**
+		 * Subtracts the provided TuioTime from the private Seconds and Microseconds attributes.
+		 *
+		 * @param  ttime	the TuioTime to subtract
+		 * @return the subtraction result of this TuioTime minus the provided TuioTime
+		 */	
+		TuioTime operator-(TuioTime ttime) {
+			long sec = seconds - ttime.getSeconds();
+			long usec = micro_seconds - ttime.getMicroseconds();
+			
+			if (usec<0) {
+				usec += USEC_SECOND;
+				sec--;
+			}
+			
+			return TuioTime(sec,usec);
+		};
+
+		
+		/**
+		 * Assigns the provided TuioTime to the private Seconds and Microseconds attributes.
+		 *
+		 * @param  ttime	the TuioTime to assign
+		 */	
+		void operator=(TuioTime ttime) {
+			seconds = ttime.getSeconds();
+			micro_seconds = ttime.getMicroseconds();
+		};
+		
+		/**
+		 * Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
+		 *
+		 * @param  ttime	the TuioTime to compare
+		 * @return true if the two TuioTime have equal Seconds and Microseconds attributes
+		 */	
+		bool operator==(TuioTime ttime) {
+			if ((seconds==(long)ttime.getSeconds()) && (micro_seconds==(long)ttime.getMicroseconds())) return true;
+			else return false;
+		};
+
+		/**
+		 * Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
+		 *
+		 * @param  ttime	the TuioTime to compare
+		 * @return true if the two TuioTime have differnt Seconds or Microseconds attributes
+		 */	
+		bool operator!=(TuioTime ttime) {
+			if ((seconds!=(long)ttime.getSeconds()) || (micro_seconds!=(long)ttime.getMicroseconds())) return true;
+			else return false;
+		};
+		
+		/**
+		 * Resets the seconds and micro_seconds attributes to zero.
+		 */
+		void reset() {
+			seconds = 0;
+			micro_seconds = 0;
+		};
+		
+		/**
+		 * Returns the TuioTime Seconds component.
+		 * @return the TuioTime Seconds component
+		 */	
+		long getSeconds() {
+			return seconds;
+		};
+		
+		/**
+		 * Returns the TuioTime Microseconds component.
+		 * @return the TuioTime Microseconds component
+		 */	
+		long getMicroseconds() {
+			return micro_seconds;
+		};
+		
+		/**
+		 * Returns the total TuioTime in Milliseconds.
+		 * @return the total TuioTime in Milliseconds
+		 */	
+		long getTotalMilliseconds() {
+			return seconds*MSEC_SECOND+micro_seconds/MSEC_SECOND;
+		};
+		
+		/**
+		 * This static method globally resets the TUIO session time.
+		 */		
+		static void initSession();
+		
+		/**
+		 * Returns the present TuioTime representing the time since session start.
+		 * @return the present TuioTime representing the time since session start
+		 */			
+		static TuioTime getSessionTime();
+		
+		/**
+		 * Returns the absolut TuioTime representing the session start.
+		 * @return the absolut TuioTime representing the session start
+		 */			
+		static TuioTime getStartTime();
+		
+		/**
+		 * Returns the absolut TuioTime representing the current system time.
+		 * @return the absolut TuioTime representing the current system time
+		 */	
+		static TuioTime getSystemTime();
+	};
+};
+#endif /* INCLUDED_TUIOTIME_H */

+ 74 - 0
Modules/Contents/TUIO/Include/ip/IpEndpointName.h

@@ -0,0 +1,74 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_IPENDPOINTNAME_H
+#define INCLUDED_IPENDPOINTNAME_H
+
+
+class IpEndpointName{
+    static unsigned long GetHostByName( const char *s );
+public:
+    static const unsigned long ANY_ADDRESS = 0xFFFFFFFF;
+    static const int ANY_PORT = -1;
+
+    IpEndpointName()
+		: address( ANY_ADDRESS ), port( ANY_PORT ) {}
+    IpEndpointName( int port_ ) 
+		: address( ANY_ADDRESS ), port( port_ ) {}
+    IpEndpointName( unsigned long ipAddress_, int port_ ) 
+		: address( ipAddress_ ), port( port_ ) {}
+    IpEndpointName( const char *addressName, int port_=ANY_PORT )
+		: address( GetHostByName( addressName ) )
+		, port( port_ ) {}
+    IpEndpointName( int addressA, int addressB, int addressC, int addressD, int port_=ANY_PORT )
+		: address( ( (addressA << 24) | (addressB << 16) | (addressC << 8) | addressD ) )
+		, port( port_ ) {}
+
+	// address and port are maintained in host byte order here
+    unsigned long address;
+    int port;
+
+	enum { ADDRESS_STRING_LENGTH=17 };
+	void AddressAsString( char *s ) const;
+
+	enum { ADDRESS_AND_PORT_STRING_LENGTH=23};
+	void AddressAndPortAsString( char *s ) const;
+};
+
+inline bool operator==( const IpEndpointName& lhs, const IpEndpointName& rhs )
+{	
+	return (lhs.address == rhs.address && lhs.port == rhs.port );
+}
+
+inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs )
+{
+	return !(lhs == rhs);
+}
+
+#endif /* INCLUDED_IPENDPOINTNAME_H */

+ 49 - 0
Modules/Contents/TUIO/Include/ip/NetworkingUtils.h

@@ -0,0 +1,49 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_NETWORKINGUTILS_H
+#define INCLUDED_NETWORKINGUTILS_H
+
+
+// in general NetworkInitializer is only used internally, but if you're 
+// application creates multiple sockets from different threads at runtime you
+// should instantiate one of these in main just to make sure the networking
+// layer is initialized.
+class NetworkInitializer{
+public:
+    NetworkInitializer();
+    ~NetworkInitializer();
+};
+
+
+// return ip address of host name in host byte order
+unsigned long GetHostByName( const char *name );
+
+
+#endif /* INCLUDED_NETWORKINGUTILS_H */

+ 43 - 0
Modules/Contents/TUIO/Include/ip/PacketListener.h

@@ -0,0 +1,43 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_PACKETLISTENER_H
+#define INCLUDED_PACKETLISTENER_H
+
+
+class IpEndpointName;
+
+class PacketListener{
+public:
+    virtual ~PacketListener() {}
+    virtual void ProcessPacket( const char *data, int size, 
+			const IpEndpointName& remoteEndpoint ) = 0;
+};
+
+#endif /* INCLUDED_PACKETLISTENER_H */

+ 40 - 0
Modules/Contents/TUIO/Include/ip/TimerListener.h

@@ -0,0 +1,40 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_TIMERLISTENER_H
+#define INCLUDED_TIMERLISTENER_H
+
+
+class TimerListener{
+public:
+    virtual ~TimerListener() {}
+    virtual void TimerExpired() = 0;
+};
+
+#endif /* INCLUDED_TIMERLISTENER_H */

+ 158 - 0
Modules/Contents/TUIO/Include/ip/UdpSocket.h

@@ -0,0 +1,158 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_UDPSOCKET_H
+#define INCLUDED_UDPSOCKET_H
+
+#ifndef INCLUDED_NETWORKINGUTILITIES_H
+#include "NetworkingUtils.h"
+#endif /* INCLUDED_NETWORKINGUTILITIES_H */
+
+#ifndef INCLUDED_IPENDPOINTNAME_H
+#include "IpEndpointName.h"
+#endif /* INCLUDED_IPENDPOINTNAME_H */
+
+
+class PacketListener;
+class TimerListener;
+
+class UdpSocket;
+
+class SocketReceiveMultiplexer{
+    class Implementation;
+    Implementation *impl_;
+
+	friend class UdpSocket;
+
+public:
+    SocketReceiveMultiplexer();
+    ~SocketReceiveMultiplexer();
+
+	// only call the attach/detach methods _before_ calling Run
+
+    // only one listener per socket, each socket at most once
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener );
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener );
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener );
+	void AttachPeriodicTimerListener(
+            int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener );
+    void DetachPeriodicTimerListener( TimerListener *listener );  
+
+    void Run();      // loop and block processing messages indefinitely
+	void RunUntilSigInt();
+    void Break();    // call this from a listener to exit once the listener returns
+    void AsynchronousBreak(); // call this from another thread or signal handler to exit the Run() state
+};
+
+
+class UdpSocket{
+    class Implementation;
+    Implementation *impl_;
+    
+	friend class SocketReceiveMultiplexer::Implementation;
+    
+public:
+
+	// ctor throws std::runtime_error if there's a problem
+	// initializing the socket.
+	UdpSocket();
+	virtual ~UdpSocket();
+
+	// the socket is created in an unbound, unconnected state
+	// such a socket can only be used to send to an arbitrary
+	// address using SendTo(). To use Send() you need to first
+	// connect to a remote endpoint using Connect(). To use
+	// ReceiveFrom you need to first bind to a local endpoint
+	// using Bind().
+
+	// retrieve the local endpoint name when sending to 'to'
+    IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const;
+
+	// Connect to a remote endpoint which is used as the target
+	// for calls to Send()
+	void Connect( const IpEndpointName& remoteEndpoint );	
+	void Send( const char *data, int size );
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size );
+
+
+	// Bind a local endpoint to receive incoming data. Endpoint
+	// can be 'any' for the system to choose an endpoint
+	void Bind( const IpEndpointName& localEndpoint );
+	bool IsBound() const;
+
+	int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size );
+};
+
+
+// convenience classes for transmitting and receiving
+// they just call Connect and/or Bind in the ctor.
+// note that you can still use a receive socket
+// for transmitting etc
+
+class UdpTransmitSocket : public UdpSocket{
+public:
+	UdpTransmitSocket( const IpEndpointName& remoteEndpoint )
+		{ Connect( remoteEndpoint ); }
+};
+
+
+class UdpReceiveSocket : public UdpSocket{
+public:
+	UdpReceiveSocket( const IpEndpointName& localEndpoint )
+		{ Bind( localEndpoint ); }
+};
+
+
+// UdpListeningReceiveSocket provides a simple way to bind one listener
+// to a single socket without having to manually set up a SocketReceiveMultiplexer
+
+class UdpListeningReceiveSocket : public UdpSocket{
+    SocketReceiveMultiplexer mux_;
+    PacketListener *listener_;
+public:
+	UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener )
+        : listener_( listener )
+    {
+        Bind( localEndpoint );
+        mux_.AttachSocketListener( this, listener_ );
+    }
+
+    ~UdpListeningReceiveSocket()
+        { mux_.DetachSocketListener( this, listener_ ); }
+
+    // see SocketReceiveMultiplexer above for the behaviour of these methods...
+    void Run() { mux_.Run(); }
+	void RunUntilSigInt() { mux_.RunUntilSigInt(); }
+    void Break() { mux_.Break(); }
+    void AsynchronousBreak() { mux_.AsynchronousBreak(); }
+};
+
+
+#endif /* INCLUDED_UDPSOCKET_H */

+ 73 - 0
Modules/Contents/TUIO/Include/osc/MessageMappingOscPacketListener.h

@@ -0,0 +1,73 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
+#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
+
+#include <string.h>
+#include <map>
+
+#include "OscPacketListener.h"
+
+
+
+namespace osc{
+
+template< class T >
+class MessageMappingOscPacketListener : public OscPacketListener{
+public:
+    typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&);
+
+protected:
+    void RegisterMessageFunction( const char *addressPattern, function_type f )
+    {
+        functions_.insert( std::make_pair( addressPattern, f ) );
+    }
+
+    virtual void ProcessMessage( const osc::ReceivedMessage& m,
+		const IpEndpointName& remoteEndpoint )
+    {
+        typename function_map_type::iterator i = functions_.find( m.AddressPattern() );
+        if( i != functions_.end() )
+            (dynamic_cast<T*>(this)->*(i->second))( m, remoteEndpoint );
+    }
+    
+private:
+    struct cstr_compare{
+        bool operator()( const char *lhs, const char *rhs ) const
+            { return strcmp( lhs, rhs ) < 0; }
+    };
+
+    typedef std::map<const char*, function_type, cstr_compare> function_map_type;
+    function_map_type functions_;
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */

+ 54 - 0
Modules/Contents/TUIO/Include/osc/OscException.h

@@ -0,0 +1,54 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSC_EXCEPTION_H
+#define INCLUDED_OSC_EXCEPTION_H
+
+#include <exception>
+
+namespace osc{
+
+class Exception : public std::exception {
+    const char *what_;
+    
+public:
+    Exception() throw() {}
+    Exception( const Exception& src ) throw()
+        : what_( src.what_ ) {}
+    Exception( const char *w ) throw()
+        : what_( w ) {}
+    Exception& operator=( const Exception& src ) throw()
+        { what_ = src.what_; return *this; }
+    virtual ~Exception() throw() {}
+    virtual const char* what() const throw() { return what_; }
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSC_EXCEPTION_H */

+ 69 - 0
Modules/Contents/TUIO/Include/osc/OscHostEndianness.h

@@ -0,0 +1,69 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef OSC_HOSTENDIANNESS_H
+#define OSC_HOSTENDIANNESS_H
+
+/*
+    Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined
+
+    If you know a way to enhance the detection below for Linux and/or MacOSX
+    please let me know! I've tried a few things which don't work.
+*/
+
+#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)
+
+// you can define one of the above symbols from the command line
+// then you don't have to edit this file.
+
+#elif defined(__WIN32__) || defined(WIN32)
+
+// assume that __WIN32__ is only defined on little endian systems
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif defined(__APPLE__)
+
+#if defined(__LITTLE_ENDIAN__)
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+#else
+#define OSC_HOST_BIG_ENDIAN 1
+#undef OSC_HOST_LITTLE_ENDIAN
+#endif
+
+#else
+
+#error please edit OSCHostEndianness.h to configure endianness
+
+#endif
+
+#endif /* OSC_HOSTENDIANNESS_H */
+

+ 142 - 0
Modules/Contents/TUIO/Include/osc/OscOutboundPacketStream.h

@@ -0,0 +1,142 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSCOUTBOUNDPACKET_H
+#define INCLUDED_OSCOUTBOUNDPACKET_H
+
+#include "OscTypes.h"
+#include "OscException.h"
+
+
+namespace osc{
+
+class OutOfBufferMemoryException : public Exception{
+public:
+    OutOfBufferMemoryException( const char *w="out of buffer memory" )
+        : Exception( w ) {}
+};
+
+class BundleNotInProgressException : public Exception{
+public:
+    BundleNotInProgressException(
+            const char *w="call to EndBundle when bundle is not in progress" )
+        : Exception( w ) {}
+};
+
+class MessageInProgressException : public Exception{
+public:
+    MessageInProgressException(
+            const char *w="opening or closing bundle or message while message is in progress" )
+        : Exception( w ) {}
+};
+
+class MessageNotInProgressException : public Exception{
+public:
+    MessageNotInProgressException(
+            const char *w="call to EndMessage when message is not in progress" )
+        : Exception( w ) {}
+};
+
+
+class OutboundPacketStream{
+public:
+	OutboundPacketStream( char *buffer, unsigned long capacity );
+	~OutboundPacketStream();
+
+    void Clear();
+
+    unsigned int Capacity() const;
+
+    // invariant: size() is valid even while building a message.
+    unsigned int Size() const;
+
+    const char *Data() const;
+
+    // indicates that all messages have been closed with a matching EndMessage
+    // and all bundles have been closed with a matching EndBundle
+    bool IsReady() const;
+
+    bool IsMessageInProgress() const;
+    bool IsBundleInProgress() const;
+
+    OutboundPacketStream& operator<<( const BundleInitiator& rhs );
+    OutboundPacketStream& operator<<( const BundleTerminator& rhs );
+    
+    OutboundPacketStream& operator<<( const BeginMessage& rhs );
+    OutboundPacketStream& operator<<( const MessageTerminator& rhs );
+
+    OutboundPacketStream& operator<<( bool rhs );
+    OutboundPacketStream& operator<<( const NilType& rhs );
+    OutboundPacketStream& operator<<( const InfinitumType& rhs );
+    OutboundPacketStream& operator<<( int32 rhs );
+
+#ifndef __x86_64__
+    OutboundPacketStream& operator<<( int rhs )
+            { *this << (int32)rhs; return *this; }
+#endif
+
+    OutboundPacketStream& operator<<( float rhs );
+    OutboundPacketStream& operator<<( char rhs );
+    OutboundPacketStream& operator<<( const RgbaColor& rhs );
+    OutboundPacketStream& operator<<( const MidiMessage& rhs );
+    OutboundPacketStream& operator<<( int64 rhs );
+    OutboundPacketStream& operator<<( const TimeTag& rhs );
+    OutboundPacketStream& operator<<( double rhs );
+    OutboundPacketStream& operator<<( const char* rhs );
+    OutboundPacketStream& operator<<( const Symbol& rhs );
+    OutboundPacketStream& operator<<( const Blob& rhs );
+
+private:
+
+    char *BeginElement( char *beginPtr );
+    void EndElement( char *endPtr );
+
+    bool ElementSizeSlotRequired() const;
+    void CheckForAvailableBundleSpace();
+    void CheckForAvailableMessageSpace( const char *addressPattern );
+    void CheckForAvailableArgumentSpace( long argumentLength );
+
+    char *data_;
+    char *end_;
+
+    char *typeTagsCurrent_; // stored in reverse order
+    char *messageCursor_;
+    char *argumentCurrent_;
+
+    // elementSizePtr_ has two special values: 0 indicates that a bundle
+    // isn't open, and elementSizePtr_==data_ indicates that a bundle is
+    // open but that it doesn't have a size slot (ie the outermost bundle)
+    uint32 *elementSizePtr_;
+
+    bool messageIsInProgress_;
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */

+ 72 - 0
Modules/Contents/TUIO/Include/osc/OscPacketListener.h

@@ -0,0 +1,72 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSCPACKETLISTENER_H
+#define INCLUDED_OSCPACKETLISTENER_H
+
+#include "OscReceivedElements.h"
+#include "../ip/PacketListener.h"
+
+
+namespace osc{
+
+class OscPacketListener : public PacketListener{ 
+protected:
+    virtual void ProcessBundle( const osc::ReceivedBundle& b, 
+				const IpEndpointName& remoteEndpoint )
+    {
+        // ignore bundle time tag for now
+
+        for( ReceivedBundle::const_iterator i = b.ElementsBegin(); 
+				i != b.ElementsEnd(); ++i ){
+            if( i->IsBundle() )
+                ProcessBundle( ReceivedBundle(*i), remoteEndpoint );
+            else
+                ProcessMessage( ReceivedMessage(*i), remoteEndpoint );
+        }
+    }
+
+    virtual void ProcessMessage( const osc::ReceivedMessage& m, 
+				const IpEndpointName& remoteEndpoint ) = 0;
+    
+public:
+	virtual void ProcessPacket( const char *data, int size, 
+			const IpEndpointName& remoteEndpoint )
+    {
+        osc::ReceivedPacket p( data, size );
+        if( p.IsBundle() )
+            ProcessBundle( ReceivedBundle(p), remoteEndpoint );
+        else
+            ProcessMessage( ReceivedMessage(p), remoteEndpoint );
+    }
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACKETLISTENER_H */

+ 50 - 0
Modules/Contents/TUIO/Include/osc/OscPrintReceivedElements.h

@@ -0,0 +1,50 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSCPRINTRECEIVEDELEMENTS_H
+#define INCLUDED_OSCPRINTRECEIVEDELEMENTS_H
+
+#include <iosfwd>
+#include <string.h>
+
+#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
+#include "OscReceivedElements.h"
+#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */
+
+
+namespace osc{
+
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p );
+std::ostream& operator<<( std::ostream & os, const ReceivedMessageArgument& arg );
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m );
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b );
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */

+ 486 - 0
Modules/Contents/TUIO/Include/osc/OscReceivedElements.h

@@ -0,0 +1,486 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
+#define INCLUDED_OSCRECEIVEDELEMENTS_H
+
+#include "OscTypes.h"
+#include "OscException.h"
+
+
+namespace osc{
+
+
+class MalformedMessageException : public Exception{
+public:
+    MalformedMessageException( const char *w="malformed message" )
+        : Exception( w ) {}
+};
+
+class MalformedBundleException : public Exception{
+public:
+    MalformedBundleException( const char *w="malformed bundle" )
+        : Exception( w ) {}
+};
+
+class WrongArgumentTypeException : public Exception{
+public:
+    WrongArgumentTypeException( const char *w="wrong argument type" )
+        : Exception( w ) {}
+};
+
+class MissingArgumentException : public Exception{
+public:
+    MissingArgumentException( const char *w="missing argument" )
+        : Exception( w ) {}
+};
+
+class ExcessArgumentException : public Exception{
+public:
+    ExcessArgumentException( const char *w="too many arguments" )
+        : Exception( w ) {}
+};
+
+
+class ReceivedPacket{
+public:
+    ReceivedPacket( const char *contents, int32 size )
+        : contents_( contents )
+        , size_( size ) {}
+
+    bool IsMessage() const { return !IsBundle(); }
+    bool IsBundle() const;
+
+    int32 Size() const { return size_; }
+    const char *Contents() const { return contents_; }
+
+private:
+    const char *contents_;
+    int32 size_;
+};
+
+
+class ReceivedBundleElement{
+public:
+    ReceivedBundleElement( const char *size )
+        : size_( size ) {}
+
+    friend class ReceivedBundleElementIterator;
+
+    bool IsMessage() const { return !IsBundle(); }
+    bool IsBundle() const;
+
+    int32 Size() const;
+    const char *Contents() const { return size_ + 4; }
+
+private:
+    const char *size_;
+};
+
+
+class ReceivedBundleElementIterator{
+public:
+	ReceivedBundleElementIterator( const char *sizePtr )
+        : value_( sizePtr ) {}
+
+	ReceivedBundleElementIterator operator++()
+	{
+        Advance();
+        return *this;
+	}
+
+    ReceivedBundleElementIterator operator++(int)
+    {
+        ReceivedBundleElementIterator old( *this );
+        Advance();
+        return old;
+    }
+
+	const ReceivedBundleElement& operator*() const { return value_; }
+
+    const ReceivedBundleElement* operator->() const { return &value_; }
+
+	friend bool operator==(const ReceivedBundleElementIterator& lhs,
+            const ReceivedBundleElementIterator& rhs );
+
+private:
+	ReceivedBundleElement value_;
+
+	void Advance() { value_.size_ = value_.Contents() + value_.Size(); }
+
+    bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
+    {
+        return value_.size_ == rhs.value_.size_;
+    }
+};
+
+inline bool operator==(const ReceivedBundleElementIterator& lhs,
+        const ReceivedBundleElementIterator& rhs )
+{	
+	return lhs.IsEqualTo( rhs );
+}
+
+inline bool operator!=(const ReceivedBundleElementIterator& lhs,
+        const ReceivedBundleElementIterator& rhs )
+{
+	return !( lhs == rhs );
+}
+
+
+class ReceivedMessageArgument{
+public:
+	ReceivedMessageArgument( const char *typeTag, const char *argument )
+		: typeTag_( typeTag )
+		, argument_( argument ) {}
+
+    friend class ReceivedMessageArgumentIterator;
+    
+	const char TypeTag() const { return *typeTag_; }
+
+    // the unchecked methods below don't check whether the argument actually
+    // is of the specified type. they should only be used if you've already
+    // checked the type tag or the associated IsType() method.
+
+    bool IsBool() const
+        { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }
+    bool AsBool() const;
+    bool AsBoolUnchecked() const;
+
+    bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }
+    bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }
+
+    bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }
+    int32 AsInt32() const;
+    int32 AsInt32Unchecked() const;
+
+    bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }
+    float AsFloat() const;
+    float AsFloatUnchecked() const;
+
+    bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }
+    char AsChar() const;
+    char AsCharUnchecked() const;
+
+    bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }
+    uint32 AsRgbaColor() const;
+    uint32 AsRgbaColorUnchecked() const;
+
+    bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }
+    uint32 AsMidiMessage() const;
+    uint32 AsMidiMessageUnchecked() const;
+
+    bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }
+    int64 AsInt64() const;
+    int64 AsInt64Unchecked() const;
+
+    bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }
+    uint64 AsTimeTag() const;
+    uint64 AsTimeTagUnchecked() const;
+
+    bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }
+    double AsDouble() const;
+    double AsDoubleUnchecked() const;
+
+    bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; }
+    const char* AsString() const;
+    const char* AsStringUnchecked() const { return argument_; }
+
+    bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }
+    const char* AsSymbol() const;
+    const char* AsSymbolUnchecked() const { return argument_; }
+
+    bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; }
+    void AsBlob( const void*& data, unsigned long& size ) const;
+    void AsBlobUnchecked( const void*& data, unsigned long& size ) const;
+    
+private:
+	const char *typeTag_;
+	const char *argument_;
+};
+
+
+class ReceivedMessageArgumentIterator{
+public:
+	ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )
+        : value_( typeTags, arguments ) {}
+
+	ReceivedMessageArgumentIterator operator++()
+	{
+        Advance();
+        return *this;
+	}
+
+    ReceivedMessageArgumentIterator operator++(int)
+    {
+        ReceivedMessageArgumentIterator old( *this );
+        Advance();
+        return old;
+    }
+
+	const ReceivedMessageArgument& operator*() const { return value_; }
+
+    const ReceivedMessageArgument* operator->() const { return &value_; }
+
+	friend bool operator==(const ReceivedMessageArgumentIterator& lhs,
+            const ReceivedMessageArgumentIterator& rhs );
+
+private:
+	ReceivedMessageArgument value_;
+
+	void Advance();
+
+    bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
+    {
+        return value_.typeTag_ == rhs.value_.typeTag_;
+    }
+};
+
+inline bool operator==(const ReceivedMessageArgumentIterator& lhs,
+        const ReceivedMessageArgumentIterator& rhs )
+{	
+	return lhs.IsEqualTo( rhs );
+}
+
+inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,
+        const ReceivedMessageArgumentIterator& rhs )
+{	
+	return !( lhs == rhs );
+}
+
+
+class ReceivedMessageArgumentStream{
+    friend class ReceivedMessage;
+    ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
+            const ReceivedMessageArgumentIterator& end )
+        : p_( begin )
+        , end_( end ) {}
+
+    ReceivedMessageArgumentIterator p_, end_;
+    
+public:
+
+    // end of stream
+    bool Eos() const { return p_ == end_; }
+
+    ReceivedMessageArgumentStream& operator>>( bool& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsBool();
+        return *this;
+    }
+
+    // not sure if it would be useful to stream Nil and Infinitum
+    // for now it's not possible
+
+    ReceivedMessageArgumentStream& operator>>( int32& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsInt32();
+        return *this;
+    }     
+
+    ReceivedMessageArgumentStream& operator>>( float& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsFloat();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( char& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsChar();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsRgbaColor();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsMidiMessage();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( int64& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsInt64();
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsTimeTag();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( double& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsDouble();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( Blob& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        (*p_++).AsBlob( rhs.data, rhs.size );
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( const char*& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsString();
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsSymbol();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
+    {
+        if( !Eos() )
+            throw ExcessArgumentException();
+
+        return *this;
+    }
+};
+
+
+class ReceivedMessage{
+    void Init( const char *bundle, unsigned long size );
+public:
+    explicit ReceivedMessage( const ReceivedPacket& packet );
+    explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
+
+	const char *AddressPattern() const { return addressPattern_; }
+
+	// Support for non-standad SuperCollider integer address patterns:
+	bool AddressPatternIsUInt32() const;
+	uint32 AddressPatternAsUInt32() const;
+
+	unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }
+
+    const char *TypeTags() const { return typeTagsBegin_; }
+
+
+    typedef ReceivedMessageArgumentIterator const_iterator;
+    
+	ReceivedMessageArgumentIterator ArgumentsBegin() const
+    {
+        return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );
+    }
+     
+	ReceivedMessageArgumentIterator ArgumentsEnd() const
+    {
+        return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );
+    }
+
+    ReceivedMessageArgumentStream ArgumentStream() const
+    {
+        return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
+    }
+
+private:
+	const char *addressPattern_;
+	const char *typeTagsBegin_;
+	const char *typeTagsEnd_;
+    const char *arguments_;
+};
+
+
+class ReceivedBundle{
+    void Init( const char *message, unsigned long size );
+public:
+    explicit ReceivedBundle( const ReceivedPacket& packet );
+    explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
+
+    uint64 TimeTag() const;
+
+    unsigned long ElementCount() const { return elementCount_; }
+
+    typedef ReceivedBundleElementIterator const_iterator;
+    
+	ReceivedBundleElementIterator ElementsBegin() const
+    {
+        return ReceivedBundleElementIterator( timeTag_ + 8 );
+    }
+     
+	ReceivedBundleElementIterator ElementsEnd() const
+    {
+        return ReceivedBundleElementIterator( end_ );
+    }
+
+private:
+    const char *timeTag_;
+    const char *end_;
+    unsigned long elementCount_;
+};
+
+
+} // namespace osc
+
+
+#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */

+ 178 - 0
Modules/Contents/TUIO/Include/osc/OscTypes.h

@@ -0,0 +1,178 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_OSCTYPES_H
+#define INCLUDED_OSCTYPES_H
+
+
+namespace osc{
+
+// basic types
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+
+#else
+
+typedef long long int64;
+typedef unsigned long long uint64;
+
+#endif
+
+
+
+#ifdef __x86_64__
+
+typedef signed int int32;
+typedef unsigned int uint32;
+
+#else
+
+typedef signed long int32;
+typedef unsigned long uint32;
+
+#endif
+
+
+
+enum TypeTagValues {
+    TRUE_TYPE_TAG = 'T',
+    FALSE_TYPE_TAG = 'F',
+    NIL_TYPE_TAG = 'N',
+    INFINITUM_TYPE_TAG = 'I',
+    INT32_TYPE_TAG = 'i',
+    FLOAT_TYPE_TAG = 'f',
+    CHAR_TYPE_TAG = 'c',
+    RGBA_COLOR_TYPE_TAG = 'r',
+    MIDI_MESSAGE_TYPE_TAG = 'm',
+    INT64_TYPE_TAG = 'h',
+    TIME_TAG_TYPE_TAG = 't',
+    DOUBLE_TYPE_TAG = 'd',
+    STRING_TYPE_TAG = 's',
+    SYMBOL_TYPE_TAG = 'S',
+    BLOB_TYPE_TAG = 'b'
+};
+
+
+
+// i/o manipulators used for streaming interfaces
+
+struct BundleInitiator{
+    explicit BundleInitiator( uint64 timeTag_ ) : timeTag( timeTag_ ) {}
+    uint64 timeTag;
+};
+
+extern BundleInitiator BeginBundleImmediate;
+
+inline BundleInitiator BeginBundle( uint64 timeTag=1 )
+{
+    return BundleInitiator(timeTag);
+}
+
+
+struct BundleTerminator{
+};
+
+extern BundleTerminator EndBundle;
+
+struct BeginMessage{
+    explicit BeginMessage( const char *addressPattern_ ) : addressPattern( addressPattern_ ) {}
+    const char *addressPattern;
+};
+
+struct MessageTerminator{
+};
+
+extern MessageTerminator EndMessage;
+
+
+// osc specific types. they are defined as structs so they can be used
+// as separately identifiable types with the streaming operators.
+
+struct NilType{
+};
+
+//extern NilType Nil;
+
+	
+struct InfinitumType{
+};
+
+extern InfinitumType Infinitum;
+
+struct RgbaColor{
+    RgbaColor() {}
+    explicit RgbaColor( uint32 value_ ) : value( value_ ) {}
+    uint32 value;
+
+    operator uint32() const { return value; }
+};
+
+
+struct MidiMessage{
+    MidiMessage() {}
+    explicit MidiMessage( uint32 value_ ) : value( value_ ) {}
+    uint32 value;
+
+    operator uint32() const { return value; }
+};
+
+
+struct TimeTag{
+    TimeTag() {}
+    explicit TimeTag( uint64 value_ ) : value( value_ ) {}
+    uint64 value;
+
+    operator uint64() const { return value; }
+};
+
+
+struct Symbol{
+    Symbol() {}
+    explicit Symbol( const char* value_ ) : value( value_ ) {}
+    const char* value;
+
+    operator const char *() const { return value; }
+};
+
+
+struct Blob{
+    Blob() {}
+    explicit Blob( const void* data_, unsigned long size_ )
+            : data( data_ ), size( size_ ) {}
+    const void* data;
+    unsigned long size;
+};
+
+} // namespace osc
+
+
+#endif /* INCLUDED_OSCTYPES_H */

+ 28 - 0
Modules/Contents/TUIO/OSCPACK_LICENSE.txt

@@ -0,0 +1,28 @@
+oscpack -- Open Sound Control packet manipulation library
+http://www.audiomulch.com/~rossb/code/oscpack
+
+Copyright (c) 2004 Ross Bencina <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+Any person wishing to distribute modifications to the Software is
+requested to send the modifications to the original developer so that
+they can be incorporated into the canonical version.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+

+ 81 - 0
Modules/Contents/TUIO/Source/IpEndpointName.cpp

@@ -0,0 +1,81 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "IpEndpointName.h"
+
+#include <stdio.h>
+
+#include "NetworkingUtils.h"
+
+
+unsigned long IpEndpointName::GetHostByName( const char *s )
+{
+	return ::GetHostByName(s);
+}
+
+
+void IpEndpointName::AddressAsString( char *s ) const
+{
+	if( address == ANY_ADDRESS ){
+		sprintf( s, "<any>" );
+	}else{
+		sprintf( s, "%d.%d.%d.%d",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF) );
+	}
+}
+
+
+void IpEndpointName::AddressAndPortAsString( char *s ) const
+{
+	if( port == ANY_PORT ){
+		if( address == ANY_ADDRESS ){
+			sprintf( s, "<any>:<any>" );
+		}else{
+			sprintf( s, "%d.%d.%d.%d:<any>",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF) );
+		}
+	}else{
+		if( address == ANY_ADDRESS ){
+			sprintf( s, "<any>:%d", port );
+		}else{
+			sprintf( s, "%d.%d.%d.%d:%d",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF),
+				(int)port );
+		}
+	}	
+}

+ 639 - 0
Modules/Contents/TUIO/Source/OscOutboundPacketStream.cpp

@@ -0,0 +1,639 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscOutboundPacketStream.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if defined(__WIN32__) || defined(WIN32)
+#include <malloc.h> // for alloca
+#endif
+
+#include "OscHostEndianness.h"
+
+
+namespace osc{
+
+static void FromInt32( char *p, int32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.i = x;
+
+    p[3] = u.c[0];
+    p[2] = u.c[1];
+    p[1] = u.c[2];
+    p[0] = u.c[3];
+#else
+    *reinterpret_cast<int32*>(p) = x;
+#endif
+}
+
+
+static void FromUInt32( char *p, uint32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint32 i;
+        char c[4];
+    } u;
+
+    u.i = x;
+
+    p[3] = u.c[0];
+    p[2] = u.c[1];
+    p[1] = u.c[2];
+    p[0] = u.c[3];
+#else
+    *reinterpret_cast<uint32*>(p) = x;
+#endif
+}
+
+
+static void FromInt64( char *p, int64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int64 i;
+        char c[8];
+    } u;
+
+    u.i = x;
+
+    p[7] = u.c[0];
+    p[6] = u.c[1];
+    p[5] = u.c[2];
+    p[4] = u.c[3];
+    p[3] = u.c[4];
+    p[2] = u.c[5];
+    p[1] = u.c[6];
+    p[0] = u.c[7];
+#else
+    *reinterpret_cast<int64*>(p) = x;
+#endif
+}
+
+
+static void FromUInt64( char *p, uint64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint64 i;
+        char c[8];
+    } u;
+
+    u.i = x;
+
+    p[7] = u.c[0];
+    p[6] = u.c[1];
+    p[5] = u.c[2];
+    p[4] = u.c[3];
+    p[3] = u.c[4];
+    p[2] = u.c[5];
+    p[1] = u.c[6];
+    p[0] = u.c[7];
+#else
+    *reinterpret_cast<uint64*>(p) = x;
+#endif
+}
+
+
+static inline long RoundUp4( long x )
+{
+    return ((x-1) & (~0x03L)) + 4;
+}
+
+
+OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity )
+    : data_( buffer )
+    , end_( data_ + capacity )
+    , typeTagsCurrent_( end_ )
+    , messageCursor_( data_ )
+    , argumentCurrent_( data_ )
+    , elementSizePtr_( 0 )
+    , messageIsInProgress_( false )
+{
+
+}
+
+
+OutboundPacketStream::~OutboundPacketStream()
+{
+
+}
+
+
+char *OutboundPacketStream::BeginElement( char *beginPtr )
+{
+    if( elementSizePtr_ == 0 ){
+
+        elementSizePtr_ = reinterpret_cast<uint32*>(data_);
+
+        return beginPtr;
+
+    }else{
+        // store an offset to the old element size ptr in the element size slot
+        // we store an offset rather than the actual pointer to be 64 bit clean.
+        *reinterpret_cast<uint32*>(beginPtr) =
+                (uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_);
+
+        elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr);
+
+        return beginPtr + 4;
+    }
+}
+
+
+void OutboundPacketStream::EndElement( char *endPtr )
+{
+    assert( elementSizePtr_ != 0 );
+
+    if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){
+
+        elementSizePtr_ = 0;
+
+    }else{
+        // while building an element, an offset to the containing element's
+        // size slot is stored in the elements size slot (or a ptr to data_
+        // if there is no containing element). We retrieve that here
+        uint32 *previousElementSizePtr =
+                (uint32*)(data_ + *reinterpret_cast<uint32*>(elementSizePtr_));
+
+        // then we store the element size in the slot, note that the element
+        // size does not include the size slot, hence the - 4 below.
+        uint32 elementSize =
+                (endPtr - reinterpret_cast<char*>(elementSizePtr_)) - 4;
+        FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );
+
+        // finally, we reset the element size ptr to the containing element
+        elementSizePtr_ = previousElementSizePtr;
+    }
+}
+
+
+bool OutboundPacketStream::ElementSizeSlotRequired() const
+{
+    return (elementSizePtr_ != 0);
+}
+
+
+void OutboundPacketStream::CheckForAvailableBundleSpace()
+{
+    unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
+{
+    // plus 4 for at least four bytes of type tag
+     unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0)
+            + RoundUp4(strlen(addressPattern) + 1) + 4;
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength )
+{
+    // plus three for extra type tag, comma and null terminator
+     unsigned long required = (argumentCurrent_ - data_) + argumentLength
+            + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::Clear()
+{
+    typeTagsCurrent_ = end_;
+    messageCursor_ = data_;
+    argumentCurrent_ = data_;
+    elementSizePtr_ = 0;
+    messageIsInProgress_ = false;
+}
+
+
+unsigned int OutboundPacketStream::Capacity() const
+{
+    return end_ - data_;
+}
+
+
+unsigned int OutboundPacketStream::Size() const
+{
+    unsigned int result = argumentCurrent_ - data_;
+    if( IsMessageInProgress() ){
+        // account for the length of the type tag string. the total type tag
+        // includes an initial comma, plus at least one terminating \0
+        result += RoundUp4( (end_ - typeTagsCurrent_) + 2 );
+    }
+
+    return result;
+}
+
+
+const char *OutboundPacketStream::Data() const
+{
+    return data_;
+}
+
+
+bool OutboundPacketStream::IsReady() const
+{
+    return (!IsMessageInProgress() && !IsBundleInProgress());
+}
+
+
+bool OutboundPacketStream::IsMessageInProgress() const
+{
+    return messageIsInProgress_;
+}
+
+
+bool OutboundPacketStream::IsBundleInProgress() const
+{
+    return (elementSizePtr_ != 0);
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
+{
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    CheckForAvailableBundleSpace();
+
+    messageCursor_ = BeginElement( messageCursor_ );
+
+    memcpy( messageCursor_, "#bundle\0", 8 );
+    FromUInt64( messageCursor_ + 8, rhs.timeTag );
+
+    messageCursor_ += 16;
+    argumentCurrent_ = messageCursor_;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
+{
+    (void) rhs;
+
+    if( !IsBundleInProgress() )
+        throw BundleNotInProgressException();
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    EndElement( messageCursor_ );
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
+{
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    CheckForAvailableMessageSpace( rhs.addressPattern );
+
+    messageCursor_ = BeginElement( messageCursor_ );
+
+    strcpy( messageCursor_, rhs.addressPattern );
+    unsigned long rhsLength = strlen(rhs.addressPattern);
+    messageCursor_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    unsigned long i = rhsLength + 1;
+    while( i & 0x3 ){
+        *messageCursor_++ = '\0';
+        ++i;
+    }
+
+    argumentCurrent_ = messageCursor_;
+    typeTagsCurrent_ = end_;
+
+    messageIsInProgress_ = true;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )
+{
+    (void) rhs;
+
+    if( !IsMessageInProgress() )
+        throw MessageNotInProgressException();
+
+    int typeTagsCount = end_ - typeTagsCurrent_;
+
+    if( typeTagsCount ){
+
+        char *tempTypeTags = (char*)alloca(typeTagsCount);
+        memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );
+
+        // slot size includes comma and null terminator
+        int typeTagSlotSize = RoundUp4( typeTagsCount + 2 );
+
+        uint32 argumentsSize = argumentCurrent_ - messageCursor_;
+
+        memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );
+
+        messageCursor_[0] = ',';
+        // copy type tags in reverse (really forward) order
+        for( int i=0; i < typeTagsCount; ++i )
+            messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];
+
+        char *p = messageCursor_ + 1 + typeTagsCount;
+        for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )
+            *p++ = '\0';
+
+        typeTagsCurrent_ = end_;
+
+        // advance messageCursor_ for next message
+        messageCursor_ += typeTagSlotSize + argumentsSize;
+
+    }else{
+        // send an empty type tags string
+        memcpy( messageCursor_, ",\0\0\0", 4 );
+
+        // advance messageCursor_ for next message
+        messageCursor_ += 4;
+    }
+
+    argumentCurrent_ = messageCursor_;
+
+    EndElement( messageCursor_ );
+
+    messageIsInProgress_ = false;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
+{
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = NIL_TYPE_TAG;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = INT32_TYPE_TAG;
+    FromInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        float f;
+        char c[4];
+    } u;
+
+    u.f = rhs;
+
+    argumentCurrent_[3] = u.c[0];
+    argumentCurrent_[2] = u.c[1];
+    argumentCurrent_[1] = u.c[2];
+    argumentCurrent_[0] = u.c[3];
+#else
+    *reinterpret_cast<float*>(argumentCurrent_) = rhs;
+#endif
+
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = CHAR_TYPE_TAG;
+    FromInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = INT64_TYPE_TAG;
+    FromInt64( argumentCurrent_, rhs );
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
+    FromUInt64( argumentCurrent_, rhs );
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        double f;
+        char c[8];
+    } u;
+
+    u.f = rhs;
+
+    argumentCurrent_[7] = u.c[0];
+    argumentCurrent_[6] = u.c[1];
+    argumentCurrent_[5] = u.c[2];
+    argumentCurrent_[4] = u.c[3];
+    argumentCurrent_[3] = u.c[4];
+    argumentCurrent_[2] = u.c[5];
+    argumentCurrent_[1] = u.c[6];
+    argumentCurrent_[0] = u.c[7];
+#else
+    *reinterpret_cast<double*>(argumentCurrent_) = rhs;
+#endif
+
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
+{
+    CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
+
+    *(--typeTagsCurrent_) = STRING_TYPE_TAG;
+    strcpy( argumentCurrent_, rhs );
+    unsigned long rhsLength = strlen(rhs);
+    argumentCurrent_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    unsigned long i = rhsLength + 1;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
+{
+    CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
+
+    *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;
+    strcpy( argumentCurrent_, rhs );
+    unsigned long rhsLength = strlen(rhs);
+    argumentCurrent_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    unsigned long i = rhsLength + 1;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
+{
+    CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
+
+    *(--typeTagsCurrent_) = BLOB_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs.size );
+    argumentCurrent_ += 4;
+    
+    memcpy( argumentCurrent_, rhs.data, rhs.size );
+    argumentCurrent_ += rhs.size;
+
+    // zero pad to 4-byte boundary
+    unsigned long i = rhs.size;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+} // namespace osc
+
+

+ 240 - 0
Modules/Contents/TUIO/Source/OscPrintReceivedElements.cpp

@@ -0,0 +1,240 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscPrintReceivedElements.h"
+
+#include <iostream>
+#include <iomanip>
+#include <ctime>
+
+
+namespace osc{
+
+
+std::ostream& operator<<( std::ostream & os,
+        const ReceivedMessageArgument& arg )
+{
+    switch( arg.TypeTag() ){
+        case TRUE_TYPE_TAG:
+            os << "bool:true";
+            break;
+                
+        case FALSE_TYPE_TAG:
+            os << "bool:false";
+            break;
+
+        case NIL_TYPE_TAG:
+            os << "(Nil)";
+            break;
+
+        case INFINITUM_TYPE_TAG:
+            os << "(Infinitum)";
+            break;
+
+        case INT32_TYPE_TAG:
+            os << "int32:" << arg.AsInt32Unchecked();
+            break;
+
+        case FLOAT_TYPE_TAG:
+            os << "float32:" << arg.AsFloatUnchecked();
+            break;
+
+        case CHAR_TYPE_TAG:
+            {
+                char s[2] = {0};
+                s[0] = arg.AsCharUnchecked();
+                os << "char:'" << s << "'";
+            }
+            break;
+
+        case RGBA_COLOR_TYPE_TAG:
+            {
+                uint32 color = arg.AsRgbaColorUnchecked();
+                
+                os << "RGBA:0x"
+                        << std::hex << std::setfill('0')
+                        << std::setw(2) << (int)((color>>24) & 0xFF)
+                        << std::setw(2) << (int)((color>>16) & 0xFF)
+                        << std::setw(2) << (int)((color>>8) & 0xFF)
+                        << std::setw(2) << (int)(color & 0xFF)
+                        << std::setfill(' ');
+                os.unsetf(std::ios::basefield);
+            }
+            break;
+
+        case MIDI_MESSAGE_TYPE_TAG:
+            {
+                uint32 m = arg.AsMidiMessageUnchecked();
+                os << "midi (port, status, data1, data2):<<"
+                        << std::hex << std::setfill('0')
+                        << "0x" << std::setw(2) << (int)((m>>24) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)((m>>16) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)((m>>8) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)(m & 0xFF)
+                        << std::setfill(' ') << ">>";
+                os.unsetf(std::ios::basefield);
+            }
+            break;
+				
+        case INT64_TYPE_TAG:
+            os << "int64:" << arg.AsInt64Unchecked();
+            break;
+
+        case TIME_TAG_TYPE_TAG:
+            {
+                os << "OSC-timetag:" << arg.AsTimeTagUnchecked();
+
+                std::time_t t =
+                        (unsigned long)( arg.AsTimeTagUnchecked() >> 32 );
+
+                // strip trailing newline from string returned by ctime
+                const char *timeString = std::ctime( &t );
+                size_t len = strlen( timeString );
+                char *s = new char[ len + 1 ];
+                strcpy( s, timeString );
+                if( len )
+                    s[ len - 1 ] = '\0';
+                    
+                os << " " << s;
+            }
+            break;
+                
+        case DOUBLE_TYPE_TAG:
+            os << "double:" << arg.AsDoubleUnchecked();
+            break;
+
+        case STRING_TYPE_TAG:
+            os << "OSC-string:`" << arg.AsStringUnchecked() << "'";
+            break;
+                
+        case SYMBOL_TYPE_TAG: 
+            os << "OSC-string (symbol):`" << arg.AsSymbolUnchecked() << "'";
+            break;
+
+        case BLOB_TYPE_TAG:
+            {
+                unsigned long size;
+                const void *data;
+                arg.AsBlobUnchecked( data, size );
+                os << "OSC-blob:<<" << std::hex << std::setfill('0');
+                unsigned char *p = (unsigned char*)data;
+                for( unsigned long i = 0; i < size; ++i ){
+                    os << "0x" << std::setw(2) << int(p[i]);
+                    if( i != size-1 )
+                        os << ' ';
+                }
+                os.unsetf(std::ios::basefield);
+                os << ">>" << std::setfill(' ');
+            }
+            break;
+
+        default:
+            os << "unknown";
+    }
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )
+{
+
+    os << "[" << m.AddressPattern();
+    bool first = true;
+
+    for( ReceivedMessage::const_iterator i = m.ArgumentsBegin();
+            i != m.ArgumentsEnd(); ++i ){
+        if( first ){
+            os << " ";
+            first = false;
+        }else{
+            os << ", ";
+        }
+
+        os << *i;
+    }
+
+    os << "]";
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b )
+{
+    static int indent = 0;
+
+    for( int j=0; j < indent; ++j )
+        os << "  ";
+    os << "{ ( ";
+    if( b.TimeTag() == 1 )
+        os << "immediate";
+    else
+        os << b.TimeTag();
+    os << " )\n";
+
+    ++indent;
+    
+    for( ReceivedBundle::const_iterator i = b.ElementsBegin();
+            i != b.ElementsEnd(); ++i ){
+        if( i->IsBundle() ){
+            ReceivedBundle b(*i);
+            os << b << "\n";
+        }else{
+            ReceivedMessage m(*i);
+            for( int j=0; j < indent; ++j )
+                os << "  ";
+            os << m << "\n";
+        }
+    }
+
+    --indent;
+
+    for( int j=0; j < indent; ++j )
+        os << "  ";
+    os << "}";
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p )
+{
+    if( p.IsBundle() ){
+        ReceivedBundle b(p);
+        os << b << "\n";
+    }else{
+        ReceivedMessage m(p);
+        os << m << "\n";
+    }
+
+    return os;
+}
+
+} // namespace osc

+ 722 - 0
Modules/Contents/TUIO/Source/OscReceivedElements.cpp

@@ -0,0 +1,722 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscReceivedElements.h"
+
+#include <cassert>
+
+#include "OscHostEndianness.h"
+
+
+namespace osc{
+
+
+// return the first 4 byte boundary after the end of a str4
+// be careful about calling this version if you don't know whether
+// the string is terminated correctly.
+static inline const char* FindStr4End( const char *p )
+{
+	if( p[0] == '\0' )    // special case for SuperCollider integer address pattern
+		return p + 4;
+
+    p += 3;
+
+    while( *p )
+        p += 4;
+
+    return p + 1;
+}
+
+
+// return the first 4 byte boundary after the end of a str4
+// returns 0 if p == end or if the string is unterminated
+static inline const char* FindStr4End( const char *p, const char *end )
+{
+    if( p >= end )
+        return 0;
+
+	if( p[0] == '\0' )    // special case for SuperCollider integer address pattern
+		return p + 4;
+
+    p += 3;
+    end -= 1;
+
+    while( p < end && *p )
+        p += 4;
+
+    if( *p )
+        return 0;
+    else
+        return p + 1;
+}
+
+
+static inline unsigned long RoundUp4( unsigned long x )
+{
+    unsigned long remainder = x & 0x3UL;
+    if( remainder )
+        return x + (4 - remainder);
+    else
+        return x;
+}
+
+
+static inline int32 ToInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = p[3];
+    u.c[1] = p[2];
+    u.c[2] = p[1];
+    u.c[3] = p[0];
+
+    return u.i;
+#else
+	return *(int32*)p;
+#endif
+}
+
+
+static inline uint32 ToUInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = p[3];
+    u.c[1] = p[2];
+    u.c[2] = p[1];
+    u.c[3] = p[0];
+
+    return u.i;
+#else
+	return *(uint32*)p;
+#endif
+}
+
+
+int64 ToInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int64 i;
+        char c[8];
+    } u;
+
+    u.c[0] = p[7];
+    u.c[1] = p[6];
+    u.c[2] = p[5];
+    u.c[3] = p[4];
+    u.c[4] = p[3];
+    u.c[5] = p[2];
+    u.c[6] = p[1];
+    u.c[7] = p[0];
+
+    return u.i;
+#else
+	return *(int64*)p;
+#endif
+}
+
+
+uint64 ToUInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint64 i;
+        char c[8];
+    } u;
+
+    u.c[0] = p[7];
+    u.c[1] = p[6];
+    u.c[2] = p[5];
+    u.c[3] = p[4];
+    u.c[4] = p[3];
+    u.c[5] = p[2];
+    u.c[6] = p[1];
+    u.c[7] = p[0];
+
+    return u.i;
+#else
+	return *(uint64*)p;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedPacket::IsBundle() const
+{
+    return (Size() > 0 && Contents()[0] == '#');
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedBundleElement::IsBundle() const
+{
+    return (Size() > 0 && Contents()[0] == '#');
+}
+
+
+int32 ReceivedBundleElement::Size() const
+{
+    return ToUInt32( size_ );
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedMessageArgument::AsBool() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == TRUE_TYPE_TAG )
+		return true;
+	else if( *typeTag_ == FALSE_TYPE_TAG )
+		return false;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+bool ReceivedMessageArgument::AsBoolUnchecked() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == TRUE_TYPE_TAG )
+		return true;
+    else
+	    return false;
+}
+
+
+int32 ReceivedMessageArgument::AsInt32() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == INT32_TYPE_TAG )
+		return AsInt32Unchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+int32 ReceivedMessageArgument::AsInt32Unchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = argument_[3];
+    u.c[1] = argument_[2];
+    u.c[2] = argument_[1];
+    u.c[3] = argument_[0];
+
+    return u.i;
+#else
+	return *(int32*)argument_;
+#endif
+}
+
+
+float ReceivedMessageArgument::AsFloat() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == FLOAT_TYPE_TAG )
+		return AsFloatUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+float ReceivedMessageArgument::AsFloatUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        float f;
+        char c[4];
+    } u;
+
+    u.c[0] = argument_[3];
+    u.c[1] = argument_[2];
+    u.c[2] = argument_[1];
+    u.c[3] = argument_[0];
+
+    return u.f;
+#else
+	return *(float*)argument_;
+#endif
+}
+
+
+char ReceivedMessageArgument::AsChar() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == CHAR_TYPE_TAG )
+		return AsCharUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+char ReceivedMessageArgument::AsCharUnchecked() const
+{
+    return (char)ToInt32( argument_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColor() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == RGBA_COLOR_TYPE_TAG )
+		return AsRgbaColorUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
+{
+	return ToUInt32( argument_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessage() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG )
+		return AsMidiMessageUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
+{
+	return ToUInt32( argument_ );
+}
+
+
+int64 ReceivedMessageArgument::AsInt64() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == INT64_TYPE_TAG )
+		return AsInt64Unchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+int64 ReceivedMessageArgument::AsInt64Unchecked() const
+{
+    return ToInt64( argument_ );
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTag() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == TIME_TAG_TYPE_TAG )
+		return AsTimeTagUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
+{
+    return ToUInt64( argument_ );
+}
+
+
+double ReceivedMessageArgument::AsDouble() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == DOUBLE_TYPE_TAG )
+		return AsDoubleUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+double ReceivedMessageArgument::AsDoubleUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        double d;
+        char c[8];
+    } u;
+
+    u.c[0] = argument_[7];
+    u.c[1] = argument_[6];
+    u.c[2] = argument_[5];
+    u.c[3] = argument_[4];
+    u.c[4] = argument_[3];
+    u.c[5] = argument_[2];
+    u.c[6] = argument_[1];
+    u.c[7] = argument_[0];
+
+    return u.d;
+#else
+	return *(double*)argument_;
+#endif
+}
+
+
+const char* ReceivedMessageArgument::AsString() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == STRING_TYPE_TAG )
+		return argument_;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+const char* ReceivedMessageArgument::AsSymbol() const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == SYMBOL_TYPE_TAG )
+		return argument_;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlob( const void*& data, unsigned long& size ) const
+{
+    if( !typeTag_ )
+        throw MissingArgumentException();
+	else if( *typeTag_ == BLOB_TYPE_TAG )
+		AsBlobUnchecked( data, size );
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, unsigned long& size ) const
+{
+    size = ToUInt32( argument_ );
+	data = (void*)(argument_+4);
+}
+
+//------------------------------------------------------------------------------
+
+void ReceivedMessageArgumentIterator::Advance()
+{
+    if( !value_.typeTag_ )
+        return;
+        
+    switch( *value_.typeTag_++ ){
+        case '\0':
+            // don't advance past end
+            --value_.typeTag_;
+            break;
+            
+        case TRUE_TYPE_TAG:
+        case FALSE_TYPE_TAG:
+        case NIL_TYPE_TAG:
+        case INFINITUM_TYPE_TAG:
+
+            // zero length
+            break;
+
+        case INT32_TYPE_TAG:
+        case FLOAT_TYPE_TAG: 					
+        case CHAR_TYPE_TAG:
+        case RGBA_COLOR_TYPE_TAG:
+        case MIDI_MESSAGE_TYPE_TAG:
+
+            value_.argument_ += 4;
+            break;
+
+        case INT64_TYPE_TAG:
+        case TIME_TAG_TYPE_TAG:
+        case DOUBLE_TYPE_TAG:
+				
+            value_.argument_ += 8;
+            break;
+
+        case STRING_TYPE_TAG: 
+        case SYMBOL_TYPE_TAG:
+
+            // we use the unsafe function FindStr4End(char*) here because all of
+            // the arguments have already been validated in
+            // ReceivedMessage::Init() below.
+            
+            value_.argument_ = FindStr4End( value_.argument_ );
+            break;
+
+        case BLOB_TYPE_TAG:
+            {
+                uint32 blobSize = ToUInt32( value_.argument_ );
+                value_.argument_ = value_.argument_ + 4 + RoundUp4( blobSize );
+            }
+            break;
+
+        default:    // unknown type tag
+            // don't advance
+            --value_.typeTag_;
+            break;
+            
+
+        //    not handled:
+        //    [ Indicates the beginning of an array. The tags following are for
+        //        data in the Array until a close brace tag is reached.
+        //    ] Indicates the end of an array.
+    }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
+    : addressPattern_( packet.Contents() )
+{
+    Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
+    : addressPattern_( bundleElement.Contents() )
+{
+    Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+bool ReceivedMessage::AddressPatternIsUInt32() const
+{
+	return (addressPattern_[0] == '\0');
+}
+
+
+uint32 ReceivedMessage::AddressPatternAsUInt32() const
+{
+    return ToUInt32( addressPattern_ );
+}
+
+
+void ReceivedMessage::Init( const char *message, unsigned long size )
+{
+    if( size == 0 )
+        throw MalformedMessageException( "zero length messages not permitted" );
+
+    if( (size & 0x03L) != 0 )
+        throw MalformedMessageException( "message size must be multiple of four" );
+
+    const char *end = message + size;
+
+    typeTagsBegin_ = FindStr4End( addressPattern_, end );
+    if( typeTagsBegin_ == 0 ){
+        // address pattern was not terminated before end
+        throw MalformedMessageException( "unterminated address pattern" );
+    }
+
+    if( typeTagsBegin_ == end ){
+        // message consists of only the address pattern - no arguments or type tags.
+        typeTagsBegin_ = 0;
+        typeTagsEnd_ = 0;
+        arguments_ = 0;
+            
+    }else{
+        if( *typeTagsBegin_ != ',' )
+            throw MalformedMessageException( "type tags not present" );
+
+        if( *(typeTagsBegin_ + 1) == '\0' ){
+            // zero length type tags
+            typeTagsBegin_ = 0;
+            typeTagsEnd_ = 0;
+            arguments_ = 0;
+
+        }else{
+            // check that all arguments are present and well formed
+                
+            arguments_ = FindStr4End( typeTagsBegin_, end );
+            if( arguments_ == 0 ){
+                throw MalformedMessageException( "type tags were not terminated before end of message" );
+            }
+
+            ++typeTagsBegin_; // advance past initial ','
+            
+            const char *typeTag = typeTagsBegin_;
+            const char *argument = arguments_;
+                        
+            do{
+                switch( *typeTag ){
+                    case TRUE_TYPE_TAG:
+                    case FALSE_TYPE_TAG:
+                    case NIL_TYPE_TAG:
+                    case INFINITUM_TYPE_TAG:
+
+                        // zero length
+                        break;
+
+                    case INT32_TYPE_TAG:
+                    case FLOAT_TYPE_TAG:
+                    case CHAR_TYPE_TAG:
+                    case RGBA_COLOR_TYPE_TAG:
+                    case MIDI_MESSAGE_TYPE_TAG:
+
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument += 4;
+                        if( argument > end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        break;
+
+                    case INT64_TYPE_TAG:
+                    case TIME_TAG_TYPE_TAG:
+                    case DOUBLE_TYPE_TAG:
+
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument += 8;
+                        if( argument > end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        break;
+
+                    case STRING_TYPE_TAG: 
+                    case SYMBOL_TYPE_TAG:
+                    
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument = FindStr4End( argument, end );
+                        if( argument == 0 )
+                            throw MalformedMessageException( "unterminated string argument" );
+                        break;
+
+                    case BLOB_TYPE_TAG:
+                        {
+                            if( argument + 4 > end )
+                                MalformedMessageException( "arguments exceed message size" );
+                                
+                            uint32 blobSize = ToUInt32( argument );
+                            argument = argument + 4 + RoundUp4( blobSize );
+                            if( argument > end )
+                                MalformedMessageException( "arguments exceed message size" );
+                        }
+                        break;
+                        
+                    default:
+                        throw MalformedMessageException( "unknown type tag" );
+
+                    //    not handled:
+                    //    [ Indicates the beginning of an array. The tags following are for
+                    //        data in the Array until a close brace tag is reached.
+                    //    ] Indicates the end of an array.
+                }
+
+            }while( *++typeTag != '\0' );
+            typeTagsEnd_ = typeTag;
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
+    : elementCount_( 0 )
+{
+    Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
+    : elementCount_( 0 )
+{
+    Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+void ReceivedBundle::Init( const char *bundle, unsigned long size )
+{
+    if( size < 16 )
+        throw MalformedBundleException( "packet too short for bundle" );
+
+    if( (size & 0x03L) != 0 )
+        throw MalformedBundleException( "bundle size must be multiple of four" );
+
+    if( bundle[0] != '#'
+        || bundle[1] != 'b'
+        || bundle[2] != 'u'
+        || bundle[3] != 'n'
+        || bundle[4] != 'd'
+        || bundle[5] != 'l'
+        || bundle[6] != 'e'
+        || bundle[7] != '\0' )
+            throw MalformedBundleException( "bad bundle address pattern" );    
+
+    end_ = bundle + size;
+
+    timeTag_ = bundle + 8;
+
+    const char *p = timeTag_ + 8;
+        
+    while( p < end_ ){
+        if( p + 4 > end_ )
+            throw MalformedBundleException( "packet too short for elementSize" );
+
+        uint32 elementSize = ToUInt32( p );
+        if( (elementSize & 0x03L) != 0 )
+            throw MalformedBundleException( "bundle element size must be multiple of four" );
+
+        p += 4 + elementSize;
+        if( p > end_ )
+            throw MalformedBundleException( "packet too short for bundle element" );
+
+        ++elementCount_;
+    }
+
+    if( p != end_ )
+        throw MalformedBundleException( "bundle contents " );
+}
+
+
+uint64 ReceivedBundle::TimeTag() const
+{
+    return ToUInt64( timeTag_ );
+}
+
+
+} // namespace osc
+

+ 40 - 0
Modules/Contents/TUIO/Source/OscTypes.cpp

@@ -0,0 +1,40 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscTypes.h"
+
+namespace osc{
+
+BundleInitiator BeginBundleImmediate(1);
+BundleTerminator EndBundle;
+MessageTerminator EndMessage;
+NilType Nil;
+InfinitumType Infinitum;
+
+} // namespace osc

+ 123 - 0
Modules/Contents/TUIO/Source/TUIOInputModule.cpp

@@ -0,0 +1,123 @@
+
+#include "TUIOInputModule.h"
+#include <Polycode.h>
+
+
+TUIOInputModule::TUIOInputModule(int port) : PolycodeModule(), TuioListener() {
+	tuioClient = new TuioClient(port);
+	tuioClient->addTuioListener(this);
+	tuioClient->connect();
+	
+	eventMutex = CoreServices::getInstance()->getCore()->createMutex();
+	_requiresUpdate = true;
+
+}
+
+TUIOInputModule::~TUIOInputModule() {
+	tuioClient->removeAllTuioListeners();
+	tuioClient->disconnect();
+	delete tuioClient;
+	delete eventMutex;
+}
+
+void TUIOInputModule::addTuioObject(TuioObject *tobj) {
+}
+
+void TUIOInputModule::updateTuioObject(TuioObject *tobj) {
+}
+
+void TUIOInputModule::removeTuioObject(TuioObject *tobj) {
+}
+
+void TUIOInputModule::addTuioCursor(TuioCursor *tcur) {
+	std::vector<TouchInfo> touches;	
+	std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
+	tuioClient->lockCursorList();
+	for (std::list<TuioCursor*>::iterator iter = cursorList.begin(); iter!=cursorList.end(); iter++) {
+			TuioCursor *tuioCursor = (*iter);	
+			TouchInfo touch;	
+			touch.position.x = tuioCursor->getX();
+			touch.position.y = tuioCursor->getY();
+			touch.id= tuioCursor->getCursorID();
+			touches.push_back(touch);
+	}
+	tuioClient->unlockCursorList();	
+	TUIOEvent event;
+	event.type = InputEvent::EVENT_TOUCHES_BEGAN;
+	event.touches = touches;
+	
+	CoreServices::getInstance()->getCore()->lockMutex(eventMutex);
+	events.push_back(event);					
+	CoreServices::getInstance()->getCore()->unlockMutex(eventMutex);
+}
+
+void TUIOInputModule::updateTuioCursor(TuioCursor *tcur) {
+	std::vector<TouchInfo> touches;	
+	std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
+	tuioClient->lockCursorList();
+	for (std::list<TuioCursor*>::iterator iter = cursorList.begin(); iter!=cursorList.end(); iter++) {
+			TuioCursor *tuioCursor = (*iter);	
+			TouchInfo touch;	
+			touch.position.x = tuioCursor->getX();
+			touch.position.y = tuioCursor->getY();
+			touch.id= tuioCursor->getCursorID();			
+			touches.push_back(touch);
+	}
+	tuioClient->unlockCursorList();	
+	TUIOEvent event;
+	event.type = InputEvent::EVENT_TOUCHES_MOVED;
+	event.touches = touches;
+	
+	CoreServices::getInstance()->getCore()->lockMutex(eventMutex);
+	events.push_back(event);					
+	CoreServices::getInstance()->getCore()->unlockMutex(eventMutex);
+}
+
+void TUIOInputModule::removeTuioCursor(TuioCursor *tcur) {
+	std::vector<TouchInfo> touches;	
+	std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
+	tuioClient->lockCursorList();
+	for (std::list<TuioCursor*>::iterator iter = cursorList.begin(); iter!=cursorList.end(); iter++) {
+			TuioCursor *tuioCursor = (*iter);	
+			TouchInfo touch;	
+			touch.position.x = tuioCursor->getX();
+			touch.position.y = tuioCursor->getY();
+			touch.id= tuioCursor->getCursorID();			
+			touches.push_back(touch);
+	}
+	tuioClient->unlockCursorList();	
+	TUIOEvent event;
+	event.type = InputEvent::EVENT_TOUCHES_ENDED;
+	event.touches = touches;
+	
+	CoreServices::getInstance()->getCore()->lockMutex(eventMutex);
+	events.push_back(event);					
+	CoreServices::getInstance()->getCore()->unlockMutex(eventMutex);
+}
+
+void TUIOInputModule::refresh(TuioTime frameTime) {
+}	
+
+void TUIOInputModule::Update(Number elapsed) {
+
+	CoreServices::getInstance()->getCore()->lockMutex(eventMutex);
+	for(int i=0; i < events.size(); i++) {
+		for(int j=0; j < events[i].touches.size(); j++) {
+			events[i].touches[j].position.x = events[i].touches[j].position.x * CoreServices::getInstance()->getCore()->getXRes();
+			events[i].touches[j].position.y = events[i].touches[j].position.y * CoreServices::getInstance()->getCore()->getYRes();			
+		}
+		switch(events[i].type) {
+			case InputEvent::EVENT_TOUCHES_BEGAN:
+				CoreServices::getInstance()->getCore()->getInput()->touchesBegan(events[i].touches);
+			break;
+			case InputEvent::EVENT_TOUCHES_MOVED:
+				CoreServices::getInstance()->getCore()->getInput()->touchesMoved(events[i].touches);
+			break;
+			case InputEvent::EVENT_TOUCHES_ENDED:
+				CoreServices::getInstance()->getCore()->getInput()->touchesEnded(events[i].touches);			
+			break;			
+		}
+	}
+	events.clear();
+	CoreServices::getInstance()->getCore()->unlockMutex(eventMutex);	
+}

+ 567 - 0
Modules/Contents/TUIO/Source/TuioClient.cpp

@@ -0,0 +1,567 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "TuioClient.h"
+
+using namespace TUIO;
+using namespace osc;
+
+#ifndef WIN32
+static void* ClientThreadFunc( void* obj )
+#else
+static DWORD WINAPI ClientThreadFunc( LPVOID obj )
+#endif
+{
+	static_cast<TuioClient*>(obj)->socket->Run();
+	return 0;
+};
+
+void TuioClient::lockObjectList() {
+	if(!connected) return;
+#ifndef WIN32	
+	pthread_mutex_lock(&objectMutex);
+#else
+	WaitForSingleObject(objectMutex, INFINITE);
+#endif		
+}
+
+void TuioClient::unlockObjectList() {
+	if(!connected) return;
+#ifndef WIN32	
+	pthread_mutex_unlock(&objectMutex);
+#else
+	ReleaseMutex(objectMutex);
+#endif
+}
+
+void TuioClient::lockCursorList() {
+	if(!connected) return;
+#ifndef WIN32	
+	pthread_mutex_lock(&cursorMutex);
+#else
+	WaitForSingleObject(cursorMutex, INFINITE);
+#endif		
+}
+
+void TuioClient::unlockCursorList() {
+	if(!connected) return;
+#ifndef WIN32	
+	pthread_mutex_unlock(&cursorMutex);
+#else
+	ReleaseMutex(cursorMutex);
+#endif		
+}
+
+TuioClient::TuioClient(int port)
+: socket      (NULL)
+, currentFrame(-1)
+, maxCursorID (-1)
+, thread      (NULL)
+, locked      (false)
+, connected   (false)
+{
+	try {
+		socket = new UdpListeningReceiveSocket(IpEndpointName( IpEndpointName::ANY_ADDRESS, port ), this );
+	} catch (std::exception &e) { 
+		std::cerr << "could not bind to UDP port " << port << std::endl;
+		socket = NULL;
+	}
+	
+	if (socket!=NULL) {
+		if (!socket->IsBound()) {
+			delete socket;
+			socket = NULL;
+		} else std::cout << "listening to TUIO messages on UDP port " << port << std::endl;
+	}	
+}
+
+TuioClient::~TuioClient() {	
+	delete socket;
+}
+
+void TuioClient::ProcessBundle( const ReceivedBundle& b, const IpEndpointName& remoteEndpoint) {
+	
+	try {
+		for( ReceivedBundle::const_iterator i = b.ElementsBegin(); i != b.ElementsEnd(); ++i ){
+			if( i->IsBundle() )
+				ProcessBundle( ReceivedBundle(*i), remoteEndpoint);
+			else
+				ProcessMessage( ReceivedMessage(*i), remoteEndpoint);
+		}
+	} catch (MalformedBundleException& e) {
+		std::cerr << "malformed OSC bundle: " << e.what() << std::endl;
+	}
+	
+}
+
+void TuioClient::ProcessMessage( const ReceivedMessage& msg, const IpEndpointName& remoteEndpoint) {
+	try {
+		ReceivedMessageArgumentStream args = msg.ArgumentStream();
+		ReceivedMessage::const_iterator arg = msg.ArgumentsBegin();
+		
+		if( strcmp( msg.AddressPattern(), "/tuio/2Dobj" ) == 0 ){
+			
+			const char* cmd;
+			args >> cmd;
+			
+			if (strcmp(cmd,"set")==0) {	
+												
+				int32 s_id, c_id;
+				float xpos, ypos, angle, xspeed, yspeed, rspeed, maccel, raccel;
+				args >> s_id >> c_id >> xpos >> ypos >> angle >> xspeed >> yspeed >> rspeed >> maccel >> raccel;
+				
+				lockObjectList();
+				std::list<TuioObject*>::iterator tobj;
+				for (tobj=objectList.begin(); tobj!= objectList.end(); tobj++)
+					if((*tobj)->getSessionID()==(long)s_id) break;
+				
+				if (tobj == objectList.end()) {
+					
+					TuioObject *addObject = new TuioObject((long)s_id,(int)c_id,xpos,ypos,angle);
+					frameObjects.push_back(addObject);
+
+				} else if ( ((*tobj)->getX()!=xpos) || ((*tobj)->getY()!=ypos) || ((*tobj)->getAngle()!=angle) || ((*tobj)->getXSpeed()!=xspeed) || ((*tobj)->getYSpeed()!=yspeed) || ((*tobj)->getRotationSpeed()!=rspeed) || ((*tobj)->getMotionAccel()!=maccel) || ((*tobj)->getRotationAccel()!=raccel) ) {
+
+					TuioObject *updateObject = new TuioObject((long)s_id,(*tobj)->getSymbolID(),xpos,ypos,angle);
+					updateObject->update(xpos,ypos,angle,xspeed,yspeed,rspeed,maccel,raccel);
+					frameObjects.push_back(updateObject);
+					
+				}
+				unlockObjectList();
+
+			} else if (strcmp(cmd,"alive")==0) {
+				
+				int32 s_id;
+				aliveObjectList.clear();
+				while(!args.Eos()) {
+					args >> s_id;
+					aliveObjectList.push_back((long)s_id);
+				}
+				
+			} else if (strcmp(cmd,"fseq")==0) {
+				
+				int32 fseq;
+				args >> fseq;
+				bool lateFrame = false;
+				if (fseq>0) {
+					if (fseq>currentFrame) currentTime = TuioTime::getSessionTime();
+					if ((fseq>=currentFrame) || ((currentFrame-fseq)>100)) currentFrame = fseq;
+					else lateFrame = true;
+				} else if ((TuioTime::getSessionTime().getTotalMilliseconds()-currentTime.getTotalMilliseconds())>100) {
+					currentTime = TuioTime::getSessionTime();
+				}
+			
+				if (!lateFrame) {
+					
+					lockObjectList();
+					//find the removed objects first
+					for (std::list<TuioObject*>::iterator tobj=objectList.begin(); tobj != objectList.end(); tobj++) {
+						std::list<long>::iterator iter = find(aliveObjectList.begin(), aliveObjectList.end(), (*tobj)->getSessionID());
+						if (iter == aliveObjectList.end()) {
+							(*tobj)->remove(currentTime);
+							frameObjects.push_back(*tobj);							
+						}
+					}
+					unlockObjectList();
+					
+					for (std::list<TuioObject*>::iterator iter=frameObjects.begin(); iter != frameObjects.end(); iter++) {
+						TuioObject *tobj = (*iter);
+
+						TuioObject *frameObject = NULL;
+						switch (tobj->getTuioState()) {
+							case TUIO_REMOVED:
+								frameObject = tobj;
+								frameObject->remove(currentTime);
+
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->removeTuioObject(frameObject);
+
+								lockObjectList();								
+								for (std::list<TuioObject*>::iterator delobj=objectList.begin(); delobj!=objectList.end(); delobj++) {
+									if((*delobj)->getSessionID()==frameObject->getSessionID()) {
+										objectList.erase(delobj);
+										break;
+									}
+								}
+								unlockObjectList();
+								break;
+							case TUIO_ADDED:
+								
+								lockObjectList();
+								frameObject = new TuioObject(currentTime,tobj->getSessionID(),tobj->getSymbolID(),tobj->getX(),tobj->getY(),tobj->getAngle());
+								objectList.push_back(frameObject);
+								unlockObjectList();
+								
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->addTuioObject(frameObject);
+								
+								break;
+							default:
+								
+								lockObjectList();
+								std::list<TuioObject*>::iterator iter;
+								for (iter=objectList.begin(); iter != objectList.end(); iter++) {
+									if((*iter)->getSessionID()==tobj->getSessionID()) {
+										frameObject = (*iter);
+										break;
+									}
+								}
+								if(iter==objectList.end()) break;
+								
+								if ( (tobj->getX()!=frameObject->getX() && tobj->getXSpeed()==0) || (tobj->getY()!=frameObject->getY() && tobj->getYSpeed()==0) )
+									frameObject->update(currentTime,tobj->getX(),tobj->getY(),tobj->getAngle());
+								else
+									frameObject->update(currentTime,tobj->getX(),tobj->getY(),tobj->getAngle(),tobj->getXSpeed(),tobj->getYSpeed(),tobj->getRotationSpeed(),tobj->getMotionAccel(),tobj->getRotationAccel());
+								unlockObjectList();
+								
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->updateTuioObject(frameObject);
+								
+						}
+						delete tobj;
+					}
+
+					for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+						(*listener)->refresh(currentTime);
+					
+				} else {
+					for (std::list<TuioObject*>::iterator iter=frameObjects.begin(); iter != frameObjects.end(); iter++) {
+						TuioObject *tobj = (*iter);
+						delete tobj;
+					}
+				}
+				
+				frameObjects.clear();
+			}
+		} else if( strcmp( msg.AddressPattern(), "/tuio/2Dcur" ) == 0 ) {
+			const char* cmd;
+			args >> cmd;
+			
+			if (strcmp(cmd,"set")==0) {	
+
+				int32 s_id;
+				float xpos, ypos, xspeed, yspeed, maccel;				
+				args >> s_id >> xpos >> ypos >> xspeed >> yspeed >> maccel;
+				
+				lockCursorList();
+				std::list<TuioCursor*>::iterator tcur;
+				for (tcur=cursorList.begin(); tcur!= cursorList.end(); tcur++)
+					if((*tcur)->getSessionID()==(long)s_id) break;
+				
+				if (tcur==cursorList.end()) {
+									
+					TuioCursor *addCursor = new TuioCursor((long)s_id,-1,xpos,ypos);
+					frameCursors.push_back(addCursor);
+
+				} else if ( ((*tcur)->getX()!=xpos) || ((*tcur)->getY()!=ypos) || ((*tcur)->getXSpeed()!=xspeed) || ((*tcur)->getYSpeed()!=yspeed) || ((*tcur)->getMotionAccel()!=maccel) ) {
+
+					TuioCursor *updateCursor = new TuioCursor((long)s_id,(*tcur)->getCursorID(),xpos,ypos);
+					updateCursor->update(xpos,ypos,xspeed,yspeed,maccel);
+					frameCursors.push_back(updateCursor);
+
+				}
+				unlockCursorList();
+				
+			} else if (strcmp(cmd,"alive")==0) {
+				
+				int32 s_id;
+				aliveCursorList.clear();
+				while(!args.Eos()) {
+					args >> s_id;
+					aliveCursorList.push_back((long)s_id);
+				}
+				
+			} else if( strcmp( cmd, "fseq" ) == 0 ){
+				
+				int32 fseq;
+				args >> fseq;
+				bool lateFrame = false;
+				if (fseq>0) {
+					if (fseq>currentFrame) currentTime = TuioTime::getSessionTime();
+					if ((fseq>=currentFrame) || ((currentFrame-fseq)>100)) currentFrame = fseq;
+					else lateFrame = true;
+				}  else if ((TuioTime::getSessionTime().getTotalMilliseconds()-currentTime.getTotalMilliseconds())>100) {
+					currentTime = TuioTime::getSessionTime();
+				}
+			
+				if (!lateFrame) {
+					
+					lockCursorList();
+					// find the removed cursors first
+					for (std::list<TuioCursor*>::iterator tcur=cursorList.begin(); tcur != cursorList.end(); tcur++) {
+						std::list<long>::iterator iter = find(aliveCursorList.begin(), aliveCursorList.end(), (*tcur)->getSessionID());
+							
+						if (iter == aliveCursorList.end()) {
+							(*tcur)->remove(currentTime);
+							frameCursors.push_back(*tcur);
+						}
+					}
+					unlockCursorList();
+					
+					for (std::list<TuioCursor*>::iterator iter=frameCursors.begin(); iter != frameCursors.end(); iter++) {
+						TuioCursor *tcur = (*iter);
+						
+						int c_id = -1;
+						TuioCursor *frameCursor = NULL;
+						switch (tcur->getTuioState()) {
+							case TUIO_REMOVED:
+								frameCursor = tcur;
+								frameCursor->remove(currentTime);
+	
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->removeTuioCursor(frameCursor);
+
+								lockCursorList();
+								for (std::list<TuioCursor*>::iterator delcur=cursorList.begin(); delcur!=cursorList.end(); delcur++) {
+									if((*delcur)->getSessionID()==frameCursor->getSessionID()) {
+										cursorList.erase(delcur);
+										break;
+									}
+								}
+
+								if (frameCursor->getCursorID()==maxCursorID) {
+									maxCursorID = -1;
+									delete frameCursor;
+									
+									if (cursorList.size()>0) {
+										std::list<TuioCursor*>::iterator clist;
+										for (clist=cursorList.begin(); clist != cursorList.end(); clist++) {
+											c_id = (*clist)->getCursorID();
+											if (c_id>maxCursorID) maxCursorID=c_id;
+										}
+			
+										freeCursorBuffer.clear();
+										for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
+											TuioCursor *freeCursor = (*flist);
+											if (freeCursor->getCursorID()>maxCursorID) delete freeCursor;
+											else freeCursorBuffer.push_back(freeCursor);
+										}	
+										freeCursorList = freeCursorBuffer;
+
+									} else {
+										for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
+											TuioCursor *freeCursor = (*flist);
+											delete freeCursor;
+										}
+										freeCursorList.clear();
+									}
+								} else if (frameCursor->getCursorID()<maxCursorID) {
+									freeCursorList.push_back(frameCursor);
+								} 
+								
+								unlockCursorList();
+								break;
+							case TUIO_ADDED:
+								
+								lockCursorList();
+								c_id = (int)cursorList.size();
+								if (((int)(cursorList.size())<=maxCursorID) && ((int)(freeCursorList.size())>0)) {
+									std::list<TuioCursor*>::iterator closestCursor = freeCursorList.begin();
+									
+									for(std::list<TuioCursor*>::iterator iter = freeCursorList.begin();iter!= freeCursorList.end(); iter++) {
+										if((*iter)->getDistance(tcur)<(*closestCursor)->getDistance(tcur)) closestCursor = iter;
+									}
+									
+									TuioCursor *freeCursor = (*closestCursor);
+									c_id = freeCursor->getCursorID();
+									freeCursorList.erase(closestCursor);
+									delete freeCursor;
+								} else maxCursorID = c_id;									
+								
+								frameCursor = new TuioCursor(currentTime,tcur->getSessionID(),c_id,tcur->getX(),tcur->getY());
+								cursorList.push_back(frameCursor);
+								
+								delete tcur;
+								unlockCursorList();
+								
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->addTuioCursor(frameCursor);
+								
+								break;
+							default:
+								
+								lockCursorList();
+								std::list<TuioCursor*>::iterator iter;
+								for (iter=cursorList.begin(); iter != cursorList.end(); iter++) {
+									if((*iter)->getSessionID()==tcur->getSessionID()) {
+										frameCursor = (*iter);
+										break;
+									}
+								}
+								
+								if ( (tcur->getX()!=frameCursor->getX() && tcur->getXSpeed()==0) || (tcur->getY()!=frameCursor->getY() && tcur->getYSpeed()==0) )
+									frameCursor->update(currentTime,tcur->getX(),tcur->getY());
+								else
+									frameCursor->update(currentTime,tcur->getX(),tcur->getY(),tcur->getXSpeed(),tcur->getYSpeed(),tcur->getMotionAccel());
+						
+								delete tcur;
+								unlockCursorList();
+								
+								for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+									(*listener)->updateTuioCursor(frameCursor);
+						}	
+					}
+					
+					for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
+						(*listener)->refresh(currentTime);
+					
+				} else {
+					for (std::list<TuioCursor*>::iterator iter=frameCursors.begin(); iter != frameCursors.end(); iter++) {
+						TuioCursor *tcur = (*iter);
+						delete tcur;
+					}
+				}
+				
+				frameCursors.clear();
+			}
+		}
+	} catch( Exception& e ){
+		std::cerr << "error parsing TUIO message: "<< msg.AddressPattern() <<  " - " << e.what() << std::endl;
+	}
+}
+
+void TuioClient::ProcessPacket( const char *data, int size, const IpEndpointName& remoteEndpoint ) {
+	try {
+		ReceivedPacket p( data, size );
+		if(p.IsBundle()) ProcessBundle( ReceivedBundle(p), remoteEndpoint);
+		else ProcessMessage( ReceivedMessage(p), remoteEndpoint);
+	} catch (MalformedBundleException& e) {
+		std::cerr << "malformed OSC bundle: " << e.what() << std::endl;
+	}
+}
+
+void TuioClient::connect(bool lk) {
+
+#ifndef WIN32	
+	/*pthread_mutexattr_settype(&attr_p, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(&cursorMutex,&attr_p);
+	pthread_mutex_init(&objectMutex,&attr_p);*/
+	pthread_mutex_init(&cursorMutex,NULL);
+	pthread_mutex_init(&objectMutex,NULL);	
+#else
+	cursorMutex = CreateMutex(NULL,FALSE,"cursorMutex");
+	objectMutex = CreateMutex(NULL,FALSE,"objectMutex");
+#endif		
+		
+	if (socket==NULL) return;
+	TuioTime::initSession();
+	currentTime.reset();
+	
+	locked = lk;
+	if (!locked) {
+#ifndef WIN32
+		pthread_create(&thread , NULL, ClientThreadFunc, this);
+#else
+		DWORD threadId;
+		thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &threadId );
+#endif
+	} else socket->Run();
+	
+	connected = true;
+	unlockCursorList();
+	unlockObjectList();
+}
+
+void TuioClient::disconnect() {
+	
+	if (socket==NULL) return;
+	socket->Break();
+	
+	if (!locked) {
+#ifdef WIN32
+		if( thread ) CloseHandle( thread );
+#endif
+		thread = 0;
+		locked = false;
+	}
+	
+#ifndef WIN32	
+	pthread_mutex_destroy(&cursorMutex);
+	pthread_mutex_destroy(&objectMutex);
+#else
+	CloseHandle(cursorMutex);
+	CloseHandle(objectMutex);
+#endif
+
+	aliveObjectList.clear();
+	aliveCursorList.clear();
+
+	for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++)
+		delete (*iter);
+	objectList.clear();
+
+	for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++)
+		delete (*iter);
+	cursorList.clear();
+	
+	for (std::list<TuioCursor*>::iterator iter=freeCursorList.begin(); iter != freeCursorList.end(); iter++)
+		delete(*iter);
+	freeCursorList.clear();
+
+	connected = false;
+}
+
+void TuioClient::addTuioListener(TuioListener *listener) {
+	listenerList.push_back(listener);
+}
+
+void TuioClient::removeTuioListener(TuioListener *listener) {
+	std::list<TuioListener*>::iterator result = find(listenerList.begin(),listenerList.end(),listener);
+	if (result!=listenerList.end()) listenerList.remove(listener);
+}
+
+TuioObject* TuioClient::getTuioObject(long s_id) {
+	lockObjectList();
+	for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
+		if((*iter)->getSessionID()==s_id) {
+			unlockObjectList();
+			return (*iter);
+		}
+	}	
+	unlockObjectList();
+	return NULL;
+}
+
+TuioCursor* TuioClient::getTuioCursor(long s_id) {
+	lockCursorList();
+	for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
+		if((*iter)->getSessionID()==s_id) {
+			unlockCursorList();
+			return (*iter);
+		}
+	}	
+	unlockCursorList();
+	return NULL;
+}
+
+std::list<TuioObject*> TuioClient::getTuioObjects() {
+	lockObjectList();
+	std::list<TuioObject*> listBuffer = objectList;
+	unlockObjectList();
+	return listBuffer;
+}
+
+std::list<TuioCursor*> TuioClient::getTuioCursors() {
+	lockCursorList();
+	std::list<TuioCursor*> listBuffer = cursorList;
+	unlockCursorList();
+	return listBuffer;
+}

+ 636 - 0
Modules/Contents/TUIO/Source/TuioServer.cpp

@@ -0,0 +1,636 @@
+/*
+	TUIO Server Component - part of the reacTIVision project
+	http://reactivision.sourceforge.net/
+
+	Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "TuioServer.h"
+
+using namespace TUIO;
+using namespace osc;
+
+#ifndef WIN32
+static void* ThreadFunc( void* obj )
+#else
+static DWORD WINAPI ThreadFunc( LPVOID obj )
+#endif
+{
+	TuioServer *tuioServer = static_cast<TuioServer*>(obj);
+	while ((tuioServer->isConnected()) && (tuioServer->periodicMessagesEnabled())) {
+		tuioServer->sendFullMessages();
+#ifndef WIN32
+		usleep(USEC_SECOND*tuioServer->getUpdateInterval());
+#else
+		Sleep(MSEC_SECOND*tuioServer->getUpdateInterval());
+#endif
+	}	
+	return 0;
+};
+
+void TuioServer::enablePeriodicMessages(int interval) {
+	if (periodic_update) return;
+	
+	update_interval = interval;
+	periodic_update = true;
+	
+#ifndef WIN32
+	pthread_create(&thread , NULL, ThreadFunc, this);
+#else
+	DWORD threadId;
+	thread = CreateThread( 0, 0, ThreadFunc, this, 0, &threadId );
+#endif
+}
+
+void TuioServer::disablePeriodicMessages() {
+	if (!periodic_update) return;
+	periodic_update = false;
+	
+#ifdef WIN32
+	if( thread ) CloseHandle( thread );
+#endif
+	thread = NULL;	
+}
+
+void TuioServer::sendFullMessages() {
+	
+	// prepare the cursor packet
+	fullPacket->Clear();
+	(*fullPacket) << osc::BeginBundleImmediate;
+	
+	// add the cursor alive message
+	(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
+	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++)
+		(*fullPacket) << (int32)((*tuioCursor)->getSessionID());	
+	(*fullPacket) << osc::EndMessage;	
+
+	// add all current cursor set messages
+	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
+		
+		// start a new packet if we exceed the packet capacity
+		if ((fullPacket->Capacity()-fullPacket->Size())<CUR_MESSAGE_SIZE) {
+			
+			// add the immediate fseq message and send the cursor packet
+			(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
+			(*fullPacket) << osc::EndBundle;
+			socket->Send( fullPacket->Data(), fullPacket->Size() );
+
+			// prepare the new cursor packet
+			fullPacket->Clear();	
+			(*fullPacket) << osc::BeginBundleImmediate;
+			
+			// add the cursor alive message
+			(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
+			for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++)
+				(*fullPacket) << (int32)((*tuioCursor)->getSessionID());	
+			(*fullPacket) << osc::EndMessage;				
+		}
+
+		// add the actual cursor set message
+		(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "set";
+		(*fullPacket) << (int32)((*tuioCursor)->getSessionID()) << (*tuioCursor)->getX() << (*tuioCursor)->getY();
+		(*fullPacket) << (*tuioCursor)->getXSpeed() << (*tuioCursor)->getYSpeed() <<(*tuioCursor)->getMotionAccel();	
+		(*fullPacket) << osc::EndMessage;	
+	}
+	
+	// add the immediate fseq message and send the cursor packet
+	(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
+	(*fullPacket) << osc::EndBundle;
+	socket->Send( fullPacket->Data(), fullPacket->Size() );
+	
+	// prepare the object packet
+	fullPacket->Clear();
+	(*fullPacket) << osc::BeginBundleImmediate;
+	
+	// add the object alive message
+	(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
+	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++)
+		(*fullPacket) << (int32)((*tuioObject)->getSessionID());	
+	(*fullPacket) << osc::EndMessage;	
+
+	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
+		
+		// start a new packet if we exceed the packet capacity
+		if ((fullPacket->Capacity()-fullPacket->Size())<OBJ_MESSAGE_SIZE) {
+			// add the immediate fseq message and send the object packet
+			(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
+			(*fullPacket) << osc::EndBundle;
+			socket->Send( fullPacket->Data(), fullPacket->Size() );
+			
+			// prepare the new object packet
+			fullPacket->Clear();	
+			(*fullPacket) << osc::BeginBundleImmediate;
+			
+			// add the object alive message
+			(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
+			for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++)
+				(*fullPacket) << (int32)((*tuioObject)->getSessionID());	
+			(*fullPacket) << osc::EndMessage;	
+		}
+
+		// add the actual object set message
+		(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "set";
+		(*fullPacket) << (int32)((*tuioObject)->getSessionID()) << (*tuioObject)->getSymbolID() << (*tuioObject)->getX() << (*tuioObject)->getY() << (*tuioObject)->getAngle();
+		(*fullPacket) << (*tuioObject)->getXSpeed() << (*tuioObject)->getYSpeed() << (*tuioObject)->getRotationSpeed() << (*tuioObject)->getMotionAccel() << (*tuioObject)->getRotationAccel();	
+		(*fullPacket) << osc::EndMessage;
+		
+	}
+	// add the immediate fseq message and send the object packet
+	(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
+	(*fullPacket) << osc::EndBundle;
+	socket->Send( fullPacket->Data(), fullPacket->Size() );
+}
+
+TuioServer::TuioServer() {
+	initialize("127.0.0.1",3333,MAX_UDP_SIZE);
+}
+
+TuioServer::TuioServer(const char *host, int port) {
+	initialize(host,port,IP_MTU_SIZE);
+}
+
+TuioServer::TuioServer(const char *host, int port, int size) {
+	initialize(host,port,size);
+}
+
+void TuioServer::initialize(const char *host, int port, int size) {
+	if (size>MAX_UDP_SIZE) size = MAX_UDP_SIZE;
+	else if (size<MIN_UDP_SIZE) size = MIN_UDP_SIZE;
+
+	try {
+		long unsigned int ip = GetHostByName(host);
+		socket = new UdpTransmitSocket(IpEndpointName(ip, port));
+
+		oscBuffer = new char[size];
+		oscPacket = new osc::OutboundPacketStream(oscBuffer,size);
+		fullBuffer = new char[size];
+		fullPacket = new osc::OutboundPacketStream(fullBuffer,size);
+	} catch (std::exception &e) { 
+		std::cout << "could not create socket" << std::endl;
+		socket = NULL;
+	}
+	
+	currentFrameTime = TuioTime::getSessionTime().getSeconds();
+	currentFrame = sessionID = maxCursorID = -1;
+	verbose = updateObject = updateCursor = false;
+	lastObjectUpdate = lastCursorUpdate = currentFrameTime.getSeconds();
+	
+	sendEmptyCursorBundle();
+	sendEmptyObjectBundle();
+
+	periodic_update = false;
+	full_update = false;
+	connected = true;
+}
+
+TuioServer::~TuioServer() {
+	connected = false;
+
+	sendEmptyCursorBundle();
+	sendEmptyObjectBundle();
+
+	delete oscPacket;
+	delete []oscBuffer;
+	delete fullPacket;
+	delete []fullBuffer;
+	delete socket;
+}
+
+
+TuioObject* TuioServer::addTuioObject(int f_id, float x, float y, float a) {
+	sessionID++;
+	TuioObject *tobj = new TuioObject(currentFrameTime, sessionID, f_id, x, y, a);
+	objectList.push_back(tobj);
+	updateObject = true;
+
+	if (verbose)
+		std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
+
+	return tobj;
+}
+
+void TuioServer::addExternalTuioObject(TuioObject *tobj) {
+	if (tobj==NULL) return;
+	objectList.push_back(tobj);
+	updateObject = true;
+	
+	if (verbose)
+		std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
+}
+
+void TuioServer::updateTuioObject(TuioObject *tobj, float x, float y, float a) {
+	if (tobj==NULL) return;
+	if (tobj->getTuioTime()==currentFrameTime) return;
+	tobj->update(currentFrameTime,x,y,a);
+	updateObject = true;
+
+	if (verbose && tobj->isMoving())		
+		std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() 
+		<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;	
+}
+
+void TuioServer::updateExternalTuioObject(TuioObject *tobj) {
+	if (tobj==NULL) return;
+	updateObject = true;
+	if (verbose && tobj->isMoving())	
+		std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() 
+		<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;	
+}
+
+void TuioServer::removeTuioObject(TuioObject *tobj) {
+	if (tobj==NULL) return;
+	objectList.remove(tobj);
+	delete tobj;
+	updateObject = true;
+	
+	if (verbose)
+		std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ")" << std::endl;
+}
+
+void TuioServer::removeExternalTuioObject(TuioObject *tobj) {
+	if (tobj==NULL) return;
+	objectList.remove(tobj);
+	updateObject = true;
+	
+	if (verbose)
+		std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ")" << std::endl;
+}
+
+TuioCursor* TuioServer::addTuioCursor(float x, float y) {
+	sessionID++;
+	
+	int cursorID = (int)cursorList.size();
+	if (((int)(cursorList.size())<=maxCursorID) && ((int)(freeCursorList.size())>0)) {
+		std::list<TuioCursor*>::iterator closestCursor = freeCursorList.begin();
+		
+		for(std::list<TuioCursor*>::iterator iter = freeCursorList.begin();iter!= freeCursorList.end(); iter++) {
+			if((*iter)->getDistance(x,y)<(*closestCursor)->getDistance(x,y)) closestCursor = iter;
+		}
+		
+		TuioCursor *freeCursor = (*closestCursor);
+		cursorID = (*closestCursor)->getCursorID();
+		freeCursorList.erase(closestCursor);
+		delete freeCursor;
+	} else maxCursorID = cursorID;	
+	
+	TuioCursor *tcur = new TuioCursor(currentFrameTime, sessionID, cursorID, x, y);
+	cursorList.push_back(tcur);
+	updateCursor = true;
+
+	if (verbose) 
+		std::cout << "add cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() << std::endl;
+
+	return tcur;
+}
+
+void TuioServer::addExternalTuioCursor(TuioCursor *tcur) {
+	if (tcur==NULL) return;
+	cursorList.push_back(tcur);
+	updateCursor = true;
+	
+	if (verbose) 
+		std::cout << "add cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() << std::endl;
+}
+
+void TuioServer::updateTuioCursor(TuioCursor *tcur,float x, float y) {
+	if (tcur==NULL) return;
+	if (tcur->getTuioTime()==currentFrameTime) return;
+	tcur->update(currentFrameTime,x,y);
+	updateCursor = true;
+
+	if (verbose && tcur->isMoving())	 	
+		std::cout << "set cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() 
+		<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed() << " " << tcur->getMotionAccel() << " " << std::endl;
+}
+
+void TuioServer::updateExternalTuioCursor(TuioCursor *tcur) {
+	if (tcur==NULL) return;
+	updateCursor = true;
+	if (verbose && tcur->isMoving())		
+		std::cout << "set cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() 
+		<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed() << " " << tcur->getMotionAccel() << " " << std::endl;
+}
+
+void TuioServer::removeTuioCursor(TuioCursor *tcur) {
+	if (tcur==NULL) return;
+	cursorList.remove(tcur);
+	tcur->remove(currentFrameTime);
+	updateCursor = true;
+
+	if (verbose)
+		std::cout << "del cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ")" << std::endl;
+
+	if (tcur->getCursorID()==maxCursorID) {
+		maxCursorID = -1;
+		delete tcur;
+		
+		if (cursorList.size()>0) {
+			std::list<TuioCursor*>::iterator clist;
+			for (clist=cursorList.begin(); clist != cursorList.end(); clist++) {
+				int cursorID = (*clist)->getCursorID();
+				if (cursorID>maxCursorID) maxCursorID=cursorID;
+			}
+			
+			freeCursorBuffer.clear();
+			for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
+				TuioCursor *freeCursor = (*flist);
+				if (freeCursor->getCursorID()>maxCursorID) delete freeCursor;
+				else freeCursorBuffer.push_back(freeCursor);
+			}
+			freeCursorList = freeCursorBuffer;
+			
+		} else {
+			for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
+				TuioCursor *freeCursor = (*flist);
+				delete freeCursor;
+			}
+			freeCursorList.clear();
+		} 
+	} else if (tcur->getCursorID()<maxCursorID) {
+		freeCursorList.push_back(tcur);
+	}
+}
+
+void TuioServer::removeExternalTuioCursor(TuioCursor *tcur) {
+	if (tcur==NULL) return;
+	cursorList.remove(tcur);
+	updateCursor = true;
+	
+	if (verbose)
+		std::cout << "del cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ")" << std::endl;
+}
+
+long TuioServer::getSessionID() {
+	sessionID++;
+	return sessionID;
+}
+
+long TuioServer::getFrameID() {
+	return currentFrame;
+}
+
+TuioTime TuioServer::getFrameTime() {
+	return currentFrameTime;
+}
+
+void TuioServer::initFrame(TuioTime ttime) {
+	currentFrameTime = ttime;
+	currentFrame++;
+}
+
+void TuioServer::commitFrame() {
+	
+	if(updateCursor) {
+		startCursorBundle();
+		for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
+			
+			// start a new packet if we exceed the packet capacity
+			if ((oscPacket->Capacity()-oscPacket->Size())<CUR_MESSAGE_SIZE) {
+				sendCursorBundle(currentFrame);
+				startCursorBundle();
+			}
+
+			TuioCursor *tcur = (*tuioCursor);
+			if ((full_update) || (tcur->getTuioTime()==currentFrameTime)) addCursorMessage(tcur);				
+		}
+		sendCursorBundle(currentFrame);
+	} else if ((!periodic_update) && (lastCursorUpdate<currentFrameTime.getSeconds())) {
+		lastCursorUpdate = currentFrameTime.getSeconds();
+		startCursorBundle();
+		sendCursorBundle(currentFrame);
+	}
+	updateCursor = false;
+	
+	if(updateObject) {
+		startObjectBundle();
+		for (std::list<TuioObject*>::iterator  tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
+			
+			// start a new packet if we exceed the packet capacity
+			if ((oscPacket->Capacity()-oscPacket->Size())<OBJ_MESSAGE_SIZE) {
+				sendObjectBundle(currentFrame);
+				startObjectBundle();
+			}
+			
+			TuioObject *tobj = (*tuioObject);
+			if  ((full_update) || (tobj->getTuioTime()==currentFrameTime)) addObjectMessage(tobj);
+		} 
+		sendObjectBundle(currentFrame);
+	} else if ((!periodic_update) && (lastObjectUpdate<currentFrameTime.getSeconds())) {
+		lastObjectUpdate = currentFrameTime.getSeconds();
+		startObjectBundle();
+		sendObjectBundle(currentFrame);
+	}
+	updateObject = false;
+}
+
+void TuioServer::sendEmptyCursorBundle() {
+	oscPacket->Clear();	
+	(*oscPacket) << osc::BeginBundleImmediate;
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive" << osc::EndMessage;	
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
+	(*oscPacket) << osc::EndBundle;
+	socket->Send( oscPacket->Data(), oscPacket->Size() );
+}
+
+void TuioServer::startCursorBundle() {	
+	oscPacket->Clear();	
+	(*oscPacket) << osc::BeginBundleImmediate;
+	
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
+	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
+		(*oscPacket) << (int32)((*tuioCursor)->getSessionID());	
+	}
+	(*oscPacket) << osc::EndMessage;	
+}
+
+void TuioServer::addCursorMessage(TuioCursor *tcur) {
+
+	 (*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "set";
+	 (*oscPacket) << (int32)(tcur->getSessionID()) << tcur->getX() << tcur->getY();
+	 (*oscPacket) << tcur->getXSpeed() << tcur->getYSpeed() << tcur->getMotionAccel();	
+	 (*oscPacket) << osc::EndMessage;
+}
+
+void TuioServer::sendCursorBundle(long fseq) {
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << (int32)fseq << osc::EndMessage;
+	(*oscPacket) << osc::EndBundle;
+	socket->Send( oscPacket->Data(), oscPacket->Size() );
+}
+
+void TuioServer::sendEmptyObjectBundle() {
+	oscPacket->Clear();	
+	(*oscPacket) << osc::BeginBundleImmediate;
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive" << osc::EndMessage;	
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
+	(*oscPacket) << osc::EndBundle;
+	socket->Send( oscPacket->Data(), oscPacket->Size() );
+}
+
+void TuioServer::startObjectBundle() {
+	oscPacket->Clear();	
+	(*oscPacket) << osc::BeginBundleImmediate;
+	
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
+	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
+		(*oscPacket) << (int32)((*tuioObject)->getSessionID());	
+	}
+	(*oscPacket) << osc::EndMessage;	
+}
+
+void TuioServer::addObjectMessage(TuioObject *tobj) {
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "set";
+	(*oscPacket) << (int32)(tobj->getSessionID()) << tobj->getSymbolID() << tobj->getX() << tobj->getY() << tobj->getAngle();
+	(*oscPacket) << tobj->getXSpeed() << tobj->getYSpeed() << tobj->getRotationSpeed() << tobj->getMotionAccel() << tobj->getRotationAccel();	
+	(*oscPacket) << osc::EndMessage;
+}
+
+void TuioServer::sendObjectBundle(long fseq) {
+	(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << (int32)fseq << osc::EndMessage;
+	(*oscPacket) << osc::EndBundle;
+	socket->Send( oscPacket->Data(), oscPacket->Size() );
+}
+
+TuioObject* TuioServer::getTuioObject(long s_id) {
+	for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++)
+		if((*iter)->getSessionID()==s_id) return (*iter);
+	
+	return NULL;
+}
+
+TuioCursor* TuioServer::getTuioCursor(long s_id) {
+	for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++)
+		if((*iter)->getSessionID()==s_id) return (*iter);
+	
+	return NULL;
+}
+
+TuioObject* TuioServer::getClosestTuioObject(float xp, float yp) {
+	
+	TuioObject *closestObject = NULL;
+	float closestDistance = 1.0f;
+	
+	for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
+		float distance = (*iter)->getDistance(xp,yp);
+		if(distance<closestDistance) {
+			closestObject = (*iter);
+			closestDistance = distance;
+		}
+	}
+	
+	return closestObject;
+}
+
+TuioCursor* TuioServer::getClosestTuioCursor(float xp, float yp) {
+
+	TuioCursor *closestCursor = NULL;
+	float closestDistance = 1.0f;
+
+	for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
+		float distance = (*iter)->getDistance(xp,yp);
+		if(distance<closestDistance) {
+			closestCursor = (*iter);
+			closestDistance = distance;
+		}
+	}
+	
+	return closestCursor;
+}
+
+std::list<TuioObject*> TuioServer::getTuioObjects() {
+	return objectList;
+}
+
+std::list<TuioCursor*> TuioServer::getTuioCursors() {
+	return cursorList;
+}
+
+std::list<TuioObject*> TuioServer::getUntouchedObjects() {
+	
+	std::list<TuioObject*> untouched;
+	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
+		TuioObject *tobj = (*tuioObject);
+		if (tobj->getTuioTime()!=currentFrameTime) untouched.push_back(tobj);
+	}	
+	return untouched;
+}
+
+void TuioServer::stopUntouchedMovingObjects() {
+	
+	std::list<TuioObject*> untouched;
+	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
+		
+		TuioObject *tobj = (*tuioObject);
+		if ((tobj->getTuioTime()!=currentFrameTime) && (tobj->isMoving())) {
+			tobj->stop(currentFrameTime);
+			updateObject = true;
+			if (verbose)		
+				std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() 
+				<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;
+		}
+	}
+}
+
+void TuioServer::removeUntouchedStoppedObjects() {
+	
+	std::list<TuioObject*>::iterator tuioObject = objectList.begin();
+	while (tuioObject!=objectList.end()) {
+		TuioObject *tobj = (*tuioObject);
+		if ((tobj->getTuioTime()!=currentFrameTime) && (!tobj->isMoving())) {
+			removeTuioObject(tobj);
+			tuioObject = objectList.begin();
+		} else tuioObject++;
+	}
+}
+
+
+std::list<TuioCursor*> TuioServer::getUntouchedCursors() {
+	
+	std::list<TuioCursor*> untouched;
+	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
+		TuioCursor *tcur = (*tuioCursor);
+		if (tcur->getTuioTime()!=currentFrameTime) untouched.push_back(tcur);
+	}	
+	return untouched;
+}
+
+void TuioServer::stopUntouchedMovingCursors() {
+	
+	std::list<TuioCursor*> untouched;
+	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
+		TuioCursor *tcur = (*tuioCursor);
+		if ((tcur->getTuioTime()!=currentFrameTime) && (tcur->isMoving())) {
+			tcur->stop(currentFrameTime);
+			updateCursor = true;
+			if (verbose) 	
+				std::cout << "set cur " << tcur->getCursorID() << " (" <<  tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() 
+				<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed()<< " " << tcur->getMotionAccel() << " " << std::endl;							
+		}
+	}	
+}
+
+void TuioServer::removeUntouchedStoppedCursors() {
+	
+	if (cursorList.size()==0) return;
+	std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin();
+	while (tuioCursor!=cursorList.end()) {
+		TuioCursor *tcur = (*tuioCursor);
+		if ((tcur->getTuioTime()!=currentFrameTime) && (!tcur->isMoving())) {
+			removeTuioCursor(tcur);
+			tuioCursor = cursorList.begin();
+		} else tuioCursor++;
+	}	
+}

+ 52 - 0
Modules/Contents/TUIO/Source/TuioTime.cpp

@@ -0,0 +1,52 @@
+/*
+ TUIO C++ Library - part of the reacTIVision project
+ http://reactivision.sourceforge.net/
+ 
+ Copyright (c) 2005-2009 Martin Kaltenbrunner <[email protected]>
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program 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 General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "TuioTime.h"
+using namespace TUIO;
+	
+long TuioTime::start_seconds = 0;
+long TuioTime::start_micro_seconds = 0;
+
+void TuioTime::initSession() {
+	TuioTime startTime = TuioTime::getSystemTime();
+	start_seconds = startTime.getSeconds();
+	start_micro_seconds = startTime.getMicroseconds();
+}
+
+TuioTime TuioTime::getSessionTime() {
+	return  (getSystemTime() - getStartTime());
+}
+
+TuioTime TuioTime::getStartTime() {
+	return TuioTime(start_seconds,start_micro_seconds);
+}
+
+TuioTime TuioTime::getSystemTime() {
+#ifdef WIN32
+	TuioTime systemTime(GetTickCount());
+#else
+	struct timeval tv;
+	struct timezone tz;
+	gettimeofday(&tv,&tz);
+	TuioTime systemTime(tv.tv_sec,tv.tv_usec);
+#endif	
+	return systemTime;
+}

+ 57 - 0
Modules/Contents/TUIO/Source/posix/NetworkingUtils.cpp

@@ -0,0 +1,57 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdio.h>
+
+
+
+NetworkInitializer::NetworkInitializer() {}
+
+NetworkInitializer::~NetworkInitializer() {}
+
+
+unsigned long GetHostByName( const char *name )
+{
+    unsigned long result = 0;
+
+    struct hostent *h = gethostbyname( name );
+    if( h ){
+        struct in_addr a;
+        memcpy( &a, h->h_addr_list[0], h->h_length );
+        result = ntohl(a.s_addr);
+    }
+
+    return result;
+}

+ 551 - 0
Modules/Contents/TUIO/Source/posix/UdpSocket.cpp

@@ -0,0 +1,551 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+#include <assert.h>
+#include <signal.h>
+#include <math.h>
+#include <errno.h>
+#include <string.h> // for memset
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h> // for sockaddr_in
+
+#include "ip/PacketListener.h"
+#include "ip/TimerListener.h"
+
+
+#if defined(__APPLE__) && !defined(_SOCKLEN_T)
+// pre system 10.3 didn have socklen_t
+typedef ssize_t socklen_t;
+#endif
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+    memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+    sockAddr.sin_family = AF_INET;
+
+	sockAddr.sin_addr.s_addr = 
+		(endpoint.address == IpEndpointName::ANY_ADDRESS)
+		? INADDR_ANY
+		: htonl( endpoint.address );
+
+	sockAddr.sin_port =
+		(endpoint.port == IpEndpointName::ANY_PORT)
+		? 0
+		: htons( endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+	return IpEndpointName( 
+		(sockAddr.sin_addr.s_addr == INADDR_ANY) 
+			? IpEndpointName::ANY_ADDRESS 
+			: ntohl( sockAddr.sin_addr.s_addr ),
+		(sockAddr.sin_port == 0)
+			? IpEndpointName::ANY_PORT
+			: ntohs( sockAddr.sin_port )
+		);
+}
+
+
+class UdpSocket::Implementation{
+	bool isBound_;
+	bool isConnected_;
+
+	int socket_;
+	struct sockaddr_in connectedAddr_;
+	struct sockaddr_in sendToAddr_;
+
+public:
+
+	Implementation()
+		: isBound_( false )
+		, isConnected_( false )
+		, socket_( -1 )
+	{
+		if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
+            throw std::runtime_error("unable to create udp socket\n");
+        }
+
+		int on=1;
+		setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on));
+		memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+        sendToAddr_.sin_family = AF_INET;
+	}
+
+	~Implementation()
+	{
+		if (socket_ != -1) close(socket_);
+	}
+
+	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+	{
+		assert( isBound_ );
+
+		// first connect the socket to the remote server
+        
+        struct sockaddr_in connectSockAddr;
+		SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+        // get the address
+
+        struct sockaddr_in sockAddr;
+        memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+        socklen_t length = sizeof(sockAddr);
+        if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+            throw std::runtime_error("unable to getsockname\n");
+        }
+        
+		if( isConnected_ ){
+			// reconnect to the connected address
+			
+			if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+				throw std::runtime_error("unable to connect udp socket\n");
+			}
+
+		}else{
+			// unconnect from the remote address
+		
+			struct sockaddr_in unconnectSockAddr;
+			memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
+			unconnectSockAddr.sin_family = AF_UNSPEC;
+			// address fields are zero
+			int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
+			if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
+				throw std::runtime_error("unable to un-connect udp socket\n");
+			}
+		}
+
+		return IpEndpointNameFromSockaddr( sockAddr );
+	}
+
+	void Connect( const IpEndpointName& remoteEndpoint )
+	{
+		SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+		isConnected_ = true;
+	}
+
+	void Send( const char *data, int size )
+	{
+		assert( isConnected_ );
+
+        send( socket_, data, size, 0 );
+	}
+
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+	{
+		sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+        sendToAddr_.sin_port = htons( remoteEndpoint.port );
+
+        sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+	}
+
+	void Bind( const IpEndpointName& localEndpoint )
+	{
+		struct sockaddr_in bindSockAddr;
+		SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+        if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+            throw std::runtime_error("unable to bind udp socket\n");
+        }
+
+		isBound_ = true;
+	}
+
+	bool IsBound() const { return isBound_; }
+
+    int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+	{
+		assert( isBound_ );
+
+		struct sockaddr_in fromAddr;
+        socklen_t fromAddrLen = sizeof(fromAddr);
+             	 
+        int result = recvfrom(socket_, data, size, 0,
+                    (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+		if( result < 0 )
+			return 0;
+
+		remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+		remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+		return result;
+	}
+
+	int Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+	impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+	delete impl_;
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+	return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+	impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, int size )
+{
+	impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+{
+	impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+	impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+	return impl_->IsBound();
+}
+
+int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+{
+	return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+	AttachedTimerListener( int id, int p, TimerListener *tl )
+		: initialDelayMs( id )
+		, periodMs( p )
+		, listener( tl ) {}
+	int initialDelayMs;
+	int periodMs;
+	TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls( 
+		const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+	return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+	multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+	signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+	std::vector< AttachedTimerListener > timerListeners_;
+
+	volatile bool break_;
+	int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
+
+	double GetCurrentTimeMs() const
+	{
+		struct timeval t;
+
+		gettimeofday( &t, 0 );
+
+		return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
+	}
+
+public:
+    Implementation()
+	{
+		if( pipe(breakPipe_) != 0 )
+			throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
+	}
+
+    ~Implementation()
+	{
+		close( breakPipe_[0] );
+		close( breakPipe_[1] );
+	}
+
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+		// we don't check that the same socket has been added multiple times, even though this is an error
+		socketListeners_.push_back( std::make_pair( listener, socket ) );
+	}
+
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = 
+				std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+		assert( i != socketListeners_.end() );
+
+		socketListeners_.erase( i );
+	}
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+	}
+
+	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+	}
+
+    void DetachPeriodicTimerListener( TimerListener *listener )
+	{
+		std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+		while( i != timerListeners_.end() ){
+			if( i->listener == listener )
+				break;
+			++i;
+		}
+
+		assert( i != timerListeners_.end() );
+
+		timerListeners_.erase( i );
+	}
+
+    void Run()
+	{
+		break_ = false;
+
+		// configure the master fd_set for select()
+
+		fd_set masterfds, tempfds;
+		FD_ZERO( &masterfds );
+		FD_ZERO( &tempfds );
+		
+		// in addition to listening to the inbound sockets we
+		// also listen to the asynchronous break pipe, so that AsynchronousBreak()
+		// can break us out of select() from another thread.
+		FD_SET( breakPipe_[0], &masterfds );
+		int fdmax = breakPipe_[0];		
+
+		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+				i != socketListeners_.end(); ++i ){
+
+			if( fdmax < i->second->impl_->Socket() )
+				fdmax = i->second->impl_->Socket();
+			FD_SET( i->second->impl_->Socket(), &masterfds );
+		}
+
+
+		// configure the timer queue
+		double currentTimeMs = GetCurrentTimeMs();
+
+		// expiry time ms, listener
+		std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+		for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+				i != timerListeners_.end(); ++i )
+			timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+		std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+		const int MAX_BUFFER_SIZE = 4098;
+		char *data = new char[ MAX_BUFFER_SIZE ];
+		IpEndpointName remoteEndpoint;
+
+		struct timeval timeout;
+
+		while( !break_ ){
+			tempfds = masterfds;
+
+			struct timeval *timeoutPtr = 0;
+			if( !timerQueue_.empty() ){
+				double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
+				if( timeoutMs < 0 )
+					timeoutMs = 0;
+			
+				// 1000000 microseconds in a second
+				timeout.tv_sec = (long)(timeoutMs * .001);
+				timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000);
+				timeoutPtr = &timeout;
+			}
+
+			if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){
+   				if (!break_) throw std::runtime_error("select failed\n");
+				else break;
+			}
+
+			if ( FD_ISSET( breakPipe_[0], &tempfds ) ){
+				// clear pending data from the asynchronous break pipe
+				char c;
+				ssize_t ret; 
+				ret = read( breakPipe_[0], &c, 1 );
+			}
+			
+			if( break_ )
+				break;
+
+			for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+					i != socketListeners_.end(); ++i ){
+
+				if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
+
+					int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+					if( size > 0 ){
+						i->first->ProcessPacket( data, size, remoteEndpoint );
+						if( break_ )
+							break;
+					}
+				}
+			}
+
+			// execute any expired timers
+			currentTimeMs = GetCurrentTimeMs();
+			bool resort = false;
+			for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+					i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+				i->second.listener->TimerExpired();
+				if( break_ )
+					break;
+
+				i->first += i->second.periodMs;
+				resort = true;
+			}
+			if( resort )
+				std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+		}
+
+		delete [] data;
+	}
+
+    void Break()
+	{
+		break_ = true;
+	}
+
+    void AsynchronousBreak()
+	{
+		break_ = true;
+
+		// Send a termination message to the asynchronous break pipe, so select() will return
+		ssize_t ret;
+		ret = write( breakPipe_[1], "!", 1 );
+	}
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+	impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{	
+	delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+	impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+	impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+	assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+	multiplexerInstanceToAbortWithSigInt_ = this;
+	signal( SIGINT, InterruptSignalHandler );
+	impl_->Run();
+	signal( SIGINT, SIG_DFL );
+	multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+	impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+	impl_->AsynchronousBreak();
+}
+

+ 88 - 0
Modules/Contents/TUIO/Source/win32/NetworkingUtils.cpp

@@ -0,0 +1,88 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+
+#include <winsock2.h>   // this must come first to prevent errors with MSVC7
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+static LONG initCount_ = 0;
+static bool winsockInitialized_ = false;
+
+NetworkInitializer::NetworkInitializer()
+{
+    if( InterlockedIncrement( &initCount_ ) == 1 ){
+        // there is a race condition here if one thread tries to access
+        // the library while another is still initializing it. 
+        // i can't think of an easy way to fix it so i'm telling you here
+        // incase you need to init the library from two threads at once.
+        // this is why the header file advises to instantiate one of these 
+        // in main() so that the initialization happens globally
+
+        // initialize winsock
+	    WSAData wsaData;
+	    int nCode = WSAStartup(MAKEWORD(1, 1), &wsaData);
+	    if( nCode != 0 ){
+	        //std::cout << "WSAStartup() failed with error code " << nCode << "\n";
+        }else{
+            winsockInitialized_ = true;
+        }
+    }
+}
+
+
+NetworkInitializer::~NetworkInitializer()
+{
+    if( InterlockedDecrement( &initCount_ ) == 0 ){
+        if( winsockInitialized_ ){
+            WSACleanup();
+            winsockInitialized_ = false;
+        }
+    }
+}
+
+
+unsigned long GetHostByName( const char *name )
+{
+    NetworkInitializer networkInitializer;
+
+    unsigned long result = 0;
+
+    struct hostent *h = gethostbyname( name );
+    if( h ){
+        struct in_addr a;
+        memcpy( &a, h->h_addr_list[0], h->h_length );
+        result = ntohl(a.s_addr);
+    }
+
+    return result;
+}

+ 523 - 0
Modules/Contents/TUIO/Source/win32/UdpSocket.cpp

@@ -0,0 +1,523 @@
+/*
+	oscpack -- Open Sound Control packet manipulation library
+	http://www.audiomulch.com/~rossb/oscpack
+
+	Copyright (c) 2004-2005 Ross Bencina <[email protected]>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+
+#include <winsock2.h>   // this must come first to prevent errors with MSVC7
+#include <windows.h>
+#include <mmsystem.h>   // for timeGetTime()
+
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+#include <assert.h>
+#include <signal.h>
+
+#include "ip/NetworkingUtils.h"
+#include "ip/PacketListener.h"
+#include "ip/TimerListener.h"
+
+
+typedef int socklen_t;
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+    memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+    sockAddr.sin_family = AF_INET;
+
+	sockAddr.sin_addr.s_addr = 
+		(endpoint.address == IpEndpointName::ANY_ADDRESS)
+		? INADDR_ANY
+		: htonl( endpoint.address );
+
+	sockAddr.sin_port =
+		(endpoint.port == IpEndpointName::ANY_PORT)
+		? (short)0
+		: htons( (short)endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+	return IpEndpointName( 
+		(sockAddr.sin_addr.s_addr == INADDR_ANY) 
+			? IpEndpointName::ANY_ADDRESS 
+			: ntohl( sockAddr.sin_addr.s_addr ),
+		(sockAddr.sin_port == 0)
+			? IpEndpointName::ANY_PORT
+			: ntohs( sockAddr.sin_port )
+		);
+}
+
+
+class UdpSocket::Implementation{
+    NetworkInitializer networkInitializer_;
+
+	bool isBound_;
+	bool isConnected_;
+
+	SOCKET socket_;
+	struct sockaddr_in connectedAddr_;
+	struct sockaddr_in sendToAddr_;
+
+public:
+
+	Implementation()
+		: isBound_( false )
+		, isConnected_( false )
+		, socket_( INVALID_SOCKET )
+	{
+		if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == INVALID_SOCKET ){
+            throw std::runtime_error("unable to create udp socket\n");
+        }
+
+		int on=1;
+		setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on));
+		memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+        sendToAddr_.sin_family = AF_INET;
+	}
+
+	~Implementation()
+	{
+		if (socket_ != INVALID_SOCKET) closesocket(socket_);
+	}
+
+	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+	{
+		assert( isBound_ );
+
+		// first connect the socket to the remote server
+        
+        struct sockaddr_in connectSockAddr;
+		SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+        // get the address
+
+        struct sockaddr_in sockAddr;
+        memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+        socklen_t length = sizeof(sockAddr);
+        if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+            throw std::runtime_error("unable to getsockname\n");
+        }
+        
+		if( isConnected_ ){
+			// reconnect to the connected address
+			
+			if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+				throw std::runtime_error("unable to connect udp socket\n");
+			}
+
+		}else{
+			// unconnect from the remote address
+		
+			struct sockaddr_in unconnectSockAddr;
+			SockaddrFromIpEndpointName( unconnectSockAddr, IpEndpointName() );
+
+			if( connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)) < 0 
+					&& WSAGetLastError() != WSAEADDRNOTAVAIL ){
+				throw std::runtime_error("unable to un-connect udp socket\n");
+			}
+		}
+
+		return IpEndpointNameFromSockaddr( sockAddr );
+	}
+
+	void Connect( const IpEndpointName& remoteEndpoint )
+	{
+		SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+		isConnected_ = true;
+	}
+
+	void Send( const char *data, int size )
+	{
+		assert( isConnected_ );
+
+        send( socket_, data, size, 0 );
+	}
+
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+	{
+		sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+        sendToAddr_.sin_port = htons( (short)remoteEndpoint.port );
+
+        sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+	}
+
+	void Bind( const IpEndpointName& localEndpoint )
+	{
+		struct sockaddr_in bindSockAddr;
+		SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+        if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+            throw std::runtime_error("unable to bind udp socket\n");
+        }
+
+		isBound_ = true;
+	}
+
+	bool IsBound() const { return isBound_; }
+
+    int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+	{
+		assert( isBound_ );
+
+		struct sockaddr_in fromAddr;
+        socklen_t fromAddrLen = sizeof(fromAddr);
+             	 
+        int result = recvfrom(socket_, data, size, 0,
+                    (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+		if( result < 0 )
+			return 0;
+
+		remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+		remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+		return result;
+	}
+
+	SOCKET& Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+	impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+	delete impl_;
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+	return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+	impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, int size )
+{
+	impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+{
+	impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+	impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+	return impl_->IsBound();
+}
+
+int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+{
+	return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+	AttachedTimerListener( int id, int p, TimerListener *tl )
+		: initialDelayMs( id )
+		, periodMs( p )
+		, listener( tl ) {}
+	int initialDelayMs;
+	int periodMs;
+	TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls( 
+		const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+	return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+	multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+	signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+    NetworkInitializer networkInitializer_;
+
+	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+	std::vector< AttachedTimerListener > timerListeners_;
+
+	volatile bool break_;
+	HANDLE breakEvent_;
+
+	double GetCurrentTimeMs() const
+	{
+		return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
+	}
+
+public:
+    Implementation()
+	{
+		breakEvent_ = CreateEvent( NULL, FALSE, FALSE, NULL );
+	}
+
+    ~Implementation()
+	{
+		CloseHandle( breakEvent_ );
+	}
+
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+		// we don't check that the same socket has been added multiple times, even though this is an error
+		socketListeners_.push_back( std::make_pair( listener, socket ) );
+	}
+
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = 
+				std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+		assert( i != socketListeners_.end() );
+
+		socketListeners_.erase( i );
+	}
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+	}
+
+	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+	}
+
+    void DetachPeriodicTimerListener( TimerListener *listener )
+	{
+		std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+		while( i != timerListeners_.end() ){
+			if( i->listener == listener )
+				break;
+			++i;
+		}
+
+		assert( i != timerListeners_.end() );
+
+		timerListeners_.erase( i );
+	}
+
+    void Run()
+	{
+		break_ = false;
+
+		// prepare the window events which we use to wake up on incoming data
+		// we use this instead of select() primarily to support the AsyncBreak() 
+		// mechanism.
+
+		std::vector<HANDLE> events( socketListeners_.size() + 1, 0 );
+		int j=0;
+		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+				i != socketListeners_.end(); ++i, ++j ){
+
+			HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
+			WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
+			events[j] = event;
+		}
+
+
+		events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
+
+		
+		// configure the timer queue
+		double currentTimeMs = GetCurrentTimeMs();
+
+		// expiry time ms, listener
+		std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+		for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+				i != timerListeners_.end(); ++i )
+			timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+		std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+		const int MAX_BUFFER_SIZE = 4098;
+		char *data = new char[ MAX_BUFFER_SIZE ];
+		IpEndpointName remoteEndpoint;
+
+		while( !break_ ){
+
+			double currentTimeMs = GetCurrentTimeMs();
+
+            DWORD waitTime = INFINITE;
+            if( !timerQueue_.empty() ){
+
+                waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
+                            ? timerQueue_.front().first - currentTimeMs
+                            : 0 );
+            }
+
+			DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
+			if( break_ )
+				break;
+
+			if( waitResult != WAIT_TIMEOUT ){
+				for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
+					int size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+					if( size > 0 ){
+						socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint );
+						if( break_ )
+							break;
+					}
+				}
+			}
+
+			// execute any expired timers
+			currentTimeMs = GetCurrentTimeMs();
+			bool resort = false;
+			for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+					i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+				i->second.listener->TimerExpired();
+				if( break_ )
+					break;
+
+				i->first += i->second.periodMs;
+				resort = true;
+			}
+			if( resort )
+				std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+		}
+
+		delete [] data;
+
+		// free events
+		j = 0;
+		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+				i != socketListeners_.end(); ++i, ++j ){
+
+			WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
+			CloseHandle( events[j] );
+			unsigned long enableNonblocking = 0;
+			ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking );  // make the socket blocking again
+		}
+	}
+
+    void Break()
+	{
+		break_ = true;
+	}
+
+    void AsynchronousBreak()
+	{
+		break_ = true;
+		SetEvent( breakEvent_ );
+	}
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+	impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{	
+	delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+	impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+	impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+	assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+	multiplexerInstanceToAbortWithSigInt_ = this;
+	signal( SIGINT, InterruptSignalHandler );
+	impl_->Run();
+	signal( SIGINT, SIG_DFL );
+	multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+	impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+	impl_->AsynchronousBreak();
+}
+

+ 340 - 0
Modules/Contents/TUIO/TUIO_LICENSE.txt

@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.