Skip to content

Commit 8114bf7

Browse files
authored
Merge pull request #13 from MrExplode/timecode
Added timecode support
2 parents b18eda6 + 6c64f4f commit 8114bf7

File tree

2 files changed

+248
-0
lines changed

2 files changed

+248
-0
lines changed
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package ch.bildspur.artnet.packets;
2+
3+
/**
4+
* For further information about the ArtNet timecode packet, read <a href="https://art-net.org.uk/structure/time-keeping-triggering/arttimecode/">this</a>.
5+
*
6+
* @author <a href="https://mrexplode.github.io">MrExplode</a>
7+
*
8+
*/
9+
public class ArtTimePacket extends ArtNetPacket {
10+
11+
private int frames;
12+
private int seconds;
13+
private int minutes;
14+
private int hours;
15+
private int type;
16+
17+
public long encoded;
18+
19+
public ArtTimePacket() {
20+
super(PacketType.ART_TIMECODE);
21+
setData(new byte[19]);
22+
setHeader();
23+
setProtocol();
24+
}
25+
26+
27+
@Override
28+
public boolean parse(byte[] raw) {
29+
setData(raw);
30+
frames = data.getInt8(14);
31+
seconds = data.getInt8(15);
32+
minutes = data.getInt8(16);
33+
hours = data.getInt8(17);
34+
type = data.getInt8(18);
35+
encoded = encode(hours, minutes, seconds, frames, type);
36+
return true;
37+
}
38+
39+
/**
40+
* Increment the timecode by 1.
41+
*/
42+
public void increment() {
43+
encoded++;
44+
int[] val = decode(encoded, type);
45+
frames = val[3];
46+
seconds = val[2];
47+
minutes = val[1];
48+
hours = val[0];
49+
updateData();
50+
}
51+
52+
/**
53+
* Decrement the timecode by 1;
54+
*/
55+
public void decrement() {
56+
encoded--;
57+
int[] val = decode(encoded, type);
58+
frames = val[3];
59+
seconds = val[2];
60+
minutes = val[1];
61+
hours = val[0];
62+
updateData();
63+
}
64+
65+
/**
66+
* Convert the separate values into one long value, for easy increment/decrement
67+
*
68+
* @param hour number of hours
69+
* @param min number of minutes
70+
* @param sec number of seconds
71+
* @param frame number of frames
72+
* @param frameType the type of the timecode
73+
* @return the encoded time value
74+
*/
75+
public long encode(int hour, int min, int sec, int frame, int frameType) {
76+
int framerate = 30;
77+
switch (frameType) {
78+
case 0:
79+
//film
80+
framerate = 24;
81+
break;
82+
case 1:
83+
//ebu
84+
framerate = 25;
85+
break;
86+
case 2:
87+
//df
88+
throw new IllegalArgumentException("DF type not implemented! Do you wanna implement it yourself?");
89+
case 3:
90+
//smtpe
91+
framerate = 30;
92+
break;
93+
default:
94+
framerate = 30;
95+
break;
96+
}
97+
98+
int hour_fr = hour * 60 * 60 * framerate;
99+
int min_fr = min * 60 * framerate;
100+
int sec_fr = sec * framerate;
101+
102+
return hour_fr + min_fr + sec_fr + frame;
103+
}
104+
105+
/**
106+
* Decodes the encoded timecode value.<br>
107+
* Elements of the returning int array:<br>
108+
* 0: hour<br>
109+
* 1: minute<br>
110+
* 2: second<br>
111+
* 3: frame<br>
112+
*
113+
* @param frames the encoded time data
114+
* @param frameType the type of the timecode
115+
* @return the decoded time values
116+
*/
117+
public int[] decode(long frames, int frameType) {
118+
int framerate = 30;
119+
switch (frameType) {
120+
case 0:
121+
framerate = 24;
122+
break;
123+
case 1:
124+
framerate = 25;
125+
break;
126+
case 2:
127+
throw new IllegalArgumentException("DF type not implemented! Do you wanna implement it yourself?");
128+
case 3:
129+
framerate = 30;
130+
break;
131+
default:
132+
framerate = 30;
133+
break;
134+
}
135+
136+
int[] dec = new int[4];
137+
138+
int hour = ((int) frames / 60 / 60 / framerate);
139+
frames = frames - (hour * 60 * 60 * framerate);
140+
dec[0] = hour;
141+
142+
int min = ((int) frames / 60 / framerate);
143+
frames = frames - (min * 60 * framerate);
144+
dec[1] = min;
145+
146+
int sec = ((int) frames / framerate);
147+
frames = frames - (sec * framerate);
148+
dec[2] = sec;
149+
150+
int frame = (int) frames;
151+
dec[3] = frame;
152+
153+
return dec;
154+
}
155+
156+
public void setTime(int hour, int min, int sec, int frame) {
157+
this.hours = hour;
158+
this.minutes = min;
159+
this.seconds = sec;
160+
this.frames = frame;
161+
this.encoded = encode(hours, minutes, seconds, frames, type);
162+
updateData();
163+
}
164+
165+
/**
166+
* @return the number of frames
167+
*/
168+
public int getFrames() {
169+
return frames;
170+
}
171+
172+
173+
public void setFrames(int frames) {
174+
this.frames = frames & 0x0f;
175+
this.encoded = encode(hours, minutes, seconds, this.frames, type);
176+
updateData();
177+
}
178+
179+
/**
180+
* @return the number of seconds
181+
*/
182+
public int getSeconds() {
183+
return seconds;
184+
}
185+
186+
187+
public void setSeconds(int seconds) {
188+
this.seconds = seconds;
189+
this.encoded = encode(hours, minutes, this.seconds, frames, type);
190+
updateData();
191+
}
192+
193+
/**
194+
* @return the number of minutes
195+
*/
196+
public int getMinutes() {
197+
return minutes;
198+
}
199+
200+
201+
public void setMinutes(int minutes) {
202+
this.minutes = minutes;
203+
this.encoded = encode(hours, this.minutes, seconds, frames, type);
204+
updateData();
205+
}
206+
207+
/**
208+
* @return the number of hours
209+
*/
210+
public int getHours() {
211+
return hours;
212+
}
213+
214+
215+
public void setHours(int hours) {
216+
this.hours = hours;
217+
this.encoded = encode(this.hours, minutes, seconds, frames, type);
218+
updateData();
219+
}
220+
221+
/**
222+
* <table><caption>Formats</caption><tr><th>Type</th><th> Type value</th><th>Frame rate</th><th>Frames in second</th></tr><tr><td>Film</td><td>0</td><td>24</td><td>0-23</td></tr><tr><td>EBU</td><td>1</td><td>25</td><td>0-24</td></tr><tr><td>DF</td><td>2</td><td>29.97</td><td>0-29</td></tr><tr><td>SMTPE</td><td>3</td><td>30</td><td>0-30</td></tr></table>
223+
* @return the frame type
224+
*/
225+
public int getFrameType() {
226+
return type;
227+
}
228+
229+
/**
230+
* <table><caption>Formats</caption><tr><th>Type</th><th> Type value</th><th>Frame rate</th><th>Frames in second</th></tr><tr><td>Film</td><td>0</td><td>24</td><td>0-23</td></tr><tr><td>EBU</td><td>1</td><td>25</td><td>0-24</td></tr><tr><td>DF</td><td>2</td><td>29.97</td><td>0-29</td></tr><tr><td>SMTPE</td><td>3</td><td>30</td><td>0-30</td></tr></table>
231+
* @param type the frame type
232+
*/
233+
public void setFrameType(int type) {
234+
this.type = type;
235+
this.encoded = encode(hours, minutes, seconds, frames, this.type);
236+
updateData();
237+
}
238+
239+
private void updateData() {
240+
data.setInt8(frames, 14);
241+
data.setInt8(seconds, 15);
242+
data.setInt8(minutes, 16);
243+
data.setInt8(hours, 17);
244+
data.setInt8(type, 18);
245+
}
246+
247+
}

src/main/java/ch/bildspur/artnet/packets/PacketType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public enum PacketType {
2424
ART_POLL(0x2000, ArtPollPacket.class),
2525
ART_POLL_REPLY(0x2100, ArtPollReplyPacket.class),
2626
ART_OUTPUT(0x5000, ArtDmxPacket.class),
27+
ART_TIMECODE(0x9700, ArtTimePacket.class),
2728
ART_ADDRESS(0x6000, null),
2829
ART_INPUT(0x7000, null),
2930
ART_TOD_REQUEST(0x8000, null),

0 commit comments

Comments
 (0)