From 5e84b7f6a2ffeb783f269052a899f0f05643fc9f Mon Sep 17 00:00:00 2001 From: Jonathan Bosson Date: Thu, 16 Feb 2017 12:52:39 -0700 Subject: [PATCH] new touch module with TUIO library to make OpenSpace tuio-aware --- apps/OpenSpace/main.cpp | 4 + data/scene/atmosphereearth.scene | 3 +- data/scene/lodglobes/earth/earth.mod | 4 + data/scene/newhorizons.scene | 2 +- data/web/log/script.js | 2 +- data/web/log/style.css | 9 - modules/touch/CMakeLists.txt | 43 + modules/touch/ext/.vs/libTUIO2/v14/.suo | Bin 0 -> 5632 bytes modules/touch/ext/libTUIO2/CMakeLists.txt | 63 ++ modules/touch/ext/libTUIO2/TUIO2/Doxyfile | 15 + .../touch/ext/libTUIO2/TUIO2/FlashSender.cpp | 650 ++++++++++++++ .../touch/ext/libTUIO2/TUIO2/FlashSender.h | 215 +++++ modules/touch/ext/libTUIO2/TUIO2/LibExport.h | 36 + .../touch/ext/libTUIO2/TUIO2/OscReceiver.cpp | 60 ++ .../touch/ext/libTUIO2/TUIO2/OscReceiver.h | 97 +++ modules/touch/ext/libTUIO2/TUIO2/OscSender.h | 90 ++ .../touch/ext/libTUIO2/TUIO2/TcpReceiver.cpp | 264 ++++++ .../touch/ext/libTUIO2/TUIO2/TcpReceiver.h | 102 +++ .../touch/ext/libTUIO2/TUIO2/TcpSender.cpp | 303 +++++++ modules/touch/ext/libTUIO2/TUIO2/TcpSender.h | 126 +++ .../touch/ext/libTUIO2/TUIO2/TuioBounds.cpp | 94 +++ modules/touch/ext/libTUIO2/TUIO2/TuioBounds.h | 206 +++++ .../touch/ext/libTUIO2/TUIO2/TuioClient.cpp | 520 ++++++++++++ modules/touch/ext/libTUIO2/TUIO2/TuioClient.h | 241 ++++++ .../ext/libTUIO2/TUIO2/TuioComponent.cpp | 245 ++++++ .../touch/ext/libTUIO2/TUIO2/TuioComponent.h | 287 +++++++ .../ext/libTUIO2/TUIO2/TuioDispatcher.cpp | 165 ++++ .../touch/ext/libTUIO2/TUIO2/TuioDispatcher.h | 169 ++++ .../touch/ext/libTUIO2/TUIO2/TuioListener.h | 80 ++ .../touch/ext/libTUIO2/TUIO2/TuioManager.cpp | 575 +++++++++++++ .../touch/ext/libTUIO2/TUIO2/TuioManager.h | 601 +++++++++++++ .../touch/ext/libTUIO2/TUIO2/TuioObject.cpp | 311 +++++++ modules/touch/ext/libTUIO2/TUIO2/TuioObject.h | 341 ++++++++ .../touch/ext/libTUIO2/TUIO2/TuioPoint.cpp | 124 +++ modules/touch/ext/libTUIO2/TUIO2/TuioPoint.h | 213 +++++ .../touch/ext/libTUIO2/TUIO2/TuioPointer.cpp | 132 +++ .../touch/ext/libTUIO2/TUIO2/TuioPointer.h | 263 ++++++ .../touch/ext/libTUIO2/TUIO2/TuioServer.cpp | 329 ++++++++ modules/touch/ext/libTUIO2/TUIO2/TuioServer.h | 210 +++++ modules/touch/ext/libTUIO2/TUIO2/TuioSource.h | 244 ++++++ .../touch/ext/libTUIO2/TUIO2/TuioSymbol.cpp | 91 ++ modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.h | 160 ++++ modules/touch/ext/libTUIO2/TUIO2/TuioTime.cpp | 160 ++++ modules/touch/ext/libTUIO2/TUIO2/TuioTime.h | 222 +++++ .../touch/ext/libTUIO2/TUIO2/TuioToken.cpp | 69 ++ modules/touch/ext/libTUIO2/TUIO2/TuioToken.h | 151 ++++ .../touch/ext/libTUIO2/TUIO2/UdpReceiver.cpp | 92 ++ .../touch/ext/libTUIO2/TUIO2/UdpReceiver.h | 77 ++ .../touch/ext/libTUIO2/TUIO2/UdpSender.cpp | 89 ++ modules/touch/ext/libTUIO2/TUIO2/UdpSender.h | 93 ++ .../ext/libTUIO2/TUIO2/WebSockSender.cpp | 286 +++++++ .../touch/ext/libTUIO2/TUIO2/WebSockSender.h | 121 +++ modules/touch/ext/libTUIO2/oscpack/CHANGES | 159 ++++ modules/touch/ext/libTUIO2/oscpack/LICENSE | 34 + modules/touch/ext/libTUIO2/oscpack/README | 150 ++++ modules/touch/ext/libTUIO2/oscpack/TODO | 52 ++ .../libTUIO2/oscpack/ip/IpEndpointName.cpp | 88 ++ .../ext/libTUIO2/oscpack/ip/IpEndpointName.h | 83 ++ .../ext/libTUIO2/oscpack/ip/NetworkingUtils.h | 56 ++ .../ext/libTUIO2/oscpack/ip/PacketListener.h | 50 ++ .../ext/libTUIO2/oscpack/ip/TimerListener.h | 47 ++ .../touch/ext/libTUIO2/oscpack/ip/UdpSocket.h | 176 ++++ .../oscpack/ip/posix/NetworkingUtils.cpp | 64 ++ .../libTUIO2/oscpack/ip/posix/UdpSocket.cpp | 602 +++++++++++++ .../oscpack/ip/win32/NetworkingUtils.cpp | 95 +++ .../libTUIO2/oscpack/ip/win32/UdpSocket.cpp | 571 +++++++++++++ .../osc/MessageMappingOscPacketListener.h | 80 ++ .../ext/libTUIO2/oscpack/osc/OscException.h | 62 ++ .../libTUIO2/oscpack/osc/OscHostEndianness.h | 127 +++ .../oscpack/osc/OscOutboundPacketStream.cpp | 683 +++++++++++++++ .../oscpack/osc/OscOutboundPacketStream.h | 154 ++++ .../libTUIO2/oscpack/osc/OscPacketListener.h | 79 ++ .../oscpack/osc/OscPrintReceivedElements.cpp | 261 ++++++ .../oscpack/osc/OscPrintReceivedElements.h | 54 ++ .../oscpack/osc/OscReceivedElements.cpp | 796 ++++++++++++++++++ .../oscpack/osc/OscReceivedElements.h | 548 ++++++++++++ .../ext/libTUIO2/oscpack/osc/OscTypes.cpp | 52 ++ .../touch/ext/libTUIO2/oscpack/osc/OscTypes.h | 240 ++++++ modules/touch/include.cmake | 1 + modules/touch/include/TuioEar.h | 62 ++ modules/touch/src/TuioEar.cpp | 89 ++ modules/touch/touchmodule.cpp | 33 + modules/touch/touchmodule.h | 39 + openspace.cfg | 2 +- 84 files changed, 14625 insertions(+), 13 deletions(-) create mode 100644 modules/touch/CMakeLists.txt create mode 100644 modules/touch/ext/.vs/libTUIO2/v14/.suo create mode 100644 modules/touch/ext/libTUIO2/CMakeLists.txt create mode 100644 modules/touch/ext/libTUIO2/TUIO2/Doxyfile create mode 100644 modules/touch/ext/libTUIO2/TUIO2/FlashSender.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/FlashSender.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/LibExport.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/OscReceiver.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/OscReceiver.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/OscSender.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TcpSender.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TcpSender.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioBounds.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioBounds.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioClient.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioClient.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioComponent.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioComponent.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioListener.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioManager.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioManager.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioObject.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioObject.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioPoint.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioPoint.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioPointer.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioPointer.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioServer.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioServer.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioSource.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioTime.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioTime.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioToken.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/TuioToken.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/UdpSender.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/UdpSender.h create mode 100644 modules/touch/ext/libTUIO2/TUIO2/WebSockSender.cpp create mode 100644 modules/touch/ext/libTUIO2/TUIO2/WebSockSender.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/CHANGES create mode 100644 modules/touch/ext/libTUIO2/oscpack/LICENSE create mode 100644 modules/touch/ext/libTUIO2/oscpack/README create mode 100644 modules/touch/ext/libTUIO2/oscpack/TODO create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/NetworkingUtils.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/PacketListener.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/TimerListener.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/UdpSocket.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/posix/NetworkingUtils.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/posix/UdpSocket.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/win32/NetworkingUtils.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/ip/win32/UdpSocket.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/MessageMappingOscPacketListener.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscException.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscHostEndianness.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscPacketListener.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.h create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.cpp create mode 100644 modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.h create mode 100644 modules/touch/include.cmake create mode 100644 modules/touch/include/TuioEar.h create mode 100644 modules/touch/src/TuioEar.cpp create mode 100644 modules/touch/touchmodule.cpp create mode 100644 modules/touch/touchmodule.h diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 90fe52a028..a0c5f2b6d8 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -33,6 +33,8 @@ #include #include +#include + sgct::Engine* _sgctEngine; void mainInitFunc(); @@ -84,6 +86,8 @@ namespace { int main(int argc, char** argv) { auto glVersion = supportedOpenGLVersion(); + TuioEar *ear = new TuioEar(); + // create the OpenSpace engine and get arguments for the sgct engine std::vector sgctArguments; const bool success = openspace::OpenSpaceEngine::create( diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index 914c040ca7..598240dc5f 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -41,7 +41,8 @@ return { CommonFolder = "common", Camera = { Focus = "Earth", - Position = {1, 0, 0, 2}, + Position = {1, 0, 0}, + Rotation = {0.250635, -0.028751, 0.879269, 0.404030}, }, Modules = { "sun", diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index 1df4498c85..9bd4c8277b 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -71,6 +71,10 @@ return { }, Enabled = true, }, + { + FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms", + Name = "ESRI", + }, { Type = "Temporal", Name = "Temporal VIIRS SNPP", diff --git a/data/scene/newhorizons.scene b/data/scene/newhorizons.scene index ca5e4106c9..36084aa2a4 100644 --- a/data/scene/newhorizons.scene +++ b/data/scene/newhorizons.scene @@ -1,4 +1,4 @@ -UseAccurateNewHorizonsKernels = true +UseAccurateNewHorizonsKernels = false -- TextureResolution = "low" TextureResolution = "med" -- TextureResolution = "high" diff --git a/data/web/log/script.js b/data/web/log/script.js index ac198a1189..fea743117f 100644 --- a/data/web/log/script.js +++ b/data/web/log/script.js @@ -1,4 +1,4 @@ -var levels = ['trace', 'debug', 'info', 'warning', 'error', 'fatal']; +var levels = ['debug', 'info', 'warning', 'error', 'fatal']; var filterLevel = 0; function insertAfter(newNode, referenceNode) { diff --git a/data/web/log/style.css b/data/web/log/style.css index 80a17198ed..3aa140b30e 100644 --- a/data/web/log/style.css +++ b/data/web/log/style.css @@ -27,15 +27,6 @@ label { margin-right: 0.5em; } -.log-level-trace { - color: #eeeeee; - background-color: #aaaaaa; - border-bottom: 1px solid #eaeaea; -} -.log-level-trace td:first-child { - border-left: 10px solid #eaeaea; -} - .log-level-debug { background-color: #bbdda9; border-bottom: 1px solid #7bc142; diff --git a/modules/touch/CMakeLists.txt b/modules/touch/CMakeLists.txt new file mode 100644 index 0000000000..c2e655c546 --- /dev/null +++ b/modules/touch/CMakeLists.txt @@ -0,0 +1,43 @@ +######################################################################################### +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# 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. # +# # +# 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(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/TuioEar.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/TuioEar.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +create_new_module( + "Touch" + touch_module + ${HEADER_FILES} ${SOURCE_FILES} +) + +include_external_library(${touch_module} libTUIO2 ${CMAKE_CURRENT_SOURCE_DIR}/ext/libTUIO2) \ No newline at end of file diff --git a/modules/touch/ext/.vs/libTUIO2/v14/.suo b/modules/touch/ext/.vs/libTUIO2/v14/.suo new file mode 100644 index 0000000000000000000000000000000000000000..cc39013d5358149db3c8b246adf0aaf2dfa512c5 GIT binary patch literal 5632 zcmeHL&ubGw6#h1~wMCE=O2FcwU@smN?9oFH#vTenO4HtQuuZE;P0}CPgcf?}LGa>5 zp=Vn?7wy%9M^O>rMn z;Dbr@;kZ160Z+d}JY?xGaE`e8j?3k;y8Cz&4WNrGFpE`QF2*p09NP_S$(2n*1pOyI zm;W0#a zhiq}9!dCY=j*w&XQg*1z=ot|I+bXTx{p~ei6<5FR0D9X3|1$qyJzh8YKg8JEseVY> zkpGU?L!L0Ni%NeR^WRY}+d0%#>Ko{k{I~Pgo~V7mpZB5%J?pdlLE9S^kbjkm`gSWO zMeEF`Z?ydGkB8n^b+8I+fz!?(6O4gI!1Kq+-lumq; z6sbIG9#Ju@nXx$A1@bPlFH5N4}thkmp6n-)OAm*-re=_o6_}Rs4wWFO+SxdA! z({5jXtLyF+xgh_Q0j+!UdB^O3^V}`hFw31!`)3+OKJ_Ong@aP&>6=Smziofqe|X{3 K-b=04=KUY%-t)5n literal 0 HcmV?d00001 diff --git a/modules/touch/ext/libTUIO2/CMakeLists.txt b/modules/touch/ext/libTUIO2/CMakeLists.txt new file mode 100644 index 0000000000..4fe0af8650 --- /dev/null +++ b/modules/touch/ext/libTUIO2/CMakeLists.txt @@ -0,0 +1,63 @@ +######################################################################################### +# # +# OpenSpace # +# # +# Copyright (c) 2014-2016 # +# # +# 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. # +# # +# 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. # +######################################################################################### + +project(libTUIO2) +message(STATUS "Generating libTUIO2 project") + +add_library(libTUIO2 + ${PROJECT_SOURCE_DIR}/TUIO2/WebSockSender.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/UdpSender.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/UdpReceiver.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioToken.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioTime.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioSymbol.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioServer.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioPointer.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioPoint.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioObject.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioManager.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioDispatcher.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioComponent.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioClient.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TuioBounds.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TcpSender.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/TcpReceiver.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/OscReceiver.cpp + ${PROJECT_SOURCE_DIR}/TUIO2/FlashSender.cpp + + ${PROJECT_SOURCE_DIR}/oscpack/ip/IpEndpointName.cpp + + #if (WIN32) + ${PROJECT_SOURCE_DIR}/oscpack/ip/win32/NetworkingUtils.cpp + ${PROJECT_SOURCE_DIR}/oscpack/ip/win32/UdpSocket.cpp + #else (WIN32) + #${PROJECT_SOURCE_DIR}/oscpack/ip/posix/NetworkingUtils.cpp + #${PROJECT_SOURCE_DIR}/oscpack/ip/posix/UdpSocket.cpp + #endif () + ${PROJECT_SOURCE_DIR}/oscpack/osc/OscTypes.cpp + ${PROJECT_SOURCE_DIR}/oscpack/osc/OscReceivedElements.cpp + ${PROJECT_SOURCE_DIR}/oscpack/osc/OscPrintReceivedElements.cpp + ${PROJECT_SOURCE_DIR}/oscpack/osc/OscOutboundPacketStream.cpp +) +target_include_directories(libTUIO2 PUBLIC ${PROJECT_SOURCE_DIR}) \ No newline at end of file diff --git a/modules/touch/ext/libTUIO2/TUIO2/Doxyfile b/modules/touch/ext/libTUIO2/TUIO2/Doxyfile new file mode 100644 index 0000000000..123a23ec35 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/Doxyfile @@ -0,0 +1,15 @@ +# Doxyfile 1.5.6 +# Project related configuration options +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "TUIO2 C++ Developer API" +# Build related configuration options +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +# configuration options related to the HTML output +GENERATE_HTML = YES +HTML_OUTPUT = ../doc +HTML_FILE_EXTENSION = .html +GENERATE_TREEVIEW = YES +GENERATE_LATEX = NO diff --git a/modules/touch/ext/libTUIO2/TUIO2/FlashSender.cpp b/modules/touch/ext/libTUIO2/TUIO2/FlashSender.cpp new file mode 100644 index 0000000000..d3e9f2237b --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/FlashSender.cpp @@ -0,0 +1,650 @@ +#include "FlashSender.h" + +// Copyright (C) 2009 Georg Kaindl +// This file is part of Touché. +// +// Touché is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// Touché is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with Touché. If not, see . + + +#include +#include +#include +#include + +#if !defined(WIN32) +#include +#include +#include +#include + +#if defined(__APPLE__) +#include +#include +#else +#include +#endif + +#endif + +#define FLASHLC_SHM_SIZE (64528) // This is what Flash always uses as size +#define FLASHLC_SHM_LISTENERS_OFFSET (40976) // Another "magic number" +#define MAX_LISTENER_NAME_LEN (64) +#define MAX_LISTENER_METHOD_NAME (64) + +#define PROTOCOL_NAME ("localhost") + +#define WIN32_SEMAPHORE_NAME TEXT("MacromediaMutexOmega") +#define WIN32_SHMEM_NAME TEXT("MacromediaFMOmega") +#define POSIX_SEMAPHORE_NAME ("MacromediaSemaphoreDig") +#define POSIX_SEMAPHORE_INITIAL_VALUE (10) + +#define AMF_TYPE_STRING (0x02) +#define AMF_TYPE_AMF3OBJ (0x11) +#define AMF3_TYPE_BYTEARRAY (0x0C) + +#define AMF_ENVELOPE_LEN (16) +#define AMF_ENVELOPE_TIMESTAMP_POS (8) +#define AMF_ENVELOPE_SIZE_POS (12) + +void _TFLCSLockSemaphore(TFLCSLocalConnection_t* connection); +void _TFLCSUnlockSemaphore(TFLCSLocalConnection_t* connection); + +// returns non-zero if the given connection is in a usable state, zero otherwise +int _TFLCSConnectionStructureIsValidForUse(TFLCSLocalConnection_t* connection); + +// On WIN32, we cannot create the shared memory and semaphore ourselves, because +// we don't know the exact parameters. Therefore, if Flash is not running when we +// try to connect, we'll try again whenever we should send data, until we finally +// manage to connect. +int _TFLCSDelayedConnect(TFLCSLocalConnection_t* connection); + +#define ENSURE_CONNECTION_UP(c, rv) do { if (!(c)->open && !_TFLCSDelayedConnect((c))) return (rv); } while (0) + +u_int32_t _TFLCSKnownDarwinKeys[] = { 0x53414e44, 0 }; + +TFLCSError_t TFLCSErrno = TFLCSErrorSuccess; + +TFLCSLocalConnection_t* TFLCSConnect(const char* listenerName, + const char* listenerMethod, + void* shmemKey, + void* semaphoreKey) +{ + TFLCSLocalConnection_t* connection = NULL; + + if (NULL == listenerName || NULL == listenerMethod || + strlen(listenerName) > TFLCS_LISTENER_NAME_MAX_LEN || + strlen(listenerMethod) > TFLCS_LISTENER_METHOD_MAX_LEN) { + TFLCSErrno = TFLCSErrorInvalidArgument; + return NULL; + } + + connection = (TFLCSLocalConnection_t*)malloc(sizeof(TFLCSLocalConnection_t)); + if (NULL == connection) { + TFLCSErrno = TFLCSErrorOutOfMemory; + goto errorReturn; + } + + connection->open = 0; + +#if defined(WIN32) + // initialize the structure + connection->semaphore = NULL; + connection->mapFile = NULL; + connection->mapAddress = NULL; + connection->data = NULL; + + _TFLCSDelayedConnect(connection); +#else + // initialize the structure + connection->semaphore = (sem_t*)SEM_FAILED; + connection->shmid = -1; + connection->data = (char*)-1; + + // we don't need a delayed connect on MacOS X, so let's just connect now! + key_t key; + char* semName; + + if (NULL != shmemKey) + key = *(key_t*)shmemKey; + else { + key_t* guessedKey = (key_t*)TFLCSGuessShmemKey(); + if (NULL != guessedKey) + key = *(key_t*)guessedKey; + else { + TFLCSErrno = TFLCSErrorShmemKeyNotFound; + goto errorReturn; + } + } + + if (NULL != semaphoreKey) + semName = (char*)semaphoreKey; + else + semName = (char*)POSIX_SEMAPHORE_NAME; + + connection->semaphore = sem_open(semName, + O_CREAT, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, + POSIX_SEMAPHORE_INITIAL_VALUE); + if ((sem_t*)SEM_FAILED == connection->semaphore) { + TFLCSErrno = TFLCSErrorSemaphoreCreationFailed; + goto errorReturn; + } + + if (-1 == (connection->shmid = shmget(key, FLASHLC_SHM_SIZE, 0666 | IPC_CREAT))) { + TFLCSErrno = TFLCSErrorShmemIDNotFound; + goto errorReturn; + } + + connection->data = (char*)shmat(connection->shmid, NULL, 0); + if ((char*)-1 == connection->data) { + TFLCSErrno = TFLCSErrorShmemOpeningFailed; + goto errorReturn; + } + + connection->open = 1; + + // initialize the memory region the way Flash likes it :-) + connection->data[0] = 1; + connection->data[4] = 1; +#endif + + strncpy(connection->listenerName, listenerName, TFLCS_LISTENER_NAME_MAX_LEN); + strncpy(connection->listenerMethod, listenerMethod, TFLCS_LISTENER_METHOD_MAX_LEN); + + return connection; + +errorReturn: + TFLCSDisconnect(connection); + + return NULL; +} + +void TFLCSDisconnect(TFLCSLocalConnection_t* connection) +{ + if (NULL != connection) { +#if defined(WIN32) + if (NULL != connection->semaphore) + CloseHandle(connection->semaphore); + + if (NULL != connection->mapAddress) + UnmapViewOfFile(connection->mapAddress); + + if (NULL != connection->mapFile) + CloseHandle(connection->mapFile); +#else + if ((sem_t*)SEM_FAILED != connection->semaphore) + sem_close(connection->semaphore); + + if ((char*)-1 != connection->data) + (void)shmdt(connection->data); +#endif + free(connection); + } +} + +void TFLCSChangeListenerName(TFLCSLocalConnection_t* connection, const char* newListenerName) +{ + if (NULL != connection && NULL != newListenerName) + strncpy(connection->listenerName, newListenerName, TFLCS_LISTENER_NAME_MAX_LEN); +} + +void TFLCSChangeMethodName(TFLCSLocalConnection_t* connection, const char* newMethodName) +{ + if (NULL != connection && NULL != newMethodName) + strncpy(connection->listenerMethod, newMethodName, TFLCS_LISTENER_METHOD_MAX_LEN); +} + +int TFLCSConnectionHasConnectedClient(TFLCSLocalConnection_t* connection) +{ + ENSURE_CONNECTION_UP(connection, 0); + + int retval = 0; + + if (_TFLCSConnectionStructureIsValidForUse(connection)) { + _TFLCSLockSemaphore(connection); + + int c, l = strlen(connection->listenerName); + char* p = &connection->data[FLASHLC_SHM_LISTENERS_OFFSET]; + + while (!retval && (char)0 != *p) { + c = strlen(p) + 1; + if (0 == strncmp(p, connection->listenerName, l)) + retval = 1; + + p += c; + } + + _TFLCSUnlockSemaphore(connection); + } + + return retval; +} + +int TFLCSGetConnectedConnectionNames(TFLCSLocalConnection_t* connection, char* dest, int destLen) +{ + ENSURE_CONNECTION_UP(connection, 0); + + int retval = 0; + + if (NULL != dest && 0 < destLen && _TFLCSConnectionStructureIsValidForUse(connection)) { + _TFLCSLockSemaphore(connection); + + int c, i=0; + char* p = &connection->data[FLASHLC_SHM_LISTENERS_OFFSET]; + + while ((char)0 != *p && destLen > 0) { + c = strlen(p) + 1; + if (0 == (i % 3)) { + strncpy(dest, p, destLen < c ? destLen : c); + destLen -= c; + dest += c; + } + + p += c; + i++; + } + + retval = i/3; + + _TFLCSUnlockSemaphore(connection); + } + + return retval; +} + +void* TFLCSGuessShmemKey() +{ +#if defined(WIN32) + return (void*)WIN32_SHMEM_NAME; +#else + static int found = 0; + static key_t key; + + // first, try our known keys + int i = 0; + while(!found && _TFLCSKnownDarwinKeys[i]) { + if (-1 != shmget(_TFLCSKnownDarwinKeys[i], FLASHLC_SHM_SIZE, 0)) { + found = 1; + key = _TFLCSKnownDarwinKeys[i]; + } + + i++; + } + + /* // magic numbers for MacOS X 10.5, probably later and earlier versions too, dunno... + int minid = 0xffff; + int maxid = 0x500000; + struct shmid_ds shm_info; + for (i=minid; !found && i<=maxid; i++) { + if (shmctl(i, IPC_STAT, &shm_info) < 0) + continue; + + if (FLASHLC_SHM_SIZE == shm_info.shm_segsz) { + found = 1; + key = shm_info.shm_perm._key; + } + } */ + + // if we didn't find anything, set the key to a reasonable guess + // this is necessary because the shared segment might not exist yet. + if (!found) { + key = _TFLCSKnownDarwinKeys[0]; + found = 1; + } + + return &key; +#endif +} + +u_int32_t TFLCSGetTickCount() +{ +#if defined(WIN32) + return (u_int32_t)GetTickCount(); +#elif defined(__APPLE__) + static mach_timebase_info_data_t timeBase; + + u_int64_t nanos = mach_absolute_time(); + + if (0 == timeBase.denom) { + (void)mach_timebase_info(&timeBase); + } + return (u_int32_t)((nanos * (u_int64_t)timeBase.numer / (u_int64_t)timeBase.denom) / (u_int64_t)1000000); +#else + static struct timeval bt; + static int initialized = 0; + + if (!initialized) { + struct utmpx* ut; + while (NULL != (ut = getutxent())) { + if (BOOT_TIME == ut->ut_type) { + memcpy(&bt, &ut->ut_tv, sizeof(struct timeval)); + break; + } + } + initialized = 1; + } + + struct timeval nt, btc; + (void)gettimeofday(&nt, NULL); + memcpy(&btc, &bt, sizeof(struct timeval)); + + if (nt.tv_usec < btc.tv_usec) { + u_int64_t n = (btc.tv_usec - nt.tv_usec) / 1000000 + 1; + btc.tv_usec -= 1000000 * n; + btc.tv_sec += n; + } + if (nt.tv_usec - btc.tv_usec > 1000000) { + u_int64_t n = (btc.tv_usec - nt.tv_usec) / 1000000; + btc.tv_usec += 1000000 * n; + btc.tv_sec -= n; + } + + nt.tv_usec = nt.tv_usec - btc.tv_usec; + nt.tv_sec = nt.tv_sec - btc.tv_sec; + + return (u_int32_t)((nt.tv_sec * 1000) + (nt.tv_usec / 1000)); +#endif +} + +int TFLCSWriteAMF3Integer(char* buffer, int value, int pos) +{ + if (value < 0) { + buffer[pos++] = (0x80 | ((value >> 22) & 0xff)); + buffer[pos++] = (0x80 | ((value >> 15) & 0x7f)); + buffer[pos++] = (0x80 | ((value >> 8) & 0x7f)); + buffer[pos++] = (value & 0xff); + } else if (value <= 0x7f) { + buffer[pos++] = value; + } else if (value <= 0x3fff) { + buffer[pos++] = (0x80 | ((value >> 7) & 0x7f)); + buffer[pos++] = (value & 0x7f); + } else if (value <= 0x1fffff) { + buffer[pos++] = (0x80 | ((value >> 14) & 0x7f)); + buffer[pos++] = (0x80 | ((value >> 7) & 0x7f)); + buffer[pos++] = (value & 0x7f); + } else { + buffer[pos++] = (0x80 | ((value >> 22) & 0xff)); + buffer[pos++] = (0x80 | ((value >> 15) & 0x7f)); + buffer[pos++] = (0x80 | ((value >> 8) & 0x7f)); + buffer[pos++] = (value & 0xff); + } + + return pos; +} + +int TFLCSWriteAMFString(char* buffer, const char * str, int pos) +{ + int len = strlen(str); + + buffer[pos++] = AMF_TYPE_STRING; + buffer[pos++] = 0; // TODO: string length is badly encoded here! + buffer[pos++] = (char)(len & 0xff); + + strcpy((char*)&buffer[pos], str); + + pos += len; + return pos; +} + +int TFLCSWriteAMF3ByteArray(char* buffer, const char* bytes, int pos, int len) +{ + // buffer[pos++] = AMF_TYPE_AMF3OBJ; + buffer[pos++] = AMF3_TYPE_BYTEARRAY; // AMF3_TYPE_BYTE_ARRAY + + pos = TFLCSWriteAMF3Integer(buffer, ((len << 1) | 1), pos); + + int i=0; + for(i=0; idata[AMF_ENVELOPE_TIMESTAMP_POS]; + + int pos = AMF_ENVELOPE_LEN; + // check timestamp and size + + memset(connection->data, 0, AMF_ENVELOPE_LEN); + + connection->data[0] = 1; + connection->data[4] = 1; + + *timestamp = TFLCSGetTickCount(); + + // write connection name + pos = TFLCSWriteAMFString(connection->data, connection->listenerName, pos); + // write protocol + pos = TFLCSWriteAMFString(connection->data, PROTOCOL_NAME, pos); + + // I have no idea what this is, but we apparently need it... + char weirdBytes[] = { + 0x01, 0x01, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x40, 0x24, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x08, 0, 0, + 0, 0, 0, 0}; + int i; + for (i=0; i<31; i++) + connection->data[pos++] = weirdBytes[i]; + + // write method name + pos = TFLCSWriteAMFString(connection->data, connection->listenerMethod, pos); + + return pos; +} + +int TFLCSWriteLCAMFEnvelopeTrailer(TFLCSLocalConnection_t* connection, int pos) +{ + if (NULL == connection) + return pos; + + u_int32_t* size = (u_int32_t*)&connection->data[AMF_ENVELOPE_SIZE_POS]; + + //pos = writeAMF3ByteArray(buffer, msg, pos, strlen(msg)); + *size = pos-16; + + return pos; +} + +int TFLCSSendByteArray(TFLCSLocalConnection_t* connection, const char* bytes, int len) +{ + ENSURE_CONNECTION_UP(connection, 0); + + if (NULL == bytes || 0 == len || !_TFLCSConnectionStructureIsValidForUse(connection)) { + TFLCSErrno = TFLCSErrorInvalidArgument; + return 0; + } + + _TFLCSLockSemaphore(connection); + + int pos = TFLCSWriteLCAMFEnvelopeHeader(connection); + pos = TFLCSWriteAMF3ByteArray(connection->data, bytes, pos, len); + (void)TFLCSWriteLCAMFEnvelopeTrailer(connection, pos); + + _TFLCSUnlockSemaphore(connection); + + return 1; +} + +void TFLCSDumpMemory(char* buffer, int offset, int size) +{ + int i = 0; + int c = 0; + char b; + + while (i < size) { + while ((c < 16) && (i+c < size)) { + b = buffer[offset+i+c]; + printf("%X%X ", b/16 & 0x0f, b & 0x0f ); + c++; + } + + while (c++ < 16) + printf(" "); + + c = 0; + + while ((c < 16) && (i+c < size)) { + b = buffer[offset+i+c]; + if (b > 31) + printf("%c", (char)b); + else + printf("."); + c++; + } + + i += 16; + c = 0; + printf("\n"); + } +} + +void _TFLCSLockSemaphore(TFLCSLocalConnection_t* connection) +{ + if (NULL != connection) { +#if defined(WIN32) + if (NULL != connection->semaphore) + WaitForSingleObject(connection->semaphore, INFINITE); +#else + if ((sem_t*)SEM_FAILED != connection->semaphore) + sem_wait(connection->semaphore); +#endif + } +} + +void _TFLCSUnlockSemaphore(TFLCSLocalConnection_t* connection) +{ + if (NULL != connection) { +#if defined(WIN32) + if (NULL != connection->semaphore) + ReleaseMutex(connection->semaphore); +#else + if ((sem_t*)SEM_FAILED != connection->semaphore) + sem_post(connection->semaphore); +#endif + } +} + +int _TFLCSConnectionStructureIsValidForUse(TFLCSLocalConnection_t* connection) +{ + return (NULL != connection + && 0 != connection->open +#if defined(WIN32) + && NULL != connection->semaphore + && NULL != connection->mapFile + && NULL != connection->mapAddress + && NULL != connection->data +#else + && (sem_t*)SEM_FAILED != connection->semaphore + && (char*)-1 != connection->data +#endif + ); +} + +int _TFLCSDelayedConnect(TFLCSLocalConnection_t* connection) +{ +#if defined(WIN32) + if (NULL == connection) + return 0; + if (connection->open) + return 1; + + if (NULL == (connection->semaphore = OpenMutex(MUTEX_ALL_ACCESS, + FALSE, + WIN32_SEMAPHORE_NAME))) { + TFLCSErrno = TFLCSErrorSemaphoreCreationFailed; + goto errorReturn; + } + + if (NULL == (connection->mapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, + FALSE, + WIN32_SHMEM_NAME))) { + TFLCSErrno = TFLCSErrorShmemIDNotFound; + goto errorReturn; + } + + if (NULL == (connection->mapAddress = MapViewOfFile(connection->mapFile, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 0))) { + TFLCSErrno = TFLCSErrorShmemOpeningFailed; + goto errorReturn; + } + + connection->data = (char*)connection->mapAddress; + connection->open = 1; + +errorReturn: +#endif + + return connection->open; +} + +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +using namespace TUIO2; + +FlashSender::FlashSender() { + local = true; + buffer_size = MAX_FLASH_SIZE; + lcConnection = TFLCSConnect(DEFAULT_LC_CONN_NAME,DEFAULT_LC_METH_NAME,NULL,NULL); + std::cout << "TUIO/FLC "<< DEFAULT_LC_METH_NAME << "@" << DEFAULT_LC_CONN_NAME << std::endl; +} + +FlashSender::FlashSender(const char *conn_name, const char *meth_name) { + local = true; + buffer_size = MAX_FLASH_SIZE; + lcConnection = TFLCSConnect(conn_name,meth_name,NULL,NULL); + std::cout << "TUIO/FLC "<< meth_name << "@" << conn_name << std::endl; +} + +FlashSender::~FlashSender() { + TFLCSDisconnect(lcConnection); +} + +bool FlashSender::isConnected() { + if (TFLCSConnectionHasConnectedClient(lcConnection)) return true; + else return false; +} + +bool FlashSender::sendOscPacket (osc::OutboundPacketStream *bundle) { + if (lcConnection==NULL)return false; + if (!TFLCSConnectionHasConnectedClient(lcConnection))return false; + if ( bundle->Size() > buffer_size ) return false; + if ( bundle->Size() == 0 ) return false; + + TFLCSSendByteArray(lcConnection, bundle->Data(), bundle->Size()); + return true; +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/FlashSender.h b/modules/touch/ext/libTUIO2/TUIO2/FlashSender.h new file mode 100644 index 0000000000..c584f8908e --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/FlashSender.h @@ -0,0 +1,215 @@ +// +// TFFlashLCSHMEM.h +// Touché +// +// Created by Georg Kaindl on 16/3/09. +// +// Copyright (C) 2009 Georg Kaindl +// +// This file is part of Touché. +// +// Touché is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// Touché is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with Touché. If not, see . + + +#if !defined(__TFFlashLCSHMEM_H__) +#define __TFFlashLCSHMEM_H__ 1 + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifdef WIN32 +#include +typedef DWORD u_int32_t; +#else +#include +#include +#endif + +#define TFLCS_LISTENER_NAME_MAX_LEN (64) +#define TFLCS_LISTENER_METHOD_MAX_LEN (64) + + typedef struct TFLCSLocalConnection_t { +#ifdef WIN32 + HANDLE semaphore; + HANDLE mapFile; + LPVOID mapAddress; +#else + int shmid; + sem_t* semaphore; +#endif + int open; + char* data; + char listenerName[TFLCS_LISTENER_NAME_MAX_LEN]; + char listenerMethod[TFLCS_LISTENER_METHOD_MAX_LEN]; + } TFLCSLocalConnection_t; + + typedef enum { + TFLCSErrorSuccess = 0, + TFLCSErrorInvalidArgument = 1, + TFLCSErrorShmemKeyNotFound = 2, + TFLCSErrorSemaphoreCreationFailed = 3, + TFLCSErrorShmemIDNotFound = 4, + TFLCSErrorShmemOpeningFailed = 5, + TFLCSErrorOutOfMemory = 6 + } TFLCSError_t; + + // much like errno, this will hold the last error that happened + extern TFLCSError_t TFLCSErrno; + + // connect to a Flash LocalConnection + // returns pointer to structure on success, NULL otherwise + // if the connection could not be opened right away (because Flash is not yet running), + // a non-null pointer is returned, but the "open" member of the structure will be 0 + // and TFLCSErrno will be set accordingly. the connection is truly open once "open" is + // non-zero. + TFLCSLocalConnection_t* TFLCSConnect(const char* listenerName, + const char* listenerMethod, + void* shmemKey, + void* semaphoreKey); + + // disconnect a Flash LocalConnection + void TFLCSDisconnect(TFLCSLocalConnection_t* connection); + + // changes the connection listener name + void TFLCSChangeListenerName(TFLCSLocalConnection_t* connection, const char* newListenerName); + + // changes the connection method name + void TFLCSChangeMethodName(TFLCSLocalConnection_t* connection, const char* newMethodName); + + // returns non-zero if the given connection's Flash client is connected, 0 otherwise + int TFLCSConnectionHasConnectedClient(TFLCSLocalConnection_t* connection); + + // tries to determine the key for the shared memory region used by the Flash LocalConnection + // returns a pointer to static memory on success, NULL on error. + void* TFLCSGuessShmemKey(); + + // get the current tick count (milliseconds since the system was started) + u_int32_t TFLCSGetTickCount(); + + // write an AMF3-encoded integer into a buffer + // returns the updated buffer position + int TFLCSWriteAMF3Integer(char* buffer, int value, int pos); + + // write an AMF-encoded string into a buffer + // returns the updated buffer position + int TFLCSWriteAMFString(char* buffer, const char * str, int pos); + + // write an AMF3-encoded byte array into a buffer + // returns the updated buffer position + int TFLCSWriteAMF3ByteArray(char* buffer, const char* bytes, int pos, int len); + + // writes the AMF envelope header for an LC method call + // returns the position in the buffer + int TFLCSWriteLCAMFEnvelopeHeader(TFLCSLocalConnection_t* connection); + + // writes the AMF envelope trailer for an LC method call + // returns the updated buffer position + int TFLCSWriteLCAMFEnvelopeTrailer(TFLCSLocalConnection_t* connection, int pos); + + // sends the given data of length len over the given connection as a ByteArray + // returns 1 on success, 0 otherwise + int TFLCSSendByteArray(TFLCSLocalConnection_t* connection, const char* bytes, int len); + + // gets the (string) names of all connected LC connections + // returns the number of found strings. + int TFLCSGetConnectedConnectionNames(TFLCSLocalConnection_t* connection, char* dest, int destLen); + + // dumps a given buffer (size bytes starting at offset) to stdout in a nice hex/ascii format. + // useful for debugging purposes. + void TFLCSDumpMemory(char* buffer, int offset, int size); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif //__TFFlashLCSHMEM_H__ + +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_FLASHSENDER_H +#define INCLUDED_FLASHSENDER_H + +#include "OscSender.h" + +#define MAX_FLASH_SIZE (40976) +#define DEFAULT_LC_CONN_NAME "_OscDataStream" +#define DEFAULT_LC_METH_NAME "receiveOscData" + +namespace TUIO2 { + + /** + * The FlashSender implements the Flash LocalConnection transport method for OSC + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL FlashSender : public OscSender { + + public: + + /** + * The default constructor creates a FlashSender using a Flash LocalConnection on localhost + */ + FlashSender(); + + /** + * The default constructor creates a FlashSender using a Flash LocalConnection on localhost + */ + FlashSender(const char *conn_name, const char *meth_name); + + /** + * The destructor closes the connection. + */ + virtual ~FlashSender(); + + /** + * This method delivers the provided OSC data + * + * @param *bundle the OSC stream to deliver + * @return true if the data was delivered successfully + */ + + bool sendOscPacket (osc::OutboundPacketStream *bundle); + + /** + * This method returns the connection state + * + * @return true if the connection is alive + */ + bool isConnected (); + + const char* tuio_type() { return "TUIO/FLC"; } + + private: + TFLCSLocalConnection_t* lcConnection; + }; +} +#endif /* INCLUDED_FLASHSENDER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/LibExport.h b/modules/touch/ext/libTUIO2/TUIO2/LibExport.h new file mode 100644 index 0000000000..deab0f1ccd --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/LibExport.h @@ -0,0 +1,36 @@ +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_LIBEXPORT_H +#define INCLUDED_LIBEXPORT_H + +#ifdef WIN32 + #pragma warning(disable: 4251) // disable annoying template exporting warnings + #pragma warning(disable: 4275) // disable warning caused by not exported OSC classes + + #ifdef LIB_EXPORT + #define LIBDECL __declspec(dllexport) + #else +// #define LIBDECL __declspec(dllimport) + #define LIBDECL + #endif +#else + #define LIBDECL +#endif + +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.cpp b/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.cpp new file mode 100644 index 0000000000..0e9af08f47 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.cpp @@ -0,0 +1,60 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "OscReceiver.h" + +using namespace TUIO2; +using namespace osc; + +void OscReceiver::ProcessMessage( const ReceivedMessage& msg, const IpEndpointName& remoteEndpoint) { + for (std::list::iterator client=clientList.begin(); client!= clientList.end(); client++) + (*client)->processOSC(msg); +} + +void OscReceiver::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 OscReceiver::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; + } +} + +bool OscReceiver::isConnected() { + return connected; +} + +void OscReceiver::addTuioClient(TuioClient *client) { + clientList.push_back(client); +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.h b/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.h new file mode 100644 index 0000000000..b8bcd22743 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/OscReceiver.h @@ -0,0 +1,97 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_OSCRECEIVER_H +#define INCLUDED_OSCRECEIVER_H + +#include "LibExport.h" +#include "TuioClient.h" + +#include "oscpack/osc/OscReceivedElements.h" +#include "oscpack/osc/OscHostEndianness.h" +#include "oscpack/ip/PacketListener.h" +#include "oscpack/ip/IpEndpointName.h" + +namespace TUIO2 { + + class TuioClient; // Forward declaration + + /** + * The OscReceiver is the base class for the various OSC transport methods such as UDP, TCP ... + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL OscReceiver: public PacketListener { + + public: + + /** + * The constructor is doing nothing in particular. + */ + OscReceiver() : connected(false) {}; + + /** + * The destructor is doing nothing in particular. + */ + virtual ~OscReceiver() {}; + + /** + * The OscReceiver connects and starts receiving TUIO messages via OSC + * + * @param lock running in the background if set to false (default) + */ + virtual void connect(bool lock=false) = 0; + + /** + * The OscReceiver disconnects and stops receiving TUIO messages via OSC + */ + virtual void disconnect() = 0; + + /** + * Returns true if this OscReceiver is currently connected. + * @return true if this OscReceiver is currently connected + */ + bool isConnected(); + + /** + * Attaches the provided TuioClient to this OscReceiver + * + * @param client a pointer to the TuioClient to attach + */ + void addTuioClient(TuioClient *client); + + /** + * The OSC callback method where the incoming OSC data is received + * + * @param data the received OSC data + * @param size the size of the received OSC data + * @param remoteEndpoint the origin of the received OSC data + */ + void ProcessPacket( const char *data, int size, const IpEndpointName &remoteEndpoint ); + + protected: + void ProcessBundle( const osc::ReceivedBundle& b, const IpEndpointName& remoteEndpoint); + + void ProcessMessage( const osc::ReceivedMessage& message, const IpEndpointName& remoteEndpoint); + + std::list clientList; + bool connected; + }; +}; +#endif /* INCLUDED_OSCRECEIVER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/OscSender.h b/modules/touch/ext/libTUIO2/TUIO2/OscSender.h new file mode 100644 index 0000000000..967941ca5b --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/OscSender.h @@ -0,0 +1,90 @@ +/* + TUIO2 C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_OSCSENDER_H +#define INCLUDED_OSCSENDER_H + +#include "LibExport.h" +#include "oscpack/osc/OscOutboundPacketStream.h" +#include "oscpack/osc/OscHostEndianness.h" +#include "oscpack/ip/NetworkingUtils.h" +#include +#include + +namespace TUIO2 { + + /** + * The OscSender class is the base class for the various OSC transport methods such as UDP, TCP ... + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL OscSender { + + public: + + /** + * The constructor is doing nothing in particular. + */ + OscSender (): local(true) {}; + + /** + * The destructor is doing nothing in particular. + */ + virtual ~OscSender() {} + + /** + * This method delivers the provided OSC data + * + * @param *bundle the OSC stream to deliver + * @return true if the data was delivered successfully + */ + virtual bool sendOscPacket (osc::OutboundPacketStream *bundle) = 0; + + /** + * This method returns the connection state + * + * @return true if the connection is alive + */ + virtual bool isConnected () = 0; + + /** + * This method returns if this OscSender delivers locally + * + * @return true if this OscSender delivers locally + */ + bool isLocal () { return local; }; + + /** + * This method returns the maximum bundle size in bytes + * + * @return the maximum bundle size in bytes + */ + int getBufferSize () { return buffer_size; }; + + virtual const char* tuio_type() = 0; + + protected: + unsigned int buffer_size; + bool local; + }; +} + + +#endif /* INCLUDED_OSCSENDER_H */ + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.cpp b/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.cpp new file mode 100644 index 0000000000..ba0a5f4c65 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.cpp @@ -0,0 +1,264 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TcpReceiver.h" + +using namespace TUIO2; +using namespace osc; + +// workaround for connect method name conflict +int tcp_connect(int socket, const struct sockaddr *address, socklen_t address_len) { + return connect(socket, address, address_len); +} + +#if defined (WIN32) && not defined (int32_t) +typedef DWORD int32_t; +#endif + +#ifdef WIN32 +static DWORD WINAPI ClientThreadFunc( LPVOID obj ) +#else +static void* ClientThreadFunc( void* obj ) +#endif +{ + TcpReceiver *sender = static_cast(obj); + char data_buffer[MAX_TCP_SIZE+4]; + char data_size[4]; + +#ifdef WIN32 + SOCKET client = sender->tcp_client_list.back(); +#else + int client = sender->tcp_client_list.back(); +#endif + + int bytes = 1; + while (bytes) { + bytes = recv(client, data_buffer, sizeof(data_buffer),0); + + if (bytes>=4) { + memcpy(&data_size[0],&data_buffer[0], 4); +#ifdef OSC_HOST_LITTLE_ENDIAN + int32_t temp = (int32_t)(*data_size); + data_size[0] = temp>>24; + data_size[1] = (temp>>16) & 255; + data_size[2] = (temp>>8) & 255; + data_size[3] = (temp) & 255; +#endif + int32_t size = (int32_t)(*data_size); + if (size+4==bytes) { + sender->ProcessPacket(&data_buffer[4],(int)size,IpEndpointName()); + } + } + } + + sender->tcp_client_list.remove(client); + std::cout << "closed TUIO/TCP connection" << std::endl; + + //if (sender->tcp_client_list.size()==0) sender->connected=false; + //std::cout << sender->tcp_client_list.size() << " clients left"<< std::endl; + + return 0; +}; + +#ifndef WIN32 +static void* ServerThreadFunc( void* obj ) +#else +static DWORD WINAPI ServerThreadFunc( LPVOID obj ) +#endif +{ + TcpReceiver *sender = static_cast(obj); + struct sockaddr_in client_addr; + socklen_t len = sizeof(client_addr); + + while ((int)sender->tcp_socket>0) { +#ifdef WIN32 + SOCKET tcp_client = -1; +#else + int tcp_client = -1; +#endif + tcp_client = accept(sender->tcp_socket, (struct sockaddr*)&client_addr, &len); + + if (tcp_client>0) { + std::cout << "listening to TUIO/TCP messages from " << inet_ntoa(client_addr.sin_addr) << "@" << client_addr.sin_port << std::endl; + sender->tcp_client_list.push_back(tcp_client); + //sender->connected=true; + //std::cout << sender->tcp_client_list.size() << " clients connected"<< std::endl; + +#ifndef WIN32 + pthread_t client_thread; + pthread_create(&client_thread , NULL, ClientThreadFunc,obj); +#else + DWORD ClientThreadId; + HANDLE client_thread = CreateThread( 0, 0, ClientThreadFunc, obj, 0, &ClientThreadId ); +#endif + } else break; + + } + + return 0; +}; + +TcpReceiver::TcpReceiver(unsigned short port) +: tcp_socket (-1) +, locked (false) +{ + + tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_socket < 0) std::cerr << "could not create TUIO/TCP socket" << std::endl; + + int optval = 1; +#ifdef WIN32 + int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const char *)&optval, sizeof(int)); +#else + int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const void *)&optval, sizeof(int)); +#endif + if (ret < 0) { + std::cerr << "could not reuse TUIO/TCP socket address" << std::endl; + return; + } + + struct sockaddr_in tcp_server; + memset( &tcp_server, 0, sizeof (tcp_server)); + + tcp_server.sin_family = AF_INET; + tcp_server.sin_addr.s_addr = htonl(INADDR_ANY); + tcp_server.sin_port = htons(port); + + socklen_t len = sizeof(tcp_server); + ret = bind(tcp_socket,(struct sockaddr*)&tcp_server,len); + if (ret < 0) { + std::cerr << "could not bind to TUIO/TCP socket on port " << port << std::endl; + return; + } + + ret = listen(tcp_socket, 1); + if (ret < 0) { + std::cerr << "could not start listening to TUIO/TCP socket" << std::endl; +#ifdef WIN32 + closesocket(tcp_socket); +#else + close(tcp_socket); +#endif + tcp_socket=-1; + return; + } + + std::cout << "TUIO/TCP socket created on port " << port << std::endl; +} + +TcpReceiver::TcpReceiver(const char *host, unsigned short port) +: tcp_socket (-1) +, locked (false) +{ + + tcp_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_socket < 0) { + std::cerr << "could not create TUIO/TCP socket" << std::endl; + return; + } + + struct sockaddr_in tcp_server; + memset( &tcp_server, 0, sizeof (tcp_server)); + unsigned long addr = inet_addr(host); + if (addr != INADDR_NONE) { + memcpy( (char *)&tcp_server.sin_addr, &addr, sizeof(addr)); + } else { + struct hostent *host_info = gethostbyname(host); + if (host_info == NULL) std::cerr << "unknown host name: " << host << std::endl; + memcpy( (char *)&tcp_server.sin_addr, host_info->h_addr, host_info->h_length ); + } + + tcp_server.sin_family = AF_INET; + tcp_server.sin_port = htons(port); + + int ret = tcp_connect(tcp_socket,(struct sockaddr*)&tcp_server,sizeof(tcp_server)); + if (ret<0) { +#ifdef WIN32 + closesocket(tcp_socket); +#else + close(tcp_socket); +#endif + std::cerr << "could not connect to TUIO/TCP server at " << host << ":"<< port << std::endl; + tcp_socket=-1; + return; + } else { + tcp_client_list.push_back(tcp_socket); + std::cout << "listening to TUIO/TCP messages from " << host << ":" << port << std::endl; + } +} + +TcpReceiver::~TcpReceiver() { + +} + +void TcpReceiver::connect(bool lk) { + + if (connected) return; + if ((int)tcp_socket<0) return; + locked = lk; + + if (tcp_client_list.size()>0) { + if (!locked) { +#ifndef WIN32 + pthread_create(&server_thread , NULL, ClientThreadFunc, this); +#else + server_thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &ServerThreadId ); +#endif + } else ClientThreadFunc(this); + } else { + if (!locked) { +#ifndef WIN32 + pthread_create(&server_thread , NULL, ServerThreadFunc, this); +#else + server_thread = CreateThread( 0, 0, ServerThreadFunc, this, 0, &ServerThreadId ); +#endif + } else ServerThreadFunc(this); + } + + connected = true; +} + +void TcpReceiver::disconnect() { + + if (!connected) return; + if ((int)tcp_socket<0) return; + +#ifdef WIN32 + for (std::list::iterator client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) + closesocket((*client)); + closesocket(tcp_socket); + if( server_thread ) CloseHandle( server_thread ); +#else + for (std::list::iterator client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) + close((*client)); + close(tcp_socket); + server_thread = 0; +#endif + + tcp_client_list.clear(); + if (!locked) { +#ifdef WIN32 + if( server_thread ) CloseHandle( server_thread ); +#endif + server_thread = 0; + } else locked = false; + + connected = false; +} + + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.h b/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.h new file mode 100644 index 0000000000..75816b5e8e --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.h @@ -0,0 +1,102 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TCPRECEIVER_H +#define INCLUDED_TCPRECEIVER_H + +#include "OscReceiver.h" +#define MAX_TCP_SIZE 65536 + +#ifdef WIN32 +#include +#include +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#endif + +namespace TUIO2 { + + /** + * The TcpReceiver provides the OscReceiver functionality for the TCP transport method + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TcpReceiver: public OscReceiver { + + public: + + /** + * This constructor creates a TcpReceiver instance listening to the provided TCP port + * + * @param port the number of the TCP port to listen to, defaults to 3333 + */ + TcpReceiver (unsigned short port=3333); + + /** + * This constructor creates a TcpReceiver connected to the provided host and TCP port + * + * @param host the host name to connect + * @param port the number of the TCP port to listen to, defaults to 3333 + */ + TcpReceiver (const char *host, unsigned short port); + + /** + * The destructor is doing nothing in particular. + */ + virtual ~TcpReceiver(); + + /** + * The TcpReceiver connects and starts receiving TUIO messages via TCP + * + * @param lock running in the background if set to false (default) + */ + void connect(bool lock=false); + + /** + * The TcpReceiver disconnects and stops receiving TUIO messages via TCP + */ + void disconnect(); + +#ifndef WIN32 + int tcp_socket; + std::list tcp_client_list; +#else + SOCKET tcp_socket; + std::list tcp_client_list; +#endif + + private: + +#ifndef WIN32 + pthread_t server_thread; +#else + HANDLE server_thread; + DWORD ServerThreadId; +#endif + + bool locked; + }; +}; +#endif /* INCLUDED_TcpReceiver_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TcpSender.cpp b/modules/touch/ext/libTUIO2/TUIO2/TcpSender.cpp new file mode 100644 index 0000000000..d6a3acc597 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TcpSender.cpp @@ -0,0 +1,303 @@ +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TcpSender.h" +using namespace TUIO2; + +#ifndef WIN32 +static void* ClientThreadFunc( void* obj ) +#else +static DWORD WINAPI ClientThreadFunc( LPVOID obj ) +#endif +{ + TcpSender *sender = static_cast(obj); + char buf[16]; + +#ifdef WIN32 + SOCKET client = sender->tcp_client_list.back(); +#else + int client = sender->tcp_client_list.back(); +#endif + + int connected = 1; + while (connected) { + connected = recv(client, buf, sizeof(buf),0); + } + + sender->tcp_client_list.remove(client); + std::cout << sender->tuio_type() << " connection closed"<< std::endl; + if (sender->tcp_client_list.size()==0) sender->connected=false; + //std::cout << sender->tcp_client_list.size() << " clients left"<< std::endl; + + return 0; +}; + +#ifndef WIN32 +static void* ServerThreadFunc( void* obj ) +#else +static DWORD WINAPI ServerThreadFunc( LPVOID obj ) +#endif +{ + TcpSender *sender = static_cast(obj); + struct sockaddr_in client_addr; + socklen_t len = sizeof(client_addr); + + std::cout << sender->tuio_type() << " socket created on port " << sender->port_no << std::endl; + while (sender->tcp_socket) { +#ifdef WIN32 + SOCKET tcp_client = -1; +#else + int tcp_client = -1; +#endif + + tcp_client = accept(sender->tcp_socket, (struct sockaddr*)&client_addr, &len); +#ifdef WIN32 + //win32 workaround on exit + if (!client_addr.sin_addr.S_un.S_addr && !client_addr.sin_port) return 0; + if ((client_addr.sin_addr.S_un.S_addr==3435973836) && (client_addr.sin_port==52428)) return 0; +#endif + + if (tcp_client>0) { + std::cout << sender->tuio_type() << " client connected from " << inet_ntoa(client_addr.sin_addr) << "@" << client_addr.sin_port << std::endl; + sender->tcp_client_list.push_back(tcp_client); + sender->connected=true; + sender->newClient(tcp_client); + //std::cout << sender->tcp_client_list.size() << " clients connected"<< std::endl; +#ifndef WIN32 + pthread_t client_thread; + pthread_create(&client_thread , NULL, ClientThreadFunc,obj); +#else + DWORD ClientThreadId; + HANDLE client_thread = CreateThread( 0, 0, ClientThreadFunc, obj, 0, &ClientThreadId ); +#endif + } else break; + } + + return 0; +}; + +TcpSender::TcpSender() + :connected (false) +{ + local = true; + buffer_size = MAX_TCP_SIZE; + + tcp_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if (tcp_socket < 0) { + std::cerr << "could not create " << tuio_type() << " socket" << std::endl; + return; + } + + struct sockaddr_in tcp_server; + memset( &tcp_server, 0, sizeof (tcp_server)); + //unsigned long addr = inet_addr("127.0.0.1"); + //memcpy( (char *)&tcp_server.sin_addr, &addr, sizeof(addr)); + + tcp_server.sin_family = AF_INET; + tcp_server.sin_port = htons(3333); + tcp_server.sin_addr.s_addr = inet_addr("127.0.0.1"); + + int ret = connect(tcp_socket,(struct sockaddr*)&tcp_server,sizeof(tcp_server)); + if (ret<0) { + std::cerr << "could not open " << tuio_type() << " connection to 127.0.0.1:3333" << std::endl; + return; + } else { + std::cout << tuio_type() << " connection opened to 127.0.0.1:3333" << std::endl; + tcp_client_list.push_back(tcp_socket); + connected = true; + +#ifndef WIN32 + pthread_create(&server_thread , NULL, ClientThreadFunc,this); +#else + HANDLE server_thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &ServerThreadId ); +#endif + + } + +} + +TcpSender::TcpSender(const char *host, int port) + :connected (false) +{ + if ((strcmp(host,"127.0.0.1")==0) || (strcmp(host,"localhost")==0)) { + local = true; + } else local = false; + buffer_size = MAX_TCP_SIZE; + + tcp_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if (tcp_socket < 0) { + std::cerr << "could not create " << tuio_type() << " socket" << std::endl; + return; + } + + struct sockaddr_in tcp_server; + memset( &tcp_server, 0, sizeof (tcp_server)); + unsigned long addr = inet_addr(host); + if (addr != INADDR_NONE) { + memcpy( (char *)&tcp_server.sin_addr, &addr, sizeof(addr)); + } else { + struct hostent *host_info = gethostbyname(host); + if (host_info == NULL) { + std::cerr << "unknown host name: " << host << std::endl; + throw std::exception(); + } + memcpy( (char *)&tcp_server.sin_addr, host_info->h_addr, host_info->h_length ); + } + + tcp_server.sin_family = AF_INET; + tcp_server.sin_port = htons(port); + + int ret = connect(tcp_socket,(struct sockaddr*)&tcp_server,sizeof(tcp_server)); + if (ret<0) { +#ifdef WIN32 + closesocket(tcp_socket); +#else + close(tcp_socket); +#endif + std::cerr << "could not open " << tuio_type() << " connection to " << host << ":"<< port << std::endl; + throw std::exception(); + } else { + std::cout << tuio_type() << " connection opened to " << host << ":"<< port << std::endl; + tcp_client_list.push_back(tcp_socket); + connected = true; + +#ifndef WIN32 + pthread_create(&server_thread , NULL, ClientThreadFunc,this); +#else + HANDLE server_thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &ServerThreadId ); +#endif + + } +} + +TcpSender::TcpSender(int port) + :connected (false) +{ + local = false; + buffer_size = MAX_TCP_SIZE; + port_no = port; + + tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_socket < 0) { + std::cerr << "could not create TUIO/TCP socket" << std::endl; + throw std::exception(); + } + + int optval = 1; + #ifdef WIN32 + int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const char *)&optval, sizeof(int)); + #else + int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const void *)&optval, sizeof(int)); + #endif + if (ret < 0) { + std::cerr << "could not reuse TUIO/TCP socket address" << std::endl; + throw std::exception(); + } + + struct sockaddr_in tcp_server; + memset( &tcp_server, 0, sizeof (tcp_server)); + + tcp_server.sin_family = AF_INET; + tcp_server.sin_addr.s_addr = htonl(INADDR_ANY); + tcp_server.sin_port = htons(port); + + socklen_t len = sizeof(tcp_server); + ret = bind(tcp_socket,(struct sockaddr*)&tcp_server,len); + if (ret < 0) { + std::cerr << "could not bind to TUIO/TCP socket on port " << port << std::endl; + throw std::exception(); + } + + ret = listen(tcp_socket, 1); + if (ret < 0) { + std::cerr << "could not start listening to TUIO/TCP socket" << std::endl; +#ifdef WIN32 + closesocket(tcp_socket); +#else + close(tcp_socket); +#endif + throw std::exception(); + } + +#ifndef WIN32 + pthread_create(&server_thread , NULL, ServerThreadFunc, this); +#else + DWORD ServerThreadId; + server_thread = CreateThread( 0, 0, ServerThreadFunc, this, 0, &ServerThreadId ); +#endif + +} + +bool TcpSender::isConnected() { + return connected; +} + + +TcpSender::~TcpSender() { +#ifdef WIN32 + + for (std::list::iterator client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) { + closesocket((*client)); + } + closesocket(tcp_socket); + + if( server_thread ) CloseHandle( server_thread ); + +#else + for (std::list::iterator client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) { + close((*client)); + } + close(tcp_socket); + tcp_socket = 0; + server_thread = 0; +#endif +} + + +bool TcpSender::sendOscPacket (osc::OutboundPacketStream *bundle) { + if (!connected) return false; + if ( bundle->Size() > buffer_size ) return false; + if ( bundle->Size() == 0 ) return false; + +#ifdef OSC_HOST_LITTLE_ENDIAN + data_size[0] = bundle->Size()>>24; + data_size[1] = (bundle->Size()>>16) & 255; + data_size[2] = (bundle->Size()>>8) & 255; + data_size[3] = (bundle->Size()) & 255; +#else + *((int32_t*)data_size) = bundle->Size(); +#endif + +#ifdef WIN32 + std::list::iterator client; +#else + std::list::iterator client; +#endif + + for (client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) { + //send((*client), data_size, 4,0); + //send((*client), bundle->Data(), bundle->Size(),0); + memcpy(&data_buffer[0], &data_size, 4); + memcpy(&data_buffer[4], bundle->Data(), bundle->Size()); + send((*client),data_buffer, 4+bundle->Size(),0); + } + + return true; +} + +void TcpSender::newClient( int tcp_client ) { } diff --git a/modules/touch/ext/libTUIO2/TUIO2/TcpSender.h b/modules/touch/ext/libTUIO2/TUIO2/TcpSender.h new file mode 100644 index 0000000000..03b8678048 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TcpSender.h @@ -0,0 +1,126 @@ +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TCPSENDER_H +#define INCLUDED_TCPSENDER_H + +#include "OscSender.h" + +#ifdef WIN32 +#include +#include +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#endif + +#include +#define MAX_TCP_SIZE 65536 + +namespace TUIO2 { + + /** + * The TcpSender implements the TCP transport method for OSC + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TcpSender : public OscSender { + + public: + + /** + * The default constructor creates a TcpSender that sends to the default TUIO port 3333 on localhost + */ + TcpSender(); + + /** + * This constructor creates a TcpSender that sends to the provided port on the the given host + * + * @param host the receiving host name + * @param port the outgoing TUIO TCP port number + */ + TcpSender(const char *host, int port); + + /** + * This constructor creates a TcpSender that listens to the provided port + * + * @param port the incoming TUIO TCP port number + */ + TcpSender(int port); + + /** + * The destructor closes the socket. + */ + virtual ~TcpSender(); + + /** + * This method delivers the provided OSC data + * + * @param *bundle the OSC stream to deliver + * @return true if the data was delivered successfully + */ + + bool sendOscPacket (osc::OutboundPacketStream *bundle); + + /** + * This method returns the connection state + * + * @return true if the connection is alive + */ + bool isConnected (); + + /** + * This method is called whenever a new client connects + * + * @param tcp_client the socket handle of the new client + */ + virtual void newClient( int tcp_client ); + + int port_no; + +#ifdef WIN32 + SOCKET tcp_socket; + std::list tcp_client_list; +#else + int tcp_socket; + std::list tcp_client_list; +#endif + bool connected; + const char* tuio_type() { return "TUIO/TCP"; } + + protected: + char data_size[4]; + char data_buffer[MAX_TCP_SIZE+4]; + + +#ifdef WIN32 + HANDLE server_thread; + DWORD ServerThreadId; +#else + pthread_t server_thread; +#endif + + }; +} +#endif /* INCLUDED_TCPSENDER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.cpp new file mode 100644 index 0000000000..bf2f1c8002 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.cpp @@ -0,0 +1,94 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioBounds.h" +using namespace TUIO2; + +TuioBounds::TuioBounds (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a, float w, float h, float f):TuioComponent(ttime, tobj, xp, yp,a) { + width = w; + height = h; + area = f; +} + +TuioBounds::TuioBounds (TuioObject *tobj, float xp, float yp, float a, float w, float h, float f):TuioComponent(tobj, xp, yp, a) { + width = w; + height = h; + area = f; +} + +TuioBounds::TuioBounds (TuioBounds *tbnd):TuioComponent(tbnd) { + angle = tbnd->getAngle(); + width = tbnd->getWidth(); + height = tbnd->getHeight(); + area = tbnd->getArea(); + rotation_speed = 0.0f; + rotation_accel = 0.0f; +} + +void TuioBounds::update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra) { + TuioComponent::update(ttime,xp,yp,a,xs,ys,rs,ma,ra); + width = w; + height = h; + area = f; +} + +void TuioBounds::update (float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra) { + TuioComponent::update(xp,yp,a,xs,ys,rs,ma,ra); + width = w; + height = h; + area = f; +} + +void TuioBounds::update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f) { + TuioComponent::update(ttime,xp,yp,a); + + width = w; + height = h; + area = f; +} + +void TuioBounds::stop (TuioTime ttime) { + update(ttime,xpos,ypos,angle,width,height,area); +} + +void TuioBounds::update (TuioBounds *tbnd) { + TuioComponent::update(tbnd); + width = tbnd->getWidth(); + height = tbnd->getHeight(); + area = tbnd->getArea(); +} + +float TuioBounds::getWidth() const{ + return width; +} + +float TuioBounds::getHeight() const{ + return height; +} + +int TuioBounds::getScreenWidth(int w) const{ + return (int)(w*width); +} + +int TuioBounds::getScreenHeight(int h) const{ + return (int)(h*height); +} + +float TuioBounds::getArea() const{ + return area; +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.h b/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.h new file mode 100644 index 0000000000..803f67c3b7 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioBounds.h @@ -0,0 +1,206 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOBOUNDS_H +#define INCLUDED_TUIOBOUNDS_H + +#include "TuioComponent.h" + +namespace TUIO2 { + + /** + * The TuioBounds class encapsulates /tuio2/bnd TUIO boundary ellipses. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + + class LIBDECL TuioBounds: public TuioComponent { + + protected: + /** + * The rotation angle value. + */ + float angle; + /** + * The width value. + */ + float width; + /** + * The height value. + */ + float height; + /** + * The area value. + */ + float area; + /** + * The rotation speed value. + */ + float rotation_speed; + /** + * The rotation acceleration value. + */ + float rotation_accel; + + public: + using TuioComponent::update; + + /** + * This constructor takes a TuioTime argument and assigns it along with the provided + * Session ID, X and Y coordinate, width, height and angle to the newly created TuioBounds. + * + * @param ttime the TuioTime to assign + * @param tobj the TuioObject to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param w the width to assign + * @param h the height to assign + * @param f the area to assign + */ + TuioBounds (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a, float w, float h, float f); + + /** + * This constructor takes a TuioTime argument and assigns it along with the provided + * Session ID, X and Y coordinate, width, height and angle to the newly created TuioBounds. + * + * @param tobj the TuioObject to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param w the width to assign + * @param h the height to assign + * @param f the area to assign + */ + TuioBounds (TuioObject *tobj, float xp, float yp, float a, float w, float h, float f); + + /** + * This constructor takes the atttibutes of the provided TuioBounds + * and assigs these values to the newly created TuioBounds. + * + * @param tbnd the TuioBounds to assign + */ + TuioBounds (TuioBounds *tbnd); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioBounds() {}; + + /** + * 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 TuioBounds attributes. + * + * @param ttime the TuioTime to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param w the width to assign + * @param h the height to assign + * @param f the area 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 w, float h, float f, float xs, float ys, float rs, float ma, float ra); + + /** + * Assigns the provided X and Y coordinate, angle, X and Y velocity, motion acceleration + * rotation velocity and rotation acceleration to the private TuioComponent 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 to assign + * @param w the width to assign + * @param h the height to assign + * @param f the area 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 w, float h, float f, float xs, float ys, float rs, float ma, float ra); + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate and angle to the private TuioBounds 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 + * @param w the width to assign + * @param h the height to assign + * @param f the area to assign + */ + void update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f); + + /** + * This method is used to calculate the speed and acceleration values of a + * TuioBounds with unchanged position and angle. + */ + void stop (TuioTime ttime); + + /** + * Takes the atttibutes of the provided TuioBounds + * and assigs these values to this TuioBounds. + * The TuioTime time stamp of this TuioComponent remains unchanged. + * + * @param tbnd the TuioComponent to assign + */ + void update (TuioBounds *tbnd); + + /** + * Returns the width of this TuioBounds. + * @return the width of this TuioBounds + */ + float getWidth() const; + + /** + * Returns the height of this TuioBounds. + * @return the height of this TuioBounds + */ + float getHeight() const; + + /** + * Returns the width of this TuioBounds. + * @return the width of this TuioBounds + */ + int getScreenWidth(int w) const; + + /** + * Returns the height of this TuioBounds. + * @return the height of this TuioBounds + */ + int getScreenHeight(int h) const; + + /** + * Returns the area of this TuioBounds. + * @return the area of this TuioBounds + */ + float getArea() const; + }; +} +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioClient.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioClient.cpp new file mode 100644 index 0000000000..e638651008 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioClient.cpp @@ -0,0 +1,520 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioClient.h" +#include "UdpReceiver.h" + +using namespace TUIO2; +using namespace osc; + + +TuioClient::TuioClient() +: lateFrame (false) +, source_count (0) +, receiver (NULL) +, local_receiver(true) +{ + receiver = new UdpReceiver(); + initialize(); +} + +TuioClient::TuioClient(unsigned short port) +: lateFrame (false) +, source_count (0) +, receiver (NULL) +, local_receiver(true) +{ + receiver = new UdpReceiver(port); + initialize(); +} + +TuioClient::TuioClient(OscReceiver *osc) +: lateFrame (false) +, source_count (0) +, receiver (osc) +, local_receiver(false) +{ + initialize(); +} + +void TuioClient::initialize() { + receiver->addTuioClient(this); +} + +TuioClient::~TuioClient() { + if (local_receiver) delete receiver; +} + +void TuioClient::processOSC( const ReceivedMessage& msg ) { + try { + ReceivedMessageArgumentStream args = msg.ArgumentStream(); + //ReceivedMessage::const_iterator arg = msg.ArgumentsBegin(); + + if( strcmp( msg.AddressPattern(), "/tuio2/frm" ) == 0 ) { + //lockFrame(); + int32 fseq_raw,dim_raw; + TimeTag timetag; + const char* src_string; + args >> fseq_raw >> timetag >> dim_raw >> src_string; + + // check if we know that source + std::map::iterator iter = sourceList.find(src_string); + + if (iter==sourceList.end()) { // add a new source + frameSource = new TuioSource(source_count, src_string, (unsigned int)dim_raw); + sourceList[src_string] = frameSource; + source_count++; + } else { // use the found source + frameSource = sourceList[src_string]; + } + + unsigned int currentFrameID = (unsigned int)fseq_raw; + frameTime = TuioTime(timetag); + frameTime.setFrameID(currentFrameID); + + // frame sequence + lateFrame = false; + unsigned int lastFrameID = frameSource->getFrameTime().getFrameID(); + unsigned int timeDiff = frameTime.getTotalMilliseconds() - frameSource->getFrameTime().getTotalMilliseconds(); + frameSource->setFrameTime(frameTime); + + // drop late frames (but accept the reserved ID 0 and consider a possible reset after 1sec + if ((currentFrameID> s_id_raw >> tu_id_raw >> c_id_raw >> xpos >> ypos >> angle; + if (!args.Eos()) args >> xspeed >> yspeed >> rspeed >> maccel >> raccel; + else xspeed = yspeed = rspeed = maccel = raccel = 0.0f; + + s_id = (unsigned int)s_id_raw; + c_id = (unsigned int)c_id_raw; + t_id = tu_id_raw >> 16; + u_id = tu_id_raw & 0x0000FFFF; + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + //if (tobj == NULL) std::cout << "new cont " << s_id << " " << frameSource.getSourceID() << std::endl; + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + TuioToken *ttok = tobj->getTuioToken(); + if (ttok == NULL) { + ttok = new TuioToken(frameTime,tobj,t_id,u_id,c_id,xpos,ypos,angle); + tobj->setTuioToken(ttok); + } else if ( (ttok->getX()!=xpos) || (ttok->getY()!=ypos) || (ttok->getAngle()!=angle) || (ttok->getXSpeed()!=xspeed) || (ttok->getYSpeed()!=yspeed) || (ttok->getRotationSpeed()!=rspeed) || (ttok->getMotionAccel()!=maccel) || (ttok->getRotationAccel()!=raccel) ) { + + ttok->update(frameTime,xpos,ypos,angle,xspeed,yspeed,rspeed,maccel,raccel); + } + + } else if( strcmp( msg.AddressPattern(), "/tuio2/ptr" ) == 0 ) { + + if (lateFrame) return; + int32 s_id_raw, tu_id_raw, c_id_raw; + unsigned short t_id, u_id; + unsigned int s_id,c_id; + float xpos, ypos, angle, shear,radius, pressure, xspeed, yspeed, pspeed, maccel, paccel; + args >> s_id_raw >> tu_id_raw >> c_id_raw >> xpos >> ypos >> angle >> shear >> radius >> pressure; + if (!args.Eos()) args >> xspeed >> yspeed >> pspeed >> maccel >> paccel; + else xspeed = yspeed = pspeed = maccel = paccel = 0.0f; + + s_id = (unsigned int)s_id_raw; + c_id = (unsigned int)c_id_raw; + t_id = tu_id_raw >> 16; + u_id = tu_id_raw & 0x0000FFFF; + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + //if (tobj == NULL) std::cout << "new cont " << s_id << " " << frameSource.getSourceID() << std::endl; + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + TuioPointer *tptr = tobj->getTuioPointer(); + if (tptr == NULL) { + tptr = new TuioPointer(frameTime,tobj,t_id,u_id,c_id,xpos,ypos,angle,shear,radius,pressure); + tobj->setTuioPointer(tptr); + + } else if ( (tptr->getX()!=xpos) || (tptr->getY()!=ypos) || (tptr->getAngle()!=angle) || (tptr->getShear()!=shear) || (tptr->getRadius()!=radius) || (tptr->getPressure()!=pressure) || (tptr->getXSpeed()!=xspeed) || (tptr->getYSpeed()!=yspeed) || (tptr->getPressureSpeed()!=pspeed) || (tptr->getMotionAccel()!=maccel) || (tptr->getPressureAccel()!=paccel) ) { + + tptr->update(frameTime,xpos,ypos,angle,shear,radius,pressure,xspeed,yspeed,pspeed,maccel,paccel); + } + } else if( strcmp( msg.AddressPattern(), "/tuio2/bnd" ) == 0 ) { + + if (lateFrame) return; + int32 s_id_raw; + unsigned int s_id; + float xpos, ypos, angle, width, height, area; + float xspeed, yspeed, rspeed, maccel, raccel; + args >> s_id_raw >> xpos >> ypos >> angle >> width >> height >> area; + if (!args.Eos()) args >> xspeed >> yspeed >> rspeed >> maccel >> raccel; + else xspeed = yspeed = rspeed = maccel = raccel = 0.0f; + + s_id = (unsigned int)s_id_raw; + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + TuioBounds *tbnd = tobj->getTuioBounds(); + if (tbnd == NULL) { + tbnd = new TuioBounds(frameTime,tobj,xpos,ypos,angle,width,height,area); + tobj->setTuioBounds(tbnd); + } else if ( (tbnd->getX()!=xpos) || (tbnd->getY()!=ypos) || (tbnd->getAngle()!=angle) || (tbnd->getWidth()!=width) || (tbnd->getHeight()!=height) || (tbnd->getArea()!=area) || (tbnd->getXSpeed()!=xspeed) || (tbnd->getYSpeed()!=yspeed) || (tbnd->getRotationSpeed()!=rspeed) || (tbnd->getMotionAccel()!=maccel) || (tbnd->getRotationAccel()!=raccel)) { + + tbnd->update(frameTime,xpos,ypos,angle,width,height,area,xspeed,yspeed,rspeed,maccel,raccel); + } + } else if( strcmp( msg.AddressPattern(), "/tuio2/sym" ) == 0 ) { + + if (lateFrame) return; + int32 s_id_raw, tu_id_raw, c_id_raw; + unsigned int s_id, c_id; + unsigned short t_id, u_id; + const char* type; + const char* data; + args >> s_id_raw >> tu_id_raw >> c_id_raw >> type >> data; + + s_id = (unsigned int)s_id_raw; + c_id = (unsigned int)c_id_raw; + t_id = tu_id_raw >> 16; + u_id = tu_id_raw & 0x0000FFFF; + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + TuioSymbol *tsym = tobj->getTuioSymbol(); + if (tsym == NULL) { + tsym = new TuioSymbol(frameTime,tobj,t_id,u_id,c_id,type,data); + tobj->setTuioSymbol(tsym); + } else { + tsym->update(frameTime); + } + + } else if( strcmp( msg.AddressPattern(), "/tuio2/chg" ) == 0 ) { + if (lateFrame) return; + int32 s_id_raw; + args >> s_id_raw; + unsigned int s_id = (unsigned int)s_id_raw; + + std::list pointList; + while(!args.Eos()) { + float xpos, ypos; + args >> xpos >> ypos; + pointList.push_back(TuioPoint(frameTime, xpos, ypos)); + } + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + + /*TuioGeometry *tgeo = tobj->getTuioGeometry(); + if (tgeo == NULL) { + tgeo = new TuioGeometry(frameTime, tobj); + tobj->setTuioGeometry(tgeo); + } tgeo->setConvexHull(pointList);*/ + + } else if( strcmp( msg.AddressPattern(), "/tuio2/ocg" ) == 0 ) { + if (lateFrame) return; + int32 s_id_raw; + args >> s_id_raw; + unsigned int s_id = (unsigned int)s_id_raw; + + std::list pointList; + while(!args.Eos()) { + float xpos, ypos; + args >> xpos >> ypos; + pointList.push_back(TuioPoint(frameTime, xpos, ypos)); + } + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + + /*TuioGeometry *tgeo = tobj->getTuioGeometry(); + if (tgeo == NULL) { + tgeo = new TuioGeometry(frameTime, tobj); + tobj->setTuioGeometry(tgeo); + } tgeo->setOuterContour(pointList);*/ + + } else if( strcmp( msg.AddressPattern(), "/tuio2/icg" ) == 0 ) { + if (lateFrame) return; + int32 s_id_raw; + args >> s_id_raw; + unsigned int s_id = (unsigned int)s_id_raw; + + std::list pointList; + while(!args.Eos()) { + float xpos,ypos; + args >> xpos >> ypos; + pointList.push_back(TuioPoint(frameTime, xpos, ypos)); + } + + TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id); + if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id); + addFrameObject(tobj); + + /*TuioGeometry *tgeo = tobj->getTuioGeometry(); + if (tgeo == NULL) { + tgeo = new TuioGeometry(frameTime, tobj); + tobj->setTuioGeometry(tgeo); + } tgeo->setOuterContour(pointList);*/ + + } else if( strcmp( msg.AddressPattern(), "/tuio2/alv" ) == 0 ) { + + if (lateFrame) return; + int32 s_id; + aliveObjectList.clear(); + while(!args.Eos()) { + args >> s_id; + aliveObjectList.push_back((unsigned int)s_id); + } + + lockObjectList(); + //find the removed tobjs first + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()!=frameSource->getSourceID()) continue; + std::list::iterator iter = find(aliveObjectList.begin(), aliveObjectList.end(), (*tobj)->getSessionID()); + if (iter == aliveObjectList.end()) { + (*tobj)->remove(frameTime); + addFrameObject(*tobj); + } + } + unlockObjectList(); + + for (std::list::iterator iter=frameObjectList.begin(); iter!=frameObjectList.end(); iter++) { + TuioObject *tobj = (*iter); + + switch (tobj->getTuioState()) { + case TUIO_REMOVED: + + for (std::list::iterator listener=listenerList.begin(); listener!=listenerList.end(); listener++) + (*listener)->tuioRemove(tobj); + + lockObjectList(); + for (std::list::iterator delcon=tobjList.begin(); delcon!=tobjList.end(); delcon++) { + if (((*delcon)->getSessionID()==tobj->getSessionID()) && ((*delcon)->getTuioSource()->getSourceID()==frameSource->getSourceID())) { + delete *delcon; + tobjList.erase(delcon); + break; + } + } + unlockObjectList(); + break; + case TUIO_ADDED: + + lockObjectList(); + tobjList.push_back(tobj); + unlockObjectList(); + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioAdd(tobj); + + break; + default: + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioUpdate(tobj); + } + } + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioRefresh(frameTime); + + frameObjectList.clear(); + //unlockFrame(); + } + } catch( Exception& e ){ + std::cerr << "error parsing TUIO2 message: "<< msg.AddressPattern() << " - " << e.what() << std::endl; + //unlockFrame(); + } +} + +bool TuioClient::isConnected() { + return receiver->isConnected(); +} + +void TuioClient::connect(bool lock) { + + receiver->connect(lock); + unlockObjectList(); +} + +void TuioClient::disconnect() { + + receiver->disconnect(); + aliveObjectList.clear(); + + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) + delete (*iter); + tobjList.clear(); +} + +TuioObject* TuioClient::getTuioObject(unsigned int src_id, unsigned int s_id) { + lockObjectList(); + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) { + unlockObjectList(); + return (*iter); + } + } + unlockObjectList(); + return NULL; +} + +TuioToken* TuioClient::getTuioToken(unsigned int src_id, unsigned int s_id) { + lockObjectList(); + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) { + unlockObjectList(); + return (*iter)->getTuioToken(); + } + } + unlockObjectList(); + return NULL; +} + +TuioPointer* TuioClient::getTuioPointer(unsigned int src_id, unsigned int s_id) { + lockObjectList(); + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) { + unlockObjectList(); + return (*iter)->getTuioPointer(); + } + } + unlockObjectList(); + return NULL; +} + +TuioBounds* TuioClient::getTuioBounds(unsigned int src_id, unsigned int s_id) { + lockObjectList(); + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) { + unlockObjectList(); + return (*iter)->getTuioBounds(); + } + } + unlockObjectList(); + return NULL; +} + +TuioSymbol* TuioClient::getTuioSymbol(unsigned int src_id, unsigned int s_id) { + lockObjectList(); + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) { + unlockObjectList(); + return (*iter)->getTuioSymbol(); + } + } + unlockObjectList(); + return NULL; +} + +std::list TuioClient::getTuioObjectList(unsigned int src_id) { + lockObjectList(); + std::list listBuffer; + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()==src_id) listBuffer.push_back(*tobj); + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioClient::getTuioTokenList(unsigned int src_id) { + lockObjectList(); + std::list listBuffer; + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()==src_id) { + TuioToken *ttok = (*tobj)->getTuioToken(); + if (ttok!=NULL) listBuffer.push_back(ttok); + } + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioClient::getTuioPointerList(unsigned int src_id) { + lockObjectList(); + std::list listBuffer; + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()==src_id) { + TuioPointer *tptr = (*tobj)->getTuioPointer(); + if (tptr!=NULL) listBuffer.push_back(tptr); + } + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioClient::getTuioBoundsList(unsigned int src_id) { + lockObjectList(); + std::list listBuffer; + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()==src_id) { + TuioBounds *tbnd = (*tobj)->getTuioBounds(); + if (tbnd!=NULL) listBuffer.push_back(tbnd); + } + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioClient::getTuioSymbolList(unsigned int src_id) { + lockObjectList(); + std::list listBuffer; + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if ((*tobj)->getTuioSource()->getSourceID()==src_id) { + TuioSymbol *tsym = (*tobj)->getTuioSymbol(); + if (tsym!=NULL) listBuffer.push_back(tsym); + } + } + unlockObjectList(); + return listBuffer; +} + +void TuioClient::addFrameObject(TuioObject *tobj) { + for (std::list::iterator iter=frameObjectList.begin(); iter != frameObjectList.end(); iter++) { + if ((*iter)->getSessionID()==tobj->getSessionID()) return; + } + + frameObjectList.push_back(tobj); +} + +TuioObject* TuioClient::getFrameObject(unsigned int src_id, unsigned int s_id) { + for (std::list::iterator tobj=frameObjectList.begin(); tobj != frameObjectList.end(); tobj++) { + if ((*tobj)->getSessionID()==s_id) return *tobj; + } + + for (std::list::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) { + if (((*tobj)->getSessionID()==s_id) && ((*tobj)->getTuioSource()->getSourceID()==src_id)) return *tobj; + } + + return NULL; +} + +void TuioClient::lockFrame() { +#ifndef WIN32 + pthread_mutex_lock(&frameMutex); +#else + WaitForSingleObject(frameMutex, INFINITE); +#endif +} + +void TuioClient::unlockFrame() { +#ifndef WIN32 + pthread_mutex_unlock(&frameMutex); +#else + ReleaseMutex(frameMutex); +#endif +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioClient.h b/modules/touch/ext/libTUIO2/TUIO2/TuioClient.h new file mode 100644 index 0000000000..65582f5f67 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioClient.h @@ -0,0 +1,241 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOCLIENT_H +#define INCLUDED_TUIOCLIENT_H + +#include "TuioDispatcher.h" +#include "OscReceiver.h" +#include "oscpack/osc/OscReceivedElements.h" + +#include +#include +#include +#include +#include +#include + +namespace TUIO2 { + + class OscReceiver; // Forward declaration + + /** + *

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.

