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 }