diff options
| author | mick grierson <mickgrierson@gmail.com> | 2015-06-16 22:11:53 +0200 |
|---|---|---|
| committer | mick grierson <mickgrierson@gmail.com> | 2015-06-16 22:11:53 +0200 |
| commit | 00a6fbc5e2fe555f61a7c799d51658f7f5a08848 (patch) | |
| tree | 7d47110ef8690843f4e91514b17c2fc1019c9ebb /ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc | |
| parent | 55f5cf4a57d526a20cf84a17e0340583eee3e7f2 (diff) | |
Update for Hackathon. Example with Wekinator Integration
Diffstat (limited to 'ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc')
34 files changed, 5907 insertions, 0 deletions
diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/IpEndpointName.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/IpEndpointName.cpp new file mode 100755 index 0000000..65cfcc2 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <cstdio> + +#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, "<any>" ); + }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, "<any>:<any>" ); + }else{ + sprintf( s, "%d.%d.%d.%d:<any>", + (int)((address >> 24) & 0xFF), + (int)((address >> 16) & 0xFF), + (int)((address >> 8) & 0xFF), + (int)(address & 0xFF) ); + } + }else{ + if( address == ANY_ADDRESS ){ + sprintf( s, "<any>:%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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/IpEndpointName.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/IpEndpointName.h new file mode 100755 index 0000000..65bd62b --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/IpEndpointName.h @@ -0,0 +1,76 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_IPENDPOINTNAME_H +#define INCLUDED_IPENDPOINTNAME_H + + +class IpEndpointName{ + static unsigned long GetHostByName( const char *s ); +public: + static const unsigned long ANY_ADDRESS = 0xFFFFFFFF; + static const int ANY_PORT = -1; + + IpEndpointName() + : address( ANY_ADDRESS ), port( ANY_PORT ) {} + IpEndpointName( int port_ ) + : address( ANY_ADDRESS ), port( port_ ) {} + IpEndpointName( unsigned long ipAddress_, int port_ ) + : address( ipAddress_ ), port( port_ ) {} + IpEndpointName( const char *addressName, int port_=ANY_PORT ) + : address( GetHostByName( addressName ) ) + , port( port_ ) {} + IpEndpointName( int addressA, int addressB, int addressC, int addressD, int port_=ANY_PORT ) + : address( ( (addressA << 24) | (addressB << 16) | (addressC << 8) | addressD ) ) + , port( port_ ) {} + + // address and port are maintained in host byte order here + unsigned long address; + int port; + + bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; } + + enum { ADDRESS_STRING_LENGTH=17 }; + void AddressAsString( char *s ) const; + + enum { ADDRESS_AND_PORT_STRING_LENGTH=23}; + void AddressAndPortAsString( char *s ) const; +}; + +inline bool operator==( const IpEndpointName& lhs, const IpEndpointName& rhs ) +{ + return (lhs.address == rhs.address && lhs.port == rhs.port ); +} + +inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs ) +{ + return !(lhs == rhs); +} + +#endif /* INCLUDED_IPENDPOINTNAME_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/NetworkingUtils.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/NetworkingUtils.h new file mode 100755 index 0000000..ff9f4e8 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/NetworkingUtils.h @@ -0,0 +1,49 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_NETWORKINGUTILS_H +#define INCLUDED_NETWORKINGUTILS_H + + +// in general NetworkInitializer is only used internally, but if you're +// application creates multiple sockets from different threads at runtime you +// should instantiate one of these in main just to make sure the networking +// layer is initialized. +class NetworkInitializer{ +public: + NetworkInitializer(); + ~NetworkInitializer(); +}; + + +// return ip address of host name in host byte order +unsigned long GetHostByName( const char *name ); + + +#endif /* INCLUDED_NETWORKINGUTILS_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/PacketListener.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/PacketListener.h new file mode 100755 index 0000000..7d9ee5a --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/PacketListener.h @@ -0,0 +1,43 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_PACKETLISTENER_H +#define INCLUDED_PACKETLISTENER_H + + +class IpEndpointName; + +class PacketListener{ +public: + virtual ~PacketListener() {} + virtual void ProcessPacket( const char *data, int size, + const IpEndpointName& remoteEndpoint ) = 0; +}; + +#endif /* INCLUDED_PACKETLISTENER_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/TimerListener.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/TimerListener.h new file mode 100755 index 0000000..fbee86d --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/TimerListener.h @@ -0,0 +1,40 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_TIMERLISTENER_H +#define INCLUDED_TIMERLISTENER_H + + +class TimerListener{ +public: + virtual ~TimerListener() {} + virtual void TimerExpired() = 0; +}; + +#endif /* INCLUDED_TIMERLISTENER_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/UdpSocket.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/UdpSocket.h new file mode 100755 index 0000000..73383e1 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/UdpSocket.h @@ -0,0 +1,158 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_UDPSOCKET_H +#define INCLUDED_UDPSOCKET_H + +#ifndef INCLUDED_NETWORKINGUTILITIES_H +#include "NetworkingUtils.h" +#endif /* INCLUDED_NETWORKINGUTILITIES_H */ + +#ifndef INCLUDED_IPENDPOINTNAME_H +#include "IpEndpointName.h" +#endif /* INCLUDED_IPENDPOINTNAME_H */ + + +class PacketListener; +class TimerListener; + +class UdpSocket; + +class SocketReceiveMultiplexer{ + class Implementation; + Implementation *impl_; + + friend class UdpSocket; + +public: + SocketReceiveMultiplexer(); + ~SocketReceiveMultiplexer(); + + // only call the attach/detach methods _before_ calling Run + + // only one listener per socket, each socket at most once + void AttachSocketListener( UdpSocket *socket, PacketListener *listener ); + void DetachSocketListener( UdpSocket *socket, PacketListener *listener ); + + void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener ); + void AttachPeriodicTimerListener( + int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener ); + void DetachPeriodicTimerListener( TimerListener *listener ); + + void Run(); // loop and block processing messages indefinitely + void RunUntilSigInt(); + void Break(); // call this from a listener to exit once the listener returns + void AsynchronousBreak(); // call this from another thread or signal handler to exit the Run() state +}; + + +class UdpSocket{ + class Implementation; + Implementation *impl_; + + friend class SocketReceiveMultiplexer::Implementation; + +public: + + // ctor throws std::runtime_error if there's a problem + // initializing the socket. + UdpSocket(); + virtual ~UdpSocket(); + + // the socket is created in an unbound, unconnected state + // such a socket can only be used to send to an arbitrary + // address using SendTo(). To use Send() you need to first + // connect to a remote endpoint using Connect(). To use + // ReceiveFrom you need to first bind to a local endpoint + // using Bind(). + + // retrieve the local endpoint name when sending to 'to' + IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const; + + // Connect to a remote endpoint which is used as the target + // for calls to Send() + void Connect( const IpEndpointName& remoteEndpoint ); + void Send( const char *data, int size ); + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ); + + + // Bind a local endpoint to receive incoming data. Endpoint + // can be 'any' for the system to choose an endpoint + void Bind( const IpEndpointName& localEndpoint ); + bool IsBound() const; + + int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ); +}; + + +// convenience classes for transmitting and receiving +// they just call Connect and/or Bind in the ctor. +// note that you can still use a receive socket +// for transmitting etc + +class UdpTransmitSocket : public UdpSocket{ +public: + UdpTransmitSocket( const IpEndpointName& remoteEndpoint ) + { Connect( remoteEndpoint ); } +}; + + +class UdpReceiveSocket : public UdpSocket{ +public: + UdpReceiveSocket( const IpEndpointName& localEndpoint ) + { Bind( localEndpoint ); } +}; + + +// UdpListeningReceiveSocket provides a simple way to bind one listener +// to a single socket without having to manually set up a SocketReceiveMultiplexer + +class UdpListeningReceiveSocket : public UdpSocket{ + SocketReceiveMultiplexer mux_; + PacketListener *listener_; +public: + UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener ) + : listener_( listener ) + { + Bind( localEndpoint ); + mux_.AttachSocketListener( this, listener_ ); + } + + ~UdpListeningReceiveSocket() + { mux_.DetachSocketListener( this, listener_ ); } + + // see SocketReceiveMultiplexer above for the behaviour of these methods... + void Run() { mux_.Run(); } + void RunUntilSigInt() { mux_.RunUntilSigInt(); } + void Break() { mux_.Break(); } + void AsynchronousBreak() { mux_.AsynchronousBreak(); } +}; + + +#endif /* INCLUDED_UDPSOCKET_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/posix/NetworkingUtils.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/posix/NetworkingUtils.cpp new file mode 100755 index 0000000..52ca45f --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <netdb.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <stdio.h> + + + +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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/posix/UdpSocket.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/posix/UdpSocket.cpp new file mode 100755 index 0000000..62897ea --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/posix/UdpSocket.cpp @@ -0,0 +1,575 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <vector> +#include <algorithm> +#include <stdexcept> +#include <assert.h> +#include <signal.h> +#include <math.h> +#include <errno.h> +#include <string.h> // for memset + +#include <pthread.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> // for sockaddr_in + +#include "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 int MAX_BUFFER_SIZE = 292000; + +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 + + // lets increase the size of the buffer if possible. + int maxBufferSize = 0; + socklen_t optlen = sizeof(maxBufferSize); + int res = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, &maxBufferSize, &optlen); + + if( maxBufferSize < MAX_BUFFER_SIZE ){ + maxBufferSize = MAX_BUFFER_SIZE; + setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, &maxBufferSize, sizeof(maxBufferSize)); + setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, &maxBufferSize, sizeof(maxBufferSize)); + }else{ + //if we are natively supporting a larger buffer size then increase our value; + MAX_BUFFER_SIZE = maxBufferSize; + } + + 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 ); + + 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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/win32/NetworkingUtilsWin.cpp new file mode 100755 index 0000000..7e8572a --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <winsock2.h> // this must come first to prevent errors with MSVC7 +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> + + +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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/win32/UdpSocketWin.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/ip/win32/UdpSocketWin.cpp new file mode 100755 index 0000000..943e9a3 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <winsock2.h> // this must come first to prevent errors with MSVC7 +#include <windows.h> +#include <mmsystem.h> // for timeGetTime() + +#include <vector> +#include <algorithm> +#include <stdexcept> +#include <assert.h> + +#ifndef WINCE +#include <signal.h> +#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<HANDLE> events( socketListeners_.size() + 1, 0 ); + int j=0; + for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); + i != socketListeners_.end(); ++i, ++j ){ + + HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL ); + WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below + events[j] = event; + } + + + events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event + + + // configure the timer queue + double currentTimeMs = GetCurrentTimeMs(); + + // expiry time ms, listener + std::vector< std::pair< double, AttachedTimerListener > > timerQueue_; + for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin(); + i != timerListeners_.end(); ++i ) + timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) ); + std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); + + const int MAX_BUFFER_SIZE = 4098; + char *data = new char[ MAX_BUFFER_SIZE ]; + IpEndpointName remoteEndpoint; + + while( !break_ ){ + + double currentTimeMs = GetCurrentTimeMs(); + + DWORD waitTime = INFINITE; + if( !timerQueue_.empty() ){ + + waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs + ? timerQueue_.front().first - currentTimeMs + : 0 ); + } + + DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime ); + if( break_ ) + break; + + if( waitResult != WAIT_TIMEOUT ){ + for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){ + 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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/MessageMappingOscPacketListener.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/MessageMappingOscPacketListener.h new file mode 100755 index 0000000..ade00e5 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/MessageMappingOscPacketListener.h @@ -0,0 +1,73 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_MESSAGEMAPPINGOSCPACKETLISTENER_H +#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H + +#include <string.h> +#include <map> + +#include "OscPacketListener.h" + + + +namespace osc{ + +template< class T > +class MessageMappingOscPacketListener : public OscPacketListener{ +public: + typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&); + +protected: + void RegisterMessageFunction( const char *addressPattern, function_type f ) + { + functions_.insert( std::make_pair( addressPattern, f ) ); + } + + virtual void ProcessMessage( const osc::ReceivedMessage& m, + const IpEndpointName& remoteEndpoint ) + { + typename function_map_type::iterator i = functions_.find( m.AddressPattern() ); + if( i != functions_.end() ) + (dynamic_cast<T*>(this)->*(i->second))( m, remoteEndpoint ); + } + +private: + struct cstr_compare{ + bool operator()( const char *lhs, const char *rhs ) const + { return strcmp( lhs, rhs ) < 0; } + }; + + typedef std::map<const char*, function_type, cstr_compare> function_map_type; + function_map_type functions_; +}; + +} // namespace osc + +#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */
\ No newline at end of file diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscException.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscException.h new file mode 100755 index 0000000..8a2d35e --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscException.h @@ -0,0 +1,54 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_OSC_EXCEPTION_H +#define INCLUDED_OSC_EXCEPTION_H + +#include <exception> + +namespace osc{ + +class Exception : public std::exception { + const char *what_; + +public: + Exception() throw() {} + Exception( const Exception& src ) throw() + : what_( src.what_ ) {} + Exception( const char *w ) throw() + : what_( w ) {} + Exception& operator=( const Exception& src ) throw() + { what_ = src.what_; return *this; } + virtual ~Exception() throw() {} + virtual const char* what() const throw() { return what_; } +}; + +} // namespace osc + +#endif /* INCLUDED_OSC_EXCEPTION_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscHostEndianness.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscHostEndianness.h new file mode 100755 index 0000000..059ad0d --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscHostEndianness.h @@ -0,0 +1,77 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 OSC_HOSTENDIANNESS_H +#define OSC_HOSTENDIANNESS_H + +/* + Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined + + If you know a way to enhance the detection below for Linux and/or MacOSX + 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) || defined(WINCE) + +// assume that __WIN32__ is only defined on little endian systems + +#define OSC_HOST_LITTLE_ENDIAN 1 +#undef OSC_HOST_BIG_ENDIAN + +#elif defined(__APPLE__) + +#if defined(__LITTLE_ENDIAN__) + +#define OSC_HOST_LITTLE_ENDIAN 1 +#undef OSC_HOST_BIG_ENDIAN + +#elif defined(__BIG_ENDIAN__) + +#define OSC_HOST_BIG_ENDIAN 1 +#undef OSC_HOST_LITTLE_ENDIAN + +#endif + +#endif + +#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN) + +#error please edit OSCHostEndianness.h to configure endianness + +#endif + +#endif /* OSC_HOSTENDIANNESS_H */ + diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.cpp new file mode 100755 index 0000000..fd324a5 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <string.h> +#include <stdlib.h> +#include <assert.h> + +#if defined(__WIN32__) || defined(WIN32) +#include <malloc.h> // 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<int32*>(p) = x; +#endif +} + + +static void FromUInt32( char *p, uint32 x ) +{ +#ifdef OSC_HOST_LITTLE_ENDIAN + union{ + osc::uint32 i; + char c[4]; + } u; + + u.i = x; + + p[3] = u.c[0]; + p[2] = u.c[1]; + p[1] = u.c[2]; + p[0] = u.c[3]; +#else + *reinterpret_cast<uint32*>(p) = x; +#endif +} + + +static void FromInt64( char *p, int64 x ) +{ +#ifdef OSC_HOST_LITTLE_ENDIAN + union{ + osc::int64 i; + char c[8]; + } u; + + u.i = x; + + p[7] = u.c[0]; + p[6] = u.c[1]; + p[5] = u.c[2]; + p[4] = u.c[3]; + p[3] = u.c[4]; + p[2] = u.c[5]; + p[1] = u.c[6]; + p[0] = u.c[7]; +#else + *reinterpret_cast<int64*>(p) = x; +#endif +} + + +static void FromUInt64( char *p, uint64 x ) +{ +#ifdef OSC_HOST_LITTLE_ENDIAN + union{ + osc::uint64 i; + char c[8]; + } u; + + u.i = x; + + p[7] = u.c[0]; + p[6] = u.c[1]; + p[5] = u.c[2]; + p[4] = u.c[3]; + p[3] = u.c[4]; + p[2] = u.c[5]; + p[1] = u.c[6]; + p[0] = u.c[7]; +#else + *reinterpret_cast<uint64*>(p) = x; +#endif +} + + +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<uint32*>(data_); + + return beginPtr; + + }else{ + // store an offset to the old element size ptr in the element size slot + // we store an offset rather than the actual pointer to be 64 bit clean. + *reinterpret_cast<uint32*>(beginPtr) = + (uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_); + + elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr); + + return beginPtr + 4; + } +} + + +void OutboundPacketStream::EndElement( char *endPtr ) +{ + assert( elementSizePtr_ != 0 ); + + if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){ + + elementSizePtr_ = 0; + + }else{ + // while building an element, an offset to the containing element's + // size slot is stored in the elements size slot (or a ptr to data_ + // if there is no containing element). We retrieve that here + uint32 *previousElementSizePtr = + (uint32*)(data_ + *reinterpret_cast<uint32*>(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<char*>(elementSizePtr_)) - 4; + FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize ); + + // finally, we reset the element size ptr to the containing element + elementSizePtr_ = previousElementSizePtr; + } +} + + +bool OutboundPacketStream::ElementSizeSlotRequired() const +{ + return (elementSizePtr_ != 0); +} + + +void OutboundPacketStream::CheckForAvailableBundleSpace() +{ + 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<float*>(argumentCurrent_) = rhs; +#endif + + argumentCurrent_ += 4; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( char rhs ) +{ + CheckForAvailableArgumentSpace(4); + + *(--typeTagsCurrent_) = CHAR_TYPE_TAG; + FromInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs ) +{ + CheckForAvailableArgumentSpace(4); + + *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG; + FromUInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs ) +{ + CheckForAvailableArgumentSpace(4); + + *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG; + FromUInt32( argumentCurrent_, rhs ); + argumentCurrent_ += 4; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs ) +{ + CheckForAvailableArgumentSpace(8); + + *(--typeTagsCurrent_) = INT64_TYPE_TAG; + FromInt64( argumentCurrent_, rhs ); + argumentCurrent_ += 8; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs ) +{ + CheckForAvailableArgumentSpace(8); + + *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG; + FromUInt64( argumentCurrent_, rhs ); + argumentCurrent_ += 8; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( double rhs ) +{ + CheckForAvailableArgumentSpace(8); + + *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG; + +#ifdef OSC_HOST_LITTLE_ENDIAN + union{ + double f; + char c[8]; + } u; + + u.f = rhs; + + argumentCurrent_[7] = u.c[0]; + argumentCurrent_[6] = u.c[1]; + argumentCurrent_[5] = u.c[2]; + argumentCurrent_[4] = u.c[3]; + argumentCurrent_[3] = u.c[4]; + argumentCurrent_[2] = u.c[5]; + argumentCurrent_[1] = u.c[6]; + argumentCurrent_[0] = u.c[7]; +#else + *reinterpret_cast<double*>(argumentCurrent_) = rhs; +#endif + + argumentCurrent_ += 8; + + return *this; +} + + +OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) +{ + CheckForAvailableArgumentSpace( RoundUp4(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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.h new file mode 100755 index 0000000..cae5405 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscOutboundPacketStream.h @@ -0,0 +1,142 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPacketListener.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPacketListener.h new file mode 100755 index 0000000..b2d1981 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPacketListener.h @@ -0,0 +1,72 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_OSCPACKETLISTENER_H +#define INCLUDED_OSCPACKETLISTENER_H + +#include "OscReceivedElements.h" +#include "../ip/PacketListener.h" + + +namespace osc{ + +class OscPacketListener : public PacketListener{ +protected: + virtual void ProcessBundle( const osc::ReceivedBundle& b, + const IpEndpointName& remoteEndpoint ) + { + // ignore bundle time tag for now + + for( ReceivedBundle::const_iterator i = b.ElementsBegin(); + i != b.ElementsEnd(); ++i ){ + if( i->IsBundle() ) + ProcessBundle( ReceivedBundle(*i), remoteEndpoint ); + else + ProcessMessage( ReceivedMessage(*i), remoteEndpoint ); + } + } + + virtual void ProcessMessage( const osc::ReceivedMessage& m, + const IpEndpointName& remoteEndpoint ) = 0; + +public: + virtual void ProcessPacket( const char *data, int size, + const IpEndpointName& remoteEndpoint ) + { + osc::ReceivedPacket p( data, size ); + if( p.IsBundle() ) + ProcessBundle( ReceivedBundle(p), remoteEndpoint ); + else + ProcessMessage( ReceivedMessage(p), remoteEndpoint ); + } +}; + +} // namespace osc + +#endif /* INCLUDED_OSCPACKETLISTENER_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.cpp new file mode 100755 index 0000000..bddafd9 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <iostream> +#include <iomanip> +#include <ctime> +#include <cstring> + + +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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.h new file mode 100755 index 0000000..7ec747c --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscPrintReceivedElements.h @@ -0,0 +1,49 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_OSCPRINTRECEIVEDELEMENTS_H +#define INCLUDED_OSCPRINTRECEIVEDELEMENTS_H + +#include <iosfwd> + +#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H +#include "OscReceivedElements.h" +#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ + + +namespace osc{ + +std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p ); +std::ostream& operator<<( std::ostream & os, const ReceivedMessageArgument& arg ); +std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m ); +std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b ); + +} // namespace osc + +#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.cpp new file mode 100755 index 0000000..e1c5de1 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 <cassert> + +#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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.h new file mode 100755 index 0000000..4836406 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscReceivedElements.h @@ -0,0 +1,488 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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_OSCRECEIVEDELEMENTS_H +#define INCLUDED_OSCRECEIVEDELEMENTS_H + +#include <cstddef> + +#include "OscTypes.h" +#include "OscException.h" + + +namespace osc{ + + +class MalformedMessageException : public Exception{ +public: + MalformedMessageException( const char *w="malformed message" ) + : Exception( w ) {} +}; + +class MalformedBundleException : public Exception{ +public: + MalformedBundleException( const char *w="malformed bundle" ) + : Exception( w ) {} +}; + +class WrongArgumentTypeException : public Exception{ +public: + WrongArgumentTypeException( const char *w="wrong argument type" ) + : Exception( w ) {} +}; + +class MissingArgumentException : public Exception{ +public: + MissingArgumentException( const char *w="missing argument" ) + : Exception( w ) {} +}; + +class ExcessArgumentException : public Exception{ +public: + ExcessArgumentException( const char *w="too many arguments" ) + : Exception( w ) {} +}; + + +class ReceivedPacket{ +public: + ReceivedPacket( const char *contents, int32 size ) + : contents_( contents ) + , size_( size ) {} + + bool IsMessage() const { return !IsBundle(); } + bool IsBundle() const; + + int32 Size() const { return size_; } + const char *Contents() const { return contents_; } + +private: + const char *contents_; + int32 size_; +}; + + +class ReceivedBundleElement{ +public: + ReceivedBundleElement( const char *size ) + : size_( size ) {} + + friend class ReceivedBundleElementIterator; + + bool IsMessage() const { return !IsBundle(); } + bool IsBundle() const; + + int32 Size() const; + const char *Contents() const { return size_ + 4; } + +private: + const char *size_; +}; + + +class ReceivedBundleElementIterator{ +public: + ReceivedBundleElementIterator( const char *sizePtr ) + : value_( sizePtr ) {} + + ReceivedBundleElementIterator operator++() + { + Advance(); + return *this; + } + + ReceivedBundleElementIterator operator++(int) + { + ReceivedBundleElementIterator old( *this ); + Advance(); + return old; + } + + const ReceivedBundleElement& operator*() const { return value_; } + + const ReceivedBundleElement* operator->() const { return &value_; } + + friend bool operator==(const ReceivedBundleElementIterator& lhs, + const ReceivedBundleElementIterator& rhs ); + +private: + ReceivedBundleElement value_; + + void Advance() { value_.size_ = value_.Contents() + value_.Size(); } + + bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const + { + return value_.size_ == rhs.value_.size_; + } +}; + +inline bool operator==(const ReceivedBundleElementIterator& lhs, + const ReceivedBundleElementIterator& rhs ) +{ + return lhs.IsEqualTo( rhs ); +} + +inline bool operator!=(const ReceivedBundleElementIterator& lhs, + const ReceivedBundleElementIterator& rhs ) +{ + return !( lhs == rhs ); +} + + +class ReceivedMessageArgument{ +public: + ReceivedMessageArgument( const char *typeTag, const char *argument ) + : typeTag_( typeTag ) + , argument_( argument ) {} + + friend class ReceivedMessageArgumentIterator; + + const char TypeTag() const { return *typeTag_; } + + // the unchecked methods below don't check whether the argument actually + // is of the specified type. they should only be used if you've already + // checked the type tag or the associated IsType() method. + + bool IsBool() const + { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; } + bool AsBool() const; + bool AsBoolUnchecked() const; + + bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; } + bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; } + + bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; } + int32 AsInt32() const; + int32 AsInt32Unchecked() const; + + bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; } + float AsFloat() const; + float AsFloatUnchecked() const; + + bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; } + char AsChar() const; + char AsCharUnchecked() const; + + bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; } + uint32 AsRgbaColor() const; + uint32 AsRgbaColorUnchecked() const; + + bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; } + uint32 AsMidiMessage() const; + uint32 AsMidiMessageUnchecked() const; + + bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; } + int64 AsInt64() const; + int64 AsInt64Unchecked() const; + + bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; } + uint64 AsTimeTag() const; + uint64 AsTimeTagUnchecked() const; + + bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; } + double AsDouble() const; + double AsDoubleUnchecked() const; + + bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; } + const char* AsString() const; + const char* AsStringUnchecked() const { return argument_; } + + bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; } + const char* AsSymbol() const; + const char* AsSymbolUnchecked() const { return argument_; } + + bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; } + void AsBlob( const void*& data, unsigned long& size ) const; + void AsBlobUnchecked( const void*& data, unsigned long& size ) const; + +private: + const char *typeTag_; + const char *argument_; +}; + + +class ReceivedMessageArgumentIterator{ +public: + ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments ) + : value_( typeTags, arguments ) {} + + ReceivedMessageArgumentIterator operator++() + { + Advance(); + return *this; + } + + ReceivedMessageArgumentIterator operator++(int) + { + ReceivedMessageArgumentIterator old( *this ); + Advance(); + return old; + } + + const ReceivedMessageArgument& operator*() const { return value_; } + + const ReceivedMessageArgument* operator->() const { return &value_; } + + friend bool operator==(const ReceivedMessageArgumentIterator& lhs, + const ReceivedMessageArgumentIterator& rhs ); + +private: + ReceivedMessageArgument value_; + + void Advance(); + + bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const + { + return value_.typeTag_ == rhs.value_.typeTag_; + } +}; + +inline bool operator==(const ReceivedMessageArgumentIterator& lhs, + const ReceivedMessageArgumentIterator& rhs ) +{ + return lhs.IsEqualTo( rhs ); +} + +inline bool operator!=(const ReceivedMessageArgumentIterator& lhs, + const ReceivedMessageArgumentIterator& rhs ) +{ + return !( lhs == rhs ); +} + + +class ReceivedMessageArgumentStream{ + friend class ReceivedMessage; + ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin, + const ReceivedMessageArgumentIterator& end ) + : p_( begin ) + , end_( end ) {} + + ReceivedMessageArgumentIterator p_, end_; + +public: + + // end of stream + bool Eos() const { return p_ == end_; } + + ReceivedMessageArgumentStream& operator>>( bool& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsBool(); + return *this; + } + + // not sure if it would be useful to stream Nil and Infinitum + // for now it's not possible + + ReceivedMessageArgumentStream& operator>>( int32& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsInt32(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( float& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsFloat(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( char& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsChar(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs.value = (*p_++).AsRgbaColor(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs.value = (*p_++).AsMidiMessage(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( int64& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsInt64(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( TimeTag& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs.value = (*p_++).AsTimeTag(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( double& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsDouble(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( Blob& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + (*p_++).AsBlob( rhs.data, rhs.size ); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( const char*& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs = (*p_++).AsString(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( Symbol& rhs ) + { + if( Eos() ) + throw MissingArgumentException(); + + rhs.value = (*p_++).AsSymbol(); + return *this; + } + + ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs ) + { + if( !Eos() ) + throw ExcessArgumentException(); + + return *this; + } +}; + + +class ReceivedMessage{ + void Init( const char *bundle, unsigned long size ); +public: + explicit ReceivedMessage( const ReceivedPacket& packet ); + explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); + + const char *AddressPattern() const { return addressPattern_; } + + // Support for non-standad SuperCollider integer address patterns: + bool AddressPatternIsUInt32() const; + uint32 AddressPatternAsUInt32() const; + + unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); } + + const char *TypeTags() const { return typeTagsBegin_; } + + + typedef ReceivedMessageArgumentIterator const_iterator; + + ReceivedMessageArgumentIterator ArgumentsBegin() const + { + return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ ); + } + + ReceivedMessageArgumentIterator ArgumentsEnd() const + { + return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 ); + } + + ReceivedMessageArgumentStream ArgumentStream() const + { + return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() ); + } + +private: + const char *addressPattern_; + const char *typeTagsBegin_; + const char *typeTagsEnd_; + const char *arguments_; +}; + + +class ReceivedBundle{ + void Init( const char *message, unsigned long size ); +public: + explicit ReceivedBundle( const ReceivedPacket& packet ); + explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); + + uint64 TimeTag() const; + + unsigned long ElementCount() const { return elementCount_; } + + typedef ReceivedBundleElementIterator const_iterator; + + ReceivedBundleElementIterator ElementsBegin() const + { + return ReceivedBundleElementIterator( timeTag_ + 8 ); + } + + ReceivedBundleElementIterator ElementsEnd() const + { + return ReceivedBundleElementIterator( end_ ); + } + +private: + const char *timeTag_; + const char *end_; + unsigned long elementCount_; +}; + + +} // namespace osc + + +#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscTypes.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscTypes.cpp new file mode 100755 index 0000000..cf8f698 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/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 <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscTypes.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscTypes.h new file mode 100755 index 0000000..670a502 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/libs/oscpack/src/osc/OscTypes.h @@ -0,0 +1,184 @@ +/* + oscpack -- Open Sound Control packet manipulation library + http://www.audiomulch.com/~rossb/oscpack + + Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 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 + + + +#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{ +}; + +#ifndef _OBJC_OBJC_H_ + extern NilType Nil; +#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/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOsc.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOsc.h new file mode 100755 index 0000000..1e65237 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOsc.h @@ -0,0 +1,34 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "ofxOscArg.h" +#include "ofxOscMessage.h" +#include "ofxOscSender.h" +#include "ofxOscReceiver.h" diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscArg.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscArg.h new file mode 100755 index 0000000..0e16fbe --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscArg.h @@ -0,0 +1,168 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <string> +#include "ofMain.h" + +typedef enum _ofxOscArgType +{ + OFXOSC_TYPE_NONE, + OFXOSC_TYPE_INT32, + OFXOSC_TYPE_INT64, + OFXOSC_TYPE_FLOAT, + OFXOSC_TYPE_STRING, + OFXOSC_TYPE_BLOB, + OFXOSC_TYPE_BUNDLE, + OFXOSC_TYPE_INDEXOUTOFBOUNDS +} ofxOscArgType; + +/* + +ofxOscArg + +base class for arguments + +*/ + +class ofxOscArg +{ +public: + ofxOscArg() {}; + virtual ~ofxOscArg() {}; + + virtual ofxOscArgType getType() { return OFXOSC_TYPE_NONE; } + virtual string getTypeName() { return "none"; } + +private: +}; + + +/* + +subclasses for each possible argument type + +*/ + +class ofxOscArgInt32 : public ofxOscArg +{ +public: + ofxOscArgInt32( int32_t _value ) { value = _value; } + ~ofxOscArgInt32() {}; + + /// return the type of this argument + ofxOscArgType getType() { return OFXOSC_TYPE_INT32; } + string getTypeName() { return "int32"; } + + /// return value + int32_t get() const { return value; } + /// set value + void set( int32_t _value ) { value = _value; } + +private: + 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: + ofxOscArgFloat( float _value ) { value = _value; } + ~ofxOscArgFloat() {}; + + /// return the type of this argument + ofxOscArgType getType() { return OFXOSC_TYPE_FLOAT; } + string getTypeName() { return "float"; } + + /// return value + float get() const { return value; } + /// set value + void set( float _value ) { value = _value; } + +private: + float value; +}; + +class ofxOscArgString : public ofxOscArg +{ +public: + ofxOscArgString( string _value ) { value = _value; } + ~ofxOscArgString() {}; + + /// return the type of this argument + ofxOscArgType getType() { return OFXOSC_TYPE_STRING; } + string getTypeName() { return "string"; } + + /// return value + string get() const { return value; } + /// set value + void set( const char* _value ) { value = _value; } + +private: + std::string value; +}; + +class ofxOscArgBlob : public ofxOscArg +{ +public: + ofxOscArgBlob( ofBuffer _value ){ + value = _value; + } + ~ofxOscArgBlob(){}; + + /// return the type of this argument + ofxOscArgType getType() { return OFXOSC_TYPE_BLOB; } + string getTypeName() { return "blob"; } + + /// return value + ofBuffer get() const { return value; } + /// set value + void set( const char * _value, unsigned int length ) { value.set(_value, length); } + +private: + ofBuffer value; +}; diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.cpp new file mode 100755 index 0000000..3bb19c2 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.cpp @@ -0,0 +1,64 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ofxOscBundle.h" + + +ofxOscBundle::ofxOscBundle() +{ +} + +ofxOscBundle::~ofxOscBundle() +{ +} + +ofxOscBundle& ofxOscBundle::copy( const ofxOscBundle& other ) +{ + for ( int i=0; i<(int)other.bundles.size(); i++ ) + { + bundles.push_back( other.bundles[i] ); + } + for ( int i=0; i<(int)other.messages.size(); i++ ) + { + messages.push_back( other.messages[i] ); + } + return *this; +} + + + +void ofxOscBundle::addBundle( const ofxOscBundle& bundle ) +{ + bundles.push_back( bundle ); +} + +void ofxOscBundle::addMessage( const ofxOscMessage& message ) +{ + messages.push_back( message ); +} + diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.h new file mode 100755 index 0000000..a7c9640 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscBundle.h @@ -0,0 +1,62 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <vector> +#include "ofxOscMessage.h" + +class ofxOscBundle +{ +public: + ofxOscBundle(); + ~ofxOscBundle(); + ofxOscBundle( const ofxOscBundle& other ) { copy ( other ); } + ofxOscBundle& operator= ( const ofxOscBundle& other ) { return copy( other ); } + /// for operator= and copy constructor + ofxOscBundle& copy( const ofxOscBundle& other ); + + /// erase contents + void clear() { messages.clear(); bundles.clear(); } + + /// add bundle elements + void addBundle( const ofxOscBundle& element ); + void addMessage( const ofxOscMessage& message ); + + /// get bundle elements + int getBundleCount() const { return bundles.size(); } + int getMessageCount() const { return messages.size(); } + /// return the bundle or message at the given index + ofxOscBundle& getBundleAt( int i ) { return bundles[i]; } + ofxOscMessage& getMessageAt( int i ) { return messages[i]; } + +private: + + std::vector< ofxOscMessage > messages; + std::vector< ofxOscBundle > bundles; +}; diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.cpp new file mode 100755 index 0000000..46f8d99 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.cpp @@ -0,0 +1,257 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ofxOscMessage.h" +#include "ofLog.h" +#include <iostream> +#include <assert.h> + +ofxOscMessage::ofxOscMessage() + +{ +} + +ofxOscMessage::~ofxOscMessage() +{ + clear(); +} + +void ofxOscMessage::clear() +{ + for ( unsigned int i=0; i<args.size(); ++i ) + delete args[i]; + args.clear(); + address = ""; +} + +/* + +get methods + +*/ + +int ofxOscMessage::getNumArgs() const +{ + return (int)args.size(); +} + +ofxOscArgType ofxOscMessage::getArgType( int index ) const +{ + if ( index >= (int)args.size() ) + { + ofLogError("ofxOscMessage") << "getArgType(): index " << index << " out of bounds"; + return OFXOSC_TYPE_INDEXOUTOFBOUNDS; + } + else + return args[index]->getType(); +} + +string ofxOscMessage::getArgTypeName( int index ) const +{ + if ( index >= (int)args.size() ) + { + ofLogError("ofxOscMessage") << "getArgTypeName(): index " << index << " out of bounds"; + return "INDEX OUT OF BOUNDS"; + } + else + return args[index]->getTypeName(); +} + + +int32_t ofxOscMessage::getArgAsInt32( int index ) const +{ + if ( getArgType(index) != OFXOSC_TYPE_INT32 ) + { + if ( getArgType( index ) == OFXOSC_TYPE_FLOAT ) + { + ofLogWarning("ofxOscMessage") << "getArgAsInt32(): converting int32 to float for argument " << index; + return ((ofxOscArgFloat*)args[index])->get(); + } + else + { + ofLogError("ofxOscMessage") << "getArgAsInt32(): argument " << index << " is not a number"; + return 0; + } + } + else + return ((ofxOscArgInt32*)args[index])->get(); +} + +uint64_t ofxOscMessage::getArgAsInt64( int index ) const +{ + if ( getArgType(index) != OFXOSC_TYPE_INT64 ) + { + if ( getArgType( index ) == OFXOSC_TYPE_FLOAT ) + { + ofLogWarning("ofxOscMessage") << "getArgAsInt64(): converting int64 to float for argument " << index; + return ((ofxOscArgFloat*)args[index])->get(); + } + else + { + ofLogError("ofxOscMessage") << "getArgAsInt64(): argument " << index << " is not a number"; + return 0; + } + } + else + return ((ofxOscArgInt64*)args[index])->get(); +} + + +float ofxOscMessage::getArgAsFloat( int index ) const +{ + if ( getArgType(index) != OFXOSC_TYPE_FLOAT ) + { + if ( getArgType( index ) == OFXOSC_TYPE_INT32 ) + { + ofLogWarning("ofxOscMessage") << "getArgAsFloat(): converting float to int32 for argument " << index; + return ((ofxOscArgInt32*)args[index])->get(); + } + else + { + ofLogError("ofxOscMessage") << "getArgAsFloat(): argument " << index << " is not a number"; + return 0; + } + } + else + return ((ofxOscArgFloat*)args[index])->get(); +} + + +string ofxOscMessage::getArgAsString( int index ) const +{ + if ( getArgType(index) != OFXOSC_TYPE_STRING ) + { + if ( getArgType( index ) == OFXOSC_TYPE_FLOAT ) + { + char buf[1024]; + sprintf(buf,"%f",((ofxOscArgFloat*)args[index])->get() ); + ofLogWarning("ofxOscMessage") << "getArgAsString(): converting float to string for argument " << index; + return buf; + } + else if ( getArgType( index ) == OFXOSC_TYPE_INT32 ) + { + char buf[1024]; + sprintf(buf,"%i",((ofxOscArgInt32*)args[index])->get() ); + ofLogWarning("ofxOscMessage") << "getArgAsString(): converting int32 to string for argument " << index; + return buf; + } + else + { + ofLogError("ofxOscMessage") << "getArgAsString(): argument " << index << " is not a string"; + return ""; + } + } + else + return ((ofxOscArgString*)args[index])->get(); +} + +ofBuffer ofxOscMessage::getArgAsBlob( int index ) const +{ + if ( getArgType(index) != OFXOSC_TYPE_BLOB ) + { + ofLogError("ofxOscMessage") << "getArgAsBlob(): argument " << index << " is not a blob"; + return ofBuffer(); + } + else + return ((ofxOscArgBlob*)args[index])->get(); +} + + + +/* + +set methods + +*/ + + +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 ) ); +} + +void ofxOscMessage::addStringArg( string argument ) +{ + args.push_back( new ofxOscArgString( argument ) ); +} + +void ofxOscMessage::addBlobArg( ofBuffer argument ) +{ + args.push_back( new ofxOscArgBlob( argument ) ); +} + +/* + + housekeeping + + */ + +ofxOscMessage& ofxOscMessage::copy( const ofxOscMessage& other ) +{ + clear(); + // copy address + address = other.address; + + remote_host = other.remote_host; + remote_port = other.remote_port; + + // copy arguments + for ( int i=0; i<(int)other.args.size(); ++i ) + { + 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 ) + args.push_back( new ofxOscArgString( other.getArgAsString( i ) ) ); + else if ( argType == OFXOSC_TYPE_BLOB ) + args.push_back( new ofxOscArgBlob( other.getArgAsBlob( i ) ) ); + else + { + assert( false && "bad argument type" ); + } + } + + return *this; +} diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.h new file mode 100755 index 0000000..ea45f24 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscMessage.h @@ -0,0 +1,95 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "ofxOscArg.h" +#include <vector> +#include <string> + +using namespace std; + +class ofxOscMessage +{ +public: + ofxOscMessage(); + ~ofxOscMessage(); + ofxOscMessage( const ofxOscMessage& other ){ copy ( other ); } + ofxOscMessage& operator= ( const ofxOscMessage& other ) { return copy( other ); } + /// for operator= and copy constructor + ofxOscMessage& copy( const ofxOscMessage& other ); + + /// clear this message, erase all contents + void clear(); + + /// return the address + string getAddress() const { return address; } + + /// return the remote ip + string getRemoteIp() const { return remote_host; } + /// return the remote port + int getRemotePort() const { return remote_port; } + + /// return number of argumentsļ + int getNumArgs() const; + /// return argument type code for argument # index + ofxOscArgType getArgType( int index ) const; + /// return argument type name as string + /// - either "int", "float", or "string" + string getArgTypeName( int index ) const; + + /// get the argument with the given index as an int, float, or string + /// ensure that the type matches what you're requesting + /// (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; + ofBuffer getArgAsBlob( int index ) const; + + /// message construction + void setAddress( string _address ) { address = _address; }; + /// 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 ); + void addBlobArg( ofBuffer argument ); + +private: + + string address; + vector<ofxOscArg*> args; + + string remote_host; + int remote_port; + + +}; diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.cpp new file mode 100755 index 0000000..2cf7a11 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.cpp @@ -0,0 +1,39 @@ +/* + * ofxOscParameterSync.cpp + * + * Created on: 13/07/2012 + * Author: arturo + */ + +#include "ofxOscParameterSync.h" + +ofxOscParameterSync::ofxOscParameterSync() { + syncGroup = NULL; + updatingParameter = false; +} + +ofxOscParameterSync::~ofxOscParameterSync(){ + if(syncGroup) + ofRemoveListener(syncGroup->parameterChangedE,this,&ofxOscParameterSync::parameterChanged); +} + + +void ofxOscParameterSync::setup(ofParameterGroup & group, int localPort, string host, int remotePort){ + syncGroup = &group; + ofAddListener(group.parameterChangedE,this,&ofxOscParameterSync::parameterChanged); + sender.setup(host,remotePort); + receiver.setup(localPort); +} + +void ofxOscParameterSync::update(){ + if(receiver.hasWaitingMessages()){ + updatingParameter = true; + receiver.getParameter(*syncGroup); + updatingParameter = false; + } +} + +void ofxOscParameterSync::parameterChanged( ofAbstractParameter & parameter ){ + if(updatingParameter) return; + sender.sendParameter(parameter); +} diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.h new file mode 100755 index 0000000..3272257 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscParameterSync.h @@ -0,0 +1,30 @@ +/* + * ofxOscParameterSync.h + * + * Created on: 13/07/2012 + * Author: arturo + */ + +#pragma once + +#include "ofxOscSender.h" +#include "ofxOscReceiver.h" +#include "ofParameter.h" +#include "ofParameterGroup.h" + +class ofxOscParameterSync { +public: + ofxOscParameterSync(); + ~ofxOscParameterSync(); + + /// the remote and local ports must be different to avoid collisions + void setup(ofParameterGroup & group, int localPort, string remoteHost, int remotePort); + void update(); + +private: + void parameterChanged( ofAbstractParameter & parameter ); + ofxOscSender sender; + ofxOscReceiver receiver; + ofParameterGroup * syncGroup; + bool updatingParameter; +}; diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.cpp new file mode 100755 index 0000000..d7ffd4e --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.cpp @@ -0,0 +1,284 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ofxOscReceiver.h" + +#ifndef TARGET_WIN32 + #include <pthread.h> +#endif +#include <iostream> +#include <assert.h> + +ofxOscReceiver::ofxOscReceiver() +{ + listen_socket = NULL; +} + +void ofxOscReceiver::setup( int listen_port ) +{ + // if we're already running, shutdown before running again + if ( listen_socket ) + shutdown(); + + // create the mutex + #ifdef TARGET_WIN32 + mutex = CreateMutexA( NULL, FALSE, NULL ); + #else + pthread_mutex_init( &mutex, NULL ); + #endif + + // create socket + socketHasShutdown = false; + listen_socket = new UdpListeningReceiveSocket( IpEndpointName( IpEndpointName::ANY_ADDRESS, listen_port ), this ); + + // start thread + #ifdef TARGET_WIN32 + thread = CreateThread( + NULL, // default security attributes + 0, // use default stack size + &ofxOscReceiver::startThread, // thread function + (void*)this, // argument to thread function + 0, // use default creation flags + NULL); // we don't the the thread id + + #else + pthread_create( &thread, NULL, &ofxOscReceiver::startThread, (void*)this ); + #endif +} + +void ofxOscReceiver::shutdown() +{ + if ( listen_socket ) + { + // tell the socket to shutdown + listen_socket->AsynchronousBreak(); + // wait for shutdown to complete + while (!socketHasShutdown) + { + #ifdef TARGET_WIN32 + Sleep(1); + #else + // sleep 0.1ms + usleep(100); + #endif + } + + // thread will clean up itself + + // clean up the mutex + #ifdef TARGET_WIN32 + ReleaseMutex( mutex ); + #else + pthread_mutex_destroy( &mutex ); + #endif + + // delete the socket + delete listen_socket; + listen_socket = NULL; + } +} + +ofxOscReceiver::~ofxOscReceiver() +{ + shutdown(); +} + +#ifdef TARGET_WIN32 +DWORD WINAPI +#else +void* +#endif + +ofxOscReceiver::startThread( void* receiverInstance ) +{ + // cast the instance + ofxOscReceiver* instance = (ofxOscReceiver*)receiverInstance; + // start the socket listener + instance->listen_socket->Run(); + // socket listener has finished - remember this fact + instance->socketHasShutdown = true; + // return + #ifdef TARGET_WIN32 + return 0; + #else + return NULL; + #endif +} + +void ofxOscReceiver::ProcessMessage( const osc::ReceivedMessage &m, const IpEndpointName& remoteEndpoint ) +{ + + // convert the message to an ofxOscMessage + ofxOscMessage* ofMessage = new ofxOscMessage(); + + // set the address + ofMessage->setAddress( m.AddressPattern() ); + + // set the sender ip/host + char endpoint_host[ IpEndpointName::ADDRESS_STRING_LENGTH ]; + remoteEndpoint.AddressAsString( endpoint_host ); + ofMessage->setRemoteEndpoint( endpoint_host, remoteEndpoint.port ); + + // transfer the arguments + for ( osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin(); + arg != m.ArgumentsEnd(); + ++arg ) + { + 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() ) + ofMessage->addStringArg( arg->AsStringUnchecked() ); + else if ( arg->IsBlob() ){ + const char * dataPtr; + unsigned long len = 0; + arg->AsBlobUnchecked((const void*&)dataPtr, len); + ofBuffer buffer(dataPtr, len); + ofMessage->addBlobArg( buffer ); + }else + { + ofLogError("ofxOscReceiver") << "ProcessMessage: argument in message " << m.AddressPattern() << " is not an int, float, or string"; + } + } + + // now add to the queue + + // at this point we are running inside the thread created by startThread, + // so anyone who calls hasWaitingMessages() or getNextMessage() is coming + // from a different thread + + // so we have to practise shared memory management + + // grab a lock on the queue + grabMutex(); + + // add incoming message on to the queue + messages.push_back( ofMessage ); + + // release the lock + releaseMutex(); +} + +bool ofxOscReceiver::hasWaitingMessages() +{ + // grab a lock on the queue + grabMutex(); + + // check the length of the queue + int queue_length = (int)messages.size(); + + // release the lock + releaseMutex(); + + // return whether we have any messages + return queue_length > 0; +} + +bool ofxOscReceiver::getNextMessage( ofxOscMessage* message ) +{ + // grab a lock on the queue + grabMutex(); + + // check if there are any to be got + if ( messages.size() == 0 ) + { + // no: release the mutex + releaseMutex(); + return false; + } + + // copy the message from the queue to message + ofxOscMessage* src_message = messages.front(); + message->copy( *src_message ); + + // now delete the src message + delete src_message; + // and remove it from the queue + messages.pop_front(); + + // release the lock on the queue + releaseMutex(); + + // return success + return true; +} + + +bool ofxOscReceiver::getParameter(ofAbstractParameter & parameter){ + ofxOscMessage msg; + if ( messages.size() == 0 ) return false; + while(hasWaitingMessages()){ + ofAbstractParameter * p = ¶meter; + + getNextMessage(&msg); + vector<string> address = ofSplitString(msg.getAddress(),"/",true); + + for(int i=0;i<address.size();i++){ + + if(p) { + if(address[i]==p->getEscapedName()){ + if(p->type()==typeid(ofParameterGroup).name()){ + if(address.size()>=i+1){ + p = &static_cast<ofParameterGroup*>(p)->get(address[i+1]); + } + }else if(p->type()==typeid(ofParameter<int>).name() && msg.getArgType(0)==OFXOSC_TYPE_INT32){ + p->cast<int>() = msg.getArgAsInt32(0); + }else if(p->type()==typeid(ofParameter<float>).name() && msg.getArgType(0)==OFXOSC_TYPE_FLOAT){ + p->cast<float>() = msg.getArgAsFloat(0); + }else if(p->type()==typeid(ofParameter<bool>).name() && msg.getArgType(0)==OFXOSC_TYPE_INT32){ + p->cast<bool>() = msg.getArgAsInt32(0); + }else if(msg.getArgType(0)==OFXOSC_TYPE_STRING){ + p->fromString(msg.getArgAsString(0)); + } + } + } + } + } + return true; +} + +void ofxOscReceiver::grabMutex() +{ +#ifdef TARGET_WIN32 + WaitForSingleObject( mutex, INFINITE ); +#else + pthread_mutex_lock( &mutex ); +#endif +} + +void ofxOscReceiver::releaseMutex() +{ +#ifdef TARGET_WIN32 + ReleaseMutex( mutex ); +#else + pthread_mutex_unlock( &mutex ); +#endif +} diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.h new file mode 100755 index 0000000..c844c33 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscReceiver.h @@ -0,0 +1,106 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <deque> +#include "ofMain.h" + +#ifdef TARGET_WIN32 +// threads +#include <windows.h> +#else +// threads +#include <pthread.h> +#endif + +// osc +#include "OscTypes.h" +#include "OscPacketListener.h" +#include "UdpSocket.h" + +// ofxOsc +#include "ofxOscMessage.h" + +class ofxOscReceiver : public osc::OscPacketListener +{ +public: + ofxOscReceiver(); + ~ofxOscReceiver(); + + /// listen_port is the port to listen for messages on + void setup( int listen_port ); + + /// returns true if there are any messages waiting for collection + bool hasWaitingMessages(); + /// take the next message on the queue of received messages, copy its details into message, and + /// remove it from the queue. return false if there are no more messages to be got, otherwise + /// return true + bool getNextMessage( ofxOscMessage* ); + + bool getParameter(ofAbstractParameter & parameter); + +protected: + /// process an incoming osc message and add it to the queue + virtual void ProcessMessage( const osc::ReceivedMessage &m, const IpEndpointName& remoteEndpoint ); + +private: + // shutdown the listener + void shutdown(); + + // start the listening thread +#ifdef TARGET_WIN32 + static DWORD WINAPI startThread( void* ofxOscReceiverInstance ); +#else + static void* startThread( void* ofxOscReceiverInstance ); +#endif + // queue of osc messages + std::deque< ofxOscMessage* > messages; + + // socket to listen on + UdpListeningReceiveSocket* listen_socket; + + // mutex helpers + void grabMutex(); + void releaseMutex(); + +#ifdef TARGET_WIN32 + // thread to listen with + HANDLE thread; + // mutex for the thread queue + HANDLE mutex; +#else + // thread to listen with + pthread_t thread; + // mutex for the message queue + pthread_mutex_t mutex; +#endif + // ready to be deleted + bool socketHasShutdown; + +}; diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.cpp b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.cpp new file mode 100755 index 0000000..e19e6a4 --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.cpp @@ -0,0 +1,192 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "ofxOscSender.h" +#include "ofUtils.h" +#include "ofParameterGroup.h" + + +#include "UdpSocket.h" + +#include <assert.h> + +ofxOscSender::ofxOscSender() +{ + socket = NULL; +} + +ofxOscSender::~ofxOscSender() +{ + if ( socket ) + shutdown(); +} + +void ofxOscSender::setup( std::string hostname, int port ) +{ + if ( socket ) + shutdown(); + + socket = new UdpTransmitSocket( IpEndpointName( hostname.c_str(), port ) ); +} + +void ofxOscSender::shutdown() +{ + if ( socket ) + delete socket; + socket = NULL; +} + +void ofxOscSender::sendBundle( ofxOscBundle& bundle ) +{ + //setting this much larger as it gets trimmed down to the size its using before being sent. + //TODO: much better if we could make this dynamic? Maybe have ofxOscBundle return its size? + static const int OUTPUT_BUFFER_SIZE = 327680; + char buffer[OUTPUT_BUFFER_SIZE]; + osc::OutboundPacketStream p(buffer, OUTPUT_BUFFER_SIZE ); + + // serialise the bundle + appendBundle( bundle, p ); + + socket->Send( p.Data(), p.Size() ); +} + +void ofxOscSender::sendMessage( ofxOscMessage& message ) +{ + //setting this much larger as it gets trimmed down to the size its using before being sent. + //TODO: much better if we could make this dynamic? Maybe have ofxOscMessage return its size? + static const int OUTPUT_BUFFER_SIZE = 327680; + char buffer[OUTPUT_BUFFER_SIZE]; + osc::OutboundPacketStream p( buffer, OUTPUT_BUFFER_SIZE ); + + // serialise the message + p << osc::BeginBundleImmediate; + appendMessage( message, p ); + p << osc::EndBundle; + + socket->Send( p.Data(), p.Size() ); +} + +void ofxOscSender::sendParameter( const ofAbstractParameter & parameter){ + if(!parameter.isSerializable()) return; + if(parameter.type()==typeid(ofParameterGroup).name()){ + string address = "/"; + const vector<string> hierarchy = parameter.getGroupHierarchyNames(); + for(int i=0;i<(int)hierarchy.size()-1;i++){ + address+=hierarchy[i] + "/"; + } + ofxOscBundle bundle; + appendParameter(bundle,parameter,address); + sendBundle(bundle); + }else{ + string address = ""; + const vector<string> hierarchy = parameter.getGroupHierarchyNames(); + for(int i=0;i<(int)hierarchy.size()-1;i++){ + address+= "/" + hierarchy[i]; + } + if(address.length()) address += "/"; + ofxOscMessage msg; + appendParameter(msg,parameter,address); + sendMessage(msg); + } +} + + +void ofxOscSender::appendParameter( ofxOscBundle & _bundle, const ofAbstractParameter & parameter, string address){ + if(parameter.type()==typeid(ofParameterGroup).name()){ + ofxOscBundle bundle; + const ofParameterGroup & group = static_cast<const ofParameterGroup &>(parameter); + for(int i=0;i<group.size();i++){ + const ofAbstractParameter & p = group[i]; + if(p.isSerializable()){ + appendParameter(bundle,p,address+group.getEscapedName()+"/"); + } + } + _bundle.addBundle(bundle); + }else{ + if(parameter.isSerializable()){ + ofxOscMessage msg; + appendParameter(msg,parameter,address); + _bundle.addMessage(msg); + } + } +} + +void ofxOscSender::appendParameter( ofxOscMessage & msg, const ofAbstractParameter & parameter, string address){ + msg.setAddress(address+parameter.getEscapedName()); + if(parameter.type()==typeid(ofParameter<int>).name()){ + msg.addIntArg(parameter.cast<int>()); + }else if(parameter.type()==typeid(ofParameter<float>).name()){ + msg.addFloatArg(parameter.cast<float>()); + }else if(parameter.type()==typeid(ofParameter<bool>).name()){ + msg.addIntArg(parameter.cast<bool>()); + }else{ + msg.addStringArg(parameter.toString()); + } +} + +void ofxOscSender::appendBundle( ofxOscBundle& bundle, osc::OutboundPacketStream& p ) +{ + // recursively serialise the bundle + p << osc::BeginBundleImmediate; + for ( int i=0; i<bundle.getBundleCount(); i++ ) + { + appendBundle( bundle.getBundleAt( i ), p ); + } + for ( int i=0; i<bundle.getMessageCount(); i++ ) + { + appendMessage( bundle.getMessageAt( i ), p ); + } + p << osc::EndBundle; +} + +void ofxOscSender::appendMessage( ofxOscMessage& message, osc::OutboundPacketStream& p ) +{ + p << osc::BeginMessage( message.getAddress().c_str() ); + for ( int i=0; i< message.getNumArgs(); ++i ) + { + 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 if ( message.getArgType( i ) == OFXOSC_TYPE_BLOB ){ + ofBuffer buff = message.getArgAsBlob(i); + osc::Blob b(buff.getBinaryBuffer(), (unsigned long)buff.size()); + p << b; + }else + { + ofLogError("ofxOscSender") << "appendMessage(): bad argument type " << message.getArgType( i ); + assert( false ); + } + } + p << osc::EndMessage; +} diff --git a/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.h b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.h new file mode 100755 index 0000000..5b07e6e --- /dev/null +++ b/ofxMaxim/HACKDAY/ofxMaximExample_0.8.4_OSX_Granular/ofxOsc/src/ofxOscSender.h @@ -0,0 +1,77 @@ +/* + + Copyright (c) 2007-2009, Damian Stewart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the developer nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY DAMIAN STEWART ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL DAMIAN STEWART BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +/** + +ofxOscSender + +an ofxOscSender sends messages to a single host/port + +*/ + +class UdpTransmitSocket; +#include <string> +#include "OscTypes.h" +#include "OscOutboundPacketStream.h" + +#include "ofxOscBundle.h" +#include "ofxOscMessage.h" +#include "ofParameter.h" +#include "ofParameterGroup.h" + + +class ofxOscSender +{ +public: + ofxOscSender(); + ~ofxOscSender(); + + /// send messages to hostname and port + void setup( std::string hostname, int port ); + + /// send the given message + void sendMessage( ofxOscMessage& message ); + /// send the given bundle + void sendBundle( ofxOscBundle& bundle ); + /// creates a message using an ofParameter + void sendParameter( const ofAbstractParameter & parameter); + + +private: + void shutdown(); + + // helper methods for constructing messages + void appendBundle( ofxOscBundle& bundle, osc::OutboundPacketStream& p ); + void appendMessage( ofxOscMessage& message, osc::OutboundPacketStream& p ); + void appendParameter( ofxOscBundle & bundle, const ofAbstractParameter & parameter, string address); + void appendParameter( ofxOscMessage & msg, const ofAbstractParameter & parameter, string address); + + UdpTransmitSocket* socket; +}; |
