new touch module with TUIO library to make OpenSpace tuio-aware

This commit is contained in:
Jonathan Bosson
2017-02-16 12:52:39 -07:00
parent 729bffb0f9
commit 5e84b7f6a2
84 changed files with 14625 additions and 13 deletions

View File

@@ -33,6 +33,8 @@
#include <chrono>
#include <thread>
#include <modules/touch/include/TuioEar.h>
sgct::Engine* _sgctEngine;
void mainInitFunc();
@@ -84,6 +86,8 @@ namespace {
int main(int argc, char** argv) {
auto glVersion = supportedOpenGLVersion();
TuioEar *ear = new TuioEar();
// create the OpenSpace engine and get arguments for the sgct engine
std::vector<std::string> sgctArguments;
const bool success = openspace::OpenSpaceEngine::create(

View File

@@ -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",

View File

@@ -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",

View File

@@ -1,4 +1,4 @@
UseAccurateNewHorizonsKernels = true
UseAccurateNewHorizonsKernels = false
-- TextureResolution = "low"
TextureResolution = "med"
-- TextureResolution = "high"

View File

@@ -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) {

View File

@@ -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;

View 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} libTUIO2 ${CMAKE_CURRENT_SOURCE_DIR}/ext/libTUIO2)

Binary file not shown.

View File

@@ -0,0 +1,63 @@
#########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2016 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
# without restriction, including without limitation the rights to use, copy, modify, #
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the following #
# conditions: #
# #
# The above copyright notice and this permission notice shall be included in all copies #
# or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A #
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT #
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF #
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE #
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
#########################################################################################
project(libTUIO2)
message(STATUS "Generating libTUIO2 project")
add_library(libTUIO2
${PROJECT_SOURCE_DIR}/TUIO2/WebSockSender.cpp
${PROJECT_SOURCE_DIR}/TUIO2/UdpSender.cpp
${PROJECT_SOURCE_DIR}/TUIO2/UdpReceiver.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioToken.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioTime.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioSymbol.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioServer.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioPointer.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioPoint.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioObject.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioManager.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioDispatcher.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioComponent.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioClient.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TuioBounds.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TcpSender.cpp
${PROJECT_SOURCE_DIR}/TUIO2/TcpReceiver.cpp
${PROJECT_SOURCE_DIR}/TUIO2/OscReceiver.cpp
${PROJECT_SOURCE_DIR}/TUIO2/FlashSender.cpp
${PROJECT_SOURCE_DIR}/oscpack/ip/IpEndpointName.cpp
#if (WIN32)
${PROJECT_SOURCE_DIR}/oscpack/ip/win32/NetworkingUtils.cpp
${PROJECT_SOURCE_DIR}/oscpack/ip/win32/UdpSocket.cpp
#else (WIN32)
#${PROJECT_SOURCE_DIR}/oscpack/ip/posix/NetworkingUtils.cpp
#${PROJECT_SOURCE_DIR}/oscpack/ip/posix/UdpSocket.cpp
#endif ()
${PROJECT_SOURCE_DIR}/oscpack/osc/OscTypes.cpp
${PROJECT_SOURCE_DIR}/oscpack/osc/OscReceivedElements.cpp
${PROJECT_SOURCE_DIR}/oscpack/osc/OscPrintReceivedElements.cpp
${PROJECT_SOURCE_DIR}/oscpack/osc/OscOutboundPacketStream.cpp
)
target_include_directories(libTUIO2 PUBLIC ${PROJECT_SOURCE_DIR})

View File

@@ -0,0 +1,15 @@
# Doxyfile 1.5.6
# Project related configuration options
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "TUIO2 C++ Developer API"
# Build related configuration options
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
# configuration options related to the HTML output
GENERATE_HTML = YES
HTML_OUTPUT = ../doc
HTML_FILE_EXTENSION = .html
GENERATE_TREEVIEW = YES
GENERATE_LATEX = NO

View 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 TUIO2;
FlashSender::FlashSender() {
local = true;
buffer_size = MAX_FLASH_SIZE;
lcConnection = TFLCSConnect(DEFAULT_LC_CONN_NAME,DEFAULT_LC_METH_NAME,NULL,NULL);
std::cout << "TUIO/FLC "<< DEFAULT_LC_METH_NAME << "@" << DEFAULT_LC_CONN_NAME << std::endl;
}
FlashSender::FlashSender(const char *conn_name, const char *meth_name) {
local = true;
buffer_size = MAX_FLASH_SIZE;
lcConnection = TFLCSConnect(conn_name,meth_name,NULL,NULL);
std::cout << "TUIO/FLC "<< meth_name << "@" << conn_name << std::endl;
}
FlashSender::~FlashSender() {
TFLCSDisconnect(lcConnection);
}
bool FlashSender::isConnected() {
if (TFLCSConnectionHasConnectedClient(lcConnection)) return true;
else return false;
}
bool FlashSender::sendOscPacket (osc::OutboundPacketStream *bundle) {
if (lcConnection==NULL)return false;
if (!TFLCSConnectionHasConnectedClient(lcConnection))return false;
if ( bundle->Size() > buffer_size ) return false;
if ( bundle->Size() == 0 ) return false;
TFLCSSendByteArray(lcConnection, bundle->Data(), bundle->Size());
return true;
}

View 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 TUIO2 {
/**
* The FlashSender implements the Flash LocalConnection transport method for OSC
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL FlashSender : public OscSender {
public:
/**
* The default constructor creates a FlashSender using a Flash LocalConnection on localhost
*/
FlashSender();
/**
* The default constructor creates a FlashSender using a Flash LocalConnection on localhost
*/
FlashSender(const char *conn_name, const char *meth_name);
/**
* The destructor closes the connection.
*/
virtual ~FlashSender();
/**
* This method delivers the provided OSC data
*
* @param *bundle the OSC stream to deliver
* @return true if the data was delivered successfully
*/
bool sendOscPacket (osc::OutboundPacketStream *bundle);
/**
* This method returns the connection state
*
* @return true if the connection is alive
*/
bool isConnected ();
const char* tuio_type() { return "TUIO/FLC"; }
private:
TFLCSLocalConnection_t* lcConnection;
};
}
#endif /* INCLUDED_FLASHSENDER_H */

View 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

View File

@@ -0,0 +1,60 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
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);
}

View File

@@ -0,0 +1,97 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2 {
class TuioClient; // Forward declaration
/**
* The OscReceiver is the base class for the various OSC transport methods such as UDP, TCP ...
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL OscReceiver: public PacketListener {
public:
/**
* The constructor is doing nothing in particular.
*/
OscReceiver() : connected(false) {};
/**
* The destructor is doing nothing in particular.
*/
virtual ~OscReceiver() {};
/**
* The OscReceiver connects and starts receiving TUIO messages via OSC
*
* @param lock running in the background if set to false (default)
*/
virtual void connect(bool lock=false) = 0;
/**
* The OscReceiver disconnects and stops receiving TUIO messages via OSC
*/
virtual void disconnect() = 0;
/**
* Returns true if this OscReceiver is currently connected.
* @return true if this OscReceiver is currently connected
*/
bool isConnected();
/**
* Attaches the provided TuioClient to this OscReceiver
*
* @param client a pointer to the TuioClient to attach
*/
void addTuioClient(TuioClient *client);
/**
* The OSC callback method where the incoming OSC data is received
*
* @param data the received OSC data
* @param size the size of the received OSC data
* @param remoteEndpoint the origin of the received OSC data
*/
void ProcessPacket( const char *data, int size, const IpEndpointName &remoteEndpoint );
protected:
void ProcessBundle( const osc::ReceivedBundle& b, const IpEndpointName& remoteEndpoint);
void ProcessMessage( const osc::ReceivedMessage& message, const IpEndpointName& remoteEndpoint);
std::list<TuioClient*> clientList;
bool connected;
};
};
#endif /* INCLUDED_OSCRECEIVER_H */

View File

@@ -0,0 +1,90 @@
/*
TUIO2 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 TUIO2 {
/**
* The OscSender class is the base class for the various OSC transport methods such as UDP, TCP ...
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL OscSender {
public:
/**
* The constructor is doing nothing in particular.
*/
OscSender (): local(true) {};
/**
* The destructor is doing nothing in particular.
*/
virtual ~OscSender() {}
/**
* This method delivers the provided OSC data
*
* @param *bundle the OSC stream to deliver
* @return true if the data was delivered successfully
*/
virtual bool sendOscPacket (osc::OutboundPacketStream *bundle) = 0;
/**
* This method returns the connection state
*
* @return true if the connection is alive
*/
virtual bool isConnected () = 0;
/**
* This method returns if this OscSender delivers locally
*
* @return true if this OscSender delivers locally
*/
bool isLocal () { return local; };
/**
* This method returns the maximum bundle size in bytes
*
* @return the maximum bundle size in bytes
*/
int getBufferSize () { return buffer_size; };
virtual const char* tuio_type() = 0;
protected:
unsigned int buffer_size;
bool local;
};
}
#endif /* INCLUDED_OSCSENDER_H */

View File

@@ -0,0 +1,264 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
using namespace osc;
// workaround for connect method name conflict
int tcp_connect(int socket, const struct sockaddr *address, socklen_t address_len) {
return connect(socket, address, address_len);
}
#if defined (WIN32) && not defined (int32_t)
typedef DWORD int32_t;
#endif
#ifdef WIN32
static DWORD WINAPI ClientThreadFunc( LPVOID obj )
#else
static void* ClientThreadFunc( void* obj )
#endif
{
TcpReceiver *sender = static_cast<TcpReceiver*>(obj);
char data_buffer[MAX_TCP_SIZE+4];
char data_size[4];
#ifdef WIN32
SOCKET client = sender->tcp_client_list.back();
#else
int client = sender->tcp_client_list.back();
#endif
int bytes = 1;
while (bytes) {
bytes = recv(client, data_buffer, sizeof(data_buffer),0);
if (bytes>=4) {
memcpy(&data_size[0],&data_buffer[0], 4);
#ifdef OSC_HOST_LITTLE_ENDIAN
int32_t temp = (int32_t)(*data_size);
data_size[0] = temp>>24;
data_size[1] = (temp>>16) & 255;
data_size[2] = (temp>>8) & 255;
data_size[3] = (temp) & 255;
#endif
int32_t size = (int32_t)(*data_size);
if (size+4==bytes) {
sender->ProcessPacket(&data_buffer[4],(int)size,IpEndpointName());
}
}
}
sender->tcp_client_list.remove(client);
std::cout << "closed TUIO/TCP connection" << std::endl;
//if (sender->tcp_client_list.size()==0) sender->connected=false;
//std::cout << sender->tcp_client_list.size() << " clients left"<< std::endl;
return 0;
};
#ifndef WIN32
static void* ServerThreadFunc( void* obj )
#else
static DWORD WINAPI ServerThreadFunc( LPVOID obj )
#endif
{
TcpReceiver *sender = static_cast<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(unsigned short port)
: tcp_socket (-1)
, locked (false)
{
tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcp_socket < 0) std::cerr << "could not create TUIO/TCP socket" << std::endl;
int optval = 1;
#ifdef WIN32
int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const char *)&optval, sizeof(int));
#else
int ret = setsockopt(tcp_socket,SOL_SOCKET,SO_REUSEADDR, (const void *)&optval, sizeof(int));
#endif
if (ret < 0) {
std::cerr << "could not reuse TUIO/TCP socket address" << std::endl;
return;
}
struct sockaddr_in tcp_server;
memset( &tcp_server, 0, sizeof (tcp_server));
tcp_server.sin_family = AF_INET;
tcp_server.sin_addr.s_addr = htonl(INADDR_ANY);
tcp_server.sin_port = htons(port);
socklen_t len = sizeof(tcp_server);
ret = bind(tcp_socket,(struct sockaddr*)&tcp_server,len);
if (ret < 0) {
std::cerr << "could not bind to TUIO/TCP socket on port " << port << std::endl;
return;
}
ret = listen(tcp_socket, 1);
if (ret < 0) {
std::cerr << "could not start listening to TUIO/TCP socket" << std::endl;
#ifdef WIN32
closesocket(tcp_socket);
#else
close(tcp_socket);
#endif
tcp_socket=-1;
return;
}
std::cout << "TUIO/TCP socket created on port " << port << std::endl;
}
TcpReceiver::TcpReceiver(const char *host, unsigned short port)
: tcp_socket (-1)
, locked (false)
{
tcp_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcp_socket < 0) {
std::cerr << "could not create TUIO/TCP socket" << std::endl;
return;
}
struct sockaddr_in tcp_server;
memset( &tcp_server, 0, sizeof (tcp_server));
unsigned long addr = inet_addr(host);
if (addr != INADDR_NONE) {
memcpy( (char *)&tcp_server.sin_addr, &addr, sizeof(addr));
} else {
struct hostent *host_info = gethostbyname(host);
if (host_info == NULL) std::cerr << "unknown host name: " << host << std::endl;
memcpy( (char *)&tcp_server.sin_addr, host_info->h_addr, host_info->h_length );
}
tcp_server.sin_family = AF_INET;
tcp_server.sin_port = htons(port);
int ret = tcp_connect(tcp_socket,(struct sockaddr*)&tcp_server,sizeof(tcp_server));
if (ret<0) {
#ifdef WIN32
closesocket(tcp_socket);
#else
close(tcp_socket);
#endif
std::cerr << "could not connect to TUIO/TCP server at " << host << ":"<< port << std::endl;
tcp_socket=-1;
return;
} else {
tcp_client_list.push_back(tcp_socket);
std::cout << "listening to TUIO/TCP messages from " << host << ":" << port << std::endl;
}
}
TcpReceiver::~TcpReceiver() {
}
void TcpReceiver::connect(bool lk) {
if (connected) return;
if ((int)tcp_socket<0) return;
locked = lk;
if (tcp_client_list.size()>0) {
if (!locked) {
#ifndef WIN32
pthread_create(&server_thread , NULL, ClientThreadFunc, this);
#else
server_thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &ServerThreadId );
#endif
} else ClientThreadFunc(this);
} else {
if (!locked) {
#ifndef WIN32
pthread_create(&server_thread , NULL, ServerThreadFunc, this);
#else
server_thread = CreateThread( 0, 0, ServerThreadFunc, this, 0, &ServerThreadId );
#endif
} else ServerThreadFunc(this);
}
connected = true;
}
void TcpReceiver::disconnect() {
if (!connected) return;
if ((int)tcp_socket<0) return;
#ifdef WIN32
for (std::list<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;
}

View File

@@ -0,0 +1,102 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2 {
/**
* The TcpReceiver provides the OscReceiver functionality for the TCP transport method
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TcpReceiver: public OscReceiver {
public:
/**
* This constructor creates a TcpReceiver instance listening to the provided TCP port
*
* @param port the number of the TCP port to listen to, defaults to 3333
*/
TcpReceiver (unsigned short port=3333);
/**
* This constructor creates a TcpReceiver connected to the provided host and TCP port
*
* @param host the host name to connect
* @param port the number of the TCP port to listen to, defaults to 3333
*/
TcpReceiver (const char *host, unsigned short port);
/**
* The destructor is doing nothing in particular.
*/
virtual ~TcpReceiver();
/**
* The TcpReceiver connects and starts receiving TUIO messages via TCP
*
* @param lock running in the background if set to false (default)
*/
void connect(bool lock=false);
/**
* The TcpReceiver disconnects and stops receiving TUIO messages via TCP
*/
void disconnect();
#ifndef WIN32
int tcp_socket;
std::list<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 */

View 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 TUIO2;
#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 ) { }

View 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 TUIO2 {
/**
* The TcpSender implements the TCP transport method for OSC
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TcpSender : public OscSender {
public:
/**
* The default constructor creates a TcpSender that sends to the default TUIO port 3333 on localhost
*/
TcpSender();
/**
* This constructor creates a TcpSender that sends to the provided port on the the given host
*
* @param host the receiving host name
* @param port the outgoing TUIO TCP port number
*/
TcpSender(const char *host, int port);
/**
* This constructor creates a TcpSender that listens to the provided port
*
* @param port the incoming TUIO TCP port number
*/
TcpSender(int port);
/**
* The destructor closes the socket.
*/
virtual ~TcpSender();
/**
* This method delivers the provided OSC data
*
* @param *bundle the OSC stream to deliver
* @return true if the data was delivered successfully
*/
bool sendOscPacket (osc::OutboundPacketStream *bundle);
/**
* This method returns the connection state
*
* @return true if the connection is alive
*/
bool isConnected ();
/**
* This method is called whenever a new client connects
*
* @param tcp_client the socket handle of the new client
*/
virtual void newClient( int tcp_client );
int port_no;
#ifdef WIN32
SOCKET tcp_socket;
std::list<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 */

View File

@@ -0,0 +1,94 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioBounds.h"
using namespace TUIO2;
TuioBounds::TuioBounds (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a, float w, float h, float f):TuioComponent(ttime, tobj, xp, yp,a) {
width = w;
height = h;
area = f;
}
TuioBounds::TuioBounds (TuioObject *tobj, float xp, float yp, float a, float w, float h, float f):TuioComponent(tobj, xp, yp, a) {
width = w;
height = h;
area = f;
}
TuioBounds::TuioBounds (TuioBounds *tbnd):TuioComponent(tbnd) {
angle = tbnd->getAngle();
width = tbnd->getWidth();
height = tbnd->getHeight();
area = tbnd->getArea();
rotation_speed = 0.0f;
rotation_accel = 0.0f;
}
void TuioBounds::update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra) {
TuioComponent::update(ttime,xp,yp,a,xs,ys,rs,ma,ra);
width = w;
height = h;
area = f;
}
void TuioBounds::update (float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra) {
TuioComponent::update(xp,yp,a,xs,ys,rs,ma,ra);
width = w;
height = h;
area = f;
}
void TuioBounds::update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f) {
TuioComponent::update(ttime,xp,yp,a);
width = w;
height = h;
area = f;
}
void TuioBounds::stop (TuioTime ttime) {
update(ttime,xpos,ypos,angle,width,height,area);
}
void TuioBounds::update (TuioBounds *tbnd) {
TuioComponent::update(tbnd);
width = tbnd->getWidth();
height = tbnd->getHeight();
area = tbnd->getArea();
}
float TuioBounds::getWidth() const{
return width;
}
float TuioBounds::getHeight() const{
return height;
}
int TuioBounds::getScreenWidth(int w) const{
return (int)(w*width);
}
int TuioBounds::getScreenHeight(int h) const{
return (int)(h*height);
}
float TuioBounds::getArea() const{
return area;
}

View File

@@ -0,0 +1,206 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOBOUNDS_H
#define INCLUDED_TUIOBOUNDS_H
#include "TuioComponent.h"
namespace TUIO2 {
/**
* The TuioBounds class encapsulates /tuio2/bnd TUIO boundary ellipses.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioBounds: public TuioComponent {
protected:
/**
* The rotation angle value.
*/
float angle;
/**
* The width value.
*/
float width;
/**
* The height value.
*/
float height;
/**
* The area value.
*/
float area;
/**
* The rotation speed value.
*/
float rotation_speed;
/**
* The rotation acceleration value.
*/
float rotation_accel;
public:
using TuioComponent::update;
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, X and Y coordinate, width, height and angle to the newly created TuioBounds.
*
* @param ttime the TuioTime to assign
* @param tobj the TuioObject to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param w the width to assign
* @param h the height to assign
* @param f the area to assign
*/
TuioBounds (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a, float w, float h, float f);
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, X and Y coordinate, width, height and angle to the newly created TuioBounds.
*
* @param tobj the TuioObject to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param w the width to assign
* @param h the height to assign
* @param f the area to assign
*/
TuioBounds (TuioObject *tobj, float xp, float yp, float a, float w, float h, float f);
/**
* This constructor takes the atttibutes of the provided TuioBounds
* and assigs these values to the newly created TuioBounds.
*
* @param tbnd the TuioBounds to assign
*/
TuioBounds (TuioBounds *tbnd);
/**
* The destructor is doing nothing in particular.
*/
~TuioBounds() {};
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate, angle, X and Y velocity, motion acceleration,
* rotation speed and rotation acceleration to the private TuioBounds attributes.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param w the width to assign
* @param h the height to assign
* @param f the area to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param rs the rotation velocity to assign
* @param ma the motion acceleration to assign
* @param ra the rotation acceleration to assign
*/
void update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra);
/**
* Assigns the provided X and Y coordinate, angle, X and Y velocity, motion acceleration
* rotation velocity and rotation acceleration to the private TuioComponent attributes.
* The TuioTime time stamp remains unchanged.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param w the width to assign
* @param h the height to assign
* @param f the area to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param rs the rotation velocity to assign
* @param ma the motion acceleration to assign
* @param ra the rotation acceleration to assign
*/
void update (float xp, float yp, float a, float w, float h, float f, float xs, float ys, float rs, float ma, float ra);
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate and angle to the private TuioBounds attributes.
* The speed and accleration values are calculated accordingly.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle coordinate to assign
* @param w the width to assign
* @param h the height to assign
* @param f the area to assign
*/
void update (TuioTime ttime, float xp, float yp, float a, float w, float h, float f);
/**
* This method is used to calculate the speed and acceleration values of a
* TuioBounds with unchanged position and angle.
*/
void stop (TuioTime ttime);
/**
* Takes the atttibutes of the provided TuioBounds
* and assigs these values to this TuioBounds.
* The TuioTime time stamp of this TuioComponent remains unchanged.
*
* @param tbnd the TuioComponent to assign
*/
void update (TuioBounds *tbnd);
/**
* Returns the width of this TuioBounds.
* @return the width of this TuioBounds
*/
float getWidth() const;
/**
* Returns the height of this TuioBounds.
* @return the height of this TuioBounds
*/
float getHeight() const;
/**
* Returns the width of this TuioBounds.
* @return the width of this TuioBounds
*/
int getScreenWidth(int w) const;
/**
* Returns the height of this TuioBounds.
* @return the height of this TuioBounds
*/
int getScreenHeight(int h) const;
/**
* Returns the area of this TuioBounds.
* @return the area of this TuioBounds
*/
float getArea() const;
};
}
#endif

View File

