1 module osc.timetag;
2 
3 import std.datetime;
4 import std.conv;
5 import std.bitmanip;
6 
7 
8 
9 /// Immediate time tag.
10 ///
11 immutable ubyte[] immediateTimeTag = [0, 0, 0, 0, 0, 0, 0, 1];
12 /// SysTime used for using the immediate time tag.
13 immutable SysTime immediateSysTime = SysTime( DateTime( 1900, 1, 1 ), UTC( ) );
14 
15 
16 
17 /// Converts a SysTime to an OSC timetag.
18 ///
19 ubyte[] toOSC( SysTime st )
20 {
21 	if( st == immediateSysTime )
22 		return immediateTimeTag.dup;
23 
24 	immutable timestamp = st - SysTime( DateTime( 1900, 1, 1 ), UTC( ) );
25 
26 	immutable ipart = timestamp.total!"seconds";
27 	immutable fpart = timestamp.total!"nsecs"%(10^^9);
28 
29 	ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
30 	buffer.write!uint( ipart.to!uint, 0 );
31 	buffer.write!uint( fpart.to!uint, 4 );
32 
33 	return buffer;
34 }
35 
36 /// Converts an OSC timetag to a SysTime.
37 ///
38 SysTime toSysTime( const(ubyte[]) buf )
39 {
40 	if( buf == immediateTimeTag )
41 		return immediateSysTime;
42 
43 	immutable ipart = buf.peek!uint( 0 );
44 	immutable fpart = buf.peek!uint( 4 );
45 
46 	return SysTime( DateTime( 1900, 1, 1 ), UTC( ) ) 
47 		+ dur!"seconds"(ipart) 
48 		+ dur!"nsecs"(fpart);
49 }
50 
51 
52 /// Checks if the given SysTime is an immediate time tag.
53 ///
54 bool isImmediate( in const(SysTime) st )
55 {
56 	return st == immediateSysTime;
57 }
58 
59 
60 
61 unittest
62 {
63 	assert( immediateSysTime.isImmediate );
64 
65 	assert( immediateSysTime.toOSC == immediateTimeTag );
66 	assert( immediateTimeTag.toSysTime == immediateSysTime );
67 }