+ *

+ * TuioClient *client = new TuioClient();
+ * client->addTuioListener(myTuioListener);
+ * client->connect();
+ *

+ * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioClient : public TuioDispatcher { + + public: + /** + * This constructor creates a TuioClient that uses an internal UdpReceiver listening to the default UDP port 3333 + * + */ + TuioClient(); + + /** + * This constructor creates a TuioClient that uses an internal UdpReceiver listening to the provided UDP port + * + * @param port the UDP port the internal UdpReceiver is listening to + */ + TuioClient(unsigned short port); + + /** + * This constructor creates a TuioClient that uses the provided OscReceiver for the incoming OSC data + * + * @param oscreceiver the OscReceiver implementation for the chosen transport method (UDP, TCP ...) + */ + TuioClient(OscReceiver *oscreceiver); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioClient(); + + /** + * The TuioClient connects and starts receiving TUIO messages from its associated OscReceiver + * + * @param lock running in the background if set to false (default) + */ + void connect(bool lock=false); + + /** + * The TuioClient disconnects and stops receiving TUIO messages from its associated OscReceiver + */ + void disconnect(); + + /** + * Returns true if this TuioClient is currently connected. + * @return true if this TuioClient is currently connected + */ + bool isConnected(); + + /** + * Returns the TuioObject corresponding to the provided Session ID + * which is associated to the given Source ID + * or NULL if the Session ID does not refer to an active TuioObject + * + * @param src_id the source ID of the corresponding TUIO source + * @param s_id the session ID of the corresponding TuioObject + * @return an active TuioObject corresponding to the provided Session ID or NULL + */ + using TuioDispatcher::getTuioObject; + TuioObject* getTuioObject(unsigned int src_id, unsigned int s_id); + + /** + * Returns a list of all currently active TuioObject + * which are associated to the given Source ID + * + * @param src_id the source ID of the corresponding TUIO source + * @return a list of TuioObject + */ + using TuioDispatcher::getTuioObjectList; + std::list getTuioObjectList(unsigned int src_id); + + /** + * Returns the TuioToken corresponding to the provided Session ID + * which is associated to the given Source ID + * or NULL if the Session ID does not refer to an active TuioToken + * + * @param src_id the source ID of the corresponding TUIO source + * @param s_id the session ID of the corresponding TuioToken + * @return an active TuioToken corresponding to the provided Session ID or NULL + */ + using TuioDispatcher::getTuioToken; + TuioToken* getTuioToken(unsigned int src_id, unsigned int s_id); + + /** + * Returns a list of all currently active TuioTokens + * which are associated to the given Source ID + * + * @param src_id the source ID of the corresponding TUIO source + * @return a list of TuioTokens + */ + using TuioDispatcher::getTuioTokenList; + std::list getTuioTokenList(unsigned int src_id); + + /** + * Returns the TuioPointer corresponding to the provided Session ID + * which is associated to the given Source ID + * or NULL if the Session ID does not refer to an active TuioPointer + * + * @param src_id the source ID of the corresponding TUIO source + * @param s_id the session ID of the corresponding TuioPointer + * @return an active TuioPointer corresponding to the provided Session ID or NULL + */ + using TuioDispatcher::getTuioPointer; + TuioPointer* getTuioPointer(unsigned int src_id, unsigned int s_id); + + /** + * Returns a List of all currently active TuioPointers + * which are associated to the given Source ID + * + * @param src_id the source ID of the corresponding TUIO source + * @return a List of TuioPointers + */ + using TuioDispatcher::getTuioPointerList; + std::list getTuioPointerList(unsigned int src_id); + + /** + * Returns the TuioBounds corresponding to the provided Session ID + * which is associated to the given Source ID + * or NULL if the Session ID does not refer to an active TuioBounds + * + * @param src_id the source ID of the corresponding TUIO source + * @param s_id the session ID of the corresponding TuioBounds + * @return an active TuioBounds corresponding to the provided Session ID or NULL + */ + using TuioDispatcher::getTuioBounds; + TuioBounds* getTuioBounds(unsigned int src_id, unsigned int s_id); + + /** + * Returns a List of all currently active TuioBounds + * which are associated to the given Source ID + * + * @param src_id the source ID of the corresponding TUIO source + * @return a List of TuioBounds + */ + using TuioDispatcher::getTuioBoundsList; + std::list getTuioBoundsList(unsigned int src_id); + + /** + * Returns the TuioSymbol corresponding to the provided Session ID + * which is associated to the given Source ID + * or NULL if the Session ID does not refer to an active TuioSymbol + * + * @param src_id the source ID of the corresponding TUIO source + * @param s_id the session ID of the corresponding TuioSymbol + * @return an active TuioSymbol corresponding to the provided Session ID or NULL + */ + using TuioDispatcher::getTuioSymbol; + TuioSymbol* getTuioSymbol(unsigned int src_id, unsigned int s_id); + + /** + * Returns a List of all currently active TuioSymbol + * which are associated to the given Source ID + * + * @param src_id the source ID of the corresponding TUIO source + * @return a List of TuioSymbol + */ + using TuioDispatcher::getTuioSymbolList; + std::list getTuioSymbolList(unsigned int src_id); + + /** + * Parses the incoming OSC message + * + * @param message the incoming OSC message + */ + void processOSC( const osc::ReceivedMessage& message); + + private: + void initialize(); + + void addFrameObject(TuioObject *con); + TuioObject* getFrameObject(unsigned int src_id,unsigned int s_id); + std::list aliveObjectList; + std::list frameObjectList; + + TuioTime frameTime; + bool lateFrame; + + unsigned int source_count; + std::map sourceList; + TuioSource *frameSource; + + OscReceiver *receiver; + bool local_receiver; + +#ifndef WIN32 + pthread_mutex_t frameMutex; +#else + HANDLE frameMutex; +#endif + + void lockFrame(); + void unlockFrame(); + }; +}; +#endif /* INCLUDED_TUIOCLIENT_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.cpp new file mode 100644 index 0000000000..d27a3dad28 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.cpp @@ -0,0 +1,245 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioComponent.h" +#include "TuioObject.h" +using namespace TUIO2; + +TuioComponent::TuioComponent (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a):TuioPoint(ttime, xp,yp) +,state(TUIO_ADDED) +{ + container = tobj; + angle = a; + x_speed = 0.0f; + y_speed = 0.0f; + motion_speed = 0.0f; + motion_accel = 0.0f; + rotation_speed = 0.0f; + rotation_accel = 0.0f; + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); + } + +TuioComponent::TuioComponent (TuioObject *tobj, float xp, float yp, float a):TuioPoint(xp,yp) +,state(TUIO_ADDED) +{ + container = tobj; + angle = a; + x_speed = 0.0f; + y_speed = 0.0f; + motion_speed = 0.0f; + motion_accel = 0.0f; + rotation_speed = 0.0f; + rotation_accel = 0.0f; + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); +} + +TuioComponent::TuioComponent (TuioComponent *tcomp):TuioPoint(tcomp) +,state(TUIO_ADDED) +{ + container = tcomp->getContainingTuioObject(); + angle = tcomp->getAngle(); + x_speed = 0.0f; + y_speed = 0.0f; + motion_speed = 0.0f; + motion_accel = 0.0f; + rotation_speed = 0.0f; + rotation_accel = 0.0f; + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); +} + +TuioObject* TuioComponent::getContainingTuioObject() { + return container; +} + +void TuioComponent::setContainingTuioObject(TuioObject *tobj) { + container = tobj; +} + +void TuioComponent::update (TuioTime ttime, float xp, float yp, float a) { + 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; + + float last_angle = angle; + float last_rotation_speed = rotation_speed; + angle = a; + + double da = (angle-last_angle)/(2*M_PI); + if (da > 0.75f) da-=1.0f; + else if (da < -0.75f) da+=1.0f; + + rotation_speed = (float)da/dt; + rotation_accel = (rotation_speed - last_rotation_speed)/dt; + + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); + if (path.size()>MAX_PATH_SIZE) path.pop_front(); + + if (motion_accel>0) state = TUIO_ACCELERATING; + else if (motion_accel<0) state = TUIO_DECELERATING; + else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING; + else state = TUIO_STOPPED; + + container->update(ttime); +} + +void TuioComponent::stop(TuioTime ttime) { + update(ttime,xpos,ypos); + container->update(ttime); +} + +void TuioComponent::update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) { + TuioPoint::update(ttime,xp, yp); + angle = a; + x_speed = xs; + y_speed = ys; + motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed); + rotation_speed = rs; + motion_accel = ma; + rotation_accel = ra; + + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); + if (path.size()>MAX_PATH_SIZE) path.pop_front(); + + if (motion_accel>0) state = TUIO_ACCELERATING; + else if (motion_accel<0) state = TUIO_DECELERATING; + else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING; + else state = TUIO_STOPPED; + + container->update(ttime); + } + +void TuioComponent::update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) { + TuioPoint::update(xp,yp); + angle = a; + x_speed = xs; + y_speed = ys; + motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed); + rotation_speed = rs; + motion_accel = ma; + rotation_accel = ra; + + TuioPoint p(currentTime,xpos,ypos); + path.push_back(p); + if (path.size()>MAX_PATH_SIZE) path.pop_front(); + + if (motion_accel>0) state = TUIO_ACCELERATING; + else if (motion_accel<0) state = TUIO_DECELERATING; + else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING; + else state = TUIO_STOPPED; + + container->update(currentTime); +} + +void TuioComponent::update (TuioComponent *tcomp) { + TuioPoint::update(tcomp); + angle = tcomp->getAngle(); + x_speed = tcomp->getXSpeed(); + y_speed = tcomp->getYSpeed(); + motion_speed = tcomp->getMotionSpeed(); + rotation_speed = tcomp->getRotationSpeed(); + motion_accel = tcomp->getMotionAccel(); + rotation_accel = tcomp->getRotationAccel(); + + TuioPoint p(tcomp->getTuioTime(),xpos,ypos); + path.push_back(p); + if (path.size()>MAX_PATH_SIZE) path.pop_front(); + + if (motion_accel>0) state = TUIO_ACCELERATING; + else if (motion_accel<0) state = TUIO_DECELERATING; + else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING; + else state = TUIO_STOPPED; + + container->update(tcomp->getTuioTime()); +} + +void TuioComponent::remove(TuioTime ttime) { + currentTime = ttime; + state = TUIO_REMOVED; + container->update(ttime); +} + +unsigned int TuioComponent::getSessionID() const{ + return container->getSessionID(); +} + +float TuioComponent::getAngle() const{ + return angle; +} + +float TuioComponent::getAngleDegrees() const{ + return (float)(angle/M_PI*180); +} + +float TuioComponent::getXSpeed() const{ + return x_speed; +} + +float TuioComponent::getYSpeed() const{ + return y_speed; +} + +TuioPoint TuioComponent::getPosition() const{ + TuioPoint p(xpos,ypos); + return p; +} + +std::list TuioComponent::getPath() const{ + return path; +} + +float TuioComponent::getMotionSpeed() const{ + return motion_speed; +} + +float TuioComponent::getMotionAccel() const{ + return motion_accel; +} + +float TuioComponent::getRotationSpeed() const{ + return rotation_speed; +} + +float TuioComponent::getRotationAccel() const{ + return rotation_accel; +} + +int TuioComponent::getTuioState() const{ + return state; +} + +bool TuioComponent::isMoving() const{ + if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING) || (state==TUIO_ROTATING)) return true; + else return false; +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.h b/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.h new file mode 100644 index 0000000000..d7790efe8a --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioComponent.h @@ -0,0 +1,287 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOCOMPONENT_H +#define INCLUDED_TUIOCOMPONENT_H + +#include "TuioPoint.h" +#include +#include + +#define TUIO_IDLE 0 +#define TUIO_ADDED 1 +#define TUIO_ACCELERATING 2 +#define TUIO_DECELERATING 3 +#define TUIO_ROTATING 4 +#define TUIO_STOPPED 5 +#define TUIO_REMOVED 6 + +#define MAX_PATH_SIZE 128 + +namespace TUIO2 { + + /** + * The abstract TuioComponent class defines common attributes that apply to all subclasses {@link TuioToken}, {@link TuioPointer} and {@link TuioBounds}. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + + class TuioObject; + class LIBDECL TuioComponent: public TuioPoint { + + protected: + /** + * The TuioObject that contains this TUIO component. + */ + TuioObject *container; + /** + * The rotation angle value. + */ + float angle; + /** + * 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; + /** + * The rotation speed value. + */ + float rotation_speed; + /** + * The rotation acceleration value. + */ + float rotation_accel; + /** + * A List of TuioPoints containing all the previous positions of the TUIO component. + */ + std::list path; + /** + * Reflects the current state of the TuioComponent + */ + int state; + + public: + using TuioPoint::update; + + /** + * This constructor takes a TuioTime argument and assigns it along with the provided + * Session ID, X and Y coordinate to the newly created TuioComponent. + * + * @param ttime the TuioTime to assign + * @param tobj the TuioObject to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + */ + TuioComponent (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a); + + /** + * This constructor takes the provided Session ID, X and Y coordinate + * and assigs these values to the newly created TuioComponent. + * + * @param tobj the TuioObject to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + */ + TuioComponent (TuioObject *tobj, float xp, float yp,float a); + + /** + * This constructor takes the atttibutes of the provided TuioComponent + * and assigs these values to the newly created TuioComponent. + * + * @param tcon the TuioComponent to assign + */ + TuioComponent (TuioComponent *tcon); + + /** + * The destructor is doing nothing in particular. + */ + virtual ~TuioComponent(){}; + + /** + * Returns the TuioObject containing this TuioComponent. + * @return the TuioObject containing this TuioComponent + */ + virtual TuioObject* getContainingTuioObject(); + + /** + * Returns the TuioObject containing this TuioComponent. + * @param the TuioObject containing this TuioComponent + */ + virtual void setContainingTuioObject(TuioObject *tobj); + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate to the private TuioComponent 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 to assign + */ + virtual void update (TuioTime ttime, float xp, float yp, float a); + + /** + * This method is used to calculate the speed and acceleration values of + * TuioComponents with unchanged positions. + */ + virtual void stop(TuioTime ttime); + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate, X and Y velocity and acceleration + * to the private TuioComponent attributes. + * + * @param ttime the TuioTime to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle 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 + */ + virtual void update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra); + + /** + * Assigns the provided X and Y coordinate, X and Y velocity and acceleration + * to the private TuioComponent attributes. The TuioTime time stamp remains unchanged. + * + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle 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 + */ + virtual void update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra); + + /** + * Takes the atttibutes of the provided TuioComponent + * and assigs these values to this TuioComponent. + * The TuioTime time stamp of this TuioComponent remains unchanged. + * + * @param tcon the TuioComponent to assign + */ + virtual void update(TuioComponent *tcon); + + /** + * Assigns the REMOVE state to this TuioComponent and sets + * its TuioTime time stamp to the provided TuioTime argument. + * + * @param ttime the TuioTime to assign + */ + virtual void remove(TuioTime ttime); + + /** + * Returns the Session ID of this TuioComponent. + * @return the Session ID of this TuioComponent + */ + virtual unsigned int getSessionID() const; + + /** + * Returns the X velocity of this TuioComponent. + * @return the X velocity of this TuioComponent + */ + virtual float getXSpeed() const; + + /** + * Returns the Y velocity of this TuioComponent. + * @return the Y velocity of this TuioComponent + */ + virtual float getYSpeed() const; + + /** + * Returns the position of this TuioComponent. + * @return the position of this TuioComponent + */ + virtual TuioPoint getPosition() const; + + /** + * Returns the path of this TuioComponent. + * @return the path of this TuioComponent + */ + virtual std::list getPath() const; + + /** + * Returns the motion speed of this TuioComponent. + * @return the motion speed of this TuioComponent + */ + virtual float getMotionSpeed() const; + + /** + * Returns the motion acceleration of this TuioComponent. + * @return the motion acceleration of this TuioComponent + */ + virtual float getMotionAccel() const; + + /** + * Returns the rotation angle of this TuioComponent. + * @return the rotation angle of this TuioComponent + */ + float getAngle() const; + + /** + * Returns the rotation angle in degrees of this TuioComponent. + * @return the rotation angle in degrees of this TuioComponent + */ + float getAngleDegrees() const; + + /** + * Returns the rotation speed of this TuioComponent. + * @return the rotation speed of this TuioComponent + */ + float getRotationSpeed() const; + + /** + * Returns the rotation acceleration of this TuioComponent. + * @return the rotation acceleration of this TuioComponent + */ + float getRotationAccel() const; + + /** + * Returns the TUIO state of this TuioComponent. + * @return the TUIO state of this TuioComponent + */ + virtual int getTuioState() const; + + /** + * Returns true of this TuioComponent is moving. + * @return true of this TuioComponent is moving + */ + virtual bool isMoving() const; + }; +} +#endif // INCLUDED_TUIOCOMPONENT_H \ No newline at end of file diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.cpp new file mode 100644 index 0000000000..d3ff480026 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.cpp @@ -0,0 +1,165 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioDispatcher.h" + +#include +#include +#include +#include + +using namespace TUIO2; + +TuioDispatcher::TuioDispatcher() { +#ifndef WIN32 + pthread_mutex_init(&tobjMutex,NULL); +#else + tobjMutex = CreateMutex(NULL,FALSE,"tobjMutex"); +#endif +} + +TuioDispatcher::~TuioDispatcher() { +#ifndef WIN32 + pthread_mutex_destroy(&tobjMutex); +#else + CloseHandle(tobjMutex); +#endif +} + +void TuioDispatcher::lockObjectList() { +#ifndef WIN32 + pthread_mutex_lock(&tobjMutex); +#else + WaitForSingleObject(tobjMutex, INFINITE); +#endif +} + +void TuioDispatcher::unlockObjectList() { +#ifndef WIN32 + pthread_mutex_unlock(&tobjMutex); +#else + ReleaseMutex(tobjMutex); +#endif +} + +void TuioDispatcher::addTuioListener(TuioListener *listener) { + listenerList.push_back(listener); +} + +void TuioDispatcher::removeTuioListener(TuioListener *listener) { + std::list::iterator result = find(listenerList.begin(),listenerList.end(),listener); + if (result!=listenerList.end()) listenerList.remove(listener); +} + +void TuioDispatcher::removeAllTuioListeners() { + listenerList.clear(); +} + +TuioObject* TuioDispatcher::getTuioObject(unsigned int s_id) { + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + if((*tobj)->getSessionID()==s_id) { + unlockObjectList(); + return (*tobj); + } + } + unlockObjectList(); + return NULL; +} + +TuioToken* TuioDispatcher::getTuioToken(unsigned int s_id) { + TuioObject *tobj = getTuioObject(s_id); + if (tobj==NULL) return NULL; + + return tobj->getTuioToken(); +} + +TuioPointer* TuioDispatcher::getTuioPointer(unsigned int s_id) { + TuioObject *tobj = getTuioObject(s_id); + if (tobj==NULL) return NULL; + + return tobj->getTuioPointer(); +} + +TuioBounds* TuioDispatcher::getTuioBounds(unsigned int s_id) { + TuioObject *tobj = getTuioObject(s_id); + if (tobj==NULL) return NULL; + + return tobj->getTuioBounds(); +} + +TuioSymbol* TuioDispatcher::getTuioSymbol(unsigned int s_id) { + TuioObject *tobj = getTuioObject(s_id); + if (tobj==NULL) return NULL; + + return tobj->getTuioSymbol(); +} + +std::list TuioDispatcher::getTuioObjectList() { + std::list listBuffer; + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + listBuffer.push_back(*tobj); + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioDispatcher::getTuioTokenList() { + std::list listBuffer; + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + TuioToken *ttok = (*tobj)->getTuioToken(); + if (ttok!=NULL) listBuffer.push_back(ttok); + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioDispatcher::getTuioPointerList() { + std::list listBuffer; + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + TuioPointer *tptr = (*tobj)->getTuioPointer(); + if (tptr!=NULL) listBuffer.push_back(tptr); + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioDispatcher::getTuioBoundsList() { + std::list listBuffer; + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + TuioBounds *tbnd = (*tobj)->getTuioBounds(); + if (tbnd!=NULL) listBuffer.push_back(tbnd); + } + unlockObjectList(); + return listBuffer; +} + +std::list TuioDispatcher::getTuioSymbolList() { + std::list listBuffer; + lockObjectList(); + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + TuioSymbol *tsym = (*tobj)->getTuioSymbol(); + if (tsym!=NULL) listBuffer.push_back(tsym); + } + unlockObjectList(); + return listBuffer; +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.h b/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.h new file mode 100644 index 0000000000..966975fea3 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioDispatcher.h @@ -0,0 +1,169 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIODISPATCHER_H +#define INCLUDED_TUIODISPATCHER_H + +#include "TuioListener.h" + +#ifndef WIN32 +#include +#else +#include +#endif + +namespace TUIO2 { + + /** + *

The TuioDispatcher generates TUIO events which are broadcasted to all + * registered classes that implement the {@link TuioListener} interface.

+ * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioDispatcher { + + public: + /** + * This constructor creates a TuioDispatcher + * + */ + TuioDispatcher(); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioDispatcher(); + + /** + * 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(); + + /** + * Returns a List of all currently active TuioObject + * + * @return a List of all currently active TuioObject + */ + std::list getTuioObjectList(); + + /** + * Returns a List of all currently active TuioTokens + * + * @return a List of all currently active TuioTokens + */ + std::list getTuioTokenList(); + + /** + * Returns a List of all currently active TuioPointers + * + * @return a List of all currently active TuioPointers + */ + std::list getTuioPointerList(); + + /** + * Returns a List of all currently active TuioBounds + * + * @return a List of all currently active TuioBounds + */ + std::list getTuioBoundsList(); + + /** + * Returns a List of all currently active TuioSymbols + * + * @return a List of all currently active TuioSymbols + */ + std::list getTuioSymbolList(); + + /** + * 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(unsigned int s_id); + + /** + * Returns the TuioToken corresponding to the provided Session ID + * or NULL if the Session ID does not refer to an active TuioToken + * + * @return an active TuioToken corresponding to the provided Session ID or NULL + */ + TuioToken* getTuioToken(unsigned int s_id); + + /** + * Returns the TuioPointer corresponding to the provided Session ID + * or NULL if the Session ID does not refer to an active TuioPointer + * + * @return an active TuioPointer corresponding to the provided Session ID or NULL + */ + TuioPointer* getTuioPointer(unsigned int s_id); + + /** + * Returns the TuioBounds corresponding to the provided Session ID + * or NULL if the Session ID does not refer to an active TuioBounds + * + * @return an active TuioBounds corresponding to the provided Session ID or NULL + */ + TuioBounds* getTuioBounds(unsigned int s_id); + + /** + * Returns the TuioSymbol corresponding to the provided Session ID + * or NULL if the Session ID does not refer to an active TuioSymbol + * + * @return an active TuioSymbol corresponding to the provided Session ID or NULL + */ + TuioSymbol* getTuioSymbol(unsigned int s_id); + + /** + * Locks the TuioObject list in order to avoid updates during access + */ + void lockObjectList(); + + /** + * Releases the lock of the TuioObject list + */ + void unlockObjectList(); + + protected: + std::list listenerList; + std::list tobjList; + +#ifndef WIN32 + pthread_mutex_t tobjMutex; +#else + HANDLE tobjMutex; +#endif + + }; +} +#endif /* INCLUDED_TUIODISPATCHER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioListener.h b/modules/touch/ext/libTUIO2/TUIO2/TuioListener.h new file mode 100644 index 0000000000..160d756f33 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioListener.h @@ -0,0 +1,80 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOLISTENER_H +#define INCLUDED_TUIOLISTENER_H + +#include "TuioObject.h" + +namespace TUIO2 { + + /** + *

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.

+ *

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.

+ *

+ * public class MyTuioListener implements TuioListener
+ * ...

+ * MyTuioListener listener = new MyTuioListener();
+ * TuioClient client = new TuioClient();
+ * client.addTuioListener(listener);
+ * client.start();
+ *

+ * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioListener { + + public: + /** + * The destructor is doing nothing in particular. + */ + virtual ~TuioListener(){}; + + /** + * This callback method is invoked by the TuioClient when a new TUIO Component is added to the session. + * + * @param tobj the TuioObject reference that encapsulates all related TUIO Components + */ + virtual void tuioAdd(TuioObject *tobj)=0; + + /** + * This callback method is invoked by the TuioClient when an existing TUIO Component is updated during the session. + * + * @param tobj the TuioObject reference that encapsulates all related TUIO Components + */ + virtual void tuioUpdate(TuioObject *tobj)=0; + + /** + * This callback method is invoked by the TuioClient when a TUIO Component is removed from the session. + * + * @param tobj the TuioObject reference that encapsulates all related TUIO Components + */ + virtual void tuioRemove(TuioObject *tobj)=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 tuioRefresh(TuioTime ftime)=0; + }; +} +#endif /* INCLUDED_TUIOLISTENER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioManager.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioManager.cpp new file mode 100644 index 0000000000..070c8f39ba --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioManager.cpp @@ -0,0 +1,575 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioManager.h" +using namespace TUIO2; + +TuioManager::TuioManager() + : currentFrameTime(TuioTime::getSystemTime()) + , currentFrame(-1) + , pointerCount(0) + , maxPointerID(-1) + , sessionID(-1) + , tobjUpdate(false) + , verbose(false) + , invert_x(false) + , invert_y(false) + , invert_a(false) +{ + +} + +TuioManager::~TuioManager() { +} + +TuioObject* TuioManager::createTuioObject() { + sessionID++; + TuioObject *tobj = new TuioObject(sessionID); + tobjList.push_back(tobj); + return tobj; +} + +void TuioManager::addExternalTuioObject(TuioObject *tobj) { + if (tobj==NULL) return; + tobjList.push_back(tobj); + + TuioPointer *tptr = tobj->getTuioPointer(); + if (tptr!=NULL) pointerCount++; + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioAdd(tobj); + + if (verbose) std::cout << "add " << tobj->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::updateExternalTuioObject(TuioObject *tobj) { + if (tobj==NULL) return; + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioUpdate(tobj); + + if (verbose) std::cout << "set " << tobj->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::removeExternalTuioObject(TuioObject *tobj) { + if (tobj==NULL) return; + tobjList.remove(tobj); + + TuioPointer *tptr = tobj->getTuioPointer(); + if (tptr!=NULL) pointerCount--; + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioRemove(tobj); + + if (verbose) std::cout << "del " << tobj->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::removeTuioObject(unsigned int s_id) { + + TuioObject *tobj = NULL; + for(std::list::iterator iter = tobjList.begin();iter!= tobjList.end(); iter++) { + if((*iter)->getSessionID()==s_id) { + tobj = *iter; + break; + } + } + if (tobj==NULL) return; + else removeTuioObject(tobj); +} + +void TuioManager::removeTuioObject(TuioObject *tobj) { + + if (tobj== NULL) return; + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioRemove(tobj); + + if (tobj->containsTuioToken()) { + if (verbose) std::cout << "del tok " << tobj->getSessionID() << std::endl; + tobj->deleteTuioToken(); + } + + if (tobj->containsTuioPointer()) { + if (verbose) std::cout << "del ptr " << tobj->getSessionID() << std::endl; + tobj->deleteTuioPointer(); + } + + if (tobj->containsTuioBounds()) { + if (verbose) std::cout << "del bnd " << tobj->getSessionID() << std::endl; + tobj->deleteTuioBounds(); + } + + if (tobj->containsTuioSymbol()) { + if (verbose) std::cout << "del sym " << tobj->getSessionID() << std::endl; + tobj->deleteTuioSymbol(); + } + + tobjList.remove(tobj); + tobjUpdate = true; + delete tobj; +} + +TuioObject* TuioManager::createTuioToken(unsigned int sym, float x, float y, float a) { + return addTuioToken(NULL, sym, 0, 0, x, y, a); +} + +TuioObject* TuioManager::createTuioToken(unsigned int sym, unsigned short t_id, unsigned short u_id, float x, float y, float a) { + return addTuioToken(NULL, sym, t_id, u_id, x, y, a); +} + +TuioObject* TuioManager::addTuioToken(TuioObject *tobj, unsigned int sym, float x, float y, float a) { + return addTuioToken(tobj, sym, 0, 0, x, y, a); +} + +TuioObject* TuioManager::addTuioToken(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, float x, float y, float a) { + + TuioToken *ttok = new TuioToken(currentFrameTime, tobj, t_id, u_id, sym, x, y, a); + return addTuioToken(ttok); +} + +TuioObject* TuioManager::addTuioToken(TuioToken *ttok) { + if (ttok==NULL) return NULL; + + TuioObject *tobj = ttok->getContainingTuioObject(); + if (tobj==NULL) tobj = createTuioObject(); + tobj->setTuioToken(ttok); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) { + (*listener)->tuioAdd(tobj); + } + + if (verbose) std::cout << "add tok " << tobj->getSessionID() << std::endl; + tobjUpdate = true; + + return tobj; +} + +void TuioManager::updateTuioToken(TuioToken *ttok, float x, float y, float a) { + if (ttok==NULL) return; + if (ttok->getTuioTime()==currentFrameTime) return; + + ttok->update(currentFrameTime,x,y,a); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioUpdate(ttok->getContainingTuioObject()); + + if (verbose)std::cout << "set tok " << ttok->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::removeTuioToken(TuioToken *ttok) { + if (ttok==NULL) return; + + TuioObject *tobj = ttok->getContainingTuioObject(); + if (tobj==NULL) { + delete ttok; + return; + } else removeTuioObject(tobj); +} + +TuioObject* TuioManager::createTuioPointer(float x, float y, float a, float s, float r, float p) { + return addTuioPointer(NULL, 0, 0, x, y, a, s, r, p); +} + +TuioObject* TuioManager::createTuioPointer(unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) { + return addTuioPointer(NULL, t_id, u_id, x, y, a, s, r, p); +} + +TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, float x, float y, float a, float s, float r, float p) { + return addTuioPointer(tobj, 0, 0, x, y, a, s, r, p); +} + +TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) { + + int pointerID = pointerCount; + if ((pointerCount<=maxPointerID) && (freePointerList.size()>0)) { + std::list::iterator closestPointer = freePointerList.begin(); + + for(std::list::iterator iter = freePointerList.begin();iter!= freePointerList.end(); iter++) { + if((*iter)->getDistance(x,y)<(*closestPointer)->getDistance(x,y)) closestPointer = iter; + } + + TuioPointer *freePointer = (*closestPointer); + pointerID = (*closestPointer)->getPointerID(); + freePointerList.erase(closestPointer); + delete freePointer; + } else maxPointerID = pointerID; + + TuioPointer *tptr = new TuioPointer(currentFrameTime, tobj, t_id, u_id, pointerID, x, y, a, s, r, p); + return addTuioPointer(tptr); +} + +TuioObject* TuioManager::createTuioPointer(unsigned int p_id, float x, float y, float a, float s, float r, float p) { + + return addTuioPointer(NULL, p_id, 0, 0, x, y, a, s, r, p); +} + +TuioObject* TuioManager::createTuioPointer(unsigned int p_id, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) { + + return addTuioPointer(NULL, p_id, t_id, u_id, x, y, a, s, r, p); +} + +TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned int p_id, float x, float y, float a, float s, float r, float p) { + + return addTuioPointer(tobj, p_id, 0, 0, x, y, a, s, r, p); +} + +TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned int p_id, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) { + + TuioPointer *tptr = new TuioPointer(currentFrameTime, tobj, t_id, u_id, p_id, x, y, a, s, r, p); + return addTuioPointer(tptr); +} + +TuioObject* TuioManager::addTuioPointer(TuioPointer *tptr) { + if (tptr==NULL) return NULL; + + TuioObject *tobj = tptr->getContainingTuioObject(); + + if (tobj==NULL) tobj = createTuioObject(); + tobj->setTuioPointer(tptr); + pointerCount++; + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) { + (*listener)->tuioAdd(tobj); + } + + if (verbose) std::cout << "add ptr " << tobj->getSessionID() << std::endl; + tobjUpdate = true; + + return tobj; +} + +void TuioManager::updateTuioPointer(TuioPointer *tptr, float x, float y, float a, float s, float r, float p) { + if (tptr==NULL) return; + if (tptr->getTuioTime()==currentFrameTime) return; + + TuioObject *tobj = tptr->getContainingTuioObject(); + if (tobj==NULL) return; + + tptr->update(currentFrameTime,x,y,a,s,r,p); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioUpdate(tobj); + + if (verbose)std::cout << "set ptr " << tobj->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::removeTuioPointer(TuioPointer *tptr) { + if (tptr==NULL) return; + pointerCount--; + + TuioObject *tobj = tptr->getContainingTuioObject(); + + if (tptr->getPointerID()==maxPointerID) { + maxPointerID = -1; + + if (pointerCount>0) { + + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + if ((*iter)->containsTuioPointer()) { + int pointerID = (*iter)->getTuioPointer()->getPointerID(); + if (pointerID>maxPointerID) maxPointerID=pointerID; + } + } + + freePointerBuffer.clear(); + for (std::list::iterator flist=freePointerList.begin(); flist != freePointerList.end(); flist++) { + TuioPointer *freePointer = (*flist); + if (freePointer->getPointerID()<=maxPointerID) freePointerBuffer.push_back(new TuioPointer(freePointer)); + } + + freePointerList = freePointerBuffer; + + } else { + for (std::list::iterator flist=freePointerList.begin(); flist != freePointerList.end(); flist++) { + TuioPointer *freePointer = (*flist); + delete freePointer; + } + freePointerList.clear(); + } + } else if (tptr->getPointerID()getContainingTuioObject(); + + if (tobj==NULL) tobj = createTuioObject(); + tobj->setTuioBounds(tbnd); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) { + (*listener)->tuioAdd(tobj); + } + + if (verbose) std::cout << "add bnd " << tobj->getSessionID() << std::endl; + tobjUpdate = true; + + return tobj; +} + +void TuioManager::updateTuioBounds(TuioBounds *tbnd, float x, float y, float a, float w, float h, float f) { + if (tbnd==NULL) return; + if (tbnd->getTuioTime()==currentFrameTime) return; + + tbnd->update(currentFrameTime,x,y,a,w,h,f); + TuioObject *tobj = tbnd->getContainingTuioObject(); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioUpdate(tobj); + + if (verbose)std::cout << "set bnd " << tobj->getSessionID() << std::endl; + tobjUpdate = true; +} + +void TuioManager::removeTuioBounds(TuioBounds *tbnd) { + if (tbnd==NULL) return; + + TuioObject *tobj = tbnd->getContainingTuioObject(); + if (tobj==NULL) { + delete tbnd; + return; + } else removeTuioObject(tobj); +} + +TuioObject* TuioManager::createTuioSymbol(unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data) { + + return addTuioSymbol(NULL, t_id, u_id, sym, type, data); +} + +TuioObject* TuioManager::addTuioSymbol(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data) { + + TuioSymbol *tsym = new TuioSymbol(currentFrameTime, tobj, t_id, u_id, sym, type, data); + return addTuioSymbol(tsym); +} + +TuioObject* TuioManager::addTuioSymbol(TuioSymbol *tsym) { + if (tsym==NULL) return NULL; + + TuioObject *tobj = tsym->getContainingTuioObject(); + if (tobj==NULL) tobj = createTuioObject(); + tobj->setTuioSymbol(tsym); + + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) { + if (tobjUpdate)(*listener)->tuioUpdate(tobj); + else(*listener)->tuioAdd(tobj); + } + + if (verbose) std::cout << "add sym " << tobj->getSessionID() << std::endl; + tobjUpdate = true; + + return tobj; +} + +void TuioManager::removeTuioSymbol(TuioSymbol *tsym) { + if (tsym==NULL) return; + + TuioObject *tobj = tsym->getContainingTuioObject(); + if (tobj==NULL) { + delete tsym; + return; + } else removeTuioObject(tobj); +} + +int TuioManager::getSessionID() { + sessionID++; + if (sessionID==UINT_MAX) sessionID = 0; + return sessionID; +} + +int TuioManager::getFrameID() { + return currentFrame; +} + +TuioTime TuioManager::getFrameTime() { + return currentFrameTime; +} + +void TuioManager::initTuioFrame(TuioTime ttime) { + frameTimeTag = TuioTime::getSystemTimeTag(); + currentFrameTime = TuioTime(ttime); + currentFrame++; + if (currentFrame==UINT_MAX) currentFrame = 1; +} + +void TuioManager::commitTuioFrame() { + for (std::list::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) + (*listener)->tuioRefresh(currentFrameTime); + + if (verbose) std::cout << "refresh " << currentFrame << " " << currentFrameTime.getTotalMilliseconds() << std::endl; +} + +TuioToken* TuioManager::getClosestTuioToken(float xp, float yp) { + + TuioToken *closestToken = NULL; + float closestDistance = 1.0f; + + for (std::list::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + TuioToken *ttok = (*iter)->getTuioToken(); + if (ttok==NULL) continue; + float distance = ttok->getDistance(xp,yp); + if(distance::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) { + TuioPointer *tptr = (*iter)->getTuioPointer(); + if (tptr==NULL) continue; + float distance = tptr->getDistance(xp,yp); + if(distance::iterator iter=tobjList.begin(); iter!=tobjList.end(); iter++) { + TuioBounds *tbnd = (*iter)->getTuioBounds(); + if (tbnd==NULL) continue; + float distance = tbnd->getDistance(xp,yp); + if(distance TuioManager::getUntouchedObjects() { + + std::list untouched; + for (std::list::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) { + + bool touched = false; + if ((*tobj)->containsTuioToken()) { + if ((*tobj)->getTuioToken()->getTuioTime()==currentFrameTime) touched=true; + } + + if ((*tobj)->containsTuioPointer()) { + if ((*tobj)->getTuioPointer()->getTuioTime()==currentFrameTime) touched=true; + } + + if ((*tobj)->containsTuioBounds()) { + if ((*tobj)->getTuioToken()->getTuioTime()==currentFrameTime) touched=true; + } + + if ((*tobj)->containsTuioSymbol()) { + if ((*tobj)->getTuioSymbol()->getTuioTime()==currentFrameTime) touched=true; + } + + if (!touched) untouched.push_back(*tobj); + + } + return untouched; +} + +void TuioManager::stopUntouchedMovingObjects() { + + for (std::list::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) { + + if ((*tobj)->containsTuioToken()) { + TuioToken *ttok = (*tobj)->getTuioToken(); + if ((ttok->getTuioTime()!=currentFrameTime) && (ttok->isMoving())) { + ttok->stop(currentFrameTime); + if (verbose) std::cout << "set tok " << ttok->getSessionID() << std::endl; + tobjUpdate = true; + } + } + + if ((*tobj)->containsTuioPointer()) { + TuioPointer *tptr = (*tobj)->getTuioPointer(); + if ((tptr->getTuioTime()!=currentFrameTime) && (tptr->isMoving())) { + tptr->stop(currentFrameTime); + if (verbose) std::cout << "set ptr " << tptr->getSessionID() << std::endl; + tobjUpdate = true; + } + } + + if ((*tobj)->containsTuioBounds()) { + TuioBounds *tbnd = (*tobj)->getTuioBounds(); + if ((tbnd->getTuioTime()!=currentFrameTime) && (tbnd->isMoving())) { + tbnd->stop(currentFrameTime); + if (verbose) std::cout << "set bnd " << tbnd->getSessionID() << std::endl; + tobjUpdate = true; + } + } + + } +} + +void TuioManager::removeUntouchedStoppedObjects() { + std::list::iterator iter = tobjList.begin(); + while (iter!=tobjList.end()) { + TuioObject *tobj = (*iter); + if ((tobj->getTuioTime()!=currentFrameTime) && (!tobj->isMoving())) { + removeTuioObject(tobj); + iter = tobjList.begin(); + } else iter++; + } +} + +void TuioManager::resetTuioObjectList() { + + pointerCount=0; + std::list::iterator tobj = tobjList.begin(); + while (tobj!=tobjList.end()) { + removeTuioObject((*tobj)); + tobj = tobjList.begin(); + } +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioManager.h b/modules/touch/ext/libTUIO2/TUIO2/TuioManager.h new file mode 100644 index 0000000000..fac3d55327 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioManager.h @@ -0,0 +1,601 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOMANAGER_H +#define INCLUDED_TUIOMANAGER_H + +#include "TuioDispatcher.h" + +#include +#include +#include + +namespace TUIO2 { + /** + *

The TuioManager class is the central TUIO session management component.

+ *

During runtime the each frame is marked with the initFrame and commitFrame methods, + * while the currently present TuioTokens are managed by the server with ADD, UPDATE and REMOVE methods in analogy to the TuioClient's TuioListener interface.

+ *

+ * TuioManager *manager = new TuioManager();
+ * ...
+ * server->initTuioFrame(TuioTime::getSessionTime());
+ * TuioToken *ttok = server->addTuioToken(xpos,ypos, angle);
+ * TuioPointer *tptr = server->addTuioToken(xpos,ypos);
+ * TuioBounds *tbnd = server->addTuioBounds(xpos,ypos,width,height,angle);
+ * server->commitFrame();
+ * ...
+ * server->initFrame(TuioTime::getSessionTime());
+ * server->updateTuioToken(ttok, xpos,ypos, angle);
+ * server->updateTuioPointer(tptr, xpos,ypos);
+ * server->updateTuioBounds(tbnd, xpos,ypos,width,height,angle);
+ * server->commitFrame();
+ * ...
+ * server->initFrame(TuioTime::getSessionTime());
+ * server->removeTuioToken(ttok);
+ * server->removeTuioPointer(tptr);
+ * server->removeTuioBounds(tbnd);
+ * server->commitFrame();
+ *

+ * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioManager : public TuioDispatcher { + + public: + + /** + * The default constructor creates a TuioManager + */ + TuioManager(); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioManager(); + + /** + * 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 an internally managed TuioObject with a new Session ID + * and adds it to the TuioServer's internal list of TuioObjects + * + * @return the newly created but empty TuioObject + */ + TuioObject* createTuioObject(); + + /** + * Removes an internally managed TuioObject from the TuioServer's internal list of TuioObjects + * The provided TuioObject (and all its encapsulated TUIO Components) are deleted + * + * @param s_id the Session ID of the internal TuioObject to remove + */ + void removeTuioObject(unsigned int s_id); + + /** + * Removes an internally managed TuioObject from the TuioServer's internal list of TuioObjects + * The provided TuioObject (and all its encapsulated TUIO Components) are deleted + * + * @param tobj the internal TuioObject to remove + */ + void removeTuioObject(TuioObject *tobj); + + /** + * Creates a new TuioToken based on the given arguments. + * A new TuioObject containing that TuioToken is added + * to the TuioServer's internal list of TuioObjects + * and the TuioToken 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 TuioToken + */ + TuioObject* createTuioToken(unsigned int sym, float xp, float yp, float a); + + /** + * Creates a new TuioToken based on the given arguments. + * A new TuioObject containing that TuioToken is added + * to the TuioServer's internal list of TuioObjects + * and the TuioToken reference is returned to the caller. + * + * @param t_id the Type ID to assign + * @param u_id the User 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 + * @return a reference to the TuioObject of the TuioToken + */ + TuioObject* createTuioToken(unsigned int sym, unsigned short t_id, unsigned short u_id, float xp, float yp, float a); + + /** + * Creates a new TuioToken based on the given arguments. + * and adds it to an existing TuioObject with the Session ID + * from the TuioServer's internal list of TuioObjects + * and the TuioToken reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param t_id the Type ID to assign + * @param u_id the User 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 + * @return a reference to the TuioObject of the TuioToken + */ + TuioObject* addTuioToken(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, float xp, float yp, float a); + + /** + * Creates a new TuioToken based on the given arguments. + * and adds it to an existing TuioObject with the Session ID + * from the TuioServer's internal list of TuioObjects + * and the TuioToken reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param t_id the Type ID to assign + * @param u_id the User 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 + * @return a reference to the TuioObject of the TuioToken + */ + TuioObject* addTuioToken(TuioObject *tobj, unsigned int sym, float xp, float yp, float a); + + /** + * Adds the provided TuioToken to an existing TuioObject + * from the TuioServer's internal list of TuioObjects + * or creates the according TuioObject if not found. + * + * @param ttok the existing TuioToken to add + * @return a reference to the TuioObject of the TuioToken + */ + TuioObject* addTuioToken(TuioToken *ttok); + + /** + * Updates the referenced TuioToken based on the given arguments. + * + * @param ttok the TuioToken to update + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + */ + void updateTuioToken(TuioToken *ttok, float xp, float yp, float a); + + /** + * Removes the provided TuioToken from an existing TuioObject + * and also deletes the TuioObject with all other components + * + * @param ttok the TuioToken to remove + */ + void removeTuioToken(TuioToken *ttok); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* createTuioPointer(float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * and adds it to an existing TuioObject with the Session ID + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference of the TuioObject is returned to the caller. + * + * @param tobj the existing TuioObject + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* addTuioPointer(TuioObject *tobj, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* createTuioPointer(unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* addTuioPointer(TuioObject *tobj, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param p_id the Pointer ID to assign + * @param xp the X coordinate to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return reference to the created TuioPointer + */ + TuioObject* createTuioPointer(unsigned int p_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param p_id the Pointer ID to assign + * @param xp the X coordinate to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return reference to the created TuioPointer + */ + TuioObject* addTuioPointer(TuioObject *tobj, unsigned int p_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param p_id the Pointer ID to assign + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param xp the X coordinate to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* createTuioPointer(unsigned int p_id, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Creates a new TuioPointer based on the given arguments. + * The new TuioPointer is added to the TuioServer's internal list of active TuioPointers + * and a reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param p_id the Pointer ID to assign + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param xp the X coordinate to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* addTuioPointer(TuioObject *tobj, unsigned int p_id, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p); + + /** + * Adds the provided TuioPointer to an existing TuioObject + * from the TuioServer's internal list of TuioObjects + * or creates the according TuioObject if not found. + * + * @param tptr the existing TuioPointer to add + * @return a reference to the TuioObject of the TuioPointer + */ + TuioObject* addTuioPointer(TuioPointer *tptr); + + /** + * Updates the referenced TuioPointer based on the given arguments. + * + * @param tptr the TuioPointer to update + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the rotation angle to assign + * @param s the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + */ + void updateTuioPointer(TuioPointer *tptr, float xp, float yp, float a, float s, float r, float p); + + /** + * Removes the provided TuioPointer from an existing TuioObject + * and also deletes the TuioObject with all other components + * + * @param tptr the TuioPointer to remove + */ + void removeTuioPointer(TuioPointer *tptr); + + /** + * Creates a new TuioBounds based on the given arguments. + * The new TuioBounds is added to the TuioServer's internal list of active TuioBounds + * and a reference is returned to the caller. + * + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param angle the angle to assign + * @param width the width to assign + * @param height the height to assign + * @param area the area to assign + * @return a reference to the TuioObject of the TuioBounds + */ + TuioObject* createTuioBounds(float xp, float yp, float angle, float width, float height, float area); + + /** + * Creates a new TuioBounds based on the given arguments. + * The new TuioBounds is added to the TuioServer's internal list of active TuioBounds + * and a reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param angle the angle to assign + * @param width the width to assign + * @param height the height to assign + * @param area the area to assign + * @return a reference to the TuioObject of the TuioBounds + */ + TuioObject* addTuioBounds(TuioObject *tobj, float xp, float yp, float angle, float width, float height, float area); + + /** + * Adds the provided TuioBounds to an existing TuioObject + * from the TuioServer's internal list of TuioObjects + * or creates the according TuioObject if not found. + * + * @param tbnd the TuioBounds to add + * @return a reference to the TuioObject of the TuioBounds + */ + TuioObject* addTuioBounds(TuioBounds *tbnd); + + /** + * Updates the referenced TuioBounds based on the given arguments. + * + * @param tbnd the TuioToken to update + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param angle the angle to assign + * @param width the width to assign + * @param height the height to assign + * @param area the area to assign + */ + void updateTuioBounds(TuioBounds *tbnd, float xp, float yp, float angle, float width, float height, float area); + + /** + * Removes the referenced TuioBounds from the TuioServer's internal list of TuioObjects + * and also deletes its TuioObject (and all its encapsulated TUIO Components) + * + * @param tbnd the TuioBounds to remove + */ + void removeTuioBounds(TuioBounds *tbnd); + + /** + * Creates a new TuioSymbol based on the given arguments. + * The new TuioSymbol is added to the TuioServer's internal list of TuioObjects + * and a reference is returned to the caller. + * + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param sym the Symbol ID to assign + * @param type the type descriptor to assign + * @param data the synbol data to assign + * @return a reference to the TuioObject of the TuioSymbol + */ + TuioObject* createTuioSymbol(unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data); + + /** + * Creates a new TuioSymbol based on the given arguments. + * The new TuioSymbol is added to the TuioServer's internal list of TuioObjects + * and a reference is returned to the caller. + * + * @param tobj the existing TuioObject + * @param t_id the Type ID to assign + * @param u_id the User ID to assign + * @param sym the Symbol ID to assign + * @param type the type descriptor to assign + * @param data the synbol data to assign + * @return a reference to the TuioObject of the TuioSymbol + */ + TuioObject* addTuioSymbol(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data); + + /** + * Adds the provided TuioSymbol to an existing TuioObject + * from the TuioServer's internal list of TuioObjects + * or creates the according TuioObject if not found. + * + * @param tsym the TuioSymbol to add + * @return a reference to the TuioObject of the TuioSymbol + */ + TuioObject* addTuioSymbol(TuioSymbol *tsym); + + /** + * Removes the referenced TuioSymbol from the TuioServer's internal list of TuioObjects + * and also deletes its TuioObject (and all its encapsulated TUIO Components) + * + * @param tsym the TuioSymbol to remove + */ + void removeTuioSymbol(TuioSymbol *tsym); + + /** + * Initializes a new frame with the given TuioTime + * + * @param ttime the frame time + */ + void initTuioFrame(TuioTime ttime); + + /** + * Commits the current frame. + * Generates and sends TUIO messages of all currently active and updated TuioTokens and TuioPointers. + */ + void commitTuioFrame(); + + /** + * Returns the next available Session ID for external use. + * @return the next available Session ID for external use + */ + int getSessionID(); + + /** + * Returns the current frame ID for external use. + * @return the current frame ID for external use + */ + int getFrameID(); + + /** + * Returns the current frame time for external use. + * @return the current frame time for external use + */ + TuioTime getFrameTime(); + + /** + * Returns a List of all currently inactive TuioObjects + * + * @return a List of all currently inactive TuioObjects + */ + std::list getUntouchedObjects(); + + /** + * Calculates speed and acceleration values for all currently inactive TuioObjects + */ + void stopUntouchedMovingObjects(); + + /** + * Removes all currently inactive TuioObjects from the TuioServer's internal list + */ + void removeUntouchedStoppedObjects(); + + /** + * Returns the TuioToken closest to the provided coordinates + * or NULL if there isn't any active TuioToken + * + * @return the closest TuioToken to the provided coordinates or NULL + */ + TuioToken* getClosestTuioToken(float xp, float yp); + + /** + * Returns the TuioPointer closest to the provided coordinates + * or NULL if there isn't any active TuioPointer + * + * @return the closest TuioPointer corresponding to the provided coordinates or NULL + */ + TuioPointer* getClosestTuioPointer(float xp, float yp); + + /** + * Returns the TuioBounds closest to the provided coordinates + * or NULL if there isn't any active TuioBounds + * + * @return the closest TuioBounds corresponding to the provided coordinates or NULL + */ + TuioBounds* getClosestTuioBounds(float xp, float yp); + + /** + * The TuioServer prints verbose TUIO event messages to the console if set to true. + * @param verbose print verbose messages if set to true + */ + void setVerbose(bool verbose) { this->verbose=verbose; } + + void setInversion(bool ix, bool iy, bool ia) { + invert_x = ix; + invert_y = iy; + invert_a = ia; + }; + + void setInvertXpos(bool ix) { invert_x = ix; }; + void setInvertYpos(bool iy) { invert_y = iy; }; + void setInvertAngle(bool ia) { invert_a = ia; }; + bool getInvertXpos() { return invert_x; }; + bool getInvertYpos() { return invert_y; }; + bool getInvertAngle() { return invert_a; }; + void resetTuioObjectList(); + + protected: + std::list freePointerList; + std::list freePointerBuffer; + + TuioTime currentFrameTime; + osc::TimeTag frameTimeTag; + unsigned int currentFrame; + unsigned int pointerCount, maxPointerID; + unsigned int sessionID; + + bool tobjUpdate; + bool verbose; + + bool invert_x; + bool invert_y; + bool invert_a; + }; +} +#endif /* INCLUDED_TUIOMANAGER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioObject.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioObject.cpp new file mode 100644 index 0000000000..15836c1b4f --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioObject.cpp @@ -0,0 +1,311 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioObject.h" + +using namespace TUIO2; + +TuioObject::TuioObject (unsigned int s_id) { + currentTime = TuioTime::getSystemTime(); + session_id = s_id; + startTime = currentTime; + + token = NULL; + pointer = NULL; + bounds = NULL; + symbol = NULL; + state = TUIO_ADDED; +} + +TuioObject::TuioObject (TuioTime ttime, unsigned int s_id) { + currentTime = ttime; + session_id = s_id; + startTime = currentTime; + + token = NULL; + pointer = NULL; + bounds = NULL; + symbol = NULL; + state = TUIO_ADDED; +} + +TuioObject::TuioObject (TuioTime ttime, TuioSource *src, unsigned int s_id) { + currentTime = ttime; + session_id = s_id; + startTime = currentTime; + + setTuioSource(src); + token = NULL; + pointer = NULL; + bounds = NULL; + symbol = NULL; + state = TUIO_ADDED; +} + +TuioObject::~TuioObject() { + deleteAllTuioComponents(); +} + +unsigned int TuioObject::getSessionID() { + return session_id; +} + +void TuioObject::setTuioSource(TuioSource *src) { + source.setSourceString(src->getSourceID(),src->getSourceString()); +} + +TuioSource* TuioObject::getTuioSource() { + return &source; +} + +void TuioObject::setTuioToken (TuioToken *ttok) { + token = ttok; + token->setContainingTuioObject(this); + currentTime = TuioTime::getSystemTime(); + state = TUIO_ADDED; +} + +void TuioObject::setTuioPointer (TuioPointer *tptr) { + pointer = tptr; + pointer->setContainingTuioObject(this); + currentTime = TuioTime::getSystemTime(); + state = TUIO_ADDED; +} + +void TuioObject::setTuioBounds (TuioBounds *tbnd) { + bounds = tbnd; + bounds->setContainingTuioObject(this); + currentTime = TuioTime::getSystemTime(); + state = TUIO_ADDED; +} + +void TuioObject::setTuioSymbol (TuioSymbol *tsym) { + symbol = tsym; + symbol->setContainingTuioObject(this); + currentTime = TuioTime::getSystemTime(); + state = TUIO_ADDED; +} + +void TuioObject::removeAllTuioComponents(TuioTime ttime) { + removeTuioToken(ttime); + removeTuioPointer(ttime); + removeTuioBounds(ttime); + removeTuioSymbol(ttime); +} + +void TuioObject::removeTuioToken (TuioTime ttime) { + if (token != NULL) token->remove(ttime); + currentTime = ttime; + } + +void TuioObject::removeTuioPointer (TuioTime ttime) { + if (pointer != NULL) pointer->remove(ttime); + currentTime = ttime; +} + +void TuioObject::removeTuioBounds (TuioTime ttime) { + if (bounds != NULL) bounds->remove(ttime); + currentTime = ttime; +} + +void TuioObject::removeTuioSymbol (TuioTime ttime) { + if (symbol != NULL) symbol->remove(ttime); + currentTime = ttime; +} + +void TuioObject::deleteAllTuioComponents() { + deleteTuioToken(); + deleteTuioPointer(); + deleteTuioBounds(); + deleteTuioSymbol(); +} + +void TuioObject::deleteTuioToken () { + if (token != NULL) { + delete token; + token = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::deleteTuioPointer () { + if (pointer != NULL) { + delete pointer; + pointer = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::deleteTuioBounds () { + if (bounds != NULL) { + delete bounds; + bounds = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::deleteTuioSymbol () { + if (symbol != NULL) { + delete symbol; + symbol = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::clearAllTuioComponents() { + clearTuioToken(); + clearTuioPointer(); + clearTuioBounds(); + clearTuioSymbol(); +} + +void TuioObject::clearTuioToken () { + if (token != NULL) { + token = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::clearTuioPointer () { + if (pointer != NULL) { + pointer = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::clearTuioBounds () { + if (bounds != NULL) { + bounds = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +void TuioObject::clearTuioSymbol () { + if (symbol != NULL) { + symbol = NULL; + //currentTime = TuioTime::getSessionTime(); + } +} + +bool TuioObject::containsAnyTuioComponent () { + if (token != NULL) return true; + else if (pointer != NULL) return true; + else if (bounds != NULL) return true; + else if (symbol != NULL) return true; + else return false; +} + +bool TuioObject::containsTuioToken () { + if (token != NULL) return true; + else return false; +} + +bool TuioObject::containsTuioPointer () { + if (pointer != NULL) return true; + else return false; +} + +bool TuioObject::containsTuioBounds () { + if (bounds != NULL) return true; + else return false; +} + +bool TuioObject::containsTuioSymbol () { + if (symbol != NULL) return true; + else return false; +} + +bool TuioObject::containsNewTuioToken () { + if (token == NULL) return false; + else if (token->getTuioState()==TUIO_ADDED) return true; + else return false; +} + +bool TuioObject::containsNewTuioPointer () { + if (pointer == NULL) return false; + else if (pointer->getTuioState()==TUIO_ADDED) return true; + else return false; +} + +bool TuioObject::containsNewTuioBounds () { + if (bounds == NULL) return false; + else if (bounds->getTuioState()==TUIO_ADDED) return true; + else return false; +} + +bool TuioObject::containsNewTuioSymbol () { + if (symbol == NULL) return false; + else if (symbol->getTuioState()==TUIO_ADDED) return true; + else return false; +} + +TuioToken* TuioObject::getTuioToken () { + return token; +} + +TuioPointer* TuioObject::getTuioPointer () { + return pointer; +} + +TuioBounds* TuioObject::getTuioBounds () { + return bounds; +} + +TuioSymbol* TuioObject::getTuioSymbol () { + return symbol; +} + +void TuioObject::stop(TuioTime ttime){ + if (token!=NULL) token->stop(ttime); + if (pointer!=NULL) pointer->stop(ttime); + if (bounds!=NULL) bounds->stop(ttime); + currentTime = ttime; +} + +void TuioObject::remove(TuioTime ttime){ + if (token!=NULL) token->remove(ttime); + if (pointer!=NULL) pointer->remove(ttime); + if (bounds!=NULL) bounds->remove(ttime); + currentTime = ttime; + state = TUIO_REMOVED; +} + +void TuioObject::update(TuioTime ttime){ + currentTime = ttime; + state = TUIO_IDLE; +} + +bool TuioObject::isMoving(){ + if ((token!=NULL) && token->isMoving()) return true; + if ((pointer!=NULL) && pointer->isMoving()) return true; + if ((bounds!=NULL) && bounds->isMoving()) return true; + return false; +} + +TuioTime TuioObject::getTuioTime() const{ + return currentTime; +} + +TuioTime TuioObject::getStartTime() const{ + return startTime; +} + +unsigned char TuioObject::getTuioState() const{ + return state; +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioObject.h b/modules/touch/ext/libTUIO2/TUIO2/TuioObject.h new file mode 100644 index 0000000000..4e18103b86 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioObject.h @@ -0,0 +1,341 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOOBJECT_H +#define INCLUDED_TUIOOBJECT_H + +#include "TuioTime.h" +#include "TuioToken.h" +#include "TuioPointer.h" +#include "TuioBounds.h" +#include "TuioSymbol.h" +#include "TuioSource.h" + +namespace TUIO2 { + + /** + * The TuioObject class encapsulates all Tuio objects that share the same Session ID. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + + class LIBDECL TuioObject { + + protected: + /** + * The shared session ID + */ + unsigned int session_id; + /** + * The associated TuioSource + */ + TuioSource source; + /** + * the associated TuioToken + */ + TuioToken *token; + /** + * the associated TuioPointer + */ + TuioPointer *pointer; + /** + * the associated TuioBounds + */ + TuioBounds *bounds; + /** + * the associated TuioSymbol + */ + TuioSymbol *symbol; + /** + * The time stamp of the last update represented as TuioTime (time since session start) + */ + TuioTime currentTime; + /** + * The creation time of this TuioObject represented as TuioTime (time since session start) + */ + TuioTime startTime; + /** + * Reflects the current state of the TuioObject + */ + unsigned char state; + + public: + /** + * The default constructor only takes the Session ID + * @param s_id the Session ID to assign + */ + TuioObject (unsigned int s_id); + + /** + * This constructor takes a TuioTime and the Session ID + * @param ttime the TuioTime to assign + * @param s_id the Session ID to assign + */ + TuioObject (TuioTime ttime, unsigned int s_id); + + /** + * This constructor takes a TuioTime and the Session ID + * @param ttime the TuioTime to assign + * @param src the TuioSource to assign + * @param s_id the Session ID to assign + */ + TuioObject (TuioTime ttime, TuioSource *src, unsigned int s_id); + + /** + * The default destructor also delets all assigned TUIO components + */ + ~TuioObject (); + + /** + * Returns the associated Session ID + * @return the associated Session ID + */ + unsigned int getSessionID(); + + /** + * Sets the assotiated TUIO source + * + * @param src the TuioSource to assign + */ + void setTuioSource(TuioSource *src); + + /** + * Returns the associated TUIO source + */ + TuioSource* getTuioSource(); + + /** + * This method assigns a TuioToken to this TuioObject + * @param ttok the TuioToken to assign + */ + void setTuioToken(TuioToken *ttok); + + /** + * This method assigns a TuioPointer to this TuioObject + * @param tptr the TuioPointer to assign + */ + void setTuioPointer(TuioPointer *tptr); + + /** + * This method assigns a TuioBounds to this TuioObject + * @param tbnd the TuioBounds to assign + */ + void setTuioBounds(TuioBounds *tbnd); + + /** + * This method assigns a TuioSymbol to this TuioObject + * @param tsym the TuioSymbol to assign + */ + void setTuioSymbol(TuioSymbol *tsym); + + /** + * This method sets all TuioComponents in this TuioObject to TUIO_REMOVED state + */ + void removeAllTuioComponents(TuioTime ttime); + + /** + * This method sets the TuioToken in this TuioObject to TUIO_REMOVED state + */ + void removeTuioToken(TuioTime ttime); + + /** + * This method sets the TuioPointer in this TuioObject to TUIO_REMOVED state + */ + void removeTuioPointer(TuioTime ttime); + + /** + * This method sets the TuioBounds in this TuioObject to TUIO_REMOVED state + */ + void removeTuioBounds(TuioTime ttime); + + /** + * This method sets the TuioSymbol in this TuioObject to TUIO_REMOVED state + */ + void removeTuioSymbol(TuioTime ttime); + + /** + * This method deletes all TuioComponents in this TuioObject + */ + void deleteAllTuioComponents(); + + /** + * This method deletes the TuioToken in this TuioObject + */ + void deleteTuioToken(); + + /** + * This method deletes the TuioPointer in this TuioObject + */ + void deleteTuioPointer(); + + /** + * This method deletes the TuioBounds in this TuioObject + */ + void deleteTuioBounds(); + + /** + * This method deletes the TuioSymbol in this TuioObject + */ + void deleteTuioSymbol(); + + /** + * This method clears all TuioComponents in this TuioObject + */ + void clearAllTuioComponents(); + + /** + * This method clears the TuioToken in this TuioObject + */ + void clearTuioToken(); + + /** + * This method clears the TuioPointer in this TuioObject + */ + void clearTuioPointer(); + + /** + * This method clears the TuioBounds in this TuioObject + */ + void clearTuioBounds(); + + /** + * This method clears the TuioSymbol in this TuioObject + */ + void clearTuioSymbol(); + + /** + * This method tests for any TuioComponent in this TuioObject + * @return true if any TuioComponent has been assigned + */ + bool containsAnyTuioComponent(); + + /** + * This method tests for a TuioToken in this TuioObject + * @return true if a TuioToken has been assigned + */ + bool containsTuioToken(); + + /** + * This method tests for a TuioPointer in this TuioObject + * @return true if a TuioPointer has been assigned + */ + bool containsTuioPointer(); + + /** + * This method tests for a TuioBounds in this TuioObject + * @return true if a TuioBounds has been assigned + */ + bool containsTuioBounds(); + + /** + * This method tests for a TuioSymbol in this TuioObject + * @return true if a TuioSymbol has been assigned + */ + bool containsTuioSymbol(); + + /** + * This method tests if a new TuioToken has been added to this TuioObject + * @return true if a TuioToken has been added + */ + bool containsNewTuioToken(); + + /** + * This method tests if a new TuioPointer has been added this TuioObject + * @return true if a TuioPointer has been added + */ + bool containsNewTuioPointer(); + + /** + * This method tests if a new TuioBounds has been added to this TuioObject + * @return true if a TuioBounds has been added + */ + bool containsNewTuioBounds(); + + /** + * This method tests if a new TuioSymbol has beed added to this TuioObject + * @return true if a TuioSymbol has been added + */ + bool containsNewTuioSymbol(); + + /** + * This method returns the TuioToken associated to this TuioObject + * @return the associated TuioToken + */ + TuioToken* getTuioToken(); + + /** + * This method returns the TuioPointer associated to this TuioObject + * @return the associated TuioPointer + */ + TuioPointer* getTuioPointer(); + + /** + * This method returns the TuioBounds associated to this TuioObject + * @return the associated TuioBounds + */ + TuioBounds* getTuioBounds(); + + /** + * This method returns the TuioSymbol associated to this TuioObject + * @return the associated TuioSymbol + */ + TuioSymbol* getTuioSymbol(); + + /** + * This method stops all encapsulated TuioComponents + */ + void stop(TuioTime ttime); + + /** + * This method removes all encapsulated TuioComponents + */ + void remove(TuioTime ttime); + + /** + * This method returns true if any encapsulated TuioComponent is moving + */ + bool isMoving(); + + /** + * This method refreshes the currentTime after an update + */ + void update(TuioTime ttime); + + /** + * Returns current time stamp of this TuioPoint as TuioTime + * + * @return the time stamp of this TuioPoint as TuioTime + */ + TuioTime getTuioTime() const; + + /** + * Returns the start time of this TuioPoint as TuioTime. + * + * @return the start time of this TuioPoint as TuioTime + */ + TuioTime getStartTime() const; + + /** + * Returns the TUIO state of this TuioObject. + * @return the TUIO state of this TuioObject + */ + unsigned char getTuioState() const; + }; +} +#endif // INCLUDED_TUIOOBJECT_H diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.cpp new file mode 100644 index 0000000000..935a63db77 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.cpp @@ -0,0 +1,124 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioPoint.h" + +using namespace TUIO2; + +TuioPoint::TuioPoint (float xp, float yp) { + xpos = xp; + ypos = yp; + currentTime = TuioTime::getSystemTime(); + startTime = currentTime; +} + +TuioPoint::TuioPoint (TuioTime ttime, float xp, float yp) { + xpos = xp; + ypos = yp; + currentTime = ttime; + startTime = currentTime; +} + +TuioPoint::TuioPoint (TuioPoint *tpoint) { + xpos = tpoint->getX(); + ypos = tpoint->getY(); + currentTime = TuioTime::getSystemTime(); + startTime = currentTime; +} + +void TuioPoint::update (TuioPoint *tpoint) { + xpos = tpoint->getX(); + ypos = tpoint->getY(); +} + +void TuioPoint::update (float xp, float yp) { + xpos = xp; + ypos = yp; +} + +void TuioPoint::update (TuioTime ttime, float xp, float yp) { + xpos = xp; + ypos = yp; + currentTime = ttime; +} + + +float TuioPoint::getX() const{ + return xpos; +} + +float TuioPoint::getY() const{ + return ypos; +} + +float TuioPoint::getDistance(float xp, float yp) const{ + float dx = xpos-xp; + float dy = ypos-yp; + return sqrtf(dx*dx+dy*dy); +} + +float TuioPoint::getScreenDistance(float xp, float yp, int w, int h) const{ + float dx = w*xpos-w*xp; + float dy = h*ypos-h*yp; + return sqrtf(dx*dx+dy*dy); +} + +float TuioPoint::getDistance(TuioPoint *tpoint) const{ + return getDistance(tpoint->getX(),tpoint->getY()); +} + + +float TuioPoint::getAngle(float xp, float yp) const{ + 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; +} + +float TuioPoint::getAngle(TuioPoint *tpoint) const{ + return getAngle(tpoint->getX(),tpoint->getY()); +} + +float TuioPoint::getAngleDegrees(float xp, float yp) const{ + return ((getAngle(xp,yp)/(float)M_PI)*180.0f); +} + +float TuioPoint::getAngleDegrees(TuioPoint *tpoint) const{ + return ((getAngle(tpoint)/(float)M_PI)*180.0f); +} + +int TuioPoint::getScreenX(int width) const{ + return (int)floor(xpos*width+0.5f); +} + +int TuioPoint::getScreenY(int height) const{ + return (int)floor(ypos*height+0.5f); +} + +TuioTime TuioPoint::getTuioTime() const{ + return currentTime; +} + +TuioTime TuioPoint::getStartTime() const{ + return startTime; +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.h b/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.h new file mode 100644 index 0000000000..a66730eb64 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioPoint.h @@ -0,0 +1,213 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOPOINT_H +#define INCLUDED_TUIOPOINT_H + +#include "TuioTime.h" +#include "limits.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +namespace TUIO2 { + + /** + * The TuioPoint class on the one hand is a simple tobj and utility class to handle TUIO positions in general, + * on the other hand the TuioPoint is the base class for the TuioPointer and TuioToken classes. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL 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: + /** + * This constructor takes two floating point coordinate arguments + * and sets the coordinate attributes to these values. + * + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + */ + TuioPoint (float xp, float yp); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + /** + * Returns the X coordinate of this TuioPoint. + * @return the X coordinate of this TuioPoint + */ + float getX() const; + + /** + * Returns the Y coordinate of this TuioPoint. + * @return the Y coordinate of this TuioPoint + */ + float getY() const; + + /** + * 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) const; + + /** + * 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 getScreenDistance(float xp, float yp, int w, int h) const; + /** + * Returns the distance to the provided TuioPoint + * + * @param tpoint the distant TuioPoint + * @return the distance to the provided TuioPoint + */ + float getDistance(TuioPoint *tpoint) const; + /** + * 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) const; + /** + * Returns the angle to the provided TuioPoint + * + * @param tpoint the distant TuioPoint + * @return the angle to the provided TuioPoint + */ + float getAngle(TuioPoint *tpoint) const; + /** + * 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) const; + /** + * 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) const; + /** + * 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) const; + /* + * 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) const; + /** + * Returns current time stamp of this TuioPoint as TuioTime + * + * @return the time stamp of this TuioPoint as TuioTime + */ + TuioTime getTuioTime() const; + /** + * Returns the start time of this TuioPoint as TuioTime. + * + * @return the start time of this TuioPoint as TuioTime + */ + TuioTime getStartTime() const; + }; +} +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.cpp new file mode 100644 index 0000000000..ffdb5066da --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.cpp @@ -0,0 +1,132 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioPointer.h" + +using namespace TUIO2; + +TuioPointer::TuioPointer (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(ttime,tobj,xp,yp,a) { + type_id = ti; + user_id = ui; + pointer_id = pi; + shear = sa; + radius = r; + pressure = p; +} + +TuioPointer::TuioPointer (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(tobj,xp,yp,a) { + type_id = ti; + user_id = ui; + shear = sa; + pointer_id = pi; + radius = r; + pressure = p; +} + +TuioPointer::TuioPointer (TuioObject *tobj, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(tobj,xp,yp,a) { + type_id = 0; + user_id = 0; + pointer_id = pi; + shear = sa; + radius = r; + pressure = p; +} + +TuioPointer::TuioPointer (TuioPointer *tptr):TuioComponent(tptr) { + pointer_id = tptr->getPointerID(); + type_id = tptr->getTypeID(); + user_id = tptr->getUserID(); + shear = tptr->getShear(); + radius = tptr->getRadius(); + pressure = tptr->getPressure(); +} + +void TuioPointer::update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa) { + TuioComponent::update(ttime,xp,yp,a,xs,ys,0,ma,0); + shear = sa; + radius = r; + pressure = p; + pressure_speed = ps; + pressure_accel = pa; +} + +void TuioPointer::update (float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa) { + TuioComponent::update(xp,yp,a,xs,ys,0,ma,0); + shear = sa; + radius = r; + pressure = p; + pressure_speed = ps; + pressure_accel = pa; +} + +void TuioPointer::update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p) { + TuioComponent::update(ttime,xp,yp,a); + shear = sa; + radius = r; + pressure = p; +} + +void TuioPointer::update (TuioPointer *tptr) { + TuioComponent::update(tptr); + shear = tptr->getShear(); + radius = tptr->getRadius(); + pressure = tptr->getPressure(); +} + +unsigned int TuioPointer::getPointerID() const{ + return pointer_id; +}; + +unsigned short TuioPointer::getTypeID() const{ + return type_id; +}; + +unsigned short TuioPointer::getUserID() const{ + return user_id; +}; + +unsigned int TuioPointer::getTypeUserID() const { + int tu_id = user_id << 16 | type_id; + return tu_id; +} + +void TuioPointer::setTypeUserID(unsigned int tu_id) { + user_id = tu_id >> 16; + type_id = tu_id & 0x0000FFFF; +} + +float TuioPointer::getShear() const{ + return shear; +}; + +float TuioPointer::getRadius() const{ + return radius; +}; + +float TuioPointer::getPressure() const{ + return pressure; +}; + +float TuioPointer::getPressureSpeed() const{ + return pressure_speed; +} + +float TuioPointer::getPressureAccel() const{ + return pressure_accel; +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.h b/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.h new file mode 100644 index 0000000000..43ffe72caf --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioPointer.h @@ -0,0 +1,263 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOPOINTER_H +#define INCLUDED_TUIOPOINTER_H + +#include "TuioComponent.h" + +namespace TUIO2 { + + /** + * The TuioPointer class encapsulates /tuio2/ptr TUIO pointers. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + + class LIBDECL TuioPointer: public TuioComponent { + + protected: + /** + * The individual pointer ID number that is assigned to each TuioPointer. + */ + unsigned int pointer_id; + + /** + * The pointer type ID that is assigned to each TuioPointer. + */ + unsigned short type_id; + + /** + * The user ID that is assigned to each TuioPointer. + */ + unsigned short user_id; + + /** + * The shear angle that is assigned to each TuioPointer. + */ + float shear; + + /** + * The action radius that is assigned to each TuioPointer. + */ + float radius; + + /** + * The pressure that is assigned to each TuioPointer. + */ + float pressure; + + /** + * The pressure speed value. + */ + float pressure_speed; + + /** + * The pressure acceleration value. + */ + float pressure_accel; + + public: + using TuioComponent::update; + + /** + * This constructor takes a TuioTime argument and assigns it along with the provided + * Session ID, Pointer ID, X and Y coordinate to the newly created TuioPointer. + * + * @param ttime the TuioTime to assign + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User ID to assign + * @param pi the Pointer ID to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + */ + TuioPointer (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p); + + /** + * This constructor takes the provided Session ID, Pointer ID, X and Y coordinate + * and assigs these values to the newly created TuioPointer. + * + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User ID to assign + * @param pi the Pointer ID to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + */ + TuioPointer (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p); + + + /** + * This constructor takes the provided Session ID, Pointer ID, X and Y coordinate + * and assigs these values to the newly created TuioPointer. + * + * @param tobj the TuioObject to assign + * @param pi the Pointer ID to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + */ + TuioPointer (TuioObject *tobj, unsigned int pi, float xp, float yp, float a, float sa, float r, float p); + + /** + * This constructor takes the atttibutes of the provided TuioPointer + * and assigs these values to the newly created TuioPointer. + * + * @param tptr the TuioPointer to assign + */ + TuioPointer (TuioPointer *tptr); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioPointer(){}; + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate, width, pressure, X and Y velocity, motion acceleration, + * @param ttime the TuioTime to assign + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @param xs the X velocity to assign + * @param ys the Y velocity to assign + * @param ps the pressure velocity to assign + * @param ma the motion acceleration to assign + * @param pa the pressure acceleration to assign + */ + void update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa); + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate, width, pressure, X and Y velocity, motion acceleration, + * @param xp the X coordinate to assign + * @param yp the Y coordinate to assign + * @param a the angle to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + * @param xs the X velocity to assign + * @param ys the Y velocity to assign + * @param ps the pressure velocity to assign + * @param ma the motion acceleration to assign + * @param pa the pressure acceleration to assign + */ + void update (float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa); + + /** + * Takes a TuioTime argument and assigns it along with the provided + * X and Y coordinate and angle to the private TuioToken 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 to assign + * @param sa the shear angle to assign + * @param r the radius to assign + * @param p the pressure to assign + */ + void update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p); + + /** + * Takes the atttibutes of the provided TuioPointer + * and assigs these values to this TuioPointer. + * The TuioTime time stamp of this TuioComponent remains unchanged. + * + * @param ttok the TuioComponent to assign + */ + void update (TuioPointer *tptr); + + /** + * Returns the Pointer ID of this TuioPointer. + * @return the Pointer ID of this TuioPointer + */ + unsigned int getPointerID() const; + + /** + * Returns the Type ID of this TuioPointer. + * @return the Type ID of this TuioPointer + */ + unsigned short getTypeID() const; + + /** + * Returns the User ID of this TuioPointer. + * @return the User ID of this TuioPointer + */ + unsigned short getUserID() const; + + /** + * Returns the encoded Type & User ID of this TuioPointer. + * @return the encoded Type & User ID of this TuioPointer + */ + unsigned int getTypeUserID() const; + + /** + * Decodes and assigns the Type & User ID to this TuioPointer. + * @param tu_id the encoded Type & User ID of this TuioPointer + */ + void setTypeUserID(unsigned int tu_id); + + /** + * Returns the shear angle of this TuioPointer. + * @return the shear angle of this TuioPointer + */ + float getShear() const; + + /** + * Returns the action radius of this TuioPointer. + * @return the action radius of this TuioPointer + */ + float getRadius() const; + + /** + * Returns the Pressure of this TuioPointer. + * @return the Pressure of this TuioPointer + */ + float getPressure() const; + + /** + * Returns the pressure speed of this TuioPointer. + * @return the pressure speed of this TuioPointer + */ + float getPressureSpeed() const; + + /** + * Returns the pressure acceleration of this TuioPointer. + * @return the pressure acceleration of this TuioPointer + */ + float getPressureAccel() const; + }; +} +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioServer.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioServer.cpp new file mode 100644 index 0000000000..9d599f774f --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioServer.cpp @@ -0,0 +1,329 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioServer.h" +#include "UdpSender.h" + +using namespace TUIO2; +using namespace osc; + +TuioServer::TuioServer() + :local_sender (true) + ,full_update (false) + ,periodic_update (false) + ,source (NULL) +{ + primary_sender = new UdpSender(); + initialize(); +} + +TuioServer::TuioServer(const char *host, unsigned short port) +:local_sender (true) +,full_update (false) +,periodic_update (false) +,source (NULL) +{ + primary_sender = new UdpSender(host,port); + initialize(); +} + +TuioServer::TuioServer(OscSender *oscsend) + :primary_sender (oscsend) + ,local_sender (false) + ,full_update (false) + ,periodic_update (false) + ,source (NULL) +{ + initialize(); +} + +void TuioServer::initialize() { + + senderList.push_back(primary_sender); + int size = primary_sender->getBufferSize(); + oscBuffer = new char[size]; + oscPacket = new osc::OutboundPacketStream(oscBuffer,size); + fullBuffer = new char[size]; + fullPacket = new osc::OutboundPacketStream(oscBuffer,size); + + updateTime = TuioTime(currentFrameTime); + //sendEmptyTuioBundle(); + + invert_x = false; + invert_y = false; + invert_a = false; +} + +TuioServer::~TuioServer() { + + initTuioFrame(TuioTime::getSystemTime()); + stopUntouchedMovingObjects(); + + initTuioFrame(TuioTime::getSystemTime()); + removeUntouchedStoppedObjects(); + sendEmptyTuioBundle(); + + delete []oscBuffer; + delete oscPacket; + delete []fullBuffer; + delete fullPacket; + + if (local_sender) delete primary_sender; +} + +void TuioServer::addOscSender(OscSender *sender) { + + // add source address if previously local + /*if ((source_name) && (primary_sender->isLocal()) && (senderList.size()==1)) { + setSourceName(source_name); + }*/ + + // resize packets to smallest transport method + unsigned int size = sender->getBufferSize(); + if (sizeCapacity()) { + osc::OutboundPacketStream *temp = oscPacket; + oscPacket = new osc::OutboundPacketStream(oscBuffer,size); + delete temp; + temp = fullPacket; + fullPacket = new osc::OutboundPacketStream(oscBuffer,size); + delete temp; + + } + + senderList.push_back(sender); +} + +void TuioServer::deliverOscPacket(osc::OutboundPacketStream *packet) { + + for (unsigned int i=0;isendOscPacket(packet); +} + +void TuioServer::setSourceName(const char* name) { + if (source==NULL) source = new TuioSource(name); + //else source->setSourceName(name); +} + +void TuioServer::setDimension(unsigned short w, unsigned short h) { + if (source!=NULL) source->setDimension(w,h); + + // decoder test + /*int dim = source->getDimension(); + short width = dim >> 16; + short height = dim & 0x0000FFFF; + printf("dim: %i %i\n",width,height);*/ +} + +void TuioServer::commitTuioFrame() { + TuioManager::commitTuioFrame(); + + if(tobjUpdate) { + startTuioBundle(currentFrame); + for (std::list::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) { + + if ((*tobj)->containsTuioToken()) { + TuioToken *ttok = (*tobj)->getTuioToken(); + if ((full_update) || (ttok->getTuioTime()==currentFrameTime)) addTokenMessage(ttok); + } + + if ((*tobj)->containsTuioPointer()) { + TuioPointer *tptr = (*tobj)->getTuioPointer(); + if ((full_update) || (tptr->getTuioTime()==currentFrameTime)) addPointerMessage(tptr); + } + + if ((*tobj)->containsTuioBounds()) { + TuioBounds *tbnd = (*tobj)->getTuioBounds(); + if ((full_update) || (tbnd->getTuioTime()==currentFrameTime)) addBoundsMessage(tbnd); + } + + if ((*tobj)->containsTuioSymbol()) { + TuioSymbol *tsym = (*tobj)->getTuioSymbol(); + if ((full_update) || (tsym->getTuioTime()==currentFrameTime)) addSymbolMessage(tsym); + } + + + } + updateTime = TuioTime(currentFrameTime); + sendTuioBundle(); + } else if (periodic_update) { + + TuioTime timeCheck = currentFrameTime - updateTime; + if(timeCheck.getSeconds()>=update_interval) { + updateTime = TuioTime(currentFrameTime); + startTuioBundle(currentFrame); + if (full_update) { + for (std::list::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) { + // start a new packet if we exceed the packet capacity + if ((oscPacket->Capacity()-oscPacket->Size())getTuioToken()); + } + } + sendTuioBundle(); + } + } + tobjUpdate = false; +} + +void TuioServer::sendEmptyTuioBundle() { + oscPacket->Clear(); + (*oscPacket) << osc::BeginBundleImmediate; + (*oscPacket) << osc::BeginMessage( "/tuio2/frm") << 0 << TuioTime::getSystemTimeTag() << (int32)source->getDimension() << source->getSourceName() << osc::EndMessage; + (*oscPacket) << osc::BeginMessage( "/tuio2/alv") << osc::EndMessage; + (*oscPacket) << osc::EndBundle; + deliverOscPacket( oscPacket ); +} + +void TuioServer::sendFullTuioBundle() { + +} + +void TuioServer::checkBundleCapacity(int msg_size) { + + int size = msg_size + ALV_MESSAGE_SIZE + 4*tobjList.size(); + + if ((oscPacket->Capacity()-oscPacket->Size())Clear(); + (*oscPacket) << osc::BeginBundleImmediate; + if (source) (*oscPacket) << osc::BeginMessage( "/tuio2/frm") << (int32)currentFrame << frameTimeTag << (int32)source->getDimension() << source->getSourceName(); + (*oscPacket) << osc::EndMessage; +} + +void TuioServer::addTokenMessage(TuioToken *ttok) { + + // start a new packet if we exceed the packet capacity + checkBundleCapacity(TOK_MESSAGE_SIZE); + + float xpos = ttok->getX(); + float xvel = ttok->getXSpeed(); + if (invert_x) { + xpos = 1 - xpos; + xvel = -1 * xvel; + } + float ypos = ttok->getY(); + float yvel = ttok->getYSpeed(); + if (invert_y) { + ypos = 1 - ypos; + yvel = -1 * yvel; + } + float angle = ttok->getAngle(); + float rvel = ttok->getRotationSpeed(); + if (invert_a) { + angle = 2.0f*(float)M_PI - angle; + rvel = -1 * rvel; + } + + (*oscPacket) << osc::BeginMessage( "/tuio2/tok"); + (*oscPacket) << (int32)ttok->getSessionID() << (int32)ttok->getTypeUserID() << (int32)ttok->getSymbolID() << xpos << ypos << angle; + (*oscPacket) << xvel << yvel << rvel << ttok->getMotionAccel() << ttok->getRotationAccel(); + (*oscPacket) << osc::EndMessage; +} + +void TuioServer::addPointerMessage(TuioPointer *tptr) { + + // start a new packet if we exceed the packet capacity + checkBundleCapacity(PTR_MESSAGE_SIZE); + + float xpos = tptr->getX(); + float xvel = tptr->getXSpeed(); + if (invert_x) { + xpos = 1 - xpos; + xvel = -1 * xvel; + } + float ypos = tptr->getY(); + float yvel = tptr->getYSpeed(); + if (invert_y) { + ypos = 1 - ypos; + yvel = -1 * yvel; + } + + (*oscPacket) << osc::BeginMessage( "/tuio2/ptr"); + (*oscPacket) << (int32)tptr->getSessionID() << (int32)tptr->getTypeUserID() << (int32)tptr->getPointerID(); + (*oscPacket) << xpos << ypos << tptr->getAngle() << tptr->getShear() << tptr->getRadius() << tptr->getPressure(); + (*oscPacket) << xvel << yvel << tptr->getPressureSpeed() << tptr->getMotionAccel() << tptr->getPressureAccel(); + (*oscPacket) << osc::EndMessage; +} + +void TuioServer::addBoundsMessage(TuioBounds *tbnd) { + + // start a new packet if we exceed the packet capacity + checkBundleCapacity(BND_MESSAGE_SIZE); + + float xpos = tbnd->getX(); + float xvel = tbnd->getXSpeed(); + if (invert_x) { + xpos = 1 - xpos; + xvel = -1 * xvel; + } + float ypos = tbnd->getY(); + float yvel = tbnd->getYSpeed(); + if (invert_y) { + ypos = 1 - ypos; + yvel = -1 * yvel; + } + float angle = tbnd->getAngle(); + float rvel = tbnd->getRotationSpeed(); + if (invert_a) { + angle = 2.0f*(float)M_PI - angle; + rvel = -1 * rvel; + } + + (*oscPacket) << osc::BeginMessage( "/tuio2/bnd"); + (*oscPacket) << (int32)tbnd->getSessionID() << xpos << ypos << angle << tbnd->getWidth() << tbnd->getHeight() << tbnd->getArea(); + (*oscPacket) << xvel << yvel << rvel << tbnd->getMotionAccel() << tbnd->getRotationAccel(); + (*oscPacket) << osc::EndMessage; +} + +void TuioServer::addSymbolMessage(TuioSymbol *tsym) { + + // start a new packet if we exceed the packet capacity + checkBundleCapacity(SYM_MESSAGE_SIZE); + + (*oscPacket) << osc::BeginMessage( "/tuio2/sym"); + (*oscPacket) << (int32)tsym->getSessionID() << (int32)tsym->getTypeUserID() << (int32)tsym->getSymbolID(); + (*oscPacket) << tsym->getSymbolType() << tsym->getSymbolData(); + (*oscPacket) << osc::EndMessage; +} + +void TuioServer::sendTuioBundle() { + + //int before = oscPacket->Capacity()-oscPacket->Size(); + (*oscPacket) << osc::BeginMessage( "/tuio2/alv"); + + for(std::list::iterator tobj = tobjList.begin();tobj!= tobjList.end(); tobj++) + (*oscPacket) << (int32)(*tobj)->getSessionID(); + + (*oscPacket) << osc::EndMessage; + //int after = oscPacket->Capacity()-oscPacket->Size(); + //printf("ALV_MESSAGE_SIZE: %i\n",before-after); + + (*oscPacket) << osc::EndBundle; + deliverOscPacket( oscPacket ); +} + + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioServer.h b/modules/touch/ext/libTUIO2/TUIO2/TuioServer.h new file mode 100644 index 0000000000..fc93f8b739 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioServer.h @@ -0,0 +1,210 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOSERVER_H +#define INCLUDED_TUIOSERVER_H + +#include "TuioManager.h" +#include "UdpSender.h" +#include +#include +#include +#ifndef WIN32 +#include +#include +#include +#endif + +#define TOK_MESSAGE_SIZE 108 +#define PTR_MESSAGE_SIZE 68 +#define BND_MESSAGE_SIZE 116 +#define SYM_MESSAGE_SIZE 116 +#define ALV_MESSAGE_SIZE 20 + +namespace TUIO2 { + /** + *

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 messages + * which are deliverered by the provided OSCSender. The shown UDPSender send OSC to UDP port 3333 on localhost or to the configured host and port.

+ *

During runtime the each frame is marked with the initFrame and commitFrame methods, + * while the currently present TuioTokens are managed by the server with ADD, UPDATE and REMOVE methods in analogy to the TuioClient's TuioListener interface.

+ *

See the SimpleSimulator example project for further hints on how to use the TuioServer class and its various methods. + *

+ * OscSender *sender = new UDPSender();
+ * TuioServer *server = new TuioServer(sender);
+ * server->setSource(src); // passes a TuioSource* argument
+ * ...
+ * server->initTuioFrame(TuioTime::getSessionTime());
+ * TuioToken *ttok = server->addTuioToken(xpos,ypos,angle);
+ * TuioPointer *tptr = server->addTuioPointer(xpos,ypos,width,pressure);
+ * TuioBounds *tbnd = server->addTuioBounds(xpos,ypos,angle,width,height,area);
+ * server->commitTuioFrame();
+ * ...
+ * server->initTuioFrame(TuioTime::getSessionTime());
+ * server->updateTuioToken(ttok,xpos,ypos,angle);
+ * server->updateTuioPointer(tptr,xpos,ypos,width,pressure);
+ * server->updateTuioBounds(tbnd,xpos,ypos,angle,width,height,area);
+ * server->commitTuioFrame();
+ * ...
+ * server->initTuioFrame(TuioTime::getSessionTime());
+ * server->removeTuioToken(ttok);
+ * server->removeTuioPointer(tptr);
+ * server->removeTuioBounds(tbnd);
+ * server->commitTuioFrame();
+ *

+ * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioServer : public TuioManager { + + public: + + /** + * This constructor creates a TuioServer that uses an internal UdpSender delivering the OSC data via UDP port 3333 on localhost + */ + TuioServer(); + + /** + * This constructor creates a TuioServer that uses an internal UdpSender delivering the OSC data via the provided UDP port on the provided host + * + * @param host the host name for UDP deleivery + * @param port the UDP port number on the provided host + */ + TuioServer(const char *host, unsigned short port); + + /** + * This constructor creates a TuioServer that sends OSC data using the provided OscSender + * + * @param sender the OscSender used for OSC data delivery + */ + TuioServer(OscSender *sender); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioServer(); + + /** + * Generates and sends TUIO messages of all currently active TUIO Components + */ + void sendFullTuioBundle(); + + /** + * Enables the full update of all currently active and inactive TUIO Components + * + */ + void enableFullUpdate() { + full_update = true; + } + + /** + * Disables the full update of all currently active and inactive TUIO Components + */ + void disableFullUpdate() { + full_update = false; + } + + /** + * Returns true if the full update of all currently active TUIO Components is enabled. + * @return true if the full update of all currently active TUIO Components is enabled + */ + bool fullUpdateEnabled() { + return full_update; + } + + /** + * Disables the periodic full update of all currently active TUIO Components + * + * @param interval update interval in seconds, defaults to one second + */ + void enablePeriodicMessages(int interval=1) { + periodic_update = true; + update_interval = interval; + } + + /** + * Disables the periodic full update of all currently active and inactive TUIO Components + */ + void disablePeriodicMessages() { + periodic_update = false; + } + + /** + * Returns true if the periodic update of all currently active TUIO Components is enabled. + * @return true if the periodic update of all currently active TUIO Components 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; + } + + /** + * Commits the current frame. + * Generates and sends TUIO messages of all currently active and updated TUIO Components. + */ + void commitTuioFrame(); + + /** + * Creates the TuioSource that is transmitted within the /tuio2/frm source attributes. + * + * @param name the source name to assign + */ + void setSourceName(const char* name); + void setDimension(unsigned short w, unsigned short h); + + void addOscSender(OscSender *sender); + + private: + + void initialize(); + + OscSender *primary_sender; + bool local_sender; + + std::vector senderList; + void deliverOscPacket(osc::OutboundPacketStream *packet); + + osc::OutboundPacketStream *oscPacket; + char *oscBuffer; + osc::OutboundPacketStream *fullPacket; + char *fullBuffer; + + void checkBundleCapacity(int size); + void startTuioBundle(unsigned int fseq); + void addTokenMessage(TuioToken *ttok); + void addPointerMessage(TuioPointer *tptr); + void addBoundsMessage(TuioBounds *tbnd); + void addSymbolMessage(TuioSymbol *tsym); + void sendTuioBundle(); + void sendEmptyTuioBundle(); + + int update_interval; + bool full_update, periodic_update; + TuioTime updateTime; + TuioSource *source; + }; +} +#endif /* INCLUDED_TUIOSERVER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioSource.h b/modules/touch/ext/libTUIO2/TUIO2/TuioSource.h new file mode 100644 index 0000000000..2bf5593a07 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioSource.h @@ -0,0 +1,244 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + */ + +#ifndef INCLUDED_TUIOSOURCE_H +#define INCLUDED_TUIOSOURCE_H + +#include +#include +#include +#include + +namespace TUIO2 { + + /** + * The TuioSource class encapsulates the meta data for the TUIO source attributes provided in /tuio2/frm. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + + class LIBDECL TuioSource { + + protected: + /** + * The ID of the TUIO source + */ + unsigned int source_id; + /** + * The name of the TUIO source + */ + std::string source_name; + /** + * The instance of the TUIO source + */ + unsigned int source_instance; + /** + * The address of the TUIO source + */ + std::string source_address; + /** + * The encoded sensor dimension + */ + unsigned int dimension; + /** + * The TuioTime of the last frame + */ + TuioTime frameTime; + + public: + + /** + * Sets the ID, name and address of the TUIO source + */ + TuioSource() { + source_id = 0; + source_name = "default"; + source_instance = 0; + source_address = "localhost"; + dimension = 0; + }; + + /** + * Sets the ID, name and address of the TUIO source + * + * @param src_name the name of the TUIO source + */ + TuioSource(std::string src_name) { + source_id = 0; + source_name = src_name; + source_instance = 0; + source_address = "localhost"; + dimension = 0; + }; + + /** + * Sets the ID, name and address of the TUIO source + * + * @param src_name the name of the TUIO source + */ + TuioSource(unsigned int sid, std::string src_string, unsigned int dim) { + source_id = sid; + setSourceString(src_string); + setDimension(dim); + }; + + /** + * Sets the ID, name and address of the TUIO source + * + * @param src_name the name of the TUIO source + * @param src_inst the instance of the TUIO source + * @param src_addr the address of the TUIO source + */ + TuioSource(std::string src_name, unsigned int src_inst, std::string src_addr) { + source_id = 0; + source_name = src_name; + source_instance = src_inst; + source_address = src_addr; + }; + + /** + * Sets the ID, name and address of the TUIO source + * + * @param src_id the ID of the TUIO source + * @param src_name the name of the TUIO source + * @param src_inst the instance of the TUIO source + * @param src_addr the address of the TUIO source + */ + TuioSource(unsigned int src_id, std::string src_name, unsigned int src_inst, std::string src_addr) { + source_id = src_id; + source_name = src_name; + source_instance = src_inst; + source_address = src_addr; + }; + + ~TuioSource() {}; + + void setSourceString(std::string src_string) { + + if (src_string.length()==0) return; + char *data = strdup(src_string.c_str()); + + char *name_inst = strtok(data, "@"); + + char *addr = strtok(NULL, "@"); + if (addr!=NULL) source_address = std::string(addr); + else source_address = (char*)"0x7F000001"; + + char *name = strtok(name_inst, ":"); + source_name = std::string(name); + + char *inst = strtok(NULL, ":"); + if (inst!=NULL) source_instance = atoi(inst); + else source_instance = 0; + } + + void setSourceString(unsigned int src_id, std::string src_string) { + + source_id = src_id; + setSourceString(src_string); + } + + std::string getSourceString() { + + std::stringstream src_stream; + src_stream << source_name << ":" << source_instance << "@" << source_address; + return src_stream.str(); + } + + /** + * Returns the ID of the TUIO source + */ + unsigned int getSourceID() { return source_id; } + + /** + * Returns the name of the TUIO source + */ + const char* getSourceName() { return source_name.c_str(); } + + /** + * Returns the instance of the TUIO source + */ + unsigned int getSourceInstance() { return source_instance; } + + /** + * Returns the address of the TUIO source + */ + const char* getSourceAddress() { return source_address.c_str(); } + + /** + * Encodes the sensor dimension + * @param w the sensor width + * @param h the sensor height + */ + void setDimension(unsigned short w, unsigned short h) { + dimension = w << 16 | h; + } + + /** + * Sets the encoded sensor dimension + * @param d the sensor dimension + */ + void setDimension(unsigned int d) { + dimension = d; + } + + /** + * Returns the encoded sensor dimension + * @return the encoded sensor dimension + */ + unsigned int getDimension() { + return dimension; + } + + /** + * Returns the decoded sensor width + * @return the decoded sensor width + */ + unsigned short getWidth() { + unsigned short width = dimension >> 16; + return width; + } + + /** + * Returns the decoded sensor height + * @return the decoded sensor height + */ + unsigned short getHeight() { + unsigned short height = dimension & 0x0000FFFF; + return height; + } + + /** + * Sets the last frame time + * @param ttime the TuioTime of the last frame + */ + void setFrameTime(TuioTime ttime) { + frameTime = ttime; + } + + /** + * Returns the last frame time + * @return the TuioTime of the last frame + */ + TuioTime getFrameTime() { + return frameTime; + } + }; +} +#endif // INCLUDED_TUIOSOURCE_H diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.cpp new file mode 100644 index 0000000000..4447c3a227 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.cpp @@ -0,0 +1,91 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioSymbol.h" + +using namespace TUIO2; + +TuioSymbol::TuioSymbol (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data):TuioComponent(ttime,tobj,0,0,0) { + currentTime = ttime; + startTime = currentTime; + type_id = ti; + user_id = ui; + symbol_id = sym; + symbol_type = std::string(type); + symbol_data = std::string(data); + state = TUIO_ADDED; +} + +TuioSymbol::TuioSymbol (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data):TuioComponent(tobj,0,0,0) { + currentTime = TuioTime::getSystemTime(); + startTime = currentTime; + type_id = ti; + user_id = ui; + symbol_id = sym; + symbol_type = std::string(type); + symbol_data = std::string(data); + state = TUIO_ADDED; +} + +TuioSymbol::TuioSymbol (TuioSymbol *tsym):TuioComponent(tsym->getTuioTime(),tsym->getContainingTuioObject(),0,0,0) { + currentTime = TuioTime::getSystemTime(); + startTime = currentTime; + session_id = tsym->getSessionID(); + type_id = tsym->getTypeID(); + user_id = tsym->getUserID(); + symbol_id = tsym->getSymbolID(); + symbol_type = tsym->getSymbolType(); + symbol_data = tsym->getSymbolData(); + state = TUIO_ADDED; +} + +unsigned int TuioSymbol::getSymbolID() const { + return symbol_id; +} + +unsigned short TuioSymbol::getTypeID() const { + return type_id; +} + +unsigned short TuioSymbol::getUserID() const { + return user_id; +} + +unsigned int TuioSymbol::getTypeUserID() const { + int tu_id = user_id << 16 | type_id; + return tu_id; +} + +void TuioSymbol::setTypeUserID(unsigned int tu_id) { + user_id = tu_id >> 16; + type_id = tu_id & 0x0000FFFF; +} + +const char* TuioSymbol::getSymbolType() const { + return symbol_type.c_str(); +} + +const char* TuioSymbol::getSymbolData() const { + return symbol_data.c_str(); +} + +void TuioSymbol::update(TuioTime ttime) { + TuioComponent::update(ttime,0,0); + +} + diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.h b/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.h new file mode 100644 index 0000000000..d66e32845d --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioSymbol.h @@ -0,0 +1,160 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOSYMBOL_H +#define INCLUDED_TUIOSYMBOL_H +//#pragma clang diagnostic ignored "-Woverloaded-virtual" + +#include "TuioTime.h" +#include "TuioComponent.h" +#include + +namespace TUIO2 { + + /** + * The TuioSymbol class encapsulates /tuio2/sym TUIO symbol. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioSymbol : public TuioComponent { + + protected: + /** + * The unique Session ID that is assigned to each TUIO tobj. + */ + unsigned int session_id; + /** + * The individual symbol ID number that is assigned to each TuioToken. + */ + unsigned int symbol_id; + /** + * The symbol type ID that is assigned to each TuioToken. + */ + unsigned short type_id; + /** + * The user ID that is assigned to each TuioToken. + */ + unsigned short user_id; + /** + * The symbol type descriptor + */ + std::string symbol_type; + /** + * The actual symbol data + */ + std::string symbol_data; + /** + * 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; + /** + * Reflects the current state of the TuioSymbol + */ + unsigned char state; + + public: + /** + * This constructor takes a TuioTime argument and assigns it along with the provided + * Session ID, Type ID, User ID and Symbol ID as well as the Symbol type and data. + * + * @param ttime the TuioTime to assign + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User ID to assign + * @param sym the Symbol ID to assign + * @param type the symbol type descriptor + * @param data the symbol data to assign + */ + TuioSymbol (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data); + + /** + * This constructor assigns the provided Session ID, Type ID, User ID and Symbol ID + * as well as the Symbol type and data. + * + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User ID to assign + * @param sym the Symbol ID to assign + * @param type the symbol type descriptor + * @param data the symbol data to assign + */ + TuioSymbol (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data); + + /** + * This constructor takes a TuioSymbol argument and sets its attributes + * to the ones of the provided TuioSymbol. + * + * @param tsym the TuioSymbol to assign + */ + TuioSymbol (TuioSymbol *tsym); + + /** + * Returns the Symbol ID of this TuioSymbol. + * @return the Symbol ID of this TuioSymbol + */ + unsigned int getSymbolID() const; + + /** + * Returns the Type ID of this TuioSymbol. + * @return the Type ID of this TuioSymbol + */ + unsigned short getTypeID() const; + + /** + * Returns the User ID of this TuioSymbol. + * @return the User ID of this TuioSymbol + */ + unsigned short getUserID() const; + + /** + * Returns the encoded Type & User ID of this TuioSymbol. + * @return the encoded Type & User ID of this TuioSymbol + */ + unsigned int getTypeUserID() const; + + /** + * Decodes and assigns the Type & User ID to this TuioSymbol. + * @param tu_id the encoded Type & User ID of this TuioSymbol + */ + void setTypeUserID(unsigned int tu_id); + + /** + * Returns the Type string of this TuioSymbol. + * @return the Type string of this TuioSymbol + */ + const char* getSymbolType() const; + + /** + * Returns the actual data of this TuioSymbol. + * @return the actual data of this TuioSymbol + */ + const char* getSymbolData() const; + + + void update(TuioTime ttime); + /*void update(TuioTime ttime, float xp, float yp); + void update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma); + void update (TuioSymbol *tsym);*/ + }; +} +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioTime.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioTime.cpp new file mode 100644 index 0000000000..b84af84458 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioTime.cpp @@ -0,0 +1,160 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioTime.h" +using namespace TUIO2; + +long TuioTime::start_seconds = 0; +long TuioTime::start_micro_seconds = 0; + +TuioTime::TuioTime (long msec) { + seconds = msec/MSEC_SECOND; + micro_seconds = USEC_MILLISECOND*(msec%MSEC_SECOND); +} + +TuioTime::TuioTime (osc::TimeTag timetag) { + osc::uint32 secs = timetag >> 32; + osc::uint32 frac = timetag & 0x00000000FFFFFFFF; + + seconds = secs - JAN_1970; + micro_seconds = frac / NTP_UNITS; +} + +TuioTime::TuioTime (long sec, long usec) { + seconds = sec; + micro_seconds = usec; +} + +TuioTime TuioTime::operator+(long us) { + long sec = seconds + us/USEC_SECOND; + long usec = micro_seconds + us%USEC_SECOND; + return TuioTime(sec,usec); +} + +TuioTime 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); +} + +TuioTime 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); +} + +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); +} + +void TuioTime::operator=(TuioTime ttime) { + seconds = ttime.getSeconds(); + micro_seconds = ttime.getMicroseconds(); +} + +bool TuioTime::operator==(TuioTime ttime) { + if ((seconds==(long)ttime.getSeconds()) && (micro_seconds==(long)ttime.getMicroseconds())) return true; + else return false; +} + +bool TuioTime::operator!=(TuioTime ttime) { + if ((seconds!=(long)ttime.getSeconds()) || (micro_seconds!=(long)ttime.getMicroseconds())) return true; + else return false; +} + +void TuioTime::reset() { + seconds = 0; + micro_seconds = 0; + + TuioTime system_time = getSystemTime(); + seconds = system_time.getSeconds(); + micro_seconds = system_time.getMicroseconds(); +} + +long TuioTime::getSeconds() const{ + return seconds; +} + +long TuioTime::getMicroseconds() const{ + return micro_seconds; +} + +long TuioTime::getTotalMilliseconds() const{ + return seconds*MSEC_SECOND+micro_seconds/MSEC_SECOND; +} + +unsigned int TuioTime::getFrameID() const{ + return frame_id; +} + +void TuioTime::setFrameID(unsigned int f_id) { + frame_id = f_id; +} + +/*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; +} + +osc::TimeTag TuioTime::getSystemTimeTag() { + + TuioTime systemTime = getSystemTime(); + + osc::uint32 secs = systemTime.getSeconds() + JAN_1970; + osc::uint32 frac = systemTime.getMicroseconds() * NTP_UNITS; + + osc::uint64 timetag = (osc::uint64) secs << 32 | frac; + return osc::TimeTag(timetag); +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioTime.h b/modules/touch/ext/libTUIO2/TUIO2/TuioTime.h new file mode 100644 index 0000000000..f1c1e10133 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioTime.h @@ -0,0 +1,222 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOTIME_H +#define INCLUDED_TUIOTIME_H + +#include "LibExport.h" +#include "oscpack/osc/OscTypes.h" + +#ifndef WIN32 +#include +#include +#else +#include +#include +#endif + +#define MSEC_SECOND 1000 +#define USEC_SECOND 1000000 +#define USEC_MILLISECOND 1000 + +#define JAN_1970 0x83aa7e80 /* 2208988800 1970 - 1900 in seconds */ +#define NTP_UNITS 4294.967295 /* NTP units per second */ + +namespace TUIO2 { + + /** + * 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 2.0.a0 + */ + class LIBDECL TuioTime { + + private: + long seconds; + long micro_seconds; + static long start_seconds; + static long start_micro_seconds; + + unsigned int frame_id; + + 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),frame_id(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); + + + /** + * This constructor takes the provided time in OSC format + * and assigs this value to the newly created TuioTime. + * + * @param tag the time in OSC format + */ + TuioTime (osc::TimeTag timetag); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + /** + * 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); + + + /** + * Assigns the provided TuioTime to the private Seconds and Microseconds attributes. + * + * @param ttime the TuioTime to assign + */ + void operator=(TuioTime ttime); + + /** + * 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); + + /** + * 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); + + /** + * Resets the seconds and micro_seconds attributes to zero. + */ + void reset(); + + /** + * Returns the TuioTime Seconds component. + * @return the TuioTime Seconds component + */ + long getSeconds() const; + + /** + * Returns the TuioTime Microseconds component. + * @return the TuioTime Microseconds component + */ + long getMicroseconds() const; + + /** + * Returns the total TuioTime in Milliseconds. + * @return the total TuioTime in Milliseconds + */ + long getTotalMilliseconds() const; + + /** + * Returns the assigned Frame ID. + * @return the assigned Frame ID + */ + unsigned int getFrameID() const; + + /** + * assigns a Frame ID. + * @f_id the Frame ID to assign + */ + void setFrameID(unsigned int f_id); + + /** + * 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 + */ + //tatic 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(); + + /** + * Returns the absolut TuioTime representing the current system time. + * @return the absolut TuioTime representing the current system time + */ + static osc::TimeTag getSystemTimeTag(); + }; +} +#endif /* INCLUDED_TUIOTIME_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioToken.cpp b/modules/touch/ext/libTUIO2/TUIO2/TuioToken.cpp new file mode 100644 index 0000000000..375c80e792 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioToken.cpp @@ -0,0 +1,69 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "TuioToken.h" + +using namespace TUIO2; + +TuioToken::TuioToken (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a):TuioComponent(ttime, tobj, xp, yp,a) { + type_id = ti; + user_id = ui; + symbol_id = sym; +} + +TuioToken::TuioToken (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a):TuioComponent(tobj, xp, yp, a) { + type_id = ti; + user_id = ui; + symbol_id = sym; +} + +TuioToken::TuioToken (TuioObject *tobj, unsigned int sym, float xp, float yp, float a):TuioComponent(tobj, xp, yp, a) { + type_id = 0; + user_id = 0; + symbol_id = sym; +} + +TuioToken::TuioToken (TuioToken *ttok):TuioComponent(ttok) { + symbol_id = ttok->getSymbolID(); +} + +void TuioToken::stop (TuioTime ttime) { + update(ttime,xpos,ypos,angle); +} + +unsigned int TuioToken::getSymbolID() const{ + return symbol_id; +} + +unsigned short TuioToken::getTypeID() const{ + return type_id; +}; + +unsigned short TuioToken::getUserID() const{ + return user_id; +}; + +unsigned int TuioToken::getTypeUserID() const { + int tu_id = user_id << 16 | type_id; + return tu_id; +} + +void TuioToken::setTypeUserID(unsigned int tu_id) { + user_id = tu_id >> 16; + type_id = tu_id & 0x0000FFFF; +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/TuioToken.h b/modules/touch/ext/libTUIO2/TUIO2/TuioToken.h new file mode 100644 index 0000000000..c6b01a0816 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/TuioToken.h @@ -0,0 +1,151 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_TUIOTOKEN_H +#define INCLUDED_TUIOTOKEN_H + +#include "TuioComponent.h" + +namespace TUIO2 { + + /** + * The TuioToken class encapsulates /tuio2/tok TUIO tokens. + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL TuioToken: public TuioComponent { + + protected: + /** + * The individual symbol ID number that is assigned to each TuioToken. + */ + unsigned int symbol_id; + /** + * The symbol type ID that is assigned to each TuioToken. + */ + unsigned short type_id; + /** + * The user ID that is assigned to each TuioToken. + */ + unsigned short user_id; + + public: + using TuioComponent::update; + + /** + * 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 TuioToken. + * + * @param ttime the TuioTime to assign + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User 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 + */ + TuioToken (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a); + + /** + * This constructor takes the provided Session ID, Symbol ID, X and Y coordinate + * and angle, and assigs these values to the newly created TuioToken. + * + * @param tobj the TuioObject to assign + * @param ti the Type ID to assign + * @param ui the User 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 + */ + TuioToken (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a); + + /** + * This constructor takes the provided Session ID, Symbol ID, X and Y coordinate + * and angle, and assigs these values to the newly created TuioToken. + * + * @param tobj the TuioObject 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 + */ + TuioToken (TuioObject *tobj, unsigned int sym, float xp, float yp, float a); + + /** + * This constructor takes the atttibutes of the provided TuioToken + * and assigs these values to the newly created TuioToken. + * + * @param ttok the TuioToken to assign + */ + TuioToken (TuioToken *ttok); + + /** + * The destructor is doing nothing in particular. + */ + ~TuioToken() {}; + + /** + * This method is used to calculate the speed and acceleration values of a + * TuioToken with unchanged position and angle. + */ + void stop (TuioTime ttime); + + /** + * Takes the atttibutes of the provided TuioToken + * and assigs these values to this TuioToken. + * The TuioTime time stamp of this TuioToken remains unchanged. + * + * @param ttok the TuioToken to assign + */ + void update (TuioToken *ttok); + + /** + * Returns the symbol ID of this TuioToken. + * @return the symbol ID of this TuioToken + */ + unsigned int getSymbolID() const; + + /** + * Returns the Type ID of this TuioToken. + * @return the Type ID of this TuioToken + */ + unsigned short getTypeID() const; + + /** + * Returns the User ID of this TuioToken. + * @return the User ID of this TuioToken + */ + unsigned short getUserID() const; + + /** + * Returns the encoded Type & User ID of this TuioToken. + * @return the encoded Type & User ID of this TuioToken + */ + unsigned int getTypeUserID() const; + + /** + * Decodes and assigns the Type & User ID to this TuioToken. + * @param tu_id the encoded Type & User ID of this TuioToken + */ + void setTypeUserID(unsigned int tu_id); + }; +} +#endif diff --git a/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.cpp b/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.cpp new file mode 100644 index 0000000000..fe1b3ad952 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.cpp @@ -0,0 +1,92 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "UdpReceiver.h" + +using namespace TUIO2; +using namespace osc; + +#ifndef WIN32 +static void* ClientThreadFunc( void* obj ) +#else +static DWORD WINAPI ClientThreadFunc( LPVOID obj ) +#endif +{ + static_cast(obj)->socket->Run(); + return 0; +}; + +UdpReceiver::UdpReceiver(unsigned short port):locked (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/UDP messages on port " << port << std::endl; + } +} + +UdpReceiver::~UdpReceiver() { + delete socket; +} + +void UdpReceiver::connect(bool lk) { + + if (connected) return; + if (socket==NULL) return; + 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; +} + +void UdpReceiver::disconnect() { + + if (!connected) return; + if (socket==NULL) { + connected = false; + locked = false; + return; + } + socket->Break(); + + if (!locked) { +#ifdef WIN32 + if( thread ) CloseHandle( thread ); +#endif + thread = 0; + } else locked = false; + + connected = false; +} + + diff --git a/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.h b/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.h new file mode 100644 index 0000000000..026e09ae26 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.h @@ -0,0 +1,77 @@ +/* + TUIO2 C++ Library + Copyright (c) 2009-2014 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_UDPRECEIVER_H +#define INCLUDED_UDPRECEIVER_H + +#include "OscReceiver.h" +#include "oscpack/ip/UdpSocket.h" + +namespace TUIO2 { + + /** + * The UdpReceiver provides the OscReceiver functionality for the UDP transport method + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL UdpReceiver: public OscReceiver { + + public: + + /** + * The UDP socket is only public to be accessible from the thread function + */ + UdpListeningReceiveSocket *socket; + + /** + * This constructor creates a UdpReceiver instance listening to the provided UDP port + * + * @param port the number of the UDP port to listen to, defaults to 3333 + */ + UdpReceiver (unsigned short port=3333); + + /** + * The destructor is doing nothing in particular. + */ + virtual ~UdpReceiver(); + + /** + * The UdpReceiver connects and starts receiving TUIO messages via UDP + * + * @param lock running in the background if set to false (default) + */ + void connect(bool lock=false); + + /** + * The UdpReceiver disconnects and stops receiving TUIO messages via UDP + */ + void disconnect(); + + private: + +#ifndef WIN32 + pthread_t thread; +#else + HANDLE thread; +#endif + + bool locked; + }; +}; +#endif /* INCLUDED_UDPRECEIVER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/UdpSender.cpp b/modules/touch/ext/libTUIO2/TUIO2/UdpSender.cpp new file mode 100644 index 0000000000..9a231a5617 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/UdpSender.cpp @@ -0,0 +1,89 @@ +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "UdpSender.h" + +using namespace TUIO2; + +UdpSender::UdpSender() { + try { + local = true; + long unsigned int ip = GetHostByName("localhost"); + socket = new UdpTransmitSocket(IpEndpointName(ip, 3333)); + buffer_size = MAX_UDP_SIZE; + std::cout << "TUIO/UDP messages to " << "127.0.0.1@3333" << std::endl; + } catch (std::exception &e) { + std::cout << "could not create UDP socket" << std::endl; + socket = NULL; + throw std::exception(); + } +} + +UdpSender::UdpSender(const char *host, int port) { + try { + if ((strcmp(host,"127.0.0.1")==0) || (strcmp(host,"localhost")==0)) { + local = true; + buffer_size = MAX_UDP_SIZE; + } else { + local = false; + buffer_size = IP_MTU_SIZE; + } + long unsigned int ip = GetHostByName(host); + socket = new UdpTransmitSocket(IpEndpointName(ip, port)); + std::cout << "TUIO/UDP messages to " << host << "@" << port << std::endl; + } catch (std::exception &e) { + std::cout << "could not create UDP socket" << std::endl; + socket = NULL; + throw std::exception(); + } +} + +UdpSender::UdpSender(const char *host, int port, int size) { + try { + if ((strcmp(host,"127.0.0.1")==0) || (strcmp(host,"localhost")==0)) { + local = true; + } else local = false; + long unsigned int ip = GetHostByName(host); + socket = new UdpTransmitSocket(IpEndpointName(ip, port)); + if (buffer_size>MAX_UDP_SIZE) buffer_size = MAX_UDP_SIZE; + else if (buffer_sizeSize() > buffer_size ) return false; + if ( bundle->Size() == 0 ) return false; + + socket->Send( bundle->Data(), bundle->Size() ); + return true; +} diff --git a/modules/touch/ext/libTUIO2/TUIO2/UdpSender.h b/modules/touch/ext/libTUIO2/TUIO2/UdpSender.h new file mode 100644 index 0000000000..9cd2eb722f --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/UdpSender.h @@ -0,0 +1,93 @@ +/* + TUIO C++ Library + Copyright (c) 2005-2016 Martin Kaltenbrunner + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_UDPSENDER_H +#define INCLUDED_UDPSENDER_H + +#include "OscSender.h" +#include "oscpack/ip/UdpSocket.h" + +#define IP_MTU_SIZE 1500 +#define MAX_UDP_SIZE 4096 +#define MIN_UDP_SIZE 576 + +namespace TUIO2 { + + /** + * The UdpSender implements the UDP transport method for OSC + * + * @author Martin Kaltenbrunner + * @version 2.0.a0 + */ + class LIBDECL UdpSender : public OscSender { + + public: + + /** + * The default constructor creates a UdpSender that sends to the default UDP port 3333 on localhost + * using the maximum packet size of 65536 bytes for single packets on the loopback device + */ + UdpSender(); + + /** + * This constructor creates a UdpSender that sends to the provided port on the the given host + * using the default MTU size of 1500 bytes to deliver unfragmented UDP packets on a LAN + * + * @param host the receiving host name + * @param port the outgoing UDP port number + */ + + UdpSender(const char *host, int port); + /** + * This constructor creates a UdpSender that sends to the provided port on the the given host + * the UDP packet size can be set to a value between 576 and 65536 bytes + * + * @param host the receiving host name + * @param port the outgoing UDP port number + * @param size the maximum UDP packet size + */ + UdpSender(const char *host, int port, int size); + + /** + * The destructor closes the socket. + */ + virtual ~UdpSender(); + + /** + * This method delivers the provided OSC data + * + * @param *bundle the OSC stream to deliver + * @return true if the data was delivered successfully + */ + + bool sendOscPacket (osc::OutboundPacketStream *bundle); + + /** + * This method returns the connection state + * + * @return true if the connection is alive + */ + bool isConnected (); + + const char* tuio_type() { return "TUIO/UDP"; } + + private: + UdpTransmitSocket *socket; + }; +} +#endif /* INCLUDED_UDPSENDER_H */ diff --git a/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.cpp b/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.cpp new file mode 100644 index 0000000000..781fcb5e75 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.cpp @@ -0,0 +1,286 @@ +/* + TUIO C++ Library + Copyright (c) 2009-2016 Martin Kaltenbrunner + WebSockSender (c) 2015 Florian Echtler + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#include "WebSockSender.h" + +#ifdef WIN32 +#if not + defined int32_t + typedef DWORD int32_t; +#endif +#endif + +using namespace TUIO2; + +WebSockSender::WebSockSender() + :TcpSender( 8080 ) +{ + local = true; + buffer_size = MAX_TCP_SIZE; + port_no = 8080; +} + +WebSockSender::WebSockSender(int port) + :TcpSender( port ) +{ + local = true; + buffer_size = MAX_TCP_SIZE; + port_no = port; +} + +bool WebSockSender::sendOscPacket (osc::OutboundPacketStream *bundle) { + if (!connected) return false; + if ( bundle->Size() > buffer_size ) return false; + if ( bundle->Size() == 0 ) return false; + +#ifdef OSC_HOST_LITTLE_ENDIAN + data_size[0] = bundle->Size()>>24; + data_size[1] = (bundle->Size()>>16) & 255; + data_size[2] = (bundle->Size()>>8) & 255; + data_size[3] = (bundle->Size()) & 255; +#else + *((int32_t*)data_size) = bundle->Size(); +#endif + +#ifdef WIN32 + std::list::iterator client; +#else + std::list::iterator client; +#endif + + for (client = tcp_client_list.begin(); client!=tcp_client_list.end(); client++) { + int len = bundle->Size(); + // add WebSocket header on top + uint8_t header[4] = { + 0x82, + (uint8_t)( len & 0xFF), + (uint8_t)((len >>8) & 0xFF), + (uint8_t)( len & 0xFF) + }; + int hs = 2; + if (len > 125) { hs = 4; header[1] = 126; } + memcpy(&data_buffer[0], &header, hs); + memcpy(&data_buffer[hs], bundle->Data(), bundle->Size()); + send((*client),data_buffer, hs+bundle->Size(),0); + } + + return true; +} + +void WebSockSender::newClient( int tcp_client ) { + + // socket -> file descriptor +#ifdef WIN32 + FILE* conn = _fdopen( tcp_client, "r+" ); +#else + FILE* conn = fdopen( tcp_client, "r+" ); +#endif + + // websocket challenge-response + uint8_t digest[SHA1_HASH_SIZE]; + char buf[1024] = "..."; + char key[1024]; + + // read client handshake challenge + while ((buf[0] != 0) && (buf[0] != '\r')) { + fgets( buf, sizeof(buf), conn ); + if (strncmp(buf,"Sec-WebSocket-Key: ",19) == 0) { + strncpy(key,buf+19,sizeof(key)); + key[strlen(buf)-21] = 0; + break; + } + } + + strncat(key,"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",sizeof(key)-strlen(key)-1); + sha1(digest,(uint8_t*)key,strlen(key)); + + snprintf(buf, sizeof(buf), + "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: %s\r\n\r\n", + base64( digest, SHA1_HASH_SIZE ).c_str() ); + + send(tcp_client,buf, strlen(buf),0); +} + + +/* + * Incredibly minimal implementation of SHA1. + * Totally independent of any other code (even libc) so it can be + * run on bare hardware. + * + * Copyright (C) 2009 John Stumpo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JOHN STUMPO ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL JOHN STUMPO BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +void WebSockSender::sha1( uint8_t digest[SHA1_HASH_SIZE], const uint8_t* inbuf, size_t length) { + + size_t i, j; + int remaining_bytes; + uint32_t h0, h1, h2, h3, h4, a, b, c, d, e, temp; + uint32_t w[80]; + unsigned char buf[64]; + + /* Initialize SHA1 hash state. */ + h0 = 0x67452301; + h1 = 0xefcdab89; + h2 = 0x98badcfe; + h3 = 0x10325476; + h4 = 0xc3d2e1f0; + + /* The extra 9 bytes are the pad byte (0x80) and 64-bit bit count that + are appended to the data being hashed. (There will more than likely + also be some zeroes in between the 0x80 and the bit count so that we + operate on a multiple of 64 bytes; 9 bytes, though, is the minimal + amount of extra data.) */ + for (i = 0; i < length + 9; i += 64) { + + /* Perform any padding necessary. */ + remaining_bytes = length - i; + if (remaining_bytes >= 64) { + memcpy(buf, inbuf + i, 64); + } else if (remaining_bytes >= 0) { + memcpy(buf, inbuf + i, remaining_bytes); + memset(buf + remaining_bytes, 0, 64 - remaining_bytes); + buf[remaining_bytes] = 0x80; + } else { + memset(buf, 0, 64); + } + + if (remaining_bytes < 56) + *(uint32_t*)(buf + 60) = SWAP(length * 8); + + /* Build the input array. */ + for (j = 0; j < 16; j++) + w[j] = SWAP(*(uint32_t*)(buf + j * 4)); + + for (j = 16; j < 80; j++) + w[j] = ROL(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + + /* Load hash state. */ + a = h0; + b = h1; + c = h2; + d = h3; + e = h4; + + for (j = 0; j < 80; j++) { + + if (j < 20) + temp = ((b & c) | ((~b) & d)) + 0x5a827999; + else if (j < 40) + temp = (b ^ c ^ d) + 0x6ed9eba1; + else if (j < 60) + temp = ((b & c) | (b & d) | (c & d)) + 0x8f1bbcdc; + else + temp = (b ^ c ^ d) + 0xca62c1d6; + + temp += ROL(a, 5) + e + w[j]; + + e = d; + d = c; + c = ROR(b, 2); + b = a; + a = temp; + } + + /* Incorporate the results of the hash operation. */ + h0 += a; + h1 += b; + h2 += c; + h3 += d; + h4 += e; + } + + /* Write the hash into the output buffer. */ + *(uint32_t*)(digest) = SWAP(h0); + *(uint32_t*)(digest + 4) = SWAP(h1); + *(uint32_t*)(digest + 8) = SWAP(h2); + *(uint32_t*)(digest + 12) = SWAP(h3); + *(uint32_t*)(digest + 16) = SWAP(h4); +} + +/* + * a very simple base64 encoder, licensed as public domain. original source: + * https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 + */ + +const static unsigned char encodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const static unsigned char padCharacter = '='; + +std::string WebSockSender::base64( uint8_t* cursor, size_t size ) { + + std::string encodedString; + uint32_t temp; + + encodedString.reserve(((size/3) + (size % 3 > 0)) * 4); + + for (size_t idx = 0; idx < size/3; idx++) { + + temp = (*cursor++) << 16; + temp += (*cursor++) << 8; + temp += (*cursor++); + + encodedString.append( 1, encodeLookup[(temp & 0x00FC0000) >> 18] ); + encodedString.append( 1, encodeLookup[(temp & 0x0003F000) >> 12] ); + encodedString.append( 1, encodeLookup[(temp & 0x00000FC0) >> 6 ] ); + encodedString.append( 1, encodeLookup[(temp & 0x0000003F) ] ); + } + + switch (size % 3) { + case 1: + temp = (*cursor++) << 16; + encodedString.append( 1, encodeLookup[(temp & 0x00FC0000) >> 18] ); + encodedString.append( 1, encodeLookup[(temp & 0x0003F000) >> 12] ); + encodedString.append( 2, padCharacter ); + break; + case 2: + temp = (*cursor++) << 16; + temp += (*cursor++) << 8; + encodedString.append( 1, encodeLookup[(temp & 0x00FC0000) >> 18] ); + encodedString.append( 1, encodeLookup[(temp & 0x0003F000) >> 12] ); + encodedString.append( 1, encodeLookup[(temp & 0x00000FC0) >> 6 ] ); + encodedString.append( 1, padCharacter); + break; + } + + return encodedString; +} + + diff --git a/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.h b/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.h new file mode 100644 index 0000000000..0cc9d12935 --- /dev/null +++ b/modules/touch/ext/libTUIO2/TUIO2/WebSockSender.h @@ -0,0 +1,121 @@ +/* + TUIO C++ Library + Copyright (c) 2009-2016 Martin Kaltenbrunner + WebSockSender (c) 2015 Florian Echtler + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. +*/ + +#ifndef INCLUDED_WEBSOCKSENDER_H +#define INCLUDED_WEBSOCKSENDER_H + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#include +#include +#define snprintf c99_snprintf +#define vsnprintf c99_vsnprintf + +__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) +{ + int count = -1; + + if (size != 0) + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + + return count; +} + +__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + + return count; +} + +#endif + + +/* All of these macros assume use on a 32-bit variable. + Additionally, SWAP assumes we're little-endian. */ +#define SWAP(a) ((((a) >> 24) & 0x000000ff) | (((a) >> 8) & 0x0000ff00) | \ +(((a) << 8) & 0x00ff0000) | (((a) << 24) & 0xff000000)) +#define ROL(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) +#define ROR(a, b) ROL((a), (32 - (b))) +#define SHA1_HASH_SIZE (160/8) + +#include "TcpSender.h" +#include +#include +#include +#include + +namespace TUIO2 { + + /** + * The WebSockSender implements the WebSocket transport method for OSC + * + * @author Florian Echtler + * @version 2.0.a0 + */ + class LIBDECL WebSockSender : public TcpSender { + + public: + + /** + * The default constructor creates a WebSockSender that listens to the default HTTP-alt port 8080 on localhost + */ + WebSockSender(); + + /** + * This constructor creates a WebSockSender that listens to the provided port + * + * @param port the listening WebSocket port number + */ + WebSockSender(int port); + + /** + * The destructor closes the socket. + */ + virtual ~WebSockSender() {} + + /** + * This method delivers the provided OSC data + * + * @param *bundle the OSC stream to deliver + * @return true if the data was delivered successfully + */ + bool sendOscPacket (osc::OutboundPacketStream *bundle); + + /** + * This method is called whenever a new client connects + * + * @param tcp_client the socket handle of the new client + */ + void newClient( int tcp_client ); + + const char* tuio_type() { return "TUIO/WEB"; } + private: + + void sha1( uint8_t digest[SHA1_HASH_SIZE], const uint8_t* inbuf, size_t length ); + std::string base64( uint8_t* buffer, size_t size ); + }; +} +#endif /* INCLUDED_WEBSOCKSENDER_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/CHANGES b/modules/touch/ext/libTUIO2/oscpack/CHANGES new file mode 100644 index 0000000000..5db666be36 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/CHANGES @@ -0,0 +1,159 @@ +April 9, 2013 +------------- + +Changes for the 1.1.0 release (vs 1.0.2) are listed below. Unless +otherwise indicated these changes have been made since +January 2013. The focus has been on general clean-up, fixing bugs, +compiler errors and warnings, and fixing issues on 64 bit platforms. +A few improvements such as support for OSC arrays, functions +for setting broadcast and reuse socket options have been added. +This update merges changes from the openFrameworks version +of oscpack. + + - Added support for arrays in messages (see OscUnitTests.cpp + for example usage). (patch thanks to Tim Blechmann) + + - Fixed bugs relating to 64 bit usage (e.g. crashes in 64 bit + builds on OS X). + + - Some member functions that previously used the "int" or + "unsigned long" type for parameters or return values now use + std::size_t (platform-defined) or + osc_bundle_element_size_t (a.k.a. int32). + This change was made to better support 64 bit platforms. + See SVN revision 70 for details. + + - The previous point introduces a breaking change on Linux/x86_64 + for callers of AsBlob() and AsBlobUnchecked(): + The type of the second argument (the "size" argument) to + ReceivedMessageArgument::AsBlob() and + ReceivedMessageArgument::AsBlobUnchecked() has changed + from unsigned long & to osc_bundle_element_size_t (an int32). + You should declare your size argument variables as + osc_bundle_element_size_t to avoid incompatibilities between + 32 and 64 bit builds. + + - Note that oscpack does not support packets larger than + 0x7FFFFFFC (see comments in class ReceivedPacket for + details). + + - Oscpack defines an osc::Nil value used for sending the nil + message argument value. This conflicts with Objective-C. + Therefore osc::Nil is no longer defined in Obj-C++ code. + There is now an osc::OscNil value, which should be preferred. + osc::Nil is still available when writing C++. + (fix thanks to openFrameworks) + + - Added UdpSocket::SetEnableBroadcast(). This needs to + be called to enable sending to the broadcast address on some + platforms (e.g. Mac OS X). (thanks to openFrameworks) + + - Added UdpSocket::SetAllowReuse(). This is useful for + sharing sockets on some platforms (Mac?), and not so useful + on other platforms. (thanks to openFrameworks) + + - Added IpEndpointName::IsMulticastAddress() (2010) + + - Cleaned up C++ header usage and std:: namespace usage + to be more standards compliant (fixes issues on recent compilers + such as clang and gcc4.6). + + - Improved host endianness detection. Should auto-detect + endianness on most platforms now. + (thanks to Tim Blechmann for help with this) + + - Fixed two memory leaks: (1) in OscPrintReceivedElements.cpp + when printing time tag message arguments (thanks to Gwydion ap Dafydd). + (2) in the posix SocketReceiveMultiplexer::Run() method if an exception + was thrown while listening. + + - Fixed bug in posix SocketReceiveMultiplexer::Run() that would cause + packets to stop being received if select() returned EINTR. + (thanks to Björn Wöldecke) + + - Updated and improved Makefile to avoid redundant re-linking + (thanks to Douglas Mandell) + + - Added CMakeLists.txt CMake build file (2010, thanks to David Doria) + + - Switched license to plain MIT license with non binding request + for contribution of improvements (same as current PortAudio + boilerplate). See LICENSE file. + +Thanks to Tim Blechmann, Rob Canning, Gwydion ap Dafydd, David Doria, +Christopher Delaney, Jon McCormack, Douglas Mandell, Björn Wöldecke, +all the guys at openFrameworks, and everyone who reported bugs, +submitted patches and helped out with testing this release. + +Thanks to Syneme at the University of Calgary for providing financial +support for the 1.1.0 update. + + +September 28, 2005 +------------------ + +Compared to the previous official snapshot (November 2004) the +current version of oscpack includes a re-written set of network +classes and some changes to the syntax of the networking code. It no +longer uses threads, which means that you don't need to use sleep() +if you are writing a simple single-threaded server, or you need to +spawn your own threads in a more complex application. + +The list below summarises the changes if you are porting code from +the previous release. + + - There are no longer any threads in oscpack. if you need to + set up an asynchronous listener you can create your own thread + and call Run on an instance of SocketReceiveMultiplexer or + UdpListeningReceiveSocket (see ip/UdpSocket.h) yourself. + + - Host byte order is now used for network (IP) addresses + + - Functions which used to take two parameters + now take an instance of IpEndpointName (see + ip/IpEndpointName.h) this class has a number of convenient + constructors for converting numbers and strings to internet + addresses. For example there is one which takes a string and + another that take the dotted address components as separate + parameters. + + - The UdpTransmitPort class, formerly in UdpTransmitPort.h, is + now called UdpTransmitSocket, which is simply a convenience + class derived from UdpSocket (see ip/UdpSocket.h). Where you + used to use the constructor UdpTransmitPort( address, port) now + you can use UdpTransmitSocket( IpEndpointName( address, port ) + ) or you can any of the other possible ctors to IpEndpointName + () (see above). The Send() method is unchanged. + + - The packet listener base class is now located in + ip/PacketListener.h instead of PacketListenerPort.h. The + ProcessPacket method now has an additional parameter indicating + the remote endpoint + + - The preferred way to set up listeners is with + SocketReceiveMultiplexer (in ip/UdpSocket.h), this also allows + attaching periodic timers. For simple applications which only + listen to a single socket with no timers you can use + UdpListeningReceiveSocket (also in UdpSocket.h) See + osc/OscReceiveTest.cpp or osc/OscDump.cpp for examples of this. + This is more or less equivalent to the UdpPacketListenerPort + object in the old oscpack versions except that you need to + explicitly call Run() before it will start receiving packets + and it runs in the same thread, not a separate thread so Run() + won't usually return. + + - Explicit calls to InitializeNetworking() and + TerminateNetworking() are no longer required for simple + applications (more complex windows applications should + instantiate NetworkInitializer in main() or WinMain (see + ip/NetworkingUtils.h/.cpp) + + - The OscPacketListener base class (OscPacketListener.h) was + added to make traversing OSC packets easier, it handles bundle + traversal automatically so you only need to process messages in + your derived classes. + + - On Windows be sure to link with ws2_32.lib or you will see + a linker error about WSAEventSelect not being found. Also you + will need to link with winmm.lib for timeGetTime() + diff --git a/modules/touch/ext/libTUIO2/oscpack/LICENSE b/modules/touch/ext/libTUIO2/oscpack/LICENSE new file mode 100644 index 0000000000..ebaaac1977 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/LICENSE @@ -0,0 +1,34 @@ +oscpack -- Open Sound Control (OSC) packet manipulation library +http://www.rossbencina.com/code/oscpack + +Copyright (c) 2004-2013 Ross Bencina + +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. + +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. + +### + +The text above constitutes the entire oscpack license; however, +the oscpack developer(s) also make the following non-binding requests: + +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. It is also +requested that these non-binding requests be included whenever the +above license is reproduced. \ No newline at end of file diff --git a/modules/touch/ext/libTUIO2/oscpack/README b/modules/touch/ext/libTUIO2/oscpack/README new file mode 100644 index 0000000000..5d1d5c1216 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/README @@ -0,0 +1,150 @@ +oscpack -- Open Sound Control packet manipulation library +A simple C++ library for packing and unpacking OSC packets. +http://www.rossbencina.com/code/oscpack + +Copyright (c) 2004-2013 Ross Bencina + + +Oscpack is simply a set of C++ classes for packing and unpacking OSC packets. +Oscpack includes a minimal set of UDP networking classes for Windows and POSIX. +The networking classes are sufficient for writing many OSC applications and servers, +but you are encouraged to use another networking framework if it better suits your needs. +Oscpack is not an OSC application framework. It doesn't include infrastructure for +constructing or routing OSC namespaces, just classes for easily constructing, +sending, receiving and parsing OSC packets. The library should also be easy to use +for other transport methods (e.g. serial). + +The key goals of the oscpack library are: + + - Be a simple and complete implementation of OSC + - Be portable to a wide variety of platforms + - Allow easy development of robust OSC applications + (for example it should be impossible to crash a server + by sending it malformed packets, and difficult to create + malformed packets.) + +Here's a quick run down of the key files: + +osc/OscReceivedElements -- classes for parsing a packet +osc/OscPrintRecievedElements -- iostream << operators for printing packet elements +osc/OscOutboundPacketStream -- a class for packing messages into a packet +osc/OscPacketListener -- base class for listening to OSC packets on a UdpSocket +ip/IpEndpointName -- class that represents an IP address and port number +ip/UdpSocket -- classes for UDP transmission and listening sockets +tests/OscUnitTests -- unit test program for the OSC modules +tests/OscSendTests -- examples of how to send messages +tests/OscReceiveTest -- example of how to receive the messages sent by OSCSendTests +examples/OscDump -- a program that prints received OSC packets +examples/SimpleSend -- a minimal program to send an OSC message +examples/SimpleReceive -- a minimal program to receive an OSC message + +osc/ contains all of the OSC related classes +ip/ contains the networking classes + +ip/windows contains the Windows implementation of the networking classes +ip/posix contains the POSIX implementation of the networking classes + + +Building +-------- + +The idea is that you will embed this source code in your projects as you +see fit. The Makefile has an install rule for building a shared library and +installing headers in usr/local. It can also build a static library. +There is a CMakeLists.txt for building with cmake. + +Makefile builds +............... + +The Makefile works for Linux and Max OS X. It should also work on other platforms +that have make. Just run: + +$ make + +You can run "make install" if you like. + + +Cmake builds +............ + +There is a CMakeLists.txt file which has been tested with cmake on +Windows and Linux. It should work on other platforms too. +For example, to generate a Visual Studio 10 project, run cmake +like this: + +> cmake -G "Visual Studio 10" + +Run cmake without any parameters to get a list of available generators. + + +Mingw build batch file +...................... + +For Windows there is a batch file for doing a simple test build with +MinGW gcc called make.MinGW32.bat. This will build the test executables +and oscdump in ./bin and run the unit tests. + + +Note: + +In some rare instances you may need to edit the Makefile or +osc/OscHostEndianness.h to configure oscpack for the endianness of your +processor (see the comments at the top of the Makefile for details). + + + +Verification test +----------------- + +To run the unit tests: + +$ ./bin/OscUnitTests + +To run the send and receive tests. Open two terminals. In one run: + +$ ./bin/OscReceiveTest + +Then in the other terminal run: + +$./bin/OscSendTests + + +You should see an indication that the messages were received +in the first terminal. + +Note that OscSendTests intentionally sends some unexpected +message parameters to test exception handling in the receiver. +You will see some "error while parsing message" messages printed. + +You can use ./bin/OscDump to print out OSC messages received +from any program, including the test programs. + + +-- + + +If you fix anything or write a set of TCP send/receive classes +please consider sending me a patch. My email address is +rossb@audiomulch.com. Thanks :) + +For more information about Open Sound Control, see: +http://opensoundcontrol.org/ + +Thanks to Till Bovermann for helping with POSIX networking code and +Mac compatibility, and to Martin Kaltenbrunner and the rest of the +reacTable team for giving me a reason to finish this library. Thanks +to Merlijn Blaauw for reviewing the interfaces. Thanks to Xavier Oliver +for additional help with Linux builds and POSIX implementation details. + +Portions developed at the Music Technology Group, Audiovisual Institute, +University Pompeu Fabra, Barcelona, during my stay as a visiting +researcher, November 2004 - September 2005. + +Thanks to Syneme at the University of Calgary for providing financial +support for the 1.1.0 update, December 2012 - March 2013. + +See the file CHANGES for information about recent updates. + +See the file LICENSE for information about distributing and using this code. + +### diff --git a/modules/touch/ext/libTUIO2/oscpack/TODO b/modules/touch/ext/libTUIO2/oscpack/TODO new file mode 100644 index 0000000000..112f02eab5 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/TODO @@ -0,0 +1,52 @@ +TODO: + + - consider adding the local endpoint name to PacketListener::PacketReceived() params + + - consider adding ListenerThread class to support old seperate thread listener functionality, something like: + + class UdpSocketListenerThread{ + public: + UdpSocketListenerThread( UdpSocket& socket, Listener *listener ); + UdpSocketListenerThread( UdpSocketReceiveMultiplexer *mux ); + ~UdpSocketListenerThread(); + + void Run(); + void Stop(); + }; + + - work out a way to make the parsing classes totally safe. at a minimum this + means adding functions to test for invalid float/doublevalues, + making sure the iterators never pass the end of the message, ... + (passing end of message can happen if: + - too many args in type tags + a. typetags overflow message size + b. args fulfilling typetags overflow message size + - strings too long or not terminated correctly + - blobs too long or not terminated correctly + + if the message was fully checked during construction, the end() iterator + could be moved back until only arguments which fit withing size() may + be interated (this could be none). A flag could be set to indicate that + something was wrong. + + - other packet badness could include: + - time tags too far into the future (the scheduler should deal with + that i guess). + - message address patterns which aren't correctly terminated + + - improve the ability to parse messages without tags (SC uses methods which + get the data and advance the iterator in one step.) + - Check* could be modified to do this - ie if typetags are not present + it could check that reading the field won't escape the message size + and return the data, or return false if some consistency + constraint is violated. + (or alternately drop support for messages without type tags) + + + - add a method to discard an inprogress message if it gets half + constructed and the buffer is full in OutboundPacket + + - write a stress testing app which can send garbage packets to try to flush out other bugs in the parsing code. + + + diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.cpp b/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.cpp new file mode 100644 index 0000000000..50b0262216 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.cpp @@ -0,0 +1,88 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "IpEndpointName.h" + +#include + +#include "NetworkingUtils.h" + + +unsigned long IpEndpointName::GetHostByName( const char *s ) +{ + return ::GetHostByName(s); +} + + +void IpEndpointName::AddressAsString( char *s ) const +{ + if( address == ANY_ADDRESS ){ + std::sprintf( s, "" ); + }else{ + std::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 ){ + std::sprintf( s, ":" ); + }else{ + std::sprintf( s, "%d.%d.%d.%d:", + (int)((address >> 24) & 0xFF), + (int)((address >> 16) & 0xFF), + (int)((address >> 8) & 0xFF), + (int)(address & 0xFF) ); + } + }else{ + if( address == ANY_ADDRESS ){ + std::sprintf( s, ":%d", port ); + }else{ + std::sprintf( s, "%d.%d.%d.%d:%d", + (int)((address >> 24) & 0xFF), + (int)((address >> 16) & 0xFF), + (int)((address >> 8) & 0xFF), + (int)(address & 0xFF), + (int)port ); + } + } +} diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.h b/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.h new file mode 100644 index 0000000000..c83e1c3cfe --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/IpEndpointName.h @@ -0,0 +1,83 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_IPENDPOINTNAME_H +#define INCLUDED_OSCPACK_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; + + bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; } + + 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_OSCPACK_IPENDPOINTNAME_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/NetworkingUtils.h b/modules/touch/ext/libTUIO2/oscpack/ip/NetworkingUtils.h new file mode 100644 index 0000000000..a83612aeda --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/NetworkingUtils.h @@ -0,0 +1,56 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_NETWORKINGUTILS_H +#define INCLUDED_OSCPACK_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_OSCPACK_NETWORKINGUTILS_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/PacketListener.h b/modules/touch/ext/libTUIO2/oscpack/ip/PacketListener.h new file mode 100644 index 0000000000..6c26b32996 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/PacketListener.h @@ -0,0 +1,50 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_PACKETLISTENER_H +#define INCLUDED_OSCPACK_PACKETLISTENER_H + + +class IpEndpointName; + +class PacketListener{ +public: + virtual ~PacketListener() {} + virtual void ProcessPacket( const char *data, int size, + const IpEndpointName& remoteEndpoint ) = 0; +}; + +#endif /* INCLUDED_OSCPACK_PACKETLISTENER_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/TimerListener.h b/modules/touch/ext/libTUIO2/oscpack/ip/TimerListener.h new file mode 100644 index 0000000000..59b4040600 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/TimerListener.h @@ -0,0 +1,47 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_TIMERLISTENER_H +#define INCLUDED_OSCPACK_TIMERLISTENER_H + + +class TimerListener{ +public: + virtual ~TimerListener() {} + virtual void TimerExpired() = 0; +}; + +#endif /* INCLUDED_OSCPACK_TIMERLISTENER_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/UdpSocket.h b/modules/touch/ext/libTUIO2/oscpack/ip/UdpSocket.h new file mode 100644 index 0000000000..2d7a189a1b --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/UdpSocket.h @@ -0,0 +1,176 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_UDPSOCKET_H +#define INCLUDED_OSCPACK_UDPSOCKET_H + +#include // size_t + +#include "NetworkingUtils.h" +#include "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(); + + // Enable broadcast addresses (e.g. x.x.x.255) + // Sets SO_BROADCAST socket option. + void SetEnableBroadcast( bool enableBroadcast ); + + // Enable multiple listeners for a single port on same + // network interface* + // Sets SO_REUSEADDR (also SO_REUSEPORT on OS X). + // [*] The exact behavior of SO_REUSEADDR and + // SO_REUSEPORT is undefined for some common cases + // and may have drastically different behavior on different + // operating systems. + void SetAllowReuse( bool allowReuse ); + + + // 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, std::size_t size ); + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t 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; + + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t 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_OSCPACK_UDPSOCKET_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/posix/NetworkingUtils.cpp b/modules/touch/ext/libTUIO2/oscpack/ip/posix/NetworkingUtils.cpp new file mode 100644 index 0000000000..720abc207e --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/posix/NetworkingUtils.cpp @@ -0,0 +1,64 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "oscpack/ip/NetworkingUtils.h" + +#include +#include +#include + +#include + + + +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; + std::memcpy( &a, h->h_addr_list[0], h->h_length ); + result = ntohl(a.s_addr); + } + + return result; +} diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/posix/UdpSocket.cpp b/modules/touch/ext/libTUIO2/oscpack/ip/posix/UdpSocket.cpp new file mode 100644 index 0000000000..f0f1afbb78 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/posix/UdpSocket.cpp @@ -0,0 +1,602 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "oscpack/ip/UdpSocket.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include // for sockaddr_in + +#include +#include +#include +#include + +#include +#include +#include // for memset +#include +#include + +#include "oscpack/ip/PacketListener.h" +#include "oscpack/ip/TimerListener.h" + + +#if defined(__APPLE__) && !defined(_SOCKLEN_T) +// pre system 10.3 didn't have socklen_t +typedef ssize_t socklen_t; +#endif + + +static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) +{ + std::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"); + } + + std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); + sendToAddr_.sin_family = AF_INET; + } + + ~Implementation() + { + if (socket_ != -1) close(socket_); + } + + void SetEnableBroadcast( bool enableBroadcast ) + { + int broadcast = (enableBroadcast) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); + } + + void SetAllowReuse( bool allowReuse ) + { + int reuseAddr = (allowReuse) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)); + +#ifdef __APPLE__ + // needed also for OS X - enable multiple listeners for a single port on same network interface + int reusePort = (allowReuse) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort)); +#endif + } + + 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; + std::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; + std::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, std::size_t size ) + { + assert( isConnected_ ); + + send( socket_, data, size, 0 ); + } + + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t 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_; } + + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) + { + assert( isBound_ ); + + struct sockaddr_in fromAddr; + socklen_t fromAddrLen = sizeof(fromAddr); + + ssize_t 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 (std::size_t)result; + } + + int Socket() { return socket_; } +}; + +UdpSocket::UdpSocket() +{ + impl_ = new Implementation(); +} + +UdpSocket::~UdpSocket() +{ + delete impl_; +} + +void UdpSocket::SetEnableBroadcast( bool enableBroadcast ) +{ + impl_->SetEnableBroadcast( enableBroadcast ); +} + +void UdpSocket::SetAllowReuse( bool allowReuse ) +{ + impl_->SetAllowReuse( allowReuse ); +} + +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, std::size_t size ) +{ + impl_->Send( data, size ); +} + +void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) +{ + impl_->SendTo( remoteEndpoint, data, size ); +} + +void UdpSocket::Bind( const IpEndpointName& localEndpoint ) +{ + impl_->Bind( localEndpoint ); +} + +bool UdpSocket::IsBound() const +{ + return impl_->IsBound(); +} + +std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t 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; + char *data = 0; + + try{ + + // 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; + 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; + + long timoutSecondsPart = (long)(timeoutMs * .001); + timeout.tv_sec = (time_t)timoutSecondsPart; + // 1000000 microseconds in a second + timeout.tv_usec = (suseconds_t)((timeoutMs - (timoutSecondsPart * 1000)) * 1000); + timeoutPtr = &timeout; + } + + if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 ){ + if( break_ ){ + break; + }else if( errno == EINTR ){ + // on returning an error, select() doesn't clear tempfds. + // so tempfds would remain all set, which would cause read( breakPipe_[0]... + // below to block indefinitely. therefore if select returns EINTR we restart + // the while() loop instead of continuing on to below. + continue; + }else{ + throw std::runtime_error("select failed\n"); + } + } + + if( FD_ISSET( breakPipe_[0], &tempfds ) ){ + // clear pending data from the asynchronous break pipe + char c; + 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 ) ){ + + std::size_t size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); + if( size > 0 ){ + i->first->ProcessPacket( data, (int)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; + }catch(...){ + if( data ) + delete [] data; + throw; + } + } + + void Break() + { + break_ = true; + } + + void AsynchronousBreak() + { + break_ = true; + + // Send a termination message to the asynchronous break pipe, so select() will return + 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(); +} + diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/win32/NetworkingUtils.cpp b/modules/touch/ext/libTUIO2/oscpack/ip/win32/NetworkingUtils.cpp new file mode 100644 index 0000000000..487cfa38a0 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/win32/NetworkingUtils.cpp @@ -0,0 +1,95 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "oscpack/ip/NetworkingUtils.h" + +#include // this must come first to prevent errors with MSVC7 +#include + +#include + + +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; + std::memcpy( &a, h->h_addr_list[0], h->h_length ); + result = ntohl(a.s_addr); + } + + return result; +} diff --git a/modules/touch/ext/libTUIO2/oscpack/ip/win32/UdpSocket.cpp b/modules/touch/ext/libTUIO2/oscpack/ip/win32/UdpSocket.cpp new file mode 100644 index 0000000000..57cff3f5bf --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/ip/win32/UdpSocket.cpp @@ -0,0 +1,571 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ + +#include // this must come first to prevent errors with MSVC7 +#include +#include // for timeGetTime() + +#ifndef WINCE +#include +#endif + +#include +#include +#include // for memset +#include +#include + +#include "oscpack/ip/UdpSocket.h" // usually I'd include the module header first + // but this is causing conflicts with BCB4 due to + // std::size_t usage. + +#include "oscpack/ip/NetworkingUtils.h" +#include "oscpack/ip/PacketListener.h" +#include "oscpack/ip/TimerListener.h" + + +typedef int socklen_t; + + +static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) +{ + std::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"); + } + + std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); + sendToAddr_.sin_family = AF_INET; + } + + ~Implementation() + { + if (socket_ != INVALID_SOCKET) closesocket(socket_); + } + + void SetEnableBroadcast( bool enableBroadcast ) + { + char broadcast = (char)((enableBroadcast) ? 1 : 0); // char on win32 + setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); + } + + void SetAllowReuse( bool allowReuse ) + { + // Note: SO_REUSEADDR is non-deterministic for listening sockets on Win32. See MSDN article: + // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" + // http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx + + char reuseAddr = (char)((allowReuse) ? 1 : 0); // char on win32 + setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)); + } + + 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; + std::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, std::size_t size ) + { + assert( isConnected_ ); + + send( socket_, data, (int)size, 0 ); + } + + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) + { + sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address ); + sendToAddr_.sin_port = htons( (short)remoteEndpoint.port ); + + sendto( socket_, data, (int)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_; } + + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) + { + assert( isBound_ ); + + struct sockaddr_in fromAddr; + socklen_t fromAddrLen = sizeof(fromAddr); + + int result = recvfrom(socket_, data, (int)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_; +} + +void UdpSocket::SetEnableBroadcast( bool enableBroadcast ) +{ + impl_->SetEnableBroadcast( enableBroadcast ); +} + +void UdpSocket::SetAllowReuse( bool allowReuse ) +{ + impl_->SetAllowReuse( allowReuse ); +} + +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, std::size_t size ) +{ + impl_->Send( data, size ); +} + +void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) +{ + impl_->SendTo( remoteEndpoint, data, size ); +} + +void UdpSocket::Bind( const IpEndpointName& localEndpoint ) +{ + impl_->Bind( localEndpoint ); +} + +bool UdpSocket::IsBound() const +{ + return impl_->IsBound(); +} + +std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t 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(); +#ifndef WINCE + signal( SIGINT, SIG_DFL ); +#endif +} + + +class SocketReceiveMultiplexer::Implementation{ + NetworkInitializer networkInitializer_; + + std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_; + std::vector< AttachedTimerListener > timerListeners_; + + volatile bool break_; + HANDLE breakEvent_; + + double GetCurrentTimeMs() const + { +#ifndef WINCE + return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days +#else + return 0; +#endif + } + +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 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 ){ + std::size_t size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); + if( size > 0 ){ + socketListeners_[i].first->ProcessPacket( data, (int)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; +#ifndef WINCE + signal( SIGINT, InterruptSignalHandler ); +#endif + impl_->Run(); +#ifndef WINCE + signal( SIGINT, SIG_DFL ); +#endif + multiplexerInstanceToAbortWithSigInt_ = 0; +} + +void SocketReceiveMultiplexer::Break() +{ + impl_->Break(); +} + +void SocketReceiveMultiplexer::AsynchronousBreak() +{ + impl_->AsynchronousBreak(); +} + diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/MessageMappingOscPacketListener.h b/modules/touch/ext/libTUIO2/oscpack/osc/MessageMappingOscPacketListener.h new file mode 100644 index 0000000000..bf56b530a2 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/MessageMappingOscPacketListener.h @@ -0,0 +1,80 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H +#define INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H + +#include +#include + +#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(this)->*(i->second))( m, remoteEndpoint ); + } + +private: + struct cstr_compare{ + bool operator()( const char *lhs, const char *rhs ) const + { return std::strcmp( lhs, rhs ) < 0; } + }; + + typedef std::map function_map_type; + function_map_type functions_; +}; + +} // namespace osc + +#endif /* INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H */ \ No newline at end of file diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscException.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscException.h new file mode 100644 index 0000000000..73981737e0 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscException.h @@ -0,0 +1,62 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCEXCEPTION_H +#define INCLUDED_OSCPACK_OSCEXCEPTION_H + +#include + +namespace osc{ + +class Exception : public std::exception { + const char *what_; + +public: + Exception() throw() {} + Exception( const Exception& src ) throw() + : std::exception( src ) + , 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_OSCPACK_OSCEXCEPTION_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscHostEndianness.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscHostEndianness.h new file mode 100644 index 0000000000..4682c473a5 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscHostEndianness.h @@ -0,0 +1,127 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H +#define INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H + +/* + Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined + + We try to use preprocessor symbols to deduce the host endianness. + + Alternatively you can define one of the above symbols from the command line. + Usually you do this with the -D flag to the compiler. e.g.: + + $ g++ -DOSC_HOST_LITTLE_ENDIAN ... +*/ + +#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN) + +// endianness defined on the command line. nothing to do here. + +#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE) + +// 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 + +#elif defined(__BIG_ENDIAN__) + +#define OSC_HOST_BIG_ENDIAN 1 +#undef OSC_HOST_LITTLE_ENDIAN + +#endif + +#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) + +// should cover gcc and clang + +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +#define OSC_HOST_LITTLE_ENDIAN 1 +#undef OSC_HOST_BIG_ENDIAN + +#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + +#define OSC_HOST_BIG_ENDIAN 1 +#undef OSC_HOST_LITTLE_ENDIAN + +#endif + +#else + +// gcc defines __LITTLE_ENDIAN__ and __BIG_ENDIAN__ +// for others used here see http://sourceforge.net/p/predef/wiki/Endianness/ +#if (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) \ + || (defined(__ARMEL__) && !defined(__ARMEB__)) \ + || (defined(__AARCH64EL__) && !defined(__AARCH64EB__)) \ + || (defined(_MIPSEL) && !defined(_MIPSEB)) \ + || (defined(__MIPSEL) && !defined(__MIPSEB)) \ + || (defined(__MIPSEL__) && !defined(__MIPSEB__)) + +#define OSC_HOST_LITTLE_ENDIAN 1 +#undef OSC_HOST_BIG_ENDIAN + +#elif (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) \ + || (defined(__ARMEB__) && !defined(__ARMEL__)) \ + || (defined(__AARCH64EB__) && !defined(__AARCH64EL__)) \ + || (defined(_MIPSEB) && !defined(_MIPSEL)) \ + || (defined(__MIPSEB) && !defined(__MIPSEL)) \ + || (defined(__MIPSEB__) && !defined(__MIPSEL__)) + +#define OSC_HOST_BIG_ENDIAN 1 +#undef OSC_HOST_LITTLE_ENDIAN + +#endif + +#endif + +#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN) + +#error please edit OSCHostEndianness.h or define one of {OSC_HOST_LITTLE_ENDIAN, OSC_HOST_BIG_ENDIAN} to configure endianness + +#endif + +#endif /* INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H */ + diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.cpp b/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.cpp new file mode 100644 index 0000000000..b474b4f01a --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.cpp @@ -0,0 +1,683 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "OscOutboundPacketStream.h" + +#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) +#include // for alloca +#else +//#include // alloca on Linux (also OSX) +#include // alloca on OSX and FreeBSD (and Linux?) +#endif + +#include +#include // memcpy, memmove, strcpy, strlen +#include // ptrdiff_t + +#include "OscHostEndianness.h" + +#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug +namespace std { +using ::__strcpy__; // avoid error: E2316 '__strcpy__' is not a member of 'std'. +} +#endif + +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(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(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(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(p) = x; +#endif +} + + +// round up to the next highest multiple of 4. unless x is already a multiple of 4 +static inline std::size_t RoundUp4( std::size_t x ) +{ + return (x + 3) & ~((std::size_t)0x03); +} + + +OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity ) + : data_( buffer ) + , end_( data_ + capacity ) + , typeTagsCurrent_( end_ ) + , messageCursor_( data_ ) + , argumentCurrent_( data_ ) + , elementSizePtr_( 0 ) + , messageIsInProgress_( false ) +{ + // sanity check integer types declared in OscTypes.h + // you'll need to fix OscTypes.h if any of these asserts fail + assert( sizeof(osc::int32) == 4 ); + assert( sizeof(osc::uint32) == 4 ); + assert( sizeof(osc::int64) == 8 ); + assert( sizeof(osc::uint64) == 8 ); +} + + +OutboundPacketStream::~OutboundPacketStream() +{ + +} + + +char *OutboundPacketStream::BeginElement( char *beginPtr ) +{ + if( elementSizePtr_ == 0 ){ + + elementSizePtr_ = reinterpret_cast(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(beginPtr) = + (uint32)(reinterpret_cast(elementSizePtr_) - data_); + + elementSizePtr_ = reinterpret_cast(beginPtr); + + return beginPtr + 4; + } +} + + +void OutboundPacketStream::EndElement( char *endPtr ) +{ + assert( elementSizePtr_ != 0 ); + + if( elementSizePtr_ == reinterpret_cast(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 = + reinterpret_cast(data_ + *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. + + std::ptrdiff_t d = endPtr - reinterpret_cast(elementSizePtr_); + // assert( d >= 4 && d <= 0x7FFFFFFF ); // assume packets smaller than 2Gb + + uint32 elementSize = static_cast(d - 4); + FromUInt32( reinterpret_cast(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() +{ + std::size_t 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 + std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + + RoundUp4(std::strlen(addressPattern) + 1) + 4; + + if( required > Capacity() ) + throw OutOfBufferMemoryException(); +} + + +void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) +{ + // plus three for extra type tag, comma and null terminator + std::size_t 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; +} + + +std::size_t OutboundPacketStream::Capacity() const +{ + return end_ - data_; +} + + +std::size_t OutboundPacketStream::Size() const +{ + std::size_t 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_ ); + + std::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_ ); + + std::strcpy( messageCursor_, rhs.addressPattern ); + std::size_t rhsLength = std::strlen(rhs.addressPattern); + messageCursor_ += rhsLength + 1; + + // zero pad to 4-byte boundary + std::size_t 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(); + + std::size_t typeTagsCount = end_ - typeTagsCurrent_; + + if( typeTagsCount ){ + + char *tempTypeTags = (char*)alloca(typeTagsCount); + std::memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount ); + + // slot size includes comma and null terminator + std::size_t typeTagSlotSize = RoundUp4( typeTagsCount + 2 ); + + std::size_t argumentsSize = argumentCurrent_ - messageCursor_; + + std::memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize ); + + messageCursor_[0] = ','; + // copy type tags in reverse (really forward) order + for( std::size_t i=0; i < typeTagsCount; ++i ) + messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ]; + + char *p = messageCursor_ + 1 + typeTagsCount; + for( std::size_t 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 + std::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(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(argumentCurrent_) = rhs; +#endif + + argumentCurrent_ += 8; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) +{ + CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + + *(--typeTagsCurrent_) = STRING_TYPE_TAG; + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); + argumentCurrent_ += rhsLength + 1; + + // zero pad to 4-byte boundary + std::size_t i = rhsLength + 1; + while( i & 0x3 ){ + *argumentCurrent_++ = '\0'; + ++i; + } + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) +{ + CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); + + *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); + argumentCurrent_ += rhsLength + 1; + + // zero pad to 4-byte boundary + std::size_t 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; + + std::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; +} + +OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs ) +{ + (void) rhs; + CheckForAvailableArgumentSpace(0); + + *(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG; + + return *this; +} + +OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs ) +{ + (void) rhs; + CheckForAvailableArgumentSpace(0); + + *(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG; + + return *this; +} + +} // namespace osc + + diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.h new file mode 100644 index 0000000000..1a90a01239 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscOutboundPacketStream.h @@ -0,0 +1,154 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H +#define INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H + +#include // size_t + +#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, std::size_t capacity ); + ~OutboundPacketStream(); + + void Clear(); + + std::size_t Capacity() const; + + // invariant: size() is valid even while building a message. + std::size_t 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 ); + +#if !(defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)) + 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 ); + + OutboundPacketStream& operator<<( const ArrayInitiator& rhs ); + OutboundPacketStream& operator<<( const ArrayTerminator& rhs ); + +private: + + char *BeginElement( char *beginPtr ); + void EndElement( char *endPtr ); + + bool ElementSizeSlotRequired() const; + void CheckForAvailableBundleSpace(); + void CheckForAvailableMessageSpace( const char *addressPattern ); + void CheckForAvailableArgumentSpace( std::size_t 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_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscPacketListener.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscPacketListener.h new file mode 100644 index 0000000000..472cb1066f --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscPacketListener.h @@ -0,0 +1,79 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCPACKETLISTENER_H +#define INCLUDED_OSCPACK_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_OSCPACK_OSCPACKETLISTENER_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.cpp b/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.cpp new file mode 100644 index 0000000000..bc1689bc1d --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.cpp @@ -0,0 +1,261 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "OscPrintReceivedElements.h" + +#include +#include +#include +#include + +#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug +namespace std { +using ::__strcpy__; // avoid error: E2316 '__strcpy__' is not a member of 'std'. +} +#endif + +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 ); + + const char *timeString = std::ctime( &t ); + size_t len = std::strlen( timeString ); + + // -1 to omit trailing newline from string returned by ctime() + if( len > 1 ) + os.write( timeString, len - 1 ); + } + 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: + { + const void *data; + osc_bundle_element_size_t size; + arg.AsBlobUnchecked( data, size ); + os << "OSC-blob:<<" << std::hex << std::setfill('0'); + unsigned char *p = (unsigned char*)data; + for( osc_bundle_element_size_t 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; + + case ARRAY_BEGIN_TYPE_TAG: + os << "["; + break; + + case ARRAY_END_TYPE_TAG: + os << "]"; + break; + + default: + os << "unknown"; + } + + return os; +} + + +std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m ) +{ + os << "["; + if( m.AddressPatternIsUInt32() ) + os << m.AddressPatternAsUInt32(); + else + 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 diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.h new file mode 100644 index 0000000000..8d71391f0c --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscPrintReceivedElements.h @@ -0,0 +1,54 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H +#define INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H + +#include + +#include "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_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.cpp b/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.cpp new file mode 100644 index 0000000000..14bbe39c19 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.cpp @@ -0,0 +1,796 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "OscReceivedElements.h" + +#include "OscHostEndianness.h" + +#include // ptrdiff_t + +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; +} + + +// round up to the next highest multiple of 4. unless x is already a multiple of 4 +static inline uint32 RoundUp4( uint32 x ) +{ + return (x + 3) & ~((uint32)0x03); +} + + +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 +} + + +static inline 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 +} + + +static inline 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] == '#'); +} + + +osc_bundle_element_size_t ReceivedBundleElement::Size() const +{ + return ToInt32( sizePtr_ ); +} + +//------------------------------------------------------------------------------ + +bool ReceivedMessageArgument::AsBool() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == TRUE_TYPE_TAG ) + return true; + else if( *typeTagPtr_ == FALSE_TYPE_TAG ) + return false; + else + throw WrongArgumentTypeException(); +} + + +bool ReceivedMessageArgument::AsBoolUnchecked() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == TRUE_TYPE_TAG ) + return true; + else + return false; +} + + +int32 ReceivedMessageArgument::AsInt32() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == 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] = argumentPtr_[3]; + u.c[1] = argumentPtr_[2]; + u.c[2] = argumentPtr_[1]; + u.c[3] = argumentPtr_[0]; + + return u.i; +#else + return *(int32*)argumentPtr_; +#endif +} + + +float ReceivedMessageArgument::AsFloat() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == 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] = argumentPtr_[3]; + u.c[1] = argumentPtr_[2]; + u.c[2] = argumentPtr_[1]; + u.c[3] = argumentPtr_[0]; + + return u.f; +#else + return *(float*)argumentPtr_; +#endif +} + + +char ReceivedMessageArgument::AsChar() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == CHAR_TYPE_TAG ) + return AsCharUnchecked(); + else + throw WrongArgumentTypeException(); +} + + +char ReceivedMessageArgument::AsCharUnchecked() const +{ + return (char)ToInt32( argumentPtr_ ); +} + + +uint32 ReceivedMessageArgument::AsRgbaColor() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG ) + return AsRgbaColorUnchecked(); + else + throw WrongArgumentTypeException(); +} + + +uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const +{ + return ToUInt32( argumentPtr_ ); +} + + +uint32 ReceivedMessageArgument::AsMidiMessage() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG ) + return AsMidiMessageUnchecked(); + else + throw WrongArgumentTypeException(); +} + + +uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const +{ + return ToUInt32( argumentPtr_ ); +} + + +int64 ReceivedMessageArgument::AsInt64() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == INT64_TYPE_TAG ) + return AsInt64Unchecked(); + else + throw WrongArgumentTypeException(); +} + + +int64 ReceivedMessageArgument::AsInt64Unchecked() const +{ + return ToInt64( argumentPtr_ ); +} + + +uint64 ReceivedMessageArgument::AsTimeTag() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG ) + return AsTimeTagUnchecked(); + else + throw WrongArgumentTypeException(); +} + + +uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const +{ + return ToUInt64( argumentPtr_ ); +} + + +double ReceivedMessageArgument::AsDouble() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == 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] = argumentPtr_[7]; + u.c[1] = argumentPtr_[6]; + u.c[2] = argumentPtr_[5]; + u.c[3] = argumentPtr_[4]; + u.c[4] = argumentPtr_[3]; + u.c[5] = argumentPtr_[2]; + u.c[6] = argumentPtr_[1]; + u.c[7] = argumentPtr_[0]; + + return u.d; +#else + return *(double*)argumentPtr_; +#endif +} + + +const char* ReceivedMessageArgument::AsString() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == STRING_TYPE_TAG ) + return argumentPtr_; + else + throw WrongArgumentTypeException(); +} + + +const char* ReceivedMessageArgument::AsSymbol() const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == SYMBOL_TYPE_TAG ) + return argumentPtr_; + else + throw WrongArgumentTypeException(); +} + + +void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const +{ + if( !typeTagPtr_ ) + throw MissingArgumentException(); + else if( *typeTagPtr_ == BLOB_TYPE_TAG ) + AsBlobUnchecked( data, size ); + else + throw WrongArgumentTypeException(); +} + + +void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const +{ + // read blob size as an unsigned int then validate + osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ ); + if( !IsValidElementSizeValue(sizeResult) ) + throw MalformedMessageException("invalid blob size"); + + size = sizeResult; + data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32); +} + +std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const +{ + // it is only valid to call ComputeArrayItemCount when the argument is the array start marker + if( !IsArrayBegin() ) + throw WrongArgumentTypeException(); + + std::size_t result = 0; + unsigned int level = 0; + const char *typeTag = typeTagPtr_ + 1; + + // iterate through all type tags. note that ReceivedMessage::Init + // has already checked that the message is well formed. + while( *typeTag ) { + switch( *typeTag++ ) { + case ARRAY_BEGIN_TYPE_TAG: + level += 1; + break; + + case ARRAY_END_TYPE_TAG: + if(level == 0) + return result; + level -= 1; + break; + + default: + if( level == 0 ) // only count items at level 0 + ++result; + } + } + + return result; +} + +//------------------------------------------------------------------------------ + +void ReceivedMessageArgumentIterator::Advance() +{ + if( !value_.typeTagPtr_ ) + return; + + switch( *value_.typeTagPtr_++ ){ + case '\0': + // don't advance past end + --value_.typeTagPtr_; + 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_.argumentPtr_ += 4; + break; + + case INT64_TYPE_TAG: + case TIME_TAG_TYPE_TAG: + case DOUBLE_TYPE_TAG: + + value_.argumentPtr_ += 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_.argumentPtr_ = FindStr4End( value_.argumentPtr_ ); + break; + + case BLOB_TYPE_TAG: + { + // treat blob size as an unsigned int for the purposes of this calculation + uint32 blobSize = ToUInt32( value_.argumentPtr_ ); + value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); + } + break; + + case ARRAY_BEGIN_TYPE_TAG: + case ARRAY_END_TYPE_TAG: + + // [ 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. + + // zero length, don't advance argument ptr + break; + + default: // unknown type tag + // don't advance + --value_.typeTagPtr_; + break; + } +} + +//------------------------------------------------------------------------------ + +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, osc_bundle_element_size_t size ) +{ + if( !IsValidElementSizeValue(size) ) + throw MalformedMessageException( "invalid message size" ); + + if( size == 0 ) + throw MalformedMessageException( "zero length messages not permitted" ); + + if( !IsMultipleOf4(size) ) + 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_; + unsigned int arrayLevel = 0; + + do{ + switch( *typeTag ){ + case TRUE_TYPE_TAG: + case FALSE_TYPE_TAG: + case NIL_TYPE_TAG: + case INFINITUM_TYPE_TAG: + // zero length + break; + + // [ 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. + case ARRAY_BEGIN_TYPE_TAG: + ++arrayLevel; + // (zero length argument data) + break; + + case ARRAY_END_TYPE_TAG: + --arrayLevel; + // (zero length argument data) + 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 + osc::OSC_SIZEOF_INT32 > end ) + MalformedMessageException( "arguments exceed message size" ); + + // treat blob size as an unsigned int for the purposes of this calculation + uint32 blobSize = ToUInt32( argument ); + argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); + if( argument > end ) + MalformedMessageException( "arguments exceed message size" ); + } + break; + + default: + throw MalformedMessageException( "unknown type tag" ); + } + + }while( *++typeTag != '\0' ); + typeTagsEnd_ = typeTag; + + if( arrayLevel != 0 ) + throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" ); + } + + // These invariants should be guaranteed by the above code. + // we depend on them in the implementation of ArgumentCount() +#ifndef NDEBUG + std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_; + assert( argumentCount >= 0 ); + assert( argumentCount <= OSC_INT32_MAX ); +#endif + } +} + +//------------------------------------------------------------------------------ + +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, osc_bundle_element_size_t size ) +{ + + if( !IsValidElementSizeValue(size) ) + throw MalformedBundleException( "invalid bundle size" ); + + if( size < 16 ) + throw MalformedBundleException( "packet too short for bundle" ); + + if( !IsMultipleOf4(size) ) + 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 + osc::OSC_SIZEOF_INT32 > end_ ) + throw MalformedBundleException( "packet too short for elementSize" ); + + // treat element size as an unsigned int for the purposes of this calculation + uint32 elementSize = ToUInt32( p ); + if( (elementSize & ((uint32)0x03)) != 0 ) + throw MalformedBundleException( "bundle element size must be multiple of four" ); + + p += osc::OSC_SIZEOF_INT32 + 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 + diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.h new file mode 100644 index 0000000000..69d0e6c545 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscReceivedElements.h @@ -0,0 +1,548 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H +#define INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H + +#include +#include +#include // size_t + +#include "OscTypes.h" +#include "OscException.h" + + +namespace osc{ + + +class MalformedPacketException : public Exception{ +public: + MalformedPacketException( const char *w="malformed packet" ) + : Exception( w ) {} +}; + +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: + // Although the OSC spec is not entirely clear on this, we only support + // packets up to 0x7FFFFFFC bytes long (the maximum 4-byte aligned value + // representable by an int32). An exception will be raised if you pass a + // larger value to the ReceivedPacket() constructor. + + ReceivedPacket( const char *contents, osc_bundle_element_size_t size ) + : contents_( contents ) + , size_( ValidateSize(size) ) {} + + ReceivedPacket( const char *contents, std::size_t size ) + : contents_( contents ) + , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} + +#if !(defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)) + ReceivedPacket( const char *contents, int size ) + : contents_( contents ) + , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} +#endif + + bool IsMessage() const { return !IsBundle(); } + bool IsBundle() const; + + osc_bundle_element_size_t Size() const { return size_; } + const char *Contents() const { return contents_; } + +private: + const char *contents_; + osc_bundle_element_size_t size_; + + static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size ) + { + // sanity check integer types declared in OscTypes.h + // you'll need to fix OscTypes.h if any of these asserts fail + assert( sizeof(osc::int32) == 4 ); + assert( sizeof(osc::uint32) == 4 ); + assert( sizeof(osc::int64) == 8 ); + assert( sizeof(osc::uint64) == 8 ); + + if( !IsValidElementSizeValue(size) ) + throw MalformedPacketException( "invalid packet size" ); + + if( size == 0 ) + throw MalformedPacketException( "zero length elements not permitted" ); + + if( !IsMultipleOf4(size) ) + throw MalformedPacketException( "element size must be multiple of four" ); + + return size; + } +}; + + +class ReceivedBundleElement{ +public: + ReceivedBundleElement( const char *sizePtr ) + : sizePtr_( sizePtr ) {} + + friend class ReceivedBundleElementIterator; + + bool IsMessage() const { return !IsBundle(); } + bool IsBundle() const; + + osc_bundle_element_size_t Size() const; + const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; } + +private: + const char *sizePtr_; +}; + + +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_.sizePtr_ = value_.Contents() + value_.Size(); } + + bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const + { + return value_.sizePtr_ == rhs.value_.sizePtr_; + } +}; + +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 *typeTagPtr, const char *argumentPtr ) + : typeTagPtr_( typeTagPtr ) + , argumentPtr_( argumentPtr ) {} + + friend class ReceivedMessageArgumentIterator; + + char TypeTag() const { return *typeTagPtr_; } + + // 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 *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; } + bool AsBool() const; + bool AsBoolUnchecked() const; + + bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; } + bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; } + + bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; } + int32 AsInt32() const; + int32 AsInt32Unchecked() const; + + bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; } + float AsFloat() const; + float AsFloatUnchecked() const; + + bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; } + char AsChar() const; + char AsCharUnchecked() const; + + bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; } + uint32 AsRgbaColor() const; + uint32 AsRgbaColorUnchecked() const; + + bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; } + uint32 AsMidiMessage() const; + uint32 AsMidiMessageUnchecked() const; + + bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; } + int64 AsInt64() const; + int64 AsInt64Unchecked() const; + + bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; } + uint64 AsTimeTag() const; + uint64 AsTimeTagUnchecked() const; + + bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; } + double AsDouble() const; + double AsDoubleUnchecked() const; + + bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; } + const char* AsString() const; + const char* AsStringUnchecked() const { return argumentPtr_; } + + bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; } + const char* AsSymbol() const; + const char* AsSymbolUnchecked() const { return argumentPtr_; } + + bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; } + void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const; + void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const; + + bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; } + bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; } + // Calculate the number of top-level items in the array. Nested arrays count as one item. + // Only valid at array start. Will throw an exception if IsArrayStart() == false. + std::size_t ComputeArrayItemCount() const; + +private: + const char *typeTagPtr_; + const char *argumentPtr_; +}; + + +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_.typeTagPtr_ == rhs.value_.typeTagPtr_; + } +}; + +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 + // same goes for array boundaries + + 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 ) + { + (void) rhs; // suppress unused parameter warning + + if( !Eos() ) + throw ExcessArgumentException(); + + return *this; + } +}; + + +class ReceivedMessage{ + void Init( const char *bundle, osc_bundle_element_size_t size ); +public: + explicit ReceivedMessage( const ReceivedPacket& packet ); + explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); + + const char *AddressPattern() const { return addressPattern_; } + + // Support for non-standard SuperCollider integer address patterns: + bool AddressPatternIsUInt32() const; + uint32 AddressPatternAsUInt32() const; + + uint32 ArgumentCount() const { return static_cast(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, osc_bundle_element_size_t size ); +public: + explicit ReceivedBundle( const ReceivedPacket& packet ); + explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); + + uint64 TimeTag() const; + + uint32 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_; + uint32 elementCount_; +}; + + +} // namespace osc + + +#endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */ diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.cpp b/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.cpp new file mode 100644 index 0000000000..444a9fed48 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.cpp @@ -0,0 +1,52 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "OscTypes.h" + +namespace osc{ + +BundleInitiator BeginBundleImmediate(1); +BundleTerminator EndBundle; +MessageTerminator EndMessage; +NilType OscNil; +#ifndef _OBJC_OBJC_H_ +NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead +#endif +InfinitumType Infinitum; +ArrayInitiator BeginArray; +ArrayTerminator EndArray; + +} // namespace osc diff --git a/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.h b/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.h new file mode 100644 index 0000000000..53db577ea9 --- /dev/null +++ b/modules/touch/ext/libTUIO2/oscpack/osc/OscTypes.h @@ -0,0 +1,240 @@ +/* + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack + + Copyright (c) 2004-2013 Ross Bencina + + 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. + + 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. +*/ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + 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. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCTYPES_H +#define INCLUDED_OSCPACK_OSCTYPES_H + + +namespace osc{ + +// basic types + +#if defined(__BORLANDC__) || defined(_MSC_VER) + +typedef __int64 int64; +typedef unsigned __int64 uint64; + +#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) + +typedef long int64; +typedef unsigned long uint64; + +#else + +typedef long long int64; +typedef unsigned long long uint64; + +#endif + + + +#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) + +typedef signed int int32; +typedef unsigned int uint32; + +#else + +typedef signed long int32; +typedef unsigned long uint32; + +#endif + + +enum ValueTypeSizes{ + OSC_SIZEOF_INT32 = 4, + OSC_SIZEOF_UINT32 = 4, + OSC_SIZEOF_INT64 = 8, + OSC_SIZEOF_UINT64 = 8, +}; + + +// osc_bundle_element_size_t is used for the size of bundle elements and blobs +// the OSC spec specifies these as int32 (signed) but we ensure that they +// are always positive since negative field sizes make no sense. + +typedef int32 osc_bundle_element_size_t; + +enum { + OSC_INT32_MAX = 0x7FFFFFFF, + + // Element sizes are specified to be int32, and are always rounded up to nearest + // multiple of 4. Therefore their values can't be greater than 0x7FFFFFFC. + OSC_BUNDLE_ELEMENT_SIZE_MAX = 0x7FFFFFFC +}; + + +inline bool IsValidElementSizeValue( osc_bundle_element_size_t x ) +{ + // sizes may not be negative or exceed OSC_BUNDLE_ELEMENT_SIZE_MAX + return x >= 0 && x <= OSC_BUNDLE_ELEMENT_SIZE_MAX; +} + + +inline bool IsMultipleOf4( osc_bundle_element_size_t x ) +{ + return (x & ((osc_bundle_element_size_t)0x03)) == 0; +} + + +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', + ARRAY_BEGIN_TYPE_TAG = '[', + ARRAY_END_TYPE_TAG = ']' +}; + + + +// 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 OscNil; + +#ifndef _OBJC_OBJC_H_ +extern NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead +#endif + +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_, osc_bundle_element_size_t size_ ) + : data( data_ ), size( size_ ) {} + const void* data; + osc_bundle_element_size_t size; +}; + +struct ArrayInitiator{ +}; + +extern ArrayInitiator BeginArray; + +struct ArrayTerminator{ +}; + +extern ArrayTerminator EndArray; + +} // namespace osc + + +#endif /* INCLUDED_OSCPACK_OSCTYPES_H */ diff --git a/modules/touch/include.cmake b/modules/touch/include.cmake new file mode 100644 index 0000000000..6eb8a40c99 --- /dev/null +++ b/modules/touch/include.cmake @@ -0,0 +1 @@ +set (DEFAULT_MODULE ON) \ No newline at end of file diff --git a/modules/touch/include/TuioEar.h b/modules/touch/include/TuioEar.h new file mode 100644 index 0000000000..9c0cae9c92 --- /dev/null +++ b/modules/touch/include/TuioEar.h @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + * * + * 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 __OPENSPACE_MODULE_TOUCH___TOUCHEAR___H__ +#define __OPENSPACE_MODULE_TOUCH___TOUCHEAR___H__ + +#include +#include +#include +#include +#include +#include + + +using namespace TUIO2; + +class TuioEar : public TuioListener { + + public: + TuioEar(); + ~TuioEar() { + tuioClient->disconnect(); + delete tuioClient; + delete oscReceiver; + } + + void tuioAdd(TuioObject *tobj); + void tuioUpdate(TuioObject *tobj); + void tuioRemove(TuioObject *tobj); + void tuioRefresh(TuioTime frameTime); + + std::vector* getInput() { return &list; } + + private: + TuioClient *tuioClient; + OscReceiver *oscReceiver; + std::vector list; + std::vector::iterator it; +}; + +#endif // __OPENSPACE_MODULE_TOUCH___TOUCHWRAPPER___H__ diff --git a/modules/touch/src/TuioEar.cpp b/modules/touch/src/TuioEar.cpp new file mode 100644 index 0000000000..74b5f29749 --- /dev/null +++ b/modules/touch/src/TuioEar.cpp @@ -0,0 +1,89 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + * * + * 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 +#include +#include // std::find + + +#include + +namespace { + const std::string _loggerCat = "TuioEar"; +} + +void TuioEar::tuioAdd(TuioObject *tobj) { + + if (tobj->containsNewTuioToken()) LINFO("add tok " << tobj->getTuioToken()->getSessionID() << "\n"); + if (tobj->containsNewTuioPointer()) { + list.push_back(tobj->getTuioPointer()); + LINFO("add ptr " << tobj->getTuioPointer()->getSessionID() << ", Fingers: " << list.size() << "\n"); + + } + if(tobj->containsNewTuioBounds()) LINFO("add bnd " << tobj->getTuioBounds()->getSessionID() << "\n"); + if(tobj->containsNewTuioSymbol()) LINFO("add sym " << tobj->getTuioSymbol()->getSessionID() << "\n"); + //std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl; + //std::cout << std::flush; +} + +void TuioEar::tuioUpdate(TuioObject *tobj) { + if (tobj->containsTuioToken()) LINFO("set tok " << tobj->getTuioToken()->getSessionID() << "\n"); + if (tobj->containsTuioPointer()) LINFO("set ptr " << tobj->getTuioPointer()->getSessionID() << "\n"); + if (tobj->containsTuioBounds()) LINFO("set bnd " << tobj->getTuioBounds()->getSessionID() << "\n"); + if (tobj->containsTuioSymbol()) LINFO("set sym " << tobj->getTuioSymbol()->getSessionID() << "\n"); + //std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << " " << tobj->getMotionSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl; + //std::cout << std::flush; +} + +void TuioEar::tuioRemove(TuioObject *tobj) { + if (tobj->containsTuioToken()) LINFO("del tok " << tobj->getTuioToken()->getSessionID() << "\n"); + + if (tobj->containsTuioPointer()) { + it = list.begin(); + for (; it != list.end(); ++it) { + if (it->getSessionID() == tobj->getTuioPointer()->getSessionID()) { + list.erase(it); + LINFO("del ptr " << tobj->getTuioPointer()->getSessionID() << ", Fingers: " << list.size() << "\n"); + break; + } + } + } + + if (tobj->containsTuioBounds()) LINFO("del bnd " << tobj->getTuioBounds()->getSessionID() << "\n"); + if (tobj->containsTuioSymbol()) LINFO("del sym " << tobj->getTuioSymbol()->getSessionID() << "\n"); + //std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ")" << std::endl; + //std::cout << std::flush; +} + +void TuioEar::tuioRefresh(TuioTime frameTime) { + LINFO("refresh " << frameTime.getFrameID() << " "<< frameTime.getTotalMilliseconds() << "\n"); +} + +TuioEar::TuioEar() { + oscReceiver = new UdpReceiver(3333); + //oscReceiver = new TcpReceiver("127.0.0.1",3333); + tuioClient = new TuioClient(oscReceiver); + tuioClient->addTuioListener(this); + tuioClient->connect(); +} diff --git a/modules/touch/touchmodule.cpp b/modules/touch/touchmodule.cpp new file mode 100644 index 0000000000..e7041fcb64 --- /dev/null +++ b/modules/touch/touchmodule.cpp @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + * * + * 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 + +namespace openspace { + +TouchModule::TouchModule() + : OpenSpaceModule("Touch") +{} + +} // namespace openspace diff --git a/modules/touch/touchmodule.h b/modules/touch/touchmodule.h new file mode 100644 index 0000000000..8c2549e58d --- /dev/null +++ b/modules/touch/touchmodule.h @@ -0,0 +1,39 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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. * + * * + * 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 __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__ +#define __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__ + +#include + +namespace openspace { + +class TouchModule : public OpenSpaceModule { +public: + TouchModule(); +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__ diff --git a/openspace.cfg b/openspace.cfg index 5233af0293..c19cbbb29c 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -7,7 +7,7 @@ return { -- Sets the scene that is to be loaded by OpenSpace. A scene file is a description -- of all entities that will be visible during an instance of OpenSpace - Scene = "${SCENE}/default.scene", + Scene = "${SCENE}/globebrowsing.scene", -- Scene = "${SCENE}/globebrowsing.scene", -- Scene = "${SCENE}/rosetta.scene",