// Create an OSC bundle object for the specified binary buffer public OscBundle(byte[] buffer) { string tag; ulong timestamp = OscData.TIMESTAMP_NOW; List<OscData> parts = new List<OscData>(); if (buffer == null) { throw new ArgumentNullException("buffer", "Buffer must not be null."); } using (MemoryStream stream = new MemoryStream(buffer)) { tag = stream.ReadOscString(); if (tag != OscBundle.BUNDLE_ADDRESS) { throw new ArgumentException("Unrecognized bundle type.", "buffer"); } timestamp = (ulong)stream.ReadOscLong(); while (stream.Position < stream.Length) { int length = stream.ReadOscInt(); if (length < 0) { throw new Exception("Bundle part has invalid length (<0)."); } if (length > buffer.Length - stream.Position) { throw new Exception("Bundle part has invalid length."); } byte[] partBytes = new byte[length]; int offset = 0; while (offset < length) { int read = stream.Read(partBytes, offset, length - offset); if (read <= 0) { throw new Exception("EOF in bundle part."); } offset += read; } OscData part = OscData.FromByteArray(partBytes); if (part == null) { break; } parts.Add(part); } } this.Buffer = buffer; this.Timestamp = timestamp; this.Parts = parts.ToArray(); }
// Create an OSC message object for the specified binary buffer public OscMessage(byte[] buffer) { string address; List<object> arguments = new List<object>(); if (buffer == null) { throw new ArgumentNullException("buffer", "Buffer must not be null."); } using (MemoryStream stream = new MemoryStream(buffer)) { address = stream.ReadOscString(); if (address == null) { throw new ArgumentException("Missing address.", "buffer"); } if (address[0] != OscMessage.ADDRESS_PREFIX) { throw new ArgumentException("Invalid address.", "buffer"); } string typeTagString = stream.ReadOscString(); if (typeTagString.Length == 0 || typeTagString[0] != TYPE_PREFIX) { throw new ArgumentException("ERROR: This implementation requires the OSC type-tag string.", "buffer"); } typeTagString = typeTagString.Substring(1); // Remove prefix for (int i = 0; i < typeTagString.Length; i++) { switch (typeTagString[i]) { // OSC 1.0 types case OscMessage.TYPE_INT: arguments.Add(stream.ReadOscInt()); break; case OscMessage.TYPE_FLOAT: arguments.Add(stream.ReadOscFloat()); break; case OscMessage.TYPE_STRING: arguments.Add(stream.ReadOscString()); break; case OscMessage.TYPE_BLOB: arguments.Add(stream.ReadOscBlob()); break; // OSC 1.1 types case OscMessage.TYPE_TRUE: arguments.Add((Boolean)true); break; case OscMessage.TYPE_FALSE: arguments.Add((Boolean)false); break; case OscMessage.TYPE_NULL: arguments.Add(null); break; case OscMessage.TYPE_IMPULSE: arguments.Add(typeof(Object)); break; // Not really sure how to represent an 'impulse' object case OscMessage.TYPE_TIME: arguments.Add(OscData.DateTimeFromTimestamp((ulong)stream.ReadOscLong())); break; // Non-standard/optional types case OscMessage.TYPE_SYMBOL: arguments.Add(stream.ReadOscString()); break; case OscMessage.TYPE_LONG: arguments.Add(stream.ReadOscLong()); break; case OscMessage.TYPE_DOUBLE: arguments.Add(stream.ReadOscDouble()); break; case OscMessage.TYPE_CHAR: arguments.Add((char)stream.ReadOscInt()); break; case OscMessage.TYPE_RGBA: arguments.Add(stream.ReadOscInt()); break; case OscMessage.TYPE_MIDI: arguments.Add(stream.ReadOscInt()); break; case OscMessage.TYPE_ARRAY_OPEN: break; // ignore for now case OscMessage.TYPE_ARRAY_CLOSE: break; // ignore for now default: throw new ArgumentException("Unknown OSC type tag '" + typeTagString[i] + "'", "buffer"); } } } this.Buffer = buffer; this.Address = address; this.Arguments = arguments.ToArray(); }