continue with MTC debugging
[ardour.git] / libs / midi++2 / mtc.cc
1 /*
2     Copyright (C) 2004 Paul Barton-Davis
3
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.
8
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.
13
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.
17
18     $Id$
19 */
20
21 #include <cstdlib>
22 #include <unistd.h>
23 #include <cstring>
24 #include <iostream>
25
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"
31
32 using namespace std;
33 using namespace sigc;
34 using namespace MIDI;
35
36 bool
37 Parser::possible_mtc (byte *sysex_buf, size_t msglen)
38 {
39         byte fake_mtc_time[5];
40
41         if (msglen != 10 || sysex_buf[0] != 0xf0 || sysex_buf[1] != 0x7f || sysex_buf[3] != 0x01 || sysex_buf[4] != 0x01) {
42                 return false;
43         }
44
45         /* full MTC */
46         
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
51         
52         _mtc_fps = MTC_FPS ((sysex_buf[5] & 0x60) >> 5); // fps
53         fake_mtc_time[4] = (byte) _mtc_fps;
54
55         /* wait for first quarter frame, which could indicate forwards
56            or backwards ...
57         */
58
59         reset_mtc_state ();
60
61         /* emit signals */
62
63         mtc (*this, &sysex_buf[1], msglen - 1);
64         mtc_time (fake_mtc_time, true);
65         mtc_status (MTC_Stopped);
66
67         return true;
68 }
69
70 void
71 Parser::reset_mtc_state ()
72 {
73         _mtc_forward = false;
74         _mtc_running = MTC_Stopped;
75         _mtc_locked = false;
76         expected_mtc_quarter_frame_code = 0;
77         memset (_mtc_time, 0, sizeof (_mtc_time));
78         memset (_qtr_mtc_time, 0, sizeof (_mtc_time));
79         consecutive_qtr_frame_cnt = 0;
80         last_qtr_frame = 0;
81 }
82
83 void
84 Parser::process_mtc_quarter_frame (byte *msg)
85 {
86         int which_quarter_frame = (msg[1] & 0xf0) >> 4;
87
88         /* Is it an expected frame?  
89            Remember, the first can be frame 7 or frame 0, 
90            depending on the direction of the MTC generator ...
91         */
92
93 #ifdef DEBUG_MTC
94          cerr << "MTC: (state = " << _mtc_running << ") " 
95               << which_quarter_frame << " vs. " << expected_mtc_quarter_frame_code
96               << " consecutive ? " << consecutive_qtr_frame_cnt
97               << endl;
98 #endif
99
100         if (_mtc_running == MTC_Stopped) {
101         
102                 /* we are stopped but are seeing qtr frame messages */
103
104                 if (consecutive_qtr_frame_cnt == 0) {
105
106                         /* first quarter frame */
107
108                         if (which_quarter_frame != 0 && which_quarter_frame != 7) {
109                                 
110                                 last_qtr_frame = which_quarter_frame;
111                                 consecutive_qtr_frame_cnt++;
112                         }
113                         
114                         // cerr << "first seen qframe = " << (int) last_qtr_frame << endl;
115
116                         return;
117
118                 } else if (consecutive_qtr_frame_cnt == 1) {
119
120                         /* third quarter frame */
121                         
122                         // cerr << "second seen qframe = " << (int) which_quarter_frame << endl;
123
124                         if (last_qtr_frame < which_quarter_frame) {
125                                 _mtc_running = MTC_Forward;
126                         } else if (last_qtr_frame > which_quarter_frame) {
127                                 _mtc_running = MTC_Backward;
128                         }
129                         
130                         mtc_status (_mtc_running);
131                 } 
132
133                 switch (_mtc_running) {
134                 case MTC_Forward:
135                         if (which_quarter_frame == 7) {
136                                 expected_mtc_quarter_frame_code = 0;
137                         } else {
138                                 expected_mtc_quarter_frame_code = which_quarter_frame + 1;
139                         }
140                         break;
141
142                 case MTC_Backward:
143                         if (which_quarter_frame == 0) {
144                                 expected_mtc_quarter_frame_code = 7;
145                                 
146                         } else {
147                                 expected_mtc_quarter_frame_code = which_quarter_frame - 1;
148                         }
149                         break;
150
151                 case MTC_Stopped:
152                         break;
153                 }
154                 
155         } else {
156                 
157                 /* already running */
158
159 // for testing bad MIDI connections etc.
160 //              if ((random() % 500) < 10) {
161
162                 if (which_quarter_frame != expected_mtc_quarter_frame_code) {
163
164                         consecutive_qtr_frame_cnt = 0;
165
166 #ifdef DEBUG_MTC
167                         cerr << "MTC: (state = " << _mtc_running << ") " 
168                              << which_quarter_frame << " vs. " << expected_mtc_quarter_frame_code << endl;
169 #endif
170
171                         /* tell listener(s) that we skipped. if they return
172                            true, just ignore this in terms of it being an error.
173                         */
174
175                         if (1) { /* mtc_skipped () */
176
177                                 /* no error, reset next expected frame */
178
179                                 switch (_mtc_running) {
180                                 case MTC_Forward:
181                                         if (which_quarter_frame == 7) {
182                                                 expected_mtc_quarter_frame_code = 0;
183                                         } else {
184                                                 expected_mtc_quarter_frame_code = which_quarter_frame + 1;
185                                         }
186                                         break;
187
188                                 case MTC_Backward:
189                                         if (which_quarter_frame == 0) {
190                                                 expected_mtc_quarter_frame_code = 7;
191                                                 
192                                         } else {
193                                                 expected_mtc_quarter_frame_code = which_quarter_frame - 1;
194                                         }
195                                         break;
196
197                                 case MTC_Stopped:
198                                         break;
199                                 }
200
201 #ifdef DEBUG_MTC
202                                 cerr << "SKIPPED, next expected = " << expected_mtc_quarter_frame_code << endl;
203 #endif                          
204                                 return;
205                         }
206
207                         /* go back to waiting for the first frame */
208
209                         expected_mtc_quarter_frame_code = 0;
210                         memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
211
212                         _mtc_running = MTC_Stopped;
213                         _mtc_locked = false;
214                         mtc_status (MTC_Stopped);
215                         
216                         return;
217
218                 } else {
219
220                         /* received qtr frame matched expected */
221                         consecutive_qtr_frame_cnt++;
222
223                 }
224         }
225
226         /* time code is looking good */
227
228 #ifdef DEBUG_MTC
229         cerr << "for quarter frame " << which_quarter_frame << " byte = " << hex << (int) msg[1] << dec << endl;
230 #endif
231
232         switch (which_quarter_frame) {
233         case 0: // frames LS nibble
234                 _qtr_mtc_time[0] |= msg[1] & 0xf;
235                 break;
236
237         case 1:  // frames MS nibble
238                 _qtr_mtc_time[0] |= (msg[1] & 0xf)<<4;
239                 break;
240
241         case 2: // seconds LS nibble
242                 _qtr_mtc_time[1] |= msg[1] & 0xf;
243                 break;
244
245         case 3: // seconds MS nibble
246                 _qtr_mtc_time[1] |= (msg[1] & 0xf)<<4;
247                 break;
248
249         case 4: // minutes LS nibble
250                 _qtr_mtc_time[2] |= msg[1] & 0xf;
251                 break;
252
253         case 5: // minutes MS nibble
254                 _qtr_mtc_time[2] |= (msg[1] & 0xf)<<4;
255                 break;
256                 
257         case 6: // hours LS nibble
258                 _qtr_mtc_time[3] |= msg[1] & 0xf;
259                 break;
260
261         case 7: 
262                 
263                 /* last quarter frame msg has the MS bit of
264                    the hour in bit 0, and the SMPTE FPS type
265                    in bits 5 and 6 
266                 */
267                 
268                 _qtr_mtc_time[3] |= ((msg[1] & 0x1) << 4);
269                 _mtc_fps = MTC_FPS ((msg[1] & 0x6) >> 1);
270                 _qtr_mtc_time[4] = _mtc_fps;
271                 break;
272
273         default:
274                 /*NOTREACHED*/
275                 break;
276
277         } 
278         
279         mtc_qtr (*this, which_quarter_frame); /* EMIT_SIGNAL */
280
281         // mtc (*this, &msg[1], msglen - 1);
282
283         switch (_mtc_running) {
284         case MTC_Forward:
285                 if ((which_quarter_frame == 7)) {
286                         
287                         /* we've reached the final of 8 quarter frame messages.
288                            store the time, reset the pending time holder,
289                            and signal anyone who wants to know the time.
290                         */
291                         
292                         if (consecutive_qtr_frame_cnt >= 8) {
293                                 memcpy (_mtc_time, _qtr_mtc_time, sizeof (_mtc_time));
294                                 memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
295                                 if (!_mtc_locked) {
296                                         _mtc_locked = true;
297                                 }
298
299                                 mtc_time (_mtc_time, false);
300                         }
301                         expected_mtc_quarter_frame_code = 0;
302                         
303                 } else {
304                         expected_mtc_quarter_frame_code = which_quarter_frame + 1;
305                 }
306                 break;
307                 
308         case MTC_Backward:
309                 if (which_quarter_frame == 0) {
310                         
311                         /* we've reached the final of 8 quarter frame messages.
312                            store the time, reset the pending time holder,
313                            and signal anyone who wants to know the time.
314                         */
315
316                         if (consecutive_qtr_frame_cnt >= 8) {
317                                 memcpy (_mtc_time, _qtr_mtc_time, sizeof (_mtc_time));
318                                 memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
319                                 if (!_mtc_locked) {
320                                         _mtc_locked = true;
321                                 }
322                                 mtc_time (_mtc_time, false);
323                         }
324
325                         expected_mtc_quarter_frame_code = 7;
326
327                 } else {
328                         expected_mtc_quarter_frame_code = which_quarter_frame - 1;
329                 }
330                 break;
331
332         default:
333                 break;
334         }
335
336 }