annotate addons/ofxOsc/src/ofxOscReceiver.cpp @ 52:13194a9dca77 tip

Added exporting of image and text data
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 17 Jul 2012 22:13:10 +0100
parents b299a65a3ad0
children
rev   line source
andrew@0 1 /*
andrew@0 2
andrew@0 3 Copyright (c) 2007-2009, Damian Stewart
andrew@0 4 All rights reserved.
andrew@0 5
andrew@0 6 Redistribution and use in source and binary forms, with or without
andrew@0 7 modification, are permitted provided that the following conditions are met:
andrew@0 8 * Redistributions of source code must retain the above copyright
andrew@0 9 notice, this list of conditions and the following disclaimer.
andrew@0 10 * Redistributions in binary form must reproduce the above copyright
andrew@0 11 notice, this list of conditions and the following disclaimer in the
andrew@0 12 documentation and/or other materials provided with the distribution.
andrew@0 13 * Neither the name of the developer nor the
andrew@0 14 names of its contributors may be used to endorse or promote products
andrew@0 15 derived from this software without specific prior written permission.
andrew@0 16
andrew@0 17 THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY
andrew@0 18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
andrew@0 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
andrew@0 20 DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY
andrew@0 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
andrew@0 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
andrew@0 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
andrew@0 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
andrew@0 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
andrew@0 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
andrew@0 27 */
andrew@0 28
andrew@0 29 #include "ofxOscReceiver.h"
andrew@0 30
andrew@0 31 #ifndef TARGET_WIN32
andrew@0 32 #include <pthread.h>
andrew@0 33 #endif
andrew@0 34 #include <iostream>
andrew@0 35 #include <assert.h>
andrew@0 36
andrew@0 37 ofxOscReceiver::ofxOscReceiver()
andrew@0 38 {
andrew@0 39 listen_socket = NULL;
andrew@0 40 }
andrew@0 41
andrew@0 42 void ofxOscReceiver::setup( int listen_port )
andrew@0 43 {
andrew@0 44 // if we're already running, shutdown before running again
andrew@0 45 if ( listen_socket )
andrew@0 46 shutdown();
andrew@0 47
andrew@0 48 // create the mutex
andrew@0 49 #ifdef TARGET_WIN32
andrew@0 50 mutex = CreateMutexA( NULL, FALSE, NULL );
andrew@0 51 #else
andrew@0 52 pthread_mutex_init( &mutex, NULL );
andrew@0 53 #endif
andrew@0 54
andrew@0 55 // create socket
andrew@0 56 socketHasShutdown = false;
andrew@0 57 listen_socket = new UdpListeningReceiveSocket( IpEndpointName( IpEndpointName::ANY_ADDRESS, listen_port ), this );
andrew@0 58
andrew@0 59 // start thread
andrew@0 60 #ifdef TARGET_WIN32
andrew@0 61 thread = CreateThread(
andrew@0 62 NULL, // default security attributes
andrew@0 63 0, // use default stack size
andrew@0 64 &ofxOscReceiver::startThread, // thread function
andrew@0 65 (void*)this, // argument to thread function
andrew@0 66 0, // use default creation flags
andrew@0 67 NULL); // we don't the the thread id
andrew@0 68
andrew@0 69 #else
andrew@0 70 pthread_create( &thread, NULL, &ofxOscReceiver::startThread, (void*)this );
andrew@0 71 #endif
andrew@0 72 }
andrew@0 73
andrew@0 74 void ofxOscReceiver::shutdown()
andrew@0 75 {
andrew@0 76 if ( listen_socket )
andrew@0 77 {
andrew@0 78 // tell the socket to shutdown
andrew@0 79 listen_socket->AsynchronousBreak();
andrew@0 80 // wait for shutdown to complete
andrew@0 81 while (!socketHasShutdown)
andrew@0 82 {
andrew@0 83 #ifdef TARGET_WIN32
andrew@0 84 Sleep(1);
andrew@0 85 #else
andrew@0 86 // sleep 0.1ms
andrew@0 87 usleep(100);
andrew@0 88 #endif
andrew@0 89 }
andrew@0 90
andrew@0 91 // thread will clean up itself
andrew@0 92
andrew@0 93 // clean up the mutex
andrew@0 94 #ifdef TARGET_WIN32
andrew@0 95 ReleaseMutex( mutex );
andrew@0 96 #else
andrew@0 97 pthread_mutex_destroy( &mutex );
andrew@0 98 #endif
andrew@0 99
andrew@0 100 // delete the socket
andrew@0 101 delete listen_socket;
andrew@0 102 listen_socket = NULL;
andrew@0 103 }
andrew@0 104 }
andrew@0 105
andrew@0 106 ofxOscReceiver::~ofxOscReceiver()
andrew@0 107 {
andrew@0 108 shutdown();
andrew@0 109 }
andrew@0 110
andrew@0 111 #ifdef TARGET_WIN32
andrew@0 112 DWORD WINAPI
andrew@0 113 #else
andrew@0 114 void*
andrew@0 115 #endif
andrew@0 116 ofxOscReceiver::startThread( void* receiverInstance )
andrew@0 117 {
andrew@0 118 // cast the instance
andrew@0 119 ofxOscReceiver* instance = (ofxOscReceiver*)receiverInstance;
andrew@0 120 // start the socket listener
andrew@0 121 instance->listen_socket->Run();
andrew@0 122 // socket listener has finished - remember this fact
andrew@0 123 instance->socketHasShutdown = true;
andrew@0 124 // return
andrew@0 125 #ifdef TARGET_WIN32
andrew@0 126 return 0;
andrew@0 127 #else
andrew@0 128 return NULL;
andrew@0 129 #endif
andrew@0 130 }
andrew@0 131
andrew@0 132 void ofxOscReceiver::ProcessMessage( const osc::ReceivedMessage &m, const IpEndpointName& remoteEndpoint )
andrew@0 133 {
andrew@0 134 // convert the message to an ofxOscMessage
andrew@0 135 ofxOscMessage* ofMessage = new ofxOscMessage();
andrew@0 136
andrew@0 137 // set the address
andrew@0 138 ofMessage->setAddress( m.AddressPattern() );
andrew@0 139
andrew@0 140 // set the sender ip/host
andrew@0 141 char endpoint_host[ IpEndpointName::ADDRESS_STRING_LENGTH ];
andrew@0 142 remoteEndpoint.AddressAsString( endpoint_host );
andrew@0 143 ofMessage->setRemoteEndpoint( endpoint_host, remoteEndpoint.port );
andrew@0 144
andrew@0 145 // transfer the arguments
andrew@0 146 for ( osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
andrew@0 147 arg != m.ArgumentsEnd();
andrew@0 148 ++arg )
andrew@0 149 {
andrew@0 150 if ( arg->IsInt32() )
andrew@0 151 ofMessage->addIntArg( arg->AsInt32Unchecked() );
andrew@0 152 else if ( arg->IsFloat() )
andrew@0 153 ofMessage->addFloatArg( arg->AsFloatUnchecked() );
andrew@0 154 else if ( arg->IsString() )
andrew@0 155 ofMessage->addStringArg( arg->AsStringUnchecked() );
andrew@0 156 else
andrew@0 157 {
andrew@0 158 assert( false && "message argument is not int, float, or string" );
andrew@0 159 }
andrew@0 160 }
andrew@0 161
andrew@0 162 // now add to the queue
andrew@0 163
andrew@0 164 // at this point we are running inside the thread created by startThread,
andrew@0 165 // so anyone who calls hasWaitingMessages() or getNextMessage() is coming
andrew@0 166 // from a different thread
andrew@0 167
andrew@0 168 // so we have to practise shared memory management
andrew@0 169
andrew@0 170 // grab a lock on the queue
andrew@0 171 grabMutex();
andrew@0 172
andrew@0 173 // add incoming message on to the queue
andrew@0 174 messages.push_back( ofMessage );
andrew@0 175
andrew@0 176 // release the lock
andrew@0 177 releaseMutex();
andrew@0 178 }
andrew@0 179
andrew@0 180 bool ofxOscReceiver::hasWaitingMessages()
andrew@0 181 {
andrew@0 182 // grab a lock on the queue
andrew@0 183 grabMutex();
andrew@0 184
andrew@0 185 // check the length of the queue
andrew@0 186 int queue_length = (int)messages.size();
andrew@0 187
andrew@0 188 // release the lock
andrew@0 189 releaseMutex();
andrew@0 190
andrew@0 191 // return whether we have any messages
andrew@0 192 return queue_length > 0;
andrew@0 193 }
andrew@0 194
andrew@0 195 bool ofxOscReceiver::getNextMessage( ofxOscMessage* message )
andrew@0 196 {
andrew@0 197 // grab a lock on the queue
andrew@0 198 grabMutex();
andrew@0 199
andrew@0 200 // check if there are any to be got
andrew@0 201 if ( messages.size() == 0 )
andrew@0 202 {
andrew@0 203 // no: release the mutex
andrew@0 204 releaseMutex();
andrew@0 205 return false;
andrew@0 206 }
andrew@0 207
andrew@0 208 // copy the message from the queue to message
andrew@0 209 ofxOscMessage* src_message = messages.front();
andrew@0 210 message->copy( *src_message );
andrew@0 211
andrew@0 212 // now delete the src message
andrew@0 213 delete src_message;
andrew@0 214 // and remove it from the queue
andrew@0 215 messages.pop_front();
andrew@0 216
andrew@0 217 // release the lock on the queue
andrew@0 218 releaseMutex();
andrew@0 219
andrew@0 220 // return success
andrew@0 221 return true;
andrew@0 222 }
andrew@0 223
andrew@0 224 void ofxOscReceiver::grabMutex()
andrew@0 225 {
andrew@0 226 #ifdef TARGET_WIN32
andrew@0 227 WaitForSingleObject( mutex, INFINITE );
andrew@0 228 #else
andrew@0 229 pthread_mutex_lock( &mutex );
andrew@0 230 #endif
andrew@0 231 }
andrew@0 232
andrew@0 233 void ofxOscReceiver::releaseMutex()
andrew@0 234 {
andrew@0 235 #ifdef TARGET_WIN32
andrew@0 236 ReleaseMutex( mutex );
andrew@0 237 #else
andrew@0 238 pthread_mutex_unlock( &mutex );
andrew@0 239 #endif
andrew@0 240 }