@@ -0,0 +1,520 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
using namespace osc;
TuioClient::TuioClient()
: lateFrame (false)
, source_count (0)
, receiver (NULL)
, local_receiver(true)
{
receiver = new UdpReceiver();
initialize();
}
TuioClient::TuioClient(unsigned short port)
: lateFrame (false)
, source_count (0)
, receiver (NULL)
, local_receiver(true)
{
receiver = new UdpReceiver(port);
initialize();
}
TuioClient::TuioClient(OscReceiver *osc)
: lateFrame (false)
, source_count (0)
, receiver (osc)
, local_receiver(false)
{
initialize();
}
void TuioClient::initialize() {
receiver->addTuioClient(this);
}
TuioClient::~TuioClient() {
if (local_receiver) delete receiver;
}
void TuioClient::processOSC( const ReceivedMessage& msg ) {
try {
ReceivedMessageArgumentStream args = msg.ArgumentStream();
//ReceivedMessage::const_iterator arg = msg.ArgumentsBegin();
if( strcmp( msg.AddressPattern(), "/tuio2/frm" ) == 0 ) {
//lockFrame();
int32 fseq_raw,dim_raw;
TimeTag timetag;
const char* src_string;
args >> fseq_raw >> timetag >> dim_raw >> src_string;
// check if we know that source
std::map<std::string,TuioSource*>::iterator iter = sourceList.find(src_string);
if (iter==sourceList.end()) { // add a new source
frameSource = new TuioSource(source_count, src_string, (unsigned int)dim_raw);
sourceList[src_string] = frameSource;
source_count++;
} else { // use the found source
frameSource = sourceList[src_string];
}
unsigned int currentFrameID = (unsigned int)fseq_raw;
frameTime = TuioTime(timetag);
frameTime.setFrameID(currentFrameID);
// frame sequence
lateFrame = false;
unsigned int lastFrameID = frameSource->getFrameTime().getFrameID();
unsigned int timeDiff = frameTime.getTotalMilliseconds() - frameSource->getFrameTime().getTotalMilliseconds();
frameSource->setFrameTime(frameTime);
// drop late frames (but accept the reserved ID 0 and consider a possible reset after 1sec
if ((currentFrameID<lastFrameID) && (currentFrameID!=0) && (timeDiff<1000)) lateFrame = true;
} else if( strcmp( msg.AddressPattern(), "/tuio2/tok" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw, tu_id_raw, c_id_raw;
unsigned short t_id, u_id;
unsigned int s_id,c_id;
float xpos, ypos, angle, xspeed, yspeed, rspeed, maccel, raccel;
args >> s_id_raw >> tu_id_raw >> c_id_raw >> xpos >> ypos >> angle;
if (!args.Eos()) args >> xspeed >> yspeed >> rspeed >> maccel >> raccel;
else xspeed = yspeed = rspeed = maccel = raccel = 0.0f;
s_id = (unsigned int)s_id_raw;
c_id = (unsigned int)c_id_raw;
t_id = tu_id_raw >> 16;
u_id = tu_id_raw & 0x0000FFFF;
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
//if (tobj == NULL) std::cout << "new cont " << s_id << " " << frameSource.getSourceID() << std::endl;
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
TuioToken *ttok = tobj->getTuioToken();
if (ttok == NULL) {
ttok = new TuioToken(frameTime,tobj,t_id,u_id,c_id,xpos,ypos,angle);
tobj->setTuioToken(ttok);
} else if ( (ttok->getX()!=xpos) || (ttok->getY()!=ypos) || (ttok->getAngle()!=angle) || (ttok->getXSpeed()!=xspeed) || (ttok->getYSpeed()!=yspeed) || (ttok->getRotationSpeed()!=rspeed) || (ttok->getMotionAccel()!=maccel) || (ttok->getRotationAccel()!=raccel) ) {
ttok->update(frameTime,xpos,ypos,angle,xspeed,yspeed,rspeed,maccel,raccel);
}
} else if( strcmp( msg.AddressPattern(), "/tuio2/ptr" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw, tu_id_raw, c_id_raw;
unsigned short t_id, u_id;
unsigned int s_id,c_id;
float xpos, ypos, angle, shear,radius, pressure, xspeed, yspeed, pspeed, maccel, paccel;
args >> s_id_raw >> tu_id_raw >> c_id_raw >> xpos >> ypos >> angle >> shear >> radius >> pressure;
if (!args.Eos()) args >> xspeed >> yspeed >> pspeed >> maccel >> paccel;
else xspeed = yspeed = pspeed = maccel = paccel = 0.0f;
s_id = (unsigned int)s_id_raw;
c_id = (unsigned int)c_id_raw;
t_id = tu_id_raw >> 16;
u_id = tu_id_raw & 0x0000FFFF;
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
//if (tobj == NULL) std::cout << "new cont " << s_id << " " << frameSource.getSourceID() << std::endl;
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
TuioPointer *tptr = tobj->getTuioPointer();
if (tptr == NULL) {
tptr = new TuioPointer(frameTime,tobj,t_id,u_id,c_id,xpos,ypos,angle,shear,radius,pressure);
tobj->setTuioPointer(tptr);
} else if ( (tptr->getX()!=xpos) || (tptr->getY()!=ypos) || (tptr->getAngle()!=angle) || (tptr->getShear()!=shear) || (tptr->getRadius()!=radius) || (tptr->getPressure()!=pressure) || (tptr->getXSpeed()!=xspeed) || (tptr->getYSpeed()!=yspeed) || (tptr->getPressureSpeed()!=pspeed) || (tptr->getMotionAccel()!=maccel) || (tptr->getPressureAccel()!=paccel) ) {
tptr->update(frameTime,xpos,ypos,angle,shear,radius,pressure,xspeed,yspeed,pspeed,maccel,paccel);
}
} else if( strcmp( msg.AddressPattern(), "/tuio2/bnd" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw;
unsigned int s_id;
float xpos, ypos, angle, width, height, area;
float xspeed, yspeed, rspeed, maccel, raccel;
args >> s_id_raw >> xpos >> ypos >> angle >> width >> height >> area;
if (!args.Eos()) args >> xspeed >> yspeed >> rspeed >> maccel >> raccel;
else xspeed = yspeed = rspeed = maccel = raccel = 0.0f;
s_id = (unsigned int)s_id_raw;
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
TuioBounds *tbnd = tobj->getTuioBounds();
if (tbnd == NULL) {
tbnd = new TuioBounds(frameTime,tobj,xpos,ypos,angle,width,height,area);
tobj->setTuioBounds(tbnd);
} else if ( (tbnd->getX()!=xpos) || (tbnd->getY()!=ypos) || (tbnd->getAngle()!=angle) || (tbnd->getWidth()!=width) || (tbnd->getHeight()!=height) || (tbnd->getArea()!=area) || (tbnd->getXSpeed()!=xspeed) || (tbnd->getYSpeed()!=yspeed) || (tbnd->getRotationSpeed()!=rspeed) || (tbnd->getMotionAccel()!=maccel) || (tbnd->getRotationAccel()!=raccel)) {
tbnd->update(frameTime,xpos,ypos,angle,width,height,area,xspeed,yspeed,rspeed,maccel,raccel);
}
} else if( strcmp( msg.AddressPattern(), "/tuio2/sym" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw, tu_id_raw, c_id_raw;
unsigned int s_id, c_id;
unsigned short t_id, u_id;
const char* type;
const char* data;
args >> s_id_raw >> tu_id_raw >> c_id_raw >> type >> data;
s_id = (unsigned int)s_id_raw;
c_id = (unsigned int)c_id_raw;
t_id = tu_id_raw >> 16;
u_id = tu_id_raw & 0x0000FFFF;
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
TuioSymbol *tsym = tobj->getTuioSymbol();
if (tsym == NULL) {
tsym = new TuioSymbol(frameTime,tobj,t_id,u_id,c_id,type,data);
tobj->setTuioSymbol(tsym);
} else {
tsym->update(frameTime);
}
} else if( strcmp( msg.AddressPattern(), "/tuio2/chg" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw;
args >> s_id_raw;
unsigned int s_id = (unsigned int)s_id_raw;
std::list<TuioPoint> pointList;
while(!args.Eos()) {
float xpos, ypos;
args >> xpos >> ypos;
pointList.push_back(TuioPoint(frameTime, xpos, ypos));
}
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
/*TuioGeometry *tgeo = tobj->getTuioGeometry();
if (tgeo == NULL) {
tgeo = new TuioGeometry(frameTime, tobj);
tobj->setTuioGeometry(tgeo);
} tgeo->setConvexHull(pointList);*/
} else if( strcmp( msg.AddressPattern(), "/tuio2/ocg" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw;
args >> s_id_raw;
unsigned int s_id = (unsigned int)s_id_raw;
std::list<TuioPoint> pointList;
while(!args.Eos()) {
float xpos, ypos;
args >> xpos >> ypos;
pointList.push_back(TuioPoint(frameTime, xpos, ypos));
}
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
/*TuioGeometry *tgeo = tobj->getTuioGeometry();
if (tgeo == NULL) {
tgeo = new TuioGeometry(frameTime, tobj);
tobj->setTuioGeometry(tgeo);
} tgeo->setOuterContour(pointList);*/
} else if( strcmp( msg.AddressPattern(), "/tuio2/icg" ) == 0 ) {
if (lateFrame) return;
int32 s_id_raw;
args >> s_id_raw;
unsigned int s_id = (unsigned int)s_id_raw;
std::list<TuioPoint> pointList;
while(!args.Eos()) {
float xpos,ypos;
args >> xpos >> ypos;
pointList.push_back(TuioPoint(frameTime, xpos, ypos));
}
TuioObject *tobj = getFrameObject(frameSource->getSourceID(),s_id);
if (tobj == NULL) tobj = new TuioObject(frameTime,frameSource,s_id);
addFrameObject(tobj);
/*TuioGeometry *tgeo = tobj->getTuioGeometry();
if (tgeo == NULL) {
tgeo = new TuioGeometry(frameTime, tobj);
tobj->setTuioGeometry(tgeo);
} tgeo->setOuterContour(pointList);*/
} else if( strcmp( msg.AddressPattern(), "/tuio2/alv" ) == 0 ) {
if (lateFrame) return;
int32 s_id;
aliveObjectList.clear();
while(!args.Eos()) {
args >> s_id;
aliveObjectList.push_back((unsigned int)s_id);
}
lockObjectList();
//find the removed tobjs first
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()!=frameSource->getSourceID()) continue;
std::list<unsigned int>::iterator iter = find(aliveObjectList.begin(), aliveObjectList.end(), (*tobj)->getSessionID());
if (iter == aliveObjectList.end()) {
(*tobj)->remove(frameTime);
addFrameObject(*tobj);
}
}
unlockObjectList();
for (std::list<TuioObject*>::iterator iter=frameObjectList.begin(); iter!=frameObjectList.end(); iter++) {
TuioObject *tobj = (*iter);
switch (tobj->getTuioState()) {
case TUIO_REMOVED:
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener!=listenerList.end(); listener++)
(*listener)->tuioRemove(tobj);
lockObjectList();
for (std::list<TuioObject*>::iterator delcon=tobjList.begin(); delcon!=tobjList.end(); delcon++) {
if (((*delcon)->getSessionID()==tobj->getSessionID()) && ((*delcon)->getTuioSource()->getSourceID()==frameSource->getSourceID())) {
delete *delcon;
tobjList.erase(delcon);
break;
}
}
unlockObjectList();
break;
case TUIO_ADDED:
lockObjectList();
tobjList.push_back(tobj);
unlockObjectList();
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioAdd(tobj);
break;
default:
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioUpdate(tobj);
}
}
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioRefresh(frameTime);
frameObjectList.clear();
//unlockFrame();
}
} catch( Exception& e ){
std::cerr << "error parsing TUIO2 message: "<< msg.AddressPattern() << " - " << e.what() << std::endl;
//unlockFrame();
}
}
bool TuioClient::isConnected() {
return receiver->isConnected();
}
void TuioClient::connect(bool lock) {
receiver->connect(lock);
unlockObjectList();
}
void TuioClient::disconnect() {
receiver->disconnect();
aliveObjectList.clear();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++)
delete (*iter);
tobjList.clear();
}
TuioObject* TuioClient::getTuioObject(unsigned int src_id, unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) {
unlockObjectList();
return (*iter);
}
}
unlockObjectList();
return NULL;
}
TuioToken* TuioClient::getTuioToken(unsigned int src_id, unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) {
unlockObjectList();
return (*iter)->getTuioToken();
}
}
unlockObjectList();
return NULL;
}
TuioPointer* TuioClient::getTuioPointer(unsigned int src_id, unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) {
unlockObjectList();
return (*iter)->getTuioPointer();
}
}
unlockObjectList();
return NULL;
}
TuioBounds* TuioClient::getTuioBounds(unsigned int src_id, unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) {
unlockObjectList();
return (*iter)->getTuioBounds();
}
}
unlockObjectList();
return NULL;
}
TuioSymbol* TuioClient::getTuioSymbol(unsigned int src_id, unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if (((*iter)->getSessionID()==s_id) && ((*iter)->getTuioSource()->getSourceID()==src_id)) {
unlockObjectList();
return (*iter)->getTuioSymbol();
}
}
unlockObjectList();
return NULL;
}
std::list<TuioObject*> TuioClient::getTuioObjectList(unsigned int src_id) {
lockObjectList();
std::list<TuioObject*> listBuffer;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()==src_id) listBuffer.push_back(*tobj);
}
unlockObjectList();
return listBuffer;
}
std::list<TuioToken*> TuioClient::getTuioTokenList(unsigned int src_id) {
lockObjectList();
std::list<TuioToken*> listBuffer;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()==src_id) {
TuioToken *ttok = (*tobj)->getTuioToken();
if (ttok!=NULL) listBuffer.push_back(ttok);
}
}
unlockObjectList();
return listBuffer;
}
std::list<TuioPointer*> TuioClient::getTuioPointerList(unsigned int src_id) {
lockObjectList();
std::list<TuioPointer*> listBuffer;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()==src_id) {
TuioPointer *tptr = (*tobj)->getTuioPointer();
if (tptr!=NULL) listBuffer.push_back(tptr);
}
}
unlockObjectList();
return listBuffer;
}
std::list<TuioBounds*> TuioClient::getTuioBoundsList(unsigned int src_id) {
lockObjectList();
std::list<TuioBounds*> listBuffer;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()==src_id) {
TuioBounds *tbnd = (*tobj)->getTuioBounds();
if (tbnd!=NULL) listBuffer.push_back(tbnd);
}
}
unlockObjectList();
return listBuffer;
}
std::list<TuioSymbol*> TuioClient::getTuioSymbolList(unsigned int src_id) {
lockObjectList();
std::list<TuioSymbol*> listBuffer;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if ((*tobj)->getTuioSource()->getSourceID()==src_id) {
TuioSymbol *tsym = (*tobj)->getTuioSymbol();
if (tsym!=NULL) listBuffer.push_back(tsym);
}
}
unlockObjectList();
return listBuffer;
}
void TuioClient::addFrameObject(TuioObject *tobj) {
for (std::list<TuioObject*>::iterator iter=frameObjectList.begin(); iter != frameObjectList.end(); iter++) {
if ((*iter)->getSessionID()==tobj->getSessionID()) return;
}
frameObjectList.push_back(tobj);
}
TuioObject* TuioClient::getFrameObject(unsigned int src_id, unsigned int s_id) {
for (std::list<TuioObject*>::iterator tobj=frameObjectList.begin(); tobj != frameObjectList.end(); tobj++) {
if ((*tobj)->getSessionID()==s_id) return *tobj;
}
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj != tobjList.end(); tobj++) {
if (((*tobj)->getSessionID()==s_id) && ((*tobj)->getTuioSource()->getSourceID()==src_id)) return *tobj;
}
return NULL;
}
void TuioClient::lockFrame() {
#ifndef WIN32
pthread_mutex_lock(&frameMutex);
#else
WaitForSingleObject(frameMutex, INFINITE);
#endif
}
void TuioClient::unlockFrame() {
#ifndef WIN32
pthread_mutex_unlock(&frameMutex);
#else
ReleaseMutex(frameMutex);
#endif
}

View File

@@ -0,0 +1,241 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2 {
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 2.0.a0
*/
class LIBDECL TuioClient : public TuioDispatcher {
public:
/**
* This constructor creates a TuioClient that uses an internal UdpReceiver listening to the default UDP port 3333
*
*/
TuioClient();
/**
* This constructor creates a TuioClient that uses an internal UdpReceiver listening to the provided UDP port
*
* @param port the UDP port the internal UdpReceiver is listening to
*/
TuioClient(unsigned short port);
/**
* This constructor creates a TuioClient that uses the provided OscReceiver for the incoming OSC data
*
* @param oscreceiver the OscReceiver implementation for the chosen transport method (UDP, TCP ...)
*/
TuioClient(OscReceiver *oscreceiver);
/**
* The destructor is doing nothing in particular.
*/
~TuioClient();
/**
* The TuioClient connects and starts receiving TUIO messages from its associated OscReceiver
*
* @param lock running in the background if set to false (default)
*/
void connect(bool lock=false);
/**
* The TuioClient disconnects and stops receiving TUIO messages from its associated OscReceiver
*/
void disconnect();
/**
* Returns true if this TuioClient is currently connected.
* @return true if this TuioClient is currently connected
*/
bool isConnected();
/**
* Returns the TuioObject corresponding to the provided Session ID
* which is associated to the given Source ID
* or NULL if the Session ID does not refer to an active TuioObject
*
* @param src_id the source ID of the corresponding TUIO source
* @param s_id the session ID of the corresponding TuioObject
* @return an active TuioObject corresponding to the provided Session ID or NULL
*/
using TuioDispatcher::getTuioObject;
TuioObject* getTuioObject(unsigned int src_id, unsigned int s_id);
/**
* Returns a list of all currently active TuioObject
* which are associated to the given Source ID
*
* @param src_id the source ID of the corresponding TUIO source
* @return a list of TuioObject
*/
using TuioDispatcher::getTuioObjectList;
std::list<TuioObject*> getTuioObjectList(unsigned int src_id);
/**
* Returns the TuioToken corresponding to the provided Session ID
* which is associated to the given Source ID
* or NULL if the Session ID does not refer to an active TuioToken
*
* @param src_id the source ID of the corresponding TUIO source
* @param s_id the session ID of the corresponding TuioToken
* @return an active TuioToken corresponding to the provided Session ID or NULL
*/
using TuioDispatcher::getTuioToken;
TuioToken* getTuioToken(unsigned int src_id, unsigned int s_id);
/**
* Returns a list of all currently active TuioTokens
* which are associated to the given Source ID
*
* @param src_id the source ID of the corresponding TUIO source
* @return a list of TuioTokens
*/
using TuioDispatcher::getTuioTokenList;
std::list<TuioToken*> getTuioTokenList(unsigned int src_id);
/**
* Returns the TuioPointer corresponding to the provided Session ID
* which is associated to the given Source ID
* or NULL if the Session ID does not refer to an active TuioPointer
*
* @param src_id the source ID of the corresponding TUIO source
* @param s_id the session ID of the corresponding TuioPointer
* @return an active TuioPointer corresponding to the provided Session ID or NULL
*/
using TuioDispatcher::getTuioPointer;
TuioPointer* getTuioPointer(unsigned int src_id, unsigned int s_id);
/**
* Returns a List of all currently active TuioPointers
* which are associated to the given Source ID
*
* @param src_id the source ID of the corresponding TUIO source
* @return a List of TuioPointers
*/
using TuioDispatcher::getTuioPointerList;
std::list<TuioPointer*> getTuioPointerList(unsigned int src_id);
/**
* Returns the TuioBounds corresponding to the provided Session ID
* which is associated to the given Source ID
* or NULL if the Session ID does not refer to an active TuioBounds
*
* @param src_id the source ID of the corresponding TUIO source
* @param s_id the session ID of the corresponding TuioBounds
* @return an active TuioBounds corresponding to the provided Session ID or NULL
*/
using TuioDispatcher::getTuioBounds;
TuioBounds* getTuioBounds(unsigned int src_id, unsigned int s_id);
/**
* Returns a List of all currently active TuioBounds
* which are associated to the given Source ID
*
* @param src_id the source ID of the corresponding TUIO source
* @return a List of TuioBounds
*/
using TuioDispatcher::getTuioBoundsList;
std::list<TuioBounds*> getTuioBoundsList(unsigned int src_id);
/**
* Returns the TuioSymbol corresponding to the provided Session ID
* which is associated to the given Source ID
* or NULL if the Session ID does not refer to an active TuioSymbol
*
* @param src_id the source ID of the corresponding TUIO source
* @param s_id the session ID of the corresponding TuioSymbol
* @return an active TuioSymbol corresponding to the provided Session ID or NULL
*/
using TuioDispatcher::getTuioSymbol;
TuioSymbol* getTuioSymbol(unsigned int src_id, unsigned int s_id);
/**
* Returns a List of all currently active TuioSymbol
* which are associated to the given Source ID
*
* @param src_id the source ID of the corresponding TUIO source
* @return a List of TuioSymbol
*/
using TuioDispatcher::getTuioSymbolList;
std::list<TuioSymbol*> getTuioSymbolList(unsigned int src_id);
/**
* Parses the incoming OSC message
*
* @param message the incoming OSC message
*/
void processOSC( const osc::ReceivedMessage& message);
private:
void initialize();
void addFrameObject(TuioObject *con);
TuioObject* getFrameObject(unsigned int src_id,unsigned int s_id);
std::list<unsigned int> aliveObjectList;
std::list<TuioObject*> frameObjectList;
TuioTime frameTime;
bool lateFrame;
unsigned int source_count;
std::map<std::string,TuioSource*> sourceList;
TuioSource *frameSource;
OscReceiver *receiver;
bool local_receiver;
#ifndef WIN32
pthread_mutex_t frameMutex;
#else
HANDLE frameMutex;
#endif
void lockFrame();
void unlockFrame();
};
};
#endif /* INCLUDED_TUIOCLIENT_H */

View File

