]> git.sesse.net Git - casparcg/commitdiff
2.1.0: Merged osc network communication. Now works as monitor-exp.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 10 Feb 2012 23:20:23 +0000 (23:20 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Fri, 10 Feb 2012 23:20:23 +0000 (23:20 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2347 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

21 files changed:
common/spl/memory.h
core/producer/frame_producer.cpp
core/producer/stage.cpp
core/video_channel.cpp
protocol/osc/oscpack/MessageMappingOscPacketListener.h [new file with mode: 0644]
protocol/osc/oscpack/OscException.h [new file with mode: 0644]
protocol/osc/oscpack/OscHostEndianness.h [new file with mode: 0644]
protocol/osc/oscpack/OscOutboundPacketStream.cpp [new file with mode: 0644]
protocol/osc/oscpack/OscOutboundPacketStream.h [new file with mode: 0644]
protocol/osc/oscpack/OscPacketListener.h [new file with mode: 0644]
protocol/osc/oscpack/OscPrintReceivedElements.cpp [new file with mode: 0644]
protocol/osc/oscpack/OscPrintReceivedElements.h [new file with mode: 0644]
protocol/osc/oscpack/OscReceivedElements.cpp [new file with mode: 0644]
protocol/osc/oscpack/OscReceivedElements.h [new file with mode: 0644]
protocol/osc/oscpack/OscTypes.cpp [new file with mode: 0644]
protocol/osc/oscpack/OscTypes.h [new file with mode: 0644]
protocol/osc/server.cpp [new file with mode: 0644]
protocol/osc/server.h [new file with mode: 0644]
protocol/protocol.vcxproj
protocol/protocol.vcxproj.filters
shell/main.cpp

index f03343e1601469af5ab2745d6c678a4099c119f9..c6601cf2f8f04990dc4305bb80c8a3787a7ecf00 100644 (file)
@@ -305,12 +305,12 @@ class enable_shared_from_this : public std::enable_shared_from_this<T>
 public:\r
     shared_ptr<T> shared_from_this() \r
     {\r
-        return shared_ptr<T>(this->shared_from_this());\r
+        return shared_ptr<T>(std::enable_shared_from_this<T>::shared_from_this());\r
     }\r
 \r
     shared_ptr<T const> shared_from_this() const \r
     {\r
-        return shared_ptr<T const>(this->shared_from_this());\r
+        return shared_ptr<T const>(std::enable_shared_from_this<T>::shared_from_this());\r
     }\r
 protected:\r
     enable_shared_from_this()\r
index 82ec06fe9f1f16435d825ad4ecdab90f26187b75..66e865d5f5f700f5763e0e329aa14997d38a92da 100644 (file)
@@ -103,7 +103,6 @@ class follow_producer_proxy : public producer_proxy_base
 public:\r
        follow_producer_proxy(spl::shared_ptr<frame_producer>&& producer) \r
                : producer_proxy_base(std::move(producer))\r
-               , event_subject_(new monitor::subject("asd"))\r
        {\r
                producer->subscribe(event_subject_);\r
        }\r
index 54f06deac10baf44cda436af0296f041378ddf40..83ca9df1da1fd4be44515a2610135dfdc2d66f4a 100644 (file)
@@ -89,7 +89,7 @@ public:
                        }       \r
                        \r
                        graph_->set_value("produce-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
-                       //*event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc.fps);\r
+                       *event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc.fps);\r
 \r
                        return frames;\r
                });\r
