-- xtra OSC -- version 1.4 -- (c) 2015 Valentin Schmidt new object me, *bufferSize setDestination object me, string host, integer port send object me, object messageOrBundle startListening object me, integer port, integer asPropList, symbol cbHandler, *cbTarget stopListening object me Description (Source: Wikipedia) =========== Open Sound Control (OSC) is a protocol for networking sound synthesizers, computers, and other multimedia devices for purposes such as musical performance or Show control. Bringing the benefits of modern networking technology to the world of electronic musical instruments, OSC's advantages include interoperability, accuracy, flexibility, and enhanced organization and documentation. OSC messages consist of an Address pattern, a Type tag string, Arguments and an optional time tag. Address patterns form a hierarchical name space, reminiscent of a Unix filesystem path, or a URL. Type tag strings are a compact string representation of the argument types. Arguments are represented in binary form with 4-byte alignment. The core types supported are: - 32-bit two's complement signed integers - 32-bit IEEE floating point numbers - Null-terminated arrays of 8 bit encoded data (C-style strings) - arbitrary sized blob (e.g. audio data, or a video frame) Applications commonly employ extensions to this core set. More recently some of these extensions such as a compact Boolean type were integrated into the required core types of OSC 1.1. Function Overview ================= ---------------------------------------- new (object me, *integer bufferSize) ---------------------------------------- Optional parameter bufferSize allows to specify the bufferSize (= the number of bytes) used for send() commands. The default value is 1024, if the maximum size of data you want to send with a single send() call exceeds this value, make sure to specify an apropriate bufferSize when creating the xtra instance! Examples: ========= osc = xtra("OSC").new() osc = xtra("OSC").new(8192) -- use 8 Kb buffer ---------------------------------------- setDestination object me, string host, integer port) ---------------------------------------- Sets the target host and port used for send(). If this function is not called before using send(), "127.0.0.1" and 5500 are used. Examples: ========= osc.setDestination("192.168.0.123", 5555) osc.setDestination("localhost", 9001) ---------------------------------------- send (object me, object messageOrBundle) -> bool success ---------------------------------------- Sends a new OSC message or message bundle to target host/port previously specified via setDestination(). A bundle can be used to send multiple messages at once. In addition to individual messages bundles can also contain other bundles (no nesting limit). If the data you want send exceeds the current bufferSize - see description of new() above - the send function fails and returns FALSE, otherwise it returns TRUE. A message is specified as lingo list, the first value contains the message's "path" or "address" as string (usually starting with a slash, e.g. "/test"), a (optional) second value contains the message's arguments as list or property list. If it's a property list, the properties determine the data type tags used in the OSC message for the corresponding argument. Use lists if you only want to pass core types (integer, float, string, bytearray), otherwise use property list. A bundle is specified as lingo list, the first value contains the bundle's time code as integer or float (specify 1 for immediately). The second value is a lingo list containing multiple messages or other bundles (which might again contain bundles, and so on). The following data types are supported as properties in the arguments propLists: property -> expected lingo value type -- original core types #int32 -> #integer #float32 -> #float #string -> #string #blob -> #bytearray -- extensions #array -> #list or #propList (list of values of any supported type other than "array", i.e. nested arrays are NOT supported!) #bool -> #integer #char -> #integer #double -> #float #infinitum -> #void (ignored, so actually can be anything) #int64 -> #float (float used to allow values beyond maxinteger limit) #midi -> #float (float used to allow values beyond maxinteger limit) #nil -> #void (ignored, so actually can be anything) #rgba -> #float (float used to allow values beyond maxinteger limit) #time -> #float (float used to allow values beyond maxinteger limit) Examples: ========= -- send message without arguments put $.osc.send(["/test"]) -- send message with int32 and float32 argument put $.osc.send(["/test", [#int32:23, #float32:66.5]]) -- send message with string and blob argument put $.osc.send(["/test", [#string:"Hello", #blob:bytearray("World!")]]) -- send message with arguments as linear list (core types only) put $.osc.send(["/test", [23, 66.5, "Hello", bytearray("World!"), VOID]]) -- send message with various arguments put $.osc.send(["/test", [#bool:1, #double:23.0, #int64:23.0, #char:65, #nil:void, #infinitum:void]]) -- send message with a rgba color argument r = 1 g = 2 b = 3 a = 255 put $.osc.send(["/test", [#rgba:256.0*256*256*r + 256*256*g + 256*b + a]]) -- send message with a time tag now = $.date.dateToTimestamp() * 4294967296.0 -- 4294967296 = 0x100000000 put $.osc.send(["/test7", [#time: now]]) -- send 2 arrays put $.osc.send(["/test", [#array: [1,2,4,5,6,7], #array:["hello","world"]]]) -- send array with explicit types (propList) put $.osc.send(["/test", [#array: [#int64:111, #int64:222]]]) -- send bundle with 3 messages bundle = [1, []] -- timecode 1 = immediately bundle[2].add(["/bundlemsg1"]) bundle[2].add(["/bundlemsg2", ["Hello World!"]]) bundle[2].add(["/bundlemsg3", [#int32:23, #float32:66.5]]) put $.osc.send(bundle) -- send nested bundle (bundle inside another bundle) bundle = [1, []] -- timecode 1 = immediately bundle[2].add(["/bundlemsg1"]) bundle[2].add(["/bundlemsg2", ["Hello World!"]]) bundle[2].add(["/bundlemsg3", [#int32:23, #float32:66.5]]) innerBundle = [1, []] -- timecode 1 = immediately innerBundle[2].add(["/innerbundlemsg1"]) innerBundle[2].add(["/innerbundlemsg2", [#int32:23, #float32:66.5]]) bundle[2].add(innerBundle) put $.osc.send(bundle) ---------------------------------------- startListening (object me, integer port, bool asPropList, symbol cbHandler, *cbTarget) -> true|string ---------------------------------------- Starts listening to OSC messages on the specified port. All received messages are forwared to the specified callback handler (of target object , if specified, otherwise a "global" handler in a movie script is expected). The callback receives 2 parameters, the OSC message's address as string ("e.g. "/test"), and the message's arguments as list (if asPropList=false) or propList (if asPropList=true). All elements in this arguments list have type #integer, #float, #string or #bytearray). If you need to know the original datatype (e.g. if it was "float32" or "double", or if it was "char" or "int32"), set asPropList to true, then each element in the list has a key (string property) that shows the original data type. Obviously the same data type can occur multiple times in the arguments, so use index access, not property access to handle the data). If a message bundle was sent, the callback receives 2 arguments when the bundle starts, and <#bundleend, 0> when the bundle ends. Since bundles can be nested, it's up to you keep track of the bundle start/end message stack. Returns true if successful, otherwise an error description as string. Examples: ========= err = osc.startListening(5500, true, #slotOscReceive) if stringP(err) then put err -- in movie script on slotOscReceive (address, args) put address, args end gReceiver = script("OSCReceiver").new() err = osc.startListening(5500, false, #slotReceive, gReceiver) if stringP(err) then put err -- in parent script "OSCReceiver" on slotReceive (me, address, args) put address, args end ---------------------------------------- stopListening (object me) ---------------------------------------- Stops listening to OSC messages. Example: ======== osc.stopListening()