@@ -0,0 +1,245 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioComponent.h"
#include "TuioObject.h"
using namespace TUIO2;
TuioComponent::TuioComponent (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a):TuioPoint(ttime, xp,yp)
,state(TUIO_ADDED)
{
container = tobj;
angle = a;
x_speed = 0.0f;
y_speed = 0.0f;
motion_speed = 0.0f;
motion_accel = 0.0f;
rotation_speed = 0.0f;
rotation_accel = 0.0f;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
}
TuioComponent::TuioComponent (TuioObject *tobj, float xp, float yp, float a):TuioPoint(xp,yp)
,state(TUIO_ADDED)
{
container = tobj;
angle = a;
x_speed = 0.0f;
y_speed = 0.0f;
motion_speed = 0.0f;
motion_accel = 0.0f;
rotation_speed = 0.0f;
rotation_accel = 0.0f;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
}
TuioComponent::TuioComponent (TuioComponent *tcomp):TuioPoint(tcomp)
,state(TUIO_ADDED)
{
container = tcomp->getContainingTuioObject();
angle = tcomp->getAngle();
x_speed = 0.0f;
y_speed = 0.0f;
motion_speed = 0.0f;
motion_accel = 0.0f;
rotation_speed = 0.0f;
rotation_accel = 0.0f;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
}
TuioObject* TuioComponent::getContainingTuioObject() {
return container;
}
void TuioComponent::setContainingTuioObject(TuioObject *tobj) {
container = tobj;
}
void TuioComponent::update (TuioTime ttime, float xp, float yp, float a) {
TuioPoint lastPoint = path.back();
TuioPoint::update(ttime,xp, yp);
TuioTime diffTime = currentTime - lastPoint.getTuioTime();
float dt = diffTime.getTotalMilliseconds()/1000.0f;
float dx = xpos - lastPoint.getX();
float dy = ypos - lastPoint.getY();
float dist = sqrt(dx*dx+dy*dy);
float last_motion_speed = motion_speed;
x_speed = dx/dt;
y_speed = dy/dt;
motion_speed = dist/dt;
motion_accel = (motion_speed - last_motion_speed)/dt;
float last_angle = angle;
float last_rotation_speed = rotation_speed;
angle = a;
double da = (angle-last_angle)/(2*M_PI);
if (da > 0.75f) da-=1.0f;
else if (da < -0.75f) da+=1.0f;
rotation_speed = (float)da/dt;
rotation_accel = (rotation_speed - last_rotation_speed)/dt;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
if (path.size()>MAX_PATH_SIZE) path.pop_front();
if (motion_accel>0) state = TUIO_ACCELERATING;
else if (motion_accel<0) state = TUIO_DECELERATING;
else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
else state = TUIO_STOPPED;
container->update(ttime);
}
void TuioComponent::stop(TuioTime ttime) {
update(ttime,xpos,ypos);
container->update(ttime);
}
void TuioComponent::update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
TuioPoint::update(ttime,xp, yp);
angle = a;
x_speed = xs;
y_speed = ys;
motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
rotation_speed = rs;
motion_accel = ma;
rotation_accel = ra;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
if (path.size()>MAX_PATH_SIZE) path.pop_front();
if (motion_accel>0) state = TUIO_ACCELERATING;
else if (motion_accel<0) state = TUIO_DECELERATING;
else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
else state = TUIO_STOPPED;
container->update(ttime);
}
void TuioComponent::update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra) {
TuioPoint::update(xp,yp);
angle = a;
x_speed = xs;
y_speed = ys;
motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
rotation_speed = rs;
motion_accel = ma;
rotation_accel = ra;
TuioPoint p(currentTime,xpos,ypos);
path.push_back(p);
if (path.size()>MAX_PATH_SIZE) path.pop_front();
if (motion_accel>0) state = TUIO_ACCELERATING;
else if (motion_accel<0) state = TUIO_DECELERATING;
else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
else state = TUIO_STOPPED;
container->update(currentTime);
}
void TuioComponent::update (TuioComponent *tcomp) {
TuioPoint::update(tcomp);
angle = tcomp->getAngle();
x_speed = tcomp->getXSpeed();
y_speed = tcomp->getYSpeed();
motion_speed = tcomp->getMotionSpeed();
rotation_speed = tcomp->getRotationSpeed();
motion_accel = tcomp->getMotionAccel();
rotation_accel = tcomp->getRotationAccel();
TuioPoint p(tcomp->getTuioTime(),xpos,ypos);
path.push_back(p);
if (path.size()>MAX_PATH_SIZE) path.pop_front();
if (motion_accel>0) state = TUIO_ACCELERATING;
else if (motion_accel<0) state = TUIO_DECELERATING;
else if ((rotation_accel!=0) && (state==TUIO_STOPPED)) state = TUIO_ROTATING;
else state = TUIO_STOPPED;
container->update(tcomp->getTuioTime());
}
void TuioComponent::remove(TuioTime ttime) {
currentTime = ttime;
state = TUIO_REMOVED;
container->update(ttime);
}
unsigned int TuioComponent::getSessionID() const{
return container->getSessionID();
}
float TuioComponent::getAngle() const{
return angle;
}
float TuioComponent::getAngleDegrees() const{
return (float)(angle/M_PI*180);
}
float TuioComponent::getXSpeed() const{
return x_speed;
}
float TuioComponent::getYSpeed() const{
return y_speed;
}
TuioPoint TuioComponent::getPosition() const{
TuioPoint p(xpos,ypos);
return p;
}
std::list<TuioPoint> TuioComponent::getPath() const{
return path;
}
float TuioComponent::getMotionSpeed() const{
return motion_speed;
}
float TuioComponent::getMotionAccel() const{
return motion_accel;
}
float TuioComponent::getRotationSpeed() const{
return rotation_speed;
}
float TuioComponent::getRotationAccel() const{
return rotation_accel;
}
int TuioComponent::getTuioState() const{
return state;
}
bool TuioComponent::isMoving() const{
if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING) || (state==TUIO_ROTATING)) return true;
else return false;
}

View File

@@ -0,0 +1,287 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOCOMPONENT_H
#define INCLUDED_TUIOCOMPONENT_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 TUIO2 {
/**
* The abstract TuioComponent class defines common attributes that apply to all subclasses {@link TuioToken}, {@link TuioPointer} and {@link TuioBounds}.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class TuioObject;
class LIBDECL TuioComponent: public TuioPoint {
protected:
/**
* The TuioObject that contains this TUIO component.
*/
TuioObject *container;
/**
* The rotation angle value.
*/
float angle;
/**
* The X-axis velocity value.
*/
float x_speed;
/**
* The Y-axis velocity value.
*/
float y_speed;
/**
* The motion speed value.
*/
float motion_speed;
/**
* The motion acceleration value.
*/
float motion_accel;
/**
* The rotation speed value.
*/
float rotation_speed;
/**
* The rotation acceleration value.
*/
float rotation_accel;
/**
* A List of TuioPoints containing all the previous positions of the TUIO component.
*/
std::list<TuioPoint> path;
/**
* Reflects the current state of the TuioComponent
*/
int state;
public:
using TuioPoint::update;
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, X and Y coordinate to the newly created TuioComponent.
*
* @param ttime the TuioTime to assign
* @param tobj the TuioObject to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
TuioComponent (TuioTime ttime, TuioObject *tobj, float xp, float yp, float a);
/**
* This constructor takes the provided Session ID, X and Y coordinate
* and assigs these values to the newly created TuioComponent.
*
* @param tobj the TuioObject to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
TuioComponent (TuioObject *tobj, float xp, float yp,float a);
/**
* This constructor takes the atttibutes of the provided TuioComponent
* and assigs these values to the newly created TuioComponent.
*
* @param tcon the TuioComponent to assign
*/
TuioComponent (TuioComponent *tcon);
/**
* The destructor is doing nothing in particular.
*/
virtual ~TuioComponent(){};
/**
* Returns the TuioObject containing this TuioComponent.
* @return the TuioObject containing this TuioComponent
*/
virtual TuioObject* getContainingTuioObject();
/**
* Returns the TuioObject containing this TuioComponent.
* @param the TuioObject containing this TuioComponent
*/
virtual void setContainingTuioObject(TuioObject *tobj);
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate to the private TuioComponent attributes.
* The speed and accleration values are calculated accordingly.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
virtual void update (TuioTime ttime, float xp, float yp, float a);
/**
* This method is used to calculate the speed and acceleration values of
* TuioComponents with unchanged positions.
*/
virtual void stop(TuioTime ttime);
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate, X and Y velocity and acceleration
* to the private TuioComponent attributes.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param rs the rotation velocity to assign
* @param ma the motion acceleration to assign
* @param ra the rotation acceleration to assign
*/
virtual void update (TuioTime ttime, float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra);
/**
* Assigns the provided X and Y coordinate, X and Y velocity and acceleration
* to the private TuioComponent attributes. The TuioTime time stamp remains unchanged.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param rs the rotation velocity to assign
* @param ma the motion acceleration to assign
* @param ra the rotation acceleration to assign
*/
virtual void update (float xp, float yp, float a, float xs, float ys, float rs, float ma, float ra);
/**
* Takes the atttibutes of the provided TuioComponent
* and assigs these values to this TuioComponent.
* The TuioTime time stamp of this TuioComponent remains unchanged.
*
* @param tcon the TuioComponent to assign
*/
virtual void update(TuioComponent *tcon);
/**
* Assigns the REMOVE state to this TuioComponent and sets
* its TuioTime time stamp to the provided TuioTime argument.
*
* @param ttime the TuioTime to assign
*/
virtual void remove(TuioTime ttime);
/**
* Returns the Session ID of this TuioComponent.
* @return the Session ID of this TuioComponent
*/
virtual unsigned int getSessionID() const;
/**
* Returns the X velocity of this TuioComponent.
* @return the X velocity of this TuioComponent
*/
virtual float getXSpeed() const;
/**
* Returns the Y velocity of this TuioComponent.
* @return the Y velocity of this TuioComponent
*/
virtual float getYSpeed() const;
/**
* Returns the position of this TuioComponent.
* @return the position of this TuioComponent
*/
virtual TuioPoint getPosition() const;
/**
* Returns the path of this TuioComponent.
* @return the path of this TuioComponent
*/
virtual std::list<TuioPoint> getPath() const;
/**
* Returns the motion speed of this TuioComponent.
* @return the motion speed of this TuioComponent
*/
virtual float getMotionSpeed() const;
/**
* Returns the motion acceleration of this TuioComponent.
* @return the motion acceleration of this TuioComponent
*/
virtual float getMotionAccel() const;
/**
* Returns the rotation angle of this TuioComponent.
* @return the rotation angle of this TuioComponent
*/
float getAngle() const;
/**
* Returns the rotation angle in degrees of this TuioComponent.
* @return the rotation angle in degrees of this TuioComponent
*/
float getAngleDegrees() const;
/**
* Returns the rotation speed of this TuioComponent.
* @return the rotation speed of this TuioComponent
*/
float getRotationSpeed() const;
/**
* Returns the rotation acceleration of this TuioComponent.
* @return the rotation acceleration of this TuioComponent
*/
float getRotationAccel() const;
/**
* Returns the TUIO state of this TuioComponent.
* @return the TUIO state of this TuioComponent
*/
virtual int getTuioState() const;
/**
* Returns true of this TuioComponent is moving.
* @return true of this TuioComponent is moving
*/
virtual bool isMoving() const;
};
}
#endif // INCLUDED_TUIOCOMPONENT_H

View File

@@ -0,0 +1,165 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
TuioDispatcher::TuioDispatcher() {
#ifndef WIN32
pthread_mutex_init(&tobjMutex,NULL);
#else
tobjMutex = CreateMutex(NULL,FALSE,"tobjMutex");
#endif
}
TuioDispatcher::~TuioDispatcher() {
#ifndef WIN32
pthread_mutex_destroy(&tobjMutex);
#else
CloseHandle(tobjMutex);
#endif
}
void TuioDispatcher::lockObjectList() {
#ifndef WIN32
pthread_mutex_lock(&tobjMutex);
#else
WaitForSingleObject(tobjMutex, INFINITE);
#endif
}
void TuioDispatcher::unlockObjectList() {
#ifndef WIN32
pthread_mutex_unlock(&tobjMutex);
#else
ReleaseMutex(tobjMutex);
#endif
}
void TuioDispatcher::addTuioListener(TuioListener *listener) {
listenerList.push_back(listener);
}
void TuioDispatcher::removeTuioListener(TuioListener *listener) {
std::list<TuioListener*>::iterator result = find(listenerList.begin(),listenerList.end(),listener);
if (result!=listenerList.end()) listenerList.remove(listener);
}
void TuioDispatcher::removeAllTuioListeners() {
listenerList.clear();
}
TuioObject* TuioDispatcher::getTuioObject(unsigned int s_id) {
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
if((*tobj)->getSessionID()==s_id) {
unlockObjectList();
return (*tobj);
}
}
unlockObjectList();
return NULL;
}
TuioToken* TuioDispatcher::getTuioToken(unsigned int s_id) {
TuioObject *tobj = getTuioObject(s_id);
if (tobj==NULL) return NULL;
return tobj->getTuioToken();
}
TuioPointer* TuioDispatcher::getTuioPointer(unsigned int s_id) {
TuioObject *tobj = getTuioObject(s_id);
if (tobj==NULL) return NULL;
return tobj->getTuioPointer();
}
TuioBounds* TuioDispatcher::getTuioBounds(unsigned int s_id) {
TuioObject *tobj = getTuioObject(s_id);
if (tobj==NULL) return NULL;
return tobj->getTuioBounds();
}
TuioSymbol* TuioDispatcher::getTuioSymbol(unsigned int s_id) {
TuioObject *tobj = getTuioObject(s_id);
if (tobj==NULL) return NULL;
return tobj->getTuioSymbol();
}
std::list<TuioObject*> TuioDispatcher::getTuioObjectList() {
std::list<TuioObject*> listBuffer;
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
listBuffer.push_back(*tobj);
}
unlockObjectList();
return listBuffer;
}
std::list<TuioToken*> TuioDispatcher::getTuioTokenList() {
std::list<TuioToken*> listBuffer;
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
TuioToken *ttok = (*tobj)->getTuioToken();
if (ttok!=NULL) listBuffer.push_back(ttok);
}
unlockObjectList();
return listBuffer;
}
std::list<TuioPointer*> TuioDispatcher::getTuioPointerList() {
std::list<TuioPointer*> listBuffer;
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
TuioPointer *tptr = (*tobj)->getTuioPointer();
if (tptr!=NULL) listBuffer.push_back(tptr);
}
unlockObjectList();
return listBuffer;
}
std::list<TuioBounds*> TuioDispatcher::getTuioBoundsList() {
std::list<TuioBounds*> listBuffer;
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
TuioBounds *tbnd = (*tobj)->getTuioBounds();
if (tbnd!=NULL) listBuffer.push_back(tbnd);
}
unlockObjectList();
return listBuffer;
}
std::list<TuioSymbol*> TuioDispatcher::getTuioSymbolList() {
std::list<TuioSymbol*> listBuffer;
lockObjectList();
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
TuioSymbol *tsym = (*tobj)->getTuioSymbol();
if (tsym!=NULL) listBuffer.push_back(tsym);
}
unlockObjectList();
return listBuffer;
}

View File

@@ -0,0 +1,169 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2 {
/**
* <p>The TuioDispatcher generates TUIO events which are broadcasted to all
* registered classes that implement the {@link TuioListener} interface.</p>
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioDispatcher {
public:
/**
* This constructor creates a TuioDispatcher
*
*/
TuioDispatcher();
/**
* The destructor is doing nothing in particular.
*/
~TuioDispatcher();
/**
* Adds the provided TuioListener to the list of registered TUIO event listeners
*
* @param listener the TuioListener to add
*/
void addTuioListener(TuioListener *listener);
/**
* Removes the provided TuioListener from the list of registered TUIO event listeners
*
* @param listener the TuioListener to remove
*/
void removeTuioListener(TuioListener *listener);
/**
* Removes all TuioListener from the list of registered TUIO event listeners
*/
void removeAllTuioListeners();
/**
* Returns a List of all currently active TuioObject
*
* @return a List of all currently active TuioObject
*/
std::list<TuioObject*> getTuioObjectList();
/**
* Returns a List of all currently active TuioTokens
*
* @return a List of all currently active TuioTokens
*/
std::list<TuioToken*> getTuioTokenList();
/**
* Returns a List of all currently active TuioPointers
*
* @return a List of all currently active TuioPointers
*/
std::list<TuioPointer*> getTuioPointerList();
/**
* Returns a List of all currently active TuioBounds
*
* @return a List of all currently active TuioBounds
*/
std::list<TuioBounds*> getTuioBoundsList();
/**
* Returns a List of all currently active TuioSymbols
*
* @return a List of all currently active TuioSymbols
*/
std::list<TuioSymbol*> getTuioSymbolList();
/**
* Returns the TuioObject corresponding to the provided Session ID
* or NULL if the Session ID does not refer to an active TuioObject
*
* @return an active TuioObject corresponding to the provided Session ID or NULL
*/
TuioObject* getTuioObject(unsigned int s_id);
/**
* Returns the TuioToken corresponding to the provided Session ID
* or NULL if the Session ID does not refer to an active TuioToken
*
* @return an active TuioToken corresponding to the provided Session ID or NULL
*/
TuioToken* getTuioToken(unsigned int s_id);
/**
* Returns the TuioPointer corresponding to the provided Session ID
* or NULL if the Session ID does not refer to an active TuioPointer
*
* @return an active TuioPointer corresponding to the provided Session ID or NULL
*/
TuioPointer* getTuioPointer(unsigned int s_id);
/**
* Returns the TuioBounds corresponding to the provided Session ID
* or NULL if the Session ID does not refer to an active TuioBounds
*
* @return an active TuioBounds corresponding to the provided Session ID or NULL
*/
TuioBounds* getTuioBounds(unsigned int s_id);
/**
* Returns the TuioSymbol corresponding to the provided Session ID
* or NULL if the Session ID does not refer to an active TuioSymbol
*
* @return an active TuioSymbol corresponding to the provided Session ID or NULL
*/
TuioSymbol* getTuioSymbol(unsigned int s_id);
/**
* Locks the TuioObject list in order to avoid updates during access
*/
void lockObjectList();
/**
* Releases the lock of the TuioObject list
*/
void unlockObjectList();
protected:
std::list<TuioListener*> listenerList;
std::list<TuioObject*> tobjList;
#ifndef WIN32
pthread_mutex_t tobjMutex;
#else
HANDLE tobjMutex;
#endif
};
}
#endif /* INCLUDED_TUIODISPATCHER_H */

View File

@@ -0,0 +1,80 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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"
namespace TUIO2 {
/**
* <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 2.0.a0
*/
class LIBDECL TuioListener {
public:
/**
* The destructor is doing nothing in particular.
*/
virtual ~TuioListener(){};
/**
* This callback method is invoked by the TuioClient when a new TUIO Component is added to the session.
*
* @param tobj the TuioObject reference that encapsulates all related TUIO Components
*/
virtual void tuioAdd(TuioObject *tobj)=0;
/**
* This callback method is invoked by the TuioClient when an existing TUIO Component is updated during the session.
*
* @param tobj the TuioObject reference that encapsulates all related TUIO Components
*/
virtual void tuioUpdate(TuioObject *tobj)=0;
/**
* This callback method is invoked by the TuioClient when a TUIO Component is removed from the session.
*
* @param tobj the TuioObject reference that encapsulates all related TUIO Components
*/
virtual void tuioRemove(TuioObject *tobj)=0;
/**
* This callback method is invoked by the TuioClient to mark the end of a received TUIO message bundle.
*
* @param ftime the TuioTime associated to the current TUIO message bundle
*/
virtual void tuioRefresh(TuioTime ftime)=0;
};
}
#endif /* INCLUDED_TUIOLISTENER_H */

View File