index af03254b1fa4ee0fc26310f6d81616a941341e56..2d138058fa9ede2a0c77ee9799e110a14f43e66d 100644 (file)
@@ -123,8 +123,8 @@ public:
                \r
                        graph_->set_value("tick-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
 \r
-                       //*event_subject_ << monitor::event("debug/profiler")  % frame_timer.elapsed() % (1.0/format_desc_.fps);\r
-                       //*event_subject_ << monitor::event("format")           % u8(format_desc.name);\r
+                       *event_subject_ << monitor::event("debug/profiler")  % frame_timer.elapsed() % (1.0/format_desc_.fps);\r
+                       *event_subject_ << monitor::event("format")             % u8(format_desc.name);\r
                }\r
                catch(...)\r
                {\r
diff --git a/protocol/osc/oscpack/MessageMappingOscPacketListener.h b/protocol/osc/oscpack/MessageMappingOscPacketListener.h
new file mode 100644 (file)
index 0000000..017bf05
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H\r
+#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H\r
+\r
+#include <string.h>\r
+#include <map>\r
+\r
+#include "OscPacketListener.h"\r
+\r
+\r
+\r
+namespace osc{\r
+\r
+template< class T >\r
+class MessageMappingOscPacketListener : public OscPacketListener{\r
+public:\r
+    typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&);\r
+\r
+protected:\r
+    void RegisterMessageFunction( const char *addressPattern, function_type f )\r
+    {\r
+        functions_.insert( std::make_pair( addressPattern, f ) );\r
+    }\r
+\r
+    virtual void ProcessMessage( const osc::ReceivedMessage& m,\r
+               const IpEndpointName& remoteEndpoint )\r
+    {\r
+        typename function_map_type::iterator i = functions_.find( m.AddressPattern() );\r
+        if( i != functions_.end() )\r
+            (dynamic_cast<T*>(this)->*(i->second))( m, remoteEndpoint );\r
+    }\r
+    \r
+private:\r
+    struct cstr_compare{\r
+        bool operator()( const char *lhs, const char *rhs ) const\r
+            { return strcmp( lhs, rhs ) < 0; }\r
+    };\r
+\r
+    typedef std::map<const char*, function_type, cstr_compare> function_map_type;\r
+    function_map_type functions_;\r
+};\r
+\r
+} // namespace osc\r
+\r
+#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */
\ No newline at end of file
diff --git a/protocol/osc/oscpack/OscException.h b/protocol/osc/oscpack/OscException.h
new file mode 100644 (file)
index 0000000..cd8d567
--- /dev/null
@@ -0,0 +1,54 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSC_EXCEPTION_H\r
+#define INCLUDED_OSC_EXCEPTION_H\r
+\r
+#include <exception>\r
+\r
+namespace osc{\r
+\r
+class Exception : public std::exception {\r
+    const char *what_;\r
+    \r
+public:\r
+    Exception() throw() {}\r
+    Exception( const Exception& src ) throw()\r
+        : what_( src.what_ ) {}\r
+    Exception( const char *w ) throw()\r
+        : what_( w ) {}\r
+    Exception& operator=( const Exception& src ) throw()\r
+        { what_ = src.what_; return *this; }\r
+    virtual ~Exception() throw() {}\r
+    virtual const char* what() const throw() { return what_; }\r
+};\r
+\r
+} // namespace osc\r
+\r
+#endif /* INCLUDED_OSC_EXCEPTION_H */\r
diff --git a/protocol/osc/oscpack/OscHostEndianness.h b/protocol/osc/oscpack/OscHostEndianness.h
new file mode 100644 (file)
index 0000000..09d115f
--- /dev/null
@@ -0,0 +1,79 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef OSC_HOSTENDIANNESS_H\r
+#define OSC_HOSTENDIANNESS_H\r
+\r
+/*\r
+    Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined\r
+\r
+    If you know a way to enhance the detection below for Linux and/or MacOSX\r
+    please let me know! I've tried a few things which don't work.\r
+*/\r
+\r
+#define OSC_HOST_LITTLE_ENDIAN 1\r
+#undef OSC_HOST_BIG_ENDIAN\r
+\r
+#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)\r
+\r
+// you can define one of the above symbols from the command line\r
+// then you don't have to edit this file.\r
+\r
+#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)\r
+\r
+// assume that __WIN32__ is only defined on little endian systems\r
+\r
+#define OSC_HOST_LITTLE_ENDIAN 1\r
+#undef OSC_HOST_BIG_ENDIAN\r
+\r
+#elif defined(__APPLE__)\r
+\r
+#if defined(__LITTLE_ENDIAN__)\r
+\r
+#define OSC_HOST_LITTLE_ENDIAN 1\r
+#undef OSC_HOST_BIG_ENDIAN\r
+\r
+#elif defined(__BIG_ENDIAN__)\r
+\r
+#define OSC_HOST_BIG_ENDIAN 1\r
+#undef OSC_HOST_LITTLE_ENDIAN\r
+\r
+#endif\r
+\r
+#endif\r
+\r
+#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)\r
+\r
+#error please edit OSCHostEndianness.h to configure endianness\r
+\r
+#endif\r
+\r
+\r
+#endif /* OSC_HOSTENDIANNESS_H */\r
+\r
diff --git a/protocol/osc/oscpack/OscOutboundPacketStream.cpp b/protocol/osc/oscpack/OscOutboundPacketStream.cpp
new file mode 100644 (file)
index 0000000..92cc3f3
--- /dev/null
@@ -0,0 +1,642 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#undef _CRT_SECURE_NO_WARNINGS\r
+#define _CRT_SECURE_NO_WARNINGS\r
+\r
+#include "OscOutboundPacketStream.h"\r
+\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <assert.h>\r
+\r
+#if defined(__WIN32__) || defined(WIN32)\r
+#include <malloc.h> // for alloca\r
+#endif\r
+\r
+#include "OscHostEndianness.h"\r
+\r
+\r
+namespace osc{\r
+\r
+static void FromInt32( char *p, int32 x )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::int32 i;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.i = x;\r
+\r
+    p[3] = u.c[0];\r
+    p[2] = u.c[1];\r
+    p[1] = u.c[2];\r
+    p[0] = u.c[3];\r
+#else\r
+    *reinterpret_cast<int32*>(p) = x;\r
+#endif\r
+}\r
+\r
+\r
+static void FromUInt32( char *p, uint32 x )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::uint32 i;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.i = x;\r
+\r
+    p[3] = u.c[0];\r
+    p[2] = u.c[1];\r
+    p[1] = u.c[2];\r
+    p[0] = u.c[3];\r
+#else\r
+    *reinterpret_cast<uint32*>(p) = x;\r
+#endif\r
+}\r
+\r
+\r
+static void FromInt64( char *p, int64 x )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::int64 i;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.i = x;\r
+\r
+    p[7] = u.c[0];\r
+    p[6] = u.c[1];\r
+    p[5] = u.c[2];\r
+    p[4] = u.c[3];\r
+    p[3] = u.c[4];\r
+    p[2] = u.c[5];\r
+    p[1] = u.c[6];\r
+    p[0] = u.c[7];\r
+#else\r
+    *reinterpret_cast<int64*>(p) = x;\r
+#endif\r
+}\r
+\r
+\r
+static void FromUInt64( char *p, uint64 x )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::uint64 i;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.i = x;\r
+\r
+    p[7] = u.c[0];\r
+    p[6] = u.c[1];\r
+    p[5] = u.c[2];\r
+    p[4] = u.c[3];\r
+    p[3] = u.c[4];\r
+    p[2] = u.c[5];\r
+    p[1] = u.c[6];\r
+    p[0] = u.c[7];\r
+#else\r
+    *reinterpret_cast<uint64*>(p) = x;\r
+#endif\r
+}\r
+\r
+\r
+static inline long RoundUp4( long x )\r
+{\r
+    return ((x-1) & (~0x03L)) + 4;\r
+}\r
+\r
+\r
+OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity )\r
+    : data_( buffer )\r
+    , end_( data_ + capacity )\r
+    , typeTagsCurrent_( end_ )\r
+    , messageCursor_( data_ )\r
+    , argumentCurrent_( data_ )\r
+    , elementSizePtr_( 0 )\r
+    , messageIsInProgress_( false )\r
+{\r
+\r
+}\r
+\r
+\r
+OutboundPacketStream::~OutboundPacketStream()\r
+{\r
+\r
+}\r
+\r
+\r
+char *OutboundPacketStream::BeginElement( char *beginPtr )\r
+{\r
+    if( elementSizePtr_ == 0 ){\r
+\r
+        elementSizePtr_ = reinterpret_cast<uint32*>(data_);\r
+\r
+        return beginPtr;\r
+\r
+    }else{\r
+        // store an offset to the old element size ptr in the element size slot\r
+        // we store an offset rather than the actual pointer to be 64 bit clean.\r
+        *reinterpret_cast<uint32*>(beginPtr) =\r
+                (uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_);\r
+\r
+        elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr);\r
+\r
+        return beginPtr + 4;\r
+    }\r
+}\r
+\r
+\r
+void OutboundPacketStream::EndElement( char *endPtr )\r
+{\r
+    assert( elementSizePtr_ != 0 );\r
+\r
+    if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){\r
+\r
+        elementSizePtr_ = 0;\r
+\r
+    }else{\r
+        // while building an element, an offset to the containing element's\r
+        // size slot is stored in the elements size slot (or a ptr to data_\r
+        // if there is no containing element). We retrieve that here\r
+        uint32 *previousElementSizePtr =\r
+                (uint32*)(data_ + *reinterpret_cast<uint32*>(elementSizePtr_));\r
+\r
+        // then we store the element size in the slot, note that the element\r
+        // size does not include the size slot, hence the - 4 below.\r
+        uint32 elementSize =\r
+                static_cast<uint32>(endPtr - reinterpret_cast<char*>(elementSizePtr_)) - 4;\r
+        FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );\r
+\r
+        // finally, we reset the element size ptr to the containing element\r
+        elementSizePtr_ = previousElementSizePtr;\r
+    }\r
+}\r
+\r
+\r
+bool OutboundPacketStream::ElementSizeSlotRequired() const\r
+{\r
+    return (elementSizePtr_ != 0);\r
+}\r
+\r
+\r
+void OutboundPacketStream::CheckForAvailableBundleSpace()\r
+{\r
+    unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;\r
+\r
+    if( required > Capacity() )\r
+        throw OutOfBufferMemoryException();\r
+}\r
+\r
+\r
+void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )\r
+{\r
+    // plus 4 for at least four bytes of type tag\r
+     unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0)\r
+            + RoundUp4(static_cast<unsigned long>(strlen(addressPattern)) + 1) + 4;\r
+\r
+    if( required > Capacity() )\r
+        throw OutOfBufferMemoryException();\r
+}\r
+\r
+\r
+void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength )\r
+{\r
+    // plus three for extra type tag, comma and null terminator\r
+     unsigned long required = static_cast<unsigned long>(argumentCurrent_ - data_) + argumentLength\r
+            + RoundUp4( static_cast<unsigned long>(end_ - typeTagsCurrent_) + 3 );\r
+\r
+    if( required > Capacity() )\r
+        throw OutOfBufferMemoryException();\r
+}\r
+\r
+\r
+void OutboundPacketStream::Clear()\r
+{\r
+    typeTagsCurrent_ = end_;\r
+    messageCursor_ = data_;\r
+    argumentCurrent_ = data_;\r
+    elementSizePtr_ = 0;\r
+    messageIsInProgress_ = false;\r
+}\r
+\r
+\r
+unsigned int OutboundPacketStream::Capacity() const\r
+{\r
+    return static_cast<int>(end_ - data_);\r
+}\r
+\r
+\r
+unsigned int OutboundPacketStream::Size() const\r
+{\r
+    unsigned int result = static_cast<unsigned long>(argumentCurrent_ - data_);\r
+    if( IsMessageInProgress() ){\r
+        // account for the length of the type tag string. the total type tag\r
+        // includes an initial comma, plus at least one terminating \0\r
+        result += RoundUp4( static_cast<unsigned long>(end_ - typeTagsCurrent_) + 2 );\r
+    }\r
+\r
+    return result;\r
+}\r
+\r
+\r
+const char *OutboundPacketStream::Data() const\r
+{\r
+    return data_;\r
+}\r
+\r
+\r
+bool OutboundPacketStream::IsReady() const\r
+{\r
+    return (!IsMessageInProgress() && !IsBundleInProgress());\r
+}\r
+\r
+\r
+bool OutboundPacketStream::IsMessageInProgress() const\r
+{\r
+    return messageIsInProgress_;\r
+}\r
+\r
+\r
+bool OutboundPacketStream::IsBundleInProgress() const\r
+{\r
+    return (elementSizePtr_ != 0);\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )\r
+{\r
+    if( IsMessageInProgress() )\r
+        throw MessageInProgressException();\r
+\r
+    CheckForAvailableBundleSpace();\r
+\r
+    messageCursor_ = BeginElement( messageCursor_ );\r
+\r
+    memcpy( messageCursor_, "#bundle\0", 8 );\r
+    FromUInt64( messageCursor_ + 8, rhs.timeTag );\r
+\r
+    messageCursor_ += 16;\r
+    argumentCurrent_ = messageCursor_;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )\r
+{\r
+    (void) rhs;\r
+\r
+    if( !IsBundleInProgress() )\r
+        throw BundleNotInProgressException();\r
+    if( IsMessageInProgress() )\r
+        throw MessageInProgressException();\r
+\r
+    EndElement( messageCursor_ );\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )\r
+{\r
+    if( IsMessageInProgress() )\r
+        throw MessageInProgressException();\r
+\r
+    CheckForAvailableMessageSpace( rhs.addressPattern );\r
+\r
+    messageCursor_ = BeginElement( messageCursor_ );\r
+\r
+    strcpy( messageCursor_, rhs.addressPattern );\r
+    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs.addressPattern));\r
+    messageCursor_ += rhsLength + 1;\r
+\r
+    // zero pad to 4-byte boundary\r
+    unsigned long i = rhsLength + 1;\r
+    while( i & 0x3 ){\r
+        *messageCursor_++ = '\0';\r
+        ++i;\r
+    }\r
+\r
+    argumentCurrent_ = messageCursor_;\r
+    typeTagsCurrent_ = end_;\r
+\r
+    messageIsInProgress_ = true;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )\r
+{\r
+    (void) rhs;\r
+\r
+    if( !IsMessageInProgress() )\r
+        throw MessageNotInProgressException();\r
+\r
+    int typeTagsCount = static_cast<int>(end_ - typeTagsCurrent_);\r
+\r
+    if( typeTagsCount ){\r
+\r
+        char *tempTypeTags = (char*)alloca(typeTagsCount);\r
+        memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );\r
+\r
+        // slot size includes comma and null terminator\r
+        int typeTagSlotSize = RoundUp4( typeTagsCount + 2 );\r
+\r
+        uint32 argumentsSize = static_cast<uint32>(argumentCurrent_ - messageCursor_);\r
+\r
+        memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );\r
+\r
+        messageCursor_[0] = ',';\r
+        // copy type tags in reverse (really forward) order\r
+        for( int i=0; i < typeTagsCount; ++i )\r
+            messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];\r
+\r
+        char *p = messageCursor_ + 1 + typeTagsCount;\r
+        for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )\r
+            *p++ = '\0';\r
+\r
+        typeTagsCurrent_ = end_;\r
+\r
+        // advance messageCursor_ for next message\r
+        messageCursor_ += typeTagSlotSize + argumentsSize;\r
+\r
+    }else{\r
+        // send an empty type tags string\r
+        memcpy( messageCursor_, ",\0\0\0", 4 );\r
+\r
+        // advance messageCursor_ for next message\r
+        messageCursor_ += 4;\r
+    }\r
+\r
+    argumentCurrent_ = messageCursor_;\r
+\r
+    EndElement( messageCursor_ );\r
+\r
+    messageIsInProgress_ = false;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(0);\r
+\r
+    *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )\r
+{\r
+    (void) rhs;\r
+    CheckForAvailableArgumentSpace(0);\r
+\r
+    *(--typeTagsCurrent_) = NIL_TYPE_TAG;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )\r
+{\r
+    (void) rhs;\r
+    CheckForAvailableArgumentSpace(0);\r
+\r
+    *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(4);\r
+\r
+    *(--typeTagsCurrent_) = INT32_TYPE_TAG;\r
+    FromInt32( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 4;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(4);\r
+\r
+    *(--typeTagsCurrent_) = FLOAT_TYPE_TAG;\r
+\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        float f;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.f = rhs;\r
+\r
+    argumentCurrent_[3] = u.c[0];\r
+    argumentCurrent_[2] = u.c[1];\r
+    argumentCurrent_[1] = u.c[2];\r
+    argumentCurrent_[0] = u.c[3];\r
+#else\r
+    *reinterpret_cast<float*>(argumentCurrent_) = rhs;\r
+#endif\r
+\r
+    argumentCurrent_ += 4;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(4);\r
+\r
+    *(--typeTagsCurrent_) = CHAR_TYPE_TAG;\r
+    FromInt32( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 4;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(4);\r
+\r
+    *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;\r
+    FromUInt32( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 4;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(4);\r
+\r
+    *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;\r
+    FromUInt32( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 4;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(8);\r
+\r
+    *(--typeTagsCurrent_) = INT64_TYPE_TAG;\r
+    FromInt64( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 8;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(8);\r
+\r
+    *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;\r
+    FromUInt64( argumentCurrent_, rhs );\r
+    argumentCurrent_ += 8;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )\r
+{\r
+    CheckForAvailableArgumentSpace(8);\r
+\r
+    *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;\r
+\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        double f;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.f = rhs;\r
+\r
+    argumentCurrent_[7] = u.c[0];\r
+    argumentCurrent_[6] = u.c[1];\r
+    argumentCurrent_[5] = u.c[2];\r
+    argumentCurrent_[4] = u.c[3];\r
+    argumentCurrent_[3] = u.c[4];\r
+    argumentCurrent_[2] = u.c[5];\r
+    argumentCurrent_[1] = u.c[6];\r
+    argumentCurrent_[0] = u.c[7];\r
+#else\r
+    *reinterpret_cast<double*>(argumentCurrent_) = rhs;\r
+#endif\r
+\r
+    argumentCurrent_ += 8;\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )\r
+{\r
+    CheckForAvailableArgumentSpace( RoundUp4(static_cast<long>(strlen(rhs)) + 1) );\r
+\r
+    *(--typeTagsCurrent_) = STRING_TYPE_TAG;\r
+    strcpy( argumentCurrent_, rhs );\r
+    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs));\r
+    argumentCurrent_ += rhsLength + 1;\r
+\r
+    // zero pad to 4-byte boundary\r
+    unsigned long i = rhsLength + 1;\r
+    while( i & 0x3 ){\r
+        *argumentCurrent_++ = '\0';\r
+        ++i;\r
+    }\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )\r
+{\r
+    CheckForAvailableArgumentSpace( RoundUp4(static_cast<long>(strlen(rhs)) + 1) );\r
+\r
+    *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;\r
+    strcpy( argumentCurrent_, rhs );\r
+    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs));\r
+    argumentCurrent_ += rhsLength + 1;\r
+\r
+    // zero pad to 4-byte boundary\r
+    unsigned long i = rhsLength + 1;\r
+    while( i & 0x3 ){\r
+        *argumentCurrent_++ = '\0';\r
+        ++i;\r
+    }\r
+\r
+    return *this;\r
+}\r
+\r
+\r
+OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )\r
+{\r
+    CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );\r
+\r
+    *(--typeTagsCurrent_) = BLOB_TYPE_TAG;\r
+    FromUInt32( argumentCurrent_, rhs.size );\r
+    argumentCurrent_ += 4;\r
+    \r
+    memcpy( argumentCurrent_, rhs.data, rhs.size );\r
+    argumentCurrent_ += rhs.size;\r
+\r
+    // zero pad to 4-byte boundary\r
+    unsigned long i = rhs.size;\r
+    while( i & 0x3 ){\r
+        *argumentCurrent_++ = '\0';\r
+        ++i;\r
+    }\r
+\r
+    return *this;\r
+}\r
+\r
+} // namespace osc\r
+\r
+\r
diff --git a/protocol/osc/oscpack/OscOutboundPacketStream.h b/protocol/osc/oscpack/OscOutboundPacketStream.h
new file mode 100644 (file)
index 0000000..a542445
--- /dev/null
@@ -0,0 +1,142 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSCOUTBOUNDPACKET_H\r
+#define INCLUDED_OSCOUTBOUNDPACKET_H\r
+\r
+#include "OscTypes.h"\r
+#include "OscException.h"\r
+\r
+\r
+namespace osc{\r
+\r
+class OutOfBufferMemoryException : public Exception{\r
+public:\r
+    OutOfBufferMemoryException( const char *w="out of buffer memory" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class BundleNotInProgressException : public Exception{\r
+public:\r
+    BundleNotInProgressException(\r
+            const char *w="call to EndBundle when bundle is not in progress" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class MessageInProgressException : public Exception{\r
+public:\r
+    MessageInProgressException(\r
+            const char *w="opening or closing bundle or message while message is in progress" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class MessageNotInProgressException : public Exception{\r
+public:\r
+    MessageNotInProgressException(\r
+            const char *w="call to EndMessage when message is not in progress" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+\r
+class OutboundPacketStream{\r
+public:\r
+       OutboundPacketStream( char *buffer, unsigned long capacity );\r
+       ~OutboundPacketStream();\r
+\r
+    void Clear();\r
+\r
+    unsigned int Capacity() const;\r
+\r
+    // invariant: size() is valid even while building a message.\r
+    unsigned int Size() const;\r
+\r
+    const char *Data() const;\r
+\r
+    // indicates that all messages have been closed with a matching EndMessage\r
+    // and all bundles have been closed with a matching EndBundle\r
+    bool IsReady() const;\r
+\r
+    bool IsMessageInProgress() const;\r
+    bool IsBundleInProgress() const;\r
+\r
+    OutboundPacketStream& operator<<( const BundleInitiator& rhs );\r
+    OutboundPacketStream& operator<<( const BundleTerminator& rhs );\r
+    \r
+    OutboundPacketStream& operator<<( const BeginMessage& rhs );\r
+    OutboundPacketStream& operator<<( const MessageTerminator& rhs );\r
+\r
+    OutboundPacketStream& operator<<( bool rhs );\r
+    OutboundPacketStream& operator<<( const NilType& rhs );\r
+    OutboundPacketStream& operator<<( const InfinitumType& rhs );\r
+    OutboundPacketStream& operator<<( int32 rhs );\r
+\r
+//#ifndef __x86_64__\r
+//    OutboundPacketStream& operator<<( int rhs )\r
+//            { *this << (int32)rhs; return *this; }\r
+//#endif\r
+\r
+    OutboundPacketStream& operator<<( float rhs );\r
+    OutboundPacketStream& operator<<( char rhs );\r
+    OutboundPacketStream& operator<<( const RgbaColor& rhs );\r
+    OutboundPacketStream& operator<<( const MidiMessage& rhs );\r
+    OutboundPacketStream& operator<<( int64 rhs );\r
+    OutboundPacketStream& operator<<( const TimeTag& rhs );\r
+    OutboundPacketStream& operator<<( double rhs );\r
+    OutboundPacketStream& operator<<( const char* rhs );\r
+    OutboundPacketStream& operator<<( const Symbol& rhs );\r
+    OutboundPacketStream& operator<<( const Blob& rhs );\r
+\r
+private:\r
+\r
+    char *BeginElement( char *beginPtr );\r
+    void EndElement( char *endPtr );\r
+\r
+    bool ElementSizeSlotRequired() const;\r
+    void CheckForAvailableBundleSpace();\r
+    void CheckForAvailableMessageSpace( const char *addressPattern );\r
+    void CheckForAvailableArgumentSpace( long argumentLength );\r
+\r
+    char *data_;\r
+    char *end_;\r
+\r
+    char *typeTagsCurrent_; // stored in reverse order\r
+    char *messageCursor_;\r
+    char *argumentCurrent_;\r
+\r
+    // elementSizePtr_ has two special values: 0 indicates that a bundle\r
+    // isn't open, and elementSizePtr_==data_ indicates that a bundle is\r
+    // open but that it doesn't have a size slot (ie the outermost bundle)\r
+    uint32 *elementSizePtr_;\r
+\r
+    bool messageIsInProgress_;\r
+};\r
+\r
+} // namespace osc\r
+\r
+#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */\r
diff --git a/protocol/osc/oscpack/OscPacketListener.h b/protocol/osc/oscpack/OscPacketListener.h
new file mode 100644 (file)
index 0000000..bc322b7
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSCPACKETLISTENER_H\r
+#define INCLUDED_OSCPACKETLISTENER_H\r
+\r
+#include "OscReceivedElements.h"\r
+#include "../ip/PacketListener.h"\r
+\r
+\r
+namespace osc{\r
+\r
+class OscPacketListener : public PacketListener{ \r
+protected:\r
+    virtual void ProcessBundle( const osc::ReceivedBundle& b, \r
+                               const IpEndpointName& remoteEndpoint )\r
+    {\r
+        // ignore bundle time tag for now\r
+\r
+        for( ReceivedBundle::const_iterator i = b.ElementsBegin(); \r
+                               i != b.ElementsEnd(); ++i ){\r
+            if( i->IsBundle() )\r
+                ProcessBundle( ReceivedBundle(*i), remoteEndpoint );\r
+            else\r
+                ProcessMessage( ReceivedMessage(*i), remoteEndpoint );\r
+        }\r
+    }\r
+\r
+    virtual void ProcessMessage( const osc::ReceivedMessage& m, \r
+                               const IpEndpointName& remoteEndpoint ) = 0;\r
+    \r
+public:\r
+       virtual void ProcessPacket( const char *data, int size, \r
+                       const IpEndpointName& remoteEndpoint )\r
+    {\r
+        osc::ReceivedPacket p( data, size );\r
+        if( p.IsBundle() )\r
+            ProcessBundle( ReceivedBundle(p), remoteEndpoint );\r
+        else\r
+            ProcessMessage( ReceivedMessage(p), remoteEndpoint );\r
+    }\r
+};\r
+\r
+} // namespace osc\r
+\r
+#endif /* INCLUDED_OSCPACKETLISTENER_H */\r
diff --git a/protocol/osc/oscpack/OscPrintReceivedElements.cpp b/protocol/osc/oscpack/OscPrintReceivedElements.cpp
new file mode 100644 (file)
index 0000000..ea7b662
--- /dev/null
@@ -0,0 +1,247 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#undef _CRT_SECURE_NO_WARNINGS\r
+#define _CRT_SECURE_NO_WARNINGS\r
+\r
+#include "OscPrintReceivedElements.h"\r
+\r
+#include <iostream>\r
+#include <iomanip>\r
+#include <ctime>\r
+#include <cstring>\r
+\r
+\r
+namespace osc{\r
+\r
+\r
+std::ostream& operator<<( std::ostream & os,\r
+        const ReceivedMessageArgument& arg )\r
+{\r
+    switch( arg.TypeTag() ){\r
+        case TRUE_TYPE_TAG:\r
+            os << "bool:true";\r
+            break;\r
+                \r
+        case FALSE_TYPE_TAG:\r
+            os << "bool:false";\r
+            break;\r
+\r
+        case NIL_TYPE_TAG:\r
+            os << "(Nil)";\r
+            break;\r
+\r
+        case INFINITUM_TYPE_TAG:\r
+            os << "(Infinitum)";\r
+            break;\r
+\r
+        case INT32_TYPE_TAG:\r
+            os << "int32:" << arg.AsInt32Unchecked();\r
+            break;\r
+\r
+        case FLOAT_TYPE_TAG:\r
+            os << "float32:" << arg.AsFloatUnchecked();\r
+            break;\r
+\r
+        case CHAR_TYPE_TAG:\r
+            {\r
+                char s[2] = {0};\r
+                s[0] = arg.AsCharUnchecked();\r
+                os << "char:'" << s << "'";\r
+            }\r
+            break;\r
+\r
+        case RGBA_COLOR_TYPE_TAG:\r
+            {\r
+                uint32 color = arg.AsRgbaColorUnchecked();\r
+                \r
+                os << "RGBA:0x"\r
+                        << std::hex << std::setfill('0')\r
+                        << std::setw(2) << (int)((color>>24) & 0xFF)\r
+                        << std::setw(2) << (int)((color>>16) & 0xFF)\r
+                        << std::setw(2) << (int)((color>>8) & 0xFF)\r
+                        << std::setw(2) << (int)(color & 0xFF)\r
+                        << std::setfill(' ');\r
+                os.unsetf(std::ios::basefield);\r
+            }\r
+            break;\r
+\r
+        case MIDI_MESSAGE_TYPE_TAG:\r
+            {\r
+                uint32 m = arg.AsMidiMessageUnchecked();\r
+                os << "midi (port, status, data1, data2):<<"\r
+                        << std::hex << std::setfill('0')\r
+                        << "0x" << std::setw(2) << (int)((m>>24) & 0xFF)\r
+                        << " 0x" << std::setw(2) << (int)((m>>16) & 0xFF)\r
+                        << " 0x" << std::setw(2) << (int)((m>>8) & 0xFF)\r
+                        << " 0x" << std::setw(2) << (int)(m & 0xFF)\r
+                        << std::setfill(' ') << ">>";\r
+                os.unsetf(std::ios::basefield);\r
+            }\r
+            break;\r
+                               \r
+        case INT64_TYPE_TAG:\r
+            os << "int64:" << arg.AsInt64Unchecked();\r
+            break;\r
+\r
+        case TIME_TAG_TYPE_TAG:\r
+            {\r
+                os << "OSC-timetag:" << arg.AsTimeTagUnchecked();\r
+\r
+                std::time_t t =\r
+                        (unsigned long)( arg.AsTimeTagUnchecked() >> 32 );\r
+\r
+                // strip trailing newline from string returned by ctime\r
+                const char *timeString = std::ctime( &t );\r
+                size_t len = strlen( timeString );\r
+                char *s = new char[ len + 1 ];\r
+                strcpy( s, timeString );\r
+                if( len )\r
+                    s[ len - 1 ] = '\0';\r
+                    \r
+                os << " " << s;\r
+            }\r
+            break;\r
+                \r
+        case DOUBLE_TYPE_TAG:\r
+            os << "double:" << arg.AsDoubleUnchecked();\r
+            break;\r
+\r
+        case STRING_TYPE_TAG:\r
+            os << "OSC-string:`" << arg.AsStringUnchecked() << "'";\r
+            break;\r
+                \r
+        case SYMBOL_TYPE_TAG: \r
+            os << "OSC-string (symbol):`" << arg.AsSymbolUnchecked() << "'";\r
+            break;\r
+\r
+        case BLOB_TYPE_TAG:\r
+            {\r
+                unsigned long size;\r
+                const void *data;\r
+                arg.AsBlobUnchecked( data, size );\r
+                os << "OSC-blob:<<" << std::hex << std::setfill('0');\r
+                unsigned char *p = (unsigned char*)data;\r
+                for( unsigned long i = 0; i < size; ++i ){\r
+                    os << "0x" << std::setw(2) << int(p[i]);\r
+                    if( i != size-1 )\r
+                        os << ' ';\r
+                }\r
+                os.unsetf(std::ios::basefield);\r
+                os << ">>" << std::setfill(' ');\r
+            }\r
+            break;\r
+\r
+        default:\r
+            os << "unknown";\r
+    }\r
+\r
+    return os;\r
+}\r
+\r
+\r
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )\r
+{\r
+    os << "[";\r
+    if( m.AddressPatternIsUInt32() )\r
+        os << m.AddressPatternAsUInt32();\r
+    else\r
+        os << m.AddressPattern();\r
+    \r
+    bool first = true;\r
+    for( ReceivedMessage::const_iterator i = m.ArgumentsBegin();\r
+            i != m.ArgumentsEnd(); ++i ){\r
+        if( first ){\r
+            os << " ";\r
+            first = false;\r
+        }else{\r
+            os << ", ";\r
+        }\r
+\r
+        os << *i;\r
+    }\r
+\r
+    os << "]";\r
+\r
+    return os;\r
+}\r
+\r
+\r
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b )\r
+{\r
+    static int indent = 0;\r
+\r
+    for( int j=0; j < indent; ++j )\r
+        os << "  ";\r
+    os << "{ ( ";\r
+    if( b.TimeTag() == 1 )\r
+        os << "immediate";\r
+    else\r
+        os << b.TimeTag();\r
+    os << " )\n";\r
+\r
+    ++indent;\r
+    \r
+    for( ReceivedBundle::const_iterator i = b.ElementsBegin();\r
+            i != b.ElementsEnd(); ++i ){\r
+        if( i->IsBundle() ){\r
+            ReceivedBundle b(*i);\r
+            os << b << "\n";\r
+        }else{\r
+            ReceivedMessage m(*i);\r
+            for( int j=0; j < indent; ++j )\r
+                os << "  ";\r
+            os << m << "\n";\r
+        }\r
+    }\r
+\r
+    --indent;\r
+\r
+    for( int j=0; j < indent; ++j )\r
+        os << "  ";\r
+    os << "}";\r
+\r
+    return os;\r
+}\r
+\r
+\r
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p )\r
+{\r
+    if( p.IsBundle() ){\r
+        ReceivedBundle b(p);\r
+        os << b << "\n";\r
+    }else{\r
+        ReceivedMessage m(p);\r
+        os << m << "\n";\r
+    }\r
+\r
+    return os;\r
+}\r
+\r
+} // namespace osc\r
diff --git a/protocol/osc/oscpack/OscPrintReceivedElements.h b/protocol/osc/oscpack/OscPrintReceivedElements.h
new file mode 100644 (file)
index 0000000..c42cfa5
--- /dev/null
@@ -0,0 +1,49 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSCPRINTRECEIVEDELEMENTS_H\r
+#define INCLUDED_OSCPRINTRECEIVEDELEMENTS_H\r
+\r
+#include <iosfwd>\r
+\r
+#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H\r
+#include "OscReceivedElements.h"\r
+#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */\r
+\r
+\r
+namespace osc{\r
+\r
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p );\r
+std::ostream& operator<<( std::ostream & os, const ReceivedMessageArgument& arg );\r
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m );\r
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b );\r
+\r
+} // namespace osc\r
+\r
+#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */\r
diff --git a/protocol/osc/oscpack/OscReceivedElements.cpp b/protocol/osc/oscpack/OscReceivedElements.cpp
new file mode 100644 (file)
index 0000000..9554cc4
--- /dev/null
@@ -0,0 +1,725 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#undef _CRT_SECURE_NO_WARNINGS\r
+#define _CRT_SECURE_NO_WARNINGS\r
+\r
+#include "OscReceivedElements.h"\r
+\r
+#include <cassert>\r
+\r
+#include "OscHostEndianness.h"\r
+\r
+\r
+namespace osc{\r
+\r
+\r
+// return the first 4 byte boundary after the end of a str4\r
+// be careful about calling this version if you don't know whether\r
+// the string is terminated correctly.\r
+static inline const char* FindStr4End( const char *p )\r
+{\r
+       if( p[0] == '\0' )    // special case for SuperCollider integer address pattern\r
+               return p + 4;\r
+\r
+    p += 3;\r
+\r
+    while( *p )\r
+        p += 4;\r
+\r
+    return p + 1;\r
+}\r
+\r
+\r
+// return the first 4 byte boundary after the end of a str4\r
+// returns 0 if p == end or if the string is unterminated\r
+static inline const char* FindStr4End( const char *p, const char *end )\r
+{\r
+    if( p >= end )\r
+        return 0;\r
+\r
+       if( p[0] == '\0' )    // special case for SuperCollider integer address pattern\r
+               return p + 4;\r
+\r
+    p += 3;\r
+    end -= 1;\r
+\r
+    while( p < end && *p )\r
+        p += 4;\r
+\r
+    if( *p )\r
+        return 0;\r
+    else\r
+        return p + 1;\r
+}\r
+\r
+\r
+static inline unsigned long RoundUp4( unsigned long x )\r
+{\r
+    unsigned long remainder = x & 0x3UL;\r
+    if( remainder )\r
+        return x + (4 - remainder);\r
+    else\r
+        return x;\r
+}\r
+\r
+\r
+static inline int32 ToInt32( const char *p )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::int32 i;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.c[0] = p[3];\r
+    u.c[1] = p[2];\r
+    u.c[2] = p[1];\r
+    u.c[3] = p[0];\r
+\r
+    return u.i;\r
+#else\r
+       return *(int32*)p;\r
+#endif\r
+}\r
+\r
+\r
+static inline uint32 ToUInt32( const char *p )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::uint32 i;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.c[0] = p[3];\r
+    u.c[1] = p[2];\r
+    u.c[2] = p[1];\r
+    u.c[3] = p[0];\r
+\r
+    return u.i;\r
+#else\r
+       return *(uint32*)p;\r
+#endif\r
+}\r
+\r
+\r
+int64 ToInt64( const char *p )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::int64 i;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.c[0] = p[7];\r
+    u.c[1] = p[6];\r
+    u.c[2] = p[5];\r
+    u.c[3] = p[4];\r
+    u.c[4] = p[3];\r
+    u.c[5] = p[2];\r
+    u.c[6] = p[1];\r
+    u.c[7] = p[0];\r
+\r
+    return u.i;\r
+#else\r
+       return *(int64*)p;\r
+#endif\r
+}\r
+\r
+\r
+uint64 ToUInt64( const char *p )\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::uint64 i;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.c[0] = p[7];\r
+    u.c[1] = p[6];\r
+    u.c[2] = p[5];\r
+    u.c[3] = p[4];\r
+    u.c[4] = p[3];\r
+    u.c[5] = p[2];\r
+    u.c[6] = p[1];\r
+    u.c[7] = p[0];\r
+\r
+    return u.i;\r
+#else\r
+       return *(uint64*)p;\r
+#endif\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+bool ReceivedPacket::IsBundle() const\r
+{\r
+    return (Size() > 0 && Contents()[0] == '#');\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+bool ReceivedBundleElement::IsBundle() const\r
+{\r
+    return (Size() > 0 && Contents()[0] == '#');\r
+}\r
+\r
+\r
+int32 ReceivedBundleElement::Size() const\r
+{\r
+    return ToUInt32( size_ );\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+bool ReceivedMessageArgument::AsBool() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == TRUE_TYPE_TAG )\r
+               return true;\r
+       else if( *typeTag_ == FALSE_TYPE_TAG )\r
+               return false;\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+bool ReceivedMessageArgument::AsBoolUnchecked() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == TRUE_TYPE_TAG )\r
+               return true;\r
+    else\r
+           return false;\r
+}\r
+\r
+\r
+int32 ReceivedMessageArgument::AsInt32() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == INT32_TYPE_TAG )\r
+               return AsInt32Unchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+int32 ReceivedMessageArgument::AsInt32Unchecked() const\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        osc::int32 i;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.c[0] = argument_[3];\r
+    u.c[1] = argument_[2];\r
+    u.c[2] = argument_[1];\r
+    u.c[3] = argument_[0];\r
+\r
+    return u.i;\r
+#else\r
+       return *(int32*)argument_;\r
+#endif\r
+}\r
+\r
+\r
+float ReceivedMessageArgument::AsFloat() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == FLOAT_TYPE_TAG )\r
+               return AsFloatUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+float ReceivedMessageArgument::AsFloatUnchecked() const\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        float f;\r
+        char c[4];\r
+    } u;\r
+\r
+    u.c[0] = argument_[3];\r
+    u.c[1] = argument_[2];\r
+    u.c[2] = argument_[1];\r
+    u.c[3] = argument_[0];\r
+\r
+    return u.f;\r
+#else\r
+       return *(float*)argument_;\r
+#endif\r
+}\r
+\r
+\r
+char ReceivedMessageArgument::AsChar() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == CHAR_TYPE_TAG )\r
+               return AsCharUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+char ReceivedMessageArgument::AsCharUnchecked() const\r
+{\r
+    return (char)ToInt32( argument_ );\r
+}\r
+\r
+\r
+uint32 ReceivedMessageArgument::AsRgbaColor() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == RGBA_COLOR_TYPE_TAG )\r
+               return AsRgbaColorUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const\r
+{\r
+       return ToUInt32( argument_ );\r
+}\r
+\r
+\r
+uint32 ReceivedMessageArgument::AsMidiMessage() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG )\r
+               return AsMidiMessageUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const\r
+{\r
+       return ToUInt32( argument_ );\r
+}\r
+\r
+\r
+int64 ReceivedMessageArgument::AsInt64() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == INT64_TYPE_TAG )\r
+               return AsInt64Unchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+int64 ReceivedMessageArgument::AsInt64Unchecked() const\r
+{\r
+    return ToInt64( argument_ );\r
+}\r
+\r
+\r
+uint64 ReceivedMessageArgument::AsTimeTag() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == TIME_TAG_TYPE_TAG )\r
+               return AsTimeTagUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const\r
+{\r
+    return ToUInt64( argument_ );\r
+}\r
+\r
+\r
+double ReceivedMessageArgument::AsDouble() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == DOUBLE_TYPE_TAG )\r
+               return AsDoubleUnchecked();\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+double ReceivedMessageArgument::AsDoubleUnchecked() const\r
+{\r
+#ifdef OSC_HOST_LITTLE_ENDIAN\r
+    union{\r
+        double d;\r
+        char c[8];\r
+    } u;\r
+\r
+    u.c[0] = argument_[7];\r
+    u.c[1] = argument_[6];\r
+    u.c[2] = argument_[5];\r
+    u.c[3] = argument_[4];\r
+    u.c[4] = argument_[3];\r
+    u.c[5] = argument_[2];\r
+    u.c[6] = argument_[1];\r
+    u.c[7] = argument_[0];\r
+\r
+    return u.d;\r
+#else\r
+       return *(double*)argument_;\r
+#endif\r
+}\r
+\r
+\r
+const char* ReceivedMessageArgument::AsString() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == STRING_TYPE_TAG )\r
+               return argument_;\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+const char* ReceivedMessageArgument::AsSymbol() const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == SYMBOL_TYPE_TAG )\r
+               return argument_;\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+void ReceivedMessageArgument::AsBlob( const void*& data, unsigned long& size ) const\r
+{\r
+    if( !typeTag_ )\r
+        throw MissingArgumentException();\r
+       else if( *typeTag_ == BLOB_TYPE_TAG )\r
+               AsBlobUnchecked( data, size );\r
+       else\r
+               throw WrongArgumentTypeException();\r
+}\r
+\r
+\r
+void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, unsigned long& size ) const\r
+{\r
+    size = ToUInt32( argument_ );\r
+       data = (void*)(argument_+4);\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+void ReceivedMessageArgumentIterator::Advance()\r
+{\r
+    if( !value_.typeTag_ )\r
+        return;\r
+        \r
+    switch( *value_.typeTag_++ ){\r
+        case '\0':\r
+            // don't advance past end\r
+            --value_.typeTag_;\r
+            break;\r
+            \r
+        case TRUE_TYPE_TAG:\r
+        case FALSE_TYPE_TAG:\r
+        case NIL_TYPE_TAG:\r
+        case INFINITUM_TYPE_TAG:\r
+\r
+            // zero length\r
+            break;\r
+\r
+        case INT32_TYPE_TAG:\r
+        case FLOAT_TYPE_TAG:                                   \r
+        case CHAR_TYPE_TAG:\r
+        case RGBA_COLOR_TYPE_TAG:\r
+        case MIDI_MESSAGE_TYPE_TAG:\r
+\r
+            value_.argument_ += 4;\r
+            break;\r
+\r
+        case INT64_TYPE_TAG:\r
+        case TIME_TAG_TYPE_TAG:\r
+        case DOUBLE_TYPE_TAG:\r
+                               \r
+            value_.argument_ += 8;\r
+            break;\r
+\r
+        case STRING_TYPE_TAG: \r
+        case SYMBOL_TYPE_TAG:\r
+\r
+            // we use the unsafe function FindStr4End(char*) here because all of\r
+            // the arguments have already been validated in\r
+            // ReceivedMessage::Init() below.\r
+            \r
+            value_.argument_ = FindStr4End( value_.argument_ );\r
+            break;\r
+\r
+        case BLOB_TYPE_TAG:\r
+            {\r
+                uint32 blobSize = ToUInt32( value_.argument_ );\r
+                value_.argument_ = value_.argument_ + 4 + RoundUp4( (unsigned long)blobSize );\r
+            }\r
+            break;\r
+\r
+        default:    // unknown type tag\r
+            // don't advance\r
+            --value_.typeTag_;\r
+            break;\r
+            \r
+\r
+        //    not handled:\r
+        //    [ Indicates the beginning of an array. The tags following are for\r
+        //        data in the Array until a close brace tag is reached.\r
+        //    ] Indicates the end of an array.\r
+    }\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )\r
+    : addressPattern_( packet.Contents() )\r
+{\r
+    Init( packet.Contents(), packet.Size() );\r
+}\r
+\r
+\r
+ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )\r
+    : addressPattern_( bundleElement.Contents() )\r
+{\r
+    Init( bundleElement.Contents(), bundleElement.Size() );\r
+}\r
+\r
+\r
+bool ReceivedMessage::AddressPatternIsUInt32() const\r
+{\r
+       return (addressPattern_[0] == '\0');\r
+}\r
+\r
+\r
+uint32 ReceivedMessage::AddressPatternAsUInt32() const\r
+{\r
+    return ToUInt32( addressPattern_ );\r
+}\r
+\r
+\r
+void ReceivedMessage::Init( const char *message, unsigned long size )\r
+{\r
+    if( size == 0 )\r
+        throw MalformedMessageException( "zero length messages not permitted" );\r
+\r
+    if( (size & 0x03L) != 0 )\r
+        throw MalformedMessageException( "message size must be multiple of four" );\r
+\r
+    const char *end = message + size;\r
+\r
+    typeTagsBegin_ = FindStr4End( addressPattern_, end );\r
+    if( typeTagsBegin_ == 0 ){\r
+        // address pattern was not terminated before end\r
+        throw MalformedMessageException( "unterminated address pattern" );\r
+    }\r
+\r
+    if( typeTagsBegin_ == end ){\r
+        // message consists of only the address pattern - no arguments or type tags.\r
+        typeTagsBegin_ = 0;\r
+        typeTagsEnd_ = 0;\r
+        arguments_ = 0;\r
+            \r
+    }else{\r
+        if( *typeTagsBegin_ != ',' )\r
+            throw MalformedMessageException( "type tags not present" );\r
+\r
+        if( *(typeTagsBegin_ + 1) == '\0' ){\r
+            // zero length type tags\r
+            typeTagsBegin_ = 0;\r
+            typeTagsEnd_ = 0;\r
+            arguments_ = 0;\r
+\r
+        }else{\r
+            // check that all arguments are present and well formed\r
+                \r
+            arguments_ = FindStr4End( typeTagsBegin_, end );\r
+            if( arguments_ == 0 ){\r
+                throw MalformedMessageException( "type tags were not terminated before end of message" );\r
+            }\r
+\r
+            ++typeTagsBegin_; // advance past initial ','\r
+            \r
+            const char *typeTag = typeTagsBegin_;\r
+            const char *argument = arguments_;\r
+                        \r
+            do{\r
+                switch( *typeTag ){\r
+                    case TRUE_TYPE_TAG:\r
+                    case FALSE_TYPE_TAG:\r
+                    case NIL_TYPE_TAG:\r
+                    case INFINITUM_TYPE_TAG:\r
+\r
+                        // zero length\r
+                        break;\r
+\r
+                    case INT32_TYPE_TAG:\r
+                    case FLOAT_TYPE_TAG:\r
+                    case CHAR_TYPE_TAG:\r
+                    case RGBA_COLOR_TYPE_TAG:\r
+                    case MIDI_MESSAGE_TYPE_TAG:\r
+\r
+                        if( argument == end )\r
+                            throw MalformedMessageException( "arguments exceed message size" );\r
+                        argument += 4;\r
+                        if( argument > end )\r
+                            throw MalformedMessageException( "arguments exceed message size" );\r
+                        break;\r
+\r
+                    case INT64_TYPE_TAG:\r
+                    case TIME_TAG_TYPE_TAG:\r
+                    case DOUBLE_TYPE_TAG:\r
+\r
+                        if( argument == end )\r
+                            throw MalformedMessageException( "arguments exceed message size" );\r
+                        argument += 8;\r
+                        if( argument > end )\r
+                            throw MalformedMessageException( "arguments exceed message size" );\r
+                        break;\r
+\r
+                    case STRING_TYPE_TAG: \r
+                    case SYMBOL_TYPE_TAG:\r
+                    \r
+                        if( argument == end )\r
+                            throw MalformedMessageException( "arguments exceed message size" );\r
+                        argument = FindStr4End( argument, end );\r
+                        if( argument == 0 )\r
+                            throw MalformedMessageException( "unterminated string argument" );\r
+                        break;\r
+\r
+                    case BLOB_TYPE_TAG:\r
+                        {\r
+                            if( argument + 4 > end )\r
+                                MalformedMessageException( "arguments exceed message size" );\r
+                                \r
+                            uint32 blobSize = ToUInt32( argument );\r
+                            argument = argument + 4 + RoundUp4( (unsigned long)blobSize );\r
+                            if( argument > end )\r
+                                MalformedMessageException( "arguments exceed message size" );\r
+                        }\r
+                        break;\r
+                        \r
+                    default:\r
+                        throw MalformedMessageException( "unknown type tag" );\r
+\r
+                    //    not handled:\r
+                    //    [ Indicates the beginning of an array. The tags following are for\r
+                    //        data in the Array until a close brace tag is reached.\r
+                    //    ] Indicates the end of an array.\r
+                }\r
+\r
+            }while( *++typeTag != '\0' );\r
+            typeTagsEnd_ = typeTag;\r
+        }\r
+    }\r
+}\r
+\r
+//------------------------------------------------------------------------------\r
+\r
+ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )\r
+    : elementCount_( 0 )\r
+{\r
+    Init( packet.Contents(), packet.Size() );\r
+}\r
+\r
+\r
+ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )\r
+    : elementCount_( 0 )\r
+{\r
+    Init( bundleElement.Contents(), bundleElement.Size() );\r
+}\r
+\r
+\r
+void ReceivedBundle::Init( const char *bundle, unsigned long size )\r
+{\r
+    if( size < 16 )\r
+        throw MalformedBundleException( "packet too short for bundle" );\r
+\r
+    if( (size & 0x03L) != 0 )\r
+        throw MalformedBundleException( "bundle size must be multiple of four" );\r
+\r
+    if( bundle[0] != '#'\r
+        || bundle[1] != 'b'\r
+        || bundle[2] != 'u'\r
+        || bundle[3] != 'n'\r
+        || bundle[4] != 'd'\r
+        || bundle[5] != 'l'\r
+        || bundle[6] != 'e'\r
+        || bundle[7] != '\0' )\r
+            throw MalformedBundleException( "bad bundle address pattern" );    \r
+\r
+    end_ = bundle + size;\r
+\r
+    timeTag_ = bundle + 8;\r
+\r
+    const char *p = timeTag_ + 8;\r
+        \r
+    while( p < end_ ){\r
+        if( p + 4 > end_ )\r
+            throw MalformedBundleException( "packet too short for elementSize" );\r
+\r
+        uint32 elementSize = ToUInt32( p );\r
+        if( (elementSize & 0x03L) != 0 )\r
+            throw MalformedBundleException( "bundle element size must be multiple of four" );\r
+\r
+        p += 4 + elementSize;\r
+        if( p > end_ )\r
+            throw MalformedBundleException( "packet too short for bundle element" );\r
+\r
+        ++elementCount_;\r
+    }\r
+\r
+    if( p != end_ )\r
+        throw MalformedBundleException( "bundle contents " );\r
+}\r
+\r
+\r
+uint64 ReceivedBundle::TimeTag() const\r
+{\r
+    return ToUInt64( timeTag_ );\r
+}\r
+\r
+\r
+} // namespace osc\r
+\r
diff --git a/protocol/osc/oscpack/OscReceivedElements.h b/protocol/osc/oscpack/OscReceivedElements.h
new file mode 100644 (file)
index 0000000..07e0194
--- /dev/null
@@ -0,0 +1,488 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H\r
+#define INCLUDED_OSCRECEIVEDELEMENTS_H\r
+\r
+#include <cstddef>\r
+\r
+#include "OscTypes.h"\r
+#include "OscException.h"\r
+\r
+\r
+namespace osc{\r
+\r
+\r
+class MalformedMessageException : public Exception{\r
+public:\r
+    MalformedMessageException( const char *w="malformed message" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class MalformedBundleException : public Exception{\r
+public:\r
+    MalformedBundleException( const char *w="malformed bundle" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class WrongArgumentTypeException : public Exception{\r
+public:\r
+    WrongArgumentTypeException( const char *w="wrong argument type" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class MissingArgumentException : public Exception{\r
+public:\r
+    MissingArgumentException( const char *w="missing argument" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+class ExcessArgumentException : public Exception{\r
+public:\r
+    ExcessArgumentException( const char *w="too many arguments" )\r
+        : Exception( w ) {}\r
+};\r
+\r
+\r
+class ReceivedPacket{\r
+public:\r
+    ReceivedPacket( const char *contents, int32 size )\r
+        : contents_( contents )\r
+        , size_( size ) {}\r
+\r
+    bool IsMessage() const { return !IsBundle(); }\r
+    bool IsBundle() const;\r
+\r
+    int32 Size() const { return size_; }\r
+    const char *Contents() const { return contents_; }\r
+\r
+private:\r
+    const char *contents_;\r
+    int32 size_;\r
+};\r
+\r
+\r
+class ReceivedBundleElement{\r
+public:\r
+    ReceivedBundleElement( const char *size )\r
+        : size_( size ) {}\r
+\r
+    friend class ReceivedBundleElementIterator;\r
+\r
+    bool IsMessage() const { return !IsBundle(); }\r
+    bool IsBundle() const;\r
+\r
+    int32 Size() const;\r
+    const char *Contents() const { return size_ + 4; }\r
+\r
+private:\r
+    const char *size_;\r
+};\r
+\r
+\r
+class ReceivedBundleElementIterator{\r
+public:\r
+       ReceivedBundleElementIterator( const char *sizePtr )\r
+        : value_( sizePtr ) {}\r
+\r
+       ReceivedBundleElementIterator operator++()\r
+       {\r
+        Advance();\r
+        return *this;\r
+       }\r
+\r
+    ReceivedBundleElementIterator operator++(int)\r
+    {\r
+        ReceivedBundleElementIterator old( *this );\r
+        Advance();\r
+        return old;\r
+    }\r
+\r
+       const ReceivedBundleElement& operator*() const { return value_; }\r
+\r
+    const ReceivedBundleElement* operator->() const { return &value_; }\r
+\r
+       friend bool operator==(const ReceivedBundleElementIterator& lhs,\r
+            const ReceivedBundleElementIterator& rhs );\r
+\r
+private:\r
+       ReceivedBundleElement value_;\r
+\r
+       void Advance() { value_.size_ = value_.Contents() + value_.Size(); }\r
+\r
+    bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const\r
+    {\r
+        return value_.size_ == rhs.value_.size_;\r
+    }\r
+};\r
+\r
+inline bool operator==(const ReceivedBundleElementIterator& lhs,\r
+        const ReceivedBundleElementIterator& rhs )\r
+{      \r
+       return lhs.IsEqualTo( rhs );\r
+}\r
+\r
+inline bool operator!=(const ReceivedBundleElementIterator& lhs,\r
+        const ReceivedBundleElementIterator& rhs )\r
+{\r
+       return !( lhs == rhs );\r
+}\r
+\r
+\r
+class ReceivedMessageArgument{\r
+public:\r
+       ReceivedMessageArgument( const char *typeTag, const char *argument )\r
+               : typeTag_( typeTag )\r
+               , argument_( argument ) {}\r
+\r
+    friend class ReceivedMessageArgumentIterator;\r
+    \r
+       const char TypeTag() const { return *typeTag_; }\r
+\r
+    // the unchecked methods below don't check whether the argument actually\r
+    // is of the specified type. they should only be used if you've already\r
+    // checked the type tag or the associated IsType() method.\r
+\r
+    bool IsBool() const\r
+        { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }\r
+    bool AsBool() const;\r
+    bool AsBoolUnchecked() const;\r
+\r
+    bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }\r
+    bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }\r
+\r
+    bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }\r
+    int32 AsInt32() const;\r
+    int32 AsInt32Unchecked() const;\r
+\r
+    bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }\r
+    float AsFloat() const;\r
+    float AsFloatUnchecked() const;\r
+\r
+    bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }\r
+    char AsChar() const;\r
+    char AsCharUnchecked() const;\r
+\r
+    bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }\r
+    uint32 AsRgbaColor() const;\r
+    uint32 AsRgbaColorUnchecked() const;\r
+\r
+    bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }\r
+    uint32 AsMidiMessage() const;\r
+    uint32 AsMidiMessageUnchecked() const;\r
+\r
+    bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }\r
+    int64 AsInt64() const;\r
+    int64 AsInt64Unchecked() const;\r
+\r
+    bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }\r
+    uint64 AsTimeTag() const;\r
+    uint64 AsTimeTagUnchecked() const;\r
+\r
+    bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }\r
+    double AsDouble() const;\r
+    double AsDoubleUnchecked() const;\r
+\r
+    bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; }\r
+    const char* AsString() const;\r
+    const char* AsStringUnchecked() const { return argument_; }\r
+\r
+    bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }\r
+    const char* AsSymbol() const;\r
+    const char* AsSymbolUnchecked() const { return argument_; }\r
+\r
+    bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; }\r
+    void AsBlob( const void*& data, unsigned long& size ) const;\r
+    void AsBlobUnchecked( const void*& data, unsigned long& size ) const;\r
+    \r
+private:\r
+       const char *typeTag_;\r
+       const char *argument_;\r
+};\r
+\r
+\r
+class ReceivedMessageArgumentIterator{\r
+public:\r
+       ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )\r
+        : value_( typeTags, arguments ) {}\r
+\r
+       ReceivedMessageArgumentIterator operator++()\r
+       {\r
+        Advance();\r
+        return *this;\r
+       }\r
+\r
+    ReceivedMessageArgumentIterator operator++(int)\r
+    {\r
+        ReceivedMessageArgumentIterator old( *this );\r
+        Advance();\r
+        return old;\r
+    }\r
+\r
+       const ReceivedMessageArgument& operator*() const { return value_; }\r
+\r
+    const ReceivedMessageArgument* operator->() const { return &value_; }\r
+\r
+       friend bool operator==(const ReceivedMessageArgumentIterator& lhs,\r
+            const ReceivedMessageArgumentIterator& rhs );\r
+\r
+private:\r
+       ReceivedMessageArgument value_;\r
+\r
+       void Advance();\r
+\r
+    bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const\r
+    {\r
+        return value_.typeTag_ == rhs.value_.typeTag_;\r
+    }\r
+};\r
+\r
+inline bool operator==(const ReceivedMessageArgumentIterator& lhs,\r
+        const ReceivedMessageArgumentIterator& rhs )\r
+{      \r
+       return lhs.IsEqualTo( rhs );\r
+}\r
+\r
+inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,\r
+        const ReceivedMessageArgumentIterator& rhs )\r
+{      \r
+       return !( lhs == rhs );\r
+}\r
+\r
+\r
+class ReceivedMessageArgumentStream{\r
+    friend class ReceivedMessage;\r
+    ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,\r
+            const ReceivedMessageArgumentIterator& end )\r
+        : p_( begin )\r
+        , end_( end ) {}\r
+\r
+    ReceivedMessageArgumentIterator p_, end_;\r
+    \r
+public:\r
+\r
+    // end of stream\r
+    bool Eos() const { return p_ == end_; }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( bool& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsBool();\r
+        return *this;\r
+    }\r
+\r
+    // not sure if it would be useful to stream Nil and Infinitum\r
+    // for now it's not possible\r
+\r
+    ReceivedMessageArgumentStream& operator>>( int32& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsInt32();\r
+        return *this;\r
+    }     \r
+\r
+    ReceivedMessageArgumentStream& operator>>( float& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsFloat();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( char& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsChar();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs.value = (*p_++).AsRgbaColor();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs.value = (*p_++).AsMidiMessage();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( int64& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsInt64();\r
+        return *this;\r
+    }\r
+    \r
+    ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs.value = (*p_++).AsTimeTag();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( double& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsDouble();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( Blob& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        (*p_++).AsBlob( rhs.data, rhs.size );\r
+        return *this;\r
+    }\r
+    \r
+    ReceivedMessageArgumentStream& operator>>( const char*& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs = (*p_++).AsString();\r
+        return *this;\r
+    }\r
+    \r
+    ReceivedMessageArgumentStream& operator>>( Symbol& rhs )\r
+    {\r
+        if( Eos() )\r
+            throw MissingArgumentException();\r
+\r
+        rhs.value = (*p_++).AsSymbol();\r
+        return *this;\r
+    }\r
+\r
+    ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )\r
+    {\r
+        if( !Eos() )\r
+            throw ExcessArgumentException();\r
+\r
+        return *this;\r
+    }\r
+};\r
+\r
+\r
+class ReceivedMessage{\r
+    void Init( const char *bundle, unsigned long size );\r
+public:\r
+    explicit ReceivedMessage( const ReceivedPacket& packet );\r
+    explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );\r
+\r
+       const char *AddressPattern() const { return addressPattern_; }\r
+\r
+       // Support for non-standad SuperCollider integer address patterns:\r
+       bool AddressPatternIsUInt32() const;\r
+       uint32 AddressPatternAsUInt32() const;\r
+\r
+       unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }\r
+\r
+    const char *TypeTags() const { return typeTagsBegin_; }\r
+\r
+\r
+    typedef ReceivedMessageArgumentIterator const_iterator;\r
+    \r
+       ReceivedMessageArgumentIterator ArgumentsBegin() const\r
+    {\r
+        return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );\r
+    }\r
+     \r
+       ReceivedMessageArgumentIterator ArgumentsEnd() const\r
+    {\r
+        return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );\r
+    }\r
+\r
+    ReceivedMessageArgumentStream ArgumentStream() const\r
+    {\r
+        return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );\r
+    }\r
+\r
+private:\r
+       const char *addressPattern_;\r
+       const char *typeTagsBegin_;\r
+       const char *typeTagsEnd_;\r
+    const char *arguments_;\r
+};\r
+\r
+\r
+class ReceivedBundle{\r
+    void Init( const char *message, unsigned long size );\r
+public:\r
+    explicit ReceivedBundle( const ReceivedPacket& packet );\r
+    explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );\r
+\r
+    uint64 TimeTag() const;\r
+\r
+    unsigned long ElementCount() const { return elementCount_; }\r
+\r
+    typedef ReceivedBundleElementIterator const_iterator;\r
+    \r
+       ReceivedBundleElementIterator ElementsBegin() const\r
+    {\r
+        return ReceivedBundleElementIterator( timeTag_ + 8 );\r
+    }\r
+     \r
+       ReceivedBundleElementIterator ElementsEnd() const\r
+    {\r
+        return ReceivedBundleElementIterator( end_ );\r
+    }\r
+\r
+private:\r
+    const char *timeTag_;\r
+    const char *end_;\r
+    unsigned long elementCount_;\r
+};\r
+\r
+\r
+} // namespace osc\r
+\r
+\r
+#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */\r
diff --git a/protocol/osc/oscpack/OscTypes.cpp b/protocol/osc/oscpack/OscTypes.cpp
new file mode 100644 (file)
index 0000000..889ab43
--- /dev/null
@@ -0,0 +1,40 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#include "OscTypes.h"\r
+\r
+namespace osc{\r
+\r
+BundleInitiator BeginBundleImmediate(1);\r
+BundleTerminator EndBundle;\r
+MessageTerminator EndMessage;\r
+NilType Nil;\r
+InfinitumType Infinitum;\r
+\r
+} // namespace osc\r
diff --git a/protocol/osc/oscpack/OscTypes.h b/protocol/osc/oscpack/OscTypes.h
new file mode 100644 (file)
index 0000000..a3712bc
--- /dev/null
@@ -0,0 +1,183 @@
+/*\r
+       oscpack -- Open Sound Control packet manipulation library\r
+       http://www.audiomulch.com/~rossb/oscpack\r
+\r
+       Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\r
+\r
+       Permission is hereby granted, free of charge, to any person obtaining\r
+       a copy of this software and associated documentation files\r
+       (the "Software"), to deal in the Software without restriction,\r
+       including without limitation the rights to use, copy, modify, merge,\r
+       publish, distribute, sublicense, and/or sell copies of the Software,\r
+       and to permit persons to whom the Software is furnished to do so,\r
+       subject to the following conditions:\r
+\r
+       The above copyright notice and this permission notice shall be\r
+       included in all copies or substantial portions of the Software.\r
+\r
+       Any person wishing to distribute modifications to the Software is\r
+       requested to send the modifications to the original developer so that\r
+       they can be incorporated into the canonical version.\r
+\r
+       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+       EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+       IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+       ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+       CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+*/\r
+#ifndef INCLUDED_OSCTYPES_H\r
+#define INCLUDED_OSCTYPES_H\r
+\r
+\r
+namespace osc{\r
+\r
+// basic types\r
+\r
+#if defined(__BORLANDC__) || defined(_MSC_VER)\r
+\r
+typedef __int64 int64;\r
+typedef unsigned __int64 uint64;\r
+\r
+#elif defined(__x86_64__) || defined(_M_X64)\r
+\r
+typedef long int64;\r
+typedef unsigned long uint64;\r
+\r
+#else\r
+\r
+typedef long long int64;\r
+typedef unsigned long long uint64;\r
+\r
+#endif\r
+\r
+\r
+\r
+#if defined(__x86_64__) || defined(_M_X64)\r
+\r
+typedef signed int int32;\r
+typedef unsigned int uint32;\r
+\r
+#else\r
+\r
+typedef signed long int32;\r
+typedef unsigned long uint32;\r
+\r
+#endif\r
+\r
+\r
+\r
+enum TypeTagValues {\r
+    TRUE_TYPE_TAG = 'T',\r
+    FALSE_TYPE_TAG = 'F',\r
+    NIL_TYPE_TAG = 'N',\r
+    INFINITUM_TYPE_TAG = 'I',\r
+    INT32_TYPE_TAG = 'i',\r
+    FLOAT_TYPE_TAG = 'f',\r
+    CHAR_TYPE_TAG = 'c',\r
+    RGBA_COLOR_TYPE_TAG = 'r',\r
+    MIDI_MESSAGE_TYPE_TAG = 'm',\r
+    INT64_TYPE_TAG = 'h',\r
+    TIME_TAG_TYPE_TAG = 't',\r
+    DOUBLE_TYPE_TAG = 'd',\r
+    STRING_TYPE_TAG = 's',\r
+    SYMBOL_TYPE_TAG = 'S',\r
+    BLOB_TYPE_TAG = 'b'\r
+};\r
+\r
+\r
+\r
+// i/o manipulators used for streaming interfaces\r
+\r
+struct BundleInitiator{\r
+    explicit BundleInitiator( uint64 timeTag_ ) : timeTag( timeTag_ ) {}\r
+    uint64 timeTag;\r
+};\r
+\r
+extern BundleInitiator BeginBundleImmediate;\r
+\r
+inline BundleInitiator BeginBundle( uint64 timeTag=1 )\r
+{\r
+    return BundleInitiator(timeTag);\r
+}\r
+\r
+\r
+struct BundleTerminator{\r
+};\r
+\r
+extern BundleTerminator EndBundle;\r
+\r
+struct BeginMessage{\r
+    explicit BeginMessage( const char *addressPattern_ ) : addressPattern( addressPattern_ ) {}\r
+    const char *addressPattern;\r
+};\r
+\r
+struct MessageTerminator{\r
+};\r
+\r
+extern MessageTerminator EndMessage;\r
+\r
+\r
+// osc specific types. they are defined as structs so they can be used\r
+// as separately identifiable types with the streaming operators.\r
+\r
+struct NilType{\r
+};\r
+\r
+extern NilType Nil;\r
+\r
+\r
+struct InfinitumType{\r
+};\r
+\r
+extern InfinitumType Infinitum;\r
+\r
+struct RgbaColor{\r
+    RgbaColor() {}\r
+    explicit RgbaColor( uint32 value_ ) : value( value_ ) {}\r
+    uint32 value;\r
+\r
+    operator uint32() const { return value; }\r
+};\r
+\r
+\r
+struct MidiMessage{\r
+    MidiMessage() {}\r
+    explicit MidiMessage( uint32 value_ ) : value( value_ ) {}\r
+    uint32 value;\r
+\r
+    operator uint32() const { return value; }\r
+};\r
+\r
+\r
+struct TimeTag{\r
+    TimeTag() {}\r
+    explicit TimeTag( uint64 value_ ) : value( value_ ) {}\r
+    uint64 value;\r
+\r
+    operator uint64() const { return value; }\r
+};\r
+\r
+\r
+struct Symbol{\r
+    Symbol() {}\r
+    explicit Symbol( const char* value_ ) : value( value_ ) {}\r
+    const char* value;\r
+\r
+    operator const char *() const { return value; }\r
+};\r
+\r
+\r
+struct Blob{\r
+    Blob() {}\r
+    explicit Blob( const void* data_, unsigned long size_ )\r
+            : data( data_ ), size( size_ ) {}\r
+    const void* data;\r
+    unsigned long size;\r
+};\r
+\r
+} // namespace osc\r
+\r
+\r
+#endif /* INCLUDED_OSCTYPES_H */\r
diff --git a/protocol/osc/server.cpp b/protocol/osc/server.cpp
new file mode 100644 (file)
index 0000000..47a0387
--- /dev/null
@@ -0,0 +1,232 @@
+#include "..\stdafx.h"\r
+\r
+#include "server.h"\r
+\r
+#include "oscpack/oscOutboundPacketStream.h"\r
+\r
+#include <algorithm>\r
+#include <array>\r
+#include <string>\r
+#include <set>\r
+#include <regex>\r
+#include <vector>\r
+\r
+#include <boost/optional.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/asio.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/algorithm/string/iter_find.hpp>\r
+#include <boost/algorithm/string/finder.hpp>\r
+#include <boost/algorithm/string/predicate.hpp>\r
+#include <boost/thread/mutex.hpp>\r
+\r
+using namespace boost::asio::ip;\r
+\r
+namespace caspar { namespace protocol { namespace osc {\r
+       \r
+template<typename T>\r
+struct param_visitor : public boost::static_visitor<void>\r
+{\r
+       T& o;\r
+\r
+       param_visitor(T& o)\r
+               : o(o)\r
+       {\r
+       }               \r
+               \r
+       void operator()(const bool value)                                       {o << value;}\r
+       void operator()(const int32_t value)                            {o << value;}\r
+       void operator()(const uint32_t value)                           {o << value;}\r
+       void operator()(const int64_t value)                            {o << value;}\r
+       void operator()(const uint64_t value)                           {o << value;}\r
+       void operator()(const float value)                                      {o << value;}\r
+       void operator()(const double value)                                     {o << static_cast<float>(value);}\r
+       void operator()(const std::string& value)                       {o << value.c_str();}\r
+       void operator()(const std::vector<int8_t>& value)       {o << ::osc::Blob(value.data(), static_cast<unsigned long>(value.size()));}\r
+       void operator()(const monitor::duration& value)\r
+       {\r
+               o << boost::chrono::duration_cast<boost::chrono::duration<double, boost::ratio<1, 1>>>(value).count();\r
+       }\r
+};\r
+\r
+std::vector<char> write_osc_event(const monitor::event& e)\r
+{\r
+       std::array<char, 4096> buffer;\r
+       ::osc::OutboundPacketStream o(buffer.data(), static_cast<unsigned long>(buffer.size()));\r
+\r
+       o       << ::osc::BeginMessage(e.path().str().c_str());\r
+                               \r
+       param_visitor<decltype(o)> pd_visitor(o);\r
+       BOOST_FOREACH(auto param, e.params())\r
+               boost::apply_visitor(pd_visitor, param);\r
+                               \r
+       o       << ::osc::EndMessage;\r
+               \r
+       return std::vector<char>(o.Data(), o.Data() + o.Size());\r
+}\r
+\r
+class connection;\r
+\r
+typedef std::set<spl::shared_ptr<connection>> connection_set;\r
+\r
+class connection : public spl::enable_shared_from_this<connection>\r
+{    \r
+    spl::shared_ptr<tcp::socket>                       socket_; \r
+       boost::optional<std::regex>             regex_;\r
+\r
+       std::array<char, 8192>                  data_;\r
+       \r
+       spl::shared_ptr<connection_set>         connection_set_;\r
+\r
+       std::string                                             input_;\r
+\r
+public:\r
+    static spl::shared_ptr<connection> create(spl::shared_ptr<tcp::socket> socket, spl::shared_ptr<connection_set> connection_set)\r
+       {\r
+               auto con = spl::shared_ptr<connection>(new connection(std::move(socket), std::move(connection_set)));\r
+               con->read_some();\r
+               return con;\r
+    }\r
+       \r
+       void stop()\r
+       {\r
+               socket_->close();\r
+       }\r
+               \r
+       std::wstring print() const\r
+       {\r
+               return L"[" + (socket_->is_open() ? u16(socket_->remote_endpoint().address().to_string()) : L"n/a") + L"]";\r
+       }\r
+               \r
+       void on_next(const monitor::event& e)\r
+       {       \r
+               if(regex_ && std::regex_search(e.path().str(), *regex_))\r
+                       return; \r
+\r
+               auto data_ptr = spl::make_shared<std::vector<char>>(write_osc_event(e));\r
+               auto size = data_ptr->size();\r
+               char* size_ptr = reinterpret_cast<char*>(&size);\r
+\r
+               data_ptr->insert(std::begin(*data_ptr), size_ptr, size_ptr + sizeof(int32_t));\r
+               socket_->async_write_some(boost::asio::buffer(*data_ptr), std::bind(&connection::handle_write, shared_from_this(), data_ptr, std::placeholders::_1, std::placeholders::_2));    \r
+       }\r
+       \r
+private:\r
+    connection(spl::shared_ptr<tcp::socket> socket, spl::shared_ptr<connection_set> connection_set) \r
+               : socket_(std::move(socket))\r
+               , connection_set_(std::move(connection_set))\r
+       {\r
+    }\r
+                                       \r
+    void handle_read(const boost::system::error_code& error, size_t bytes_transferred) \r
+       {               \r
+               if(!error)\r
+               {\r
+                       try\r
+                       {\r
+                               on_read(std::string(data_.begin(), data_.begin() + bytes_transferred));\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+                       \r
+                       read_some();\r
+               }  \r
+               else if (error != boost::asio::error::operation_aborted)\r
+                       connection_set_->erase(shared_from_this());\r
+               else\r
+                       read_some();\r
+    }\r
+\r
+    void handle_write(const spl::shared_ptr<std::vector<char>>& data, const boost::system::error_code& error, size_t bytes_transferred)\r
+       {\r
+               if(!error)                      \r
+               {\r
+               }\r
+               else if (error != boost::asio::error::operation_aborted)\r
+                       connection_set_->erase(shared_from_this());\r
+    }\r
+\r
+       void read_some()\r
+       {\r
+               socket_->async_read_some(boost::asio::buffer(data_.data(), data_.size()), std::bind(&connection::handle_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));\r
+       }\r
+               \r
+       void on_read(std::string str)\r
+       {\r
+               input_ += str;\r
+\r
+               std::vector<std::string> commands;\r
+               boost::iter_split(commands, input_, boost::algorithm::first_finder("\r\n"));\r
+               \r
+               if(commands.size() == 1)\r
+                       return;\r
+\r
+               input_ = commands.back();\r
+               commands.pop_back();    \r
+\r
+               if(commands.back() == ".*")\r
+                       regex_.reset();\r
+               else\r
+                       regex_ = std::regex(commands.back());\r
+       }\r
+};\r
+\r
+class tcp_observer : public reactive::observer<monitor::event>\r
+{\r
+       boost::asio::io_service                 service_;\r
+       tcp::acceptor                                   acceptor_;\r
+       spl::shared_ptr<connection_set> connection_set_;\r
+       boost::thread                                   thread_;\r
+       \r
+public:\r
+       tcp_observer(unsigned short port)\r
+               : acceptor_(service_, tcp::endpoint(tcp::v4(), port))\r
+               , thread_(std::bind(&boost::asio::io_service::run, &service_))\r
+       {\r
+               start_accept(); \r
+       }\r
+\r
+       ~tcp_observer()\r
+       {               \r
+               acceptor_.close();\r
+               BOOST_FOREACH(auto& connection, *connection_set_)\r
+                       connection->stop();\r
+\r
+               thread_.join();\r
+       }\r
+       \r
+       void on_next(const monitor::event& e) override\r
+       {\r
+               service_.post([=]\r
+               {\r
+                       BOOST_FOREACH(auto& connection, *connection_set_)\r
+                               connection->on_next(e);\r
+               });\r
+       }       \r
+private:               \r
+    void start_accept() \r
+       {\r
+               auto socket = spl::make_shared<tcp::socket>(service_);\r
+               acceptor_.async_accept(*socket, std::bind(&tcp_observer::handle_accept, this, socket, std::placeholders::_1));\r
+    }\r
+\r
+       void handle_accept(const spl::shared_ptr<tcp::socket>& socket, const boost::system::error_code& error) \r
+       {\r
+               if (!acceptor_.is_open())\r
+                       return;\r
+\r
+        if (!error)            \r
+                       connection_set_->insert(connection::create(socket, connection_set_));\r
+        \r
+               start_accept();\r
+    }\r
+};\r
+\r
+server::server(unsigned short port) \r
+       : impl_(new tcp_observer(port)){}\r
+void server::on_next(const monitor::event& e){impl_->on_next(e);}\r
+\r
+}}}
\ No newline at end of file
diff --git a/protocol/osc/server.h b/protocol/osc/server.h
new file mode 100644 (file)
index 0000000..192a3c9
--- /dev/null
@@ -0,0 +1,21 @@
+#pragma once\r
+\r
+#include <common/spl/memory.h>\r
+\r
+#include <core/monitor/monitor.h>\r
+\r
+#include <functional>\r
+\r
+namespace caspar { namespace protocol { namespace osc {\r
+\r
+class server : public reactive::observer<monitor::event>\r
+{\r
+public:        \r
+       server(unsigned short port);\r
+       \r
+       virtual void on_next(const monitor::event& e) override;\r
+private:\r
+       spl::shared_ptr<observer<monitor::event>> impl_;\r
+};\r
+\r
+}}}
\ No newline at end of file
index 832969f2ceb321bc7ebf06c7103932699524ffa0..c7191536e5882f5b76942ee22706401dc4e65c8a 100644 (file)
     <ClInclude Include="cii\CIIProtocolStrategy.h" />\r
     <ClInclude Include="clk\CLKCommand.h" />\r
     <ClInclude Include="clk\CLKProtocolStrategy.h" />\r
+    <ClInclude Include="osc\oscpack\MessageMappingOscPacketListener.h" />\r
+    <ClInclude Include="osc\oscpack\OscException.h" />\r
+    <ClInclude Include="osc\oscpack\OscHostEndianness.h" />\r
+    <ClInclude Include="osc\oscpack\OscOutboundPacketStream.h" />\r
+    <ClInclude Include="osc\oscpack\OscPacketListener.h" />\r
+    <ClInclude Include="osc\oscpack\OscPrintReceivedElements.h" />\r
+    <ClInclude Include="osc\oscpack\OscReceivedElements.h" />\r
+    <ClInclude Include="osc\oscpack\OscTypes.h" />\r
+    <ClInclude Include="osc\server.h" />\r
     <ClInclude Include="StdAfx.h" />\r
     <ClInclude Include="util\AsyncEventServer.h" />\r
     <ClInclude Include="util\ClientInfo.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscOutboundPacketStream.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscPrintReceivedElements.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscReceivedElements.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscTypes.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\server.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="StdAfx.cpp">\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>\r
index fe16c366f9c4837a62651297d3c96b1c087fdfcd..f2ae85fe332b44ba03202d5772f6b601d79bc281 100644 (file)
     <Filter Include="source\amcp">\r
       <UniqueIdentifier>{93331f26-581b-4d15-81a6-0aae31ad3958}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\osc">\r
+      <UniqueIdentifier>{c42b1c65-4f93-4cde-a3d2-e403f599142b}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\osc\oscpack">\r
+      <UniqueIdentifier>{d6dede65-7a93-4494-aa2d-d18d5267902c}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="amcp\AMCPCommand.h">\r
       <Filter>source\util</Filter>\r
     </ClInclude>\r
     <ClInclude Include="StdAfx.h" />\r
+    <ClInclude Include="osc\oscpack\OscHostEndianness.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscOutboundPacketStream.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscPacketListener.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscPrintReceivedElements.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscReceivedElements.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscTypes.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\MessageMappingOscPacketListener.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\oscpack\OscException.h">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="osc\server.h">\r
+      <Filter>source\osc</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="amcp\AMCPCommandQueue.cpp">\r
       <Filter>source\util</Filter>\r
     </ClCompile>\r
     <ClCompile Include="StdAfx.cpp" />\r
+    <ClCompile Include="osc\oscpack\OscOutboundPacketStream.cpp">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscPrintReceivedElements.cpp">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscReceivedElements.cpp">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\oscpack\OscTypes.cpp">\r
+      <Filter>source\osc\oscpack</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="osc\server.cpp">\r
+      <Filter>source\osc</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 394751cb5bd6c6c801592cb0caa44d3427918937..253d89a4e1085ff43919585f67fde886aa1506a9 100644 (file)
@@ -43,6 +43,7 @@
 #include <atlbase.h>\r
 \r
 #include <protocol/amcp/AMCPProtocolStrategy.h>\r
+#include <protocol/osc/server.h>\r
 \r
 #include <modules/bluefish/bluefish.h>\r
 #include <modules/decklink/decklink.h>\r
@@ -65,6 +66,8 @@
 #include <boost/property_tree/xml_parser.hpp>\r
 #include <boost/foreach.hpp>\r
 \r
+using namespace caspar;\r
+       \r
 // NOTE: This is needed in order to make CComObject work since this is not a real ATL project.\r
 CComModule _AtlModule;\r
 extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;\r
@@ -102,7 +105,7 @@ void setup_console_window()
 \r
        // Set console title.\r
        std::wstringstream str;\r
-       str << "CasparCG Server " << caspar::env::version() << L" x64 ";\r
+       str << "CasparCG Server " << env::version() << L" x64 ";\r
 #ifdef COMPILE_RELEASE\r
        str << " Release";\r
 #elif  COMPILE_PROFILE\r
@@ -120,26 +123,26 @@ void print_info()
        CASPAR_LOG(info) << L"################################################################################";\r
        CASPAR_LOG(info) << L"Copyright (c) 2010 Sveriges Television AB, www.casparcg.com, <info@casparcg.com>";\r
        CASPAR_LOG(info) << L"################################################################################";\r
-       CASPAR_LOG(info) << L"Starting CasparCG Video and Graphics Playout Server " << caspar::env::version();\r
-       CASPAR_LOG(info) << L"on " << caspar::get_win_product_name() << L" " << caspar::get_win_sp_version();\r
-       CASPAR_LOG(info) << caspar::get_cpu_info();\r
-       CASPAR_LOG(info) << caspar::get_system_product_name();\r
+       CASPAR_LOG(info) << L"Starting CasparCG Video and Graphics Playout Server " << env::version();\r
+       CASPAR_LOG(info) << L"on " << get_win_product_name() << L" " << get_win_sp_version();\r
+       CASPAR_LOG(info) << get_cpu_info();\r
+       CASPAR_LOG(info) << get_system_product_name();\r
        \r
-       CASPAR_LOG(info) << L"Decklink " << caspar::decklink::get_version();\r
-       BOOST_FOREACH(auto device, caspar::decklink::get_device_list())\r
+       CASPAR_LOG(info) << L"Decklink " << decklink::get_version();\r
+       BOOST_FOREACH(auto device, decklink::get_device_list())\r
                CASPAR_LOG(info) << L" - " << device;   \r
                \r
-       CASPAR_LOG(info) << L"Bluefish " << caspar::bluefish::get_version();\r
-       BOOST_FOREACH(auto device, caspar::bluefish::get_device_list())\r
+       CASPAR_LOG(info) << L"Bluefish " << bluefish::get_version();\r
+       BOOST_FOREACH(auto device, bluefish::get_device_list())\r
                CASPAR_LOG(info) << L" - " << device;   \r
        \r
-       CASPAR_LOG(info) << L"Flash "                   << caspar::flash::get_version();\r
-       CASPAR_LOG(info) << L"FreeImage "               << caspar::image::get_version();\r
-       CASPAR_LOG(info) << L"FFMPEG-avcodec "  << caspar::ffmpeg::get_avcodec_version();\r
-       CASPAR_LOG(info) << L"FFMPEG-avformat " << caspar::ffmpeg::get_avformat_version();\r
-       CASPAR_LOG(info) << L"FFMPEG-avfilter " << caspar::ffmpeg::get_avfilter_version();\r
-       CASPAR_LOG(info) << L"FFMPEG-avutil "   << caspar::ffmpeg::get_avutil_version();\r
-       CASPAR_LOG(info) << L"FFMPEG-swscale "  << caspar::ffmpeg::get_swscale_version();\r
+       CASPAR_LOG(info) << L"Flash "                   << flash::get_version();\r
+       CASPAR_LOG(info) << L"FreeImage "               << image::get_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avcodec "  << ffmpeg::get_avcodec_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avformat " << ffmpeg::get_avformat_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avfilter " << ffmpeg::get_avfilter_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-avutil "   << ffmpeg::get_avutil_version();\r
+       CASPAR_LOG(info) << L"FFMPEG-swscale "  << ffmpeg::get_swscale_version();\r
 }\r
 \r
 LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)\r
