1 module osc.bundle; 2 3 import std.range; 4 import std.conv; 5 import std.algorithm; 6 import std.datetime; 7 8 import osc.address; 9 import osc.timetag; 10 import osc.typetag; 11 import osc.oscstring; 12 import osc.message; 13 import osc.packet; 14 15 16 17 /// A bundle of multiple OSC messages. 18 /// 19 class OSCBundle : OSCPacket 20 { 21 22 private { 23 SysTime _timetag; 24 25 } 26 27 /// List of messages contained in the bundle. 28 /// 29 OSCMessage[] messages; 30 31 32 33 /// Constructs a new OSC bundle. 34 /// 35 this( SysTime timetag ) 36 { 37 _timetag = timetag; 38 } 39 40 41 42 /// Gets the timetag associated to this bundle. 43 /// 44 @property const(SysTime) timetag( ) const 45 { 46 return _timetag; 47 } 48 49 /// Sets the timetag associated to this bundle. 50 /// 51 @property void timetag( SysTime v ) 52 { 53 _timetag = v; 54 } 55 56 57 58 @property override ubyte[] data( ) const 59 { 60 ubyte[] res; 61 62 res ~= "#bundle".toOSC; 63 res ~= _set!SysTime( _timetag ); 64 65 foreach( msg; messages ) 66 { 67 ubyte[] data = msg.data; 68 69 res ~= _set!int( cast(int)data.length ); 70 res ~= data; 71 72 if( res.length % 4 != 0 ) 73 { 74 res ~= 0 75 .repeat( 4 - res.length % 4 ) 76 .map!( x => cast(ubyte) x ) 77 .array; 78 } 79 } 80 81 return res; 82 } 83 84 } 85 86 87 unittest 88 { 89 immutable ubyte[] raw = [ 90 0x23, 0x62, 0x75, 0x6e, 91 0x64, 0x6c, 0x65, 0x00, 92 0x00, 0x00, 0x00, 0x00, 93 0x00, 0x00, 0x00, 0x01, 94 0x00, 0x00, 0x00, 0x20, 95 0x2f, 0x6f, 0x73, 0x63, 96 0x69, 0x6c, 0x6c, 0x61, 97 0x74, 0x6f, 0x72, 0x2f, 98 0x34, 0x2f, 0x66, 0x72, 99 0x65, 0x71, 0x75, 0x65, 100 0x6e, 0x63, 0x79, 0x00, 101 0x2c, 0x66, 0x00, 0x00, 102 0x43, 0xdc, 0x00, 0x00 103 ]; 104 105 OSCBundle bundle = new OSCBundle( immediateSysTime ); 106 107 OSCMessage msg = new OSCMessage( "/oscillator/4/frequency" ); 108 msg.add!float( 440.0 ); 109 110 bundle.messages ~= msg; 111 112 assert( bundle.data == raw ); 113 }