@@ -0,0 +1,575 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
TuioManager::TuioManager()
: currentFrameTime(TuioTime::getSystemTime())
, currentFrame(-1)
, pointerCount(0)
, maxPointerID(-1)
, sessionID(-1)
, tobjUpdate(false)
, verbose(false)
, invert_x(false)
, invert_y(false)
, invert_a(false)
{
}
TuioManager::~TuioManager() {
}
TuioObject* TuioManager::createTuioObject() {
sessionID++;
TuioObject *tobj = new TuioObject(sessionID);
tobjList.push_back(tobj);
return tobj;
}
void TuioManager::addExternalTuioObject(TuioObject *tobj) {
if (tobj==NULL) return;
tobjList.push_back(tobj);
TuioPointer *tptr = tobj->getTuioPointer();
if (tptr!=NULL) pointerCount++;
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioAdd(tobj);
if (verbose) std::cout << "add " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::updateExternalTuioObject(TuioObject *tobj) {
if (tobj==NULL) return;
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioUpdate(tobj);
if (verbose) std::cout << "set " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::removeExternalTuioObject(TuioObject *tobj) {
if (tobj==NULL) return;
tobjList.remove(tobj);
TuioPointer *tptr = tobj->getTuioPointer();
if (tptr!=NULL) pointerCount--;
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioRemove(tobj);
if (verbose) std::cout << "del " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::removeTuioObject(unsigned int s_id) {
TuioObject *tobj = NULL;
for(std::list<TuioObject*>::iterator iter = tobjList.begin();iter!= tobjList.end(); iter++) {
if((*iter)->getSessionID()==s_id) {
tobj = *iter;
break;
}
}
if (tobj==NULL) return;
else removeTuioObject(tobj);
}
void TuioManager::removeTuioObject(TuioObject *tobj) {
if (tobj== NULL) return;
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioRemove(tobj);
if (tobj->containsTuioToken()) {
if (verbose) std::cout << "del tok " << tobj->getSessionID() << std::endl;
tobj->deleteTuioToken();
}
if (tobj->containsTuioPointer()) {
if (verbose) std::cout << "del ptr " << tobj->getSessionID() << std::endl;
tobj->deleteTuioPointer();
}
if (tobj->containsTuioBounds()) {
if (verbose) std::cout << "del bnd " << tobj->getSessionID() << std::endl;
tobj->deleteTuioBounds();
}
if (tobj->containsTuioSymbol()) {
if (verbose) std::cout << "del sym " << tobj->getSessionID() << std::endl;
tobj->deleteTuioSymbol();
}
tobjList.remove(tobj);
tobjUpdate = true;
delete tobj;
}
TuioObject* TuioManager::createTuioToken(unsigned int sym, float x, float y, float a) {
return addTuioToken(NULL, sym, 0, 0, x, y, a);
}
TuioObject* TuioManager::createTuioToken(unsigned int sym, unsigned short t_id, unsigned short u_id, float x, float y, float a) {
return addTuioToken(NULL, sym, t_id, u_id, x, y, a);
}
TuioObject* TuioManager::addTuioToken(TuioObject *tobj, unsigned int sym, float x, float y, float a) {
return addTuioToken(tobj, sym, 0, 0, x, y, a);
}
TuioObject* TuioManager::addTuioToken(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, float x, float y, float a) {
TuioToken *ttok = new TuioToken(currentFrameTime, tobj, t_id, u_id, sym, x, y, a);
return addTuioToken(ttok);
}
TuioObject* TuioManager::addTuioToken(TuioToken *ttok) {
if (ttok==NULL) return NULL;
TuioObject *tobj = ttok->getContainingTuioObject();
if (tobj==NULL) tobj = createTuioObject();
tobj->setTuioToken(ttok);
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) {
(*listener)->tuioAdd(tobj);
}
if (verbose) std::cout << "add tok " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
return tobj;
}
void TuioManager::updateTuioToken(TuioToken *ttok, float x, float y, float a) {
if (ttok==NULL) return;
if (ttok->getTuioTime()==currentFrameTime) return;
ttok->update(currentFrameTime,x,y,a);
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioUpdate(ttok->getContainingTuioObject());
if (verbose)std::cout << "set tok " << ttok->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::removeTuioToken(TuioToken *ttok) {
if (ttok==NULL) return;
TuioObject *tobj = ttok->getContainingTuioObject();
if (tobj==NULL) {
delete ttok;
return;
} else removeTuioObject(tobj);
}
TuioObject* TuioManager::createTuioPointer(float x, float y, float a, float s, float r, float p) {
return addTuioPointer(NULL, 0, 0, x, y, a, s, r, p);
}
TuioObject* TuioManager::createTuioPointer(unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) {
return addTuioPointer(NULL, t_id, u_id, x, y, a, s, r, p);
}
TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, float x, float y, float a, float s, float r, float p) {
return addTuioPointer(tobj, 0, 0, x, y, a, s, r, p);
}
TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) {
int pointerID = pointerCount;
if ((pointerCount<=maxPointerID) && (freePointerList.size()>0)) {
std::list<TuioPointer*>::iterator closestPointer = freePointerList.begin();
for(std::list<TuioPointer*>::iterator iter = freePointerList.begin();iter!= freePointerList.end(); iter++) {
if((*iter)->getDistance(x,y)<(*closestPointer)->getDistance(x,y)) closestPointer = iter;
}
TuioPointer *freePointer = (*closestPointer);
pointerID = (*closestPointer)->getPointerID();
freePointerList.erase(closestPointer);
delete freePointer;
} else maxPointerID = pointerID;
TuioPointer *tptr = new TuioPointer(currentFrameTime, tobj, t_id, u_id, pointerID, x, y, a, s, r, p);
return addTuioPointer(tptr);
}
TuioObject* TuioManager::createTuioPointer(unsigned int p_id, float x, float y, float a, float s, float r, float p) {
return addTuioPointer(NULL, p_id, 0, 0, x, y, a, s, r, p);
}
TuioObject* TuioManager::createTuioPointer(unsigned int p_id, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) {
return addTuioPointer(NULL, p_id, t_id, u_id, x, y, a, s, r, p);
}
TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned int p_id, float x, float y, float a, float s, float r, float p) {
return addTuioPointer(tobj, p_id, 0, 0, x, y, a, s, r, p);
}
TuioObject* TuioManager::addTuioPointer(TuioObject *tobj, unsigned int p_id, unsigned short t_id, unsigned short u_id, float x, float y, float a, float s, float r, float p) {
TuioPointer *tptr = new TuioPointer(currentFrameTime, tobj, t_id, u_id, p_id, x, y, a, s, r, p);
return addTuioPointer(tptr);
}
TuioObject* TuioManager::addTuioPointer(TuioPointer *tptr) {
if (tptr==NULL) return NULL;
TuioObject *tobj = tptr->getContainingTuioObject();
if (tobj==NULL) tobj = createTuioObject();
tobj->setTuioPointer(tptr);
pointerCount++;
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) {
(*listener)->tuioAdd(tobj);
}
if (verbose) std::cout << "add ptr " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
return tobj;
}
void TuioManager::updateTuioPointer(TuioPointer *tptr, float x, float y, float a, float s, float r, float p) {
if (tptr==NULL) return;
if (tptr->getTuioTime()==currentFrameTime) return;
TuioObject *tobj = tptr->getContainingTuioObject();
if (tobj==NULL) return;
tptr->update(currentFrameTime,x,y,a,s,r,p);
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioUpdate(tobj);
if (verbose)std::cout << "set ptr " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::removeTuioPointer(TuioPointer *tptr) {
if (tptr==NULL) return;
pointerCount--;
TuioObject *tobj = tptr->getContainingTuioObject();
if (tptr->getPointerID()==maxPointerID) {
maxPointerID = -1;
if (pointerCount>0) {
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
if ((*iter)->containsTuioPointer()) {
int pointerID = (*iter)->getTuioPointer()->getPointerID();
if (pointerID>maxPointerID) maxPointerID=pointerID;
}
}
freePointerBuffer.clear();
for (std::list<TuioPointer*>::iterator flist=freePointerList.begin(); flist != freePointerList.end(); flist++) {
TuioPointer *freePointer = (*flist);
if (freePointer->getPointerID()<=maxPointerID) freePointerBuffer.push_back(new TuioPointer(freePointer));
}
freePointerList = freePointerBuffer;
} else {
for (std::list<TuioPointer*>::iterator flist=freePointerList.begin(); flist != freePointerList.end(); flist++) {
TuioPointer *freePointer = (*flist);
delete freePointer;
}
freePointerList.clear();
}
} else if (tptr->getPointerID()<maxPointerID) {
freePointerList.push_back(new TuioPointer(tptr));
}
if (tobj==NULL) {
delete tptr;
return;
} else removeTuioObject(tobj);
}
TuioObject* TuioManager::createTuioBounds(float x, float y, float a, float w, float h, float f) {
return addTuioBounds(NULL, x, y, a ,w ,h ,f);
}
TuioObject* TuioManager::addTuioBounds(TuioObject *tobj, float x, float y, float a, float w, float h, float f) {
TuioBounds *tbnd = new TuioBounds(currentFrameTime, tobj, x, y, a, w, h, f);
return addTuioBounds(tbnd);
}
TuioObject* TuioManager::addTuioBounds(TuioBounds *tbnd) {
if (tbnd==NULL) return NULL;
TuioObject *tobj = tbnd->getContainingTuioObject();
if (tobj==NULL) tobj = createTuioObject();
tobj->setTuioBounds(tbnd);
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) {
(*listener)->tuioAdd(tobj);
}
if (verbose) std::cout << "add bnd " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
return tobj;
}
void TuioManager::updateTuioBounds(TuioBounds *tbnd, float x, float y, float a, float w, float h, float f) {
if (tbnd==NULL) return;
if (tbnd->getTuioTime()==currentFrameTime) return;
tbnd->update(currentFrameTime,x,y,a,w,h,f);
TuioObject *tobj = tbnd->getContainingTuioObject();
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioUpdate(tobj);
if (verbose)std::cout << "set bnd " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
}
void TuioManager::removeTuioBounds(TuioBounds *tbnd) {
if (tbnd==NULL) return;
TuioObject *tobj = tbnd->getContainingTuioObject();
if (tobj==NULL) {
delete tbnd;
return;
} else removeTuioObject(tobj);
}
TuioObject* TuioManager::createTuioSymbol(unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data) {
return addTuioSymbol(NULL, t_id, u_id, sym, type, data);
}
TuioObject* TuioManager::addTuioSymbol(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data) {
TuioSymbol *tsym = new TuioSymbol(currentFrameTime, tobj, t_id, u_id, sym, type, data);
return addTuioSymbol(tsym);
}
TuioObject* TuioManager::addTuioSymbol(TuioSymbol *tsym) {
if (tsym==NULL) return NULL;
TuioObject *tobj = tsym->getContainingTuioObject();
if (tobj==NULL) tobj = createTuioObject();
tobj->setTuioSymbol(tsym);
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++) {
if (tobjUpdate)(*listener)->tuioUpdate(tobj);
else(*listener)->tuioAdd(tobj);
}
if (verbose) std::cout << "add sym " << tobj->getSessionID() << std::endl;
tobjUpdate = true;
return tobj;
}
void TuioManager::removeTuioSymbol(TuioSymbol *tsym) {
if (tsym==NULL) return;
TuioObject *tobj = tsym->getContainingTuioObject();
if (tobj==NULL) {
delete tsym;
return;
} else removeTuioObject(tobj);
}
int TuioManager::getSessionID() {
sessionID++;
if (sessionID==UINT_MAX) sessionID = 0;
return sessionID;
}
int TuioManager::getFrameID() {
return currentFrame;
}
TuioTime TuioManager::getFrameTime() {
return currentFrameTime;
}
void TuioManager::initTuioFrame(TuioTime ttime) {
frameTimeTag = TuioTime::getSystemTimeTag();
currentFrameTime = TuioTime(ttime);
currentFrame++;
if (currentFrame==UINT_MAX) currentFrame = 1;
}
void TuioManager::commitTuioFrame() {
for (std::list<TuioListener*>::iterator listener=listenerList.begin(); listener != listenerList.end(); listener++)
(*listener)->tuioRefresh(currentFrameTime);
if (verbose) std::cout << "refresh " << currentFrame << " " << currentFrameTime.getTotalMilliseconds() << std::endl;
}
TuioToken* TuioManager::getClosestTuioToken(float xp, float yp) {
TuioToken *closestToken = NULL;
float closestDistance = 1.0f;
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
TuioToken *ttok = (*iter)->getTuioToken();
if (ttok==NULL) continue;
float distance = ttok->getDistance(xp,yp);
if(distance<closestDistance) {
closestToken = ttok;
closestDistance = distance;
}
}
return closestToken;
}
TuioPointer* TuioManager::getClosestTuioPointer(float xp, float yp) {
TuioPointer *closestPointer = NULL;
float closestDistance = 1.0f;
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter != tobjList.end(); iter++) {
TuioPointer *tptr = (*iter)->getTuioPointer();
if (tptr==NULL) continue;
float distance = tptr->getDistance(xp,yp);
if(distance<closestDistance) {
closestPointer = tptr;
closestDistance = distance;
}
}
return closestPointer;
}
TuioBounds* TuioManager::getClosestTuioBounds(float xp, float yp) {
TuioBounds *closestBounds = NULL;
float closestDistance = 1.0f;
for (std::list<TuioObject*>::iterator iter=tobjList.begin(); iter!=tobjList.end(); iter++) {
TuioBounds *tbnd = (*iter)->getTuioBounds();
if (tbnd==NULL) continue;
float distance = tbnd->getDistance(xp,yp);
if(distance<closestDistance) {
closestBounds = tbnd;
closestDistance = distance;
}
}
return closestBounds;
}
std::list<TuioObject*> TuioManager::getUntouchedObjects() {
std::list<TuioObject*> untouched;
for (std::list<TuioObject*>::iterator tobj=tobjList.begin(); tobj!=tobjList.end(); tobj++) {
bool touched = false;
if ((*tobj)->containsTuioToken()) {
if ((*tobj)->getTuioToken()->getTuioTime()==currentFrameTime) touched=true;
}
if ((*tobj)->containsTuioPointer()) {
if ((*tobj)->getTuioPointer()->getTuioTime()==currentFrameTime) touched=true;
}
if ((*tobj)->containsTuioBounds()) {
if ((*tobj)->getTuioToken()->getTuioTime()==currentFrameTime) touched=true;
}
if ((*tobj)->containsTuioSymbol()) {
if ((*tobj)->getTuioSymbol()->getTuioTime()==currentFrameTime) touched=true;
}
if (!touched) untouched.push_back(*tobj);
}
return untouched;
}
void TuioManager::stopUntouchedMovingObjects() {
for (std::list<TuioObject*>::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) {
if ((*tobj)->containsTuioToken()) {
TuioToken *ttok = (*tobj)->getTuioToken();
if ((ttok->getTuioTime()!=currentFrameTime) && (ttok->isMoving())) {
ttok->stop(currentFrameTime);
if (verbose) std::cout << "set tok " << ttok->getSessionID() << std::endl;
tobjUpdate = true;
}
}
if ((*tobj)->containsTuioPointer()) {
TuioPointer *tptr = (*tobj)->getTuioPointer();
if ((tptr->getTuioTime()!=currentFrameTime) && (tptr->isMoving())) {
tptr->stop(currentFrameTime);
if (verbose) std::cout << "set ptr " << tptr->getSessionID() << std::endl;
tobjUpdate = true;
}
}
if ((*tobj)->containsTuioBounds()) {
TuioBounds *tbnd = (*tobj)->getTuioBounds();
if ((tbnd->getTuioTime()!=currentFrameTime) && (tbnd->isMoving())) {
tbnd->stop(currentFrameTime);
if (verbose) std::cout << "set bnd " << tbnd->getSessionID() << std::endl;
tobjUpdate = true;
}
}
}
}
void TuioManager::removeUntouchedStoppedObjects() {
std::list<TuioObject*>::iterator iter = tobjList.begin();
while (iter!=tobjList.end()) {
TuioObject *tobj = (*iter);
if ((tobj->getTuioTime()!=currentFrameTime) && (!tobj->isMoving())) {
removeTuioObject(tobj);
iter = tobjList.begin();
} else iter++;
}
}
void TuioManager::resetTuioObjectList() {
pointerCount=0;
std::list<TuioObject*>::iterator tobj = tobjList.begin();
while (tobj!=tobjList.end()) {
removeTuioObject((*tobj));
tobj = tobjList.begin();
}
}

View File