@@ -159,7 +162,7 @@ LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)
 }\r
 \r
 int main(int argc, wchar_t* argv[])\r
-{              \r
+{      \r
        SetUnhandledExceptionFilter(UserUnhandledExceptionFilter);\r
 \r
        std::wcout << L"Type \"q\" to close application." << std::endl;\r
@@ -183,7 +186,7 @@ int main(int argc, wchar_t* argv[])
        SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);\r
 \r
        // Install structured exception handler.\r
-       caspar::win32_exception::install_handler();\r
+       win32_exception::install_handler();\r
                                \r
        // Increase time precision. This will increase accuracy of function like Sleep(1) from 10 ms to 1 ms.\r
        struct inc_prec\r
@@ -198,8 +201,8 @@ int main(int argc, wchar_t* argv[])
                tbb_thread_installer(){observe(true);}\r
                void on_scheduler_entry(bool is_worker)\r
                {\r
-                       //caspar::detail::SetThreadName(GetCurrentThreadId(), "tbb-worker-thread");\r
-                       caspar::win32_exception::install_handler();\r
+                       //detail::SetThreadName(GetCurrentThreadId(), "tbb-worker-thread");\r
+                       win32_exception::install_handler();\r
                }\r
        } tbb_thread_installer;\r
 \r
@@ -208,18 +211,18 @@ int main(int argc, wchar_t* argv[])
        try \r
        {\r
                // Configure environment properties from configuration.\r
-               caspar::env::configure(L"casparcg.config");\r
+               env::configure(L"casparcg.config");\r
                                \r
-               caspar::log::set_log_level(caspar::env::properties().get(L"configuration.log-level", L"debug"));\r
+               log::set_log_level(env::properties().get(L"configuration.log-level", L"debug"));\r
 \r
        #ifdef _DEBUG\r
-               if(caspar::env::properties().get(L"configuration.debugging.remote", false))\r
+               if(env::properties().get(L"configuration.debugging.remote", false))\r
                        MessageBox(nullptr, TEXT("Now is the time to connect for remote debugging..."), TEXT("Debug"), MB_OK | MB_TOPMOST);\r
        #endif   \r
 \r
                // Start logging to file.\r
-               caspar::log::add_file_sink(caspar::env::log_folder());                  \r
-               std::wcout << L"Logging [info] or higher severity to " << caspar::env::log_folder() << std::endl << std::endl;\r
+               log::add_file_sink(env::log_folder());                  \r
+               std::wcout << L"Logging [info] or higher severity to " << env::log_folder() << std::endl << std::endl;\r
                \r
                // Setup console window.\r
                setup_console_window();\r
@@ -229,26 +232,22 @@ int main(int argc, wchar_t* argv[])
                \r
                std::wstringstream str;\r
                boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);\r
