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