@@ -0,0 +1,601 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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>
namespace TUIO2 {
/**
* <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 TuioTokens 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->initTuioFrame(TuioTime::getSessionTime());<br/>
* TuioToken *ttok = server->addTuioToken(xpos,ypos, angle);<br/>
* TuioPointer *tptr = server->addTuioToken(xpos,ypos);<br/>
* TuioBounds *tbnd = server->addTuioBounds(xpos,ypos,width,height,angle);<br/>
* server->commitFrame();<br/>
* ...<br/>
* server->initFrame(TuioTime::getSessionTime());<br/>
* server->updateTuioToken(ttok, xpos,ypos, angle);<br/>
* server->updateTuioPointer(tptr, xpos,ypos);<br/>
* server->updateTuioBounds(tbnd, xpos,ypos,width,height,angle);<br/>
* server->commitFrame();<br/>
* ...<br/>
* server->initFrame(TuioTime::getSessionTime());<br/>
* server->removeTuioToken(ttok);<br/>
* server->removeTuioPointer(tptr);<br/>
* server->removeTuioBounds(tbnd);<br/>
* server->commitFrame();<br/>
* </code></p>
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioManager : public TuioDispatcher {
public:
/**
* The default constructor creates a TuioManager
*/
TuioManager();
/**
* The destructor is doing nothing in particular.
*/
~TuioManager();
/**
* Adds an externally managed TuioObject to the TuioServer's internal list of active TuioObjects
*
* @param tobj the TuioObject to add
*/
void addExternalTuioObject(TuioObject *tobj);
/**
* Updates an externally managed TuioObject
*
* @param tobj the TuioObject to update
*/
void updateExternalTuioObject(TuioObject *tobj);
/**
* Removes an externally managed TuioObject from the TuioServer's internal list of TuioObjects
* The referenced TuioObject is not deleted
*
* @param tobj the TuioObject to remove
*/
void removeExternalTuioObject(TuioObject *tobj);
/**
* Creates an internally managed TuioObject with a new Session ID
* and adds it to the TuioServer's internal list of TuioObjects
*
* @return the newly created but empty TuioObject
*/
TuioObject* createTuioObject();
/**
* Removes an internally managed TuioObject from the TuioServer's internal list of TuioObjects
* The provided TuioObject (and all its encapsulated TUIO Components) are deleted
*
* @param s_id the Session ID of the internal TuioObject to remove
*/
void removeTuioObject(unsigned int s_id);
/**
* Removes an internally managed TuioObject from the TuioServer's internal list of TuioObjects
* The provided TuioObject (and all its encapsulated TUIO Components) are deleted
*
* @param tobj the internal TuioObject to remove
*/
void removeTuioObject(TuioObject *tobj);
/**
* Creates a new TuioToken based on the given arguments.
* A new TuioObject containing that TuioToken is added
* to the TuioServer's internal list of TuioObjects
* and the TuioToken reference is returned to the caller.
*
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @return reference to the created TuioToken
*/
TuioObject* createTuioToken(unsigned int sym, float xp, float yp, float a);
/**
* Creates a new TuioToken based on the given arguments.
* A new TuioObject containing that TuioToken is added
* to the TuioServer's internal list of TuioObjects
* and the TuioToken reference is returned to the caller.
*
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @return a reference to the TuioObject of the TuioToken
*/
TuioObject* createTuioToken(unsigned int sym, unsigned short t_id, unsigned short u_id, float xp, float yp, float a);
/**
* Creates a new TuioToken based on the given arguments.
* and adds it to an existing TuioObject with the Session ID
* from the TuioServer's internal list of TuioObjects
* and the TuioToken reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @return a reference to the TuioObject of the TuioToken
*/
TuioObject* addTuioToken(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, float xp, float yp, float a);
/**
* Creates a new TuioToken based on the given arguments.
* and adds it to an existing TuioObject with the Session ID
* from the TuioServer's internal list of TuioObjects
* and the TuioToken reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @return a reference to the TuioObject of the TuioToken
*/
TuioObject* addTuioToken(TuioObject *tobj, unsigned int sym, float xp, float yp, float a);
/**
* Adds the provided TuioToken to an existing TuioObject
* from the TuioServer's internal list of TuioObjects
* or creates the according TuioObject if not found.
*
* @param ttok the existing TuioToken to add
* @return a reference to the TuioObject of the TuioToken
*/
TuioObject* addTuioToken(TuioToken *ttok);
/**
* Updates the referenced TuioToken based on the given arguments.
*
* @param ttok the TuioToken to update
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
void updateTuioToken(TuioToken *ttok, float xp, float yp, float a);
/**
* Removes the provided TuioToken from an existing TuioObject
* and also deletes the TuioObject with all other components
*
* @param ttok the TuioToken to remove
*/
void removeTuioToken(TuioToken *ttok);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* createTuioPointer(float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* and adds it to an existing TuioObject with the Session ID
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference of the TuioObject is returned to the caller.
*
* @param tobj the existing TuioObject
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* addTuioPointer(TuioObject *tobj, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* createTuioPointer(unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* addTuioPointer(TuioObject *tobj, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param p_id the Pointer ID to assign
* @param xp the X coordinate to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return reference to the created TuioPointer
*/
TuioObject* createTuioPointer(unsigned int p_id, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param p_id the Pointer ID to assign
* @param xp the X coordinate to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return reference to the created TuioPointer
*/
TuioObject* addTuioPointer(TuioObject *tobj, unsigned int p_id, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param p_id the Pointer ID to assign
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param xp the X coordinate to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* createTuioPointer(unsigned int p_id, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p);
/**
* Creates a new TuioPointer based on the given arguments.
* The new TuioPointer is added to the TuioServer's internal list of active TuioPointers
* and a reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param p_id the Pointer ID to assign
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param xp the X coordinate to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* addTuioPointer(TuioObject *tobj, unsigned int p_id, unsigned short t_id, unsigned short u_id, float xp, float yp, float a, float s, float r, float p);
/**
* Adds the provided TuioPointer to an existing TuioObject
* from the TuioServer's internal list of TuioObjects
* or creates the according TuioObject if not found.
*
* @param tptr the existing TuioPointer to add
* @return a reference to the TuioObject of the TuioPointer
*/
TuioObject* addTuioPointer(TuioPointer *tptr);
/**
* Updates the referenced TuioPointer based on the given arguments.
*
* @param tptr the TuioPointer to update
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the rotation angle to assign
* @param s the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
*/
void updateTuioPointer(TuioPointer *tptr, float xp, float yp, float a, float s, float r, float p);
/**
* Removes the provided TuioPointer from an existing TuioObject
* and also deletes the TuioObject with all other components
*
* @param tptr the TuioPointer to remove
*/
void removeTuioPointer(TuioPointer *tptr);
/**
* Creates a new TuioBounds based on the given arguments.
* The new TuioBounds is added to the TuioServer's internal list of active TuioBounds
* and a reference is returned to the caller.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param angle the angle to assign
* @param width the width to assign
* @param height the height to assign
* @param area the area to assign
* @return a reference to the TuioObject of the TuioBounds
*/
TuioObject* createTuioBounds(float xp, float yp, float angle, float width, float height, float area);
/**
* Creates a new TuioBounds based on the given arguments.
* The new TuioBounds is added to the TuioServer's internal list of active TuioBounds
* and a reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param angle the angle to assign
* @param width the width to assign
* @param height the height to assign
* @param area the area to assign
* @return a reference to the TuioObject of the TuioBounds
*/
TuioObject* addTuioBounds(TuioObject *tobj, float xp, float yp, float angle, float width, float height, float area);
/**
* Adds the provided TuioBounds to an existing TuioObject
* from the TuioServer's internal list of TuioObjects
* or creates the according TuioObject if not found.
*
* @param tbnd the TuioBounds to add
* @return a reference to the TuioObject of the TuioBounds
*/
TuioObject* addTuioBounds(TuioBounds *tbnd);
/**
* Updates the referenced TuioBounds based on the given arguments.
*
* @param tbnd the TuioToken to update
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param angle the angle to assign
* @param width the width to assign
* @param height the height to assign
* @param area the area to assign
*/
void updateTuioBounds(TuioBounds *tbnd, float xp, float yp, float angle, float width, float height, float area);
/**
* Removes the referenced TuioBounds from the TuioServer's internal list of TuioObjects
* and also deletes its TuioObject (and all its encapsulated TUIO Components)
*
* @param tbnd the TuioBounds to remove
*/
void removeTuioBounds(TuioBounds *tbnd);
/**
* Creates a new TuioSymbol based on the given arguments.
* The new TuioSymbol is added to the TuioServer's internal list of TuioObjects
* and a reference is returned to the caller.
*
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param sym the Symbol ID to assign
* @param type the type descriptor to assign
* @param data the synbol data to assign
* @return a reference to the TuioObject of the TuioSymbol
*/
TuioObject* createTuioSymbol(unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data);
/**
* Creates a new TuioSymbol based on the given arguments.
* The new TuioSymbol is added to the TuioServer's internal list of TuioObjects
* and a reference is returned to the caller.
*
* @param tobj the existing TuioObject
* @param t_id the Type ID to assign
* @param u_id the User ID to assign
* @param sym the Symbol ID to assign
* @param type the type descriptor to assign
* @param data the synbol data to assign
* @return a reference to the TuioObject of the TuioSymbol
*/
TuioObject* addTuioSymbol(TuioObject *tobj, unsigned short t_id, unsigned short u_id, unsigned int sym, const char *type, const char *data);
/**
* Adds the provided TuioSymbol to an existing TuioObject
* from the TuioServer's internal list of TuioObjects
* or creates the according TuioObject if not found.
*
* @param tsym the TuioSymbol to add
* @return a reference to the TuioObject of the TuioSymbol
*/
TuioObject* addTuioSymbol(TuioSymbol *tsym);
/**
* Removes the referenced TuioSymbol from the TuioServer's internal list of TuioObjects
* and also deletes its TuioObject (and all its encapsulated TUIO Components)
*
* @param tsym the TuioSymbol to remove
*/
void removeTuioSymbol(TuioSymbol *tsym);
/**
* Initializes a new frame with the given TuioTime
*
* @param ttime the frame time
*/
void initTuioFrame(TuioTime ttime);
/**
* Commits the current frame.
* Generates and sends TUIO messages of all currently active and updated TuioTokens and TuioPointers.
*/
void commitTuioFrame();
/**
* Returns the next available Session ID for external use.
* @return the next available Session ID for external use
*/
int getSessionID();
/**
* Returns the current frame ID for external use.
* @return the current frame ID for external use
*/
int getFrameID();
/**
* Returns the current frame time for external use.
* @return the current frame time for external use
*/
TuioTime getFrameTime();
/**
* Returns a List of all currently inactive TuioObjects
*
* @return a List of all currently inactive TuioObjects
*/
std::list<TuioObject*> getUntouchedObjects();
/**
* Calculates speed and acceleration values for all currently inactive TuioObjects
*/
void stopUntouchedMovingObjects();
/**
* Removes all currently inactive TuioObjects from the TuioServer's internal list
*/
void removeUntouchedStoppedObjects();
/**
* Returns the TuioToken closest to the provided coordinates
* or NULL if there isn't any active TuioToken
*
* @return the closest TuioToken to the provided coordinates or NULL
*/
TuioToken* getClosestTuioToken(float xp, float yp);
/**
* Returns the TuioPointer closest to the provided coordinates
* or NULL if there isn't any active TuioPointer
*
* @return the closest TuioPointer corresponding to the provided coordinates or NULL
*/
TuioPointer* getClosestTuioPointer(float xp, float yp);
/**
* Returns the TuioBounds closest to the provided coordinates
* or NULL if there isn't any active TuioBounds
*
* @return the closest TuioBounds corresponding to the provided coordinates or NULL
*/
TuioBounds* getClosestTuioBounds(float xp, float yp);
/**
* The TuioServer prints verbose TUIO event messages to the console if set to true.
* @param verbose print verbose messages if set to true
*/
void setVerbose(bool verbose) { this->verbose=verbose; }
void setInversion(bool ix, bool iy, bool ia) {
invert_x = ix;
invert_y = iy;
invert_a = ia;
};
void setInvertXpos(bool ix) { invert_x = ix; };
void setInvertYpos(bool iy) { invert_y = iy; };
void setInvertAngle(bool ia) { invert_a = ia; };
bool getInvertXpos() { return invert_x; };
bool getInvertYpos() { return invert_y; };
bool getInvertAngle() { return invert_a; };
void resetTuioObjectList();
protected:
std::list<TuioPointer*> freePointerList;
std::list<TuioPointer*> freePointerBuffer;
TuioTime currentFrameTime;
osc::TimeTag frameTimeTag;
unsigned int currentFrame;
unsigned int pointerCount, maxPointerID;
unsigned int sessionID;
bool tobjUpdate;
bool verbose;
bool invert_x;
bool invert_y;
bool invert_a;
};
}
#endif /* INCLUDED_TUIOMANAGER_H */

View File

@@ -0,0 +1,311 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
TuioObject::TuioObject (unsigned int s_id) {
currentTime = TuioTime::getSystemTime();
session_id = s_id;
startTime = currentTime;
token = NULL;
pointer = NULL;
bounds = NULL;
symbol = NULL;
state = TUIO_ADDED;
}
TuioObject::TuioObject (TuioTime ttime, unsigned int s_id) {
currentTime = ttime;
session_id = s_id;
startTime = currentTime;
token = NULL;
pointer = NULL;
bounds = NULL;
symbol = NULL;
state = TUIO_ADDED;
}
TuioObject::TuioObject (TuioTime ttime, TuioSource *src, unsigned int s_id) {
currentTime = ttime;
session_id = s_id;
startTime = currentTime;
setTuioSource(src);
token = NULL;
pointer = NULL;
bounds = NULL;
symbol = NULL;
state = TUIO_ADDED;
}
TuioObject::~TuioObject() {
deleteAllTuioComponents();
}
unsigned int TuioObject::getSessionID() {
return session_id;
}
void TuioObject::setTuioSource(TuioSource *src) {
source.setSourceString(src->getSourceID(),src->getSourceString());
}
TuioSource* TuioObject::getTuioSource() {
return &source;
}
void TuioObject::setTuioToken (TuioToken *ttok) {
token = ttok;
token->setContainingTuioObject(this);
currentTime = TuioTime::getSystemTime();
state = TUIO_ADDED;
}
void TuioObject::setTuioPointer (TuioPointer *tptr) {
pointer = tptr;
pointer->setContainingTuioObject(this);
currentTime = TuioTime::getSystemTime();
state = TUIO_ADDED;
}
void TuioObject::setTuioBounds (TuioBounds *tbnd) {
bounds = tbnd;
bounds->setContainingTuioObject(this);
currentTime = TuioTime::getSystemTime();
state = TUIO_ADDED;
}
void TuioObject::setTuioSymbol (TuioSymbol *tsym) {
symbol = tsym;
symbol->setContainingTuioObject(this);
currentTime = TuioTime::getSystemTime();
state = TUIO_ADDED;
}
void TuioObject::removeAllTuioComponents(TuioTime ttime) {
removeTuioToken(ttime);
removeTuioPointer(ttime);
removeTuioBounds(ttime);
removeTuioSymbol(ttime);
}
void TuioObject::removeTuioToken (TuioTime ttime) {
if (token != NULL) token->remove(ttime);
currentTime = ttime;
}
void TuioObject::removeTuioPointer (TuioTime ttime) {
if (pointer != NULL) pointer->remove(ttime);
currentTime = ttime;
}
void TuioObject::removeTuioBounds (TuioTime ttime) {
if (bounds != NULL) bounds->remove(ttime);
currentTime = ttime;
}
void TuioObject::removeTuioSymbol (TuioTime ttime) {
if (symbol != NULL) symbol->remove(ttime);
currentTime = ttime;
}
void TuioObject::deleteAllTuioComponents() {
deleteTuioToken();
deleteTuioPointer();
deleteTuioBounds();
deleteTuioSymbol();
}
void TuioObject::deleteTuioToken () {
if (token != NULL) {
delete token;
token = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::deleteTuioPointer () {
if (pointer != NULL) {
delete pointer;
pointer = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::deleteTuioBounds () {
if (bounds != NULL) {
delete bounds;
bounds = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::deleteTuioSymbol () {
if (symbol != NULL) {
delete symbol;
symbol = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::clearAllTuioComponents() {
clearTuioToken();
clearTuioPointer();
clearTuioBounds();
clearTuioSymbol();
}
void TuioObject::clearTuioToken () {
if (token != NULL) {
token = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::clearTuioPointer () {
if (pointer != NULL) {
pointer = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::clearTuioBounds () {
if (bounds != NULL) {
bounds = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
void TuioObject::clearTuioSymbol () {
if (symbol != NULL) {
symbol = NULL;
//currentTime = TuioTime::getSessionTime();
}
}
bool TuioObject::containsAnyTuioComponent () {
if (token != NULL) return true;
else if (pointer != NULL) return true;
else if (bounds != NULL) return true;
else if (symbol != NULL) return true;
else return false;
}
bool TuioObject::containsTuioToken () {
if (token != NULL) return true;
else return false;
}
bool TuioObject::containsTuioPointer () {
if (pointer != NULL) return true;
else return false;
}
bool TuioObject::containsTuioBounds () {
if (bounds != NULL) return true;
else return false;
}
bool TuioObject::containsTuioSymbol () {
if (symbol != NULL) return true;
else return false;
}
bool TuioObject::containsNewTuioToken () {
if (token == NULL) return false;
else if (token->getTuioState()==TUIO_ADDED) return true;
else return false;
}
bool TuioObject::containsNewTuioPointer () {
if (pointer == NULL) return false;
else if (pointer->getTuioState()==TUIO_ADDED) return true;
else return false;
}
bool TuioObject::containsNewTuioBounds () {
if (bounds == NULL) return false;
else if (bounds->getTuioState()==TUIO_ADDED) return true;
else return false;
}
bool TuioObject::containsNewTuioSymbol () {
if (symbol == NULL) return false;
else if (symbol->getTuioState()==TUIO_ADDED) return true;
else return false;
}
TuioToken* TuioObject::getTuioToken () {
return token;
}
TuioPointer* TuioObject::getTuioPointer () {
return pointer;
}
TuioBounds* TuioObject::getTuioBounds () {
return bounds;
}
TuioSymbol* TuioObject::getTuioSymbol () {
return symbol;
}
void TuioObject::stop(TuioTime ttime){
if (token!=NULL) token->stop(ttime);
if (pointer!=NULL) pointer->stop(ttime);
if (bounds!=NULL) bounds->stop(ttime);
currentTime = ttime;
}
void TuioObject::remove(TuioTime ttime){
if (token!=NULL) token->remove(ttime);
if (pointer!=NULL) pointer->remove(ttime);
if (bounds!=NULL) bounds->remove(ttime);
currentTime = ttime;
state = TUIO_REMOVED;
}
void TuioObject::update(TuioTime ttime){
currentTime = ttime;
state = TUIO_IDLE;
}
bool TuioObject::isMoving(){
if ((token!=NULL) && token->isMoving()) return true;
if ((pointer!=NULL) && pointer->isMoving()) return true;
if ((bounds!=NULL) && bounds->isMoving()) return true;
return false;
}
TuioTime TuioObject::getTuioTime() const{
return currentTime;
}
TuioTime TuioObject::getStartTime() const{
return startTime;
}
unsigned char TuioObject::getTuioState() const{
return state;
}

View File

@@ -0,0 +1,341 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioTime.h"
#include "TuioToken.h"
#include "TuioPointer.h"
#include "TuioBounds.h"
#include "TuioSymbol.h"
#include "TuioSource.h"
namespace TUIO2 {
/**
* The TuioObject class encapsulates all Tuio objects that share the same Session ID.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioObject {
protected:
/**
* The shared session ID
*/
unsigned int session_id;
/**
* The associated TuioSource
*/
TuioSource source;
/**
* the associated TuioToken
*/
TuioToken *token;
/**
* the associated TuioPointer
*/
TuioPointer *pointer;
/**
* the associated TuioBounds
*/
TuioBounds *bounds;
/**
* the associated TuioSymbol
*/
TuioSymbol *symbol;
/**
* The time stamp of the last update represented as TuioTime (time since session start)
*/
TuioTime currentTime;
/**
* The creation time of this TuioObject represented as TuioTime (time since session start)
*/
TuioTime startTime;
/**
* Reflects the current state of the TuioObject
*/
unsigned char state;
public:
/**
* The default constructor only takes the Session ID
* @param s_id the Session ID to assign
*/
TuioObject (unsigned int s_id);
/**
* This constructor takes a TuioTime and the Session ID
* @param ttime the TuioTime to assign
* @param s_id the Session ID to assign
*/
TuioObject (TuioTime ttime, unsigned int s_id);
/**
* This constructor takes a TuioTime and the Session ID
* @param ttime the TuioTime to assign
* @param src the TuioSource to assign
* @param s_id the Session ID to assign
*/
TuioObject (TuioTime ttime, TuioSource *src, unsigned int s_id);
/**
* The default destructor also delets all assigned TUIO components
*/
~TuioObject ();
/**
* Returns the associated Session ID
* @return the associated Session ID
*/
unsigned int getSessionID();
/**
* Sets the assotiated TUIO source
*
* @param src the TuioSource to assign
*/
void setTuioSource(TuioSource *src);
/**
* Returns the associated TUIO source
*/
TuioSource* getTuioSource();
/**
* This method assigns a TuioToken to this TuioObject
* @param ttok the TuioToken to assign
*/
void setTuioToken(TuioToken *ttok);
/**
* This method assigns a TuioPointer to this TuioObject
* @param tptr the TuioPointer to assign
*/
void setTuioPointer(TuioPointer *tptr);
/**
* This method assigns a TuioBounds to this TuioObject
* @param tbnd the TuioBounds to assign
*/
void setTuioBounds(TuioBounds *tbnd);
/**
* This method assigns a TuioSymbol to this TuioObject
* @param tsym the TuioSymbol to assign
*/
void setTuioSymbol(TuioSymbol *tsym);
/**
* This method sets all TuioComponents in this TuioObject to TUIO_REMOVED state
*/
void removeAllTuioComponents(TuioTime ttime);
/**
* This method sets the TuioToken in this TuioObject to TUIO_REMOVED state
*/
void removeTuioToken(TuioTime ttime);
/**
* This method sets the TuioPointer in this TuioObject to TUIO_REMOVED state
*/
void removeTuioPointer(TuioTime ttime);
/**
* This method sets the TuioBounds in this TuioObject to TUIO_REMOVED state
*/
void removeTuioBounds(TuioTime ttime);
/**
* This method sets the TuioSymbol in this TuioObject to TUIO_REMOVED state
*/
void removeTuioSymbol(TuioTime ttime);
/**
* This method deletes all TuioComponents in this TuioObject
*/
void deleteAllTuioComponents();
/**
* This method deletes the TuioToken in this TuioObject
*/
void deleteTuioToken();
/**
* This method deletes the TuioPointer in this TuioObject
*/
void deleteTuioPointer();
/**
* This method deletes the TuioBounds in this TuioObject
*/
void deleteTuioBounds();
/**
* This method deletes the TuioSymbol in this TuioObject
*/
void deleteTuioSymbol();
/**
* This method clears all TuioComponents in this TuioObject
*/
void clearAllTuioComponents();
/**
* This method clears the TuioToken in this TuioObject
*/
void clearTuioToken();
/**
* This method clears the TuioPointer in this TuioObject
*/
void clearTuioPointer();
/**
* This method clears the TuioBounds in this TuioObject
*/
void clearTuioBounds();
/**
* This method clears the TuioSymbol in this TuioObject
*/
void clearTuioSymbol();
/**
* This method tests for any TuioComponent in this TuioObject
* @return true if any TuioComponent has been assigned
*/
bool containsAnyTuioComponent();
/**
* This method tests for a TuioToken in this TuioObject
* @return true if a TuioToken has been assigned
*/
bool containsTuioToken();
/**
* This method tests for a TuioPointer in this TuioObject
* @return true if a TuioPointer has been assigned
*/
bool containsTuioPointer();
/**
* This method tests for a TuioBounds in this TuioObject
* @return true if a TuioBounds has been assigned
*/
bool containsTuioBounds();
/**
* This method tests for a TuioSymbol in this TuioObject
* @return true if a TuioSymbol has been assigned
*/
bool containsTuioSymbol();
/**
* This method tests if a new TuioToken has been added to this TuioObject
* @return true if a TuioToken has been added
*/
bool containsNewTuioToken();
/**
* This method tests if a new TuioPointer has been added this TuioObject
* @return true if a TuioPointer has been added
*/
bool containsNewTuioPointer();
/**
* This method tests if a new TuioBounds has been added to this TuioObject
* @return true if a TuioBounds has been added
*/
bool containsNewTuioBounds();
/**
* This method tests if a new TuioSymbol has beed added to this TuioObject
* @return true if a TuioSymbol has been added
*/
bool containsNewTuioSymbol();
/**
* This method returns the TuioToken associated to this TuioObject
* @return the associated TuioToken
*/
TuioToken* getTuioToken();
/**
* This method returns the TuioPointer associated to this TuioObject
* @return the associated TuioPointer
*/
TuioPointer* getTuioPointer();
/**
* This method returns the TuioBounds associated to this TuioObject
* @return the associated TuioBounds
*/
TuioBounds* getTuioBounds();
/**
* This method returns the TuioSymbol associated to this TuioObject
* @return the associated TuioSymbol
*/
TuioSymbol* getTuioSymbol();
/**
* This method stops all encapsulated TuioComponents
*/
void stop(TuioTime ttime);
/**
* This method removes all encapsulated TuioComponents
*/
void remove(TuioTime ttime);
/**
* This method returns true if any encapsulated TuioComponent is moving
*/
bool isMoving();
/**
* This method refreshes the currentTime after an update
*/
void update(TuioTime ttime);
/**
* Returns current time stamp of this TuioPoint as TuioTime
*
* @return the time stamp of this TuioPoint as TuioTime
*/
TuioTime getTuioTime() const;
/**
* Returns the start time of this TuioPoint as TuioTime.
*
* @return the start time of this TuioPoint as TuioTime
*/
TuioTime getStartTime() const;
/**
* Returns the TUIO state of this TuioObject.
* @return the TUIO state of this TuioObject
*/
unsigned char getTuioState() const;
};
}
#endif // INCLUDED_TUIOOBJECT_H

View File

@@ -0,0 +1,124 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
TuioPoint::TuioPoint (float xp, float yp) {
xpos = xp;
ypos = yp;
currentTime = TuioTime::getSystemTime();
startTime = currentTime;
}
TuioPoint::TuioPoint (TuioTime ttime, float xp, float yp) {
xpos = xp;
ypos = yp;
currentTime = ttime;
startTime = currentTime;
}
TuioPoint::TuioPoint (TuioPoint *tpoint) {
xpos = tpoint->getX();
ypos = tpoint->getY();
currentTime = TuioTime::getSystemTime();
startTime = currentTime;
}
void TuioPoint::update (TuioPoint *tpoint) {
xpos = tpoint->getX();
ypos = tpoint->getY();
}
void TuioPoint::update (float xp, float yp) {
xpos = xp;
ypos = yp;
}
void TuioPoint::update (TuioTime ttime, float xp, float yp) {
xpos = xp;
ypos = yp;
currentTime = ttime;
}
float TuioPoint::getX() const{
return xpos;
}
float TuioPoint::getY() const{
return ypos;
}
float TuioPoint::getDistance(float xp, float yp) const{
float dx = xpos-xp;
float dy = ypos-yp;
return sqrtf(dx*dx+dy*dy);
}
float TuioPoint::getScreenDistance(float xp, float yp, int w, int h) const{
float dx = w*xpos-w*xp;
float dy = h*ypos-h*yp;
return sqrtf(dx*dx+dy*dy);
}
float TuioPoint::getDistance(TuioPoint *tpoint) const{
return getDistance(tpoint->getX(),tpoint->getY());
}
float TuioPoint::getAngle(float xp, float yp) const{
float side = xpos-xp;
float height = ypos-yp;
float distance = getDistance(xp,yp);
float angle = (float)(asin(side/distance)+M_PI/2);
if (height<0) angle = 2.0f*(float)M_PI-angle;
return angle;
}
float TuioPoint::getAngle(TuioPoint *tpoint) const{
return getAngle(tpoint->getX(),tpoint->getY());
}
float TuioPoint::getAngleDegrees(float xp, float yp) const{
return ((getAngle(xp,yp)/(float)M_PI)*180.0f);
}
float TuioPoint::getAngleDegrees(TuioPoint *tpoint) const{
return ((getAngle(tpoint)/(float)M_PI)*180.0f);
}
int TuioPoint::getScreenX(int width) const{
return (int)floor(xpos*width+0.5f);
}
int TuioPoint::getScreenY(int height) const{
return (int)floor(ypos*height+0.5f);
}
TuioTime TuioPoint::getTuioTime() const{
return currentTime;
}
TuioTime TuioPoint::getStartTime() const{
return startTime;
}

View File

@@ -0,0 +1,213 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "limits.h"
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
namespace TUIO2 {
/**
* The TuioPoint class on the one hand is a simple tobj and utility class to handle TUIO positions in general,
* on the other hand the TuioPoint is the base class for the TuioPointer and TuioToken classes.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioPoint {
protected:
/**
* X coordinate, representated as a floating point value in a range of 0..1
*/
float xpos;
/**
* X coordinate, representated as a floating point value in a range of 0..1
*/
float ypos;
/**
* The time stamp of the last update represented as TuioTime (time since session start)
*/
TuioTime currentTime;
/**
* The creation time of this TuioPoint represented as TuioTime (time since session start)
*/
TuioTime startTime;
public:
/**
* This constructor takes two floating point coordinate arguments
* and sets the coordinate attributes to these values.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
*/
TuioPoint (float xp, float yp);
/**
* This constructor takes a TuioTime object and two floating point coordinate arguments and sets
* its coordinate attributes to these values and its time stamp to the provided TUIO time object.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
*/
TuioPoint (TuioTime ttime, float xp, float yp);
/**
* This constructor takes a TuioPoint argument and sets its coordinate attributes
* to the coordinates of the provided TuioPoint and its time stamp to the current session time.
*
* @param tpoint the TuioPoint to assign
*/
TuioPoint (TuioPoint *tpoint);
/**
* The destructor is doing nothing in particular.
*/
~TuioPoint(){};
/**
* Takes a TuioPoint argument and updates its coordinate attributes
* to the coordinates of the provided TuioPoint and leaves its time stamp unchanged.
*
* @param tpoint the TuioPoint to assign
*/
void update (TuioPoint *tpoint);
/**
* Takes two floating point coordinate arguments and updates its coordinate attributes
* to the coordinates of the provided TuioPoint and leaves its time stamp unchanged.
*
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
*/
void update (float xp, float yp);
/**
* Takes a TuioTime object and two floating point coordinate arguments and updates its coordinate attributes
* to the coordinates of the provided TuioPoint and its time stamp to the provided TUIO time object.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
*/
void update (TuioTime ttime, float xp, float yp);
/**
* Returns the X coordinate of this TuioPoint.
* @return the X coordinate of this TuioPoint
*/
float getX() const;
/**
* Returns the Y coordinate of this TuioPoint.
* @return the Y coordinate of this TuioPoint
*/
float getY() const;
/**
* Returns the distance to the provided coordinates
*
* @param xp the X coordinate of the distant point
* @param yp the Y coordinate of the distant point
* @return the distance to the provided coordinates
*/
float getDistance(float xp, float yp) const;
/**
* Returns the distance to the provided coordinates
*
* @param xp the X coordinate of the distant point
* @param yp the Y coordinate of the distant point
* @return the distance to the provided coordinates
*/
float getScreenDistance(float xp, float yp, int w, int h) const;
/**
* Returns the distance to the provided TuioPoint
*
* @param tpoint the distant TuioPoint
* @return the distance to the provided TuioPoint
*/
float getDistance(TuioPoint *tpoint) const;
/**
* Returns the angle to the provided coordinates
*
* @param xp the X coordinate of the distant point
* @param yp the Y coordinate of the distant point
* @return the angle to the provided coordinates
*/
float getAngle(float xp, float yp) const;
/**
* Returns the angle to the provided TuioPoint
*
* @param tpoint the distant TuioPoint
* @return the angle to the provided TuioPoint
*/
float getAngle(TuioPoint *tpoint) const;
/**
* Returns the angle in degrees to the provided coordinates
*
* @param xp the X coordinate of the distant point
* @param yp the Y coordinate of the distant point
* @return the angle in degrees to the provided TuioPoint
*/
float getAngleDegrees(float xp, float yp) const;
/**
* Returns the angle in degrees to the provided TuioPoint
*
* @param tpoint the distant TuioPoint
* @return the angle in degrees to the provided TuioPoint
*/
float getAngleDegrees(TuioPoint *tpoint) const;
/**
* Returns the X coordinate in pixels relative to the provided screen width.
*
* @param width the screen width
* @return the X coordinate of this TuioPoint in pixels relative to the provided screen width
*/
int getScreenX(int width) const;
/*
* Returns the Y coordinate in pixels relative to the provided screen height.
*
* @param height the screen height
* @return the Y coordinate of this TuioPoint in pixels relative to the provided screen height
*/
int getScreenY(int height) const;
/**
* Returns current time stamp of this TuioPoint as TuioTime
*
* @return the time stamp of this TuioPoint as TuioTime
*/
TuioTime getTuioTime() const;
/**
* Returns the start time of this TuioPoint as TuioTime.
*
* @return the start time of this TuioPoint as TuioTime
*/
TuioTime getStartTime() const;
};
}
#endif

View File

@@ -0,0 +1,132 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioPointer.h"
using namespace TUIO2;
TuioPointer::TuioPointer (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(ttime,tobj,xp,yp,a) {
type_id = ti;
user_id = ui;
pointer_id = pi;
shear = sa;
radius = r;
pressure = p;
}
TuioPointer::TuioPointer (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(tobj,xp,yp,a) {
type_id = ti;
user_id = ui;
shear = sa;
pointer_id = pi;
radius = r;
pressure = p;
}
TuioPointer::TuioPointer (TuioObject *tobj, unsigned int pi, float xp, float yp, float a, float sa, float r, float p):TuioComponent(tobj,xp,yp,a) {
type_id = 0;
user_id = 0;
pointer_id = pi;
shear = sa;
radius = r;
pressure = p;
}
TuioPointer::TuioPointer (TuioPointer *tptr):TuioComponent(tptr) {
pointer_id = tptr->getPointerID();
type_id = tptr->getTypeID();
user_id = tptr->getUserID();
shear = tptr->getShear();
radius = tptr->getRadius();
pressure = tptr->getPressure();
}
void TuioPointer::update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa) {
TuioComponent::update(ttime,xp,yp,a,xs,ys,0,ma,0);
shear = sa;
radius = r;
pressure = p;
pressure_speed = ps;
pressure_accel = pa;
}
void TuioPointer::update (float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa) {
TuioComponent::update(xp,yp,a,xs,ys,0,ma,0);
shear = sa;
radius = r;
pressure = p;
pressure_speed = ps;
pressure_accel = pa;
}
void TuioPointer::update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p) {
TuioComponent::update(ttime,xp,yp,a);
shear = sa;
radius = r;
pressure = p;
}
void TuioPointer::update (TuioPointer *tptr) {
TuioComponent::update(tptr);
shear = tptr->getShear();
radius = tptr->getRadius();
pressure = tptr->getPressure();
}
unsigned int TuioPointer::getPointerID() const{
return pointer_id;
};
unsigned short TuioPointer::getTypeID() const{
return type_id;
};
unsigned short TuioPointer::getUserID() const{
return user_id;
};
unsigned int TuioPointer::getTypeUserID() const {
int tu_id = user_id << 16 | type_id;
return tu_id;
}
void TuioPointer::setTypeUserID(unsigned int tu_id) {
user_id = tu_id >> 16;
type_id = tu_id & 0x0000FFFF;
}
float TuioPointer::getShear() const{
return shear;
};
float TuioPointer::getRadius() const{
return radius;
};
float TuioPointer::getPressure() const{
return pressure;
};
float TuioPointer::getPressureSpeed() const{
return pressure_speed;
}
float TuioPointer::getPressureAccel() const{
return pressure_accel;
}

View File

@@ -0,0 +1,263 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOPOINTER_H
#define INCLUDED_TUIOPOINTER_H
#include "TuioComponent.h"
namespace TUIO2 {
/**
* The TuioPointer class encapsulates /tuio2/ptr TUIO pointers.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioPointer: public TuioComponent {
protected:
/**
* The individual pointer ID number that is assigned to each TuioPointer.
*/
unsigned int pointer_id;
/**
* The pointer type ID that is assigned to each TuioPointer.
*/
unsigned short type_id;
/**
* The user ID that is assigned to each TuioPointer.
*/
unsigned short user_id;
/**
* The shear angle that is assigned to each TuioPointer.
*/
float shear;
/**
* The action radius that is assigned to each TuioPointer.
*/
float radius;
/**
* The pressure that is assigned to each TuioPointer.
*/
float pressure;
/**
* The pressure speed value.
*/
float pressure_speed;
/**
* The pressure acceleration value.
*/
float pressure_accel;
public:
using TuioComponent::update;
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, Pointer ID, X and Y coordinate to the newly created TuioPointer.
*
* @param ttime the TuioTime to assign
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param pi the Pointer ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
*/
TuioPointer (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p);
/**
* This constructor takes the provided Session ID, Pointer ID, X and Y coordinate
* and assigs these values to the newly created TuioPointer.
*
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param pi the Pointer ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
*/
TuioPointer (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int pi, float xp, float yp, float a, float sa, float r, float p);
/**
* This constructor takes the provided Session ID, Pointer ID, X and Y coordinate
* and assigs these values to the newly created TuioPointer.
*
* @param tobj the TuioObject to assign
* @param pi the Pointer ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
*/
TuioPointer (TuioObject *tobj, unsigned int pi, float xp, float yp, float a, float sa, float r, float p);
/**
* This constructor takes the atttibutes of the provided TuioPointer
* and assigs these values to the newly created TuioPointer.
*
* @param tptr the TuioPointer to assign
*/
TuioPointer (TuioPointer *tptr);
/**
* The destructor is doing nothing in particular.
*/
~TuioPointer(){};
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate, width, pressure, X and Y velocity, motion acceleration,
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param ps the pressure velocity to assign
* @param ma the motion acceleration to assign
* @param pa the pressure acceleration to assign
*/
void update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa);
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate, width, pressure, X and Y velocity, motion acceleration,
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
* @param xs the X velocity to assign
* @param ys the Y velocity to assign
* @param ps the pressure velocity to assign
* @param ma the motion acceleration to assign
* @param pa the pressure acceleration to assign
*/
void update (float xp, float yp, float a, float sa, float r, float p, float xs, float ys, float ps, float ma, float pa);
/**
* Takes a TuioTime argument and assigns it along with the provided
* X and Y coordinate and angle to the private TuioToken attributes.
* The speed and accleration values are calculated accordingly.
*
* @param ttime the TuioTime to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
* @param sa the shear angle to assign
* @param r the radius to assign
* @param p the pressure to assign
*/
void update (TuioTime ttime, float xp, float yp, float a, float sa, float r, float p);
/**
* Takes the atttibutes of the provided TuioPointer
* and assigs these values to this TuioPointer.
* The TuioTime time stamp of this TuioComponent remains unchanged.
*
* @param ttok the TuioComponent to assign
*/
void update (TuioPointer *tptr);
/**
* Returns the Pointer ID of this TuioPointer.
* @return the Pointer ID of this TuioPointer
*/
unsigned int getPointerID() const;
/**
* Returns the Type ID of this TuioPointer.
* @return the Type ID of this TuioPointer
*/
unsigned short getTypeID() const;
/**
* Returns the User ID of this TuioPointer.
* @return the User ID of this TuioPointer
*/
unsigned short getUserID() const;
/**
* Returns the encoded Type & User ID of this TuioPointer.
* @return the encoded Type & User ID of this TuioPointer
*/
unsigned int getTypeUserID() const;
/**
* Decodes and assigns the Type & User ID to this TuioPointer.
* @param tu_id the encoded Type & User ID of this TuioPointer
*/
void setTypeUserID(unsigned int tu_id);
/**
* Returns the shear angle of this TuioPointer.
* @return the shear angle of this TuioPointer
*/
float getShear() const;
/**
* Returns the action radius of this TuioPointer.
* @return the action radius of this TuioPointer
*/
float getRadius() const;
/**
* Returns the Pressure of this TuioPointer.
* @return the Pressure of this TuioPointer
*/
float getPressure() const;
/**
* Returns the pressure speed of this TuioPointer.
* @return the pressure speed of this TuioPointer
*/
float getPressureSpeed() const;
/**
* Returns the pressure acceleration of this TuioPointer.
* @return the pressure acceleration of this TuioPointer
*/
float getPressureAccel() const;
};
}
#endif

View File

@@ -0,0 +1,329 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
using namespace osc;
TuioServer::TuioServer()
:local_sender (true)
,full_update (false)
,periodic_update (false)
,source (NULL)
{
primary_sender = new UdpSender();
initialize();
}
TuioServer::TuioServer(const char *host, unsigned short port)
:local_sender (true)
,full_update (false)
,periodic_update (false)
,source (NULL)
{
primary_sender = new UdpSender(host,port);
initialize();
}
TuioServer::TuioServer(OscSender *oscsend)
:primary_sender (oscsend)
,local_sender (false)
,full_update (false)
,periodic_update (false)
,source (NULL)
{
initialize();
}
void TuioServer::initialize() {
senderList.push_back(primary_sender);
int size = primary_sender->getBufferSize();
oscBuffer = new char[size];
oscPacket = new osc::OutboundPacketStream(oscBuffer,size);
fullBuffer = new char[size];
fullPacket = new osc::OutboundPacketStream(oscBuffer,size);
updateTime = TuioTime(currentFrameTime);
//sendEmptyTuioBundle();
invert_x = false;
invert_y = false;
invert_a = false;
}
TuioServer::~TuioServer() {
initTuioFrame(TuioTime::getSystemTime());
stopUntouchedMovingObjects();
initTuioFrame(TuioTime::getSystemTime());
removeUntouchedStoppedObjects();
sendEmptyTuioBundle();
delete []oscBuffer;
delete oscPacket;
delete []fullBuffer;
delete fullPacket;
if (local_sender) delete primary_sender;
}
void TuioServer::addOscSender(OscSender *sender) {
// add source address if previously local
/*if ((source_name) && (primary_sender->isLocal()) && (senderList.size()==1)) {
setSourceName(source_name);
}*/
// resize packets to smallest transport method
unsigned int size = sender->getBufferSize();
if (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) {
if (source==NULL) source = new TuioSource(name);
//else source->setSourceName(name);
}
void TuioServer::setDimension(unsigned short w, unsigned short h) {
if (source!=NULL) source->setDimension(w,h);
// decoder test
/*int dim = source->getDimension();
short width = dim >> 16;
short height = dim & 0x0000FFFF;
printf("dim: %i %i\n",width,height);*/
}
void TuioServer::commitTuioFrame() {
TuioManager::commitTuioFrame();
if(tobjUpdate) {
startTuioBundle(currentFrame);
for (std::list<TuioObject*>::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) {
if ((*tobj)->containsTuioToken()) {
TuioToken *ttok = (*tobj)->getTuioToken();
if ((full_update) || (ttok->getTuioTime()==currentFrameTime)) addTokenMessage(ttok);
}
if ((*tobj)->containsTuioPointer()) {
TuioPointer *tptr = (*tobj)->getTuioPointer();
if ((full_update) || (tptr->getTuioTime()==currentFrameTime)) addPointerMessage(tptr);
}
if ((*tobj)->containsTuioBounds()) {
TuioBounds *tbnd = (*tobj)->getTuioBounds();
if ((full_update) || (tbnd->getTuioTime()==currentFrameTime)) addBoundsMessage(tbnd);
}
if ((*tobj)->containsTuioSymbol()) {
TuioSymbol *tsym = (*tobj)->getTuioSymbol();
if ((full_update) || (tsym->getTuioTime()==currentFrameTime)) addSymbolMessage(tsym);
}
}
updateTime = TuioTime(currentFrameTime);
sendTuioBundle();
} else if (periodic_update) {
TuioTime timeCheck = currentFrameTime - updateTime;
if(timeCheck.getSeconds()>=update_interval) {
updateTime = TuioTime(currentFrameTime);
startTuioBundle(currentFrame);
if (full_update) {
for (std::list<TuioObject*>::iterator tobj = tobjList.begin(); tobj!=tobjList.end(); tobj++) {
// start a new packet if we exceed the packet capacity
if ((oscPacket->Capacity()-oscPacket->Size())<TOK_MESSAGE_SIZE) {
sendTuioBundle();
startTuioBundle(currentFrame);
}
addTokenMessage((*tobj)->getTuioToken());
}
}
sendTuioBundle();
}
}
tobjUpdate = false;
}
void TuioServer::sendEmptyTuioBundle() {
oscPacket->Clear();
(*oscPacket) << osc::BeginBundleImmediate;
(*oscPacket) << osc::BeginMessage( "/tuio2/frm") << 0 << TuioTime::getSystemTimeTag() << (int32)source->getDimension() << source->getSourceName() << osc::EndMessage;
(*oscPacket) << osc::BeginMessage( "/tuio2/alv") << osc::EndMessage;
(*oscPacket) << osc::EndBundle;
deliverOscPacket( oscPacket );
}
void TuioServer::sendFullTuioBundle() {
}
void TuioServer::checkBundleCapacity(int msg_size) {
int size = msg_size + ALV_MESSAGE_SIZE + 4*tobjList.size();
if ((oscPacket->Capacity()-oscPacket->Size())<size) {
(*oscPacket) << osc::EndBundle;
deliverOscPacket( oscPacket ); // send the intermediate bundle without final ALV message!
startTuioBundle(currentFrame);
}
}
void TuioServer::startTuioBundle(unsigned int fseq) {
oscPacket->Clear();
(*oscPacket) << osc::BeginBundleImmediate;
if (source) (*oscPacket) << osc::BeginMessage( "/tuio2/frm") << (int32)currentFrame << frameTimeTag << (int32)source->getDimension() << source->getSourceName();
(*oscPacket) << osc::EndMessage;
}
void TuioServer::addTokenMessage(TuioToken *ttok) {
// start a new packet if we exceed the packet capacity
checkBundleCapacity(TOK_MESSAGE_SIZE);
float xpos = ttok->getX();
float xvel = ttok->getXSpeed();
if (invert_x) {
xpos = 1 - xpos;
xvel = -1 * xvel;
}
float ypos = ttok->getY();
float yvel = ttok->getYSpeed();
if (invert_y) {
ypos = 1 - ypos;
yvel = -1 * yvel;
}
float angle = ttok->getAngle();
float rvel = ttok->getRotationSpeed();
if (invert_a) {
angle = 2.0f*(float)M_PI - angle;
rvel = -1 * rvel;
}
(*oscPacket) << osc::BeginMessage( "/tuio2/tok");
(*oscPacket) << (int32)ttok->getSessionID() << (int32)ttok->getTypeUserID() << (int32)ttok->getSymbolID() << xpos << ypos << angle;
(*oscPacket) << xvel << yvel << rvel << ttok->getMotionAccel() << ttok->getRotationAccel();
(*oscPacket) << osc::EndMessage;
}
void TuioServer::addPointerMessage(TuioPointer *tptr) {
// start a new packet if we exceed the packet capacity
checkBundleCapacity(PTR_MESSAGE_SIZE);
float xpos = tptr->getX();
float xvel = tptr->getXSpeed();
if (invert_x) {
xpos = 1 - xpos;
xvel = -1 * xvel;
}
float ypos = tptr->getY();
float yvel = tptr->getYSpeed();
if (invert_y) {
ypos = 1 - ypos;
yvel = -1 * yvel;
}
(*oscPacket) << osc::BeginMessage( "/tuio2/ptr");
(*oscPacket) << (int32)tptr->getSessionID() << (int32)tptr->getTypeUserID() << (int32)tptr->getPointerID();
(*oscPacket) << xpos << ypos << tptr->getAngle() << tptr->getShear() << tptr->getRadius() << tptr->getPressure();
(*oscPacket) << xvel << yvel << tptr->getPressureSpeed() << tptr->getMotionAccel() << tptr->getPressureAccel();
(*oscPacket) << osc::EndMessage;
}
void TuioServer::addBoundsMessage(TuioBounds *tbnd) {
// start a new packet if we exceed the packet capacity
checkBundleCapacity(BND_MESSAGE_SIZE);
float xpos = tbnd->getX();
float xvel = tbnd->getXSpeed();
if (invert_x) {
xpos = 1 - xpos;
xvel = -1 * xvel;
}
float ypos = tbnd->getY();
float yvel = tbnd->getYSpeed();
if (invert_y) {
ypos = 1 - ypos;
yvel = -1 * yvel;
}
float angle = tbnd->getAngle();
float rvel = tbnd->getRotationSpeed();
if (invert_a) {
angle = 2.0f*(float)M_PI - angle;
rvel = -1 * rvel;
}
(*oscPacket) << osc::BeginMessage( "/tuio2/bnd");
(*oscPacket) << (int32)tbnd->getSessionID() << xpos << ypos << angle << tbnd->getWidth() << tbnd->getHeight() << tbnd->getArea();
(*oscPacket) << xvel << yvel << rvel << tbnd->getMotionAccel() << tbnd->getRotationAccel();
(*oscPacket) << osc::EndMessage;
}
void TuioServer::addSymbolMessage(TuioSymbol *tsym) {
// start a new packet if we exceed the packet capacity
checkBundleCapacity(SYM_MESSAGE_SIZE);
(*oscPacket) << osc::BeginMessage( "/tuio2/sym");
(*oscPacket) << (int32)tsym->getSessionID() << (int32)tsym->getTypeUserID() << (int32)tsym->getSymbolID();
(*oscPacket) << tsym->getSymbolType() << tsym->getSymbolData();
(*oscPacket) << osc::EndMessage;
}
void TuioServer::sendTuioBundle() {
//int before = oscPacket->Capacity()-oscPacket->Size();
(*oscPacket) << osc::BeginMessage( "/tuio2/alv");
for(std::list<TuioObject*>::iterator tobj = tobjList.begin();tobj!= tobjList.end(); tobj++)
(*oscPacket) << (int32)(*tobj)->getSessionID();
(*oscPacket) << osc::EndMessage;
//int after = oscPacket->Capacity()-oscPacket->Size();
//printf("ALV_MESSAGE_SIZE: %i\n",before-after);
(*oscPacket) << osc::EndBundle;
deliverOscPacket( oscPacket );
}

View File

@@ -0,0 +1,210 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 <iostream>
#include <vector>
#include <stdio.h>
#ifndef WIN32
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#define TOK_MESSAGE_SIZE 108
#define PTR_MESSAGE_SIZE 68
#define BND_MESSAGE_SIZE 116
#define SYM_MESSAGE_SIZE 116
#define ALV_MESSAGE_SIZE 20
namespace TUIO2 {
/**
* <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 TuioTokens 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->setSource(src); // passes a TuioSource* argument<br/>
* ...<br/>
* server->initTuioFrame(TuioTime::getSessionTime());<br/>
* TuioToken *ttok = server->addTuioToken(xpos,ypos,angle);<br/>
* TuioPointer *tptr = server->addTuioPointer(xpos,ypos,width,pressure);<br/>
* TuioBounds *tbnd = server->addTuioBounds(xpos,ypos,angle,width,height,area);<br/>
* server->commitTuioFrame();<br/>
* ...<br/>
* server->initTuioFrame(TuioTime::getSessionTime());<br/>
* server->updateTuioToken(ttok,xpos,ypos,angle);<br/>
* server->updateTuioPointer(tptr,xpos,ypos,width,pressure);<br/>
* server->updateTuioBounds(tbnd,xpos,ypos,angle,width,height,area);<br/>
* server->commitTuioFrame();<br/>
* ...<br/>
* server->initTuioFrame(TuioTime::getSessionTime());<br/>
* server->removeTuioToken(ttok);<br/>
* server->removeTuioPointer(tptr);<br/>
* server->removeTuioBounds(tbnd);<br/>
* server->commitTuioFrame();<br/>
* </code></p>
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioServer : public TuioManager {
public:
/**
* This constructor creates a TuioServer that uses an internal UdpSender delivering the OSC data via UDP port 3333 on localhost
*/
TuioServer();
/**
* This constructor creates a TuioServer that uses an internal UdpSender delivering the OSC data via the provided UDP port on the provided host
*
* @param host the host name for UDP deleivery
* @param port the UDP port number on the provided host
*/
TuioServer(const char *host, unsigned short port);
/**
* This constructor creates a TuioServer that sends OSC data using the provided OscSender
*
* @param sender the OscSender used for OSC data delivery
*/
TuioServer(OscSender *sender);
/**
* The destructor is doing nothing in particular.
*/
~TuioServer();
/**
* Generates and sends TUIO messages of all currently active TUIO Components
*/
void sendFullTuioBundle();
/**
* Enables the full update of all currently active and inactive TUIO Components
*
*/
void enableFullUpdate() {
full_update = true;
}
/**
* Disables the full update of all currently active and inactive TUIO Components
*/
void disableFullUpdate() {
full_update = false;
}
/**
* Returns true if the full update of all currently active TUIO Components is enabled.
* @return true if the full update of all currently active TUIO Components is enabled
*/
bool fullUpdateEnabled() {
return full_update;
}
/**
* Disables the periodic full update of all currently active TUIO Components
*
* @param interval update interval in seconds, defaults to one second
*/
void enablePeriodicMessages(int interval=1) {
periodic_update = true;
update_interval = interval;
}
/**
* Disables the periodic full update of all currently active and inactive TUIO Components
*/
void disablePeriodicMessages() {
periodic_update = false;
}
/**
* Returns true if the periodic update of all currently active TUIO Components is enabled.
* @return true if the periodic update of all currently active TUIO Components is enabled
*/
bool periodicMessagesEnabled() {
return periodic_update;
}
/**
* Returns the periodic update interval in seconds.
* @return the periodic update interval in seconds
*/
int getUpdateInterval() {
return update_interval;
}
/**
* Commits the current frame.
* Generates and sends TUIO messages of all currently active and updated TUIO Components.
*/
void commitTuioFrame();
/**
* Creates the TuioSource that is transmitted within the /tuio2/frm source attributes.
*
* @param name the source name to assign
*/
void setSourceName(const char* name);
void setDimension(unsigned short w, unsigned short h);
void addOscSender(OscSender *sender);
private:
void initialize();
OscSender *primary_sender;
bool local_sender;
std::vector<OscSender*> senderList;
void deliverOscPacket(osc::OutboundPacketStream *packet);
osc::OutboundPacketStream *oscPacket;
char *oscBuffer;
osc::OutboundPacketStream *fullPacket;
char *fullBuffer;
void checkBundleCapacity(int size);
void startTuioBundle(unsigned int fseq);
void addTokenMessage(TuioToken *ttok);
void addPointerMessage(TuioPointer *tptr);
void addBoundsMessage(TuioBounds *tbnd);
void addSymbolMessage(TuioSymbol *tsym);
void sendTuioBundle();
void sendEmptyTuioBundle();
int update_interval;
bool full_update, periodic_update;
TuioTime updateTime;
TuioSource *source;
};
}
#endif /* INCLUDED_TUIOSERVER_H */

View File

@@ -0,0 +1,244 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOSOURCE_H
#define INCLUDED_TUIOSOURCE_H
#include <sstream>
#include <string.h>
#include <stdlib.h>
#include <iostream>
namespace TUIO2 {
/**
* The TuioSource class encapsulates the meta data for the TUIO source attributes provided in /tuio2/frm.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioSource {
protected:
/**
* The ID of the TUIO source
*/
unsigned int source_id;
/**
* The name of the TUIO source
*/
std::string source_name;
/**
* The instance of the TUIO source
*/
unsigned int source_instance;
/**
* The address of the TUIO source
*/
std::string source_address;
/**
* The encoded sensor dimension
*/
unsigned int dimension;
/**
* The TuioTime of the last frame
*/
TuioTime frameTime;
public:
/**
* Sets the ID, name and address of the TUIO source
*/
TuioSource() {
source_id = 0;
source_name = "default";
source_instance = 0;
source_address = "localhost";
dimension = 0;
};
/**
* Sets the ID, name and address of the TUIO source
*
* @param src_name the name of the TUIO source
*/
TuioSource(std::string src_name) {
source_id = 0;
source_name = src_name;
source_instance = 0;
source_address = "localhost";
dimension = 0;
};
/**
* Sets the ID, name and address of the TUIO source
*
* @param src_name the name of the TUIO source
*/
TuioSource(unsigned int sid, std::string src_string, unsigned int dim) {
source_id = sid;
setSourceString(src_string);
setDimension(dim);
};
/**
* Sets the ID, name and address of the TUIO source
*
* @param src_name the name of the TUIO source
* @param src_inst the instance of the TUIO source
* @param src_addr the address of the TUIO source
*/
TuioSource(std::string src_name, unsigned int src_inst, std::string src_addr) {
source_id = 0;
source_name = src_name;
source_instance = src_inst;
source_address = src_addr;
};
/**
* Sets the ID, name and address of the TUIO source
*
* @param src_id the ID of the TUIO source
* @param src_name the name of the TUIO source
* @param src_inst the instance of the TUIO source
* @param src_addr the address of the TUIO source
*/
TuioSource(unsigned int src_id, std::string src_name, unsigned int src_inst, std::string src_addr) {
source_id = src_id;
source_name = src_name;
source_instance = src_inst;
source_address = src_addr;
};
~TuioSource() {};
void setSourceString(std::string src_string) {
if (src_string.length()==0) return;
char *data = strdup(src_string.c_str());
char *name_inst = strtok(data, "@");
char *addr = strtok(NULL, "@");
if (addr!=NULL) source_address = std::string(addr);
else source_address = (char*)"0x7F000001";
char *name = strtok(name_inst, ":");
source_name = std::string(name);
char *inst = strtok(NULL, ":");
if (inst!=NULL) source_instance = atoi(inst);
else source_instance = 0;
}
void setSourceString(unsigned int src_id, std::string src_string) {
source_id = src_id;
setSourceString(src_string);
}
std::string getSourceString() {
std::stringstream src_stream;
src_stream << source_name << ":" << source_instance << "@" << source_address;
return src_stream.str();
}
/**
* Returns the ID of the TUIO source
*/
unsigned int getSourceID() { return source_id; }
/**
* Returns the name of the TUIO source
*/
const char* getSourceName() { return source_name.c_str(); }
/**
* Returns the instance of the TUIO source
*/
unsigned int getSourceInstance() { return source_instance; }
/**
* Returns the address of the TUIO source
*/
const char* getSourceAddress() { return source_address.c_str(); }
/**
* Encodes the sensor dimension
* @param w the sensor width
* @param h the sensor height
*/
void setDimension(unsigned short w, unsigned short h) {
dimension = w << 16 | h;
}
/**
* Sets the encoded sensor dimension
* @param d the sensor dimension
*/
void setDimension(unsigned int d) {
dimension = d;
}
/**
* Returns the encoded sensor dimension
* @return the encoded sensor dimension
*/
unsigned int getDimension() {
return dimension;
}
/**
* Returns the decoded sensor width
* @return the decoded sensor width
*/
unsigned short getWidth() {
unsigned short width = dimension >> 16;
return width;
}
/**
* Returns the decoded sensor height
* @return the decoded sensor height
*/
unsigned short getHeight() {
unsigned short height = dimension & 0x0000FFFF;
return height;
}
/**
* Sets the last frame time
* @param ttime the TuioTime of the last frame
*/
void setFrameTime(TuioTime ttime) {
frameTime = ttime;
}
/**
* Returns the last frame time
* @return the TuioTime of the last frame
*/
TuioTime getFrameTime() {
return frameTime;
}
};
}
#endif // INCLUDED_TUIOSOURCE_H

View File

@@ -0,0 +1,91 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioSymbol.h"
using namespace TUIO2;
TuioSymbol::TuioSymbol (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data):TuioComponent(ttime,tobj,0,0,0) {
currentTime = ttime;
startTime = currentTime;
type_id = ti;
user_id = ui;
symbol_id = sym;
symbol_type = std::string(type);
symbol_data = std::string(data);
state = TUIO_ADDED;
}
TuioSymbol::TuioSymbol (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data):TuioComponent(tobj,0,0,0) {
currentTime = TuioTime::getSystemTime();
startTime = currentTime;
type_id = ti;
user_id = ui;
symbol_id = sym;
symbol_type = std::string(type);
symbol_data = std::string(data);
state = TUIO_ADDED;
}
TuioSymbol::TuioSymbol (TuioSymbol *tsym):TuioComponent(tsym->getTuioTime(),tsym->getContainingTuioObject(),0,0,0) {
currentTime = TuioTime::getSystemTime();
startTime = currentTime;
session_id = tsym->getSessionID();
type_id = tsym->getTypeID();
user_id = tsym->getUserID();
symbol_id = tsym->getSymbolID();
symbol_type = tsym->getSymbolType();
symbol_data = tsym->getSymbolData();
state = TUIO_ADDED;
}
unsigned int TuioSymbol::getSymbolID() const {
return symbol_id;
}
unsigned short TuioSymbol::getTypeID() const {
return type_id;
}
unsigned short TuioSymbol::getUserID() const {
return user_id;
}
unsigned int TuioSymbol::getTypeUserID() const {
int tu_id = user_id << 16 | type_id;
return tu_id;
}
void TuioSymbol::setTypeUserID(unsigned int tu_id) {
user_id = tu_id >> 16;
type_id = tu_id & 0x0000FFFF;
}
const char* TuioSymbol::getSymbolType() const {
return symbol_type.c_str();
}
const char* TuioSymbol::getSymbolData() const {
return symbol_data.c_str();
}
void TuioSymbol::update(TuioTime ttime) {
TuioComponent::update(ttime,0,0);
}

View File

@@ -0,0 +1,160 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOSYMBOL_H
#define INCLUDED_TUIOSYMBOL_H
//#pragma clang diagnostic ignored "-Woverloaded-virtual"
#include "TuioTime.h"
#include "TuioComponent.h"
#include <string>
namespace TUIO2 {
/**
* The TuioSymbol class encapsulates /tuio2/sym TUIO symbol.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioSymbol : public TuioComponent {
protected:
/**
* The unique Session ID that is assigned to each TUIO tobj.
*/
unsigned int session_id;
/**
* The individual symbol ID number that is assigned to each TuioToken.
*/
unsigned int symbol_id;
/**
* The symbol type ID that is assigned to each TuioToken.
*/
unsigned short type_id;
/**
* The user ID that is assigned to each TuioToken.
*/
unsigned short user_id;
/**
* The symbol type descriptor
*/
std::string symbol_type;
/**
* The actual symbol data
*/
std::string symbol_data;
/**
* The time stamp of the last update represented as TuioTime (time since session start)
*/
TuioTime currentTime;
/**
* The creation time of this TuioPoint represented as TuioTime (time since session start)
*/
TuioTime startTime;
/**
* Reflects the current state of the TuioSymbol
*/
unsigned char state;
public:
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, Type ID, User ID and Symbol ID as well as the Symbol type and data.
*
* @param ttime the TuioTime to assign
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param sym the Symbol ID to assign
* @param type the symbol type descriptor
* @param data the symbol data to assign
*/
TuioSymbol (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data);
/**
* This constructor assigns the provided Session ID, Type ID, User ID and Symbol ID
* as well as the Symbol type and data.
*
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param sym the Symbol ID to assign
* @param type the symbol type descriptor
* @param data the symbol data to assign
*/
TuioSymbol (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, const char *type, const char *data);
/**
* This constructor takes a TuioSymbol argument and sets its attributes
* to the ones of the provided TuioSymbol.
*
* @param tsym the TuioSymbol to assign
*/
TuioSymbol (TuioSymbol *tsym);
/**
* Returns the Symbol ID of this TuioSymbol.
* @return the Symbol ID of this TuioSymbol
*/
unsigned int getSymbolID() const;
/**
* Returns the Type ID of this TuioSymbol.
* @return the Type ID of this TuioSymbol
*/
unsigned short getTypeID() const;
/**
* Returns the User ID of this TuioSymbol.
* @return the User ID of this TuioSymbol
*/
unsigned short getUserID() const;
/**
* Returns the encoded Type & User ID of this TuioSymbol.
* @return the encoded Type & User ID of this TuioSymbol
*/
unsigned int getTypeUserID() const;
/**
* Decodes and assigns the Type & User ID to this TuioSymbol.
* @param tu_id the encoded Type & User ID of this TuioSymbol
*/
void setTypeUserID(unsigned int tu_id);
/**
* Returns the Type string of this TuioSymbol.
* @return the Type string of this TuioSymbol
*/
const char* getSymbolType() const;
/**
* Returns the actual data of this TuioSymbol.
* @return the actual data of this TuioSymbol
*/
const char* getSymbolData() const;
void update(TuioTime ttime);
/*void update(TuioTime ttime, float xp, float yp);
void update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma);
void update (TuioSymbol *tsym);*/
};
}
#endif

View File

@@ -0,0 +1,160 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
long TuioTime::start_seconds = 0;
long TuioTime::start_micro_seconds = 0;
TuioTime::TuioTime (long msec) {
seconds = msec/MSEC_SECOND;
micro_seconds = USEC_MILLISECOND*(msec%MSEC_SECOND);
}
TuioTime::TuioTime (osc::TimeTag timetag) {
osc::uint32 secs = timetag >> 32;
osc::uint32 frac = timetag & 0x00000000FFFFFFFF;
seconds = secs - JAN_1970;
micro_seconds = frac / NTP_UNITS;
}
TuioTime::TuioTime (long sec, long usec) {
seconds = sec;
micro_seconds = usec;
}
TuioTime TuioTime::operator+(long us) {
long sec = seconds + us/USEC_SECOND;
long usec = micro_seconds + us%USEC_SECOND;
return TuioTime(sec,usec);
}
TuioTime TuioTime::operator+(TuioTime ttime) {
long sec = seconds + ttime.getSeconds();
long usec = micro_seconds + ttime.getMicroseconds();
sec += usec/USEC_SECOND;
usec = usec%USEC_SECOND;
return TuioTime(sec,usec);
}
TuioTime TuioTime::operator-(long us) {
long sec = seconds - us/USEC_SECOND;
long usec = micro_seconds - us%USEC_SECOND;
if (usec<0) {
usec += USEC_SECOND;
sec--;
}
return TuioTime(sec,usec);
}
TuioTime TuioTime::operator-(TuioTime ttime) {
long sec = seconds - ttime.getSeconds();
long usec = micro_seconds - ttime.getMicroseconds();
if (usec<0) {
usec += USEC_SECOND;
sec--;
}
return TuioTime(sec,usec);
}
void TuioTime::operator=(TuioTime ttime) {
seconds = ttime.getSeconds();
micro_seconds = ttime.getMicroseconds();
}
bool TuioTime::operator==(TuioTime ttime) {
if ((seconds==(long)ttime.getSeconds()) && (micro_seconds==(long)ttime.getMicroseconds())) return true;
else return false;
}
bool TuioTime::operator!=(TuioTime ttime) {
if ((seconds!=(long)ttime.getSeconds()) || (micro_seconds!=(long)ttime.getMicroseconds())) return true;
else return false;
}
void TuioTime::reset() {
seconds = 0;
micro_seconds = 0;
TuioTime system_time = getSystemTime();
seconds = system_time.getSeconds();
micro_seconds = system_time.getMicroseconds();
}
long TuioTime::getSeconds() const{
return seconds;
}
long TuioTime::getMicroseconds() const{
return micro_seconds;
}
long TuioTime::getTotalMilliseconds() const{
return seconds*MSEC_SECOND+micro_seconds/MSEC_SECOND;
}
unsigned int TuioTime::getFrameID() const{
return frame_id;
}
void TuioTime::setFrameID(unsigned int f_id) {
frame_id = f_id;
}
/*void TuioTime::initSession() {
TuioTime startTime = TuioTime::getSystemTime();
start_seconds = startTime.getSeconds();
start_micro_seconds = startTime.getMicroseconds();
}
TuioTime TuioTime::getSessionTime() {
return (getSystemTime() - getStartTime());
}*/
TuioTime TuioTime::getStartTime() {
return TuioTime(start_seconds,start_micro_seconds);
}
TuioTime TuioTime::getSystemTime() {
#ifdef WIN32
TuioTime systemTime(GetTickCount());
#else
struct timeval tv;
struct timezone tz;
gettimeofday(&tv,&tz);
TuioTime systemTime(tv.tv_sec,tv.tv_usec);
#endif
return systemTime;
}
osc::TimeTag TuioTime::getSystemTimeTag() {
TuioTime systemTime = getSystemTime();
osc::uint32 secs = systemTime.getSeconds() + JAN_1970;
osc::uint32 frac = systemTime.getMicroseconds() * NTP_UNITS;
osc::uint64 timetag = (osc::uint64) secs << 32 | frac;
return osc::TimeTag(timetag);
}

View File

@@ -0,0 +1,222 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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"
#include "oscpack/osc/OscTypes.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
#define JAN_1970 0x83aa7e80 /* 2208988800 1970 - 1900 in seconds */
#define NTP_UNITS 4294.967295 /* NTP units per second */
namespace TUIO2 {
/**
* The TuioTime class is a simple structure that is used to reprent the time that has elapsed since the session start.
* The time is internally represented as seconds and fractions of microseconds which should be more than sufficient for gesture related timing requirements.
* Therefore at the beginning of a typical TUIO session the static method initSession() will set the reference time for the session.
* Another important static method getSessionTime will return a TuioTime object representing the time elapsed since the session start.
* The class also provides various addtional convience method, which allow some simple time arithmetics.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioTime {
private:
long seconds;
long micro_seconds;
static long start_seconds;
static long start_micro_seconds;
unsigned int frame_id;
public:
/**
* The default constructor takes no arguments and sets
* the Seconds and Microseconds attributes of the newly created TuioTime both to zero.
*/
TuioTime ():seconds(0),micro_seconds(0),frame_id(0) {};
/**
* The destructor is doing nothing in particular.
*/
~TuioTime() {}
/**
* This constructor takes the provided time represented in total Milliseconds
* and assigs this value to the newly created TuioTime.
*
* @param msec the total time in Millseconds
*/
TuioTime (long msec);
/**
* This constructor takes the provided time in OSC format
* and assigs this value to the newly created TuioTime.
*
* @param tag the time in OSC format
*/
TuioTime (osc::TimeTag timetag);
/**
* This constructor takes the provided time represented in Seconds and Microseconds
* and assigs these value to the newly created TuioTime.
*
* @param sec the total time in seconds
* @param usec the microseconds time component
*/
TuioTime (long sec, long usec);
/**
* Sums the provided time value represented in total Microseconds to this TuioTime.
*
* @param us the total time to add in Microseconds
* @return the sum of this TuioTime with the provided argument in microseconds
*/
TuioTime operator+(long us);
/**
* Sums the provided TuioTime to the private Seconds and Microseconds attributes.
*
* @param ttime the TuioTime to add
* @return the sum of this TuioTime with the provided TuioTime argument
*/
TuioTime operator+(TuioTime ttime);
/**
* Subtracts the provided time represented in Microseconds from the private Seconds and Microseconds attributes.
*
* @param us the total time to subtract in Microseconds
* @return the subtraction result of this TuioTime minus the provided time in Microseconds
*/
TuioTime operator-(long us);
/**
* Subtracts the provided TuioTime from the private Seconds and Microseconds attributes.
*
* @param ttime the TuioTime to subtract
* @return the subtraction result of this TuioTime minus the provided TuioTime
*/
TuioTime operator-(TuioTime ttime);
/**
* Assigns the provided TuioTime to the private Seconds and Microseconds attributes.
*
* @param ttime the TuioTime to assign
*/
void operator=(TuioTime ttime);
/**
* Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
*
* @param ttime the TuioTime to compare
* @return true if the two TuioTime have equal Seconds and Microseconds attributes
*/
bool operator==(TuioTime ttime);
/**
* Takes a TuioTime argument and compares the provided TuioTime to the private Seconds and Microseconds attributes.
*
* @param ttime the TuioTime to compare
* @return true if the two TuioTime have differnt Seconds or Microseconds attributes
*/
bool operator!=(TuioTime ttime);
/**
* Resets the seconds and micro_seconds attributes to zero.
*/
void reset();
/**
* Returns the TuioTime Seconds component.
* @return the TuioTime Seconds component
*/
long getSeconds() const;
/**
* Returns the TuioTime Microseconds component.
* @return the TuioTime Microseconds component
*/
long getMicroseconds() const;
/**
* Returns the total TuioTime in Milliseconds.
* @return the total TuioTime in Milliseconds
*/
long getTotalMilliseconds() const;
/**
* Returns the assigned Frame ID.
* @return the assigned Frame ID
*/
unsigned int getFrameID() const;
/**
* assigns a Frame ID.
* @f_id the Frame ID to assign
*/
void setFrameID(unsigned int f_id);
/**
* This static method globally resets the TUIO session time.
*/
//static void initSession();
/**
* Returns the present TuioTime representing the time since session start.
* @return the present TuioTime representing the time since session start
*/
//tatic TuioTime getSessionTime();
/**
* Returns the absolut TuioTime representing the session start.
* @return the absolut TuioTime representing the session start
*/
static TuioTime getStartTime();
/**
* Returns the absolut TuioTime representing the current system time.
* @return the absolut TuioTime representing the current system time
*/
static TuioTime getSystemTime();
/**
* Returns the absolut TuioTime representing the current system time.
* @return the absolut TuioTime representing the current system time
*/
static osc::TimeTag getSystemTimeTag();
};
}
#endif /* INCLUDED_TUIOTIME_H */

View File

@@ -0,0 +1,69 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 "TuioToken.h"
using namespace TUIO2;
TuioToken::TuioToken (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a):TuioComponent(ttime, tobj, xp, yp,a) {
type_id = ti;
user_id = ui;
symbol_id = sym;
}
TuioToken::TuioToken (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a):TuioComponent(tobj, xp, yp, a) {
type_id = ti;
user_id = ui;
symbol_id = sym;
}
TuioToken::TuioToken (TuioObject *tobj, unsigned int sym, float xp, float yp, float a):TuioComponent(tobj, xp, yp, a) {
type_id = 0;
user_id = 0;
symbol_id = sym;
}
TuioToken::TuioToken (TuioToken *ttok):TuioComponent(ttok) {
symbol_id = ttok->getSymbolID();
}
void TuioToken::stop (TuioTime ttime) {
update(ttime,xpos,ypos,angle);
}
unsigned int TuioToken::getSymbolID() const{
return symbol_id;
}
unsigned short TuioToken::getTypeID() const{
return type_id;
};
unsigned short TuioToken::getUserID() const{
return user_id;
};
unsigned int TuioToken::getTypeUserID() const {
int tu_id = user_id << 16 | type_id;
return tu_id;
}
void TuioToken::setTypeUserID(unsigned int tu_id) {
user_id = tu_id >> 16;
type_id = tu_id & 0x0000FFFF;
}

View File

@@ -0,0 +1,151 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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_TUIOTOKEN_H
#define INCLUDED_TUIOTOKEN_H
#include "TuioComponent.h"
namespace TUIO2 {
/**
* The TuioToken class encapsulates /tuio2/tok TUIO tokens.
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL TuioToken: public TuioComponent {
protected:
/**
* The individual symbol ID number that is assigned to each TuioToken.
*/
unsigned int symbol_id;
/**
* The symbol type ID that is assigned to each TuioToken.
*/
unsigned short type_id;
/**
* The user ID that is assigned to each TuioToken.
*/
unsigned short user_id;
public:
using TuioComponent::update;
/**
* This constructor takes a TuioTime argument and assigns it along with the provided
* Session ID, Symbol ID, X and Y coordinate and angle to the newly created TuioToken.
*
* @param ttime the TuioTime to assign
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
TuioToken (TuioTime ttime, TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a);
/**
* This constructor takes the provided Session ID, Symbol ID, X and Y coordinate
* and angle, and assigs these values to the newly created TuioToken.
*
* @param tobj the TuioObject to assign
* @param ti the Type ID to assign
* @param ui the User ID to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
TuioToken (TuioObject *tobj, unsigned short ti, unsigned short ui, unsigned int sym, float xp, float yp, float a);
/**
* This constructor takes the provided Session ID, Symbol ID, X and Y coordinate
* and angle, and assigs these values to the newly created TuioToken.
*
* @param tobj the TuioObject to assign
* @param sym the Symbol ID to assign
* @param xp the X coordinate to assign
* @param yp the Y coordinate to assign
* @param a the angle to assign
*/
TuioToken (TuioObject *tobj, unsigned int sym, float xp, float yp, float a);
/**
* This constructor takes the atttibutes of the provided TuioToken
* and assigs these values to the newly created TuioToken.
*
* @param ttok the TuioToken to assign
*/
TuioToken (TuioToken *ttok);
/**
* The destructor is doing nothing in particular.
*/
~TuioToken() {};
/**
* This method is used to calculate the speed and acceleration values of a
* TuioToken with unchanged position and angle.
*/
void stop (TuioTime ttime);
/**
* Takes the atttibutes of the provided TuioToken
* and assigs these values to this TuioToken.
* The TuioTime time stamp of this TuioToken remains unchanged.
*
* @param ttok the TuioToken to assign
*/
void update (TuioToken *ttok);
/**
* Returns the symbol ID of this TuioToken.
* @return the symbol ID of this TuioToken
*/
unsigned int getSymbolID() const;
/**
* Returns the Type ID of this TuioToken.
* @return the Type ID of this TuioToken
*/
unsigned short getTypeID() const;
/**
* Returns the User ID of this TuioToken.
* @return the User ID of this TuioToken
*/
unsigned short getUserID() const;
/**
* Returns the encoded Type & User ID of this TuioToken.
* @return the encoded Type & User ID of this TuioToken
*/
unsigned int getTypeUserID() const;
/**
* Decodes and assigns the Type & User ID to this TuioToken.
* @param tu_id the encoded Type & User ID of this TuioToken
*/
void setTypeUserID(unsigned int tu_id);
};
}
#endif

View File

@@ -0,0 +1,92 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2;
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(unsigned short port):locked (false) {
try {
socket = new UdpListeningReceiveSocket(IpEndpointName( IpEndpointName::ANY_ADDRESS, port ), this );
} catch (std::exception &e) {
std::cerr << "could not bind to UDP port " << port << std::endl;
socket = NULL;
}
if (socket!=NULL) {
if (!socket->IsBound()) {
delete socket;
socket = NULL;
} else std::cout << "listening to TUIO/UDP messages on port " << port << std::endl;
}
}
UdpReceiver::~UdpReceiver() {
delete socket;
}
void UdpReceiver::connect(bool lk) {
if (connected) return;
if (socket==NULL) return;
locked = lk;
if (!locked) {
#ifndef WIN32
pthread_create(&thread , NULL, ClientThreadFunc, this);
#else
DWORD threadId;
thread = CreateThread( 0, 0, ClientThreadFunc, this, 0, &threadId );
#endif
} else socket->Run();
connected = true;
}
void UdpReceiver::disconnect() {
if (!connected) return;
if (socket==NULL) {
connected = false;
locked = false;
return;
}
socket->Break();
if (!locked) {
#ifdef WIN32
if( thread ) CloseHandle( thread );
#endif
thread = 0;
} else locked = false;
connected = false;
}

View File

@@ -0,0 +1,77 @@
/*
TUIO2 C++ Library
Copyright (c) 2009-2014 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 TUIO2 {
/**
* The UdpReceiver provides the OscReceiver functionality for the UDP transport method
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL UdpReceiver: public OscReceiver {
public:
/**
* The UDP socket is only public to be accessible from the thread function
*/
UdpListeningReceiveSocket *socket;
/**
* This constructor creates a UdpReceiver instance listening to the provided UDP port
*
* @param port the number of the UDP port to listen to, defaults to 3333
*/
UdpReceiver (unsigned short port=3333);
/**
* The destructor is doing nothing in particular.
*/
virtual ~UdpReceiver();
/**
* The UdpReceiver connects and starts receiving TUIO messages via UDP
*
* @param lock running in the background if set to false (default)
*/
void connect(bool lock=false);
/**
* The UdpReceiver disconnects and stops receiving TUIO messages via UDP
*/
void disconnect();
private:
#ifndef WIN32
pthread_t thread;
#else
HANDLE thread;
#endif
bool locked;
};
};
#endif /* INCLUDED_UDPRECEIVER_H */

View 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 TUIO2;
UdpSender::UdpSender() {
try {
local = true;
long unsigned int ip = GetHostByName("localhost");
socket = new UdpTransmitSocket(IpEndpointName(ip, 3333));
buffer_size = MAX_UDP_SIZE;
std::cout << "TUIO/UDP messages to " << "127.0.0.1@3333" << std::endl;
} catch (std::exception &e) {
std::cout << "could not create UDP socket" << std::endl;
socket = NULL;
throw std::exception();
}
}
UdpSender::UdpSender(const char *host, int port) {
try {
if ((strcmp(host,"127.0.0.1")==0) || (strcmp(host,"localhost")==0)) {
local = true;
buffer_size = MAX_UDP_SIZE;
} else {
local = false;
buffer_size = IP_MTU_SIZE;
}
long unsigned int ip = GetHostByName(host);
socket = new UdpTransmitSocket(IpEndpointName(ip, port));
std::cout << "TUIO/UDP messages to " << host << "@" << port << std::endl;
} catch (std::exception &e) {
std::cout << "could not create UDP socket" << std::endl;
socket = NULL;
throw std::exception();
}
}
UdpSender::UdpSender(const char *host, int port, int size) {
try {
if ((strcmp(host,"127.0.0.1")==0) || (strcmp(host,"localhost")==0)) {
local = true;
} else local = false;
long unsigned int ip = GetHostByName(host);
socket = new UdpTransmitSocket(IpEndpointName(ip, port));
if (buffer_size>MAX_UDP_SIZE) buffer_size = MAX_UDP_SIZE;
else if (buffer_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;
}

View 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 TUIO2 {
/**
* The UdpSender implements the UDP transport method for OSC
*
* @author Martin Kaltenbrunner
* @version 2.0.a0
*/
class LIBDECL UdpSender : public OscSender {
public:
/**
* The default constructor creates a UdpSender that sends to the default UDP port 3333 on localhost
* using the maximum packet size of 65536 bytes for single packets on the loopback device
*/
UdpSender();
/**
* This constructor creates a UdpSender that sends to the provided port on the the given host
* using the default MTU size of 1500 bytes to deliver unfragmented UDP packets on a LAN
*
* @param host the receiving host name
* @param port the outgoing UDP port number
*/
UdpSender(const char *host, int port);
/**
* This constructor creates a UdpSender that sends to the provided port on the the given host
* the UDP packet size can be set to a value between 576 and 65536 bytes
*
* @param host the receiving host name
* @param port the outgoing UDP port number
* @param size the maximum UDP packet size
*/
UdpSender(const char *host, int port, int size);
/**
* The destructor closes the socket.
*/
virtual ~UdpSender();
/**
* This method delivers the provided OSC data
*
* @param *bundle the OSC stream to deliver
* @return true if the data was delivered successfully
*/
bool sendOscPacket (osc::OutboundPacketStream *bundle);
/**
* This method returns the connection state
*
* @return true if the connection is alive
*/
bool isConnected ();
const char* tuio_type() { return "TUIO/UDP"; }
private:
UdpTransmitSocket *socket;
};
}
#endif /* INCLUDED_UDPSENDER_H */

View File

@@ -0,0 +1,286 @@
/*
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 TUIO2;
WebSockSender::WebSockSender()
:TcpSender( 8080 )
{
local = true;
buffer_size = MAX_TCP_SIZE;
port_no = 8080;
}
WebSockSender::WebSockSender(int port)
:TcpSender( port )
{
local = true;
buffer_size = MAX_TCP_SIZE;
port_no = port;
}
bool WebSockSender::sendOscPacket (osc::OutboundPacketStream *bundle) {
if (!connected) return false;
if ( bundle->Size() > buffer_size ) return false;
if ( bundle->Size() == 0 ) return false;
#ifdef OSC_HOST_LITTLE_ENDIAN
data_size[0] = bundle->Size()>>24;
data_size[1] = (bundle->Size()>>16) & 255;
data_size[2] = (bundle->Size()>>8) & 255;
data_size[3] = (bundle->Size()) & 255;
#else
*((int32_t*)data_size) = bundle->Size();
#endif
#ifdef WIN32
std::list<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"
"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;
}

View 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 TUIO2 {
/**
* The WebSockSender implements the WebSocket transport method for OSC
*
* @author Florian Echtler
* @version 2.0.a0
*/
class LIBDECL WebSockSender : public TcpSender {
public:
/**
* The default constructor creates a WebSockSender that listens to the default HTTP-alt port 8080 on localhost
*/
WebSockSender();
/**
* This constructor creates a WebSockSender that listens to the provided port
*
* @param port the listening WebSocket port number
*/
WebSockSender(int port);
/**
* The destructor closes the socket.
*/
virtual ~WebSockSender() {}
/**
* This method delivers the provided OSC data
*
* @param *bundle the OSC stream to deliver
* @return true if the data was delivered successfully
*/
bool sendOscPacket (osc::OutboundPacketStream *bundle);
/**
* This method is called whenever a new client connects
*
* @param tcp_client the socket handle of the new client
*/
void newClient( int tcp_client );
const char* tuio_type() { return "TUIO/WEB"; }
private:
void sha1( uint8_t digest[SHA1_HASH_SIZE], const uint8_t* inbuf, size_t length );
std::string base64( uint8_t* buffer, size_t size );
};
}
#endif /* INCLUDED_WEBSOCKSENDER_H */

View 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()

View 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.

View 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.
###

View 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.

View 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 );
}
}
}

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View File

@@ -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 "oscpack/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;
}

View 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 "oscpack/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 "oscpack/ip/PacketListener.h"
#include "oscpack/ip/TimerListener.h"
#if defined(__APPLE__) && !defined(_SOCKLEN_T)
// pre system 10.3 didn't have socklen_t
typedef ssize_t socklen_t;
#endif
static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
{
std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr =
(endpoint.address == IpEndpointName::ANY_ADDRESS)
? INADDR_ANY
: htonl( endpoint.address );
sockAddr.sin_port =
(endpoint.port == IpEndpointName::ANY_PORT)
? 0
: htons( endpoint.port );
}
static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
{
return IpEndpointName(
(sockAddr.sin_addr.s_addr == INADDR_ANY)
? IpEndpointName::ANY_ADDRESS
: ntohl( sockAddr.sin_addr.s_addr ),
(sockAddr.sin_port == 0)
? IpEndpointName::ANY_PORT
: ntohs( sockAddr.sin_port )
);
}
class UdpSocket::Implementation{
bool isBound_;
bool isConnected_;
int socket_;
struct sockaddr_in connectedAddr_;
struct sockaddr_in sendToAddr_;
public:
Implementation()
: isBound_( false )
, isConnected_( false )
, socket_( -1 )
{
if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
throw std::runtime_error("unable to create udp socket\n");
}
std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
sendToAddr_.sin_family = AF_INET;
}
~Implementation()
{
if (socket_ != -1) close(socket_);
}
void SetEnableBroadcast( bool enableBroadcast )
{
int broadcast = (enableBroadcast) ? 1 : 0; // int on posix
setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
}
void SetAllowReuse( bool allowReuse )
{
int reuseAddr = (allowReuse) ? 1 : 0; // int on posix
setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
#ifdef __APPLE__
// needed also for OS X - enable multiple listeners for a single port on same network interface
int reusePort = (allowReuse) ? 1 : 0; // int on posix
setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort));
#endif
}
IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{
assert( isBound_ );
// first connect the socket to the remote server
struct sockaddr_in connectSockAddr;
SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
throw std::runtime_error("unable to connect udp socket\n");
}
// get the address
struct sockaddr_in sockAddr;
std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
socklen_t length = sizeof(sockAddr);
if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
throw std::runtime_error("unable to getsockname\n");
}
if( isConnected_ ){
// reconnect to the connected address
if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
throw std::runtime_error("unable to connect udp socket\n");
}
}else{
// unconnect from the remote address
struct sockaddr_in unconnectSockAddr;
std::memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
unconnectSockAddr.sin_family = AF_UNSPEC;
// address fields are zero
int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
throw std::runtime_error("unable to un-connect udp socket\n");
}
}
return IpEndpointNameFromSockaddr( sockAddr );
}
void Connect( const IpEndpointName& remoteEndpoint )
{
SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
throw std::runtime_error("unable to connect udp socket\n");
}
isConnected_ = true;
}
void Send( const char *data, std::size_t size )
{
assert( isConnected_ );
send( socket_, data, size, 0 );
}
void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
{
sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
sendToAddr_.sin_port = htons( remoteEndpoint.port );
sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
}
void Bind( const IpEndpointName& localEndpoint )
{
struct sockaddr_in bindSockAddr;
SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
throw std::runtime_error("unable to bind udp socket\n");
}
isBound_ = true;
}
bool IsBound() const { return isBound_; }
std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
{
assert( isBound_ );
struct sockaddr_in fromAddr;
socklen_t fromAddrLen = sizeof(fromAddr);
ssize_t result = recvfrom(socket_, data, size, 0,
(struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
if( result < 0 )
return 0;
remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
remoteEndpoint.port = ntohs(fromAddr.sin_port);
return (std::size_t)result;
}
int Socket() { return socket_; }
};
UdpSocket::UdpSocket()
{
impl_ = new Implementation();
}
UdpSocket::~UdpSocket()
{
delete impl_;
}
void UdpSocket::SetEnableBroadcast( bool enableBroadcast )
{
impl_->SetEnableBroadcast( enableBroadcast );
}
void UdpSocket::SetAllowReuse( bool allowReuse )
{
impl_->SetAllowReuse( allowReuse );
}
IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{
return impl_->LocalEndpointFor( remoteEndpoint );
}
void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
{
impl_->Connect( remoteEndpoint );
}
void UdpSocket::Send( const char *data, std::size_t size )
{
impl_->Send( data, size );
}
void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
{
impl_->SendTo( remoteEndpoint, data, size );
}
void UdpSocket::Bind( const IpEndpointName& localEndpoint )
{
impl_->Bind( localEndpoint );
}
bool UdpSocket::IsBound() const
{
return impl_->IsBound();
}
std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
{
return impl_->ReceiveFrom( remoteEndpoint, data, size );
}
struct AttachedTimerListener{
AttachedTimerListener( int id, int p, TimerListener *tl )
: initialDelayMs( id )
, periodMs( p )
, listener( tl ) {}
int initialDelayMs;
int periodMs;
TimerListener *listener;
};
static bool CompareScheduledTimerCalls(
const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
{
return lhs.first < rhs.first;
}
SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
extern "C" /*static*/ void InterruptSignalHandler( int );
/*static*/ void InterruptSignalHandler( int )
{
multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
signal( SIGINT, SIG_DFL );
}
class SocketReceiveMultiplexer::Implementation{
std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
std::vector< AttachedTimerListener > timerListeners_;
volatile bool break_;
int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
double GetCurrentTimeMs() const
{
struct timeval t;
gettimeofday( &t, 0 );
return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
}
public:
Implementation()
{
if( pipe(breakPipe_) != 0 )
throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
}
~Implementation()
{
close( breakPipe_[0] );
close( breakPipe_[1] );
}
void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
{
assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
// we don't check that the same socket has been added multiple times, even though this is an error
socketListeners_.push_back( std::make_pair( listener, socket ) );
}
void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
{
std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
assert( i != socketListeners_.end() );
socketListeners_.erase( i );
}
void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
{
timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
}
void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
{
timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
}
void DetachPeriodicTimerListener( TimerListener *listener )
{
std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
while( i != timerListeners_.end() ){
if( i->listener == listener )
break;
++i;
}
assert( i != timerListeners_.end() );
timerListeners_.erase( i );
}
void Run()
{
break_ = false;
char *data = 0;
try{
// configure the master fd_set for select()
fd_set masterfds, tempfds;
FD_ZERO( &masterfds );
FD_ZERO( &tempfds );
// in addition to listening to the inbound sockets we
// also listen to the asynchronous break pipe, so that AsynchronousBreak()
// can break us out of select() from another thread.
FD_SET( breakPipe_[0], &masterfds );
int fdmax = breakPipe_[0];
for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
i != socketListeners_.end(); ++i ){
if( fdmax < i->second->impl_->Socket() )
fdmax = i->second->impl_->Socket();
FD_SET( i->second->impl_->Socket(), &masterfds );
}
// configure the timer queue
double currentTimeMs = GetCurrentTimeMs();
// expiry time ms, listener
std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
i != timerListeners_.end(); ++i )
timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
const int MAX_BUFFER_SIZE = 4098;
data = new char[ MAX_BUFFER_SIZE ];
IpEndpointName remoteEndpoint;
struct timeval timeout;
while( !break_ ){
tempfds = masterfds;
struct timeval *timeoutPtr = 0;
if( !timerQueue_.empty() ){
double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
if( timeoutMs < 0 )
timeoutMs = 0;
long timoutSecondsPart = (long)(timeoutMs * .001);
timeout.tv_sec = (time_t)timoutSecondsPart;
// 1000000 microseconds in a second
timeout.tv_usec = (suseconds_t)((timeoutMs - (timoutSecondsPart * 1000)) * 1000);
timeoutPtr = &timeout;
}
if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 ){
if( break_ ){
break;
}else if( errno == EINTR ){
// on returning an error, select() doesn't clear tempfds.
// so tempfds would remain all set, which would cause read( breakPipe_[0]...
// below to block indefinitely. therefore if select returns EINTR we restart
// the while() loop instead of continuing on to below.
continue;
}else{
throw std::runtime_error("select failed\n");
}
}
if( FD_ISSET( breakPipe_[0], &tempfds ) ){
// clear pending data from the asynchronous break pipe
char c;
read( breakPipe_[0], &c, 1 );
}
if( break_ )
break;
for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
i != socketListeners_.end(); ++i ){
if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
std::size_t size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
if( size > 0 ){
i->first->ProcessPacket( data, (int)size, remoteEndpoint );
if( break_ )
break;
}
}
}
// execute any expired timers
currentTimeMs = GetCurrentTimeMs();
bool resort = false;
for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
i->second.listener->TimerExpired();
if( break_ )
break;
i->first += i->second.periodMs;
resort = true;
}
if( resort )
std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
}
delete [] data;
}catch(...){
if( data )
delete [] data;
throw;
}
}
void Break()
{
break_ = true;
}
void AsynchronousBreak()
{
break_ = true;
// Send a termination message to the asynchronous break pipe, so select() will return
write( breakPipe_[1], "!", 1 );
}
};
SocketReceiveMultiplexer::SocketReceiveMultiplexer()
{
impl_ = new Implementation();
}
SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
{
delete impl_;
}
void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
{
impl_->AttachSocketListener( socket, listener );
}
void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
{
impl_->DetachSocketListener( socket, listener );
}
void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
{
impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
}
void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
{
impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
}
void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
{
impl_->DetachPeriodicTimerListener( listener );
}
void SocketReceiveMultiplexer::Run()
{
impl_->Run();
}
void SocketReceiveMultiplexer::RunUntilSigInt()
{
assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
multiplexerInstanceToAbortWithSigInt_ = this;
signal( SIGINT, InterruptSignalHandler );
impl_->Run();
signal( SIGINT, SIG_DFL );
multiplexerInstanceToAbortWithSigInt_ = 0;
}
void SocketReceiveMultiplexer::Break()
{
impl_->Break();
}
void SocketReceiveMultiplexer::AsynchronousBreak()
{
impl_->AsynchronousBreak();
}

