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