Example #1
0
        // Create a binary OSC bundle from the specified parts
        public OscBundle(ulong timestamp, IEnumerable<OscData> parts)
        {
            // Check parameters are valid
            if (parts == null) { throw new ArgumentNullException("parts", "Parts must not be null."); }

            // Store parameters
            this.Timestamp = timestamp;
            int numParts = 0;
            foreach (OscData part in parts) { numParts++; }
            this.Parts = new OscData[numParts];
            numParts = 0;
            foreach (OscData part in parts) { this.Parts[numParts++] = part; }

            // Memory stream for OSC bundle
            using (MemoryStream stream = new MemoryStream())
            {
                // An OSC Bundle consists of the OSC-string "#bundle" (null-terminated)
                stream.WriteOscString(OscBundle.BUNDLE_ADDRESS);

                // ...followed by an OSC Time Tag (The OSC-timetag is a 64-bit fixed point time tag, high 32 bits are seconds since 1/1/1900, low 32 bits are fractions of second)
                stream.WriteOscLong((long)this.Timestamp);

                // ...followed by zero or more OSC Bundle Elements.
                foreach (OscData part in Parts)
                {
                    // Check part is valid
                    if (part == null) { throw new ArgumentNullException("parts", "None of the parts may be null."); }
                    if (part.Buffer == null) { throw new ArgumentException("None of the parts may have null data.", "parts"); }
                    if (part.Buffer.Length % 4 != 0) { throw new ArgumentException("Every part must have a length that is a multiple of 4.", "parts"); }

                    // An OSC Bundle Element consists of its size (b-e int-32, multiple of 4)...
                    stream.WriteOscInt(part.Buffer.Length);

                    // ...and its contents
                    stream.Write(part.Buffer, 0, part.Buffer.Length);
                }

                // Return bundle bytes
                Buffer = stream.ToArray();
            }
        }
Example #2
0
        // Create a binary OSC message for the specified address from the specified parameters
        public OscMessage(string address, IEnumerable<object> arguments)
        {
            // Check parameters are valid
            if (address == null) { throw new ArgumentNullException("address", "Address must not be null."); }
            if (!address.StartsWith(OscMessage.ADDRESS_PREFIX.ToString())) { throw new ArgumentException("Address must begin with a forward-slash ('/').", "address"); }
            if (address.IndexOfAny(OscMessage.ADDRESS_DISALLOWED_CHARS) >= 0) { throw new ArgumentException("Address contains one or more invalid characters.", "address"); }
            if (arguments == null) { throw new ArgumentNullException("arguments", "Arguments array must not be null."); }

            // Store address and arguments
            this.Address = address;
            int numArguments = 0;
            foreach (object o in arguments) { numArguments++; }
            this.Arguments = new object[numArguments];
            numArguments = 0;
            foreach (object o in arguments) { this.Arguments[numArguments++] = o; }

            // Memory stream for OSC message
            using (MemoryStream stream = new MemoryStream())
            {
                // Write address
                stream.WriteOscString(address);

                // Write param type tag:    ",iiii\0" (i = 32-bit integer)
                StringBuilder typeTag = new StringBuilder();
                typeTag.Append(',');                                  // comma indicates start of parameter type tag list
                foreach (object o in Arguments)
                {
                    if (o is SByte || o is Byte || o is Int16 || o is UInt16 || o is Int32 || o is UInt32) { typeTag.Append(OscMessage.TYPE_INT); } // signed two's complement int32 (big-endian)
                    else if (o is Int64 || o is UInt64) { typeTag.Append(OscMessage.TYPE_LONG); }   // (non-standard long int-64 type)
                    else if (o is Single) { typeTag.Append(OscMessage.TYPE_FLOAT); }                // IEEE 32-bit float (big-endian)
                    else if (o is Double) { typeTag.Append(OscMessage.TYPE_DOUBLE); }               // (non-standard double type)
                    else if (o is Char) { typeTag.Append(OscMessage.TYPE_CHAR); }                   // (non-standard char type)
                    else if (o is String) { typeTag.Append(OscMessage.TYPE_STRING); }               // ASCII null-terminated string
                    else if (o is byte[]) { typeTag.Append(OscMessage.TYPE_BLOB); }                 // blob (byte[]) with size
                    else if (o is Boolean) { typeTag.Append((bool)o ? OscMessage.TYPE_TRUE : OscMessage.TYPE_FALSE); }  // true or false type
                    else if (o == null) { typeTag.Append(OscMessage.TYPE_NULL); }                   // null
                    else if (o is DateTime) { typeTag.Append(OscMessage.TYPE_TIME); }               // time tag (RFC-1305 NTP Timestamp format - upper 32 bits is the number of seconds since midnight on January 1, 1900, lower 32 bits specify the fractional part of a second)
                    else if (o.Equals(typeof(Object))) { typeTag.Append(OscMessage.TYPE_IMPULSE); } // impulse (not sure of a good .NET representation for this)
                    else if (o is Array) { throw new ArgumentException("Arrays not yet supported.", "arguments"); }
                    else { throw new ArgumentException("One or more arguments are of an unhandled type.", "arguments"); }
                }
                stream.WriteOscString(typeTag.ToString());

                // Values           (all values are big-endian and will be padded to 4 bytes)
                foreach (object o in Arguments)
                {
                    if      (o is SByte)  { stream.WriteOscInt((int)(SByte)o); }
                    else if (o is Byte)   { stream.WriteOscInt((int)(Byte)o); }
                    else if (o is Int16)  { stream.WriteOscInt((int)(Int16)o); }
                    else if (o is UInt16) { stream.WriteOscInt((int)(UInt16)o); }
                    else if (o is Int32)  { stream.WriteOscInt((int)(Int32)o); }
                    else if (o is UInt32) { stream.WriteOscInt((int)(UInt32)o); }
                    else if (o is Int64)  { stream.WriteOscLong((long)(Int64)o); }      // (non-standard long int-64 type)
                    else if (o is UInt64) { stream.WriteOscLong((long)(UInt64)o); }     // (non-standard long int-64 type)
                    else if (o is Single) { stream.WriteOscFloat((float)(Single)o); }
                    else if (o is Double) { stream.WriteOscDouble((float)(Double)o); }  // (non-standard double type)
                    else if (o is Char)   { stream.WriteOscInt((int)(Char)o); }         // (non-standard char type, written as int-32)
                    else if (o is String) { stream.WriteOscString((String)o); }
                    else if (o is byte[]) { stream.WriteOscBlob((byte[])o); }
                    else if (o is Boolean) { }                                          // true or false type -- neither has data
                    else if (o == null) { }                                             // null type -- no data
                    else if (o is DateTime) { stream.WriteOscLong((long)OscData.TimestampFromDateTime((DateTime)o)); }
                    else if (o.Equals(typeof(Object))) { }                              // impulse (not sure of a good .NET representation for this)
                    else if (o is Array) { throw new ArgumentException("Arrays not yet supported.", "arguments"); }
                    else { throw new ArgumentException("One or more arguments are of an unhandled type.", "arguments"); }
                }

                // Return message bytes
                Buffer = stream.ToArray();
            }
        }