View File

@@ -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;
}

View 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();
}

View File

@@ -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 */

View 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 */

View 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 */

View File

@@ -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

View 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 */

View 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 */

View File

@@ -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

View File

@@ -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 */

View 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

View 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 */

View 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

View 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 */

View File

@@ -0,0 +1 @@
set (DEFAULT_MODULE ON)

View File

@@ -0,0 +1,62 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_TOUCH___TOUCHEAR___H__
#define __OPENSPACE_MODULE_TOUCH___TOUCHEAR___H__
#include <modules/touch/ext/libTUIO2/TUIO2/TuioListener.h>
#include <modules/touch/ext/libTUIO2/TUIO2/TuioClient.h>
#include <modules/touch/ext/libTUIO2/TUIO2/UdpReceiver.h>
#include <modules/touch/ext/libTUIO2/TUIO2/TcpReceiver.h>
#include <math.h>
#include <vector>
using namespace TUIO2;
class TuioEar : public TuioListener {
public:
TuioEar();
~TuioEar() {
tuioClient->disconnect();
delete tuioClient;
delete oscReceiver;
}
void tuioAdd(TuioObject *tobj);
void tuioUpdate(TuioObject *tobj);
void tuioRemove(TuioObject *tobj);
void tuioRefresh(TuioTime frameTime);
std::vector<TuioPointer>* getInput() { return &list; }
private:
TuioClient *tuioClient;
OscReceiver *oscReceiver;
std::vector<TuioPointer> list;
std::vector<TuioPointer>::iterator it;
};
#endif // __OPENSPACE_MODULE_TOUCH___TOUCHWRAPPER___H__

