|
| 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 | +} |
0 commit comments