mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 19:19:39 -06:00
merge with develop
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -119,3 +119,5 @@ data/spice/OsirisRexKernels
|
||||
data/spice/plu055.bsp
|
||||
data/spice/Rosetta
|
||||
data/spice/sat375.bsp
|
||||
data/scene/lodglobes/saturn/Launcher.config
|
||||
data/scene/lodglobes/mars/test_stats
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
UseAccurateNewHorizonsKernels = true
|
||||
UseAccurateNewHorizonsKernels = false
|
||||
-- TextureResolution = "low"
|
||||
TextureResolution = "med"
|
||||
-- TextureResolution = "high"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
43
modules/touch/CMakeLists.txt
Normal file
43
modules/touch/CMakeLists.txt
Normal file
@@ -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} libTUIO ${CMAKE_CURRENT_SOURCE_DIR}/ext/libTUIO)
|
||||
BIN
modules/touch/ext/.vs/libTUIO2/v14/.suo
Normal file
BIN
modules/touch/ext/.vs/libTUIO2/v14/.suo
Normal file
Binary file not shown.
67
modules/touch/ext/libTUIO/CMakeLists.txt
Normal file
67
modules/touch/ext/libTUIO/CMakeLists.txt
Normal file
@@ -0,0 +1,67 @@
|
||||
#########################################################################################
|
||||
# #
|
||||
# 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(libTUIO)
|
||||
message(STATUS "Generating libTUIO project")
|
||||
|
||||
add_library(libTUIO
|
||||
${PROJECT_SOURCE_DIR}/TUIO/WebSockSender.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/UdpSender.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/UdpReceiver.cpp
|
||||
#${PROJECT_SOURCE_DIR}/TUIO2/TuioToken.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioTime.cpp
|
||||
#${PROJECT_SOURCE_DIR}/TUIO2/TuioSymbol.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioServer.cpp
|
||||
#${PROJECT_SOURCE_DIR}/TUIO2/TuioPointer.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioPoint.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioObject.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioManager.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioDispatcher.cpp
|
||||
#${PROJECT_SOURCE_DIR}/TUIO2/TuioComponent.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioCursor.cpp #
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioContainer.cpp #
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioClient.cpp
|
||||
#${PROJECT_SOURCE_DIR}/TUIO2/TuioBounds.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TuioBlob.cpp #
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TcpSender.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/TcpReceiver.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/OscReceiver.cpp
|
||||
${PROJECT_SOURCE_DIR}/TUIO/OneEuroFilter.cpp #
|
||||
${PROJECT_SOURCE_DIR}/TUIO/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(libTUIO PUBLIC ${PROJECT_SOURCE_DIR})
|
||||
15
modules/touch/ext/libTUIO/TUIO/Doxyfile
Normal file
15
modules/touch/ext/libTUIO/TUIO/Doxyfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Doxyfile 1.5.6
|
||||
# Project related configuration options
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "TUIO 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
|
||||
650
modules/touch/ext/libTUIO/TUIO/FlashSender.cpp
Normal file
650
modules/touch/ext/libTUIO/TUIO/FlashSender.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(WIN32)
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#else
|
||||
#include <utmpx.h>
|
||||
#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; i<len; i++)
|
||||
buffer[pos++] = bytes[i];
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int TFLCSWriteLCAMFEnvelopeHeader(TFLCSLocalConnection_t* connection)
|
||||
{
|
||||
if (NULL == connection)
|
||||
return 0;
|
||||
|
||||
u_int32_t* timestamp = (u_int32_t*)&connection->data[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 <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
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;
|
||||
}
|
||||
215
modules/touch/ext/libTUIO/TUIO/FlashSender.h
Normal file
215
modules/touch/ext/libTUIO/TUIO/FlashSender.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#if !defined(__TFFlashLCSHMEM_H__)
|
||||
#define __TFFlashLCSHMEM_H__ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
typedef DWORD u_int32_t;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <semaphore.h>
|
||||
#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 <martin@tuio.org>
|
||||
|
||||
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 TUIO {
|
||||
|
||||
/**
|
||||
* The FlashSender implements the Flash LocalConnection transport method for OSC
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 */
|
||||
36
modules/touch/ext/libTUIO/TUIO/LibExport.h
Normal file
36
modules/touch/ext/libTUIO/TUIO/LibExport.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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
|
||||
66
modules/touch/ext/libTUIO/TUIO/OneEuroFilter.cpp
Normal file
66
modules/touch/ext/libTUIO/TUIO/OneEuroFilter.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* reacTIVision tangible interaction framework
|
||||
Copyright (C) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
Based on an example by Nicolas Roussel <nicolas.roussel@inria.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "OneEuroFilter.h"
|
||||
#define M_PI 3.14159265392
|
||||
|
||||
using namespace TUIO;
|
||||
|
||||
double LowPassFilter::filter(double value, double alpha) {
|
||||
|
||||
if (alpha<=0.0 || alpha>1.0)
|
||||
throw std::range_error("alpha should be in (0.0., 1.0]");
|
||||
|
||||
double result;
|
||||
if (initialized)
|
||||
result = alpha*value + (1.0-alpha)*lastResult;
|
||||
else {
|
||||
result = value;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
lastRawValue = value;
|
||||
lastResult = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
double OneEuroFilter::alpha(double cutoff) {
|
||||
double te = 1.0 / freq;
|
||||
double tau = 1.0 / (2*M_PI*cutoff);
|
||||
return 1.0 / (1.0 + tau/te);
|
||||
}
|
||||
|
||||
double OneEuroFilter::filter(double value, TimeStamp timestamp) {
|
||||
// update the sampling frequency based on timestamps
|
||||
if (lasttime!=UndefinedTime && timestamp!=UndefinedTime)
|
||||
freq = 1.0 / (timestamp-lasttime);
|
||||
lasttime = timestamp;
|
||||
// estimate the current variation per second
|
||||
double dvalue = x->initialized ? (value - x->lastRawValue)*freq : value;
|
||||
|
||||
double edvalue;
|
||||
try { edvalue = dx->filter(dvalue, alpha(dcutoff));
|
||||
} catch (std::range_error e) { return value; }
|
||||
// use it to update the cutoff frequency
|
||||
double cutoff = mincutoff + beta*fabs(edvalue);
|
||||
// filter the given value
|
||||
return x->filter(value, alpha(cutoff));
|
||||
}
|
||||
90
modules/touch/ext/libTUIO/TUIO/OneEuroFilter.h
Normal file
90
modules/touch/ext/libTUIO/TUIO/OneEuroFilter.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* reacTIVision tangible interaction framework
|
||||
Copyright (C) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
Based on an example by Nicolas Roussel <nicolas.roussel@inria.fr>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef ONEEUROFILTER
|
||||
#define ONEEUROFILTER
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
typedef double TimeStamp; // in seconds
|
||||
static const TimeStamp UndefinedTime = -1.0;
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
class LowPassFilter {
|
||||
|
||||
public:
|
||||
|
||||
bool initialized;
|
||||
double lastRawValue,lastResult;
|
||||
|
||||
LowPassFilter(double initval=0.0) {
|
||||
|
||||
lastRawValue = lastResult = initval;
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
double filter(double value, double alpha);
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
class OneEuroFilter {
|
||||
|
||||
double freq;
|
||||
double mincutoff;
|
||||
double beta;
|
||||
double dcutoff;
|
||||
LowPassFilter *x;
|
||||
LowPassFilter *dx;
|
||||
TimeStamp lasttime;
|
||||
|
||||
double alpha(double cutoff);
|
||||
|
||||
public:
|
||||
|
||||
OneEuroFilter(double f, double mc=1.0, double b=0.0, double dc=1.0) {
|
||||
|
||||
if (f<=0) throw std::range_error("freq should be >0");
|
||||
else freq = f;
|
||||
if (mc<=0) throw std::range_error("mincutoff should be >0");
|
||||
else mincutoff = mc;
|
||||
if (b<=0) throw std::range_error("beta should be >0");
|
||||
else beta = b;
|
||||
if (dc<=0) throw std::range_error("dcutoff should be >0");
|
||||
else dcutoff = dc;
|
||||
|
||||
x = new LowPassFilter(alpha(mincutoff));
|
||||
dx = new LowPassFilter(alpha(dcutoff));
|
||||
lasttime = UndefinedTime;
|
||||
}
|
||||
|
||||
~OneEuroFilter(void) {
|
||||
delete x;
|
||||
delete dx;
|
||||
}
|
||||
|
||||
double filter(double value, TimeStamp timestamp=UndefinedTime);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
60
modules/touch/ext/libTUIO/TUIO/OscReceiver.cpp
Normal file
60
modules/touch/ext/libTUIO/TUIO/OscReceiver.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
using namespace osc;
|
||||
|
||||
void OscReceiver::ProcessMessage( const ReceivedMessage& msg, const IpEndpointName& remoteEndpoint) {
|
||||
for (std::list<TuioClient*>::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);
|
||||
}
|
||||
|
||||
97
modules/touch/ext/libTUIO/TUIO/OscReceiver.h
Normal file
97
modules/touch/ext/libTUIO/TUIO/OscReceiver.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO {
|
||||
|
||||
class TuioClient; // Forward declaration
|
||||
|
||||
/**
|
||||
* The OscReceiver is the base class for the various OSC transport methods such as UDP, TCP ...
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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<TuioClient*> clientList;
|
||||
bool connected;
|
||||
};
|
||||
};
|
||||
#endif /* INCLUDED_OSCRECEIVER_H */
|
||||
90
modules/touch/ext/libTUIO/TUIO/OscSender.h
Normal file
90
modules/touch/ext/libTUIO/TUIO/OscSender.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <iostream>
|
||||
#include <cstring>
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The OscSender class is the base class for the various OSC transport methods such as UDP, TCP ...
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 */
|
||||
|
||||
265
modules/touch/ext/libTUIO/TUIO/TcpReceiver.cpp
Normal file
265
modules/touch/ext/libTUIO/TUIO/TcpReceiver.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
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<TcpReceiver*>(obj);
|
||||
char data_buffer[MAX_TCP_SIZE+4];
|
||||
char data_size[4];
|
||||
int32_t bundle_size;
|
||||
|
||||
#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
|
||||
bundle_size = 0xFF & data_size[3];
|
||||
bundle_size |= (0xFF & data_size[2]) << 8;
|
||||
bundle_size |= (0xFF & data_size[1]) << 16;
|
||||
bundle_size |= (int32_t)(0xFF & data_size[0]) << 24;
|
||||
#else
|
||||
bundle_size = (int32_t)(*data_size);
|
||||
#endif
|
||||
if (bundle_size+4==bytes) {
|
||||
sender->ProcessPacket(&data_buffer[4],(int)bundle_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<TcpReceiver*>(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(int 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, int 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<SOCKET>::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<int>::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;
|
||||
}
|
||||
|
||||
|
||||
102
modules/touch/ext/libTUIO/TUIO/TcpReceiver.h
Normal file
102
modules/touch/ext/libTUIO/TUIO/TcpReceiver.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <winsock.h>
|
||||
#include <io.h>
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TcpReceiver provides the OscReceiver functionality for the TCP transport method
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 (int 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, int 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<int> tcp_client_list;
|
||||
#else
|
||||
SOCKET tcp_socket;
|
||||
std::list<SOCKET> tcp_client_list;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifndef WIN32
|
||||
pthread_t server_thread;
|
||||
#else
|
||||
HANDLE server_thread;
|
||||
DWORD ServerThreadId;
|
||||
#endif
|
||||
|
||||
bool locked;
|
||||
};
|
||||
};
|
||||
#endif /* INCLUDED_TcpReceiver_H */
|
||||
303
modules/touch/ext/libTUIO/TUIO/TcpSender.cpp
Normal file
303
modules/touch/ext/libTUIO/TUIO/TcpSender.cpp
Normal file
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
#ifndef WIN32
|
||||
static void* ClientThreadFunc( void* obj )
|
||||
#else
|
||||
static DWORD WINAPI ClientThreadFunc( LPVOID obj )
|
||||
#endif
|
||||
{
|
||||
TcpSender *sender = static_cast<TcpSender*>(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<TcpSender*>(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<SOCKET>::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<int>::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<SOCKET>::iterator client;
|
||||
#else
|
||||
std::list<int>::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 ) { }
|
||||
126
modules/touch/ext/libTUIO/TUIO/TcpSender.h
Normal file
126
modules/touch/ext/libTUIO/TUIO/TcpSender.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <winsock.h>
|
||||
#include <io.h>
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#define MAX_TCP_SIZE 65536
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* 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<SOCKET> tcp_client_list;
|
||||
#else
|
||||
int tcp_socket;
|
||||
std::list<int> 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 */
|
||||
253
modules/touch/ext/libTUIO/TUIO/TuioBlob.cpp
Normal file
253
modules/touch/ext/libTUIO/TUIO/TuioBlob.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "TuioBlob.h"
|
||||
using namespace TUIO;
|
||||
|
||||
TuioBlob::TuioBlob (TuioTime ttime, long si, int bi, float xp, float yp, float a, float w, float h, float f):TuioContainer(ttime, si, xp, yp) {
|
||||
blob_id = bi;
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
width = w;
|
||||
height = h;
|
||||
area = f;
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
widthFilter = NULL;
|
||||
heightFilter = NULL;
|
||||
sizeThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioBlob::TuioBlob (long si, int bi, float xp, float yp, float a, float w, float h, float f):TuioContainer(si, xp, yp) {
|
||||
blob_id = bi;
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
width = w;
|
||||
height = h;
|
||||
area = f;
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
widthFilter = NULL;
|
||||
heightFilter = NULL;
|
||||
sizeThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioBlob::TuioBlob (TuioBlob *tblb):TuioContainer(tblb) {
|
||||
blob_id = tblb->getBlobID();
|
||||
angle = tblb->getAngle();
|
||||
angle_sum = tblb->getAngleSum();
|
||||
width = tblb->getWidth();
|
||||
height = tblb->getHeight();
|
||||
area = tblb->getArea();
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
widthFilter = NULL;
|
||||
heightFilter = NULL;
|
||||
sizeThreshold = 0.0f;
|
||||
}
|
||||
|
||||
int TuioBlob::getBlobID() const{
|
||||
return blob_id;
|
||||
}
|
||||
|
||||
void TuioBlob::setBlobID(long b_id) {
|
||||
blob_id = b_id;
|
||||
}
|
||||
|
||||
void TuioBlob::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) {
|
||||
TuioContainer::update(ttime,xp,yp,xs,ys,ma);
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
width = w;
|
||||
height = h;
|
||||
area = f;
|
||||
rotation_speed = rs;
|
||||
rotation_accel = ra;
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
void TuioBlob::update (float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra) {
|
||||
TuioContainer::update(xp,yp,xs,ys,ma);
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
width = w;
|
||||
height = h;
|
||||
area = f;
|
||||
rotation_speed = rs;
|
||||
rotation_accel = ra;
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
void TuioBlob::update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f) {
|
||||
TuioPoint lastPoint = path.back();
|
||||
TuioContainer::update(ttime,xp,yp);
|
||||
|
||||
TuioTime diffTime = currentTime - lastPoint.getTuioTime();
|
||||
float dt = diffTime.getTotalMilliseconds()/1000.0f;
|
||||
float last_rotation_speed = rotation_speed;
|
||||
|
||||
float prev_angle = angle_sum;
|
||||
float da = a-angle;
|
||||
if (da > M_PI/2.0f) angle_sum += (da-2*M_PI);
|
||||
else if (da < M_PI/-2.0f) angle_sum += (da+2*M_PI);
|
||||
else angle_sum += da;
|
||||
|
||||
if (angleFilter) angle_sum = angleFilter->filter(angle_sum,dt);
|
||||
if (fabs(angle_sum-prev_angle)<angleThreshold) angle_sum = prev_angle;
|
||||
|
||||
int m = floor(angle_sum/(2*M_PI));
|
||||
angle = angle_sum-(m*(2*M_PI));
|
||||
|
||||
da = (angle-a)/(2*M_PI);
|
||||
if (da > 0.75f) da-=1.0f;
|
||||
else if (da < -0.75f) da+=1.0f;
|
||||
|
||||
if (widthFilter && heightFilter) {
|
||||
w = widthFilter->filter(w,dt);
|
||||
h = heightFilter->filter(h,dt);
|
||||
}
|
||||
|
||||
float dw = fabs(width - w);
|
||||
float dh = fabs(height - h);
|
||||
if ((dw>sizeThreshold) || (dh>sizeThreshold)) {
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
area = f;
|
||||
|
||||
rotation_speed = (float)da/dt;
|
||||
rotation_accel = (rotation_speed - last_rotation_speed)/dt;
|
||||
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
void TuioBlob::stop (TuioTime ttime) {
|
||||
update(ttime,xpos,ypos,angle,width,height,area);
|
||||
}
|
||||
|
||||
void TuioBlob::update (TuioBlob *tblb) {
|
||||
TuioContainer::update(tblb);
|
||||
angle = tblb->getAngle();
|
||||
angle = tblb->getAngleSum();
|
||||
width = tblb->getWidth();
|
||||
height = tblb->getHeight();
|
||||
area = tblb->getArea();
|
||||
rotation_speed = tblb->getRotationSpeed();
|
||||
rotation_accel = tblb->getRotationAccel();
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
float TuioBlob::getWidth() const{
|
||||
return width;
|
||||
}
|
||||
|
||||
float TuioBlob::getHeight() const{
|
||||
return height;
|
||||
}
|
||||
|
||||
int TuioBlob::getScreenWidth(int w) const{
|
||||
return (int)(w*width);
|
||||
}
|
||||
|
||||
int TuioBlob::getScreenHeight(int h) const{
|
||||
return (int)(h*height);
|
||||
}
|
||||
|
||||
float TuioBlob::getArea() const{
|
||||
return area;
|
||||
}
|
||||
|
||||
float TuioBlob::getAngle() const{
|
||||
return angle;
|
||||
}
|
||||
|
||||
float TuioBlob::getAngleSum() const{
|
||||
return angle_sum;
|
||||
}
|
||||
|
||||
float TuioBlob::getAngleDegrees() const{
|
||||
return (float)(angle/M_PI*180);
|
||||
}
|
||||
|
||||
float TuioBlob::getRotationSpeed() const{
|
||||
return rotation_speed;
|
||||
}
|
||||
|
||||
float TuioBlob::getRotationAccel() const{
|
||||
return rotation_accel;
|
||||
}
|
||||
|
||||
bool TuioBlob::isMoving() const{
|
||||
if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING) || (state==TUIO_ROTATING)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void TuioBlob::addAngleThreshold(float thresh) {
|
||||
angleThreshold = thresh;
|
||||
}
|
||||
|
||||
void TuioBlob::removeAngleThreshold() {
|
||||
angleThreshold = 0.0f;
|
||||
}
|
||||
|
||||
void TuioBlob::addAngleFilter(float mcut, float beta) {
|
||||
|
||||
if (angleFilter) delete angleFilter;
|
||||
angleFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
}
|
||||
|
||||
void TuioBlob::removeAngleFilter() {
|
||||
|
||||
if (angleFilter) delete angleFilter;
|
||||
angleFilter = NULL;
|
||||
}
|
||||
|
||||
void TuioBlob::addSizeThreshold(float thresh) {
|
||||
sizeThreshold = thresh;
|
||||
}
|
||||
|
||||
void TuioBlob::removeSizeThreshold() {
|
||||
sizeThreshold = 0.0f;
|
||||
}
|
||||
|
||||
void TuioBlob::addSizeFilter(float mcut, float beta) {
|
||||
|
||||
if (widthFilter) delete widthFilter;
|
||||
widthFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
if (heightFilter) delete heightFilter;
|
||||
heightFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
}
|
||||
|
||||
void TuioBlob::removeSizeFilter() {
|
||||
|
||||
if (widthFilter) delete widthFilter;
|
||||
widthFilter = NULL;
|
||||
if (heightFilter) delete heightFilter;
|
||||
heightFilter = NULL;
|
||||
}
|
||||
|
||||
287
modules/touch/ext/libTUIO/TUIO/TuioBlob.h
Normal file
287
modules/touch/ext/libTUIO/TUIO/TuioBlob.h
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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_TUIOBLOB_H
|
||||
#define INCLUDED_TUIOBLOB_H
|
||||
|
||||
#include "TuioContainer.h"
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TuioBlob class encapsulates /tuio/2Dblb TUIO objects.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioBlob: public TuioContainer {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The individual blob ID number that is assigned to each TuioBlob.
|
||||
*/
|
||||
int blob_id;
|
||||
/**
|
||||
* The rotation angle value.
|
||||
*/
|
||||
float angle;
|
||||
/**
|
||||
* The accumulated angle value.
|
||||
*/
|
||||
float angle_sum;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
float angleThreshold;
|
||||
OneEuroFilter *angleFilter;
|
||||
float sizeThreshold;
|
||||
OneEuroFilter *widthFilter;
|
||||
OneEuroFilter *heightFilter;
|
||||
|
||||
public:
|
||||
using TuioContainer::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 TuioBlob.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param si the Session ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle to assign
|
||||
* @param w the width to assign
|
||||
* @param h the height to assign
|
||||
* @param f the area to assign
|
||||
*/
|
||||
TuioBlob (TuioTime ttime, long si, int bi, float xp, float yp, float a, float w, float h, float f);
|
||||
|
||||
/**
|
||||
* This constructor takes the provided Session ID, X and Y coordinate
|
||||
* width, height and angle, and assigs these values to the newly created TuioBlob.
|
||||
*
|
||||
* @param si the Session ID 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
|
||||
*/
|
||||
TuioBlob (long si, int bi, float xp, float yp, float a, float w, float h, float f);
|
||||
|
||||
/**
|
||||
* This constructor takes the atttibutes of the provided TuioBlob
|
||||
* and assigs these values to the newly created TuioBlob.
|
||||
*
|
||||
* @param tblb the TuioBlob to assign
|
||||
*/
|
||||
TuioBlob (TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
virtual ~TuioBlob() {
|
||||
if (widthFilter) delete widthFilter;
|
||||
if (heightFilter) delete heightFilter;
|
||||
if (angleFilter) delete angleFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the Blob ID of this TuioBlob.
|
||||
* @return the Blob ID of this TuioBlob
|
||||
*/
|
||||
int getBlobID() const;
|
||||
|
||||
/**
|
||||
* Sets the Blob ID of this TuioBlob.
|
||||
* @param b_id the new Blob ID for this TuioBlob
|
||||
*/
|
||||
void setBlobID(long b_id);
|
||||
|
||||
/**
|
||||
* 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 TuioBlob 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 TuioContainer attributes.
|
||||
* The TuioTime time stamp remains unchanged.
|
||||
*
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle 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 TuioBlob 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
|
||||
* TuioBlob with unchanged position and angle.
|
||||
*/
|
||||
void stop (TuioTime ttime);
|
||||
|
||||
/**
|
||||
* Takes the atttibutes of the provided TuioBlob
|
||||
* and assigs these values to this TuioBlob.
|
||||
* The TuioTime time stamp of this TuioContainer remains unchanged.
|
||||
*
|
||||
* @param tblb the TuioContainer to assign
|
||||
*/
|
||||
void update (TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* Returns the width of this TuioBlob.
|
||||
* @return the width of this TuioBlob
|
||||
*/
|
||||
float getWidth() const;
|
||||
|
||||
/**
|
||||
* Returns the height of this TuioBlob.
|
||||
* @return the height of this TuioBlob
|
||||
*/
|
||||
float getHeight() const;
|
||||
|
||||
/**
|
||||
* Returns the width of this TuioBlob.
|
||||
* @return the width of this TuioBlob
|
||||
*/
|
||||
int getScreenWidth(int w) const;
|
||||
|
||||
/**
|
||||
* Returns the height of this TuioBlob.
|
||||
* @return the height of this TuioBlob
|
||||
*/
|
||||
int getScreenHeight(int h) const;
|
||||
|
||||
/**
|
||||
* Returns the area of this TuioBlob.
|
||||
* @return the area of this TuioBlob
|
||||
*/
|
||||
float getArea() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation angle of this TuioBlob.
|
||||
* @return the rotation angle of this TuioBlob
|
||||
*/
|
||||
float getAngle() const;
|
||||
|
||||
/**
|
||||
* Returns the accumulated rotation angle of this TuioBlob.
|
||||
* @return the accumulated rotation angle of this TuioBlob
|
||||
*/
|
||||
float getAngleSum() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation angle in degrees of this TuioBlob.
|
||||
* @return the rotation angle in degrees of this TuioBlob
|
||||
*/
|
||||
float getAngleDegrees() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation speed of this TuioBlob.
|
||||
* @return the rotation speed of this TuioBlob
|
||||
*/
|
||||
float getRotationSpeed() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation acceleration of this TuioBlob.
|
||||
* @return the rotation acceleration of this TuioBlob
|
||||
*/
|
||||
float getRotationAccel() const;
|
||||
|
||||
/**
|
||||
* Returns true of this TuioBlob is moving.
|
||||
* @return true of this TuioBlob is moving
|
||||
*/
|
||||
bool isMoving() const;
|
||||
|
||||
void addAngleThreshold(float thresh);
|
||||
|
||||
void removeAngleThreshold();
|
||||
|
||||
void addAngleFilter(float mcut, float beta);
|
||||
|
||||
void removeAngleFilter();
|
||||
|
||||
void addSizeThreshold(float thresh);
|
||||
|
||||
void removeSizeThreshold();
|
||||
|
||||
void addSizeFilter(float mcut, float beta);
|
||||
|
||||
void removeSizeFilter();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
849
modules/touch/ext/libTUIO/TUIO/TuioClient.cpp
Normal file
849
modules/touch/ext/libTUIO/TUIO/TuioClient.cpp
Normal file
@@ -0,0 +1,849 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
using namespace osc;
|
||||
|
||||
|
||||
TuioClient::TuioClient()
|
||||
: currentFrame (-1)
|
||||
, source_id (0)
|
||||
, source_name (NULL)
|
||||
, source_addr (NULL)
|
||||
, local_receiver(true)
|
||||
{
|
||||
receiver = new UdpReceiver();
|
||||
initialize();
|
||||
}
|
||||
|
||||
TuioClient::TuioClient(int port)
|
||||
: currentFrame (-1)
|
||||
, source_id (0)
|
||||
, source_name (NULL)
|
||||
, source_addr (NULL)
|
||||
, local_receiver(true)
|
||||
{
|
||||
receiver = new UdpReceiver(port);
|
||||
initialize();
|
||||
}
|
||||
|
||||
TuioClient::TuioClient(OscReceiver *osc)
|
||||
: currentFrame (-1)
|
||||
, source_id (0)
|
||||
, source_name (NULL)
|
||||
, source_addr (NULL)
|
||||
, receiver (osc)
|
||||
, local_receiver(false)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
void TuioClient::initialize() {
|
||||
receiver->addTuioClient(this);
|
||||
maxCursorID[source_id] = -1;
|
||||
maxBlobID[source_id] = -1;
|
||||
}
|
||||
|
||||
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(), "/tuio/2Dobj" ) == 0 ){
|
||||
|
||||
const char* cmd;
|
||||
args >> cmd;
|
||||
|
||||
if (strcmp(cmd,"source")==0) {
|
||||
const char* src;
|
||||
args >> src;
|
||||
|
||||
source_name = strtok((char*)src, "@");
|
||||
char *addr = strtok(NULL, "@");
|
||||
|
||||
if (addr!=NULL) source_addr = addr;
|
||||
else source_addr = (char*)"localhost";
|
||||
|
||||
// check if we know that source
|
||||
std::string source_str(src);
|
||||
std::map<std::string,int>::iterator iter = sourceList.find(source_str);
|
||||
|
||||
// add a new source
|
||||
if (iter==sourceList.end()) {
|
||||
source_id = sourceList.size();
|
||||
sourceList[source_str] = source_id;
|
||||
} else {
|
||||
// use the found source_id
|
||||
source_id = sourceList[source_str];
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd,"set")==0) {
|
||||
int32 s_id, c_id;
|
||||
float xpos, ypos, angle, xspeed, yspeed, rspeed, maccel, raccel;
|
||||
args >> s_id >> c_id >> xpos >> ypos >> angle >> xspeed >> yspeed >> rspeed >> maccel >> raccel;
|
||||
|
||||
lockObjectList();
|
||||
std::list<TuioObject*>::iterator tobj;
|
||||
for (tobj=objectList.begin(); tobj!= objectList.end(); tobj++)
|
||||
if((*tobj)->getSessionID()==(long)s_id) break;
|
||||
|
||||
if (tobj == objectList.end()) {
|
||||
|
||||
TuioObject *addObject = new TuioObject((long)s_id,(int)c_id,xpos,ypos,angle);
|
||||
frameObjects.push_back(addObject);
|
||||
|
||||
} else if ( ((*tobj)->getX()!=xpos) || ((*tobj)->getY()!=ypos) || ((*tobj)->getAngle()!=angle) || ((*tobj)->getXSpeed()!=xspeed) || ((*tobj)->getYSpeed()!=yspeed) || ((*tobj)->getRotationSpeed()!=rspeed) || ((*tobj)->getMotionAccel()!=maccel) || ((*tobj)->getRotationAccel()!=raccel) ) {
|
||||
|
||||
TuioObject *updateObject = new TuioObject((long)s_id,(*tobj)->getSymbolID(),xpos,ypos,angle);
|
||||
updateObject->update(xpos,ypos,angle,xspeed,yspeed,rspeed,maccel,raccel);
|
||||
frameObjects.push_back(updateObject);
|
||||
|
||||
}
|
||||
unlockObjectList();
|
||||
|
||||
} else if (strcmp(cmd,"alive")==0) {
|
||||
|
||||
int32 s_id;
|
||||
aliveObjectList.clear();
|
||||
while(!args.Eos()) {
|
||||
args >> s_id;
|
||||
aliveObjectList.push_back((long)s_id);
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd,"fseq")==0) {
|
||||
|
||||
int32 fseq;
|
||||
args >> fseq;
|
||||
bool lateFrame = false;
|
||||
if (fseq>0) {
|
||||
if (fseq>currentFrame) currentTime = TuioTime::getSessionTime();
|
||||
if ((fseq>=currentFrame) || ((currentFrame-fseq)>100)) currentFrame = fseq;
|
||||
else lateFrame = true;
|
||||
} else if ((TuioTime::getSessionTime().getTotalMilliseconds()-currentTime.getTotalMilliseconds())>100) {
|
||||
currentTime = TuioTime::getSessionTime();
|
||||
}
|
||||
|
||||
if (!lateFrame) {
|
||||
|
||||
lockObjectList();
|
||||
//find the removed objects first
|
||||
for (std::list<TuioObject*>::iterator tobj=objectList.begin(); tobj != objectList.end(); tobj++) {
|
||||
if ((*tobj)->getTuioSourceID()==source_id) {
|
||||
std::list<long>::iterator iter = find(aliveObjectList.begin(), aliveObjectList.end(), (*tobj)->getSessionID());
|
||||
if (iter == aliveObjectList.end()) {
|
||||
(*tobj)->remove(currentTime);
|
||||
frameObjects.push_back(*tobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
unlockObjectList();
|
||||
|
||||
for (std::list<TuioObject*>::iterator iter=frameObjects.begin(); iter != frameObjects.end(); iter++) {
|
||||
TuioObject *tobj = (*iter);
|
||||
|
||||
TuioObject *frameObject = NULL;
|
||||
switch (tobj->getTuioState()) {
|
||||
case TUIO_REMOVED:
|
||||
|
||||
frameObject = tobj;
|
||||
frameObject->remove(currentTime);
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioObject(frameObject);
|
||||
|
||||
lockObjectList();
|
||||
for (std::list<TuioObject*>::iterator delobj=objectList.begin(); delobj!=objectList.end(); delobj++) {
|
||||
if((*delobj)->getSessionID()==frameObject->getSessionID()) {
|
||||
objectList.erase(delobj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlockObjectList();
|
||||
break;
|
||||
case TUIO_ADDED:
|
||||
|
||||
lockObjectList();
|
||||
frameObject = new TuioObject(currentTime,tobj->getSessionID(),tobj->getSymbolID(),tobj->getX(),tobj->getY(),tobj->getAngle());
|
||||
if (source_name) frameObject->setTuioSource(source_id,source_name,source_addr);
|
||||
objectList.push_back(frameObject);
|
||||
unlockObjectList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioObject(frameObject);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
lockObjectList();
|
||||
std::list<TuioObject*>::iterator iter;
|
||||
for (iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==source_id) && ((*iter)->getSessionID()==tobj->getSessionID())) {
|
||||
frameObject = (*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter==objectList.end()) {
|
||||
unlockObjectList();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (tobj->getX()!=frameObject->getX() && tobj->getXSpeed()==0) || (tobj->getY()!=frameObject->getY() && tobj->getYSpeed()==0) )
|
||||
frameObject->update(currentTime,tobj->getX(),tobj->getY(),tobj->getAngle());
|
||||
else
|
||||
frameObject->update(currentTime,tobj->getX(),tobj->getY(),tobj->getAngle(),tobj->getXSpeed(),tobj->getYSpeed(),tobj->getRotationSpeed(),tobj->getMotionAccel(),tobj->getRotationAccel());
|
||||
|
||||
unlockObjectList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioObject(frameObject);
|
||||
}
|
||||
delete tobj;
|
||||
}
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->refresh(currentTime);
|
||||
|
||||
} else {
|
||||
for (std::list<TuioObject*>::iterator iter=frameObjects.begin(); iter != frameObjects.end(); iter++) {
|
||||
TuioObject *tobj = (*iter);
|
||||
delete tobj;
|
||||
}
|
||||
}
|
||||
|
||||
frameObjects.clear();
|
||||
}
|
||||
} else if( strcmp( msg.AddressPattern(), "/tuio/2Dcur" ) == 0 ) {
|
||||
const char* cmd;
|
||||
args >> cmd;
|
||||
|
||||
if (strcmp(cmd,"source")==0) {
|
||||
const char* src;
|
||||
args >> src;
|
||||
|
||||
source_name = strtok((char*)src, "@");
|
||||
char *addr = strtok(NULL, "@");
|
||||
|
||||
if (addr!=NULL) source_addr = addr;
|
||||
else source_addr = (char*)"localhost";
|
||||
|
||||
// check if we know that source
|
||||
std::string source_str(src);
|
||||
std::map<std::string,int>::iterator iter = sourceList.find(source_str);
|
||||
|
||||
// add a new source
|
||||
if (iter==sourceList.end()) {
|
||||
source_id = sourceList.size();
|
||||
sourceList[source_str] = source_id;
|
||||
maxCursorID[source_id] = -1;
|
||||
} else {
|
||||
// use the found source_id
|
||||
source_id = sourceList[source_str];
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd,"set")==0) {
|
||||
|
||||
int32 s_id;
|
||||
float xpos, ypos, xspeed, yspeed, maccel;
|
||||
args >> s_id >> xpos >> ypos >> xspeed >> yspeed >> maccel;
|
||||
|
||||
lockCursorList();
|
||||
std::list<TuioCursor*>::iterator tcur;
|
||||
for (tcur=cursorList.begin(); tcur!= cursorList.end(); tcur++)
|
||||
if (((*tcur)->getSessionID()==(long)s_id) && ((*tcur)->getTuioSourceID()==source_id)) break;
|
||||
|
||||
if (tcur==cursorList.end()) {
|
||||
|
||||
TuioCursor *addCursor = new TuioCursor((long)s_id,-1,xpos,ypos);
|
||||
frameCursors.push_back(addCursor);
|
||||
|
||||
} else if ( ((*tcur)->getX()!=xpos) || ((*tcur)->getY()!=ypos) || ((*tcur)->getXSpeed()!=xspeed) || ((*tcur)->getYSpeed()!=yspeed) || ((*tcur)->getMotionAccel()!=maccel) ) {
|
||||
|
||||
TuioCursor *updateCursor = new TuioCursor((long)s_id,(*tcur)->getCursorID(),xpos,ypos);
|
||||
updateCursor->update(xpos,ypos,xspeed,yspeed,maccel);
|
||||
frameCursors.push_back(updateCursor);
|
||||
|
||||
}
|
||||
unlockCursorList();
|
||||
|
||||
} else if (strcmp(cmd,"alive")==0) {
|
||||
|
||||
int32 s_id;
|
||||
aliveCursorList.clear();
|
||||
while(!args.Eos()) {
|
||||
args >> s_id;
|
||||
aliveCursorList.push_back((long)s_id);
|
||||
}
|
||||
|
||||
} else if( strcmp( cmd, "fseq" ) == 0 ) {
|
||||
int32 fseq;
|
||||
args >> fseq;
|
||||
bool lateFrame = false;
|
||||
if (fseq>0) {
|
||||
if (fseq>currentFrame) currentTime = TuioTime::getSessionTime();
|
||||
if ((fseq>=currentFrame) || ((currentFrame-fseq)>100)) currentFrame = fseq;
|
||||
else lateFrame = true;
|
||||
} else if ((TuioTime::getSessionTime().getTotalMilliseconds()-currentTime.getTotalMilliseconds())>100) {
|
||||
currentTime = TuioTime::getSessionTime();
|
||||
}
|
||||
|
||||
if (!lateFrame) {
|
||||
|
||||
lockCursorList();
|
||||
// find the removed cursors first
|
||||
for (std::list<TuioCursor*>::iterator tcur=cursorList.begin(); tcur != cursorList.end(); tcur++) {
|
||||
if ((*tcur)->getTuioSourceID()==source_id) {
|
||||
std::list<long>::iterator iter = find(aliveCursorList.begin(), aliveCursorList.end(), (*tcur)->getSessionID());
|
||||
|
||||
if (iter == aliveCursorList.end()) {
|
||||
(*tcur)->remove(currentTime);
|
||||
frameCursors.push_back(*tcur);
|
||||
}
|
||||
}
|
||||
}
|
||||
unlockCursorList();
|
||||
|
||||
for (std::list<TuioCursor*>::iterator iter=frameCursors.begin(); iter != frameCursors.end(); iter++) {
|
||||
TuioCursor *tcur = (*iter);
|
||||
|
||||
int c_id = 0;
|
||||
int free_size = 0;
|
||||
TuioCursor *frameCursor = NULL;
|
||||
switch (tcur->getTuioState()) {
|
||||
case TUIO_REMOVED:
|
||||
|
||||
frameCursor = tcur;
|
||||
frameCursor->remove(currentTime);
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioCursor(frameCursor);
|
||||
|
||||
lockCursorList();
|
||||
for (std::list<TuioCursor*>::iterator delcur=cursorList.begin(); delcur!=cursorList.end(); delcur++) {
|
||||
if(((*delcur)->getTuioSourceID()==source_id) && ((*delcur)->getSessionID()==frameCursor->getSessionID())) {
|
||||
cursorList.erase(delcur);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameCursor->getCursorID()==maxCursorID[source_id]) {
|
||||
maxCursorID[source_id] = -1;
|
||||
delete frameCursor;
|
||||
|
||||
if (cursorList.size()>0) {
|
||||
std::list<TuioCursor*>::iterator clist;
|
||||
for (clist=cursorList.begin(); clist != cursorList.end(); clist++) {
|
||||
if ((*clist)->getTuioSourceID()==source_id) {
|
||||
c_id = (*clist)->getCursorID();
|
||||
if (c_id>maxCursorID[source_id]) maxCursorID[source_id]=c_id;
|
||||
}
|
||||
}
|
||||
|
||||
freeCursorBuffer.clear();
|
||||
for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
|
||||
TuioCursor *freeCursor = (*flist);
|
||||
if (freeCursor->getTuioSourceID()==source_id) {
|
||||
if (freeCursor->getCursorID()>maxCursorID[source_id]) delete freeCursor;
|
||||
else freeCursorBuffer.push_back(freeCursor);
|
||||
} else freeCursorBuffer.push_back(freeCursor);
|
||||
}
|
||||
freeCursorList = freeCursorBuffer;
|
||||
|
||||
} else {
|
||||
freeCursorBuffer.clear();
|
||||
for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
|
||||
TuioCursor *freeCursor = (*flist);
|
||||
if (freeCursor->getTuioSourceID()==source_id) delete freeCursor;
|
||||
else freeCursorBuffer.push_back(freeCursor);
|
||||
}
|
||||
freeCursorList = freeCursorBuffer;
|
||||
|
||||
}
|
||||
} else if (frameCursor->getCursorID()<maxCursorID[source_id]) {
|
||||
freeCursorList.push_back(frameCursor);
|
||||
}
|
||||
|
||||
unlockCursorList();
|
||||
break;
|
||||
case TUIO_ADDED:
|
||||
|
||||
lockCursorList();
|
||||
for(std::list<TuioCursor*>::iterator iter = cursorList.begin();iter!= cursorList.end(); iter++)
|
||||
if ((*iter)->getTuioSourceID()==source_id) c_id++;
|
||||
|
||||
for(std::list<TuioCursor*>::iterator iter = freeCursorList.begin();iter!= freeCursorList.end(); iter++)
|
||||
if ((*iter)->getTuioSourceID()==source_id) free_size++;
|
||||
|
||||
if ((free_size<=maxCursorID[source_id]) && (free_size>0)) {
|
||||
std::list<TuioCursor*>::iterator closestCursor = freeCursorList.begin();
|
||||
|
||||
for(std::list<TuioCursor*>::iterator iter = freeCursorList.begin();iter!= freeCursorList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==source_id) && ((*iter)->getDistance(tcur)<(*closestCursor)->getDistance(tcur))) closestCursor = iter;
|
||||
}
|
||||
|
||||
if (closestCursor!=freeCursorList.end()) {
|
||||
TuioCursor *freeCursor = (*closestCursor);
|
||||
c_id = freeCursor->getCursorID();
|
||||
freeCursorList.erase(closestCursor);
|
||||
delete freeCursor;
|
||||
}
|
||||
} else maxCursorID[source_id] = c_id;
|
||||
|
||||
frameCursor = new TuioCursor(currentTime,tcur->getSessionID(),c_id,tcur->getX(),tcur->getY());
|
||||
if (source_name) frameCursor->setTuioSource(source_id,source_name,source_addr);
|
||||
cursorList.push_back(frameCursor);
|
||||
|
||||
delete tcur;
|
||||
unlockCursorList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioCursor(frameCursor);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
lockCursorList();
|
||||
std::list<TuioCursor*>::iterator iter;
|
||||
for (iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==source_id) && ((*iter)->getSessionID()==tcur->getSessionID())) {
|
||||
frameCursor = (*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter==cursorList.end()) {
|
||||
unlockCursorList();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (tcur->getX()!=frameCursor->getX() && tcur->getXSpeed()==0) || (tcur->getY()!=frameCursor->getY() && tcur->getYSpeed()==0) )
|
||||
frameCursor->update(currentTime,tcur->getX(),tcur->getY());
|
||||
else
|
||||
frameCursor->update(currentTime,tcur->getX(),tcur->getY(),tcur->getXSpeed(),tcur->getYSpeed(),tcur->getMotionAccel());
|
||||
|
||||
delete tcur;
|
||||
unlockCursorList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioCursor(frameCursor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->refresh(currentTime);
|
||||
|
||||
} else {
|
||||
for (std::list<TuioCursor*>::iterator iter=frameCursors.begin(); iter != frameCursors.end(); iter++) {
|
||||
TuioCursor *tcur = (*iter);
|
||||
delete tcur;
|
||||
}
|
||||
}
|
||||
|
||||
frameCursors.clear();
|
||||
}
|
||||
} else if( strcmp( msg.AddressPattern(), "/tuio/2Dblb" ) == 0 ){
|
||||
const char* cmd;
|
||||
args >> cmd;
|
||||
|
||||
if (strcmp(cmd,"source")==0) {
|
||||
const char* src;
|
||||
args >> src;
|
||||
|
||||
source_name = strtok((char*)src, "@");
|
||||
char *addr = strtok(NULL, "@");
|
||||
|
||||
if (addr!=NULL) source_addr = addr;
|
||||
else source_addr = (char*)"localhost";
|
||||
|
||||
// check if we know that source
|
||||
std::string source_str(src);
|
||||
std::map<std::string,int>::iterator iter = sourceList.find(source_str);
|
||||
|
||||
// add a new source
|
||||
if (iter==sourceList.end()) {
|
||||
source_id = sourceList.size();
|
||||
sourceList[source_str] = source_id;
|
||||
maxBlobID[source_id] = -1;
|
||||
} else {
|
||||
// use the found source_id
|
||||
source_id = sourceList[source_str];
|
||||
}
|
||||
|
||||
} else if (strcmp(cmd,"set")==0) {
|
||||
|
||||
int32 s_id;
|
||||
float xpos, ypos, angle, width, height, area, xspeed, yspeed, rspeed, maccel, raccel;
|
||||
args >> s_id >> xpos >> ypos >> angle >> width >> height >> area >> xspeed >> yspeed >> rspeed >> maccel >> raccel;
|
||||
|
||||
lockBlobList();
|
||||
std::list<TuioBlob*>::iterator tblb;
|
||||
for (tblb=blobList.begin(); tblb!= blobList.end(); tblb++)
|
||||
if((*tblb)->getSessionID()==(long)s_id) break;
|
||||
|
||||
if (tblb==blobList.end()) {
|
||||
|
||||
TuioBlob *addBlob = new TuioBlob((long)s_id,-1,xpos,ypos,angle,width,height,area);
|
||||
frameBlobs.push_back(addBlob);
|
||||
|
||||
} else if ( ((*tblb)->getX()!=xpos) || ((*tblb)->getY()!=ypos) || ((*tblb)->getAngle()!=angle) || ((*tblb)->getWidth()!=width) || ((*tblb)->getHeight()!=height) || ((*tblb)->getArea()!=area) || ((*tblb)->getXSpeed()!=xspeed) || ((*tblb)->getYSpeed()!=yspeed) || ((*tblb)->getMotionAccel()!=maccel) ) {
|
||||
|
||||
TuioBlob *updateBlob = new TuioBlob((long)s_id,(*tblb)->getBlobID(),xpos,ypos,angle,width,height,area);
|
||||
updateBlob->update(xpos,ypos,angle,width,height,area,xspeed,yspeed,rspeed,maccel,raccel);
|
||||
frameBlobs.push_back(updateBlob);
|
||||
}
|
||||
unlockBlobList();
|
||||
|
||||
} else if (strcmp(cmd,"alive")==0) {
|
||||
|
||||
int32 s_id;
|
||||
aliveBlobList.clear();
|
||||
while(!args.Eos()) {
|
||||
args >> s_id;
|
||||
aliveBlobList.push_back((long)s_id);
|
||||
}
|
||||
|
||||
} else if( strcmp( cmd, "fseq" ) == 0 ) {
|
||||
|
||||
int32 fseq;
|
||||
args >> fseq;
|
||||
bool lateFrame = false;
|
||||
if (fseq>0) {
|
||||
if (fseq>currentFrame) currentTime = TuioTime::getSessionTime();
|
||||
if ((fseq>=currentFrame) || ((currentFrame-fseq)>100)) currentFrame = fseq;
|
||||
else lateFrame = true;
|
||||
} else if ((TuioTime::getSessionTime().getTotalMilliseconds()-currentTime.getTotalMilliseconds())>100) {
|
||||
currentTime = TuioTime::getSessionTime();
|
||||
}
|
||||
|
||||
if (!lateFrame) {
|
||||
|
||||
lockBlobList();
|
||||
// find the removed blobs first
|
||||
for (std::list<TuioBlob*>::iterator tblb=blobList.begin(); tblb != blobList.end(); tblb++) {
|
||||
if ((*tblb)->getTuioSourceID()==source_id) {
|
||||
std::list<long>::iterator iter = find(aliveBlobList.begin(), aliveBlobList.end(), (*tblb)->getSessionID());
|
||||
|
||||
if (iter == aliveBlobList.end()) {
|
||||
(*tblb)->remove(currentTime);
|
||||
frameBlobs.push_back(*tblb);
|
||||
}
|
||||
}
|
||||
}
|
||||
unlockBlobList();
|
||||
|
||||
for (std::list<TuioBlob*>::iterator iter=frameBlobs.begin(); iter != frameBlobs.end(); iter++) {
|
||||
TuioBlob *tblb = (*iter);
|
||||
|
||||
int b_id = 0;
|
||||
int free_size = 0;
|
||||
TuioBlob *frameBlob = NULL;
|
||||
switch (tblb->getTuioState()) {
|
||||
case TUIO_REMOVED:
|
||||
frameBlob = tblb;
|
||||
frameBlob->remove(currentTime);
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioBlob(frameBlob);
|
||||
|
||||
lockBlobList();
|
||||
for (std::list<TuioBlob*>::iterator delblb=blobList.begin(); delblb!=blobList.end(); delblb++) {
|
||||
if(((*delblb)->getTuioSourceID()==source_id) && ((*delblb)->getSessionID()==frameBlob->getSessionID())) {
|
||||
blobList.erase(delblb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameBlob->getBlobID()==maxBlobID[source_id]) {
|
||||
maxBlobID[source_id] = -1;
|
||||
delete frameBlob;
|
||||
|
||||
if (blobList.size()>0) {
|
||||
std::list<TuioBlob*>::iterator clist;
|
||||
for (clist=blobList.begin(); clist != blobList.end(); clist++) {
|
||||
if ((*clist)->getTuioSourceID()==source_id) {
|
||||
b_id = (*clist)->getBlobID();
|
||||
if (b_id>maxBlobID[source_id]) maxBlobID[source_id]=b_id;
|
||||
}
|
||||
}
|
||||
|
||||
freeBlobBuffer.clear();
|
||||
for (std::list<TuioBlob*>::iterator flist=freeBlobList.begin(); flist != freeBlobList.end(); flist++) {
|
||||
TuioBlob *freeBlob = (*flist);
|
||||
if (freeBlob->getTuioSourceID()==source_id) {
|
||||
if (freeBlob->getBlobID()>maxBlobID[source_id]) delete freeBlob;
|
||||
else freeBlobBuffer.push_back(freeBlob);
|
||||
} else freeBlobBuffer.push_back(freeBlob);
|
||||
}
|
||||
freeBlobList = freeBlobBuffer;
|
||||
|
||||
} else {
|
||||
freeBlobBuffer.clear();
|
||||
for (std::list<TuioBlob*>::iterator flist=freeBlobList.begin(); flist != freeBlobList.end(); flist++) {
|
||||
TuioBlob *freeBlob = (*flist);
|
||||
if (freeBlob->getTuioSourceID()==source_id) delete freeBlob;
|
||||
else freeBlobBuffer.push_back(freeBlob);
|
||||
}
|
||||
freeBlobList = freeBlobBuffer;
|
||||
|
||||
}
|
||||
} else if (frameBlob->getBlobID()<maxBlobID[source_id]) {
|
||||
freeBlobList.push_back(frameBlob);
|
||||
}
|
||||
|
||||
unlockBlobList();
|
||||
break;
|
||||
case TUIO_ADDED:
|
||||
|
||||
lockBlobList();
|
||||
for(std::list<TuioBlob*>::iterator iter = blobList.begin();iter!= blobList.end(); iter++)
|
||||
if ((*iter)->getTuioSourceID()==source_id) b_id++;
|
||||
|
||||
for(std::list<TuioBlob*>::iterator iter = freeBlobList.begin();iter!= freeBlobList.end(); iter++)
|
||||
if ((*iter)->getTuioSourceID()==source_id) free_size++;
|
||||
|
||||
if ((free_size<=maxBlobID[source_id]) && (free_size>0)) {
|
||||
std::list<TuioBlob*>::iterator closestBlob = freeBlobList.begin();
|
||||
|
||||
for(std::list<TuioBlob*>::iterator iter = freeBlobList.begin();iter!= freeBlobList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==source_id) && ((*iter)->getDistance(tblb)<(*closestBlob)->getDistance(tblb))) closestBlob = iter;
|
||||
}
|
||||
|
||||
if (closestBlob!=freeBlobList.end()) {
|
||||
TuioBlob *freeBlob = (*closestBlob);
|
||||
b_id = freeBlob->getBlobID();
|
||||
freeBlobList.erase(closestBlob);
|
||||
delete freeBlob;
|
||||
}
|
||||
} else maxBlobID[source_id] = b_id;
|
||||
|
||||
frameBlob = new TuioBlob(currentTime,tblb->getSessionID(),b_id,tblb->getX(),tblb->getY(),tblb->getAngle(),tblb->getWidth(),tblb->getHeight(),tblb->getArea());
|
||||
if (source_name) frameBlob->setTuioSource(source_id,source_name,source_addr);
|
||||
blobList.push_back(frameBlob);
|
||||
|
||||
delete tblb;
|
||||
unlockBlobList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioBlob(frameBlob);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
lockBlobList();
|
||||
std::list<TuioBlob*>::iterator iter;
|
||||
for (iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==source_id) && ((*iter)->getSessionID()==tblb->getSessionID())) {
|
||||
frameBlob = (*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter==blobList.end()) {
|
||||
unlockBlobList();
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (tblb->getX()!=frameBlob->getX() && tblb->getXSpeed()==0) || (tblb->getY()!=frameBlob->getY() && tblb->getYSpeed()==0) || (tblb->getAngle()!=frameBlob->getAngle() && tblb->getRotationSpeed()==0) )
|
||||
frameBlob->update(currentTime,tblb->getX(),tblb->getY(),tblb->getAngle(),tblb->getWidth(),tblb->getHeight(),tblb->getArea());
|
||||
else
|
||||
frameBlob->update(currentTime,tblb->getX(),tblb->getY(),tblb->getAngle(),tblb->getWidth(),tblb->getHeight(),tblb->getArea(),tblb->getXSpeed(),tblb->getYSpeed(),tblb->getRotationSpeed(),tblb->getMotionAccel(),tblb->getRotationAccel());
|
||||
|
||||
delete tblb;
|
||||
unlockBlobList();
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioBlob(frameBlob);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->refresh(currentTime);
|
||||
|
||||
} else {
|
||||
for (std::list<TuioBlob*>::iterator iter=frameBlobs.begin(); iter != frameBlobs.end(); iter++) {
|
||||
TuioBlob *tblb = (*iter);
|
||||
delete tblb;
|
||||
}
|
||||
}
|
||||
|
||||
frameBlobs.clear();
|
||||
}
|
||||
}
|
||||
} catch( Exception& e ){
|
||||
std::cerr << "error parsing TUIO message: "<< msg.AddressPattern() << " - " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool TuioClient::isConnected() {
|
||||
return receiver->isConnected();
|
||||
}
|
||||
|
||||
void TuioClient::connect(bool lock) {
|
||||
|
||||
TuioTime::initSession();
|
||||
currentTime.reset();
|
||||
|
||||
receiver->connect(lock);
|
||||
|
||||
unlockCursorList();
|
||||
unlockObjectList();
|
||||
unlockBlobList();
|
||||
}
|
||||
|
||||
void TuioClient::disconnect() {
|
||||
|
||||
receiver->disconnect();
|
||||
|
||||
aliveObjectList.clear();
|
||||
aliveCursorList.clear();
|
||||
aliveBlobList.clear();
|
||||
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++)
|
||||
delete (*iter);
|
||||
objectList.clear();
|
||||
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++)
|
||||
delete (*iter);
|
||||
cursorList.clear();
|
||||
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++)
|
||||
delete (*iter);
|
||||
blobList.clear();
|
||||
|
||||
for (std::list<TuioCursor*>::iterator iter=freeCursorList.begin(); iter != freeCursorList.end(); iter++)
|
||||
delete(*iter);
|
||||
freeCursorList.clear();
|
||||
|
||||
for (std::list<TuioBlob*>::iterator iter=freeBlobList.begin(); iter != freeBlobList.end(); iter++)
|
||||
delete(*iter);
|
||||
freeBlobList.clear();
|
||||
}
|
||||
|
||||
|
||||
TuioObject* TuioClient::getTuioObject(int src_id, long s_id) {
|
||||
lockObjectList();
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==src_id) && ((*iter)->getSessionID()==s_id)) {
|
||||
unlockObjectList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockObjectList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TuioCursor* TuioClient::getTuioCursor(int src_id, long s_id) {
|
||||
lockCursorList();
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==src_id) && ((*iter)->getSessionID()==s_id)) {
|
||||
unlockCursorList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockCursorList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TuioBlob* TuioClient::getTuioBlob(int src_id, long s_id) {
|
||||
lockBlobList();
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
if (((*iter)->getTuioSourceID()==src_id) && ((*iter)->getSessionID()==s_id)) {
|
||||
unlockBlobList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockBlobList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
std::list<TuioObject*> TuioClient::getTuioObjects(int source_id) {
|
||||
lockObjectList();
|
||||
std::list<TuioObject*> listBuffer;
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
TuioObject *tobj = (*iter);
|
||||
if (tobj->getTuioSourceID()==source_id) listBuffer.push_back(tobj);
|
||||
}
|
||||
unlockObjectList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioCursor*> TuioClient::getTuioCursors(int source_id) {
|
||||
lockCursorList();
|
||||
std::list<TuioCursor*> listBuffer;
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
TuioCursor *tcur = (*iter);
|
||||
if (tcur->getTuioSourceID()==source_id) listBuffer.push_back(tcur);
|
||||
}
|
||||
unlockCursorList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioBlob*> TuioClient::getTuioBlobs(int source_id) {
|
||||
lockBlobList();
|
||||
std::list<TuioBlob*> listBuffer;
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
TuioBlob *tblb = (*iter);
|
||||
if (tblb->getTuioSourceID()==source_id) listBuffer.push_back(tblb);
|
||||
}
|
||||
unlockBlobList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
|
||||
std::list<TuioObject> TuioClient::copyTuioObjects(int source_id) {
|
||||
lockObjectList();
|
||||
std::list<TuioObject> listBuffer;
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
TuioObject *tobj = (*iter);
|
||||
if (tobj->getTuioSourceID()==source_id) listBuffer.push_back(*tobj);
|
||||
}
|
||||
unlockObjectList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioCursor> TuioClient::copyTuioCursors(int source_id) {
|
||||
lockCursorList();
|
||||
std::list<TuioCursor> listBuffer;
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
TuioCursor *tcur = (*iter);
|
||||
if (tcur->getTuioSourceID()==source_id) listBuffer.push_back(*tcur);
|
||||
}
|
||||
unlockCursorList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioBlob> TuioClient::copyTuioBlobs(int source_id) {
|
||||
lockBlobList();
|
||||
std::list<TuioBlob> listBuffer;
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
TuioBlob *tblb = (*iter);
|
||||
if (tblb->getTuioSourceID()==source_id) listBuffer.push_back(*tblb);
|
||||
}
|
||||
unlockBlobList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
301
modules/touch/ext/libTUIO/TUIO/TuioClient.h
Normal file
301
modules/touch/ext/libTUIO/TUIO/TuioClient.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
class OscReceiver; // Forward declaration
|
||||
|
||||
/**
|
||||
* <p>The TuioClient class is the central TUIO protocol decoder component. It provides a simple callback infrastructure using the {@link TuioListener} interface.
|
||||
* In order to receive and decode TUIO messages an instance of TuioClient needs to be created. The TuioClient instance then generates TUIO events
|
||||
* which are broadcasted to all registered classes that implement the {@link TuioListener} interface.</p>
|
||||
* <p><code>
|
||||
* TuioClient *client = new TuioClient();<br/>
|
||||
* client->addTuioListener(myTuioListener);<br/>
|
||||
* client->connect();<br/>
|
||||
* </code></p>
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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(int 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 a List of all currently active TuioObjects
|
||||
*
|
||||
* @return a List of TuioObjects
|
||||
*/
|
||||
std::list<TuioObject*> getTuioObjects() {
|
||||
return TuioDispatcher::getTuioObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioObjects
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List of TuioObjects
|
||||
*/
|
||||
std::list<TuioObject*> getTuioObjects(int source_id);
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioObjects
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List with a copy of TuioObjects
|
||||
*/
|
||||
std::list<TuioObject> copyTuioObjects(int source_id);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioObjects
|
||||
*
|
||||
* @return a List with a copy of TuioObjects
|
||||
*/
|
||||
std::list<TuioObject> copyTuioObjects() {
|
||||
return TuioDispatcher::copyTuioObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TuioObject corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioObject
|
||||
*
|
||||
* @param s_id the session ID of the corresponding TuioObject
|
||||
* @return an active TuioObject corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioObject* getTuioObject(long s_id) {
|
||||
return getTuioObject(0,s_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
TuioObject* getTuioObject(int src_id, long s_id);
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioCursors
|
||||
*
|
||||
* @return a List of TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor*> getTuioCursors() {
|
||||
return TuioDispatcher::getTuioCursors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioCursors
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List of TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor*> getTuioCursors(int source_id);
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioCursors
|
||||
*
|
||||
* @return a List with a copy of TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor> copyTuioCursors() {
|
||||
return TuioDispatcher::copyTuioCursors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioCursors
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List with a copy of TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor> copyTuioCursors(int source_id);
|
||||
|
||||
/**
|
||||
* Returns the TuioCursor corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioCursor
|
||||
*
|
||||
* @param s_id the session ID of the corresponding TuioCursor
|
||||
* @return an active TuioCursor corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioCursor* getTuioCursor(long s_id) {
|
||||
return getTuioCursor(0,s_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the TuioCursor 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 TuioCursor
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @param s_id the session ID of the corresponding TuioCursor
|
||||
* @return an active TuioCursor corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioCursor* getTuioCursor(int src_id, long s_id);
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioBlobs
|
||||
*
|
||||
* @return a List of TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob*> getTuioBlobs() {
|
||||
return TuioDispatcher::getTuioBlobs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioBlobs
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List of TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob*> getTuioBlobs(int source_id);
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioBlobs
|
||||
*
|
||||
* @return a List with a copy of TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob> copyTuioBlobs() {
|
||||
return TuioDispatcher::copyTuioBlobs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of all currently active TuioBlobs
|
||||
* which are associated to the given Source ID
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @return a List with a copy of TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob> copyTuioBlobs(int source_id);
|
||||
|
||||
/**
|
||||
* Returns the TuioBlob corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioBlob
|
||||
*
|
||||
* @param s_id the session ID of the corresponding TuioBlob
|
||||
* @return an active TuioBlob corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioBlob* getTuioBlob(long s_id) {
|
||||
return getTuioBlob(0,s_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the TuioBlob 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 TuioBlob
|
||||
*
|
||||
* @param src_id the source ID of the corresponding TUIO source
|
||||
* @param s_id the session ID of the corresponding TuioBlob
|
||||
* @return an active TuioBlob corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioBlob* getTuioBlob(int src_id, long s_id);
|
||||
|
||||
void processOSC( const osc::ReceivedMessage& message);
|
||||
|
||||
private:
|
||||
void initialize();
|
||||
|
||||
std::list<TuioObject*> frameObjects;
|
||||
std::list<long> aliveObjectList;
|
||||
std::list<TuioCursor*> frameCursors;
|
||||
std::list<long> aliveCursorList;
|
||||
std::list<TuioBlob*> frameBlobs;
|
||||
std::list<long> aliveBlobList;
|
||||
|
||||
osc::int32 currentFrame;
|
||||
TuioTime currentTime;
|
||||
|
||||
std::list<TuioCursor*> freeCursorList, freeCursorBuffer;
|
||||
std::map<int,int> maxCursorID;
|
||||
|
||||
std::list<TuioBlob*> freeBlobList, freeBlobBuffer;
|
||||
std::map<int,int> maxBlobID;
|
||||
|
||||
std::map<std::string,int> sourceList;
|
||||
int source_id;
|
||||
char *source_name;
|
||||
char *source_addr;
|
||||
|
||||
OscReceiver *receiver;
|
||||
bool local_receiver;
|
||||
};
|
||||
};
|
||||
#endif /* INCLUDED_TUIOCLIENT_H */
|
||||
277
modules/touch/ext/libTUIO/TUIO/TuioContainer.cpp
Normal file
277
modules/touch/ext/libTUIO/TUIO/TuioContainer.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "TuioContainer.h"
|
||||
using namespace TUIO;
|
||||
|
||||
TuioContainer::TuioContainer (TuioTime ttime, long si, float xp, float yp):TuioPoint(ttime, xp,yp)
|
||||
,state(TUIO_ADDED)
|
||||
,source_id(0)
|
||||
,source_name("undefined")
|
||||
,source_addr("localhost")
|
||||
{
|
||||
session_id = si;
|
||||
x_speed = 0.0f;
|
||||
y_speed = 0.0f;
|
||||
motion_speed = 0.0f;
|
||||
motion_accel = 0.0f;
|
||||
x_accel = 0.0f;
|
||||
y_accel = 0.0f;
|
||||
TuioPoint p(currentTime,xpos,ypos);
|
||||
path.push_back(p);
|
||||
lastPoint = &path.back();
|
||||
}
|
||||
|
||||
TuioContainer::TuioContainer (long si, float xp, float yp):TuioPoint(xp,yp)
|
||||
,state(TUIO_ADDED)
|
||||
,source_id(0)
|
||||
,source_name("undefined")
|
||||
,source_addr("localhost")
|
||||
{
|
||||
session_id = si;
|
||||
x_speed = 0.0f;
|
||||
y_speed = 0.0f;
|
||||
motion_speed = 0.0f;
|
||||
motion_accel = 0.0f;
|
||||
x_accel = 0.0f;
|
||||
y_accel = 0.0f;
|
||||
TuioPoint p(currentTime,xpos,ypos);
|
||||
path.push_back(p);
|
||||
lastPoint = &path.back();
|
||||
}
|
||||
|
||||
TuioContainer::TuioContainer (TuioContainer *tcon):TuioPoint(tcon)
|
||||
,state(TUIO_ADDED)
|
||||
,source_id(0)
|
||||
,source_name("undefined")
|
||||
,source_addr("localhost")
|
||||
{
|
||||
session_id = tcon->getSessionID();
|
||||
x_speed = 0.0f;
|
||||
y_speed = 0.0f;
|
||||
motion_speed = 0.0f;
|
||||
motion_accel = 0.0f;
|
||||
x_accel = 0.0f;
|
||||
y_accel = 0.0f;
|
||||
|
||||
TuioPoint p(currentTime,xpos,ypos);
|
||||
path.push_back(p);
|
||||
lastPoint = &path.back();
|
||||
}
|
||||
|
||||
void TuioContainer::setTuioSource(int src_id, const char *src_name, const char *src_addr) {
|
||||
source_id = src_id;
|
||||
source_name = std::string(src_name);
|
||||
source_addr = std::string(src_addr);
|
||||
}
|
||||
|
||||
const char* TuioContainer::getTuioSourceName() const{
|
||||
return source_name.c_str();
|
||||
}
|
||||
|
||||
const char* TuioContainer::getTuioSourceAddress() const{
|
||||
return source_addr.c_str();
|
||||
}
|
||||
|
||||
int TuioContainer::getTuioSourceID() const{
|
||||
return source_id;
|
||||
}
|
||||
|
||||
void TuioContainer::update (TuioTime ttime, float xp, float yp) {
|
||||
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;
|
||||
float last_x_speed = x_speed;
|
||||
float last_y_speed = y_speed;
|
||||
|
||||
x_speed = dx/dt;
|
||||
y_speed = dy/dt;
|
||||
motion_speed = dist/dt;
|
||||
motion_accel = (motion_speed - last_motion_speed)/dt;
|
||||
x_accel = (x_speed - last_x_speed)/dt;
|
||||
y_accel = (y_speed - last_y_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 state = TUIO_STOPPED;
|
||||
}
|
||||
|
||||
void TuioContainer::stop(TuioTime ttime) {
|
||||
if ( state==TUIO_IDLE )update(ttime,xpos,ypos);
|
||||
else state=TUIO_IDLE;
|
||||
}
|
||||
|
||||
void TuioContainer::update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma) {
|
||||
TuioPoint::update(ttime,xp, yp);
|
||||
x_speed = xs;
|
||||
y_speed = ys;
|
||||
motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
|
||||
motion_accel = ma;
|
||||
x_accel = ma;
|
||||
y_accel = ma;
|
||||
|
||||
lastPoint = &path.back();
|
||||
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 state = TUIO_STOPPED;
|
||||
}
|
||||
|
||||
void TuioContainer::update (float xp, float yp, float xs, float ys, float ma) {
|
||||
TuioPoint::update(xp,yp);
|
||||
x_speed = xs;
|
||||
y_speed = ys;
|
||||
motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
|
||||
motion_accel = ma;
|
||||
x_accel = ma;
|
||||
y_accel = ma;
|
||||
|
||||
lastPoint = &path.back();
|
||||
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 state = TUIO_STOPPED;
|
||||
}
|
||||
|
||||
void TuioContainer::update (TuioContainer *tcon) {
|
||||
TuioPoint::update(tcon);
|
||||
x_speed = tcon->getXSpeed();
|
||||
y_speed = tcon->getYSpeed();
|
||||
motion_speed = tcon->getMotionSpeed();
|
||||
motion_accel = tcon->getMotionAccel();
|
||||
x_accel = motion_accel;
|
||||
y_accel = motion_accel;
|
||||
|
||||
lastPoint = &path.back();
|
||||
TuioPoint p(tcon->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 state = TUIO_STOPPED;
|
||||
}
|
||||
|
||||
void TuioContainer::remove(TuioTime ttime) {
|
||||
currentTime = ttime;
|
||||
state = TUIO_REMOVED;
|
||||
}
|
||||
|
||||
long TuioContainer::getSessionID() const{
|
||||
return session_id;
|
||||
}
|
||||
|
||||
void TuioContainer::setSessionID(long s_id) {
|
||||
session_id = s_id;
|
||||
}
|
||||
|
||||
float TuioContainer::getXSpeed() const{
|
||||
return x_speed;
|
||||
}
|
||||
|
||||
float TuioContainer::getYSpeed() const{
|
||||
return y_speed;
|
||||
}
|
||||
|
||||
TuioPoint TuioContainer::getPosition() const{
|
||||
TuioPoint p(xpos,ypos);
|
||||
return p;
|
||||
}
|
||||
|
||||
std::list<TuioPoint> TuioContainer::getPath() const{
|
||||
return path;
|
||||
}
|
||||
|
||||
float TuioContainer::getMotionSpeed() const{
|
||||
return motion_speed;
|
||||
}
|
||||
|
||||
float TuioContainer::getMotionAccel() const{
|
||||
return motion_accel;
|
||||
}
|
||||
|
||||
int TuioContainer::getTuioState() const{
|
||||
return state;
|
||||
}
|
||||
|
||||
bool TuioContainer::isMoving() const{
|
||||
if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
TuioPoint TuioContainer::predictPosition() {
|
||||
/*if (path.size()>1) {
|
||||
std::list<TuioPoint>::iterator iter = path.end();
|
||||
std::advance(iter, -2);
|
||||
|
||||
TuioTime diffTime = currentTime - (*iter).getTuioTime();
|
||||
float dt = diffTime.getTotalMilliseconds()/1000.0f;
|
||||
|
||||
float tx = x_speed * dt;
|
||||
float ty = y_speed * dt;
|
||||
|
||||
float nx = xpos+tx-tx*x_accel*dt;
|
||||
float ny = ypos+ty-ty*y_accel*dt;
|
||||
|
||||
//if (xposFilter && yposFilter) {
|
||||
// nx = xposFilter->filter(nx,dt);
|
||||
// ny = yposFilter->filter(ny,dt);
|
||||
// //std::cout << dt << " " << xp << " " << xpos << " " << yp << " " << ypos << std::endl;
|
||||
//}
|
||||
|
||||
//std::cout << nx << " " << ny << std::endl;
|
||||
return TuioPoint(nx,ny);
|
||||
} else return TuioPoint(xpos,ypos);*/
|
||||
|
||||
TuioTime diffTime = currentTime - lastPoint->getTuioTime();
|
||||
float dt = diffTime.getTotalMilliseconds()/1000.0f;
|
||||
|
||||
float tx = x_speed * dt;
|
||||
float ty = y_speed * dt;
|
||||
|
||||
float nx = xpos+tx-tx*x_accel*dt;
|
||||
float ny = ypos+ty-ty*y_accel*dt;
|
||||
|
||||
//if (xposFilter && yposFilter) {
|
||||
// nx = xposFilter->filter(nx,dt);
|
||||
// ny = yposFilter->filter(ny,dt);
|
||||
// //std::cout << dt << " " << xp << " " << xpos << " " << yp << " " << ypos << std::endl;
|
||||
//}
|
||||
|
||||
//std::cout << nx << " " << ny << std::endl;
|
||||
return TuioPoint(nx,ny);
|
||||
|
||||
|
||||
}
|
||||
|
||||
279
modules/touch/ext/libTUIO/TUIO/TuioContainer.h
Normal file
279
modules/touch/ext/libTUIO/TUIO/TuioContainer.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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_TUIOCONTAINER_H
|
||||
#define INCLUDED_TUIOCONTAINER_H
|
||||
|
||||
#include "TuioPoint.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#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 TUIO {
|
||||
|
||||
/**
|
||||
* The abstract TuioContainer class defines common attributes that apply to both subclasses {@link TuioObject} and {@link TuioCursor}.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioContainer: public TuioPoint {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TuioPoint *lastPoint;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The unique session ID number that is assigned to each TUIO object or cursor.
|
||||
*/
|
||||
long session_id;
|
||||
/**
|
||||
* The X-axis velocity value.
|
||||
*/
|
||||
float x_speed;
|
||||
/**
|
||||
* The Y-axis velocity value.
|
||||
*/
|
||||
float y_speed;
|
||||
/**
|
||||
* The motion speed value.
|
||||
*/
|
||||
float motion_speed;
|
||||
/**
|
||||
* The motion acceleration value.
|
||||
*/
|
||||
float motion_accel;
|
||||
float x_accel;
|
||||
float y_accel;
|
||||
/**
|
||||
* A List of TuioPoints containing all the previous positions of the TUIO component.
|
||||
*/
|
||||
std::list<TuioPoint> path;
|
||||
/**
|
||||
* Reflects the current state of the TuioComponent
|
||||
*/
|
||||
int state;
|
||||
/**
|
||||
* The ID of the TUIO source
|
||||
*/
|
||||
int source_id;
|
||||
/**
|
||||
* The name of the TUIO source
|
||||
*/
|
||||
std::string source_name;
|
||||
/**
|
||||
* The address of the TUIO source
|
||||
*/
|
||||
std::string source_addr;
|
||||
|
||||
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 TuioContainer.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param si the Session ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
TuioContainer (TuioTime ttime, long si, float xp, float yp);
|
||||
|
||||
/**
|
||||
* This constructor takes the provided Session ID, X and Y coordinate
|
||||
* and assigs these values to the newly created TuioContainer.
|
||||
*
|
||||
* @param si the Session ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
TuioContainer (long si, float xp, float yp);
|
||||
|
||||
/**
|
||||
* This constructor takes the atttibutes of the provided TuioContainer
|
||||
* and assigs these values to the newly created TuioContainer.
|
||||
*
|
||||
* @param tcon the TuioContainer to assign
|
||||
*/
|
||||
TuioContainer (TuioContainer *tcon);
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
virtual ~TuioContainer(){};
|
||||
|
||||
/**
|
||||
* 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_addr the address of the TUIO source
|
||||
*/
|
||||
virtual void setTuioSource(int src_id, const char *src_name, const char *src_addr);
|
||||
|
||||
/**
|
||||
* Returns the name of the TUIO source
|
||||
*/
|
||||
virtual const char* getTuioSourceName() const;
|
||||
|
||||
/**
|
||||
* Returns the address of the TUIO source
|
||||
*/
|
||||
virtual const char* getTuioSourceAddress() const;
|
||||
|
||||
/**
|
||||
* Returns the ID of the TUIO source
|
||||
*/
|
||||
virtual int getTuioSourceID() const;
|
||||
|
||||
/**
|
||||
* Takes a TuioTime argument and assigns it along with the provided
|
||||
* X and Y coordinate to the private TuioContainer attributes.
|
||||
* The speed and accleration values are calculated accordingly.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
virtual void update (TuioTime ttime, float xp, float yp);
|
||||
|
||||
/**
|
||||
* This method is used to calculate the speed and acceleration values of
|
||||
* TuioContainers 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 TuioContainer attributes.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param xs the X velocity to assign
|
||||
* @param ys the Y velocity to assign
|
||||
* @param ma the acceleration to assign
|
||||
*/
|
||||
virtual void update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma);
|
||||
|
||||
/**
|
||||
* Assigns the provided X and Y coordinate, X and Y velocity and acceleration
|
||||
* to the private TuioContainer attributes. The TuioTime time stamp remains unchanged.
|
||||
*
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param xs the X velocity to assign
|
||||
* @param ys the Y velocity to assign
|
||||
* @param ma the acceleration to assign
|
||||
*/
|
||||
virtual void update (float xp, float yp, float xs, float ys, float ma);
|
||||
|
||||
/**
|
||||
* Takes the atttibutes of the provided TuioContainer
|
||||
* and assigs these values to this TuioContainer.
|
||||
* The TuioTime time stamp of this TuioContainer remains unchanged.
|
||||
*
|
||||
* @param tcon the TuioContainer to assign
|
||||
*/
|
||||
virtual void update (TuioContainer *tcon);
|
||||
|
||||
/**
|
||||
* Assigns the REMOVE state to this TuioContainer and sets
|
||||
* its TuioTime time stamp to the provided TuioTime argument.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
*/
|
||||
virtual void remove(TuioTime ttime);
|
||||
|
||||
/**
|
||||
* Returns the Session ID of this TuioContainer.
|
||||
* @return the Session ID of this TuioContainer
|
||||
*/
|
||||
virtual long getSessionID() const;
|
||||
|
||||
/**
|
||||
* Sets the Session ID of this TuioContainer.
|
||||
* @param s_id the new Session ID for this TuioContainer
|
||||
*/
|
||||
virtual void setSessionID(long s_id);
|
||||
|
||||
/**
|
||||
* Returns the X velocity of this TuioContainer.
|
||||
* @return the X velocity of this TuioContainer
|
||||
*/
|
||||
virtual float getXSpeed() const;
|
||||
|
||||
/**
|
||||
* Returns the Y velocity of this TuioContainer.
|
||||
* @return the Y velocity of this TuioContainer
|
||||
*/
|
||||
virtual float getYSpeed() const;
|
||||
|
||||
/**
|
||||
* Returns the position of this TuioContainer.
|
||||
* @return the position of this TuioContainer
|
||||
*/
|
||||
virtual TuioPoint getPosition() const;
|
||||
|
||||
/**
|
||||
* Returns the path of this TuioContainer.
|
||||
* @return the path of this TuioContainer
|
||||
*/
|
||||
virtual std::list<TuioPoint> getPath() const;
|
||||
|
||||
/**
|
||||
* Returns the motion speed of this TuioContainer.
|
||||
* @return the motion speed of this TuioContainer
|
||||
*/
|
||||
virtual float getMotionSpeed() const;
|
||||
|
||||
/**
|
||||
* Returns the motion acceleration of this TuioContainer.
|
||||
* @return the motion acceleration of this TuioContainer
|
||||
*/
|
||||
virtual float getMotionAccel() const;
|
||||
|
||||
/**
|
||||
* Returns the TUIO state of this TuioContainer.
|
||||
* @return the TUIO state of this TuioContainer
|
||||
*/
|
||||
virtual int getTuioState() const;
|
||||
|
||||
/**
|
||||
* Returns true of this TuioContainer is moving.
|
||||
* @return true of this TuioContainer is moving
|
||||
*/
|
||||
virtual bool isMoving() const;
|
||||
|
||||
virtual TuioPoint predictPosition();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
38
modules/touch/ext/libTUIO/TUIO/TuioCursor.cpp
Normal file
38
modules/touch/ext/libTUIO/TUIO/TuioCursor.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "TuioCursor.h"
|
||||
|
||||
using namespace TUIO;
|
||||
|
||||
TuioCursor::TuioCursor (TuioTime ttime, long si, int ci, float xp, float yp):TuioContainer(ttime,si,xp,yp) {
|
||||
cursor_id = ci;
|
||||
}
|
||||
|
||||
TuioCursor::TuioCursor (long si, int ci, float xp, float yp):TuioContainer(si,xp,yp) {
|
||||
cursor_id = ci;
|
||||
}
|
||||
|
||||
TuioCursor::TuioCursor (TuioCursor *tcur):TuioContainer(tcur) {
|
||||
cursor_id = tcur->getCursorID();
|
||||
}
|
||||
|
||||
int TuioCursor::getCursorID() const{
|
||||
return cursor_id;
|
||||
};
|
||||
|
||||
86
modules/touch/ext/libTUIO/TUIO/TuioCursor.h
Normal file
86
modules/touch/ext/libTUIO/TUIO/TuioCursor.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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_TUIOCURSOR_H
|
||||
#define INCLUDED_TUIOCURSOR_H
|
||||
|
||||
#include "TuioContainer.h"
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TuioCursor class encapsulates /tuio/2Dcur TUIO cursors.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioCursor: public TuioContainer {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The individual cursor ID number that is assigned to each TuioCursor.
|
||||
*/
|
||||
int cursor_id;
|
||||
|
||||
public:
|
||||
using TuioContainer::update;
|
||||
|
||||
/**
|
||||
* This constructor takes a TuioTime argument and assigns it along with the provided
|
||||
* Session ID, Cursor ID, X and Y coordinate to the newly created TuioCursor.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param si the Session ID to assign
|
||||
* @param ci the Cursor ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
TuioCursor (TuioTime ttime, long si, int ci, float xp, float yp);
|
||||
|
||||
/**
|
||||
* This constructor takes the provided Session ID, Cursor ID, X and Y coordinate
|
||||
* and assigs these values to the newly created TuioCursor.
|
||||
*
|
||||
* @param si the Session ID to assign
|
||||
* @param ci the Cursor ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
TuioCursor (long si, int ci, float xp, float yp);
|
||||
|
||||
/**
|
||||
* This constructor takes the atttibutes of the provided TuioCursor
|
||||
* and assigs these values to the newly created TuioCursor.
|
||||
*
|
||||
* @param tcur the TuioCursor to assign
|
||||
*/
|
||||
TuioCursor (TuioCursor *tcur);
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
virtual ~TuioCursor(){};
|
||||
|
||||
/**
|
||||
* Returns the Cursor ID of this TuioCursor.
|
||||
* @return the Cursor ID of this TuioCursor
|
||||
*/
|
||||
int getCursorID() const;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
211
modules/touch/ext/libTUIO/TUIO/TuioDispatcher.cpp
Normal file
211
modules/touch/ext/libTUIO/TUIO/TuioDispatcher.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <iostream>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
using namespace TUIO;
|
||||
|
||||
TuioDispatcher::TuioDispatcher() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_init(&cursorMutex,NULL);
|
||||
pthread_mutex_init(&objectMutex,NULL);
|
||||
pthread_mutex_init(&blobMutex,NULL);
|
||||
#else
|
||||
cursorMutex = CreateMutex(NULL,FALSE,TEXT("cursorMutex"));
|
||||
objectMutex = CreateMutex(NULL,FALSE,TEXT("objectMutex"));
|
||||
blobMutex = CreateMutex(NULL,FALSE,TEXT("blobMutex"));
|
||||
#endif
|
||||
}
|
||||
|
||||
TuioDispatcher::~TuioDispatcher() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_destroy(&cursorMutex);
|
||||
pthread_mutex_destroy(&objectMutex);
|
||||
pthread_mutex_destroy(&blobMutex);
|
||||
#else
|
||||
CloseHandle(cursorMutex);
|
||||
CloseHandle(objectMutex);
|
||||
CloseHandle(blobMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::lockObjectList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_lock(&objectMutex);
|
||||
#else
|
||||
WaitForSingleObject(objectMutex, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::unlockObjectList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_unlock(&objectMutex);
|
||||
#else
|
||||
ReleaseMutex(objectMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::lockCursorList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_lock(&cursorMutex);
|
||||
#else
|
||||
WaitForSingleObject(cursorMutex, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::unlockCursorList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_unlock(&cursorMutex);
|
||||
#else
|
||||
ReleaseMutex(cursorMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::lockBlobList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_lock(&blobMutex);
|
||||
#else
|
||||
WaitForSingleObject(blobMutex, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::unlockBlobList() {
|
||||
#ifndef WIN32
|
||||
pthread_mutex_unlock(&blobMutex);
|
||||
#else
|
||||
ReleaseMutex(blobMutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TuioDispatcher::addTuioListener(TuioListener *listener) {
|
||||
listenerList.push_back(listener);
|
||||
}
|
||||
|
||||
void TuioDispatcher::removeTuioListener(TuioListener *listener) {
|
||||
std::list<TuioListener*>::iterator result = find(listenerList.begin(),listenerList.end(),listener);
|
||||
if (result!=listenerList.end()) listenerList.remove(listener);
|
||||
}
|
||||
|
||||
void TuioDispatcher::removeAllTuioListeners() {
|
||||
listenerList.clear();
|
||||
}
|
||||
|
||||
TuioObject* TuioDispatcher::getTuioObject(long s_id) {
|
||||
lockObjectList();
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
if((*iter)->getSessionID()==s_id) {
|
||||
unlockObjectList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockObjectList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TuioCursor* TuioDispatcher::getTuioCursor(long s_id) {
|
||||
lockCursorList();
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
if((*iter)->getSessionID()==s_id) {
|
||||
unlockCursorList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockCursorList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TuioBlob* TuioDispatcher::getTuioBlob(long s_id) {
|
||||
lockBlobList();
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
if((*iter)->getSessionID()==s_id) {
|
||||
unlockBlobList();
|
||||
return (*iter);
|
||||
}
|
||||
}
|
||||
unlockBlobList();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::list<TuioObject*> TuioDispatcher::getTuioObjects() {
|
||||
lockObjectList();
|
||||
std::list<TuioObject*> listBuffer;
|
||||
listBuffer.insert(listBuffer.end(), objectList.begin(), objectList.end());
|
||||
//std::list<TuioObject*> listBuffer = objectList;
|
||||
unlockObjectList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioCursor*> TuioDispatcher::getTuioCursors() {
|
||||
lockCursorList();
|
||||
std::list<TuioCursor*> listBuffer;
|
||||
listBuffer.insert(listBuffer.end(), cursorList.begin(), cursorList.end());
|
||||
//std::list<TuioCursor*> listBuffer = cursorList;
|
||||
unlockCursorList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioBlob*> TuioDispatcher::getTuioBlobs() {
|
||||
lockBlobList();
|
||||
std::list<TuioBlob*> listBuffer;
|
||||
listBuffer.insert(listBuffer.end(), blobList.begin(), blobList.end());
|
||||
//std::list<TuioBlob*> listBuffer = blobList;
|
||||
unlockBlobList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioObject> TuioDispatcher::copyTuioObjects() {
|
||||
lockObjectList();
|
||||
std::list<TuioObject> listBuffer;
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
TuioObject *tobj = (*iter);
|
||||
listBuffer.push_back(*tobj);
|
||||
}
|
||||
unlockObjectList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioCursor> TuioDispatcher::copyTuioCursors() {
|
||||
lockCursorList();
|
||||
std::list<TuioCursor> listBuffer;
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
TuioCursor *tcur = (*iter);
|
||||
listBuffer.push_back(*tcur);
|
||||
}
|
||||
unlockCursorList();
|
||||
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
std::list<TuioBlob> TuioDispatcher::copyTuioBlobs() {
|
||||
lockBlobList();
|
||||
std::list<TuioBlob> listBuffer;
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
TuioBlob *tblb = (*iter);
|
||||
listBuffer.push_back(*tblb);
|
||||
}
|
||||
unlockBlobList();
|
||||
return listBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
187
modules/touch/ext/libTUIO/TUIO/TuioDispatcher.h
Normal file
187
modules/touch/ext/libTUIO/TUIO/TuioDispatcher.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <pthread.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* <p>The TuioDispatcher generates TUIO events which are broadcasted to all
|
||||
* registered classes that implement the {@link TuioListener} interface.</p>
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 TuioObjects
|
||||
*
|
||||
* @return a List of all currently active TuioObjects
|
||||
*/
|
||||
std::list<TuioObject*> getTuioObjects();
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of currently active TuioObjects
|
||||
*
|
||||
* @return a List with a copy of all currently active TuioObjects
|
||||
*/
|
||||
std::list<TuioObject> copyTuioObjects();
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioCursors
|
||||
*
|
||||
* @return a List of all currently active TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor*> getTuioCursors();
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of currently active TuioCursors
|
||||
*
|
||||
* @return a List with a copy of all currently active TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor> copyTuioCursors();
|
||||
|
||||
/**
|
||||
* Returns a List of all currently active TuioBlobs
|
||||
*
|
||||
* @return a List of all currently active TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob*> getTuioBlobs();
|
||||
|
||||
/**
|
||||
* Returns a List with a copy of currently active TuioBlobs
|
||||
*
|
||||
* @return a List with a copy of all currently active TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob> copyTuioBlobs();
|
||||
|
||||
/**
|
||||
* Returns the TuioObject corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioObject
|
||||
*
|
||||
* @return an active TuioObject corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioObject* getTuioObject(long s_id);
|
||||
|
||||
/**
|
||||
* Returns the TuioCursor corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioCursor
|
||||
*
|
||||
* @return an active TuioCursor corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioCursor* getTuioCursor(long s_id);
|
||||
|
||||
/**
|
||||
* Returns the TuioBlob corresponding to the provided Session ID
|
||||
* or NULL if the Session ID does not refer to an active TuioBlob
|
||||
*
|
||||
* @return an active TuioBlob corresponding to the provided Session ID or NULL
|
||||
*/
|
||||
TuioBlob* getTuioBlob(long s_id);
|
||||
|
||||
/**
|
||||
* Locks the TuioObject list in order to avoid updates during access
|
||||
*/
|
||||
void lockObjectList();
|
||||
|
||||
/**
|
||||
* Releases the lock of the TuioObject list
|
||||
*/
|
||||
void unlockObjectList();
|
||||
|
||||
/**
|
||||
* Locks the TuioCursor list in order to avoid updates during access
|
||||
*/
|
||||
void lockCursorList();
|
||||
|
||||
/**
|
||||
* Releases the lock of the TuioCursor list
|
||||
*/
|
||||
void unlockCursorList();
|
||||
|
||||
/**
|
||||
* Locks the TuioBlob list in order to avoid updates during access
|
||||
*/
|
||||
void lockBlobList();
|
||||
|
||||
/**
|
||||
* Releases the lock of the TuioBlob list
|
||||
*/
|
||||
void unlockBlobList();
|
||||
|
||||
protected:
|
||||
std::list<TuioListener*> listenerList;
|
||||
|
||||
std::list<TuioObject*> objectList;
|
||||
std::list<TuioCursor*> cursorList;
|
||||
std::list<TuioBlob*> blobList;
|
||||
|
||||
#ifndef WIN32
|
||||
pthread_mutex_t objectMutex;
|
||||
pthread_mutex_t cursorMutex;
|
||||
pthread_mutex_t blobMutex;
|
||||
#else
|
||||
HANDLE objectMutex;
|
||||
HANDLE cursorMutex;
|
||||
HANDLE blobMutex;
|
||||
#endif
|
||||
|
||||
};
|
||||
}
|
||||
#endif /* INCLUDED_TUIODISPATCHER_H */
|
||||
124
modules/touch/ext/libTUIO/TUIO/TuioListener.h
Normal file
124
modules/touch/ext/libTUIO/TUIO/TuioListener.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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"
|
||||
#include "TuioCursor.h"
|
||||
#include "TuioBlob.h"
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* <p>The TuioListener interface provides a simple callback infrastructure which is used by the {@link TuioClient} class
|
||||
* to dispatch TUIO events to all registered instances of classes that implement the TuioListener interface defined here.</p>
|
||||
* <p>Any class that implements the TuioListener interface is required to implement all of the callback methods defined here.
|
||||
* The {@link TuioClient} makes use of these interface methods in order to dispatch TUIO events to all registered TuioListener implementations.</p>
|
||||
* <p><code>
|
||||
* public class MyTuioListener implements TuioListener<br/>
|
||||
* ...</code><p><code>
|
||||
* MyTuioListener listener = new MyTuioListener();<br/>
|
||||
* TuioClient client = new TuioClient();<br/>
|
||||
* client.addTuioListener(listener);<br/>
|
||||
* client.start();<br/>
|
||||
* </code></p>
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioListener {
|
||||
|
||||
public:
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
virtual ~TuioListener(){};
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when a new TuioObject is added to the session.
|
||||
*
|
||||
* @param tobj the TuioObject reference associated to the addTuioObject event
|
||||
*/
|
||||
virtual void addTuioObject(TuioObject *tobj)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioObject is updated during the session.
|
||||
*
|
||||
* @param tobj the TuioObject reference associated to the updateTuioObject event
|
||||
*/
|
||||
virtual void updateTuioObject(TuioObject *tobj)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioObject is removed from the session.
|
||||
*
|
||||
* @param tobj the TuioObject reference associated to the removeTuioObject event
|
||||
*/
|
||||
virtual void removeTuioObject(TuioObject *tobj)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when a new TuioCursor is added to the session.
|
||||
*
|
||||
* @param tcur the TuioCursor reference associated to the addTuioCursor event
|
||||
*/
|
||||
virtual void addTuioCursor(TuioCursor *tcur)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioCursor is updated during the session.
|
||||
*
|
||||
* @param tcur the TuioCursor reference associated to the updateTuioCursor event
|
||||
*/
|
||||
virtual void updateTuioCursor(TuioCursor *tcur)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioCursor is removed from the session.
|
||||
*
|
||||
* @param tcur the TuioCursor reference associated to the removeTuioCursor event
|
||||
*/
|
||||
virtual void removeTuioCursor(TuioCursor *tcur)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when a new TuioBlob is added to the session.
|
||||
*
|
||||
* @param tcur the TuioBlob reference associated to the addTuioBlob event
|
||||
*/
|
||||
virtual void addTuioBlob(TuioBlob *tblb)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioBlob is updated during the session.
|
||||
*
|
||||
* @param tblb the TuioBlob reference associated to the updateTuioBlob event
|
||||
*/
|
||||
virtual void updateTuioBlob(TuioBlob *tblb)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient when an existing TuioBlob is removed from the session.
|
||||
*
|
||||
* @param tblb the TuioBlob reference associated to the removeTuioBlob event
|
||||
*/
|
||||
virtual void removeTuioBlob(TuioBlob *tblb)=0;
|
||||
|
||||
/**
|
||||
* This callback method is invoked by the TuioClient to mark the end of a received TUIO message bundle.
|
||||
*
|
||||
* @param ftime the TuioTime associated to the current TUIO message bundle
|
||||
*/
|
||||
virtual void refresh(TuioTime ftime)=0;
|
||||
};
|
||||
}
|
||||
#endif /* INCLUDED_TUIOLISTENER_H */
|
||||
615
modules/touch/ext/libTUIO/TUIO/TuioManager.cpp
Normal file
615
modules/touch/ext/libTUIO/TUIO/TuioManager.cpp
Normal file
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
|
||||
TuioManager::TuioManager()
|
||||
: currentFrameTime(TuioTime::getSystemTime())
|
||||
, currentFrame(-1)
|
||||
, maxCursorID(-1)
|
||||
, maxBlobID(-1)
|
||||
, sessionID(-1)
|
||||
, updateObject(false)
|
||||
, updateCursor(false)
|
||||
, updateBlob(false)
|
||||
, verbose(false)
|
||||
, invert_x(false)
|
||||
, invert_y(false)
|
||||
, invert_a(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TuioManager::~TuioManager() {
|
||||
}
|
||||
|
||||
|
||||
TuioObject* TuioManager::addTuioObject(int f_id, float x, float y, float a) {
|
||||
sessionID++;
|
||||
TuioObject *tobj = new TuioObject(currentFrameTime, sessionID, f_id, x, y, a);
|
||||
objectList.push_back(tobj);
|
||||
updateObject = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
|
||||
|
||||
return tobj;
|
||||
}
|
||||
|
||||
void TuioManager::addExternalTuioObject(TuioObject *tobj) {
|
||||
if (tobj==NULL) return;
|
||||
tobj->setSessionID(sessionID++);
|
||||
objectList.push_back(tobj);
|
||||
updateObject = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
|
||||
}
|
||||
|
||||
void TuioManager::updateTuioObject(TuioObject *tobj, float x, float y, float a) {
|
||||
if (tobj==NULL) return;
|
||||
if (tobj->getTuioTime()==currentFrameTime) return;
|
||||
tobj->update(currentFrameTime,x,y,a);
|
||||
updateObject = true;
|
||||
|
||||
if (tobj->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle()
|
||||
<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::updateExternalTuioObject(TuioObject *tobj) {
|
||||
if (tobj==NULL) return;
|
||||
updateObject = true;
|
||||
|
||||
if (tobj->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle()
|
||||
<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeTuioObject(TuioObject *tobj) {
|
||||
if (tobj==NULL) return;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ")" << std::endl;
|
||||
|
||||
objectList.remove(tobj);
|
||||
delete tobj;
|
||||
updateObject = true;
|
||||
}
|
||||
|
||||
void TuioManager::removeExternalTuioObject(TuioObject *tobj) {
|
||||
if (tobj==NULL) return;
|
||||
objectList.remove(tobj);
|
||||
updateObject = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioObject(tobj);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ")" << std::endl;
|
||||
}
|
||||
|
||||
TuioCursor* TuioManager::addTuioCursor(float x, float y) {
|
||||
sessionID++;
|
||||
|
||||
int cursorID = (int)cursorList.size();
|
||||
if ((int)(cursorList.size())<=maxCursorID) {
|
||||
std::list<TuioCursor*>::iterator closestCursor = freeCursorList.begin();
|
||||
|
||||
for(std::list<TuioCursor*>::iterator iter = freeCursorList.begin();iter!= freeCursorList.end(); iter++) {
|
||||
if((*iter)->getDistance(x,y)<(*closestCursor)->getDistance(x,y)) closestCursor = iter;
|
||||
}
|
||||
|
||||
TuioCursor *freeCursor = (*closestCursor);
|
||||
cursorID = (*closestCursor)->getCursorID();
|
||||
freeCursorList.erase(closestCursor);
|
||||
delete freeCursor;
|
||||
} else maxCursorID = cursorID;
|
||||
|
||||
TuioCursor *tcur = new TuioCursor(currentFrameTime, sessionID, cursorID, x, y);
|
||||
cursorList.push_back(tcur);
|
||||
updateCursor = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() << std::endl;
|
||||
|
||||
return tcur;
|
||||
}
|
||||
|
||||
void TuioManager::addExternalTuioCursor(TuioCursor *tcur) {
|
||||
if (tcur==NULL) return;
|
||||
tcur->setSessionID(sessionID++);
|
||||
cursorList.push_back(tcur);
|
||||
updateCursor = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY() << std::endl;
|
||||
}
|
||||
|
||||
void TuioManager::updateTuioCursor(TuioCursor *tcur,float x, float y) {
|
||||
if (tcur==NULL) return;
|
||||
//if (tcur->getTuioTime()==currentFrameTime) return;
|
||||
tcur->update(currentFrameTime,x,y);
|
||||
updateCursor = true;
|
||||
|
||||
if (tcur->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY()
|
||||
<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed() << " " << tcur->getMotionAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::updateExternalTuioCursor(TuioCursor *tcur) {
|
||||
if (tcur==NULL) return;
|
||||
updateCursor = true;
|
||||
|
||||
if (tcur->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY()
|
||||
<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed() << " " << tcur->getMotionAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeTuioCursor(TuioCursor *tcur) {
|
||||
if (tcur==NULL) return;
|
||||
|
||||
cursorList.remove(tcur);
|
||||
tcur->remove(currentFrameTime);
|
||||
updateCursor = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ")" << std::endl;
|
||||
|
||||
if (tcur->getCursorID()==maxCursorID) {
|
||||
maxCursorID = -1;
|
||||
delete tcur;
|
||||
|
||||
if (cursorList.size()>0) {
|
||||
std::list<TuioCursor*>::iterator clist;
|
||||
for (clist=cursorList.begin(); clist != cursorList.end(); clist++) {
|
||||
int cursorID = (*clist)->getCursorID();
|
||||
if (cursorID>maxCursorID) maxCursorID=cursorID;
|
||||
}
|
||||
|
||||
freeCursorBuffer.clear();
|
||||
for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
|
||||
TuioCursor *freeCursor = (*flist);
|
||||
if (freeCursor->getCursorID()>maxCursorID) delete freeCursor;
|
||||
else freeCursorBuffer.push_back(freeCursor);
|
||||
}
|
||||
|
||||
freeCursorList = freeCursorBuffer;
|
||||
|
||||
} else {
|
||||
for (std::list<TuioCursor*>::iterator flist=freeCursorList.begin(); flist != freeCursorList.end(); flist++) {
|
||||
TuioCursor *freeCursor = (*flist);
|
||||
delete freeCursor;
|
||||
}
|
||||
freeCursorList.clear();
|
||||
}
|
||||
} else if (tcur->getCursorID()<maxCursorID) {
|
||||
freeCursorList.push_back(tcur);
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeExternalTuioCursor(TuioCursor *tcur) {
|
||||
if (tcur==NULL) return;
|
||||
cursorList.remove(tcur);
|
||||
updateCursor = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioCursor(tcur);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ")" << std::endl;
|
||||
}
|
||||
|
||||
TuioBlob* TuioManager::addTuioBlob(float x, float y, float a, float w, float h, float f) {
|
||||
sessionID++;
|
||||
|
||||
int blobID = (int)blobList.size();
|
||||
if ((int)(blobList.size())<=maxBlobID) {
|
||||
std::list<TuioBlob*>::iterator closestBlob = freeBlobList.begin();
|
||||
|
||||
for(std::list<TuioBlob*>::iterator iter = freeBlobList.begin();iter!= freeBlobList.end(); iter++) {
|
||||
if((*iter)->getDistance(x,y)<(*closestBlob)->getDistance(x,y)) closestBlob = iter;
|
||||
}
|
||||
|
||||
TuioBlob *freeBlob = (*closestBlob);
|
||||
blobID = (*closestBlob)->getBlobID();
|
||||
freeBlobList.erase(closestBlob);
|
||||
delete freeBlob;
|
||||
} else maxBlobID = blobID;
|
||||
|
||||
TuioBlob *tblb = new TuioBlob(currentFrameTime, sessionID, blobID, x, y, a, w, h, f);
|
||||
blobList.push_back(tblb);
|
||||
updateBlob = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea() << std::endl;
|
||||
|
||||
return tblb;
|
||||
}
|
||||
|
||||
void TuioManager::addExternalTuioBlob(TuioBlob *tblb) {
|
||||
if (tblb==NULL) return;
|
||||
|
||||
int blobID = (int)blobList.size();
|
||||
if (blobID <= maxBlobID) {
|
||||
std::list<TuioBlob*>::iterator closestBlob = freeBlobList.begin();
|
||||
|
||||
for(std::list<TuioBlob*>::iterator iter = freeBlobList.begin();iter!= freeBlobList.end(); iter++) {
|
||||
if((*iter)->getDistance(tblb->getX(),tblb->getY())<(*closestBlob)->getDistance(tblb->getX(),tblb->getY())) closestBlob = iter;
|
||||
}
|
||||
|
||||
TuioBlob *freeBlob = (*closestBlob);
|
||||
blobID = (*closestBlob)->getBlobID();
|
||||
freeBlobList.erase(closestBlob);
|
||||
delete freeBlob;
|
||||
} else maxBlobID = blobID;
|
||||
|
||||
tblb->setSessionID(sessionID++);
|
||||
tblb->setBlobID(blobID);
|
||||
|
||||
blobList.push_back(tblb);
|
||||
updateBlob = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->addTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "add blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea() << std::endl;
|
||||
}
|
||||
|
||||
void TuioManager::updateTuioBlob(TuioBlob *tblb,float x, float y, float a, float w, float h, float f) {
|
||||
if (tblb==NULL) return;
|
||||
if (tblb->getTuioTime()==currentFrameTime) return;
|
||||
tblb->update(currentFrameTime,x,y,a,w,h,f);
|
||||
updateBlob = true;
|
||||
|
||||
if (tblb->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea()
|
||||
<< " " << tblb->getXSpeed() << " " << tblb->getYSpeed() << " " << tblb->getRotationSpeed() << " " << tblb->getMotionAccel()<< " " << tblb->getRotationAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::updateExternalTuioBlob(TuioBlob *tblb) {
|
||||
if (tblb==NULL) return;
|
||||
updateBlob = true;
|
||||
|
||||
if (tblb->isMoving()) {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->updateTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "set blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea()
|
||||
<< " " << tblb->getXSpeed() << " " << tblb->getYSpeed() << " " << tblb->getRotationSpeed() << " " << tblb->getMotionAccel()<< " " << tblb->getRotationAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeTuioBlob(TuioBlob *tblb) {
|
||||
if (tblb==NULL) return;
|
||||
|
||||
blobList.remove(tblb);
|
||||
tblb->remove(currentFrameTime);
|
||||
updateBlob = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ")" << std::endl;
|
||||
|
||||
if (tblb->getBlobID()==maxBlobID) {
|
||||
maxBlobID = -1;
|
||||
delete tblb;
|
||||
|
||||
if (blobList.size()>0) {
|
||||
std::list<TuioBlob*>::iterator clist;
|
||||
for (clist=blobList.begin(); clist != blobList.end(); clist++) {
|
||||
int blobID = (*clist)->getBlobID();
|
||||
if (blobID>maxBlobID) maxBlobID=blobID;
|
||||
}
|
||||
|
||||
freeBlobBuffer.clear();
|
||||
for (std::list<TuioBlob*>::iterator flist=freeBlobList.begin(); flist != freeBlobList.end(); flist++) {
|
||||
TuioBlob *freeBlob = (*flist);
|
||||
if (freeBlob->getBlobID()>maxBlobID) delete freeBlob;
|
||||
else freeBlobBuffer.push_back(freeBlob);
|
||||
}
|
||||
|
||||
freeBlobList = freeBlobBuffer;
|
||||
|
||||
} else {
|
||||
for (std::list<TuioBlob*>::iterator flist=freeBlobList.begin(); flist != freeBlobList.end(); flist++) {
|
||||
TuioBlob *freeBlob = (*flist);
|
||||
delete freeBlob;
|
||||
}
|
||||
freeBlobList.clear();
|
||||
}
|
||||
} else if (tblb->getBlobID()<maxBlobID) {
|
||||
freeBlobList.push_back(tblb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TuioManager::removeExternalTuioBlob(TuioBlob *tblb) {
|
||||
if (tblb==NULL) return;
|
||||
blobList.remove(tblb);
|
||||
updateBlob = true;
|
||||
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->removeTuioBlob(tblb);
|
||||
|
||||
if (verbose)
|
||||
std::cout << "del blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ")" << std::endl;
|
||||
}
|
||||
|
||||
long TuioManager::getSessionID() {
|
||||
sessionID++;
|
||||
return sessionID;
|
||||
}
|
||||
|
||||
long TuioManager::getFrameID() {
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
TuioTime TuioManager::getFrameTime() {
|
||||
return currentFrameTime;
|
||||
}
|
||||
|
||||
void TuioManager::initFrame(TuioTime ttime) {
|
||||
currentFrameTime = TuioTime(ttime);
|
||||
currentFrame++;
|
||||
}
|
||||
|
||||
void TuioManager::commitFrame() {
|
||||
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
|
||||
(*listener)->refresh(currentFrameTime);
|
||||
}
|
||||
|
||||
TuioObject* TuioManager::getClosestTuioObject(float xp, float yp) {
|
||||
|
||||
TuioObject *closestObject = NULL;
|
||||
float closestDistance = 1.0f;
|
||||
|
||||
for (std::list<TuioObject*>::iterator iter=objectList.begin(); iter != objectList.end(); iter++) {
|
||||
float distance = (*iter)->getDistance(xp,yp);
|
||||
if(distance<closestDistance) {
|
||||
closestObject = (*iter);
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return closestObject;
|
||||
}
|
||||
|
||||
TuioCursor* TuioManager::getClosestTuioCursor(float xp, float yp) {
|
||||
|
||||
TuioCursor *closestCursor = NULL;
|
||||
float closestDistance = 1.0f;
|
||||
|
||||
for (std::list<TuioCursor*>::iterator iter=cursorList.begin(); iter != cursorList.end(); iter++) {
|
||||
float distance = (*iter)->getDistance(xp,yp);
|
||||
if(distance<closestDistance) {
|
||||
closestCursor = (*iter);
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return closestCursor;
|
||||
}
|
||||
|
||||
TuioBlob* TuioManager::getClosestTuioBlob(float xp, float yp) {
|
||||
|
||||
TuioBlob *closestBlob = NULL;
|
||||
float closestDistance = 1.0f;
|
||||
|
||||
for (std::list<TuioBlob*>::iterator iter=blobList.begin(); iter != blobList.end(); iter++) {
|
||||
float distance = (*iter)->getDistance(xp,yp);
|
||||
if(distance<closestDistance) {
|
||||
closestBlob = (*iter);
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return closestBlob;
|
||||
}
|
||||
|
||||
std::list<TuioObject*> TuioManager::getUntouchedObjects() {
|
||||
|
||||
std::list<TuioObject*> untouched;
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
TuioObject *tobj = (*tuioObject);
|
||||
if (tobj->getTuioTime()!=currentFrameTime) untouched.push_back(tobj);
|
||||
}
|
||||
return untouched;
|
||||
}
|
||||
|
||||
void TuioManager::stopUntouchedMovingObjects() {
|
||||
|
||||
std::list<TuioObject*> untouched;
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
|
||||
TuioObject *tobj = (*tuioObject);
|
||||
if ((tobj->getTuioTime()!=currentFrameTime) && (tobj->isMoving())) {
|
||||
tobj->stop(currentFrameTime);
|
||||
updateObject = true;
|
||||
if (verbose)
|
||||
std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle()
|
||||
<< " " << tobj->getXSpeed() << " " << tobj->getYSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeUntouchedStoppedObjects() {
|
||||
|
||||
std::list<TuioObject*>::iterator tuioObject = objectList.begin();
|
||||
while (tuioObject!=objectList.end()) {
|
||||
TuioObject *tobj = (*tuioObject);
|
||||
if ((tobj->getTuioTime()!=currentFrameTime) && (!tobj->isMoving())) {
|
||||
removeTuioObject(tobj);
|
||||
tuioObject = objectList.begin();
|
||||
} else tuioObject++;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::resetTuioObjects() {
|
||||
|
||||
std::list<TuioObject*>::iterator tuioObject = objectList.begin();
|
||||
while (tuioObject!=objectList.end()) {
|
||||
removeTuioObject((*tuioObject));
|
||||
tuioObject = objectList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
std::list<TuioCursor*> TuioManager::getUntouchedCursors() {
|
||||
|
||||
std::list<TuioCursor*> untouched;
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
TuioCursor *tcur = (*tuioCursor);
|
||||
if (tcur->getTuioTime()!=currentFrameTime) untouched.push_back(tcur);
|
||||
}
|
||||
return untouched;
|
||||
}
|
||||
|
||||
void TuioManager::stopUntouchedMovingCursors() {
|
||||
|
||||
std::list<TuioCursor*> untouched;
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
TuioCursor *tcur = (*tuioCursor);
|
||||
if ((tcur->getTuioTime()!=currentFrameTime) && (tcur->isMoving())) {
|
||||
tcur->stop(currentFrameTime);
|
||||
updateCursor = true;
|
||||
if (verbose)
|
||||
std::cout << "set cur " << tcur->getCursorID() << " (" << tcur->getSessionID() << ") " << tcur->getX() << " " << tcur->getY()
|
||||
<< " " << tcur->getXSpeed() << " " << tcur->getYSpeed()<< " " << tcur->getMotionAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeUntouchedStoppedCursors() {
|
||||
|
||||
if (cursorList.size()==0) return;
|
||||
std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin();
|
||||
while (tuioCursor!=cursorList.end()) {
|
||||
TuioCursor *tcur = (*tuioCursor);
|
||||
if ((tcur->getTuioTime()!=currentFrameTime) && (!tcur->isMoving())) {
|
||||
removeTuioCursor(tcur);
|
||||
tuioCursor = cursorList.begin();
|
||||
} else tuioCursor++;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::resetTuioCursors() {
|
||||
|
||||
std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin();
|
||||
while (tuioCursor!=cursorList.end()) {
|
||||
removeTuioCursor((*tuioCursor));
|
||||
tuioCursor = cursorList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
std::list<TuioBlob*> TuioManager::getUntouchedBlobs() {
|
||||
|
||||
std::list<TuioBlob*> untouched;
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
TuioBlob *tblb = (*tuioBlob);
|
||||
if (tblb->getTuioTime()!=currentFrameTime) untouched.push_back(tblb);
|
||||
}
|
||||
return untouched;
|
||||
}
|
||||
|
||||
void TuioManager::stopUntouchedMovingBlobs() {
|
||||
|
||||
std::list<TuioBlob*> untouched;
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
TuioBlob *tblb = (*tuioBlob);
|
||||
if ((tblb->getTuioTime()!=currentFrameTime) && (tblb->isMoving())) {
|
||||
tblb->stop(currentFrameTime);
|
||||
updateBlob = true;
|
||||
if (verbose)
|
||||
std::cout << "set blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea()
|
||||
<< " " << tblb->getXSpeed() << " " << tblb->getYSpeed() << " " << tblb->getRotationSpeed() << " " << tblb->getMotionAccel()<< " " << tblb->getRotationAccel() << " " << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::removeUntouchedStoppedBlobs() {
|
||||
|
||||
std::list<TuioBlob*>::iterator tuioBlob = blobList.begin();
|
||||
while (tuioBlob!=blobList.end()) {
|
||||
TuioBlob *tblb = (*tuioBlob);
|
||||
if ((tblb->getTuioTime()!=currentFrameTime) && (!tblb->isMoving())) {
|
||||
removeTuioBlob(tblb);
|
||||
tuioBlob = blobList.begin();
|
||||
} else tuioBlob++;
|
||||
}
|
||||
}
|
||||
|
||||
void TuioManager::resetTuioBlobs() {
|
||||
|
||||
std::list<TuioBlob*>::iterator tuioBlob = blobList.begin();
|
||||
while (tuioBlob!=blobList.end()) {
|
||||
removeTuioBlob((*tuioBlob));
|
||||
tuioBlob = blobList.begin();
|
||||
}
|
||||
}
|
||||
389
modules/touch/ext/libTUIO/TUIO/TuioManager.h
Normal file
389
modules/touch/ext/libTUIO/TUIO/TuioManager.h
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 <iostream>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
#define OBJ_MESSAGE_SIZE 108 // setMessage + fseqMessage size
|
||||
#define CUR_MESSAGE_SIZE 88
|
||||
#define BLB_MESSAGE_SIZE 116
|
||||
|
||||
namespace TUIO {
|
||||
/**
|
||||
* <p>The TuioManager class is the central TUIO session management component.</p>
|
||||
* <p>During runtime the each frame is marked with the initFrame and commitFrame methods,
|
||||
* while the currently present TuioObjects are managed by the server with ADD, UPDATE and REMOVE methods in analogy to the TuioClient's TuioListener interface.</p>
|
||||
* <p><code>
|
||||
* TuioManager *manager = new TuioManager();<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* TuioObject *tobj = server->addTuioObject(xpos,ypos, angle);<br/>
|
||||
* TuioCursor *tcur = server->addTuioObject(xpos,ypos);<br/>
|
||||
* TuioBlob *tblb = server->addTuioBlob(xpos,ypos,width,height,angle);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* server->updateTuioObject(tobj, xpos,ypos, angle);<br/>
|
||||
* server->updateTuioCursor(tcur, xpos,ypos);<br/>
|
||||
* server->updateTuioBlob(tblb, xpos,ypos,width,height,angle);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* server->removeTuioObject(tobj);<br/>
|
||||
* server->removeTuioCursor(tcur);<br/>
|
||||
* server->removeTuioBlob(tblb);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* </code></p>
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioManager : public TuioDispatcher {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The default constructor creates a TuioManager
|
||||
*/
|
||||
TuioManager();
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
~TuioManager();
|
||||
|
||||
/**
|
||||
* Creates a new TuioObject based on the given arguments.
|
||||
* The new TuioObject is added to the TuioServer's internal list of active TuioObjects
|
||||
* and a reference is returned to the caller.
|
||||
*
|
||||
* @param sym the Symbol ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle to assign
|
||||
* @return reference to the created TuioObject
|
||||
*/
|
||||
TuioObject* addTuioObject(int sym, float xp, float yp, float a);
|
||||
|
||||
/**
|
||||
* Updates the referenced TuioObject based on the given arguments.
|
||||
*
|
||||
* @param tobj the TuioObject to update
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle to assign
|
||||
*/
|
||||
void updateTuioObject(TuioObject *tobj, float xp, float yp, float a);
|
||||
|
||||
/**
|
||||
* Removes the referenced TuioObject from the TuioServer's internal list of TuioObjects
|
||||
* and deletes the referenced TuioObject afterwards
|
||||
*
|
||||
* @param tobj the TuioObject to remove
|
||||
*/
|
||||
void removeTuioObject(TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* Adds an externally managed TuioObject to the TuioServer's internal list of active TuioObjects
|
||||
*
|
||||
* @param tobj the TuioObject to add
|
||||
*/
|
||||
void addExternalTuioObject(TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* Updates an externally managed TuioObject
|
||||
*
|
||||
* @param tobj the TuioObject to update
|
||||
*/
|
||||
void updateExternalTuioObject(TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* Removes an externally managed TuioObject from the TuioServer's internal list of TuioObjects
|
||||
* The referenced TuioObject is not deleted
|
||||
*
|
||||
* @param tobj the TuioObject to remove
|
||||
*/
|
||||
void removeExternalTuioObject(TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* Creates a new TuioCursor based on the given arguments.
|
||||
* The new TuioCursor is added to the TuioServer's internal list of active TuioCursors
|
||||
* and a reference is returned to the caller.
|
||||
*
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @return reference to the created TuioCursor
|
||||
*/
|
||||
TuioCursor* addTuioCursor(float xp, float yp);
|
||||
|
||||
/**
|
||||
* Updates the referenced TuioCursor based on the given arguments.
|
||||
*
|
||||
* @param tcur the TuioObject to update
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
*/
|
||||
void updateTuioCursor(TuioCursor *tcur, float xp, float yp);
|
||||
|
||||
/**
|
||||
* Removes the referenced TuioCursor from the TuioServer's internal list of TuioCursors
|
||||
* and deletes the referenced TuioCursor afterwards
|
||||
*
|
||||
* @param tcur the TuioCursor to remove
|
||||
*/
|
||||
void removeTuioCursor(TuioCursor *tcur);
|
||||
|
||||
/**
|
||||
* Adds an externally managed TuioCursor
|
||||
*
|
||||
* @param tcur the TuioCursor to add
|
||||
*/
|
||||
void addExternalTuioCursor(TuioCursor *tcur);
|
||||
|
||||
/**
|
||||
* Updates an externally managed TuioCursor
|
||||
*
|
||||
* @param tcur the TuioCursor to update
|
||||
*/
|
||||
void updateExternalTuioCursor(TuioCursor *tcur);
|
||||
|
||||
/**
|
||||
* Removes an externally managed TuioCursor from the TuioServer's internal list of TuioCursor
|
||||
* The referenced TuioCursor is not deleted
|
||||
*
|
||||
* @param tcur the TuioCursor to remove
|
||||
*/
|
||||
void removeExternalTuioCursor(TuioCursor *tcur);
|
||||
|
||||
/**
|
||||
* Creates a new TuioBlob based on the given arguments.
|
||||
* The new TuioBlob is added to the TuioServer's internal list of active TuioBlobs
|
||||
* 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 reference to the created TuioBlob
|
||||
*/
|
||||
TuioBlob* addTuioBlob(float xp, float yp, float angle, float width, float height, float area);
|
||||
|
||||
/**
|
||||
* Updates the referenced TuioBlob based on the given arguments.
|
||||
*
|
||||
* @param tblb the TuioObject 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 updateTuioBlob(TuioBlob *tblb, float xp, float yp, float angle, float width, float height, float area);
|
||||
|
||||
/**
|
||||
* Removes the referenced TuioBlob from the TuioServer's internal list of TuioBlobs
|
||||
* and deletes the referenced TuioBlob afterwards
|
||||
*
|
||||
* @param tblb the TuioBlob to remove
|
||||
*/
|
||||
void removeTuioBlob(TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* Updates an externally managed TuioBlob
|
||||
*
|
||||
* @param tblb the TuioBlob to update
|
||||
*/
|
||||
void addExternalTuioBlob(TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* Updates an externally managed TuioBlob
|
||||
*
|
||||
* @param tblb the TuioBlob to update
|
||||
*/
|
||||
void updateExternalTuioBlob(TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* Removes an externally managed TuioBlob from the TuioServer's internal list of TuioBlob
|
||||
* The referenced TuioBlob is not deleted
|
||||
*
|
||||
* @param tblb the TuioBlob to remove
|
||||
*/
|
||||
void removeExternalTuioBlob(TuioBlob *tblb);
|
||||
|
||||
/**
|
||||
* Initializes a new frame with the given TuioTime
|
||||
*
|
||||
* @param ttime the frame time
|
||||
*/
|
||||
void initFrame(TuioTime ttime);
|
||||
|
||||
/**
|
||||
* Commits the current frame.
|
||||
* Generates and sends TUIO messages of all currently active and updated TuioObjects and TuioCursors.
|
||||
*/
|
||||
void commitFrame();
|
||||
|
||||
/**
|
||||
* Returns the next available Session ID for external use.
|
||||
* @return the next available Session ID for external use
|
||||
*/
|
||||
long getSessionID();
|
||||
|
||||
/**
|
||||
* Returns the current frame ID for external use.
|
||||
* @return the current frame ID for external use
|
||||
*/
|
||||
long getFrameID();
|
||||
|
||||
/**
|
||||
* Returns the current frame ID for external use.
|
||||
* @return the current frame ID for external use
|
||||
*/
|
||||
TuioTime getFrameTime();
|
||||
|
||||
/**
|
||||
* Returns a List of all currently inactive TuioObjects
|
||||
*
|
||||
* @return a List of all currently inactive TuioObjects
|
||||
*/
|
||||
std::list<TuioObject*> getUntouchedObjects();
|
||||
|
||||
/**
|
||||
* Returns a List of all currently inactive TuioCursors
|
||||
*
|
||||
* @return a List of all currently inactive TuioCursors
|
||||
*/
|
||||
std::list<TuioCursor*> getUntouchedCursors();
|
||||
|
||||
/**
|
||||
* Returns a List of all currently inactive TuioBlobs
|
||||
*
|
||||
* @return a List of all currently inactive TuioBlobs
|
||||
*/
|
||||
std::list<TuioBlob*> getUntouchedBlobs();
|
||||
|
||||
/**
|
||||
* Calculates speed and acceleration values for all currently inactive TuioObjects
|
||||
*/
|
||||
void stopUntouchedMovingObjects();
|
||||
|
||||
/**
|
||||
* Calculates speed and acceleration values for all currently inactive TuioCursors
|
||||
*/
|
||||
void stopUntouchedMovingCursors();
|
||||
|
||||
/**
|
||||
* Calculates speed and acceleration values for all currently inactive TuioBlobs
|
||||
*/
|
||||
void stopUntouchedMovingBlobs();
|
||||
|
||||
/**
|
||||
* Removes all currently inactive TuioObjects from the TuioServer's internal list of TuioObjects
|
||||
*/
|
||||
void removeUntouchedStoppedObjects();
|
||||
|
||||
/**
|
||||
* Removes all currently inactive TuioCursors from the TuioServer's internal list of TuioCursors
|
||||
*/
|
||||
void removeUntouchedStoppedCursors();
|
||||
|
||||
/**
|
||||
* Removes all currently inactive TuioCursors from the TuioServer's internal list of TuioBlobs
|
||||
*/
|
||||
void removeUntouchedStoppedBlobs();
|
||||
|
||||
/**
|
||||
* Returns the TuioObject closest to the provided coordinates
|
||||
* or NULL if there isn't any active TuioObject
|
||||
*
|
||||
* @return the closest TuioObject to the provided coordinates or NULL
|
||||
*/
|
||||
TuioObject* getClosestTuioObject(float xp, float yp);
|
||||
|
||||
/**
|
||||
* Returns the TuioCursor closest to the provided coordinates
|
||||
* or NULL if there isn't any active TuioCursor
|
||||
*
|
||||
* @return the closest TuioCursor corresponding to the provided coordinates or NULL
|
||||
*/
|
||||
TuioCursor* getClosestTuioCursor(float xp, float yp);
|
||||
|
||||
/**
|
||||
* Returns the TuioBlob closest to the provided coordinates
|
||||
* or NULL if there isn't any active TuioBlob
|
||||
*
|
||||
* @return the closest TuioBlob corresponding to the provided coordinates or NULL
|
||||
*/
|
||||
TuioBlob* getClosestTuioBlob(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; }
|
||||
bool isVerbose() { return 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 resetTuioObjects();
|
||||
void resetTuioCursors();
|
||||
void resetTuioBlobs();
|
||||
|
||||
protected:
|
||||
std::list<TuioCursor*> freeCursorList;
|
||||
std::list<TuioCursor*> freeCursorBuffer;
|
||||
|
||||
std::list<TuioBlob*> freeBlobList;
|
||||
std::list<TuioBlob*> freeBlobBuffer;
|
||||
|
||||
TuioTime currentFrameTime;
|
||||
long currentFrame;
|
||||
int maxCursorID;
|
||||
int maxBlobID;
|
||||
long sessionID;
|
||||
|
||||
bool updateObject;
|
||||
bool updateCursor;
|
||||
bool updateBlob;
|
||||
bool verbose;
|
||||
|
||||
bool invert_x;
|
||||
bool invert_y;
|
||||
bool invert_a;
|
||||
};
|
||||
}
|
||||
#endif /* INCLUDED_TUIOMANAGER_H */
|
||||
165
modules/touch/ext/libTUIO/TUIO/TuioObject.cpp
Normal file
165
modules/touch/ext/libTUIO/TUIO/TuioObject.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
TuioObject::TuioObject (TuioTime ttime, long si, int sym, float xp, float yp, float a):TuioContainer(ttime, si, xp, yp) {
|
||||
symbol_id = sym;
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioObject::TuioObject (long si, int sym, float xp, float yp, float a):TuioContainer(si, xp, yp) {
|
||||
symbol_id = sym;
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioObject::TuioObject (TuioObject *tobj):TuioContainer(tobj) {
|
||||
symbol_id = tobj->getSymbolID();
|
||||
angle = tobj->getAngle();
|
||||
angle_sum = tobj->getAngleSum();
|
||||
rotation_speed = 0.0f;
|
||||
rotation_accel = 0.0f;
|
||||
|
||||
angleFilter = NULL;
|
||||
angleThreshold = 0.0f;
|
||||
}
|
||||
|
||||
void TuioObject::update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
|
||||
TuioContainer::update(ttime,xp,yp,xs,ys,ma);
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
rotation_speed = rs;
|
||||
rotation_accel = ra;
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
|
||||
void TuioObject::update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
|
||||
TuioContainer::update(xp,yp,xs,ys,ma);
|
||||
angle = a;
|
||||
angle_sum = a;
|
||||
rotation_speed = rs;
|
||||
rotation_accel = ra;
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
void TuioObject::update (TuioTime ttime, float xp, float yp, float a) {
|
||||
TuioPoint lastPoint = path.back();
|
||||
TuioContainer::update(ttime,xp,yp);
|
||||
|
||||
TuioTime diffTime = currentTime - lastPoint.getTuioTime();
|
||||
float dt = diffTime.getTotalMilliseconds()/1000.0f;
|
||||
float last_rotation_speed = rotation_speed;
|
||||
|
||||
float prev_angle = angle_sum;
|
||||
float da = a-angle;
|
||||
if (da > M_PI/2.0f) angle_sum += (da-2*M_PI);
|
||||
else if (da < M_PI/-2.0f) angle_sum += (da+2*M_PI);
|
||||
else angle_sum += da;
|
||||
|
||||
if (angleFilter) angle_sum = angleFilter->filter(angle_sum,dt);
|
||||
if (fabs(angle_sum-prev_angle)<angleThreshold) angle_sum = prev_angle;
|
||||
|
||||
int m = floor(angle_sum/(2*M_PI));
|
||||
angle = angle_sum-(m*(2*M_PI));
|
||||
|
||||
da = (angle-a)/(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;
|
||||
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
void TuioObject::stop (TuioTime ttime) {
|
||||
update(ttime,xpos,ypos,angle);
|
||||
}
|
||||
|
||||
void TuioObject::update (TuioObject *tobj) {
|
||||
TuioContainer::update(tobj);
|
||||
angle = tobj->getAngle();
|
||||
angle_sum = tobj->getAngleSum();
|
||||
rotation_speed = tobj->getRotationSpeed();
|
||||
rotation_accel = tobj->getRotationAccel();
|
||||
if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
|
||||
}
|
||||
|
||||
int TuioObject::getSymbolID() const{
|
||||
return symbol_id;
|
||||
}
|
||||
|
||||
float TuioObject::getAngle() const{
|
||||
return angle;
|
||||
}
|
||||
|
||||
float TuioObject::getAngleSum() const{
|
||||
return angle_sum;
|
||||
}
|
||||
|
||||
float TuioObject::getAngleDegrees() const{
|
||||
return (float)(angle/M_PI*180);
|
||||
}
|
||||
|
||||
float TuioObject::getRotationSpeed() const{
|
||||
return rotation_speed;
|
||||
}
|
||||
|
||||
float TuioObject::getRotationAccel() const{
|
||||
return rotation_accel;
|
||||
}
|
||||
|
||||
bool TuioObject::isMoving() const{
|
||||
if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING) || (state==TUIO_ROTATING)) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
void TuioObject::addAngleThreshold(float thresh) {
|
||||
angleThreshold = thresh;
|
||||
}
|
||||
|
||||
void TuioObject::removeAngleThreshold() {
|
||||
angleThreshold = 0.0f;
|
||||
}
|
||||
|
||||
void TuioObject::addAngleFilter(float mcut, float beta) {
|
||||
|
||||
if (angleFilter) delete angleFilter;
|
||||
angleFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
}
|
||||
|
||||
void TuioObject::removeAngleFilter() {
|
||||
|
||||
if (angleFilter) delete angleFilter;
|
||||
angleFilter = NULL;
|
||||
}
|
||||
213
modules/touch/ext/libTUIO/TUIO/TuioObject.h
Normal file
213
modules/touch/ext/libTUIO/TUIO/TuioObject.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "TuioContainer.h"
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TuioObject class encapsulates /tuio/2Dobj TUIO objects.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioObject: public TuioContainer {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The individual symbol ID number that is assigned to each TuioObject.
|
||||
*/
|
||||
int symbol_id;
|
||||
/**
|
||||
* The rotation angle value.
|
||||
*/
|
||||
float angle;
|
||||
/**
|
||||
* The accumulated angle value.
|
||||
*/
|
||||
float angle_sum;
|
||||
/**
|
||||
* The rotation speed value.
|
||||
*/
|
||||
float rotation_speed;
|
||||
/**
|
||||
* The rotation acceleration value.
|
||||
*/
|
||||
float rotation_accel;
|
||||
|
||||
float angleThreshold;
|
||||
OneEuroFilter *angleFilter;
|
||||
|
||||
public:
|
||||
using TuioContainer::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 TuioObject.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param si the Session ID to assign
|
||||
* @param sym the Symbol ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle to assign
|
||||
*/
|
||||
TuioObject (TuioTime ttime, long si, int sym, float xp, float yp, float a);
|
||||
|
||||
/**
|
||||
* This constructor takes the provided Session ID, Symbol ID, X and Y coordinate
|
||||
* and angle, and assigs these values to the newly created TuioObject.
|
||||
*
|
||||
* @param si the Session ID to assign
|
||||
* @param sym the Symbol ID to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle to assign
|
||||
*/
|
||||
TuioObject (long si, int sym, float xp, float yp, float a);
|
||||
|
||||
/**
|
||||
* This constructor takes the atttibutes of the provided TuioObject
|
||||
* and assigs these values to the newly created TuioObject.
|
||||
*
|
||||
* @param tobj the TuioObject to assign
|
||||
*/
|
||||
TuioObject (TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
virtual ~TuioObject() {
|
||||
if (angleFilter) delete angleFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a TuioTime argument and assigns it along with the provided
|
||||
* X and Y coordinate, angle, X and Y velocity, motion acceleration,
|
||||
* rotation speed and rotation acceleration to the private TuioObject attributes.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle coordinate to assign
|
||||
* @param xs the X velocity to assign
|
||||
* @param ys the Y velocity to assign
|
||||
* @param rs the rotation velocity to assign
|
||||
* @param ma the motion acceleration to assign
|
||||
* @param ra the rotation acceleration to assign
|
||||
*/
|
||||
void update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra);
|
||||
|
||||
/**
|
||||
* Assigns the provided X and Y coordinate, angle, X and Y velocity, motion acceleration
|
||||
* rotation velocity and rotation acceleration to the private TuioContainer attributes.
|
||||
* The TuioTime time stamp remains unchanged.
|
||||
*
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle coordinate to assign
|
||||
* @param xs the X velocity to assign
|
||||
* @param ys the Y velocity to assign
|
||||
* @param rs the rotation velocity to assign
|
||||
* @param ma the motion acceleration to assign
|
||||
* @param ra the rotation acceleration to assign
|
||||
*/
|
||||
void update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra);
|
||||
|
||||
/**
|
||||
* Takes a TuioTime argument and assigns it along with the provided
|
||||
* X and Y coordinate and angle to the private TuioObject attributes.
|
||||
* The speed and accleration values are calculated accordingly.
|
||||
*
|
||||
* @param ttime the TuioTime to assign
|
||||
* @param xp the X coordinate to assign
|
||||
* @param yp the Y coordinate to assign
|
||||
* @param a the angle coordinate to assign
|
||||
*/
|
||||
void update (TuioTime ttime, float xp, float yp, float a);
|
||||
|
||||
/**
|
||||
* This method is used to calculate the speed and acceleration values of a
|
||||
* TuioObject with unchanged position and angle.
|
||||
*/
|
||||
void stop (TuioTime ttime);
|
||||
|
||||
/**
|
||||
* Takes the atttibutes of the provided TuioObject
|
||||
* and assigs these values to this TuioObject.
|
||||
* The TuioTime time stamp of this TuioContainer remains unchanged.
|
||||
*
|
||||
* @param tobj the TuioContainer to assign
|
||||
*/
|
||||
void update (TuioObject *tobj);
|
||||
|
||||
/**
|
||||
* Returns the symbol ID of this TuioObject.
|
||||
* @return the symbol ID of this TuioObject
|
||||
*/
|
||||
int getSymbolID() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation angle of this TuioObject.
|
||||
* @return the rotation angle of this TuioObject
|
||||
*/
|
||||
float getAngle() const;
|
||||
|
||||
/**
|
||||
* Returns the accumulated rotation angle of this TuioObject.
|
||||
* @return the accumulated rotation angle of this TuioObject
|
||||
*/
|
||||
float getAngleSum() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation angle in degrees of this TuioObject.
|
||||
* @return the rotation angle in degrees of this TuioObject
|
||||
*/
|
||||
float getAngleDegrees() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation speed of this TuioObject.
|
||||
* @return the rotation speed of this TuioObject
|
||||
*/
|
||||
float getRotationSpeed() const;
|
||||
|
||||
/**
|
||||
* Returns the rotation acceleration of this TuioObject.
|
||||
* @return the rotation acceleration of this TuioObject
|
||||
*/
|
||||
float getRotationAccel() const;
|
||||
|
||||
/**
|
||||
* Returns true of this TuioObject is moving.
|
||||
* @return true of this TuioObject is moving
|
||||
*/
|
||||
bool isMoving() const;
|
||||
|
||||
void addAngleThreshold(float thresh);
|
||||
|
||||
void removeAngleThreshold();
|
||||
|
||||
void addAngleFilter(float mcut, float beta);
|
||||
|
||||
void removeAngleFilter();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
176
modules/touch/ext/libTUIO/TUIO/TuioPoint.cpp
Normal file
176
modules/touch/ext/libTUIO/TUIO/TuioPoint.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
TuioPoint::TuioPoint (float xp, float yp) {
|
||||
xpos = xp;
|
||||
ypos = yp;
|
||||
currentTime = TuioTime::getSessionTime();
|
||||
startTime = currentTime;
|
||||
|
||||
xposFilter = NULL;
|
||||
yposFilter = NULL;
|
||||
|
||||
posThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioPoint::TuioPoint (TuioTime ttime, float xp, float yp) {
|
||||
xpos = xp;
|
||||
ypos = yp;
|
||||
currentTime = ttime;
|
||||
startTime = currentTime;
|
||||
|
||||
xposFilter = NULL;
|
||||
yposFilter = NULL;
|
||||
|
||||
posThreshold = 0.0f;
|
||||
}
|
||||
|
||||
TuioPoint::TuioPoint (TuioPoint *tpoint) {
|
||||
xpos = tpoint->getX();
|
||||
ypos = tpoint->getY();
|
||||
currentTime = TuioTime::getSessionTime();
|
||||
startTime = currentTime;
|
||||
|
||||
xposFilter = NULL;
|
||||
yposFilter = NULL;
|
||||
|
||||
posThreshold = 0.0f;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if (xposFilter && yposFilter) {
|
||||
TuioTime diffTime = ttime - startTime;
|
||||
float dt = diffTime.getTotalMilliseconds()/1000.0f;
|
||||
xp = xposFilter->filter(xp,dt);
|
||||
yp = yposFilter->filter(yp,dt);
|
||||
//std::cout << dt << " " << xp << " " << xpos << " " << yp << " " << ypos << std::endl;
|
||||
}
|
||||
|
||||
float dx = fabs(xpos - xp);
|
||||
float dy = fabs(ypos - yp);
|
||||
if ((dx>posThreshold) || (dy>posThreshold)) {
|
||||
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;
|
||||
}
|
||||
|
||||
void TuioPoint::addPositionThreshold(float thresh) {
|
||||
posThreshold = thresh;
|
||||
}
|
||||
|
||||
void TuioPoint::removePositionThreshold() {
|
||||
posThreshold = 0.0f;
|
||||
}
|
||||
|
||||
void TuioPoint::addPositionFilter(float mcut, float beta) {
|
||||
|
||||
if (xposFilter) delete xposFilter;
|
||||
xposFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
if (yposFilter) delete yposFilter;
|
||||
yposFilter = new OneEuroFilter(60.0f, mcut, beta, 1.0f);
|
||||
}
|
||||
|
||||
void TuioPoint::removePositionFilter() {
|
||||
|
||||
if (xposFilter) delete xposFilter;
|
||||
xposFilter = NULL;
|
||||
if (yposFilter) delete yposFilter;
|
||||
yposFilter = NULL;
|
||||
}
|
||||
226
modules/touch/ext/libTUIO/TUIO/TuioPoint.h
Normal file
226
modules/touch/ext/libTUIO/TUIO/TuioPoint.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "OneEuroFilter.h"
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TuioPoint class on the one hand is a simple container and utility class to handle TUIO positions in general,
|
||||
* on the other hand the TuioPoint is the base class for the TuioCursor and TuioObject classes.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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;
|
||||
|
||||
OneEuroFilter *xposFilter;
|
||||
OneEuroFilter *yposFilter;
|
||||
float posThreshold;
|
||||
|
||||
public:
|
||||
/**
|
||||
* The default constructor takes no arguments and sets
|
||||
* its coordinate attributes to zero and its time stamp to the current session time.
|
||||
*/
|
||||
TuioPoint (float xp, float yp);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual ~TuioPoint(){
|
||||
if (xposFilter) delete xposFilter;
|
||||
if (yposFilter) delete yposFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
void addPositionThreshold(float thresh);
|
||||
|
||||
void removePositionThreshold();
|
||||
|
||||
void addPositionFilter(float mcut, float beta);
|
||||
|
||||
void removePositionFilter();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
634
modules/touch/ext/libTUIO/TUIO/TuioServer.cpp
Normal file
634
modules/touch/ext/libTUIO/TUIO/TuioServer.cpp
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
using namespace osc;
|
||||
|
||||
TuioServer::TuioServer()
|
||||
:full_update (false)
|
||||
,periodic_update (false)
|
||||
,objectProfileEnabled (true)
|
||||
,cursorProfileEnabled (true)
|
||||
,blobProfileEnabled (true)
|
||||
,source_name (NULL)
|
||||
{
|
||||
OscSender *oscsend = new UdpSender();
|
||||
initialize(oscsend);
|
||||
}
|
||||
|
||||
TuioServer::TuioServer(const char *host, int port)
|
||||
:full_update (false)
|
||||
,periodic_update (false)
|
||||
,objectProfileEnabled (true)
|
||||
,cursorProfileEnabled (true)
|
||||
,blobProfileEnabled (true)
|
||||
,source_name (NULL)
|
||||
{
|
||||
OscSender *oscsend = new UdpSender(host,port);
|
||||
initialize(oscsend);
|
||||
}
|
||||
|
||||
TuioServer::TuioServer(OscSender *oscsend)
|
||||
:full_update (false)
|
||||
,periodic_update (false)
|
||||
,objectProfileEnabled (true)
|
||||
,cursorProfileEnabled (true)
|
||||
,blobProfileEnabled (true)
|
||||
,source_name (NULL)
|
||||
{
|
||||
initialize(oscsend);
|
||||
}
|
||||
|
||||
void TuioServer::initialize(OscSender *oscsend) {
|
||||
|
||||
senderList.push_back(oscsend);
|
||||
int size = oscsend->getBufferSize();
|
||||
oscBuffer = new char[size];
|
||||
oscPacket = new osc::OutboundPacketStream(oscBuffer,size);
|
||||
fullBuffer = new char[size];
|
||||
fullPacket = new osc::OutboundPacketStream(oscBuffer,size);
|
||||
|
||||
objectUpdateTime = TuioTime(currentFrameTime);
|
||||
cursorUpdateTime = TuioTime(currentFrameTime);
|
||||
blobUpdateTime = TuioTime(currentFrameTime);
|
||||
|
||||
if (cursorProfileEnabled) sendEmptyCursorBundle();
|
||||
if (objectProfileEnabled) sendEmptyObjectBundle();
|
||||
if (blobProfileEnabled) sendEmptyBlobBundle();
|
||||
|
||||
invert_x = false;
|
||||
invert_y = false;
|
||||
invert_a = false;
|
||||
}
|
||||
|
||||
TuioServer::~TuioServer() {
|
||||
|
||||
initFrame(TuioTime::getSessionTime());
|
||||
stopUntouchedMovingCursors();
|
||||
stopUntouchedMovingObjects();
|
||||
stopUntouchedMovingBlobs();
|
||||
|
||||
initFrame(TuioTime::getSessionTime());
|
||||
removeUntouchedStoppedCursors();
|
||||
removeUntouchedStoppedObjects();
|
||||
removeUntouchedStoppedBlobs();
|
||||
|
||||
if (cursorProfileEnabled) sendEmptyCursorBundle();
|
||||
if (objectProfileEnabled) sendEmptyObjectBundle();
|
||||
if (blobProfileEnabled) sendEmptyBlobBundle();
|
||||
|
||||
delete []oscBuffer;
|
||||
delete oscPacket;
|
||||
delete []fullBuffer;
|
||||
delete fullPacket;
|
||||
|
||||
if (source_name) delete[] source_name;
|
||||
for (unsigned int i=0;i<senderList.size();i++)
|
||||
delete senderList[i];
|
||||
}
|
||||
|
||||
|
||||
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 (size<oscPacket->Capacity()) {
|
||||
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;i<senderList.size();i++)
|
||||
senderList[i]->sendOscPacket(packet);
|
||||
}
|
||||
|
||||
void TuioServer::setSourceName(const char *name, const char *ip) {
|
||||
if (!source_name) source_name = new char[256];
|
||||
sprintf(source_name,"%s@%s",name,ip);
|
||||
}
|
||||
|
||||
|
||||
void TuioServer::setSourceName(const char *src) {
|
||||
|
||||
if (!source_name) source_name = new char[256];
|
||||
|
||||
/*if (senderList[0]->isLocal()) {
|
||||
sprintf(source_name,"%s",src);
|
||||
} else {*/
|
||||
char hostname[64];
|
||||
char *source_addr = NULL;
|
||||
struct hostent *hp = NULL;
|
||||
struct in_addr *addr = NULL;
|
||||
|
||||
gethostname(hostname, 64);
|
||||
hp = gethostbyname(hostname);
|
||||
|
||||
if (hp==NULL) {
|
||||
sprintf(hostname, "%s.local", hostname);
|
||||
hp = gethostbyname(hostname);
|
||||
}
|
||||
|
||||
if (hp!=NULL) {
|
||||
for (int i = 0; hp->h_addr_list[i] != 0; ++i) {
|
||||
addr = (struct in_addr *)(hp->h_addr_list[i]);
|
||||
//std::cout << inet_ntoa(*addr) << std::endl;
|
||||
source_addr = inet_ntoa(*addr);
|
||||
}
|
||||
} else {
|
||||
//generate a random internet address
|
||||
srand ( (unsigned int)time(NULL) );
|
||||
int32 r = rand();
|
||||
addr = (struct in_addr*)&r;
|
||||
source_addr = inet_ntoa(*addr);
|
||||
}
|
||||
sprintf(source_name,"%s@%s",src,source_addr);
|
||||
//}
|
||||
|
||||
std::cout << "tuio/src " << source_name << std::endl;
|
||||
}
|
||||
|
||||
void TuioServer::commitFrame() {
|
||||
TuioManager::commitFrame();
|
||||
|
||||
if(updateObject) {
|
||||
startObjectBundle();
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<OBJ_MESSAGE_SIZE) {
|
||||
sendObjectBundle(currentFrame);
|
||||
startObjectBundle();
|
||||
}
|
||||
TuioObject *tobj = (*tuioObject);
|
||||
if ((full_update) || (tobj->getTuioTime()==currentFrameTime)) addObjectMessage(tobj);
|
||||
}
|
||||
objectUpdateTime = TuioTime(currentFrameTime);
|
||||
sendObjectBundle(currentFrame);
|
||||
} else if (objectProfileEnabled && periodic_update) {
|
||||
|
||||
TuioTime timeCheck = currentFrameTime - objectUpdateTime;
|
||||
if(timeCheck.getSeconds()>=update_interval) {
|
||||
objectUpdateTime = TuioTime(currentFrameTime);
|
||||
startObjectBundle();
|
||||
if (full_update) {
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<OBJ_MESSAGE_SIZE) {
|
||||
sendObjectBundle(currentFrame);
|
||||
startObjectBundle();
|
||||
}
|
||||
addObjectMessage(*tuioObject);
|
||||
}
|
||||
}
|
||||
sendObjectBundle(currentFrame);
|
||||
}
|
||||
}
|
||||
updateObject = false;
|
||||
|
||||
if(updateCursor) {
|
||||
startCursorBundle();
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<CUR_MESSAGE_SIZE) {
|
||||
sendCursorBundle(currentFrame);
|
||||
startCursorBundle();
|
||||
}
|
||||
TuioCursor *tcur = (*tuioCursor);
|
||||
if ((full_update) || (tcur->getTuioTime()==currentFrameTime)) addCursorMessage(tcur);
|
||||
}
|
||||
cursorUpdateTime = TuioTime(currentFrameTime);
|
||||
sendCursorBundle(currentFrame);
|
||||
} else if (cursorProfileEnabled && periodic_update) {
|
||||
TuioTime timeCheck = currentFrameTime - cursorUpdateTime;
|
||||
if(timeCheck.getSeconds()>=update_interval) {
|
||||
cursorUpdateTime = TuioTime(currentFrameTime);
|
||||
startCursorBundle();
|
||||
if (full_update) {
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<CUR_MESSAGE_SIZE) {
|
||||
sendCursorBundle(currentFrame);
|
||||
startCursorBundle();
|
||||
}
|
||||
addCursorMessage(*tuioCursor);
|
||||
}
|
||||
}
|
||||
sendCursorBundle(currentFrame);
|
||||
}
|
||||
}
|
||||
updateCursor = false;
|
||||
|
||||
if(updateBlob) {
|
||||
startBlobBundle();
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob =blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<BLB_MESSAGE_SIZE) {
|
||||
sendBlobBundle(currentFrame);
|
||||
startBlobBundle();
|
||||
}
|
||||
TuioBlob *tblb = (*tuioBlob);
|
||||
if ((full_update) || (tblb->getTuioTime()==currentFrameTime)) addBlobMessage(tblb);
|
||||
}
|
||||
blobUpdateTime = TuioTime(currentFrameTime);
|
||||
sendBlobBundle(currentFrame);
|
||||
} else if (blobProfileEnabled && periodic_update) {
|
||||
TuioTime timeCheck = currentFrameTime - blobUpdateTime;
|
||||
if(timeCheck.getSeconds()>=update_interval) {
|
||||
blobUpdateTime = TuioTime(currentFrameTime);
|
||||
startBlobBundle();
|
||||
if (full_update) {
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob =blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((oscPacket->Capacity()-oscPacket->Size())<BLB_MESSAGE_SIZE) {
|
||||
sendBlobBundle(currentFrame);
|
||||
startBlobBundle();
|
||||
}
|
||||
addBlobMessage(*tuioBlob);
|
||||
}
|
||||
}
|
||||
sendBlobBundle(currentFrame);
|
||||
}
|
||||
}
|
||||
updateBlob = false;
|
||||
}
|
||||
|
||||
void TuioServer::sendEmptyCursorBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive" << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
void TuioServer::startCursorBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
if ((*tuioCursor)->getTuioState()!=TUIO_ADDED) (*oscPacket) << (int32)((*tuioCursor)->getSessionID());
|
||||
}
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::addCursorMessage(TuioCursor *tcur) {
|
||||
|
||||
if (tcur->getTuioState()==TUIO_ADDED) return;
|
||||
|
||||
float xpos = tcur->getX();
|
||||
float xvel = tcur->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = tcur->getY();
|
||||
float yvel = tcur->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "set";
|
||||
(*oscPacket) << (int32)(tcur->getSessionID()) << xpos << ypos;
|
||||
(*oscPacket) << xvel << yvel << tcur->getMotionAccel();
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::sendCursorBundle(long fseq) {
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << (int32)fseq << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
void TuioServer::sendEmptyObjectBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive" << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
void TuioServer::startObjectBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
(*oscPacket) << (int32)((*tuioObject)->getSessionID());
|
||||
}
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::addObjectMessage(TuioObject *tobj) {
|
||||
|
||||
float xpos = tobj->getX();
|
||||
float xvel = tobj->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = tobj->getY();
|
||||
float yvel = tobj->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
float angle = tobj->getAngle();
|
||||
float rvel = tobj->getRotationSpeed();
|
||||
if (invert_a) {
|
||||
angle = 2.0f*(float)M_PI - angle;
|
||||
rvel = -1 * rvel;
|
||||
}
|
||||
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "set";
|
||||
(*oscPacket) << (int32)(tobj->getSessionID()) << tobj->getSymbolID() << xpos << ypos << angle;
|
||||
(*oscPacket) << xvel << yvel << rvel << tobj->getMotionAccel() << tobj->getRotationAccel();
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::sendObjectBundle(long fseq) {
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << (int32)fseq << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
|
||||
void TuioServer::sendEmptyBlobBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "alive" << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "fseq" << -1 << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
void TuioServer::startBlobBundle() {
|
||||
oscPacket->Clear();
|
||||
(*oscPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "source" << source_name << osc::EndMessage;
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "alive";
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
if ((*tuioBlob)->getTuioState()!=TUIO_ADDED) (*oscPacket) << (int32)((*tuioBlob)->getSessionID());
|
||||
}
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::addBlobMessage(TuioBlob *tblb) {
|
||||
|
||||
if (tblb->getTuioState()==TUIO_ADDED) return;
|
||||
|
||||
float xpos = tblb->getX();
|
||||
float xvel = tblb->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = tblb->getY();
|
||||
float yvel = tblb->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
float angle = tblb->getAngle();
|
||||
float rvel = tblb->getRotationSpeed();
|
||||
if (invert_a) {
|
||||
angle = 2.0f*(float)M_PI - angle;
|
||||
rvel = -1 * rvel;
|
||||
}
|
||||
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "set";
|
||||
(*oscPacket) << (int32)(tblb->getSessionID()) << xpos << ypos << angle << tblb->getWidth() << tblb->getHeight() << tblb->getArea();
|
||||
(*oscPacket) << xvel << yvel << rvel << tblb->getMotionAccel() << tblb->getRotationAccel();
|
||||
(*oscPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
void TuioServer::sendBlobBundle(long fseq) {
|
||||
(*oscPacket) << osc::BeginMessage( "/tuio/2Dblb") << "fseq" << (int32)fseq << osc::EndMessage;
|
||||
(*oscPacket) << osc::EndBundle;
|
||||
|
||||
deliverOscPacket( oscPacket );
|
||||
}
|
||||
|
||||
void TuioServer::sendFullMessages() {
|
||||
|
||||
// prepare the cursor packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "source" << source_name << osc::EndMessage;
|
||||
// add the cursor alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++)
|
||||
(*fullPacket) << (int32)((*tuioCursor)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
|
||||
// add all current cursor set messages
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((fullPacket->Capacity()-fullPacket->Size())<CUR_MESSAGE_SIZE) {
|
||||
|
||||
// add the immediate fseq message and send the cursor packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
|
||||
// prepare the new cursor packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "source" << source_name << osc::EndMessage;
|
||||
// add the cursor alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "alive";
|
||||
for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++)
|
||||
(*fullPacket) << (int32)((*tuioCursor)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
float xpos = (*tuioCursor)->getX();
|
||||
float xvel = (*tuioCursor)->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = (*tuioCursor)->getY();
|
||||
float yvel = (*tuioCursor)->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
|
||||
// add the actual cursor set message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "set";
|
||||
(*fullPacket) << (int32)((*tuioCursor)->getSessionID()) << xpos << ypos;
|
||||
(*fullPacket) << xvel << yvel <<(*tuioCursor)->getMotionAccel();
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
// add the immediate fseq message and send the cursor packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dcur") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
|
||||
// prepare the object packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "source" << source_name << osc::EndMessage;
|
||||
// add the object alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++)
|
||||
(*fullPacket) << (int32)((*tuioObject)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((fullPacket->Capacity()-fullPacket->Size())<OBJ_MESSAGE_SIZE) {
|
||||
// add the immediate fseq message and send the object packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
|
||||
// prepare the new object packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "source" << source_name << osc::EndMessage;
|
||||
// add the object alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "alive";
|
||||
for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++)
|
||||
(*fullPacket) << (int32)((*tuioObject)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
float xpos = (*tuioObject)->getX();
|
||||
float xvel = (*tuioObject)->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = (*tuioObject)->getY();
|
||||
float yvel = (*tuioObject)->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
float angle = (*tuioObject)->getAngle();
|
||||
float rvel = (*tuioObject)->getRotationSpeed();
|
||||
if (invert_a) {
|
||||
angle = 2.0f*(float)M_PI - angle;
|
||||
rvel = -1 * rvel;
|
||||
}
|
||||
|
||||
// add the actual object set message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "set";
|
||||
(*fullPacket) << (int32)((*tuioObject)->getSessionID()) << (*tuioObject)->getSymbolID() << xpos << ypos << angle;
|
||||
(*fullPacket) << xvel << yvel << rvel << (*tuioObject)->getMotionAccel() << (*tuioObject)->getRotationAccel();
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
|
||||
}
|
||||
// add the immediate fseq message and send the object packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dobj") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
|
||||
// prepare the blob packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "source" << source_name << osc::EndMessage;
|
||||
// add the object alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "alive";
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++)
|
||||
(*fullPacket) << (int32)((*tuioBlob)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++) {
|
||||
|
||||
// start a new packet if we exceed the packet capacity
|
||||
if ((fullPacket->Capacity()-fullPacket->Size())<BLB_MESSAGE_SIZE) {
|
||||
// add the immediate fseq message and send the object packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
|
||||
// prepare the new blob packet
|
||||
fullPacket->Clear();
|
||||
(*fullPacket) << osc::BeginBundleImmediate;
|
||||
if (source_name) (*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "source" << source_name << osc::EndMessage;
|
||||
// add the blob alive message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "alive";
|
||||
for (std::list<TuioBlob*>::iterator tuioBlob = blobList.begin(); tuioBlob!=blobList.end(); tuioBlob++)
|
||||
(*fullPacket) << (int32)((*tuioBlob)->getSessionID());
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
}
|
||||
|
||||
float xpos = (*tuioBlob)->getX();
|
||||
float xvel = (*tuioBlob)->getXSpeed();
|
||||
if (invert_x) {
|
||||
xpos = 1 - xpos;
|
||||
xvel = -1 * xvel;
|
||||
}
|
||||
float ypos = (*tuioBlob)->getY();
|
||||
float yvel = (*tuioBlob)->getYSpeed();
|
||||
if (invert_y) {
|
||||
ypos = 1 - ypos;
|
||||
yvel = -1 * yvel;
|
||||
}
|
||||
float angle = (*tuioBlob)->getAngle();
|
||||
float rvel = (*tuioBlob)->getRotationSpeed();
|
||||
if (invert_a) {
|
||||
angle = 2.0f*(float)M_PI - angle;
|
||||
rvel = -1 * rvel;
|
||||
}
|
||||
|
||||
// add the actual blob set message
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "set";
|
||||
(*fullPacket) << (int32)((*tuioBlob)->getSessionID()) << xpos << ypos << angle << (*tuioBlob)->getWidth() << (*tuioBlob)->getHeight() << (*tuioBlob)->getArea();
|
||||
(*fullPacket) << xvel << yvel << rvel << (*tuioBlob)->getMotionAccel() << (*tuioBlob)->getRotationAccel();
|
||||
(*fullPacket) << osc::EndMessage;
|
||||
|
||||
}
|
||||
// add the immediate fseq message and send the blob packet
|
||||
(*fullPacket) << osc::BeginMessage( "/tuio/2Dblb") << "fseq" << -1 << osc::EndMessage;
|
||||
(*fullPacket) << osc::EndBundle;
|
||||
deliverOscPacket( fullPacket );
|
||||
}
|
||||
|
||||
|
||||
|
||||
230
modules/touch/ext/libTUIO/TUIO/TuioServer.h
Normal file
230
modules/touch/ext/libTUIO/TUIO/TuioServer.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 "TcpSender.h"
|
||||
#include "WebSockSender.h"
|
||||
#include "FlashSender.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace TUIO {
|
||||
/**
|
||||
* <p>The TuioServer class is the central TUIO protocol encoder component.
|
||||
* In order to encode and send TUIO messages an instance of TuioServer needs to be created. The TuioServer instance then generates TUIO 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.</p>
|
||||
* <p>During runtime the each frame is marked with the initFrame and commitFrame methods,
|
||||
* while the currently present TuioObjects are managed by the server with ADD, UPDATE and REMOVE methods in analogy to the TuioClient's TuioListener interface.</p>
|
||||
*<p>See the SimpleSimulator example project for further hints on how to use the TuioServer class and its various methods.
|
||||
* <p><code>
|
||||
* OscSender *sender = new UDPSender();</br>
|
||||
* TuioServer *server = new TuioServer(sender);<br/>
|
||||
* server->setSourceName("MyTuioSource"); // optional for TUIO 1.1<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* TuioObject *tobj = server->addTuioObject(xpos,ypos,angle);<br/>
|
||||
* TuioCursor *tcur = server->addTuiCursor(xpos,ypos);<br/>
|
||||
* TuioBlob *tblb = server->addTuioBlob(xpos,ypos,angle,width,height, area);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* server->updateTuioObject(tobj,xpos,ypos,angle);<br/>
|
||||
* server->updateTuioCursor(tcur,xpos,ypos);<br/>
|
||||
* server->updateTuioBlob(tblb,xpos,ypos,angle,width,height,area);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* ...<br/>
|
||||
* server->initFrame(TuioTime::getSessionTime());<br/>
|
||||
* server->removeTuioObject(tobj);<br/>
|
||||
* server->removeTuioCursor(tcur);<br/>
|
||||
* server->removeTuioBlob(tblb);<br/>
|
||||
* server->commitFrame();<br/>
|
||||
* </code></p>
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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, int 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 TuioObjects, TuioCursors and TuioBlobs
|
||||
*/
|
||||
void sendFullMessages();
|
||||
|
||||
/**
|
||||
* Enables the full update of all currently active and inactive TuioObjects, TuioCursors and TuioBlobs
|
||||
*
|
||||
*/
|
||||
void enableFullUpdate() {
|
||||
full_update = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the full update of all currently active and inactive TuioObjects, TuioCursors and TuioBlobs
|
||||
*/
|
||||
void disableFullUpdate() {
|
||||
full_update = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the full update of all currently active TuioObjects, TuioCursors and TuioBlobs is enabled.
|
||||
* @return true if the full update of all currently active TuioObjects, TuioCursors and TuioBlobs is enabled
|
||||
*/
|
||||
bool fullUpdateEnabled() {
|
||||
return full_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the periodic full update of all currently active TuioObjects TuioObjects, TuioCursors and TuioBlobs
|
||||
*
|
||||
* @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 TuioObjects, TuioCursors and TuioBlobs
|
||||
*/
|
||||
void disablePeriodicMessages() {
|
||||
periodic_update = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the periodic update of all currently active TuioObjects, TuioCursors and TuioBlobs is enabled.
|
||||
* @return true if the periodic update of all currently active TuioObjects, TuioCursors and TuioBlobs 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 TuioObjects, TuioCursors and TuioBlobs.
|
||||
*/
|
||||
void commitFrame();
|
||||
|
||||
/**
|
||||
* Commits the current frame.
|
||||
* Generates and sends TUIO messages of all currently active and updated TuioObjects, TuioCursors and TuioBlobs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the name of this TUIO source, which is transmitted within the /tuio/[profile] source message.
|
||||
*
|
||||
* @param name the desired name of this TUIO source
|
||||
*/
|
||||
void setSourceName(const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* Defines the name and IP address of this TUIO source, which is transmitted within the /tuio/[profile] source message.
|
||||
*
|
||||
* @param name the desired name of this TUIO source
|
||||
* @param ip the local IP address
|
||||
*/
|
||||
void setSourceName(const char *name, const char *ip);
|
||||
|
||||
|
||||
|
||||
void addOscSender(OscSender *sender);
|
||||
|
||||
void enableObjectProfile(bool flag) { objectProfileEnabled = flag; };
|
||||
void enableCursorProfile(bool flag) { cursorProfileEnabled = flag; };
|
||||
void enableBlobProfile(bool flag) { blobProfileEnabled = flag; };
|
||||
|
||||
private:
|
||||
|
||||
void initialize(OscSender *oscsend);
|
||||
|
||||
std::vector<OscSender*> senderList;
|
||||
void deliverOscPacket(osc::OutboundPacketStream *packet);
|
||||
|
||||
osc::OutboundPacketStream *oscPacket;
|
||||
char *oscBuffer;
|
||||
osc::OutboundPacketStream *fullPacket;
|
||||
char *fullBuffer;
|
||||
|
||||
void startObjectBundle();
|
||||
void addObjectMessage(TuioObject *tobj);
|
||||
void sendObjectBundle(long fseq);
|
||||
void sendEmptyObjectBundle();
|
||||
|
||||
void startCursorBundle();
|
||||
void addCursorMessage(TuioCursor *tcur);
|
||||
void sendCursorBundle(long fseq);
|
||||
void sendEmptyCursorBundle();
|
||||
|
||||
void startBlobBundle();
|
||||
void addBlobMessage(TuioBlob *tblb);
|
||||
void sendBlobBundle(long fseq);
|
||||
void sendEmptyBlobBundle();
|
||||
|
||||
int update_interval;
|
||||
bool full_update, periodic_update;
|
||||
TuioTime objectUpdateTime, cursorUpdateTime, blobUpdateTime ;
|
||||
bool objectProfileEnabled, cursorProfileEnabled, blobProfileEnabled;
|
||||
char *source_name;
|
||||
};
|
||||
}
|
||||
#endif /* INCLUDED_TuioServer_H */
|
||||
129
modules/touch/ext/libTUIO/TUIO/TuioTime.cpp
Normal file
129
modules/touch/ext/libTUIO/TUIO/TuioTime.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
189
modules/touch/ext/libTUIO/TUIO/TuioTime.h
Normal file
189
modules/touch/ext/libTUIO/TUIO/TuioTime.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
#define MSEC_SECOND 1000
|
||||
#define USEC_SECOND 1000000
|
||||
#define USEC_MILLISECOND 1000
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* The TuioTime class is a simple structure that is used to reprent the time that has elapsed since the session start.
|
||||
* The time is internally represented as seconds and fractions of microseconds which should be more than sufficient for gesture related timing requirements.
|
||||
* Therefore at the beginning of a typical TUIO session the static method initSession() will set the reference time for the session.
|
||||
* Another important static method getSessionTime will return a TuioTime object representing the time elapsed since the session start.
|
||||
* The class also provides various addtional convience method, which allow some simple time arithmetics.
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
class LIBDECL TuioTime {
|
||||
|
||||
private:
|
||||
long seconds;
|
||||
long micro_seconds;
|
||||
static long start_seconds;
|
||||
static long start_micro_seconds;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The default constructor takes no arguments and sets
|
||||
* the Seconds and Microseconds attributes of the newly created TuioTime both to zero.
|
||||
*/
|
||||
TuioTime ():seconds(0),micro_seconds(0) {};
|
||||
|
||||
/**
|
||||
* The destructor is doing nothing in particular.
|
||||
*/
|
||||
~TuioTime() {}
|
||||
|
||||
/**
|
||||
* This constructor takes the provided time represented in total Milliseconds
|
||||
* and assigs this value to the newly created TuioTime.
|
||||
*
|
||||
* @param msec the total time in Millseconds
|
||||
*/
|
||||
TuioTime (long msec);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This static method globally resets the TUIO session time.
|
||||
*/
|
||||
static void initSession();
|
||||
|
||||
/**
|
||||
* Returns the present TuioTime representing the time since session start.
|
||||
* @return the present TuioTime representing the time since session start
|
||||
*/
|
||||
static TuioTime getSessionTime();
|
||||
|
||||
/**
|
||||
* Returns the absolut TuioTime representing the session start.
|
||||
* @return the absolut TuioTime representing the session start
|
||||
*/
|
||||
static TuioTime getStartTime();
|
||||
|
||||
/**
|
||||
* Returns the absolut TuioTime representing the current system time.
|
||||
* @return the absolut TuioTime representing the current system time
|
||||
*/
|
||||
static TuioTime getSystemTime();
|
||||
};
|
||||
}
|
||||
#endif /* INCLUDED_TUIOTIME_H */
|
||||
92
modules/touch/ext/libTUIO/TUIO/UdpReceiver.cpp
Normal file
92
modules/touch/ext/libTUIO/TUIO/UdpReceiver.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
using namespace osc;
|
||||
|
||||
#ifndef WIN32
|
||||
static void* ClientThreadFunc( void* obj )
|
||||
#else
|
||||
static DWORD WINAPI ClientThreadFunc( LPVOID obj )
|
||||
#endif
|
||||
{
|
||||
static_cast<UdpReceiver*>(obj)->socket->Run();
|
||||
return 0;
|
||||
};
|
||||
|
||||
UdpReceiver::UdpReceiver(int 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;
|
||||
}
|
||||
|
||||
|
||||
77
modules/touch/ext/libTUIO/TUIO/UdpReceiver.h
Normal file
77
modules/touch/ext/libTUIO/TUIO/UdpReceiver.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO {
|
||||
|
||||
/**
|
||||
* The UdpReceiver provides the OscReceiver functionality for the UDP transport method
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 (int 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 */
|
||||
89
modules/touch/ext/libTUIO/TUIO/UdpSender.cpp
Normal file
89
modules/touch/ext/libTUIO/TUIO/UdpSender.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
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_size<MIN_UDP_SIZE) buffer_size = MIN_UDP_SIZE;
|
||||
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() {
|
||||
delete socket;
|
||||
}
|
||||
|
||||
bool UdpSender::isConnected() {
|
||||
if (socket==NULL) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UdpSender::sendOscPacket (osc::OutboundPacketStream *bundle) {
|
||||
if (socket==NULL) return false;
|
||||
if ( bundle->Size() > buffer_size ) return false;
|
||||
if ( bundle->Size() == 0 ) return false;
|
||||
|
||||
socket->Send( bundle->Data(), bundle->Size() );
|
||||
return true;
|
||||
}
|
||||
93
modules/touch/ext/libTUIO/TUIO/UdpSender.h
Normal file
93
modules/touch/ext/libTUIO/TUIO/UdpSender.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2005-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
|
||||
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 TUIO {
|
||||
|
||||
/**
|
||||
* The UdpSender implements the UDP transport method for OSC
|
||||
*
|
||||
* @author Martin Kaltenbrunner
|
||||
* @version 1.1.6
|
||||
*/
|
||||
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 */
|
||||
287
modules/touch/ext/libTUIO/TUIO/WebSockSender.cpp
Normal file
287
modules/touch/ext/libTUIO/TUIO/WebSockSender.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2009-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
WebSockSender (c) 2015 Florian Echtler <floe@butterbrot.org>
|
||||
|
||||
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 TUIO;
|
||||
|
||||
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<SOCKET>::iterator client;
|
||||
#else
|
||||
std::list<int>::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"
|
||||
"Access-Control-Allow-Origin: *\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;
|
||||
}
|
||||
|
||||
|
||||
121
modules/touch/ext/libTUIO/TUIO/WebSockSender.h
Normal file
121
modules/touch/ext/libTUIO/TUIO/WebSockSender.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
TUIO C++ Library
|
||||
Copyright (c) 2009-2016 Martin Kaltenbrunner <martin@tuio.org>
|
||||
WebSockSender (c) 2015 Florian Echtler <floe@butterbrot.org>
|
||||
|
||||
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 <Windows.h>
|
||||
#include <stdio.h>
|
||||
#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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
namespace TUIO {
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
159
modules/touch/ext/libTUIO/oscpack/CHANGES
Normal file
159
modules/touch/ext/libTUIO/oscpack/CHANGES
Normal file
@@ -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 <address, port>
|
||||
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()
|
||||
|
||||
34
modules/touch/ext/libTUIO/oscpack/LICENSE
Normal file
34
modules/touch/ext/libTUIO/oscpack/LICENSE
Normal file
@@ -0,0 +1,34 @@
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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.
|
||||
150
modules/touch/ext/libTUIO/oscpack/README
Normal file
150
modules/touch/ext/libTUIO/oscpack/README
Normal file
@@ -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 <rossb@audiomulch.com>
|
||||
|
||||
|
||||
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.
|
||||
|
||||
###
|
||||
52
modules/touch/ext/libTUIO/oscpack/TODO
Normal file
52
modules/touch/ext/libTUIO/oscpack/TODO
Normal file
@@ -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.
|
||||
|
||||
|
||||
|
||||
88
modules/touch/ext/libTUIO/oscpack/ip/IpEndpointName.cpp
Normal file
88
modules/touch/ext/libTUIO/oscpack/ip/IpEndpointName.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstdio>
|
||||
|
||||
#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, "<any>" );
|
||||
}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, "<any>:<any>" );
|
||||
}else{
|
||||
std::sprintf( s, "%d.%d.%d.%d:<any>",
|
||||
(int)((address >> 24) & 0xFF),
|
||||
(int)((address >> 16) & 0xFF),
|
||||
(int)((address >> 8) & 0xFF),
|
||||
(int)(address & 0xFF) );
|
||||
}
|
||||
}else{
|
||||
if( address == ANY_ADDRESS ){
|
||||
std::sprintf( s, "<any>:%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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
83
modules/touch/ext/libTUIO/oscpack/ip/IpEndpointName.h
Normal file
83
modules/touch/ext/libTUIO/oscpack/ip/IpEndpointName.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
56
modules/touch/ext/libTUIO/oscpack/ip/NetworkingUtils.h
Normal file
56
modules/touch/ext/libTUIO/oscpack/ip/NetworkingUtils.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
50
modules/touch/ext/libTUIO/oscpack/ip/PacketListener.h
Normal file
50
modules/touch/ext/libTUIO/oscpack/ip/PacketListener.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
47
modules/touch/ext/libTUIO/oscpack/ip/TimerListener.h
Normal file
47
modules/touch/ext/libTUIO/oscpack/ip/TimerListener.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
176
modules/touch/ext/libTUIO/oscpack/ip/UdpSocket.h
Normal file
176
modules/touch/ext/libTUIO/oscpack/ip/UdpSocket.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstring> // 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 */
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 "ip/NetworkingUtils.h"
|
||||
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
602
modules/touch/ext/libTUIO/oscpack/ip/posix/UdpSocket.cpp
Normal file
602
modules/touch/ext/libTUIO/oscpack/ip/posix/UdpSocket.cpp
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 "ip/UdpSocket.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h> // for sockaddr_in
|
||||
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring> // for memset
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "ip/PacketListener.h"
|
||||
#include "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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <winsock2.h> // this must come first to prevent errors with MSVC7
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
571
modules/touch/ext/libTUIO/oscpack/ip/win32/UdpSocket.cpp
Normal file
571
modules/touch/ext/libTUIO/oscpack/ip/win32/UdpSocket.cpp
Normal file
@@ -0,0 +1,571 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <winsock2.h> // this must come first to prevent errors with MSVC7
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // for timeGetTime()
|
||||
|
||||
#ifndef WINCE
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring> // for memset
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#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<HANDLE> events( socketListeners_.size() + 1, 0 );
|
||||
int j=0;
|
||||
for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
|
||||
i != socketListeners_.end(); ++i, ++j ){
|
||||
|
||||
HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
|
||||
events[j] = event;
|
||||
}
|
||||
|
||||
|
||||
events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
|
||||
|
||||
|
||||
// configure the timer queue
|
||||
double currentTimeMs = GetCurrentTimeMs();
|
||||
|
||||
// expiry time ms, listener
|
||||
std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
|
||||
for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
|
||||
i != timerListeners_.end(); ++i )
|
||||
timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
|
||||
std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
|
||||
|
||||
const int MAX_BUFFER_SIZE = 4098;
|
||||
char *data = new char[ MAX_BUFFER_SIZE ];
|
||||
IpEndpointName remoteEndpoint;
|
||||
|
||||
while( !break_ ){
|
||||
|
||||
double currentTimeMs = GetCurrentTimeMs();
|
||||
|
||||
DWORD waitTime = INFINITE;
|
||||
if( !timerQueue_.empty() ){
|
||||
|
||||
waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
|
||||
? timerQueue_.front().first - currentTimeMs
|
||||
: 0 );
|
||||
}
|
||||
|
||||
DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
|
||||
if( break_ )
|
||||
break;
|
||||
|
||||
if( waitResult != WAIT_TIMEOUT ){
|
||||
for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstring>
|
||||
#include <map>
|
||||
|
||||
#include "OscPacketListener.h"
|
||||
|
||||
|
||||
|
||||
namespace osc{
|
||||
|
||||
template< class T >
|
||||
class MessageMappingOscPacketListener : public OscPacketListener{
|
||||
public:
|
||||
typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&);
|
||||
|
||||
protected:
|
||||
void RegisterMessageFunction( const char *addressPattern, function_type f )
|
||||
{
|
||||
functions_.insert( std::make_pair( addressPattern, f ) );
|
||||
}
|
||||
|
||||
virtual void ProcessMessage( const osc::ReceivedMessage& m,
|
||||
const IpEndpointName& remoteEndpoint )
|
||||
{
|
||||
typename function_map_type::iterator i = functions_.find( m.AddressPattern() );
|
||||
if( i != functions_.end() )
|
||||
(dynamic_cast<T*>(this)->*(i->second))( m, remoteEndpoint );
|
||||
}
|
||||
|
||||
private:
|
||||
struct cstr_compare{
|
||||
bool operator()( const char *lhs, const char *rhs ) const
|
||||
{ return std::strcmp( lhs, rhs ) < 0; }
|
||||
};
|
||||
|
||||
typedef std::map<const char*, function_type, cstr_compare> function_map_type;
|
||||
function_map_type functions_;
|
||||
};
|
||||
|
||||
} // namespace osc
|
||||
|
||||
#endif /* INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H */
|
||||
62
modules/touch/ext/libTUIO/oscpack/osc/OscException.h
Normal file
62
modules/touch/ext/libTUIO/oscpack/osc/OscException.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <exception>
|
||||
|
||||
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 */
|
||||
127
modules/touch/ext/libTUIO/oscpack/osc/OscHostEndianness.h
Normal file
127
modules/touch/ext/libTUIO/oscpack/osc/OscHostEndianness.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
|
||||
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <malloc.h> // for alloca
|
||||
#else
|
||||
//#include <alloca.h> // alloca on Linux (also OSX)
|
||||
#include <stdlib.h> // alloca on OSX and FreeBSD (and Linux?)
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring> // memcpy, memmove, strcpy, strlen
|
||||
#include <cstddef> // 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<int32*>(p) = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void FromUInt32( char *p, uint32 x )
|
||||
{
|
||||
#ifdef OSC_HOST_LITTLE_ENDIAN
|
||||
union{
|
||||
osc::uint32 i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.i = x;
|
||||
|
||||
p[3] = u.c[0];
|
||||
p[2] = u.c[1];
|
||||
p[1] = u.c[2];
|
||||
p[0] = u.c[3];
|
||||
#else
|
||||
*reinterpret_cast<uint32*>(p) = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void FromInt64( char *p, int64 x )
|
||||
{
|
||||
#ifdef OSC_HOST_LITTLE_ENDIAN
|
||||
union{
|
||||
osc::int64 i;
|
||||
char c[8];
|
||||
} u;
|
||||
|
||||
u.i = x;
|
||||
|
||||
p[7] = u.c[0];
|
||||
p[6] = u.c[1];
|
||||
p[5] = u.c[2];
|
||||
p[4] = u.c[3];
|
||||
p[3] = u.c[4];
|
||||
p[2] = u.c[5];
|
||||
p[1] = u.c[6];
|
||||
p[0] = u.c[7];
|
||||
#else
|
||||
*reinterpret_cast<int64*>(p) = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void FromUInt64( char *p, uint64 x )
|
||||
{
|
||||
#ifdef OSC_HOST_LITTLE_ENDIAN
|
||||
union{
|
||||
osc::uint64 i;
|
||||
char c[8];
|
||||
} u;
|
||||
|
||||
u.i = x;
|
||||
|
||||
p[7] = u.c[0];
|
||||
p[6] = u.c[1];
|
||||
p[5] = u.c[2];
|
||||
p[4] = u.c[3];
|
||||
p[3] = u.c[4];
|
||||
p[2] = u.c[5];
|
||||
p[1] = u.c[6];
|
||||
p[0] = u.c[7];
|
||||
#else
|
||||
*reinterpret_cast<uint64*>(p) = x;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// 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<uint32*>(data_);
|
||||
|
||||
return beginPtr;
|
||||
|
||||
}else{
|
||||
// store an offset to the old element size ptr in the element size slot
|
||||
// we store an offset rather than the actual pointer to be 64 bit clean.
|
||||
*reinterpret_cast<uint32*>(beginPtr) =
|
||||
(uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_);
|
||||
|
||||
elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr);
|
||||
|
||||
return beginPtr + 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OutboundPacketStream::EndElement( char *endPtr )
|
||||
{
|
||||
assert( elementSizePtr_ != 0 );
|
||||
|
||||
if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){
|
||||
|
||||
elementSizePtr_ = 0;
|
||||
|
||||
}else{
|
||||
// while building an element, an offset to the containing element's
|
||||
// size slot is stored in the elements size slot (or a ptr to data_
|
||||
// if there is no containing element). We retrieve that here
|
||||
uint32 *previousElementSizePtr =
|
||||
reinterpret_cast<uint32*>(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<char*>(elementSizePtr_);
|
||||
// assert( d >= 4 && d <= 0x7FFFFFFF ); // assume packets smaller than 2Gb
|
||||
|
||||
uint32 elementSize = static_cast<uint32>(d - 4);
|
||||
FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );
|
||||
|
||||
// finally, we reset the element size ptr to the containing element
|
||||
elementSizePtr_ = previousElementSizePtr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool OutboundPacketStream::ElementSizeSlotRequired() const
|
||||
{
|
||||
return (elementSizePtr_ != 0);
|
||||
}
|
||||
|
||||
|
||||
void OutboundPacketStream::CheckForAvailableBundleSpace()
|
||||
{
|
||||
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<float*>(argumentCurrent_) = rhs;
|
||||
#endif
|
||||
|
||||
argumentCurrent_ += 4;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(4);
|
||||
|
||||
*(--typeTagsCurrent_) = CHAR_TYPE_TAG;
|
||||
FromInt32( argumentCurrent_, rhs );
|
||||
argumentCurrent_ += 4;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(4);
|
||||
|
||||
*(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
|
||||
FromUInt32( argumentCurrent_, rhs );
|
||||
argumentCurrent_ += 4;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(4);
|
||||
|
||||
*(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
|
||||
FromUInt32( argumentCurrent_, rhs );
|
||||
argumentCurrent_ += 4;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(8);
|
||||
|
||||
*(--typeTagsCurrent_) = INT64_TYPE_TAG;
|
||||
FromInt64( argumentCurrent_, rhs );
|
||||
argumentCurrent_ += 8;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(8);
|
||||
|
||||
*(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
|
||||
FromUInt64( argumentCurrent_, rhs );
|
||||
argumentCurrent_ += 8;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace(8);
|
||||
|
||||
*(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
|
||||
|
||||
#ifdef OSC_HOST_LITTLE_ENDIAN
|
||||
union{
|
||||
double f;
|
||||
char c[8];
|
||||
} u;
|
||||
|
||||
u.f = rhs;
|
||||
|
||||
argumentCurrent_[7] = u.c[0];
|
||||
argumentCurrent_[6] = u.c[1];
|
||||
argumentCurrent_[5] = u.c[2];
|
||||
argumentCurrent_[4] = u.c[3];
|
||||
argumentCurrent_[3] = u.c[4];
|
||||
argumentCurrent_[2] = u.c[5];
|
||||
argumentCurrent_[1] = u.c[6];
|
||||
argumentCurrent_[0] = u.c[7];
|
||||
#else
|
||||
*reinterpret_cast<double*>(argumentCurrent_) = rhs;
|
||||
#endif
|
||||
|
||||
argumentCurrent_ += 8;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
|
||||
{
|
||||
CheckForAvailableArgumentSpace( RoundUp4(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
|
||||
|
||||
|
||||
154
modules/touch/ext/libTUIO/oscpack/osc/OscOutboundPacketStream.h
Normal file
154
modules/touch/ext/libTUIO/oscpack/osc/OscOutboundPacketStream.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstring> // 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 */
|
||||
79
modules/touch/ext/libTUIO/oscpack/osc/OscPacketListener.h
Normal file
79
modules/touch/ext/libTUIO/oscpack/osc/OscPacketListener.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstring>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <iosfwd>
|
||||
|
||||
#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 */
|
||||
796
modules/touch/ext/libTUIO/oscpack/osc/OscReceivedElements.cpp
Normal file
796
modules/touch/ext/libTUIO/oscpack/osc/OscReceivedElements.cpp
Normal file
@@ -0,0 +1,796 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cstddef> // 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
|
||||
|
||||
548
modules/touch/ext/libTUIO/oscpack/osc/OscReceivedElements.h
Normal file
548
modules/touch/ext/libTUIO/oscpack/osc/OscReceivedElements.h
Normal file
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring> // 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<uint32>(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 */
|
||||
52
modules/touch/ext/libTUIO/oscpack/osc/OscTypes.cpp
Normal file
52
modules/touch/ext/libTUIO/oscpack/osc/OscTypes.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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
|
||||
240
modules/touch/ext/libTUIO/oscpack/osc/OscTypes.h
Normal file
240
modules/touch/ext/libTUIO/oscpack/osc/OscTypes.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
oscpack -- Open Sound Control (OSC) packet manipulation library
|
||||
http://www.rossbencina.com/code/oscpack
|
||||
|
||||
Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
|
||||
|
||||
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 */
|
||||
1
modules/touch/include.cmake
Normal file
1
modules/touch/include.cmake
Normal file
@@ -0,0 +1 @@
|
||||
set (DEFAULT_MODULE ON)
|
||||
80
modules/touch/include/TuioEar.h
Normal file
80
modules/touch/include/TuioEar.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/touch/ext/libTUIO/TUIO/TuioListener.h>
|
||||
#include <modules/touch/ext/libTUIO/TUIO/TuioClient.h>
|
||||
#include <modules/touch/ext/libTUIO/TUIO/UdpReceiver.h>
|
||||
#include <modules/touch/ext/libTUIO/TUIO/TcpReceiver.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace TUIO;
|
||||
|
||||
class TuioEar : public TuioListener {
|
||||
|
||||
public:
|
||||
TuioEar();
|
||||
~TuioEar() {
|
||||
_tuioClient->disconnect();
|
||||
delete _tuioClient;
|
||||
delete _oscReceiver;
|
||||
}
|
||||
|
||||
void addTuioObject(TuioObject *tobj);
|
||||
void updateTuioObject(TuioObject *tobj);
|
||||
void removeTuioObject(TuioObject *tobj);
|
||||
|
||||
void addTuioCursor(TuioCursor *tcur);
|
||||
void updateTuioCursor(TuioCursor *tcur);
|
||||
void removeTuioCursor(TuioCursor *tcur);
|
||||
|
||||
void addTuioBlob(TuioBlob *tblb);
|
||||
void updateTuioBlob(TuioBlob *tblb);
|
||||
void removeTuioBlob(TuioBlob *tblb);
|
||||
|
||||
void refresh(TuioTime frameTime);
|
||||
|
||||
std::vector<TuioCursor> getInput();
|
||||
void clearInput();
|
||||
|
||||
private:
|
||||
TuioClient *_tuioClient;
|
||||
OscReceiver *_oscReceiver;
|
||||
|
||||
std::vector<TuioCursor> _list;
|
||||
std::vector<int> _removeList;
|
||||
std::mutex _mx;
|
||||
};
|
||||
|
||||
#endif // __OPENSPACE_MODULE_TOUCH___TOUCHWRAPPER___H__
|
||||
150
modules/touch/src/TuioEar.cpp
Normal file
150
modules/touch/src/TuioEar.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/touch/include/TuioEar.h>
|
||||
#include <vector>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/settingsengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TuioEar";
|
||||
}
|
||||
|
||||
void TuioEar::addTuioObject(TuioObject *tobj) {
|
||||
//std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/" << tobj->getTuioSourceID() << ") " << tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
|
||||
}
|
||||
|
||||
void TuioEar::updateTuioObject(TuioObject *tobj) {
|
||||
//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;
|
||||
}
|
||||
|
||||
void TuioEar::removeTuioObject(TuioObject *tobj) {
|
||||
//std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/" << tobj->getTuioSourceID() << ")" << std::endl;
|
||||
}
|
||||
|
||||
void TuioEar::addTuioCursor(TuioCursor *tcur) {
|
||||
_mx.lock();
|
||||
|
||||
// find same id in _list if it exists in _removeList (new input with same ID as a previously stored)
|
||||
int i = tcur->getSessionID();
|
||||
std::vector<int>::iterator foundID = std::find_if(
|
||||
_removeList.begin(),
|
||||
_removeList.end(),
|
||||
[&i](int id) { return id == i; });
|
||||
|
||||
// if found, remove id from _removeList and update, otherwise add new id to list
|
||||
if (foundID != _removeList.end()) {
|
||||
std::find_if(
|
||||
_list.begin(),
|
||||
_list.end(),
|
||||
[&i](const TuioCursor& cursor) {
|
||||
return cursor.getSessionID() == i;
|
||||
})->update(tcur);
|
||||
_removeList.erase(foundID);
|
||||
}
|
||||
else
|
||||
_list.push_back(TuioCursor(*tcur));
|
||||
|
||||
_mx.unlock();
|
||||
}
|
||||
|
||||
void TuioEar::updateTuioCursor(TuioCursor *tcur) {
|
||||
_mx.lock();
|
||||
int i = tcur->getSessionID();
|
||||
std::find_if(
|
||||
_list.begin(),
|
||||
_list.end(),
|
||||
[&i](const TuioCursor& cursor) {
|
||||
return cursor.getSessionID() == i;
|
||||
})->update(tcur);
|
||||
_mx.unlock();
|
||||
}
|
||||
|
||||
// save id to be removed and remove it in clearInput
|
||||
void TuioEar::removeTuioCursor(TuioCursor *tcur) {
|
||||
_mx.lock();
|
||||
_removeList.push_back(tcur->getSessionID());
|
||||
//LINFO("To be removed: " << _removeFromList.size() << "\n");
|
||||
_mx.unlock();
|
||||
}
|
||||
|
||||
void TuioEar::addTuioBlob(TuioBlob *tblb) {
|
||||
std::cout << "add blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << "/" << tblb->getTuioSourceID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea() << std::endl;
|
||||
}
|
||||
|
||||
void TuioEar::updateTuioBlob(TuioBlob *tblb) {
|
||||
std::cout << "set blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << "/" << tblb->getTuioSourceID() << ") " << tblb->getX() << " " << tblb->getY() << " " << tblb->getAngle() << " " << tblb->getWidth() << " " << tblb->getHeight() << " " << tblb->getArea()
|
||||
<< " " << tblb->getMotionSpeed() << " " << tblb->getRotationSpeed() << " " << tblb->getMotionAccel() << " " << tblb->getRotationAccel() << std::endl;
|
||||
}
|
||||
|
||||
void TuioEar::removeTuioBlob(TuioBlob *tblb) {
|
||||
std::cout << "del blb " << tblb->getBlobID() << " (" << tblb->getSessionID() << "/" << tblb->getTuioSourceID() << ")" << std::endl;
|
||||
}
|
||||
|
||||
void TuioEar::refresh(TuioTime frameTime) {
|
||||
//LINFO("refresh " << frameTime.getTotalMilliseconds() << "\n"); // about every 15ms on TuioPad app
|
||||
}
|
||||
|
||||
std::vector<TuioCursor> TuioEar::getInput() {
|
||||
std::lock_guard<std::mutex> lock(_mx);
|
||||
return _list;
|
||||
}
|
||||
|
||||
void TuioEar::clearInput() {
|
||||
_mx.lock();
|
||||
_list.erase(
|
||||
std::remove_if(
|
||||
_list.begin(),
|
||||
_list.end(),
|
||||
[this](const TuioCursor& cursor) {
|
||||
return std::find_if(
|
||||
_removeList.begin(),
|
||||
_removeList.end(),
|
||||
[&cursor](int id) {\
|
||||
return cursor.getSessionID() == id;
|
||||
}
|
||||
) != _removeList.end();
|
||||
}),
|
||||
_list.end()
|
||||
);
|
||||
_removeList.clear();
|
||||
_mx.unlock();
|
||||
}
|
||||
|
||||
TuioEar::TuioEar() {
|
||||
_oscReceiver = new UdpReceiver(3333);
|
||||
//oscReceiver = new TcpReceiver("127.0.0.1",3333);
|
||||
_tuioClient = new TuioClient(_oscReceiver);
|
||||
_tuioClient->addTuioListener(this);
|
||||
_tuioClient->connect();
|
||||
}
|
||||
200
modules/touch/touchmodule.cpp
Normal file
200
modules/touch/touchmodule.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <modules/touch/touchmodule.h>
|
||||
#include <modules/touch/include/TuioEar.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/settingsengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <thread> // std::this_thread::sleep_for
|
||||
#include <chrono> // std::chrono::seconds
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TouchModule";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
TuioEar TouchModule::*ear;
|
||||
|
||||
|
||||
|
||||
bool TouchModule::gotNewInput() {
|
||||
// Get new input from listener
|
||||
list = ear->getInput();
|
||||
ear->clearInput();
|
||||
|
||||
// Erase old input id's that no longer exists
|
||||
lastProcessed.erase(
|
||||
std::remove_if(
|
||||
lastProcessed.begin(),
|
||||
lastProcessed.end(),
|
||||
[this](const Point& point) {
|
||||
return std::find_if(
|
||||
list.begin(),
|
||||
list.end(),
|
||||
[&point](const TuioCursor& c) {
|
||||
return point.first == c.getSessionID();
|
||||
}
|
||||
) == list.end(); }),
|
||||
lastProcessed.end()
|
||||
);
|
||||
|
||||
// Return true if we got new input
|
||||
if (list.size() == lastProcessed.size() && list.size() > 0) {
|
||||
for (Point& p : lastProcessed) {
|
||||
std::vector<TuioCursor>::iterator foundID = find_if(list.begin(), list.end(), [&p](const TuioCursor& c) { return c.getSessionID() == p.first; });
|
||||
if (p.second.getTuioTime() == foundID->getPath().back().getTuioTime())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
TouchModule::TouchModule()
|
||||
: OpenSpaceModule("Touch")
|
||||
{
|
||||
|
||||
OsEng.registerModuleCallback(
|
||||
OpenSpaceEngine::CallbackOption::Initialize,
|
||||
[&]() {
|
||||
LDEBUGC("TouchModule", "Initializing TuioEar");
|
||||
ear = new TuioEar();
|
||||
}
|
||||
);
|
||||
|
||||
OsEng.registerModuleCallback(
|
||||
OpenSpaceEngine::CallbackOption::Deinitialize,
|
||||
[&]() {
|
||||
LDEBUGC("TouchModule", "Deinitialize TuioEar");
|
||||
delete ear;
|
||||
}
|
||||
);
|
||||
|
||||
OsEng.registerModuleCallback( // maybe call ear->clearInput() here rather than postdraw
|
||||
OpenSpaceEngine::CallbackOption::PreSync,
|
||||
[&]() {
|
||||
if (OsEng.isMaster() && gotNewInput()) {
|
||||
//std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
|
||||
Camera* cam = OsEng.interactionHandler().camera();
|
||||
glm::vec3 pos = cam->positionVec3();
|
||||
glm::vec3 focusDir = glm::normalize(glm::vec3(cam->focusPositionVec3()) - pos);
|
||||
|
||||
glm::vec2 centroid;
|
||||
float distance = 0.0f;
|
||||
float lastDistance = 0.0f;
|
||||
float zoomFactor = 0.0f;
|
||||
|
||||
if (list.size() > 1) { // calculate centroid if we have multiple IDs
|
||||
centroid.x = std::accumulate(list.begin(), list.end(), 0.0f, [](float x, const TuioCursor& c) { return x + c.getX(); }) / list.size();
|
||||
centroid.y = std::accumulate(list.begin(), list.end(), 0.0f, [](float y, const TuioCursor& c) { return y + c.getY(); }) / list.size();
|
||||
|
||||
|
||||
|
||||
|
||||
// ------- testing, should use more than just one point later on
|
||||
distance = std::accumulate(list.begin(), list.end(), 0.0f, [¢roid](float d, const TuioCursor& c) {
|
||||
return d + sqrt(pow(c.getX() - centroid.x, 2) + pow(c.getY() - centroid.y, 2));
|
||||
});
|
||||
lastDistance = std::accumulate(lastProcessed.begin(), lastProcessed.end(), 0.0f, [¢roid](float d, const Point& p) {
|
||||
return d + sqrt(pow(p.second.getX() - centroid.x, 2) + pow(p.second.getY() - centroid.y, 2));
|
||||
});
|
||||
zoomFactor = distance - lastDistance; // should be dependant on screen size, distance from focusNode
|
||||
zoomFactor *= glm::distance(pos, glm::vec3(cam->focusPositionVec3()));
|
||||
|
||||
std::cout << "Distance: " << distance << ", Last Distance: " << lastDistance << ", zoomFactor: " << zoomFactor
|
||||
<< "\n";
|
||||
|
||||
glm::vec3 newPos = pos + focusDir*zoomFactor;
|
||||
cam->setPosition(newPos);
|
||||
}
|
||||
else { // do new rotation, work with spherical coordinates. Orbit it both position and rotation, check OrbitInteractionMode in interactionmode
|
||||
//cam->rotate(rot);
|
||||
}
|
||||
// ----------------
|
||||
|
||||
|
||||
std::ostringstream os; // for debugging
|
||||
|
||||
for (const TuioCursor &j : list) { // go through each item
|
||||
std::list<TuioPoint> path = j.getPath();
|
||||
|
||||
TuioTime lastTime = find_if(
|
||||
lastProcessed.begin(),
|
||||
lastProcessed.end(),
|
||||
[&j](const Point& p) { return p.first == j.getSessionID(); }
|
||||
)->second.getTuioTime();
|
||||
|
||||
std::list<TuioPoint>::iterator lastPoint = find_if(
|
||||
path.begin(),
|
||||
path.end(),
|
||||
[&lastTime](const TuioPoint& c) { return lastTime == c.getTuioTime(); });
|
||||
|
||||
int count = 0;
|
||||
for (; lastPoint != path.end(); ++lastPoint) // here we can access all elements that are to be processed
|
||||
count++;
|
||||
|
||||
os << ", Id: " << j.getCursorID() << ", path size: " << j.getPath().size() << ", (" << j.getX() << "," << j.getY() << "), To Process: " << count;
|
||||
|
||||
}
|
||||
LINFO("List size: " << list.size() << os.str() << "\n");
|
||||
os.clear();
|
||||
|
||||
}
|
||||
|
||||
// update lastProcessed
|
||||
lastProcessed.clear();
|
||||
for (const TuioCursor& c : list) {
|
||||
lastProcessed.push_back(std::make_pair(c.getSessionID(), c.getPath().back()));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
OsEng.registerModuleCallback(
|
||||
OpenSpaceEngine::CallbackOption::PostDraw,
|
||||
[&]() {
|
||||
WindowWrapper& wrapper = OsEng.windowWrapper();
|
||||
if (OsEng.isMaster() && wrapper.isRegularRendering()) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
51
modules/touch/touchmodule.h
Normal file
51
modules/touch/touchmodule.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <openspace/util/openspacemodule.h>
|
||||
#include <modules/touch/include/TuioEar.h>
|
||||
|
||||
//using Point = std::vector<TuioCursor>::iterator;
|
||||
|
||||
using Point = std::pair<int, TuioPoint>;
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class TouchModule : public OpenSpaceModule {
|
||||
public:
|
||||
TouchModule();
|
||||
|
||||
bool gotNewInput();
|
||||
|
||||
TuioEar *ear;
|
||||
std::vector<TuioCursor> list;
|
||||
std::vector<Point> lastProcessed; // contains an id and the TuioPoint that was processed last frame
|
||||
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__
|
||||
@@ -23,7 +23,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",
|
||||
|
||||
@@ -201,7 +201,7 @@ Interpolator<double>& InteractionMode::rotateToFocusNodeInterpolator() {
|
||||
|
||||
|
||||
// KeyframeInteractionMode
|
||||
KeyframeInteractionMode::KeyframeInteractionMode(){
|
||||
KeyframeInteractionMode::KeyframeInteractionMode() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user