2 Copyright (C) 2004 Paul Barton-Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <midi++/types.h>
27 #include <midi++/parser.h>
28 #include <midi++/port.h>
29 #include <midi++/mmc.h>
30 #include <pbd/transmitter.h>
37 Parser::possible_mtc (byte *sysex_buf, size_t msglen)
39 byte fake_mtc_time[5];
41 if (msglen != 10 || sysex_buf[0] != 0xf0 || sysex_buf[1] != 0x7f || sysex_buf[3] != 0x01 || sysex_buf[4] != 0x01) {
47 fake_mtc_time[0] = sysex_buf[8]; // frames
48 fake_mtc_time[1] = sysex_buf[7]; // minutes
49 fake_mtc_time[2] = sysex_buf[6]; // seconds
50 fake_mtc_time[3] = (sysex_buf[5] & 0x1f); // hours
52 _mtc_fps = MTC_FPS ((sysex_buf[5] & 0x60) >> 5); // fps
54 fake_mtc_time[4] = (byte) _mtc_fps;
56 /* wait for first quarter frame, which could indicate forwards
64 mtc (*this, &sysex_buf[1], msglen - 1);
65 mtc_time (fake_mtc_time, true);
66 mtc_status (MTC_Stopped);
72 Parser::reset_mtc_state ()
75 _mtc_running = MTC_Stopped;
77 expected_mtc_quarter_frame_code = 0;
78 memset (_mtc_time, 0, sizeof (_mtc_time));
79 memset (_qtr_mtc_time, 0, sizeof (_mtc_time));
80 consecutive_qtr_frame_cnt = 0;
85 Parser::process_mtc_quarter_frame (byte *msg)
87 int which_quarter_frame = (msg[1] & 0xf0) >> 4;
89 /* Is it an expected frame?
90 Remember, the first can be frame 7 or frame 0,
91 depending on the direction of the MTC generator ...
95 cerr << "MTC: (state = " << _mtc_running << ") "
96 << which_quarter_frame << " vs. " << expected_mtc_quarter_frame_code
97 << " consecutive ? " << consecutive_qtr_frame_cnt
101 if (_mtc_running == MTC_Stopped) {
103 /* we are stopped but are seeing qtr frame messages */
105 if (consecutive_qtr_frame_cnt == 0) {
107 /* first quarter frame */
109 if (which_quarter_frame != 0 && which_quarter_frame != 7) {
111 last_qtr_frame = which_quarter_frame;
112 consecutive_qtr_frame_cnt++;
115 // cerr << "first seen qframe = " << (int) last_qtr_frame << endl;
119 } else if (consecutive_qtr_frame_cnt == 1) {
121 /* third quarter frame */
123 // cerr << "second seen qframe = " << (int) which_quarter_frame << endl;
125 if (last_qtr_frame < which_quarter_frame) {
126 _mtc_running = MTC_Forward;
127 } else if (last_qtr_frame > which_quarter_frame) {
128 _mtc_running = MTC_Backward;
131 mtc_status (_mtc_running);
134 switch (_mtc_running) {
136 if (which_quarter_frame == 7) {
137 expected_mtc_quarter_frame_code = 0;
139 expected_mtc_quarter_frame_code = which_quarter_frame + 1;
144 if (which_quarter_frame == 0) {
145 expected_mtc_quarter_frame_code = 7;
148 expected_mtc_quarter_frame_code = which_quarter_frame - 1;
158 /* already running */
160 // for testing bad MIDI connections etc.
161 // if ((random() % 500) < 10) {
163 if (which_quarter_frame != expected_mtc_quarter_frame_code) {
165 consecutive_qtr_frame_cnt = 0;
168 cerr << "MTC: (state = " << _mtc_running << ") "
169 << which_quarter_frame << " vs. " << expected_mtc_quarter_frame_code << endl;
172 /* tell listener(s) that we skipped. if they return
173 true, just ignore this in terms of it being an error.
176 if (1) { /* mtc_skipped () */
178 /* no error, reset next expected frame */
180 switch (_mtc_running) {
182 if (which_quarter_frame == 7) {
183 expected_mtc_quarter_frame_code = 0;
185 expected_mtc_quarter_frame_code = which_quarter_frame + 1;
190 if (which_quarter_frame == 0) {
191 expected_mtc_quarter_frame_code = 7;
194 expected_mtc_quarter_frame_code = which_quarter_frame - 1;
203 cerr << "SKIPPED, next expected = " << expected_mtc_quarter_frame_code << endl;
208 /* go back to waiting for the first frame */
210 expected_mtc_quarter_frame_code = 0;
211 memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
213 _mtc_running = MTC_Stopped;
215 mtc_status (MTC_Stopped);
221 /* received qtr frame matched expected */
222 consecutive_qtr_frame_cnt++;
227 /* time code is looking good */
229 switch (which_quarter_frame) {
230 case 0: // frames LS nibble
231 _qtr_mtc_time[0] |= msg[1] & 0xf;
234 case 1: // frames MS nibble
235 _qtr_mtc_time[0] |= (msg[1] & 0xf)<<4;
238 case 2: // seconds LS nibble
239 _qtr_mtc_time[1] |= msg[1] & 0xf;
242 case 3: // seconds MS nibble
243 _qtr_mtc_time[1] |= (msg[1] & 0xf)<<4;
246 case 4: // minutes LS nibble
247 _qtr_mtc_time[2] |= msg[1] & 0xf;
250 case 5: // minutes MS nibble
251 _qtr_mtc_time[2] |= (msg[1] & 0xf)<<4;
254 case 6: // hours LS nibble
255 _qtr_mtc_time[3] |= msg[1] & 0xf;
260 /* last quarter frame msg has the MS bit of
261 the hour in bit 0, and the SMPTE FPS type
265 _qtr_mtc_time[3] |= ((msg[1] & 0x1) << 4);
266 _mtc_fps = MTC_FPS ((msg[1] & 0x6) >> 1);
267 _qtr_mtc_time[4] = _mtc_fps;
276 mtc_qtr (*this); /* EMIT_SIGNAL */
278 // mtc (*this, &msg[1], msglen - 1);
280 switch (_mtc_running) {
282 if ((which_quarter_frame == 7)) {
284 /* we've reached the final of 8 quarter frame messages.
285 store the time, reset the pending time holder,
286 and signal anyone who wants to know the time.
289 if (consecutive_qtr_frame_cnt >= 8) {
290 memcpy (_mtc_time, _qtr_mtc_time, sizeof (_mtc_time));
291 memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
295 mtc_time (_mtc_time, false);
297 expected_mtc_quarter_frame_code = 0;
300 expected_mtc_quarter_frame_code = which_quarter_frame + 1;
305 if (which_quarter_frame == 0) {
307 /* we've reached the final of 8 quarter frame messages.
308 store the time, reset the pending time holder,
309 and signal anyone who wants to know the time.
312 if (consecutive_qtr_frame_cnt >= 8) {
313 memcpy (_mtc_time, _qtr_mtc_time, sizeof (_mtc_time));
314 memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
318 mtc_time (_mtc_time, false);
321 expected_mtc_quarter_frame_code = 7;
324 expected_mtc_quarter_frame_code = which_quarter_frame - 1;