diff --git a/install.xml b/install.xml
index 797964f..fae0461 100644
--- a/install.xml
+++ b/install.xml
@@ -22,6 +22,40 @@
../../../addons/ofxOsc/src/ofxOscSender.cpp
../../../addons/ofxOsc/src/ofxOscSender.h
+
+
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/IpEndpointName.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/IpEndpointName.h
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/NetworkingUtils.h
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/PacketListener.h
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/TimerListener.h
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/UdpSocket.h
+
+
+
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/posix/NetworkingUtils.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/posix/UdpSocket.cpp
+
+
+
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/ip/win32/UdpSocketWin.cpp
+
+
+
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/MessageMappingOscPacketListener.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscException.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscHostEndianness.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscPacketListener.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.h
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscTypes.cpp
+ ../../../addons/ofxOsc/libs/oscpack/src/osc/OscTypes.h
+
@@ -31,13 +65,6 @@
- ../../../addons/ofxOsc/libs/oscpack/lib/win32/oscpack.a
- ../../../addons/ofxOsc/libs/oscpack/lib/win32/oscpack.lib
- ../../../addons/ofxOsc/libs/oscpack/lib/linux/liboscpack.a
- ../../../addons/ofxOsc/libs/oscpack/lib/linux64/liboscpack.a
- ../../../addons/ofxOsc/libs/oscpack/lib/osx/osc.a
- ../../../addons/ofxOsc/libs/oscpack/lib/iphone/osc.a
- ../../../addons/ofxOsc/libs/oscpack/lib/osx/osc.a
diff --git a/libs/oscpack/lib/osx/osc.a b/libs/oscpack/lib/osx/osc.a
deleted file mode 100644
index 643f536..0000000
Binary files a/libs/oscpack/lib/osx/osc.a and /dev/null differ
diff --git a/libs/oscpack/src/ip/IpEndpointName.cpp b/libs/oscpack/src/ip/IpEndpointName.cpp
new file mode 100644
index 0000000..65cfcc2
--- /dev/null
+++ b/libs/oscpack/src/ip/IpEndpointName.cpp
@@ -0,0 +1,81 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "IpEndpointName.h"
+
+#include
+
+#include "NetworkingUtils.h"
+
+
+unsigned long IpEndpointName::GetHostByName( const char *s )
+{
+ return ::GetHostByName(s);
+}
+
+
+void IpEndpointName::AddressAsString( char *s ) const
+{
+ if( address == ANY_ADDRESS ){
+ sprintf( s, "" );
+ }else{
+ sprintf( s, "%d.%d.%d.%d",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF) );
+ }
+}
+
+
+void IpEndpointName::AddressAndPortAsString( char *s ) const
+{
+ if( port == ANY_PORT ){
+ if( address == ANY_ADDRESS ){
+ sprintf( s, ":" );
+ }else{
+ sprintf( s, "%d.%d.%d.%d:",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF) );
+ }
+ }else{
+ if( address == ANY_ADDRESS ){
+ sprintf( s, ":%d", port );
+ }else{
+ sprintf( s, "%d.%d.%d.%d:%d",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF),
+ (int)port );
+ }
+ }
+}
diff --git a/libs/oscpack/include/ip/IpEndpointName.h b/libs/oscpack/src/ip/IpEndpointName.h
similarity index 96%
rename from libs/oscpack/include/ip/IpEndpointName.h
rename to libs/oscpack/src/ip/IpEndpointName.h
index 7d61d85..65bd62b 100644
--- a/libs/oscpack/include/ip/IpEndpointName.h
+++ b/libs/oscpack/src/ip/IpEndpointName.h
@@ -54,6 +54,8 @@ class IpEndpointName{
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;
diff --git a/libs/oscpack/include/ip/NetworkingUtils.h b/libs/oscpack/src/ip/NetworkingUtils.h
similarity index 100%
rename from libs/oscpack/include/ip/NetworkingUtils.h
rename to libs/oscpack/src/ip/NetworkingUtils.h
diff --git a/libs/oscpack/include/ip/PacketListener.h b/libs/oscpack/src/ip/PacketListener.h
similarity index 100%
rename from libs/oscpack/include/ip/PacketListener.h
rename to libs/oscpack/src/ip/PacketListener.h
diff --git a/libs/oscpack/include/ip/TimerListener.h b/libs/oscpack/src/ip/TimerListener.h
similarity index 100%
rename from libs/oscpack/include/ip/TimerListener.h
rename to libs/oscpack/src/ip/TimerListener.h
diff --git a/libs/oscpack/include/ip/UdpSocket.h b/libs/oscpack/src/ip/UdpSocket.h
similarity index 100%
rename from libs/oscpack/include/ip/UdpSocket.h
rename to libs/oscpack/src/ip/UdpSocket.h
diff --git a/libs/oscpack/src/ip/posix/NetworkingUtils.cpp b/libs/oscpack/src/ip/posix/NetworkingUtils.cpp
new file mode 100644
index 0000000..52ca45f
--- /dev/null
+++ b/libs/oscpack/src/ip/posix/NetworkingUtils.cpp
@@ -0,0 +1,59 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+#if !defined( __WIN32__ ) && !defined( _WIN32 )
+
+#include
+#include
+#include
+#include
+#include
+
+
+
+NetworkInitializer::NetworkInitializer() {}
+
+NetworkInitializer::~NetworkInitializer() {}
+
+
+unsigned long GetHostByName( const char *name )
+{
+ unsigned long result = 0;
+
+ struct hostent *h = gethostbyname( name );
+ if( h ){
+ struct in_addr a;
+ memcpy( &a, h->h_addr_list[0], h->h_length );
+ result = ntohl(a.s_addr);
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/oscpack/src/ip/posix/UdpSocket.cpp b/libs/oscpack/src/ip/posix/UdpSocket.cpp
new file mode 100644
index 0000000..d94d0a4
--- /dev/null
+++ b/libs/oscpack/src/ip/posix/UdpSocket.cpp
@@ -0,0 +1,561 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+#if !defined( __WIN32__ ) && !defined( _WIN32 )
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // for memset
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // for sockaddr_in
+
+#include "ip/PacketListener.h"
+#include "ip/TimerListener.h"
+
+
+#if defined(__APPLE__) && !defined(_SOCKLEN_T)
+// pre system 10.3 didn have socklen_t
+typedef ssize_t socklen_t;
+#endif
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ sockAddr.sin_family = AF_INET;
+
+ sockAddr.sin_addr.s_addr =
+ (endpoint.address == IpEndpointName::ANY_ADDRESS)
+ ? INADDR_ANY
+ : htonl( endpoint.address );
+
+ sockAddr.sin_port =
+ (endpoint.port == IpEndpointName::ANY_PORT)
+ ? 0
+ : htons( endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+ return IpEndpointName(
+ (sockAddr.sin_addr.s_addr == INADDR_ANY)
+ ? IpEndpointName::ANY_ADDRESS
+ : ntohl( sockAddr.sin_addr.s_addr ),
+ (sockAddr.sin_port == 0)
+ ? IpEndpointName::ANY_PORT
+ : ntohs( sockAddr.sin_port )
+ );
+}
+
+
+class UdpSocket::Implementation{
+ bool isBound_;
+ bool isConnected_;
+
+ int socket_;
+ struct sockaddr_in connectedAddr_;
+ struct sockaddr_in sendToAddr_;
+
+public:
+
+ Implementation()
+ : isBound_( false )
+ , isConnected_( false )
+ , socket_( -1 )
+ {
+ if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
+ throw std::runtime_error("unable to create udp socket\n");
+ }
+
+ // enable multicast addresses
+ int on = 1; // int on posix
+ setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+
+ // enable multiple listeners for a single port on same network interface
+ int reuse = 1; // int on posix
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
+
+ #ifdef __APPLE__
+ // needed also for OS X - enable multiple listeners for a single port on same network interface
+ int reusePort = 1; // int on posix
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort));
+ #endif
+
+ memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+ sendToAddr_.sin_family = AF_INET;
+ }
+
+ ~Implementation()
+ {
+ if (socket_ != -1) close(socket_);
+ }
+
+ IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+ {
+ assert( isBound_ );
+
+ // first connect the socket to the remote server
+
+ struct sockaddr_in connectSockAddr;
+ SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ // get the address
+
+ struct sockaddr_in sockAddr;
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ socklen_t length = sizeof(sockAddr);
+ if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+ throw std::runtime_error("unable to getsockname\n");
+ }
+
+ if( isConnected_ ){
+ // reconnect to the connected address
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ }else{
+ // unconnect from the remote address
+
+ struct sockaddr_in unconnectSockAddr;
+ memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
+ unconnectSockAddr.sin_family = AF_UNSPEC;
+ // address fields are zero
+ int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
+ if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
+ throw std::runtime_error("unable to un-connect udp socket\n");
+ }
+ }
+
+ return IpEndpointNameFromSockaddr( sockAddr );
+ }
+
+ void Connect( const IpEndpointName& remoteEndpoint )
+ {
+ SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ isConnected_ = true;
+ }
+
+ void Send( const char *data, int size )
+ {
+ assert( isConnected_ );
+
+ send( socket_, data, size, 0 );
+ }
+
+ void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+ {
+ sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+ sendToAddr_.sin_port = htons( remoteEndpoint.port );
+
+ sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+ }
+
+ void Bind( const IpEndpointName& localEndpoint )
+ {
+ struct sockaddr_in bindSockAddr;
+ SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+ if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+ throw std::runtime_error("unable to bind udp socket\n");
+ }
+
+ isBound_ = true;
+ }
+
+ bool IsBound() const { return isBound_; }
+
+ int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+ {
+ assert( isBound_ );
+
+ struct sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof(fromAddr);
+
+ int result = recvfrom(socket_, data, size, 0,
+ (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+ if( result < 0 )
+ return 0;
+
+ remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+ remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+ return result;
+ }
+
+ int Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+ impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+ delete impl_;
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+ return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+ impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, int size )
+{
+ impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+{
+ impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+ impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+ return impl_->IsBound();
+}
+
+int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+{
+ return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+ AttachedTimerListener( int id, int p, TimerListener *tl )
+ : initialDelayMs( id )
+ , periodMs( p )
+ , listener( tl ) {}
+ int initialDelayMs;
+ int periodMs;
+ TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls(
+ const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+ return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+ multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+ signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+ std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+ std::vector< AttachedTimerListener > timerListeners_;
+
+ volatile bool break_;
+ int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
+
+ double GetCurrentTimeMs() const
+ {
+ struct timeval t;
+
+ gettimeofday( &t, 0 );
+
+ return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
+ }
+
+public:
+ Implementation()
+ {
+ if( pipe(breakPipe_) != 0 )
+ throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
+ }
+
+ ~Implementation()
+ {
+ close( breakPipe_[0] );
+ close( breakPipe_[1] );
+ }
+
+ void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+ // we don't check that the same socket has been added multiple times, even though this is an error
+ socketListeners_.push_back( std::make_pair( listener, socket ) );
+ }
+
+ void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
+ std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+ assert( i != socketListeners_.end() );
+
+ socketListeners_.erase( i );
+ }
+
+ void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void DetachPeriodicTimerListener( TimerListener *listener )
+ {
+ std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ while( i != timerListeners_.end() ){
+ if( i->listener == listener )
+ break;
+ ++i;
+ }
+
+ assert( i != timerListeners_.end() );
+
+ timerListeners_.erase( i );
+ }
+
+ void Run()
+ {
+ break_ = false;
+
+ // configure the master fd_set for select()
+
+ fd_set masterfds, tempfds;
+ FD_ZERO( &masterfds );
+ FD_ZERO( &tempfds );
+
+ // in addition to listening to the inbound sockets we
+ // also listen to the asynchronous break pipe, so that AsynchronousBreak()
+ // can break us out of select() from another thread.
+ FD_SET( breakPipe_[0], &masterfds );
+ int fdmax = breakPipe_[0];
+
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i ){
+
+ if( fdmax < i->second->impl_->Socket() )
+ fdmax = i->second->impl_->Socket();
+ FD_SET( i->second->impl_->Socket(), &masterfds );
+ }
+
+
+ // configure the timer queue
+ double currentTimeMs = GetCurrentTimeMs();
+
+ // expiry time ms, listener
+ std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+ for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ i != timerListeners_.end(); ++i )
+ timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+ const int MAX_BUFFER_SIZE = 4098;
+ char *data = new char[ MAX_BUFFER_SIZE ];
+ IpEndpointName remoteEndpoint;
+
+ struct timeval timeout;
+
+ while( !break_ ){
+ tempfds = masterfds;
+
+ struct timeval *timeoutPtr = 0;
+ if( !timerQueue_.empty() ){
+ double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
+ if( timeoutMs < 0 )
+ timeoutMs = 0;
+
+ // 1000000 microseconds in a second
+ timeout.tv_sec = (long)(timeoutMs * .001);
+ timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000);
+ timeoutPtr = &timeout;
+ }
+
+ if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){
+ 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 ) ){
+
+ int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+ if( size > 0 ){
+ i->first->ProcessPacket( data, size, remoteEndpoint );
+ if( break_ )
+ break;
+ }
+ }
+ }
+
+ // execute any expired timers
+ currentTimeMs = GetCurrentTimeMs();
+ bool resort = false;
+ for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+ i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+ i->second.listener->TimerExpired();
+ if( break_ )
+ break;
+
+ i->first += i->second.periodMs;
+ resort = true;
+ }
+ if( resort )
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+ }
+
+ delete [] data;
+ }
+
+ void Break()
+ {
+ break_ = true;
+ }
+
+ void AsynchronousBreak()
+ {
+ break_ = true;
+
+ // Send a termination message to the asynchronous break pipe, so select() will return
+ 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();
+}
+#endif
diff --git a/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp b/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp
new file mode 100644
index 0000000..7e8572a
--- /dev/null
+++ b/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp
@@ -0,0 +1,90 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+#if defined( __WIN32__ ) || defined( _WIN32 )
+
+#include // this must come first to prevent errors with MSVC7
+#include
+#include
+#include
+
+
+static LONG initCount_ = 0;
+static bool winsockInitialized_ = false;
+
+NetworkInitializer::NetworkInitializer()
+{
+ if( InterlockedIncrement( &initCount_ ) == 1 ){
+ // there is a race condition here if one thread tries to access
+ // the library while another is still initializing it.
+ // i can't think of an easy way to fix it so i'm telling you here
+ // incase you need to init the library from two threads at once.
+ // this is why the header file advises to instantiate one of these
+ // in main() so that the initialization happens globally
+
+ // initialize winsock
+ WSAData wsaData;
+ int nCode = WSAStartup(MAKEWORD(1, 1), &wsaData);
+ if( nCode != 0 ){
+ //std::cout << "WSAStartup() failed with error code " << nCode << "\n";
+ }else{
+ winsockInitialized_ = true;
+ }
+ }
+}
+
+
+NetworkInitializer::~NetworkInitializer()
+{
+ if( InterlockedDecrement( &initCount_ ) == 0 ){
+ if( winsockInitialized_ ){
+ WSACleanup();
+ winsockInitialized_ = false;
+ }
+ }
+}
+
+
+unsigned long GetHostByName( const char *name )
+{
+ NetworkInitializer networkInitializer;
+
+ unsigned long result = 0;
+
+ struct hostent *h = gethostbyname( name );
+ if( h ){
+ struct in_addr a;
+ memcpy( &a, h->h_addr_list[0], h->h_length );
+ result = ntohl(a.s_addr);
+ }
+
+ return result;
+}
+#endif
diff --git a/libs/oscpack/src/ip/win32/UdpSocketWin.cpp b/libs/oscpack/src/ip/win32/UdpSocketWin.cpp
new file mode 100644
index 0000000..943e9a3
--- /dev/null
+++ b/libs/oscpack/src/ip/win32/UdpSocketWin.cpp
@@ -0,0 +1,544 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+#if defined( __WIN32__ ) || defined( _WIN32 )
+
+#include // this must come first to prevent errors with MSVC7
+#include
+#include // for timeGetTime()
+
+#include
+#include
+#include
+#include
+
+#ifndef WINCE
+#include
+#endif
+
+#include "ip/NetworkingUtils.h"
+#include "ip/PacketListener.h"
+#include "ip/TimerListener.h"
+
+
+typedef int socklen_t;
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ sockAddr.sin_family = AF_INET;
+
+ sockAddr.sin_addr.s_addr =
+ (endpoint.address == IpEndpointName::ANY_ADDRESS)
+ ? INADDR_ANY
+ : htonl( endpoint.address );
+
+ sockAddr.sin_port =
+ (endpoint.port == IpEndpointName::ANY_PORT)
+ ? (short)0
+ : htons( (short)endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+ return IpEndpointName(
+ (sockAddr.sin_addr.s_addr == INADDR_ANY)
+ ? IpEndpointName::ANY_ADDRESS
+ : ntohl( sockAddr.sin_addr.s_addr ),
+ (sockAddr.sin_port == 0)
+ ? IpEndpointName::ANY_PORT
+ : ntohs( sockAddr.sin_port )
+ );
+}
+
+
+class UdpSocket::Implementation{
+ NetworkInitializer networkInitializer_;
+
+ bool isBound_;
+ bool isConnected_;
+
+ SOCKET socket_;
+ struct sockaddr_in connectedAddr_;
+ struct sockaddr_in sendToAddr_;
+
+public:
+
+ Implementation()
+ : isBound_( false )
+ , isConnected_( false )
+ , socket_( INVALID_SOCKET )
+ {
+ if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == INVALID_SOCKET ){
+ throw std::runtime_error("unable to create udp socket\n");
+ }
+
+ // enable multicast addresses
+ char on = 1; // char on win32
+ setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+
+ // enable multiple listeners for a single port on same network interface
+ char reuse = 1; // char on win32
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
+
+ memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+ sendToAddr_.sin_family = AF_INET;
+ }
+
+ ~Implementation()
+ {
+ if (socket_ != INVALID_SOCKET) closesocket(socket_);
+ }
+
+ IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+ {
+ assert( isBound_ );
+
+ // first connect the socket to the remote server
+
+ struct sockaddr_in connectSockAddr;
+ SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ // get the address
+
+ struct sockaddr_in sockAddr;
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ socklen_t length = sizeof(sockAddr);
+ if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+ throw std::runtime_error("unable to getsockname\n");
+ }
+
+ if( isConnected_ ){
+ // reconnect to the connected address
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ }else{
+ // unconnect from the remote address
+
+ struct sockaddr_in unconnectSockAddr;
+ SockaddrFromIpEndpointName( unconnectSockAddr, IpEndpointName() );
+
+ if( connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)) < 0
+ && WSAGetLastError() != WSAEADDRNOTAVAIL ){
+ throw std::runtime_error("unable to un-connect udp socket\n");
+ }
+ }
+
+ return IpEndpointNameFromSockaddr( sockAddr );
+ }
+
+ void Connect( const IpEndpointName& remoteEndpoint )
+ {
+ SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ isConnected_ = true;
+ }
+
+ void Send( const char *data, int size )
+ {
+ assert( isConnected_ );
+
+ send( socket_, data, size, 0 );
+ }
+
+ void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+ {
+ sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+ sendToAddr_.sin_port = htons( (short)remoteEndpoint.port );
+
+ sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+ }
+
+ void Bind( const IpEndpointName& localEndpoint )
+ {
+ struct sockaddr_in bindSockAddr;
+ SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+ if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+ throw std::runtime_error("unable to bind udp socket\n");
+ }
+
+ isBound_ = true;
+ }
+
+ bool IsBound() const { return isBound_; }
+
+ int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+ {
+ assert( isBound_ );
+
+ struct sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof(fromAddr);
+
+ int result = recvfrom(socket_, data, size, 0,
+ (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+ if( result < 0 )
+ return 0;
+
+ remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+ remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+ return result;
+ }
+
+ SOCKET& Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+ impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+ delete impl_;
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+ return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+ impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, int size )
+{
+ impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+{
+ impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+ impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+ return impl_->IsBound();
+}
+
+int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+{
+ return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+ AttachedTimerListener( int id, int p, TimerListener *tl )
+ : initialDelayMs( id )
+ , periodMs( p )
+ , listener( tl ) {}
+ int initialDelayMs;
+ int periodMs;
+ TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls(
+ const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+ return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+ multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+#ifndef WINCE
+ signal( SIGINT, SIG_DFL );
+#endif
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+ NetworkInitializer networkInitializer_;
+
+ std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+ std::vector< AttachedTimerListener > timerListeners_;
+
+ volatile bool break_;
+ HANDLE breakEvent_;
+
+ double GetCurrentTimeMs() const
+ {
+#ifndef WINCE
+ return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
+#else
+ return 0;
+#endif
+ }
+
+public:
+ Implementation()
+ {
+ breakEvent_ = CreateEvent( NULL, FALSE, FALSE, NULL );
+ }
+
+ ~Implementation()
+ {
+ CloseHandle( breakEvent_ );
+ }
+
+ void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+ // we don't check that the same socket has been added multiple times, even though this is an error
+ socketListeners_.push_back( std::make_pair( listener, socket ) );
+ }
+
+ void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
+ std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+ assert( i != socketListeners_.end() );
+
+ socketListeners_.erase( i );
+ }
+
+ void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void DetachPeriodicTimerListener( TimerListener *listener )
+ {
+ std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ while( i != timerListeners_.end() ){
+ if( i->listener == listener )
+ break;
+ ++i;
+ }
+
+ assert( i != timerListeners_.end() );
+
+ timerListeners_.erase( i );
+ }
+
+ void Run()
+ {
+ break_ = false;
+
+ // prepare the window events which we use to wake up on incoming data
+ // we use this instead of select() primarily to support the AsyncBreak()
+ // mechanism.
+
+ std::vector events( socketListeners_.size() + 1, 0 );
+ int j=0;
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i, ++j ){
+
+ HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
+ WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
+ events[j] = event;
+ }
+
+
+ events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
+
+
+ // configure the timer queue
+ double currentTimeMs = GetCurrentTimeMs();
+
+ // expiry time ms, listener
+ std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+ for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ i != timerListeners_.end(); ++i )
+ timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+ const int MAX_BUFFER_SIZE = 4098;
+ char *data = new char[ MAX_BUFFER_SIZE ];
+ IpEndpointName remoteEndpoint;
+
+ while( !break_ ){
+
+ double currentTimeMs = GetCurrentTimeMs();
+
+ DWORD waitTime = INFINITE;
+ if( !timerQueue_.empty() ){
+
+ waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
+ ? timerQueue_.front().first - currentTimeMs
+ : 0 );
+ }
+
+ DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
+ if( break_ )
+ break;
+
+ if( waitResult != WAIT_TIMEOUT ){
+ for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
+ int size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+ if( size > 0 ){
+ socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint );
+ if( break_ )
+ break;
+ }
+ }
+ }
+
+ // execute any expired timers
+ currentTimeMs = GetCurrentTimeMs();
+ bool resort = false;
+ for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+ i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+ i->second.listener->TimerExpired();
+ if( break_ )
+ break;
+
+ i->first += i->second.periodMs;
+ resort = true;
+ }
+ if( resort )
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+ }
+
+ delete [] data;
+
+ // free events
+ j = 0;
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i, ++j ){
+
+ WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
+ CloseHandle( events[j] );
+ unsigned long enableNonblocking = 0;
+ ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking ); // make the socket blocking again
+ }
+ }
+
+ void Break()
+ {
+ break_ = true;
+ }
+
+ void AsynchronousBreak()
+ {
+ break_ = true;
+ SetEvent( breakEvent_ );
+ }
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+ impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{
+ delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+ impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+ impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+ assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+ multiplexerInstanceToAbortWithSigInt_ = this;
+#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();
+}
+#endif
+
diff --git a/libs/oscpack/include/osc/MessageMappingOscPacketListener.h b/libs/oscpack/src/osc/MessageMappingOscPacketListener.h
similarity index 100%
rename from libs/oscpack/include/osc/MessageMappingOscPacketListener.h
rename to libs/oscpack/src/osc/MessageMappingOscPacketListener.h
diff --git a/libs/oscpack/include/osc/OscException.h b/libs/oscpack/src/osc/OscException.h
similarity index 100%
rename from libs/oscpack/include/osc/OscException.h
rename to libs/oscpack/src/osc/OscException.h
diff --git a/libs/oscpack/include/osc/OscHostEndianness.h b/libs/oscpack/src/osc/OscHostEndianness.h
similarity index 89%
rename from libs/oscpack/include/osc/OscHostEndianness.h
rename to libs/oscpack/src/osc/OscHostEndianness.h
index 9446984..059ad0d 100644
--- a/libs/oscpack/include/osc/OscHostEndianness.h
+++ b/libs/oscpack/src/osc/OscHostEndianness.h
@@ -37,12 +37,14 @@
please let me know! I've tried a few things which don't work.
*/
+#define OSC_HOST_LITTLE_ENDIAN
+
#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)
// you can define one of the above symbols from the command line
// then you don't have to edit this file.
-#elif defined(__WIN32__) || defined(WIN32)
+#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)
// assume that __WIN32__ is only defined on little endian systems
@@ -52,19 +54,22 @@
#elif defined(__APPLE__)
#if defined(__LITTLE_ENDIAN__)
+
#define OSC_HOST_LITTLE_ENDIAN 1
#undef OSC_HOST_BIG_ENDIAN
-#else
+
+#elif defined(__BIG_ENDIAN__)
+
#define OSC_HOST_BIG_ENDIAN 1
#undef OSC_HOST_LITTLE_ENDIAN
+
#endif
-#else
+#endif
-//#error please edit OSCHostEndianness.h to configure endianness
-// assume LITTLE_ENDIAN for everthing else
-#define OSC_HOST_LITTLE_ENDIAN 1
-#undef OSC_HOST_BIG_ENDIAN
+#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)
+
+#error please edit OSCHostEndianness.h to configure endianness
#endif
diff --git a/libs/oscpack/src/osc/OscOutboundPacketStream.cpp b/libs/oscpack/src/osc/OscOutboundPacketStream.cpp
new file mode 100644
index 0000000..fd324a5
--- /dev/null
+++ b/libs/oscpack/src/osc/OscOutboundPacketStream.cpp
@@ -0,0 +1,639 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscOutboundPacketStream.h"
+
+#include
+#include
+#include
+
+#if defined(__WIN32__) || defined(WIN32)
+#include // for alloca
+#endif
+
+#include "OscHostEndianness.h"
+
+
+namespace osc{
+
+static void FromInt32( char *p, int32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::int32 i;
+ char c[4];
+ } u;
+
+ u.i = x;
+
+ p[3] = u.c[0];
+ p[2] = u.c[1];
+ p[1] = u.c[2];
+ p[0] = u.c[3];
+#else
+ *reinterpret_cast(p) = x;
+#endif
+}
+
+
+static void FromUInt32( char *p, uint32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::uint32 i;
+ char c[4];
+ } u;
+
+ u.i = x;
+
+ p[3] = u.c[0];
+ p[2] = u.c[1];
+ p[1] = u.c[2];
+ p[0] = u.c[3];
+#else
+ *reinterpret_cast(p) = x;
+#endif
+}
+
+
+static void FromInt64( char *p, int64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::int64 i;
+ char c[8];
+ } u;
+
+ u.i = x;
+
+ p[7] = u.c[0];
+ p[6] = u.c[1];
+ p[5] = u.c[2];
+ p[4] = u.c[3];
+ p[3] = u.c[4];
+ p[2] = u.c[5];
+ p[1] = u.c[6];
+ p[0] = u.c[7];
+#else
+ *reinterpret_cast(p) = x;
+#endif
+}
+
+
+static void FromUInt64( char *p, uint64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::uint64 i;
+ char c[8];
+ } u;
+
+ u.i = x;
+
+ p[7] = u.c[0];
+ p[6] = u.c[1];
+ p[5] = u.c[2];
+ p[4] = u.c[3];
+ p[3] = u.c[4];
+ p[2] = u.c[5];
+ p[1] = u.c[6];
+ p[0] = u.c[7];
+#else
+ *reinterpret_cast(p) = x;
+#endif
+}
+
+
+static inline long RoundUp4( long x )
+{
+ return ((x-1) & (~0x03L)) + 4;
+}
+
+
+OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity )
+ : data_( buffer )
+ , end_( data_ + capacity )
+ , typeTagsCurrent_( end_ )
+ , messageCursor_( data_ )
+ , argumentCurrent_( data_ )
+ , elementSizePtr_( 0 )
+ , messageIsInProgress_( false )
+{
+
+}
+
+
+OutboundPacketStream::~OutboundPacketStream()
+{
+
+}
+
+
+char *OutboundPacketStream::BeginElement( char *beginPtr )
+{
+ if( elementSizePtr_ == 0 ){
+
+ elementSizePtr_ = reinterpret_cast(data_);
+
+ return beginPtr;
+
+ }else{
+ // store an offset to the old element size ptr in the element size slot
+ // we store an offset rather than the actual pointer to be 64 bit clean.
+ *reinterpret_cast(beginPtr) =
+ (uint32)(reinterpret_cast(elementSizePtr_) - data_);
+
+ elementSizePtr_ = reinterpret_cast(beginPtr);
+
+ return beginPtr + 4;
+ }
+}
+
+
+void OutboundPacketStream::EndElement( char *endPtr )
+{
+ assert( elementSizePtr_ != 0 );
+
+ if( elementSizePtr_ == reinterpret_cast(data_) ){
+
+ elementSizePtr_ = 0;
+
+ }else{
+ // while building an element, an offset to the containing element's
+ // size slot is stored in the elements size slot (or a ptr to data_
+ // if there is no containing element). We retrieve that here
+ uint32 *previousElementSizePtr =
+ (uint32*)(data_ + *reinterpret_cast(elementSizePtr_));
+
+ // then we store the element size in the slot, note that the element
+ // size does not include the size slot, hence the - 4 below.
+ uint32 elementSize =
+ (endPtr - reinterpret_cast(elementSizePtr_)) - 4;
+ FromUInt32( reinterpret_cast(elementSizePtr_), elementSize );
+
+ // finally, we reset the element size ptr to the containing element
+ elementSizePtr_ = previousElementSizePtr;
+ }
+}
+
+
+bool OutboundPacketStream::ElementSizeSlotRequired() const
+{
+ return (elementSizePtr_ != 0);
+}
+
+
+void OutboundPacketStream::CheckForAvailableBundleSpace()
+{
+ unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
+
+ if( required > Capacity() )
+ throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
+{
+ // plus 4 for at least four bytes of type tag
+ unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0)
+ + RoundUp4(strlen(addressPattern) + 1) + 4;
+
+ if( required > Capacity() )
+ throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength )
+{
+ // plus three for extra type tag, comma and null terminator
+ unsigned long required = (argumentCurrent_ - data_) + argumentLength
+ + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
+
+ if( required > Capacity() )
+ throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::Clear()
+{
+ typeTagsCurrent_ = end_;
+ messageCursor_ = data_;
+ argumentCurrent_ = data_;
+ elementSizePtr_ = 0;
+ messageIsInProgress_ = false;
+}
+
+
+unsigned int OutboundPacketStream::Capacity() const
+{
+ return end_ - data_;
+}
+
+
+unsigned int OutboundPacketStream::Size() const
+{
+ unsigned int result = argumentCurrent_ - data_;
+ if( IsMessageInProgress() ){
+ // account for the length of the type tag string. the total type tag
+ // includes an initial comma, plus at least one terminating \0
+ result += RoundUp4( (end_ - typeTagsCurrent_) + 2 );
+ }
+
+ return result;
+}
+
+
+const char *OutboundPacketStream::Data() const
+{
+ return data_;
+}
+
+
+bool OutboundPacketStream::IsReady() const
+{
+ return (!IsMessageInProgress() && !IsBundleInProgress());
+}
+
+
+bool OutboundPacketStream::IsMessageInProgress() const
+{
+ return messageIsInProgress_;
+}
+
+
+bool OutboundPacketStream::IsBundleInProgress() const
+{
+ return (elementSizePtr_ != 0);
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
+{
+ if( IsMessageInProgress() )
+ throw MessageInProgressException();
+
+ CheckForAvailableBundleSpace();
+
+ messageCursor_ = BeginElement( messageCursor_ );
+
+ memcpy( messageCursor_, "#bundle\0", 8 );
+ FromUInt64( messageCursor_ + 8, rhs.timeTag );
+
+ messageCursor_ += 16;
+ argumentCurrent_ = messageCursor_;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
+{
+ (void) rhs;
+
+ if( !IsBundleInProgress() )
+ throw BundleNotInProgressException();
+ if( IsMessageInProgress() )
+ throw MessageInProgressException();
+
+ EndElement( messageCursor_ );
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
+{
+ if( IsMessageInProgress() )
+ throw MessageInProgressException();
+
+ CheckForAvailableMessageSpace( rhs.addressPattern );
+
+ messageCursor_ = BeginElement( messageCursor_ );
+
+ strcpy( messageCursor_, rhs.addressPattern );
+ unsigned long rhsLength = strlen(rhs.addressPattern);
+ messageCursor_ += rhsLength + 1;
+
+ // zero pad to 4-byte boundary
+ unsigned long i = rhsLength + 1;
+ while( i & 0x3 ){
+ *messageCursor_++ = '\0';
+ ++i;
+ }
+
+ argumentCurrent_ = messageCursor_;
+ typeTagsCurrent_ = end_;
+
+ messageIsInProgress_ = true;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )
+{
+ (void) rhs;
+
+ if( !IsMessageInProgress() )
+ throw MessageNotInProgressException();
+
+ int typeTagsCount = end_ - typeTagsCurrent_;
+
+ if( typeTagsCount ){
+
+ char *tempTypeTags = (char*)alloca(typeTagsCount);
+ memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );
+
+ // slot size includes comma and null terminator
+ int typeTagSlotSize = RoundUp4( typeTagsCount + 2 );
+
+ uint32 argumentsSize = argumentCurrent_ - messageCursor_;
+
+ memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );
+
+ messageCursor_[0] = ',';
+ // copy type tags in reverse (really forward) order
+ for( int i=0; i < typeTagsCount; ++i )
+ messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];
+
+ char *p = messageCursor_ + 1 + typeTagsCount;
+ for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )
+ *p++ = '\0';
+
+ typeTagsCurrent_ = end_;
+
+ // advance messageCursor_ for next message
+ messageCursor_ += typeTagSlotSize + argumentsSize;
+
+ }else{
+ // send an empty type tags string
+ memcpy( messageCursor_, ",\0\0\0", 4 );
+
+ // advance messageCursor_ for next message
+ messageCursor_ += 4;
+ }
+
+ argumentCurrent_ = messageCursor_;
+
+ EndElement( messageCursor_ );
+
+ messageIsInProgress_ = false;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
+{
+ CheckForAvailableArgumentSpace(0);
+
+ *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
+{
+ (void) rhs;
+ CheckForAvailableArgumentSpace(0);
+
+ *(--typeTagsCurrent_) = NIL_TYPE_TAG;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
+{
+ (void) rhs;
+ CheckForAvailableArgumentSpace(0);
+
+ *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
+{
+ CheckForAvailableArgumentSpace(4);
+
+ *(--typeTagsCurrent_) = INT32_TYPE_TAG;
+ FromInt32( argumentCurrent_, rhs );
+ argumentCurrent_ += 4;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
+{
+ CheckForAvailableArgumentSpace(4);
+
+ *(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ float f;
+ char c[4];
+ } u;
+
+ u.f = rhs;
+
+ argumentCurrent_[3] = u.c[0];
+ argumentCurrent_[2] = u.c[1];
+ argumentCurrent_[1] = u.c[2];
+ argumentCurrent_[0] = u.c[3];
+#else
+ *reinterpret_cast(argumentCurrent_) = rhs;
+#endif
+
+ argumentCurrent_ += 4;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
+{
+ CheckForAvailableArgumentSpace(4);
+
+ *(--typeTagsCurrent_) = CHAR_TYPE_TAG;
+ FromInt32( argumentCurrent_, rhs );
+ argumentCurrent_ += 4;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
+{
+ CheckForAvailableArgumentSpace(4);
+
+ *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
+ FromUInt32( argumentCurrent_, rhs );
+ argumentCurrent_ += 4;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
+{
+ CheckForAvailableArgumentSpace(4);
+
+ *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
+ FromUInt32( argumentCurrent_, rhs );
+ argumentCurrent_ += 4;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
+{
+ CheckForAvailableArgumentSpace(8);
+
+ *(--typeTagsCurrent_) = INT64_TYPE_TAG;
+ FromInt64( argumentCurrent_, rhs );
+ argumentCurrent_ += 8;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
+{
+ CheckForAvailableArgumentSpace(8);
+
+ *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
+ FromUInt64( argumentCurrent_, rhs );
+ argumentCurrent_ += 8;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
+{
+ CheckForAvailableArgumentSpace(8);
+
+ *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ double f;
+ char c[8];
+ } u;
+
+ u.f = rhs;
+
+ argumentCurrent_[7] = u.c[0];
+ argumentCurrent_[6] = u.c[1];
+ argumentCurrent_[5] = u.c[2];
+ argumentCurrent_[4] = u.c[3];
+ argumentCurrent_[3] = u.c[4];
+ argumentCurrent_[2] = u.c[5];
+ argumentCurrent_[1] = u.c[6];
+ argumentCurrent_[0] = u.c[7];
+#else
+ *reinterpret_cast(argumentCurrent_) = rhs;
+#endif
+
+ argumentCurrent_ += 8;
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
+{
+ CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
+
+ *(--typeTagsCurrent_) = STRING_TYPE_TAG;
+ strcpy( argumentCurrent_, rhs );
+ unsigned long rhsLength = strlen(rhs);
+ argumentCurrent_ += rhsLength + 1;
+
+ // zero pad to 4-byte boundary
+ unsigned long i = rhsLength + 1;
+ while( i & 0x3 ){
+ *argumentCurrent_++ = '\0';
+ ++i;
+ }
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
+{
+ CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) );
+
+ *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;
+ strcpy( argumentCurrent_, rhs );
+ unsigned long rhsLength = strlen(rhs);
+ argumentCurrent_ += rhsLength + 1;
+
+ // zero pad to 4-byte boundary
+ unsigned long i = rhsLength + 1;
+ while( i & 0x3 ){
+ *argumentCurrent_++ = '\0';
+ ++i;
+ }
+
+ return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
+{
+ CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
+
+ *(--typeTagsCurrent_) = BLOB_TYPE_TAG;
+ FromUInt32( argumentCurrent_, rhs.size );
+ argumentCurrent_ += 4;
+
+ memcpy( argumentCurrent_, rhs.data, rhs.size );
+ argumentCurrent_ += rhs.size;
+
+ // zero pad to 4-byte boundary
+ unsigned long i = rhs.size;
+ while( i & 0x3 ){
+ *argumentCurrent_++ = '\0';
+ ++i;
+ }
+
+ return *this;
+}
+
+} // namespace osc
+
+
diff --git a/libs/oscpack/include/osc/OscOutboundPacketStream.h b/libs/oscpack/src/osc/OscOutboundPacketStream.h
similarity index 97%
rename from libs/oscpack/include/osc/OscOutboundPacketStream.h
rename to libs/oscpack/src/osc/OscOutboundPacketStream.h
index 468785a..cae5405 100644
--- a/libs/oscpack/include/osc/OscOutboundPacketStream.h
+++ b/libs/oscpack/src/osc/OscOutboundPacketStream.h
@@ -1,284 +1,142 @@
/*
-
oscpack -- Open Sound Control packet manipulation library
-
http://www.audiomulch.com/~rossb/oscpack
-
-
Copyright (c) 2004-2005 Ross Bencina
-
-
Permission is hereby granted, free of charge, to any person obtaining
-
a copy of this software and associated documentation files
-
(the "Software"), to deal in the Software without restriction,
-
including without limitation the rights to use, copy, modify, merge,
-
publish, distribute, sublicense, and/or sell copies of the Software,
-
and to permit persons to whom the Software is furnished to do so,
-
subject to the following conditions:
-
-
The above copyright notice and this permission notice shall be
-
included in all copies or substantial portions of the Software.
-
-
Any person wishing to distribute modifications to the Software is
-
requested to send the modifications to the original developer so that
-
they can be incorporated into the canonical version.
-
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
-
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
*/
-
#ifndef INCLUDED_OSCOUTBOUNDPACKET_H
-
#define INCLUDED_OSCOUTBOUNDPACKET_H
-
-
#include "OscTypes.h"
-
#include "OscException.h"
-
-
-
namespace osc{
-
-
class OutOfBufferMemoryException : public Exception{
-
public:
-
OutOfBufferMemoryException( const char *w="out of buffer memory" )
-
: Exception( w ) {}
-
};
-
-
class BundleNotInProgressException : public Exception{
-
public:
-
BundleNotInProgressException(
-
const char *w="call to EndBundle when bundle is not in progress" )
-
: Exception( w ) {}
-
};
-
-
class MessageInProgressException : public Exception{
-
public:
-
MessageInProgressException(
-
const char *w="opening or closing bundle or message while message is in progress" )
-
: Exception( w ) {}
-
};
-
-
class MessageNotInProgressException : public Exception{
-
public:
-
MessageNotInProgressException(
-
const char *w="call to EndMessage when message is not in progress" )
-
: Exception( w ) {}
-
};
-
-
-
class OutboundPacketStream{
-
public:
-
OutboundPacketStream( char *buffer, unsigned long capacity );
-
~OutboundPacketStream();
-
-
void Clear();
-
-
unsigned int Capacity() const;
-
-
// invariant: size() is valid even while building a message.
-
unsigned int Size() const;
-
-
const char *Data() const;
-
-
// indicates that all messages have been closed with a matching EndMessage
-
// and all bundles have been closed with a matching EndBundle
-
bool IsReady() const;
-
-
bool IsMessageInProgress() const;
-
bool IsBundleInProgress() const;
-
-
OutboundPacketStream& operator<<( const BundleInitiator& rhs );
-
OutboundPacketStream& operator<<( const BundleTerminator& rhs );
-
-
-
+
OutboundPacketStream& operator<<( const BeginMessage& rhs );
-
OutboundPacketStream& operator<<( const MessageTerminator& rhs );
-
-
OutboundPacketStream& operator<<( bool rhs );
-
OutboundPacketStream& operator<<( const NilType& rhs );
-
OutboundPacketStream& operator<<( const InfinitumType& rhs );
-
OutboundPacketStream& operator<<( int32 rhs );
-
-
#ifndef __x86_64__
-
OutboundPacketStream& operator<<( int rhs )
-
{ *this << (int32)rhs; return *this; }
-
#endif
-
-
OutboundPacketStream& operator<<( float rhs );
-
OutboundPacketStream& operator<<( char rhs );
-
OutboundPacketStream& operator<<( const RgbaColor& rhs );
-
OutboundPacketStream& operator<<( const MidiMessage& rhs );
-
OutboundPacketStream& operator<<( int64 rhs );
-
OutboundPacketStream& operator<<( const TimeTag& rhs );
-
OutboundPacketStream& operator<<( double rhs );
-
OutboundPacketStream& operator<<( const char* rhs );
-
OutboundPacketStream& operator<<( const Symbol& rhs );
-
OutboundPacketStream& operator<<( const Blob& rhs );
-
-
private:
-
-
char *BeginElement( char *beginPtr );
-
void EndElement( char *endPtr );
-
-
bool ElementSizeSlotRequired() const;
-
void CheckForAvailableBundleSpace();
-
void CheckForAvailableMessageSpace( const char *addressPattern );
-
void CheckForAvailableArgumentSpace( long argumentLength );
-
-
char *data_;
-
char *end_;
-
-
char *typeTagsCurrent_; // stored in reverse order
-
char *messageCursor_;
-
char *argumentCurrent_;
-
-
// elementSizePtr_ has two special values: 0 indicates that a bundle
-
// isn't open, and elementSizePtr_==data_ indicates that a bundle is
-
// open but that it doesn't have a size slot (ie the outermost bundle)
-
uint32 *elementSizePtr_;
-
-
bool messageIsInProgress_;
-
};
-
-
} // namespace osc
-
-
#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */
-
diff --git a/libs/oscpack/include/osc/OscPacketListener.h b/libs/oscpack/src/osc/OscPacketListener.h
similarity index 100%
rename from libs/oscpack/include/osc/OscPacketListener.h
rename to libs/oscpack/src/osc/OscPacketListener.h
diff --git a/libs/oscpack/src/osc/OscPrintReceivedElements.cpp b/libs/oscpack/src/osc/OscPrintReceivedElements.cpp
new file mode 100644
index 0000000..bddafd9
--- /dev/null
+++ b/libs/oscpack/src/osc/OscPrintReceivedElements.cpp
@@ -0,0 +1,244 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscPrintReceivedElements.h"
+
+#include
+#include
+#include
+#include
+
+
+namespace osc{
+
+
+std::ostream& operator<<( std::ostream & os,
+ const ReceivedMessageArgument& arg )
+{
+ switch( arg.TypeTag() ){
+ case TRUE_TYPE_TAG:
+ os << "bool:true";
+ break;
+
+ case FALSE_TYPE_TAG:
+ os << "bool:false";
+ break;
+
+ case NIL_TYPE_TAG:
+ os << "(Nil)";
+ break;
+
+ case INFINITUM_TYPE_TAG:
+ os << "(Infinitum)";
+ break;
+
+ case INT32_TYPE_TAG:
+ os << "int32:" << arg.AsInt32Unchecked();
+ break;
+
+ case FLOAT_TYPE_TAG:
+ os << "float32:" << arg.AsFloatUnchecked();
+ break;
+
+ case CHAR_TYPE_TAG:
+ {
+ char s[2] = {0};
+ s[0] = arg.AsCharUnchecked();
+ os << "char:'" << s << "'";
+ }
+ break;
+
+ case RGBA_COLOR_TYPE_TAG:
+ {
+ uint32 color = arg.AsRgbaColorUnchecked();
+
+ os << "RGBA:0x"
+ << std::hex << std::setfill('0')
+ << std::setw(2) << (int)((color>>24) & 0xFF)
+ << std::setw(2) << (int)((color>>16) & 0xFF)
+ << std::setw(2) << (int)((color>>8) & 0xFF)
+ << std::setw(2) << (int)(color & 0xFF)
+ << std::setfill(' ');
+ os.unsetf(std::ios::basefield);
+ }
+ break;
+
+ case MIDI_MESSAGE_TYPE_TAG:
+ {
+ uint32 m = arg.AsMidiMessageUnchecked();
+ os << "midi (port, status, data1, data2):<<"
+ << std::hex << std::setfill('0')
+ << "0x" << std::setw(2) << (int)((m>>24) & 0xFF)
+ << " 0x" << std::setw(2) << (int)((m>>16) & 0xFF)
+ << " 0x" << std::setw(2) << (int)((m>>8) & 0xFF)
+ << " 0x" << std::setw(2) << (int)(m & 0xFF)
+ << std::setfill(' ') << ">>";
+ os.unsetf(std::ios::basefield);
+ }
+ break;
+
+ case INT64_TYPE_TAG:
+ os << "int64:" << arg.AsInt64Unchecked();
+ break;
+
+ case TIME_TAG_TYPE_TAG:
+ {
+ os << "OSC-timetag:" << arg.AsTimeTagUnchecked();
+
+ std::time_t t =
+ (unsigned long)( arg.AsTimeTagUnchecked() >> 32 );
+
+ // strip trailing newline from string returned by ctime
+ const char *timeString = std::ctime( &t );
+ size_t len = strlen( timeString );
+ char *s = new char[ len + 1 ];
+ strcpy( s, timeString );
+ if( len )
+ s[ len - 1 ] = '\0';
+
+ os << " " << s;
+ }
+ break;
+
+ case DOUBLE_TYPE_TAG:
+ os << "double:" << arg.AsDoubleUnchecked();
+ break;
+
+ case STRING_TYPE_TAG:
+ os << "OSC-string:`" << arg.AsStringUnchecked() << "'";
+ break;
+
+ case SYMBOL_TYPE_TAG:
+ os << "OSC-string (symbol):`" << arg.AsSymbolUnchecked() << "'";
+ break;
+
+ case BLOB_TYPE_TAG:
+ {
+ unsigned long size;
+ const void *data;
+ arg.AsBlobUnchecked( data, size );
+ os << "OSC-blob:<<" << std::hex << std::setfill('0');
+ unsigned char *p = (unsigned char*)data;
+ for( unsigned long i = 0; i < size; ++i ){
+ os << "0x" << std::setw(2) << int(p[i]);
+ if( i != size-1 )
+ os << ' ';
+ }
+ os.unsetf(std::ios::basefield);
+ os << ">>" << std::setfill(' ');
+ }
+ break;
+
+ default:
+ os << "unknown";
+ }
+
+ return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )
+{
+ os << "[";
+ if( m.AddressPatternIsUInt32() )
+ os << m.AddressPatternAsUInt32();
+ else
+ os << m.AddressPattern();
+
+ bool first = true;
+ for( ReceivedMessage::const_iterator i = m.ArgumentsBegin();
+ i != m.ArgumentsEnd(); ++i ){
+ if( first ){
+ os << " ";
+ first = false;
+ }else{
+ os << ", ";
+ }
+
+ os << *i;
+ }
+
+ os << "]";
+
+ return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b )
+{
+ static int indent = 0;
+
+ for( int j=0; j < indent; ++j )
+ os << " ";
+ os << "{ ( ";
+ if( b.TimeTag() == 1 )
+ os << "immediate";
+ else
+ os << b.TimeTag();
+ os << " )\n";
+
+ ++indent;
+
+ for( ReceivedBundle::const_iterator i = b.ElementsBegin();
+ i != b.ElementsEnd(); ++i ){
+ if( i->IsBundle() ){
+ ReceivedBundle b(*i);
+ os << b << "\n";
+ }else{
+ ReceivedMessage m(*i);
+ for( int j=0; j < indent; ++j )
+ os << " ";
+ os << m << "\n";
+ }
+ }
+
+ --indent;
+
+ for( int j=0; j < indent; ++j )
+ os << " ";
+ os << "}";
+
+ return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p )
+{
+ if( p.IsBundle() ){
+ ReceivedBundle b(p);
+ os << b << "\n";
+ }else{
+ ReceivedMessage m(p);
+ os << m << "\n";
+ }
+
+ return os;
+}
+
+} // namespace osc
diff --git a/libs/oscpack/include/osc/OscPrintReceivedElements.h b/libs/oscpack/src/osc/OscPrintReceivedElements.h
similarity index 100%
rename from libs/oscpack/include/osc/OscPrintReceivedElements.h
rename to libs/oscpack/src/osc/OscPrintReceivedElements.h
diff --git a/libs/oscpack/src/osc/OscReceivedElements.cpp b/libs/oscpack/src/osc/OscReceivedElements.cpp
new file mode 100644
index 0000000..e1c5de1
--- /dev/null
+++ b/libs/oscpack/src/osc/OscReceivedElements.cpp
@@ -0,0 +1,722 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscReceivedElements.h"
+
+#include
+
+#include "OscHostEndianness.h"
+
+
+namespace osc{
+
+
+// return the first 4 byte boundary after the end of a str4
+// be careful about calling this version if you don't know whether
+// the string is terminated correctly.
+static inline const char* FindStr4End( const char *p )
+{
+ if( p[0] == '\0' ) // special case for SuperCollider integer address pattern
+ return p + 4;
+
+ p += 3;
+
+ while( *p )
+ p += 4;
+
+ return p + 1;
+}
+
+
+// return the first 4 byte boundary after the end of a str4
+// returns 0 if p == end or if the string is unterminated
+static inline const char* FindStr4End( const char *p, const char *end )
+{
+ if( p >= end )
+ return 0;
+
+ if( p[0] == '\0' ) // special case for SuperCollider integer address pattern
+ return p + 4;
+
+ p += 3;
+ end -= 1;
+
+ while( p < end && *p )
+ p += 4;
+
+ if( *p )
+ return 0;
+ else
+ return p + 1;
+}
+
+
+static inline unsigned long RoundUp4( unsigned long x )
+{
+ unsigned long remainder = x & 0x3UL;
+ if( remainder )
+ return x + (4 - remainder);
+ else
+ return x;
+}
+
+
+static inline int32 ToInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::int32 i;
+ char c[4];
+ } u;
+
+ u.c[0] = p[3];
+ u.c[1] = p[2];
+ u.c[2] = p[1];
+ u.c[3] = p[0];
+
+ return u.i;
+#else
+ return *(int32*)p;
+#endif
+}
+
+
+static inline uint32 ToUInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::uint32 i;
+ char c[4];
+ } u;
+
+ u.c[0] = p[3];
+ u.c[1] = p[2];
+ u.c[2] = p[1];
+ u.c[3] = p[0];
+
+ return u.i;
+#else
+ return *(uint32*)p;
+#endif
+}
+
+
+int64 ToInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::int64 i;
+ char c[8];
+ } u;
+
+ u.c[0] = p[7];
+ u.c[1] = p[6];
+ u.c[2] = p[5];
+ u.c[3] = p[4];
+ u.c[4] = p[3];
+ u.c[5] = p[2];
+ u.c[6] = p[1];
+ u.c[7] = p[0];
+
+ return u.i;
+#else
+ return *(int64*)p;
+#endif
+}
+
+
+uint64 ToUInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::uint64 i;
+ char c[8];
+ } u;
+
+ u.c[0] = p[7];
+ u.c[1] = p[6];
+ u.c[2] = p[5];
+ u.c[3] = p[4];
+ u.c[4] = p[3];
+ u.c[5] = p[2];
+ u.c[6] = p[1];
+ u.c[7] = p[0];
+
+ return u.i;
+#else
+ return *(uint64*)p;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedPacket::IsBundle() const
+{
+ return (Size() > 0 && Contents()[0] == '#');
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedBundleElement::IsBundle() const
+{
+ return (Size() > 0 && Contents()[0] == '#');
+}
+
+
+int32 ReceivedBundleElement::Size() const
+{
+ return ToUInt32( size_ );
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedMessageArgument::AsBool() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == TRUE_TYPE_TAG )
+ return true;
+ else if( *typeTag_ == FALSE_TYPE_TAG )
+ return false;
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+bool ReceivedMessageArgument::AsBoolUnchecked() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == TRUE_TYPE_TAG )
+ return true;
+ else
+ return false;
+}
+
+
+int32 ReceivedMessageArgument::AsInt32() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == INT32_TYPE_TAG )
+ return AsInt32Unchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+int32 ReceivedMessageArgument::AsInt32Unchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ osc::int32 i;
+ char c[4];
+ } u;
+
+ u.c[0] = argument_[3];
+ u.c[1] = argument_[2];
+ u.c[2] = argument_[1];
+ u.c[3] = argument_[0];
+
+ return u.i;
+#else
+ return *(int32*)argument_;
+#endif
+}
+
+
+float ReceivedMessageArgument::AsFloat() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == FLOAT_TYPE_TAG )
+ return AsFloatUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+float ReceivedMessageArgument::AsFloatUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ float f;
+ char c[4];
+ } u;
+
+ u.c[0] = argument_[3];
+ u.c[1] = argument_[2];
+ u.c[2] = argument_[1];
+ u.c[3] = argument_[0];
+
+ return u.f;
+#else
+ return *(float*)argument_;
+#endif
+}
+
+
+char ReceivedMessageArgument::AsChar() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == CHAR_TYPE_TAG )
+ return AsCharUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+char ReceivedMessageArgument::AsCharUnchecked() const
+{
+ return (char)ToInt32( argument_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColor() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == RGBA_COLOR_TYPE_TAG )
+ return AsRgbaColorUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
+{
+ return ToUInt32( argument_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessage() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG )
+ return AsMidiMessageUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
+{
+ return ToUInt32( argument_ );
+}
+
+
+int64 ReceivedMessageArgument::AsInt64() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == INT64_TYPE_TAG )
+ return AsInt64Unchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+int64 ReceivedMessageArgument::AsInt64Unchecked() const
+{
+ return ToInt64( argument_ );
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTag() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == TIME_TAG_TYPE_TAG )
+ return AsTimeTagUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
+{
+ return ToUInt64( argument_ );
+}
+
+
+double ReceivedMessageArgument::AsDouble() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == DOUBLE_TYPE_TAG )
+ return AsDoubleUnchecked();
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+double ReceivedMessageArgument::AsDoubleUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+ union{
+ double d;
+ char c[8];
+ } u;
+
+ u.c[0] = argument_[7];
+ u.c[1] = argument_[6];
+ u.c[2] = argument_[5];
+ u.c[3] = argument_[4];
+ u.c[4] = argument_[3];
+ u.c[5] = argument_[2];
+ u.c[6] = argument_[1];
+ u.c[7] = argument_[0];
+
+ return u.d;
+#else
+ return *(double*)argument_;
+#endif
+}
+
+
+const char* ReceivedMessageArgument::AsString() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == STRING_TYPE_TAG )
+ return argument_;
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+const char* ReceivedMessageArgument::AsSymbol() const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == SYMBOL_TYPE_TAG )
+ return argument_;
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlob( const void*& data, unsigned long& size ) const
+{
+ if( !typeTag_ )
+ throw MissingArgumentException();
+ else if( *typeTag_ == BLOB_TYPE_TAG )
+ AsBlobUnchecked( data, size );
+ else
+ throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, unsigned long& size ) const
+{
+ size = ToUInt32( argument_ );
+ data = (void*)(argument_+4);
+}
+
+//------------------------------------------------------------------------------
+
+void ReceivedMessageArgumentIterator::Advance()
+{
+ if( !value_.typeTag_ )
+ return;
+
+ switch( *value_.typeTag_++ ){
+ case '\0':
+ // don't advance past end
+ --value_.typeTag_;
+ break;
+
+ case TRUE_TYPE_TAG:
+ case FALSE_TYPE_TAG:
+ case NIL_TYPE_TAG:
+ case INFINITUM_TYPE_TAG:
+
+ // zero length
+ break;
+
+ case INT32_TYPE_TAG:
+ case FLOAT_TYPE_TAG:
+ case CHAR_TYPE_TAG:
+ case RGBA_COLOR_TYPE_TAG:
+ case MIDI_MESSAGE_TYPE_TAG:
+
+ value_.argument_ += 4;
+ break;
+
+ case INT64_TYPE_TAG:
+ case TIME_TAG_TYPE_TAG:
+ case DOUBLE_TYPE_TAG:
+
+ value_.argument_ += 8;
+ break;
+
+ case STRING_TYPE_TAG:
+ case SYMBOL_TYPE_TAG:
+
+ // we use the unsafe function FindStr4End(char*) here because all of
+ // the arguments have already been validated in
+ // ReceivedMessage::Init() below.
+
+ value_.argument_ = FindStr4End( value_.argument_ );
+ break;
+
+ case BLOB_TYPE_TAG:
+ {
+ uint32 blobSize = ToUInt32( value_.argument_ );
+ value_.argument_ = value_.argument_ + 4 + RoundUp4( (unsigned long)blobSize );
+ }
+ break;
+
+ default: // unknown type tag
+ // don't advance
+ --value_.typeTag_;
+ break;
+
+
+ // not handled:
+ // [ Indicates the beginning of an array. The tags following are for
+ // data in the Array until a close brace tag is reached.
+ // ] Indicates the end of an array.
+ }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
+ : addressPattern_( packet.Contents() )
+{
+ Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
+ : addressPattern_( bundleElement.Contents() )
+{
+ Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+bool ReceivedMessage::AddressPatternIsUInt32() const
+{
+ return (addressPattern_[0] == '\0');
+}
+
+
+uint32 ReceivedMessage::AddressPatternAsUInt32() const
+{
+ return ToUInt32( addressPattern_ );
+}
+
+
+void ReceivedMessage::Init( const char *message, unsigned long size )
+{
+ if( size == 0 )
+ throw MalformedMessageException( "zero length messages not permitted" );
+
+ if( (size & 0x03L) != 0 )
+ throw MalformedMessageException( "message size must be multiple of four" );
+
+ const char *end = message + size;
+
+ typeTagsBegin_ = FindStr4End( addressPattern_, end );
+ if( typeTagsBegin_ == 0 ){
+ // address pattern was not terminated before end
+ throw MalformedMessageException( "unterminated address pattern" );
+ }
+
+ if( typeTagsBegin_ == end ){
+ // message consists of only the address pattern - no arguments or type tags.
+ typeTagsBegin_ = 0;
+ typeTagsEnd_ = 0;
+ arguments_ = 0;
+
+ }else{
+ if( *typeTagsBegin_ != ',' )
+ throw MalformedMessageException( "type tags not present" );
+
+ if( *(typeTagsBegin_ + 1) == '\0' ){
+ // zero length type tags
+ typeTagsBegin_ = 0;
+ typeTagsEnd_ = 0;
+ arguments_ = 0;
+
+ }else{
+ // check that all arguments are present and well formed
+
+ arguments_ = FindStr4End( typeTagsBegin_, end );
+ if( arguments_ == 0 ){
+ throw MalformedMessageException( "type tags were not terminated before end of message" );
+ }
+
+ ++typeTagsBegin_; // advance past initial ','
+
+ const char *typeTag = typeTagsBegin_;
+ const char *argument = arguments_;
+
+ do{
+ switch( *typeTag ){
+ case TRUE_TYPE_TAG:
+ case FALSE_TYPE_TAG:
+ case NIL_TYPE_TAG:
+ case INFINITUM_TYPE_TAG:
+
+ // zero length
+ break;
+
+ case INT32_TYPE_TAG:
+ case FLOAT_TYPE_TAG:
+ case CHAR_TYPE_TAG:
+ case RGBA_COLOR_TYPE_TAG:
+ case MIDI_MESSAGE_TYPE_TAG:
+
+ if( argument == end )
+ throw MalformedMessageException( "arguments exceed message size" );
+ argument += 4;
+ if( argument > end )
+ throw MalformedMessageException( "arguments exceed message size" );
+ break;
+
+ case INT64_TYPE_TAG:
+ case TIME_TAG_TYPE_TAG:
+ case DOUBLE_TYPE_TAG:
+
+ if( argument == end )
+ throw MalformedMessageException( "arguments exceed message size" );
+ argument += 8;
+ if( argument > end )
+ throw MalformedMessageException( "arguments exceed message size" );
+ break;
+
+ case STRING_TYPE_TAG:
+ case SYMBOL_TYPE_TAG:
+
+ if( argument == end )
+ throw MalformedMessageException( "arguments exceed message size" );
+ argument = FindStr4End( argument, end );
+ if( argument == 0 )
+ throw MalformedMessageException( "unterminated string argument" );
+ break;
+
+ case BLOB_TYPE_TAG:
+ {
+ if( argument + 4 > end )
+ MalformedMessageException( "arguments exceed message size" );
+
+ uint32 blobSize = ToUInt32( argument );
+ argument = argument + 4 + RoundUp4( (unsigned long)blobSize );
+ if( argument > end )
+ MalformedMessageException( "arguments exceed message size" );
+ }
+ break;
+
+ default:
+ throw MalformedMessageException( "unknown type tag" );
+
+ // not handled:
+ // [ Indicates the beginning of an array. The tags following are for
+ // data in the Array until a close brace tag is reached.
+ // ] Indicates the end of an array.
+ }
+
+ }while( *++typeTag != '\0' );
+ typeTagsEnd_ = typeTag;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
+ : elementCount_( 0 )
+{
+ Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
+ : elementCount_( 0 )
+{
+ Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+void ReceivedBundle::Init( const char *bundle, unsigned long size )
+{
+ if( size < 16 )
+ throw MalformedBundleException( "packet too short for bundle" );
+
+ if( (size & 0x03L) != 0 )
+ throw MalformedBundleException( "bundle size must be multiple of four" );
+
+ if( bundle[0] != '#'
+ || bundle[1] != 'b'
+ || bundle[2] != 'u'
+ || bundle[3] != 'n'
+ || bundle[4] != 'd'
+ || bundle[5] != 'l'
+ || bundle[6] != 'e'
+ || bundle[7] != '\0' )
+ throw MalformedBundleException( "bad bundle address pattern" );
+
+ end_ = bundle + size;
+
+ timeTag_ = bundle + 8;
+
+ const char *p = timeTag_ + 8;
+
+ while( p < end_ ){
+ if( p + 4 > end_ )
+ throw MalformedBundleException( "packet too short for elementSize" );
+
+ uint32 elementSize = ToUInt32( p );
+ if( (elementSize & 0x03L) != 0 )
+ throw MalformedBundleException( "bundle element size must be multiple of four" );
+
+ p += 4 + elementSize;
+ if( p > end_ )
+ throw MalformedBundleException( "packet too short for bundle element" );
+
+ ++elementCount_;
+ }
+
+ if( p != end_ )
+ throw MalformedBundleException( "bundle contents " );
+}
+
+
+uint64 ReceivedBundle::TimeTag() const
+{
+ return ToUInt64( timeTag_ );
+}
+
+
+} // namespace osc
+
diff --git a/libs/oscpack/include/osc/OscReceivedElements.h b/libs/oscpack/src/osc/OscReceivedElements.h
similarity index 99%
rename from libs/oscpack/include/osc/OscReceivedElements.h
rename to libs/oscpack/src/osc/OscReceivedElements.h
index b1f44c4..4836406 100644
--- a/libs/oscpack/include/osc/OscReceivedElements.h
+++ b/libs/oscpack/src/osc/OscReceivedElements.h
@@ -30,6 +30,8 @@
#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
#define INCLUDED_OSCRECEIVEDELEMENTS_H
+#include
+
#include "OscTypes.h"
#include "OscException.h"
diff --git a/libs/oscpack/src/osc/OscTypes.cpp b/libs/oscpack/src/osc/OscTypes.cpp
new file mode 100644
index 0000000..cf8f698
--- /dev/null
+++ b/libs/oscpack/src/osc/OscTypes.cpp
@@ -0,0 +1,40 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "OscTypes.h"
+
+namespace osc{
+
+BundleInitiator BeginBundleImmediate(1);
+BundleTerminator EndBundle;
+MessageTerminator EndMessage;
+NilType Nil;
+InfinitumType Infinitum;
+
+} // namespace osc
diff --git a/libs/oscpack/include/osc/OscTypes.h b/libs/oscpack/src/osc/OscTypes.h
similarity index 91%
rename from libs/oscpack/include/osc/OscTypes.h
rename to libs/oscpack/src/osc/OscTypes.h
index c61d72f..670a502 100644
--- a/libs/oscpack/include/osc/OscTypes.h
+++ b/libs/oscpack/src/osc/OscTypes.h
@@ -1,361 +1,184 @@
/*
-
oscpack -- Open Sound Control packet manipulation library
-
http://www.audiomulch.com/~rossb/oscpack
-
-
Copyright (c) 2004-2005 Ross Bencina
-
-
Permission is hereby granted, free of charge, to any person obtaining
-
a copy of this software and associated documentation files
-
(the "Software"), to deal in the Software without restriction,
-
including without limitation the rights to use, copy, modify, merge,
-
publish, distribute, sublicense, and/or sell copies of the Software,
-
and to permit persons to whom the Software is furnished to do so,
-
subject to the following conditions:
-
-
The above copyright notice and this permission notice shall be
-
included in all copies or substantial portions of the Software.
-
-
Any person wishing to distribute modifications to the Software is
-
requested to send the modifications to the original developer so that
-
they can be incorporated into the canonical version.
-
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
-
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
*/
-
#ifndef INCLUDED_OSCTYPES_H
-
#define INCLUDED_OSCTYPES_H
-
-
-
namespace osc{
-
-
// basic types
-
-
#if defined(__BORLANDC__) || defined(_MSC_VER)
-
-
typedef __int64 int64;
-
typedef unsigned __int64 uint64;
+#elif defined(__x86_64__) || defined(_M_X64)
+typedef long int64;
+typedef unsigned long uint64;
#else
-
-
typedef long long int64;
-
typedef unsigned long long uint64;
-
-
#endif
-
-
-
-
-#ifdef __x86_64__
-
-
+#if defined(__x86_64__) || defined(_M_X64)
typedef signed int int32;
-
typedef unsigned int uint32;
-
-
#else
-
-
typedef signed long int32;
-
typedef unsigned long uint32;
-
-
#endif
-
-
-
-
enum TypeTagValues {
-
TRUE_TYPE_TAG = 'T',
-
FALSE_TYPE_TAG = 'F',
-
NIL_TYPE_TAG = 'N',
-
INFINITUM_TYPE_TAG = 'I',
-
INT32_TYPE_TAG = 'i',
-
FLOAT_TYPE_TAG = 'f',
-
CHAR_TYPE_TAG = 'c',
-
RGBA_COLOR_TYPE_TAG = 'r',
-
MIDI_MESSAGE_TYPE_TAG = 'm',
-
INT64_TYPE_TAG = 'h',
-
TIME_TAG_TYPE_TAG = 't',
-
DOUBLE_TYPE_TAG = 'd',
-
STRING_TYPE_TAG = 's',
-
SYMBOL_TYPE_TAG = 'S',
-
BLOB_TYPE_TAG = 'b'
-
};
-
-
-
-
// i/o manipulators used for streaming interfaces
-
-
struct BundleInitiator{
-
explicit BundleInitiator( uint64 timeTag_ ) : timeTag( timeTag_ ) {}
-
uint64 timeTag;
-
};
-
-
extern BundleInitiator BeginBundleImmediate;
-
-
inline BundleInitiator BeginBundle( uint64 timeTag=1 )
-
{
-
return BundleInitiator(timeTag);
-
}
-
-
-
struct BundleTerminator{
-
};
-
-
extern BundleTerminator EndBundle;
-
-
struct BeginMessage{
-
explicit BeginMessage( const char *addressPattern_ ) : addressPattern( addressPattern_ ) {}
-
const char *addressPattern;
-
};
-
-
struct MessageTerminator{
-
};
-
-
extern MessageTerminator EndMessage;
-
-
-
// osc specific types. they are defined as structs so they can be used
-
// as separately identifiable types with the streaming operators.
-
-
struct NilType{
-
};
-#if defined( __APPLE_CC__)
- #include
-#endif
-
-#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
- #define IGNORE_NIL_TYPE
-#endif
-
-#ifndef IGNORE_NIL_TYPE
+#ifndef _OBJC_OBJC_H_
extern NilType Nil;
-#endif
-
+#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_, unsigned long size_ )
-
: data( data_ ), size( size_ ) {}
-
const void* data;
-
unsigned long size;
-
};
-
-
} // namespace osc
-
-
-
#endif /* INCLUDED_OSCTYPES_H */
-
diff --git a/src/ofxOscArg.h b/src/ofxOscArg.h
index e89b900..db586c9 100644
--- a/src/ofxOscArg.h
+++ b/src/ofxOscArg.h
@@ -36,6 +36,7 @@ typedef enum _ofxOscArgType
{
OFXOSC_TYPE_NONE,
OFXOSC_TYPE_INT32,
+ OFXOSC_TYPE_INT64,
OFXOSC_TYPE_FLOAT,
OFXOSC_TYPE_STRING,
OFXOSC_TYPE_BLOB,
@@ -71,8 +72,8 @@ subclasses for each possible argument type
*/
#if defined TARGET_WIN32 && defined _MSC_VER
-// required because MSVC isn't ANSI-C compliant
-typedef long int32_t;
+ // required because MSVC isn't ANSI-C compliant
+ typedef long int32_t;
#endif
class ofxOscArgInt32 : public ofxOscArg
@@ -94,6 +95,25 @@ class ofxOscArgInt32 : public ofxOscArg
int32_t value;
};
+class ofxOscArgInt64 : public ofxOscArg
+{
+public:
+ ofxOscArgInt64( uint64_t _value ) { value = _value; }
+ ~ofxOscArgInt64() {};
+
+ /// return the type of this argument
+ ofxOscArgType getType() { return OFXOSC_TYPE_INT64; }
+ string getTypeName() { return "int64"; }
+
+ /// return value
+ uint64_t get() const { return value; }
+ /// set value
+ void set( uint64_t _value ) { value = _value; }
+
+private:
+ uint64_t value;
+};
+
class ofxOscArgFloat : public ofxOscArg
{
public:
diff --git a/src/ofxOscMessage.cpp b/src/ofxOscMessage.cpp
index 585fb4d..ba57452 100644
--- a/src/ofxOscMessage.cpp
+++ b/src/ofxOscMessage.cpp
@@ -27,6 +27,7 @@
*/
#include "ofxOscMessage.h"
+#include "ofLog.h"
#include
#include
@@ -63,7 +64,7 @@ ofxOscArgType ofxOscMessage::getArgType( int index ) const
{
if ( index >= (int)args.size() )
{
- fprintf(stderr,"ofxOscMessage::getArgType: index %d out of bounds\n", index );
+ ofLog(OF_LOG_ERROR,"ofxOscMessage::getArgType: index %d out of bounds", index );
return OFXOSC_TYPE_INDEXOUTOFBOUNDS;
}
else
@@ -74,7 +75,7 @@ string ofxOscMessage::getArgTypeName( int index ) const
{
if ( index >= (int)args.size() )
{
- fprintf(stderr,"ofxOscMessage::getArgTypeName: index %d out of bounds\n", index );
+ ofLog(OF_LOG_ERROR,"ofxOscMessage::getArgTypeName: index %d out of bounds", index );
return "INDEX OUT OF BOUNDS";
}
else
@@ -88,12 +89,12 @@ int32_t ofxOscMessage::getArgAsInt32( int index ) const
{
if ( getArgType( index ) == OFXOSC_TYPE_FLOAT )
{
- fprintf(stderr, "ofxOscMessage:getArgAsInt32: warning: converting int32 to float for argument %i\n", index );
+ ofLog(OF_LOG_WARNING, "ofxOscMessage:getArgAsInt32: converting int32 to float for argument %i", index );
return ((ofxOscArgFloat*)args[index])->get();
}
else
{
- fprintf(stderr, "ofxOscMessage:getArgAsInt32: error: argument %i is not a number\n", index );
+ ofLog(OF_LOG_ERROR, "ofxOscMessage:getArgAsInt32: argument %i is not a number", index );
return 0;
}
}
@@ -101,6 +102,25 @@ int32_t ofxOscMessage::getArgAsInt32( int index ) const
return ((ofxOscArgInt32*)args[index])->get();
}
+uint64_t ofxOscMessage::getArgAsInt64( int index ) const
+{
+ if ( getArgType(index) != OFXOSC_TYPE_INT64 )
+ {
+ if ( getArgType( index ) == OFXOSC_TYPE_FLOAT )
+ {
+ ofLog(OF_LOG_WARNING, "ofxOscMessage:getArgAsInt64: converting int64 to float for argument %i", index );
+ return ((ofxOscArgFloat*)args[index])->get();
+ }
+ else
+ {
+ ofLog(OF_LOG_ERROR, "ofxOscMessage:getArgAsInt64: argument %i is not a number", index );
+ return 0;
+ }
+ }
+ else
+ return ((ofxOscArgInt64*)args[index])->get();
+}
+
float ofxOscMessage::getArgAsFloat( int index ) const
{
@@ -108,12 +128,12 @@ float ofxOscMessage::getArgAsFloat( int index ) const
{
if ( getArgType( index ) == OFXOSC_TYPE_INT32 )
{
- fprintf(stderr, "ofxOscMessage:getArgAsFloat: warning: converting float to int32 for argument %i\n", index );
+ ofLog(OF_LOG_WARNING, "ofxOscMessage:getArgAsFloat: converting float to int32 for argument %i", index );
return ((ofxOscArgInt32*)args[index])->get();
}
else
{
- fprintf(stderr, "ofxOscMessage:getArgAsFloat: error: argument %i is not a number\n", index );
+ ofLog(OF_LOG_ERROR, "ofxOscMessage:getArgAsFloat: argument %i is not a number", index );
return 0;
}
}
@@ -130,19 +150,19 @@ string ofxOscMessage::getArgAsString( int index ) const
{
char buf[1024];
sprintf(buf,"%f",((ofxOscArgFloat*)args[index])->get() );
- fprintf(stderr, "ofxOscMessage:getArgAsString: warning: converting float to string for argument %i\n", index );
+ ofLog(OF_LOG_WARNING, "ofxOscMessage:getArgAsString: converting float to string for argument %i", index );
return buf;
}
else if ( getArgType( index ) == OFXOSC_TYPE_INT32 )
{
char buf[1024];
sprintf(buf,"%i",((ofxOscArgInt32*)args[index])->get() );
- fprintf(stderr, "ofxOscMessage:getArgAsString: warning: converting int32 to string for argument %i\n", index );
+ ofLog(OF_LOG_WARNING, "ofxOscMessage:getArgAsString: converting int32 to string for argument %i", index );
return buf;
}
else
{
- fprintf(stderr, "ofxOscMessage:getArgAsString: error: argument %i is not a string\n", index );
+ ofLog(OF_LOG_ERROR, "ofxOscMessage:getArgAsString: argument %i is not a string", index );
return "";
}
}
@@ -165,6 +185,13 @@ void ofxOscMessage::addIntArg( int32_t argument )
args.push_back( new ofxOscArgInt32( argument ) );
}
+void ofxOscMessage::addInt64Arg( uint64_t argument )
+{
+
+ args.push_back( new ofxOscArgInt64( argument ) );
+}
+
+
void ofxOscMessage::addFloatArg( float argument )
{
args.push_back( new ofxOscArgFloat( argument ) );
@@ -197,6 +224,8 @@ ofxOscMessage& ofxOscMessage::copy( const ofxOscMessage& other )
ofxOscArgType argType = other.getArgType( i );
if ( argType == OFXOSC_TYPE_INT32 )
args.push_back( new ofxOscArgInt32( other.getArgAsInt32( i ) ) );
+ else if ( argType == OFXOSC_TYPE_INT64 )
+ args.push_back( new ofxOscArgInt64( other.getArgAsInt64( i ) ) );
else if ( argType == OFXOSC_TYPE_FLOAT )
args.push_back( new ofxOscArgFloat( other.getArgAsFloat( i ) ) );
else if ( argType == OFXOSC_TYPE_STRING )
diff --git a/src/ofxOscMessage.h b/src/ofxOscMessage.h
index 4781dda..fab5892 100644
--- a/src/ofxOscMessage.h
+++ b/src/ofxOscMessage.h
@@ -70,6 +70,7 @@ class ofxOscMessage
/// (eg for an int argument, getArgType(index)==OF_TYPE_INT32
/// or getArgTypeName(index)=="int32")
int32_t getArgAsInt32( int index ) const;
+ uint64_t getArgAsInt64( int index ) const;
float getArgAsFloat( int index ) const;
string getArgAsString( int index ) const;
@@ -78,6 +79,7 @@ class ofxOscMessage
/// host and port of the remote endpoint
void setRemoteEndpoint( string host, int port ) { remote_host = host; remote_port = port; }
void addIntArg( int32_t argument );
+ void addInt64Arg( uint64_t argument );
void addFloatArg( float argument );
void addStringArg( string argument );
diff --git a/src/ofxOscReceiver.cpp b/src/ofxOscReceiver.cpp
index 840268d..92d275d 100644
--- a/src/ofxOscReceiver.cpp
+++ b/src/ofxOscReceiver.cpp
@@ -70,7 +70,7 @@ void ofxOscReceiver::setup( int listen_port )
pthread_create( &thread, NULL, &ofxOscReceiver::startThread, (void*)this );
#endif
- ofAddListener(ofEvents.update, this, &ofxOscReceiver::update);
+ ofAddListener(ofEvents().update, this, &ofxOscReceiver::update);
}
void ofxOscReceiver::shutdown()
@@ -151,6 +151,8 @@ void ofxOscReceiver::ProcessMessage( const osc::ReceivedMessage &m, const IpEndp
{
if ( arg->IsInt32() )
ofMessage->addIntArg( arg->AsInt32Unchecked() );
+ else if ( arg->IsInt64() )
+ ofMessage->addInt64Arg( arg->AsInt64Unchecked() );
else if ( arg->IsFloat() )
ofMessage->addFloatArg( arg->AsFloatUnchecked() );
else if ( arg->IsString() )
@@ -248,4 +250,4 @@ void ofxOscReceiver::update(ofEventArgs &e)
{
ofNotifyEvent(onMessageReceived, msg, this);
}
-}
+}
\ No newline at end of file
diff --git a/src/ofxOscReceiver.h b/src/ofxOscReceiver.h
index c62fc84..87c0ec5 100644
--- a/src/ofxOscReceiver.h
+++ b/src/ofxOscReceiver.h
@@ -91,7 +91,6 @@ class ofxOscReceiver : public osc::OscPacketListener
void grabMutex();
void releaseMutex();
- ofxOscMessage currentMsg;
void update(ofEventArgs &e);
#ifdef TARGET_WIN32
@@ -107,8 +106,7 @@ class ofxOscReceiver : public osc::OscPacketListener
#endif
// ready to be deleted
bool socketHasShutdown;
-
- void update(ofEventArgs &e);
+
};
#endif
diff --git a/src/ofxOscSender.cpp b/src/ofxOscSender.cpp
index 675d41a..fa4e123 100644
--- a/src/ofxOscSender.cpp
+++ b/src/ofxOscSender.cpp
@@ -28,6 +28,7 @@
#include "ofxOscSender.h"
+#include "ofUtils.h"
#include "UdpSocket.h"
@@ -108,13 +109,16 @@ void ofxOscSender::appendMessage( ofxOscMessage& message, osc::OutboundPacketStr
{
if ( message.getArgType(i) == OFXOSC_TYPE_INT32 )
p << message.getArgAsInt32( i );
+ else if ( message.getArgType(i) == OFXOSC_TYPE_INT64 )
+ p << (osc::int64)message.getArgAsInt64( i );
else if ( message.getArgType( i ) == OFXOSC_TYPE_FLOAT )
p << message.getArgAsFloat( i );
else if ( message.getArgType( i ) == OFXOSC_TYPE_STRING )
p << message.getArgAsString( i ).c_str();
else
{
- assert( false && "bad argument type" );
+ ofLogError() << "bad argument type" + ofToString(message.getArgType( i ));
+ assert( false );
}
}
p << osc::EndMessage;