# HG changeset patch
# User tomwalters@google.com
# Date 1340367728 0
# Node ID 0284d2152e1783a01f1163277a8fc59ea640552c
# Parent d609725e568aa1fb22551594ff46242e8669744c
Add support for outputting featutes using OSC (for use with the Wekinator, etc).
diff -r d609725e568a -r 0284d2152e17 SConstruct
--- a/SConstruct Fri Jun 22 12:17:24 2012 +0000
+++ b/SConstruct Fri Jun 22 12:22:08 2012 +0000
@@ -52,6 +52,7 @@
'Modules/Profile/ModuleScaler.cc',
'Modules/Output/FileOutputHTK.cc',
'Modules/Output/FileOutputAIMC.cc',
+ 'Modules/Output/OSCOutput.cc',
'Modules/Features/ModuleGaussians.cc',
'Modules/Features/ModuleBoxes.cc',]
#'Modules/Features/ModuleDCT.cc' ]
@@ -177,6 +178,9 @@
deplibs = ['sndfile']
deplibs += graphics_libraries
+env.Append(CPPPATH = ['#external/oscpack/oscpack/include/'])
+env.AppendUnique(LIBPATH = ['#external/oscpack/oscpack/lib/'])
+
if target_platform != 'win32':
for depname in deplibs:
env.ParseConfig('pkg-config --cflags --libs ' + depname)
@@ -203,6 +207,8 @@
build_dir+'/libcairo-2.dll')
env.Append(CPPPATH = [windows_cairo_location + '/include/cairo/'])
env.AppendUnique(LIBPATH = [windows_cairo_location + '/lib/'])
+
+deplibs.append('liboscpack')
env.AppendUnique(LIBS = deplibs)
diff -r d609725e568a -r 0284d2152e17 external/oscpack/CHANGES
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/CHANGES Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,68 @@
+September 28, 2005
+------------------
+
+Compared to the previous official snapshot (November 2004) the
+current version of oscpack includes a re-written set of network
+classes and some changes to the syntax of the networking code. It no
+longer uses threads, which means that you don't need to use sleep()
+if you are writing a simple single-threaded server, or you need to
+spawn your own threads in a more complex application.
+
+The list below summarises the changes if you are porting code from
+the previous release.
+
+ - there are no longer any threads in oscpack. if you need to
+ set up an asynchronous listener you can create your own thread
+ and call Run on an instance of SocketReceiveMultiplexer or
+ UdpListeningReceiveSocket (see ip/UdpSocket.h) yourself.
+
+ - host byte order is now used for network (IP) addresses
+
+ - functions which used to take two parameters
+ now take an instance of IpEndpointName (see
+ ip/IpEndpointName.h) this class has a number of convenient
+ constructors for converting numbers and strings to internet
+ addresses. For example there is one which takes a string and
+ another that take the dotted address components as separate
+ parameters.
+
+ - The UdpTransmitPort class, formerly in UdpTransmitPort.h, is
+ now called UdpTransmitSocket, which is simply a convenience
+ class derived from UdpSocket (see ip/UdpSocket.h). Where you
+ used to use the constructor UdpTransmitPort( address, port) now
+ you can use UdpTransmitSocket( IpEndpointName( address, port )
+ ) or you can any of the other possible ctors to IpEndpointName
+ () (see above). The Send() method is unchanged.
+
+ - The packet listener base class is now located in
+ ip/PacketListener.h instead of PacketListenerPort.h. The
+ ProcessPacket method now has an additional parameter indicating
+ the remote endpoint
+
+ - The preferred way to set up listeners is with
+ SocketReceiveMultiplexer (in ip/UdpSocket.h), this also allows
+ attaching periodic timers. For simple applications which only
+ listen to a single socket with no timers you can use
+ UdpListeningReceiveSocket (also in UdpSocket.h) See
+ osc/OscReceiveTest.cpp or osc/OscDump.cpp for examples of this.
+ This is more or less equivalent to the UdpPacketListenerPort
+ object in the old oscpack versions except that you need to
+ explicitly call Run() before it will start receiving packets
+ and it runs in the same thread, not a separate thread so Run()
+ won't usually return.
+
+ - Explicit calls to InitializeNetworking() and
+ TerminateNetworking() are no longer required for simple
+ applications (more complex windows applications should
+ instantiate NetworkInitializer in main() or WinMain (see
+ ip/NetworkingUtils.h/.cpp)
+
+ - The OscPacketListener base class (OscPacketListener.h) was
+ added to make traversing OSC packets easier, it handles bundle
+ traversal automatically so you only need to process messages in
+ your derived classes.
+
+ - On Windows be sure to link with ws2_32.lib or you will see
+ a linker error about WSAEventSelect not being found. Also you
+ will need to link with winmm.lib for timeGetTime()
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/LICENSE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/LICENSE Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,28 @@
+oscpack -- Open Sound Control packet manipulation library
+http://www.audiomulch.com/~rossb/code/oscpack
+
+Copyright (c) 2004 Ross Bencina
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files
+(the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+Any person wishing to distribute modifications to the Software is
+requested to send the modifications to the original developer so that
+they can be incorporated into the canonical version.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/Makefile Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,99 @@
+# should be either OSC_HOST_BIG_ENDIAN or OSC_HOST_LITTLE_ENDIAN
+# Apple Mac OS X: OSC_HOST_BIG_ENDIAN
+# Win32: OSC_HOST_LITTLE_ENDIAN
+# i386 GNU/Linux: OSC_HOST_LITTLE_ENDIAN
+ENDIANESS=OSC_HOST_LITTLE_ENDIAN
+
+CXX = g++
+INCLUDES = -I./
+COPTS = -Wall -O3
+CDEBUG = -Wall -g
+CXXFLAGS = $(COPTS) $(INCLUDES) -D$(ENDIANESS) -arch i386
+
+PREFIX = /usr/local
+INSTALL = /usr/bin/install -c
+
+#Name definitions
+UNITTESTS=OscUnitTests
+SEND=OscSendTests
+RECEIVE=OscReceiveTest
+DUMP=OscDump
+
+INCLUDEDIR = oscpack
+LIBNAME = liboscpack
+LIBSONAME = $(LIBNAME)
+LIBFILENAME = $(LIBSONAME).1.0.2.dylib
+
+#Test and example source
+SENDSOURCES = ./tests/OscSendTests.cpp ./osc/OscOutboundPacketStream.cpp ./osc/OscTypes.cpp ./ip/posix/NetworkingUtils.cpp ./ip/posix/UdpSocket.cpp ./ip/IpEndpointName.cpp
+SENDOBJECTS = $(SENDSOURCES:.cpp=.o)
+
+RECEIVESOURCES = ./tests/OscReceiveTest.cpp ./osc/OscTypes.cpp ./osc/OscReceivedElements.cpp ./osc/OscPrintReceivedElements.cpp ./ip/posix/NetworkingUtils.cpp ./ip/posix/UdpSocket.cpp
+RECEIVEOBJECTS = $(RECEIVESOURCES:.cpp=.o)
+
+DUMPSOURCES = ./examples/OscDump.cpp ./osc/OscTypes.cpp ./osc/OscReceivedElements.cpp ./osc/OscPrintReceivedElements.cpp ./ip/posix/NetworkingUtils.cpp ./ip/posix/UdpSocket.cpp
+DUMPOBJECTS = $(DUMPSOURCES:.cpp=.o)
+
+UNITTESTSOURCES = ./tests/OscUnitTests.cpp ./osc/OscOutboundPacketStream.cpp ./osc/OscTypes.cpp ./osc/OscReceivedElements.cpp ./osc/OscPrintReceivedElements.cpp
+UNITTESTOBJECTS = $(UNITTESTSOURCES:.cpp=.o)
+
+#Library sources
+LIBSOURCES = ./ip/IpEndpointName.cpp \
+ ./ip/posix/NetworkingUtils.cpp ./ip/posix/UdpSocket.cpp\
+ ./osc/OscOutboundPacketStream.cpp ./osc/OscPrintReceivedElements.cpp ./osc/OscReceivedElements.cpp ./osc/OscTypes.cpp
+LIBOBJECTS = $(LIBSOURCES:.cpp=.o)
+
+all: unittests send receive dump
+
+unittests : $(UNITTESTOBJECTS)
+ @if [ ! -d bin ] ; then mkdir bin ; fi
+ $(CXX) -o bin/$(UNITTESTS) $+ $(LIBS)
+send : $(SENDOBJECTS)
+ @if [ ! -d bin ] ; then mkdir bin ; fi
+ $(CXX) -o bin/$(SEND) $+ $(LIBS)
+receive : $(RECEIVEOBJECTS)
+ @if [ ! -d bin ] ; then mkdir bin ; fi
+ $(CXX) -o bin/$(RECEIVE) $+ $(LIBS)
+dump : $(DUMPOBJECTS)
+ @if [ ! -d bin ] ; then mkdir bin ; fi
+ $(CXX) -o bin/$(DUMP) $+ $(LIBS)
+
+clean:
+ rm -rf bin $(UNITTESTOBJECTS) $(SENDOBJECTS) $(RECEIVEOBJECTS) $(DUMPOBJECTS) $(LIBOBJECTS) $(LIBFILENAME) include lib oscpack &> /dev/null
+
+$(LIBFILENAME): $(LIBOBJECTS)
+ @#GNU/Linux case
+ #$(CXX) -shared -Wl,-soname,$(LIBSONAME) -o $(LIBFILENAME) $(LIBOBJECTS) -lc
+ @#Mac OS X case
+ $(CXX) -dynamiclib -Wl,-install_name,$(LIBSONAME) -o $(LIBFILENAME) $(LIBOBJECTS) -lc -arch i386
+
+lib: $(LIBFILENAME)
+
+#Installs the library on a system global location
+install: lib
+ @$(INSTALL) -m 755 $(LIBFILENAME) $(PREFIX)/lib/$(LIBFILENAME)
+ @ln -s -f $(PREFIX)/lib/$(LIBFILENAME) $(PREFIX)/lib/$(LIBSONAME)
+ @mkdir -p $(PREFIX)/include/oscpack/ip $(PREFIX)/include/oscpack/osc
+ @$(INSTALL) -m 644 ip/*.h $(PREFIX)/include/oscpack/ip
+ @$(INSTALL) -m 644 osc/*.h $(PREFIX)/include/oscpack/osc
+ @echo "SUCCESS! oscpack has been installed in $(PREFIX)/lib and $(PREFIX)/include/ospack/"
+ @echo "now doing ldconfig..."
+ @ldconfig
+
+#Installs the include/lib structure locally
+install-local: lib
+ @echo ""
+ @echo " Installing in local directory <$(INCLUDEDIR)>"
+ @echo " > Creating symbolic link"
+ @ln -s $(LIBFILENAME) $(LIBSONAME)
+ @echo " > Creating directories"
+ @mkdir -p oscpack/lib
+ @mkdir -p oscpack/include/ip
+ @mkdir -p oscpack/include/osc
+ @echo " > Copying files"
+ @mv $(LIBFILENAME) $(LIBSONAME) oscpack/lib
+ @cp ip/*.h oscpack/include/ip
+ @cp osc/*.h oscpack/include/osc
+ @echo ""
+ @echo " > Success!"
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/README Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,80 @@
+oscpack -- Open Sound Control packet manipulation library
+http://www.audiomulch.com/~rossb/code/oscpack
+
+Copyright (c) 2004-2005 Ross Bencina
+
+A simple C++ library for packing and unpacking OSC packets.
+
+
+Oscpack is simply a set of C++ classes for packing and unpacking OSC packets.
+Oscpack includes a minimal set of UDP networking classes for windows and posix
+which are sufficient for writing many OSC applications and servers, but you are
+encouraged to use another networking framework if it better suits your needs.
+Oscpack is not an OSC application framework, it doesn't include infrastructure for
+constructing or routing OSC namespaces, just classes for easily constructing,
+sending, receiving and parsing OSC packets. The library should also be easy to use
+for other transport methods (eg serial).
+
+The key goals of the oscpack library are:
+
+ - to be a simple and complete implementation of OSC
+ - to be portable to a wide variety of platforms
+ - to allow easy development of robust OSC applications
+ (for example it should be impossible to crash a server
+ by sending it malformed packets, and difficult to
+ create malformed packets.)
+
+Here's a summary of the key files:
+
+osc/OscReceivedElements -- classes for parsing a packet
+osc/OscPrintRecievedElements -- iostream << operators for printing packet elements
+osc/OscOutboundPacket -- a class for packing messages into a packet
+osc/OscPacketListener -- base class for listening to OSC packets on a UdpSocket
+tests/OscUnitTests -- unit test program for the OSC modules
+tests/OscSendTests -- examples of how to send messages
+tests/OscReceiveTest -- example of how to receive the messages sent by OSCSendTests
+examples/OscDump -- a program that prints received OSC packets
+
+
+
+Building
+--------
+
+In general the idea is that you will embed this source code in your projects as you
+see fit. The Makefile has an install rule for building a shared library and
+installing headers in usr/local.
+
+The Makefile works for Linux and MaxOS X except that if you are on a big endian
+machine such as PowerPC Macintosh you need to edit the line which sets the
+endianness to OSC_HOST_BIG_ENDIAN (see the makefile comment for details) or it won't
+work. If you want to build and install liboscpack as a library on OS X you also need
+to edit the $(LIBFILENAME) rule by commenting out the Linux case and uncommenting
+the OS X case since OS X uses different gcc flags for shared libraries.
+
+On Windows there is a batch file for doing a simple test build with MinGW gcc called
+make.MinGW32.bat. This will build the test executables and oscdump in ./bin and run
+the unit tests.
+
+--
+
+
+If you fix anything or write a set of TCP send/recieve classes
+please consider sending me a patch. Thanks :)
+
+For more information about Open Sound Control, see:
+http://www.cnmat.berkeley.edu/OpenSoundControl/
+
+
+Thanks to Till Bovermann for helping with POSIX networking code and
+Mac compatibility, and to Martin Kaltenbrunner and the rest of the
+reacTable team for giving me a reason to finish this library. Thanks
+to Merlijn Blaauw for reviewing the interfaces. Thanks to Xavier Oliver
+for additional help with Linux builds and POSIX implementation details.
+
+Portions developed at the Music Technology Group, Audiovisual Institute,
+University Pompeu Fabra, Barcelona, during my stay as a visiting
+researcher, November 2004 - September 2005.
+
+See the file LICENSE for information about distributing and using this code.
+
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/TODO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/TODO Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,55 @@
+TODO:
+
+ - consider adding the local endpoint name to PacketListener::PacketReceived() params
+
+ - consider adding ListenerThread class to support old seperate thread listener functionality, something like:
+
+ class UdpSocketListenerThread{
+ public:
+ UdpSocketListenerThread( UdpSocket& socket, Listener *listener );
+ UdpSocketListenerThread( UdpSocketReceiveMultiplexer *mux );
+ ~UdpSocketListenerThread();
+
+ void Run();
+ void Stop();
+ };
+
+ - provide some kind of automatic endianness configuration (hopefully there
+ are gcc symbols for this)
+
+ - work out a way to make the parsing classes totally safe. at a minimum this
+ means adding functions to test for invalid float/doublevalues,
+ making sure the iterators never pass the end of the message, ...
+ (passing end of message can happen if:
+ - too many args in type tags
+ a. typetags overflow message size
+ b. args fulfilling typetags overflow message size
+ - strings too long or not terminated correctly
+ - blobs too long or not terminated correctly
+
+ if the message was fully checked during construction, the end() iterator
+ could be moved back until only arguments which fit withing size() may
+ be interated (this could be none). A flag could be set to indicate that
+ something was wrong.
+
+ - other packet badness could include:
+ - time tags too far into the future (the scheduler should deal with
+ that i guess).
+ - message address patterns which aren't correctly terminated
+
+ - improve the ability to parse messages without tags (SC uses methods which
+ get the data and advance the iterator in one step.)
+ - Check* could be modified to do this - ie if typetags are not present
+ it could check that reading the field won't escape the message size
+ and return the data, or return false if some consistency
+ constraint is violated.
+ (or alternately drop support for messages without type tags)
+
+
+ - add a method to discard an inprogress message if it gets half
+ constructed and the buffer is full in OutboundPacket
+
+ - write a stress testing app which can send garbage packets to try to flush out other bugs in the parsing code.
+
+
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/examples/OscDump.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/examples/OscDump.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,83 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ OscDump prints incoming Osc packets. Unlike the Berkeley dumposc program
+ OscDump uses a different printing format which indicates the type of each
+ message argument.
+*/
+
+
+#include
+
+#include "osc/OscReceivedElements.h"
+#include "osc/OscPrintReceivedElements.h"
+
+#include "ip/UdpSocket.h"
+#include "ip/PacketListener.h"
+
+
+class OscDumpPacketListener : public PacketListener{
+public:
+ virtual void ProcessPacket( const char *data, int size,
+ const IpEndpointName& remoteEndpoint )
+ {
+ std::cout << osc::ReceivedPacket( data, size );
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ if( argc >= 2 && strcmp( argv[1], "-h" ) == 0 ){
+ std::cout << "usage: OscDump [port]\n";
+ return 0;
+ }
+
+ int port = 7000;
+
+ if( argc >= 2 )
+ port = atoi( argv[1] );
+
+ OscDumpPacketListener listener;
+ UdpListeningReceiveSocket s(
+ IpEndpointName( IpEndpointName::ANY_ADDRESS, port ),
+ &listener );
+
+ std::cout << "listening for input on port " << port << "...\n";
+ std::cout << "press ctrl-c to end\n";
+
+ s.RunUntilSigInt();
+
+ std::cout << "finishing.\n";
+
+ return 0;
+}
+
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/examples/SimpleReceive.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/examples/SimpleReceive.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,74 @@
+/*
+ Example of two different ways to process received OSC messages using oscpack.
+ Receives the messages from the SimpleSend.cpp example.
+*/
+
+#include
+
+#include "osc/OscReceivedElements.h"
+#include "osc/OscPacketListener.h"
+#include "ip/UdpSocket.h"
+
+
+#define PORT 7000
+
+class ExamplePacketListener : public osc::OscPacketListener {
+protected:
+
+ virtual void ProcessMessage( const osc::ReceivedMessage& m,
+ const IpEndpointName& remoteEndpoint )
+ {
+ try{
+ // example of parsing single messages. osc::OsckPacketListener
+ // handles the bundle traversal.
+
+ if( strcmp( m.AddressPattern(), "/test1" ) == 0 ){
+ // example #1 -- argument stream interface
+ osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
+ bool a1;
+ osc::int32 a2;
+ float a3;
+ const char *a4;
+ args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
+
+ std::cout << "received '/test1' message with arguments: "
+ << a1 << " " << a2 << " " << a3 << " " << a4 << "\n";
+
+ }else if( strcmp( m.AddressPattern(), "/test2" ) == 0 ){
+ // example #2 -- argument iterator interface, supports
+ // reflection for overloaded messages (eg you can call
+ // (*arg)->IsBool() to check if a bool was passed etc).
+ osc::ReceivedMessage::const_iterator arg = m.ArgumentsBegin();
+ bool a1 = (arg++)->AsBool();
+ int a2 = (arg++)->AsInt32();
+ float a3 = (arg++)->AsFloat();
+ const char *a4 = (arg++)->AsString();
+ if( arg != m.ArgumentsEnd() )
+ throw osc::ExcessArgumentException();
+
+ std::cout << "received '/test2' message with arguments: "
+ << a1 << " " << a2 << " " << a3 << " " << a4 << "\n";
+ }
+ }catch( osc::Exception& e ){
+ // any parsing errors such as unexpected argument types, or
+ // missing arguments get thrown as exceptions.
+ std::cout << "error while parsing message: "
+ << m.AddressPattern() << ": " << e.what() << "\n";
+ }
+ }
+};
+
+int main(int argc, char* argv[])
+{
+ ExamplePacketListener listener;
+ UdpListeningReceiveSocket s(
+ IpEndpointName( IpEndpointName::ANY_ADDRESS, PORT ),
+ &listener );
+
+ std::cout << "press ctrl-c to end\n";
+
+ s.RunUntilSigInt();
+
+ return 0;
+}
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/examples/SimpleSend.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/examples/SimpleSend.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,30 @@
+/*
+ Simple example of sending an OSC message using oscpack.
+*/
+
+#include "osc/OscOutboundPacketStream.h"
+#include "ip/UdpSocket.h"
+
+
+#define ADDRESS "127.0.0.1"
+#define PORT 7000
+
+#define OUTPUT_BUFFER_SIZE 1024
+
+int main(int argc, char* argv[])
+{
+ UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, PORT ) );
+
+ char buffer[OUTPUT_BUFFER_SIZE];
+ osc::OutboundPacketStream p( buffer, OUTPUT_BUFFER_SIZE );
+
+ p << osc::BeginBundleImmediate
+ << osc::BeginMessage( "/test1" )
+ << true << 23 << (float)3.1415 << "hello" << osc::EndMessage
+ << osc::BeginMessage( "/test2" )
+ << true << 24 << (float)10.8 << "world" << osc::EndMessage
+ << osc::EndBundle;
+
+ transmitSocket.Send( p.Data(), p.Size() );
+}
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/IpEndpointName.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/IpEndpointName.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,81 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "IpEndpointName.h"
+
+#include
+
+#include "NetworkingUtils.h"
+
+
+unsigned long IpEndpointName::GetHostByName( const char *s )
+{
+ return ::GetHostByName(s);
+}
+
+
+void IpEndpointName::AddressAsString( char *s ) const
+{
+ if( address == ANY_ADDRESS ){
+ sprintf( s, "" );
+ }else{
+ sprintf( s, "%d.%d.%d.%d",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF) );
+ }
+}
+
+
+void IpEndpointName::AddressAndPortAsString( char *s ) const
+{
+ if( port == ANY_PORT ){
+ if( address == ANY_ADDRESS ){
+ sprintf( s, ":" );
+ }else{
+ sprintf( s, "%d.%d.%d.%d:",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF) );
+ }
+ }else{
+ if( address == ANY_ADDRESS ){
+ sprintf( s, ":%d", port );
+ }else{
+ sprintf( s, "%d.%d.%d.%d:%d",
+ (int)((address >> 24) & 0xFF),
+ (int)((address >> 16) & 0xFF),
+ (int)((address >> 8) & 0xFF),
+ (int)(address & 0xFF),
+ (int)port );
+ }
+ }
+}
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/IpEndpointName.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/IpEndpointName.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,74 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_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;
+
+ 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 -r d609725e568a -r 0284d2152e17 external/oscpack/ip/NetworkingUtils.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/NetworkingUtils.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,49 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_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 -r d609725e568a -r 0284d2152e17 external/oscpack/ip/PacketListener.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/PacketListener.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,43 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_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 -r d609725e568a -r 0284d2152e17 external/oscpack/ip/TimerListener.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/TimerListener.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,40 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_TIMERLISTENER_H
+#define INCLUDED_TIMERLISTENER_H
+
+
+class TimerListener{
+public:
+ virtual ~TimerListener() {}
+ virtual void TimerExpired() = 0;
+};
+
+#endif /* INCLUDED_TIMERLISTENER_H */
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/UdpSocket.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/UdpSocket.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,158 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_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 -r d609725e568a -r 0284d2152e17 external/oscpack/ip/posix/NetworkingUtils.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/posix/NetworkingUtils.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,57 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+
+#include
+#include
+#include
+#include
+#include
+
+
+
+NetworkInitializer::NetworkInitializer() {}
+
+NetworkInitializer::~NetworkInitializer() {}
+
+
+unsigned long GetHostByName( const char *name )
+{
+ unsigned long result = 0;
+
+ struct hostent *h = gethostbyname( name );
+ if( h ){
+ struct in_addr a;
+ memcpy( &a, h->h_addr_list[0], h->h_length );
+ result = ntohl(a.s_addr);
+ }
+
+ return result;
+}
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/posix/UdpSocket.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/posix/UdpSocket.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,546 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // for memset
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include // for sockaddr_in
+
+#include "ip/PacketListener.h"
+#include "ip/TimerListener.h"
+
+
+#if defined(__APPLE__) && !defined(_SOCKLEN_T)
+// pre system 10.3 didn have socklen_t
+typedef ssize_t socklen_t;
+#endif
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ sockAddr.sin_family = AF_INET;
+
+ sockAddr.sin_addr.s_addr =
+ (endpoint.address == IpEndpointName::ANY_ADDRESS)
+ ? INADDR_ANY
+ : htonl( endpoint.address );
+
+ sockAddr.sin_port =
+ (endpoint.port == IpEndpointName::ANY_PORT)
+ ? 0
+ : htons( endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+ return IpEndpointName(
+ (sockAddr.sin_addr.s_addr == INADDR_ANY)
+ ? IpEndpointName::ANY_ADDRESS
+ : ntohl( sockAddr.sin_addr.s_addr ),
+ (sockAddr.sin_port == 0)
+ ? IpEndpointName::ANY_PORT
+ : ntohs( sockAddr.sin_port )
+ );
+}
+
+
+class UdpSocket::Implementation{
+ bool isBound_;
+ bool isConnected_;
+
+ int socket_;
+ struct sockaddr_in connectedAddr_;
+ struct sockaddr_in sendToAddr_;
+
+public:
+
+ Implementation()
+ : isBound_( false )
+ , isConnected_( false )
+ , socket_( -1 )
+ {
+ if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
+ throw std::runtime_error("unable to create udp socket\n");
+ }
+
+ memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+ sendToAddr_.sin_family = AF_INET;
+ }
+
+ ~Implementation()
+ {
+ if (socket_ != -1) close(socket_);
+ }
+
+ IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+ {
+ assert( isBound_ );
+
+ // first connect the socket to the remote server
+
+ struct sockaddr_in connectSockAddr;
+ SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ // get the address
+
+ struct sockaddr_in sockAddr;
+ memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+ socklen_t length = sizeof(sockAddr);
+ if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+ throw std::runtime_error("unable to getsockname\n");
+ }
+
+ if( isConnected_ ){
+ // reconnect to the connected address
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ }else{
+ // unconnect from the remote address
+
+ struct sockaddr_in unconnectSockAddr;
+ memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
+ unconnectSockAddr.sin_family = AF_UNSPEC;
+ // address fields are zero
+ int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
+ if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
+ throw std::runtime_error("unable to un-connect udp socket\n");
+ }
+ }
+
+ return IpEndpointNameFromSockaddr( sockAddr );
+ }
+
+ void Connect( const IpEndpointName& remoteEndpoint )
+ {
+ SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+
+ if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+ throw std::runtime_error("unable to connect udp socket\n");
+ }
+
+ isConnected_ = true;
+ }
+
+ void Send( const char *data, int size )
+ {
+ assert( isConnected_ );
+
+ send( socket_, data, size, 0 );
+ }
+
+ void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+ {
+ sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+ sendToAddr_.sin_port = htons( remoteEndpoint.port );
+
+ sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+ }
+
+ void Bind( const IpEndpointName& localEndpoint )
+ {
+ struct sockaddr_in bindSockAddr;
+ SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+ if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+ throw std::runtime_error("unable to bind udp socket\n");
+ }
+
+ isBound_ = true;
+ }
+
+ bool IsBound() const { return isBound_; }
+
+ int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+ {
+ assert( isBound_ );
+
+ struct sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof(fromAddr);
+
+ int result = recvfrom(socket_, data, size, 0,
+ (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+ if( result < 0 )
+ return 0;
+
+ remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+ remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+ return result;
+ }
+
+ int Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+ impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+ delete impl_;
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+ return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+ impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, int size )
+{
+ impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
+{
+ impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+ impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+ return impl_->IsBound();
+}
+
+int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
+{
+ return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+ AttachedTimerListener( int id, int p, TimerListener *tl )
+ : initialDelayMs( id )
+ , periodMs( p )
+ , listener( tl ) {}
+ int initialDelayMs;
+ int periodMs;
+ TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls(
+ const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+ return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+ multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+ signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+ std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+ std::vector< AttachedTimerListener > timerListeners_;
+
+ volatile bool break_;
+ int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
+
+ double GetCurrentTimeMs() const
+ {
+ struct timeval t;
+
+ gettimeofday( &t, 0 );
+
+ return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
+ }
+
+public:
+ Implementation()
+ {
+ if( pipe(breakPipe_) != 0 )
+ throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
+ }
+
+ ~Implementation()
+ {
+ close( breakPipe_[0] );
+ close( breakPipe_[1] );
+ }
+
+ void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+ // we don't check that the same socket has been added multiple times, even though this is an error
+ socketListeners_.push_back( std::make_pair( listener, socket ) );
+ }
+
+ void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
+ std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+ assert( i != socketListeners_.end() );
+
+ socketListeners_.erase( i );
+ }
+
+ void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void DetachPeriodicTimerListener( TimerListener *listener )
+ {
+ std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ while( i != timerListeners_.end() ){
+ if( i->listener == listener )
+ break;
+ ++i;
+ }
+
+ assert( i != timerListeners_.end() );
+
+ timerListeners_.erase( i );
+ }
+
+ void Run()
+ {
+ break_ = false;
+
+ // configure the master fd_set for select()
+
+ fd_set masterfds, tempfds;
+ FD_ZERO( &masterfds );
+ FD_ZERO( &tempfds );
+
+ // in addition to listening to the inbound sockets we
+ // also listen to the asynchronous break pipe, so that AsynchronousBreak()
+ // can break us out of select() from another thread.
+ FD_SET( breakPipe_[0], &masterfds );
+ int fdmax = breakPipe_[0];
+
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i ){
+
+ if( fdmax < i->second->impl_->Socket() )
+ fdmax = i->second->impl_->Socket();
+ FD_SET( i->second->impl_->Socket(), &masterfds );
+ }
+
+
+ // configure the timer queue
+ double currentTimeMs = GetCurrentTimeMs();
+
+ // expiry time ms, listener
+ std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+ for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ i != timerListeners_.end(); ++i )
+ timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+ const int MAX_BUFFER_SIZE = 4098;
+ char *data = new char[ MAX_BUFFER_SIZE ];
+ IpEndpointName remoteEndpoint;
+
+ struct timeval timeout;
+
+ while( !break_ ){
+ tempfds = masterfds;
+
+ struct timeval *timeoutPtr = 0;
+ if( !timerQueue_.empty() ){
+ double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
+ if( timeoutMs < 0 )
+ timeoutMs = 0;
+
+ // 1000000 microseconds in a second
+ timeout.tv_sec = (long)(timeoutMs * .001);
+ timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000);
+ timeoutPtr = &timeout;
+ }
+
+ if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){
+ throw std::runtime_error("select failed\n");
+ }
+
+ if ( FD_ISSET( breakPipe_[0], &tempfds ) ){
+ // clear pending data from the asynchronous break pipe
+ char c;
+ read( breakPipe_[0], &c, 1 );
+ }
+
+ if( break_ )
+ break;
+
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i ){
+
+ if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
+
+ int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+ if( size > 0 ){
+ i->first->ProcessPacket( data, size, remoteEndpoint );
+ if( break_ )
+ break;
+ }
+ }
+ }
+
+ // execute any expired timers
+ currentTimeMs = GetCurrentTimeMs();
+ bool resort = false;
+ for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+ i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+ i->second.listener->TimerExpired();
+ if( break_ )
+ break;
+
+ i->first += i->second.periodMs;
+ resort = true;
+ }
+ if( resort )
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+ }
+
+ delete [] data;
+ }
+
+ void Break()
+ {
+ break_ = true;
+ }
+
+ void AsynchronousBreak()
+ {
+ break_ = true;
+
+ // Send a termination message to the asynchronous break pipe, so select() will return
+ write( breakPipe_[1], "!", 1 );
+ }
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+ impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{
+ delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+ impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+ impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+ assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+ multiplexerInstanceToAbortWithSigInt_ = this;
+ signal( SIGINT, InterruptSignalHandler );
+ impl_->Run();
+ signal( SIGINT, SIG_DFL );
+ multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+ impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+ impl_->AsynchronousBreak();
+}
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/win32/NetworkingUtils.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/win32/NetworkingUtils.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,88 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/NetworkingUtils.h"
+
+#include // this must come first to prevent errors with MSVC7
+#include
+#include
+#include
+
+
+static LONG initCount_ = 0;
+static bool winsockInitialized_ = false;
+
+NetworkInitializer::NetworkInitializer()
+{
+ if( InterlockedIncrement( &initCount_ ) == 1 ){
+ // there is a race condition here if one thread tries to access
+ // the library while another is still initializing it.
+ // i can't think of an easy way to fix it so i'm telling you here
+ // incase you need to init the library from two threads at once.
+ // this is why the header file advises to instantiate one of these
+ // in main() so that the initialization happens globally
+
+ // initialize winsock
+ WSAData wsaData;
+ int nCode = WSAStartup(MAKEWORD(1, 1), &wsaData);
+ if( nCode != 0 ){
+ //std::cout << "WSAStartup() failed with error code " << nCode << "\n";
+ }else{
+ winsockInitialized_ = true;
+ }
+ }
+}
+
+
+NetworkInitializer::~NetworkInitializer()
+{
+ if( InterlockedDecrement( &initCount_ ) == 0 ){
+ if( winsockInitialized_ ){
+ WSACleanup();
+ winsockInitialized_ = false;
+ }
+ }
+}
+
+
+unsigned long GetHostByName( const char *name )
+{
+ NetworkInitializer networkInitializer;
+
+ unsigned long result = 0;
+
+ struct hostent *h = gethostbyname( name );
+ if( h ){
+ struct in_addr a;
+ memcpy( &a, h->h_addr_list[0], h->h_length );
+ result = ntohl(a.s_addr);
+ }
+
+ return result;
+}
diff -r d609725e568a -r 0284d2152e17 external/oscpack/ip/win32/UdpSocket.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/ip/win32/UdpSocket.cpp Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,521 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "ip/UdpSocket.h"
+
+#include // this must come first to prevent errors with MSVC7
+#include
+#include // for timeGetTime()
+
+#include
+#include
+#include
+#include
+#include
+
+#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");
+ }
+
+ 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();
+ signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+ NetworkInitializer networkInitializer_;
+
+ std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+ std::vector< AttachedTimerListener > timerListeners_;
+
+ volatile bool break_;
+ HANDLE breakEvent_;
+
+ double GetCurrentTimeMs() const
+ {
+ return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
+ }
+
+public:
+ Implementation()
+ {
+ breakEvent_ = CreateEvent( NULL, FALSE, FALSE, NULL );
+ }
+
+ ~Implementation()
+ {
+ CloseHandle( breakEvent_ );
+ }
+
+ void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+ // we don't check that the same socket has been added multiple times, even though this is an error
+ socketListeners_.push_back( std::make_pair( listener, socket ) );
+ }
+
+ void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+ {
+ std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
+ std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+ assert( i != socketListeners_.end() );
+
+ socketListeners_.erase( i );
+ }
+
+ void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+ {
+ timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+ }
+
+ void DetachPeriodicTimerListener( TimerListener *listener )
+ {
+ std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ while( i != timerListeners_.end() ){
+ if( i->listener == listener )
+ break;
+ ++i;
+ }
+
+ assert( i != timerListeners_.end() );
+
+ timerListeners_.erase( i );
+ }
+
+ void Run()
+ {
+ break_ = false;
+
+ // prepare the window events which we use to wake up on incoming data
+ // we use this instead of select() primarily to support the AsyncBreak()
+ // mechanism.
+
+ std::vector events( socketListeners_.size() + 1, 0 );
+ int j=0;
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i, ++j ){
+
+ HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
+ WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
+ events[j] = event;
+ }
+
+
+ events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
+
+
+ // configure the timer queue
+ double currentTimeMs = GetCurrentTimeMs();
+
+ // expiry time ms, listener
+ std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+ for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+ i != timerListeners_.end(); ++i )
+ timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+ const int MAX_BUFFER_SIZE = 4098;
+ char *data = new char[ MAX_BUFFER_SIZE ];
+ IpEndpointName remoteEndpoint;
+
+ while( !break_ ){
+
+ double currentTimeMs = GetCurrentTimeMs();
+
+ DWORD waitTime = INFINITE;
+ if( !timerQueue_.empty() ){
+
+ waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
+ ? timerQueue_.front().first - currentTimeMs
+ : 0 );
+ }
+
+ DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
+ if( break_ )
+ break;
+
+ if( waitResult != WAIT_TIMEOUT ){
+ for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
+ int size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+ if( size > 0 ){
+ socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint );
+ if( break_ )
+ break;
+ }
+ }
+ }
+
+ // execute any expired timers
+ currentTimeMs = GetCurrentTimeMs();
+ bool resort = false;
+ for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+ i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+ i->second.listener->TimerExpired();
+ if( break_ )
+ break;
+
+ i->first += i->second.periodMs;
+ resort = true;
+ }
+ if( resort )
+ std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+ }
+
+ delete [] data;
+
+ // free events
+ j = 0;
+ for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+ i != socketListeners_.end(); ++i, ++j ){
+
+ WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
+ CloseHandle( events[j] );
+ unsigned long enableNonblocking = 0;
+ ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking ); // make the socket blocking again
+ }
+ }
+
+ void Break()
+ {
+ break_ = true;
+ }
+
+ void AsynchronousBreak()
+ {
+ break_ = true;
+ SetEvent( breakEvent_ );
+ }
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+ impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{
+ delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+ impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+ impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+ impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+ impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+ assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+ multiplexerInstanceToAbortWithSigInt_ = this;
+ signal( SIGINT, InterruptSignalHandler );
+ impl_->Run();
+ signal( SIGINT, SIG_DFL );
+ multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+ impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+ impl_->AsynchronousBreak();
+}
+
diff -r d609725e568a -r 0284d2152e17 external/oscpack/liboscpack.1.0.2.dylib
Binary file external/oscpack/liboscpack.1.0.2.dylib has changed
diff -r d609725e568a -r 0284d2152e17 external/oscpack/make.MinGW32.bat
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/make.MinGW32.bat Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,19 @@
+del bin\OscUnitTests.exe
+del bin\OscDump.exe
+del bin\OscSendTests.exe
+del bin\OscReceiveTest.exe
+mkdir bin
+
+g++ tests\OscUnitTests.cpp osc\OscTypes.cpp osc\OscReceivedElements.cpp osc\OscPrintReceivedElements.cpp osc\OscOutboundPacketStream.cpp -Wall -I. -lws2_32 -o bin\OscUnitTests.exe
+
+g++ examples\OscDump.cpp osc\OscTypes.cpp osc\OscReceivedElements.cpp osc\OscPrintReceivedElements.cpp ip\win32\NetworkingUtils.cpp ip\win32\UdpSocket.cpp -Wall -I. -lws2_32 -lwinmm -o bin\OscDump.exe
+
+g++ examples\SimpleSend.cpp osc\OscTypes.cpp osc\OscOutboundPacketStream.cpp ip\win32\NetworkingUtils.cpp ip\win32\UdpSocket.cpp ip\IpEndpointName.cpp -Wall -I. -lws2_32 -lwinmm -o bin\SimpleSend.exe
+
+g++ examples\SimpleReceive.cpp osc\OscTypes.cpp osc\OscReceivedElements.cpp ip\win32\NetworkingUtils.cpp ip\win32\UdpSocket.cpp -Wall -I. -lws2_32 -lwinmm -o bin\SimpleReceive.exe
+
+g++ tests\OscSendTests.cpp osc\OscTypes.cpp osc\OscOutboundPacketStream.cpp ip\win32\NetworkingUtils.cpp ip\win32\UdpSocket.cpp ip\IpEndpointName.cpp -Wall -I. -lws2_32 -lwinmm -o bin\OscSendTests.exe
+
+g++ tests\OscReceiveTest.cpp osc\OscTypes.cpp osc\OscReceivedElements.cpp ip\win32\NetworkingUtils.cpp ip\win32\UdpSocket.cpp -Wall -I. -lws2_32 -lwinmm -o bin\OscReceiveTest.exe
+
+.\bin\OscUnitTests.exe
\ No newline at end of file
diff -r d609725e568a -r 0284d2152e17 external/oscpack/osc/MessageMappingOscPacketListener.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/external/oscpack/osc/MessageMappingOscPacketListener.h Fri Jun 22 12:22:08 2012 +0000
@@ -0,0 +1,73 @@
+/*
+ oscpack -- Open Sound Control packet manipulation library
+ http://www.audiomulch.com/~rossb/oscpack
+
+ Copyright (c) 2004-2005 Ross Bencina
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ requested to send the modifications to the original developer so that
+ they can be incorporated into the canonical version.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
+#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
+
+#include
+#include