-               boost::property_tree::write_xml(str, caspar::env::properties(), w);\r
+               boost::property_tree::write_xml(str, env::properties(), w);\r
                CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------";\r
                                \r
                {\r
                        // Create server object which initializes channels, protocols and controllers.\r
-                       caspar::server caspar_server;\r
+                       server caspar_server;\r
                                \r
+                       auto server = spl::make_shared<protocol::osc::server>(protocol::osc::server::tcp_params(5253));\r
+                       caspar_server.subscribe(server);\r
+\r
                        // Create a amcp parser for console commands.\r
-                       caspar::protocol::amcp::AMCPProtocolStrategy amcp(caspar_server.get_channels());\r
+                       protocol::amcp::AMCPProtocolStrategy amcp(caspar_server.get_channels());\r
 \r
                        // Create a dummy client which prints amcp responses to console.\r
-                       auto console_client = std::make_shared<caspar::IO::ConsoleClientInfo>();\r
+                       auto console_client = std::make_shared<IO::ConsoleClientInfo>();\r
                        \r
-                       //auto console_obs = caspar::reactive::make_observer([](const caspar::monitor::event& e)\r
-                       //{\r
-                       //      std::cout << e.path().str() << std::endl;\r
-                       //});\r
-                       //\r
-                       //caspar_server.subscribe(console_obs);\r
-\r
                        std::wstring wcmd;\r
                        while(true)\r
                        {\r