View File

@@ -0,0 +1,89 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/touch/include/TuioEar.h>
#include <vector>
#include <algorithm> // std::find
#include <ghoul/logging/logmanager.h>
namespace {
const std::string _loggerCat = "TuioEar";
}
void TuioEar::tuioAdd(TuioObject *tobj) {
if (tobj->containsNewTuioToken()) LINFO("add tok " << tobj->getTuioToken()->getSessionID() << "\n");
if (tobj->containsNewTuioPointer()) {
list.push_back(tobj->getTuioPointer());
LINFO("add ptr " << tobj->getTuioPointer()->getSessionID() << ", Fingers: " << list.size() << "\n");
}
if(tobj->containsNewTuioBounds()) LINFO("add bnd " << tobj->getTuioBounds()->getSessionID() << "\n");
if(tobj->containsNewTuioSymbol()) LINFO("add sym " << tobj->getTuioSymbol()->getSessionID() << "\n");
//std::cout << "add obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << std::endl;
//std::cout << std::flush;
}
void TuioEar::tuioUpdate(TuioObject *tobj) {
if (tobj->containsTuioToken()) LINFO("set tok " << tobj->getTuioToken()->getSessionID() << "\n");
if (tobj->containsTuioPointer()) LINFO("set ptr " << tobj->getTuioPointer()->getSessionID() << "\n");
if (tobj->containsTuioBounds()) LINFO("set bnd " << tobj->getTuioBounds()->getSessionID() << "\n");
if (tobj->containsTuioSymbol()) LINFO("set sym " << tobj->getTuioSymbol()->getSessionID() << "\n");
//std::cout << "set obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ") "<< tobj->getX() << " " << tobj->getY() << " " << tobj->getAngle() << " " << tobj->getMotionSpeed() << " " << tobj->getRotationSpeed() << " " << tobj->getMotionAccel() << " " << tobj->getRotationAccel() << std::endl;
//std::cout << std::flush;
}
void TuioEar::tuioRemove(TuioObject *tobj) {
if (tobj->containsTuioToken()) LINFO("del tok " << tobj->getTuioToken()->getSessionID() << "\n");
if (tobj->containsTuioPointer()) {
it = list.begin();
for (; it != list.end(); ++it) {
if (it->getSessionID() == tobj->getTuioPointer()->getSessionID()) {
list.erase(it);
LINFO("del ptr " << tobj->getTuioPointer()->getSessionID() << ", Fingers: " << list.size() << "\n");
break;
}
}
}
if (tobj->containsTuioBounds()) LINFO("del bnd " << tobj->getTuioBounds()->getSessionID() << "\n");
if (tobj->containsTuioSymbol()) LINFO("del sym " << tobj->getTuioSymbol()->getSessionID() << "\n");
//std::cout << "del obj " << tobj->getSymbolID() << " (" << tobj->getSessionID() << "/"<< tobj->getTuioSourceID() << ")" << std::endl;
//std::cout << std::flush;
}
void TuioEar::tuioRefresh(TuioTime frameTime) {
LINFO("refresh " << frameTime.getFrameID() << " "<< frameTime.getTotalMilliseconds() << "\n");
}
TuioEar::TuioEar() {
oscReceiver = new UdpReceiver(3333);
//oscReceiver = new TcpReceiver("127.0.0.1",3333);
tuioClient = new TuioClient(oscReceiver);
tuioClient->addTuioListener(this);
tuioClient->connect();
}

View File

@@ -0,0 +1,33 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/touch/touchmodule.h>
namespace openspace {
TouchModule::TouchModule()
: OpenSpaceModule("Touch")
{}
} // namespace openspace

View File

@@ -0,0 +1,39 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__
#define __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__
#include <openspace/util/openspacemodule.h>
namespace openspace {
class TouchModule : public OpenSpaceModule {
public:
TouchModule();
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_TOUCH___TOUCHMODULE___H__

View File

@@ -7,7 +7,7 @@ return {
-- Sets the scene that is to be loaded by OpenSpace. A scene file is a description
-- of all entities that will be visible during an instance of OpenSpace
Scene = "${SCENE}/default.scene",
Scene = "${SCENE}/globebrowsing.scene",
-- Scene = "${SCENE}/globebrowsing.scene",
-- Scene = "${SCENE}/rosetta.scene",