continue with MTC debugging
[ardour.git] / libs / ardour / mtc_slave.cc
1 /*
2     Copyright (C) 2002-4 Paul 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 */
19 #include <iostream>
20 #include <errno.h>
21 #include <poll.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "pbd/error.h"
25 #include "pbd/failed_constructor.h"
26 #include "pbd/pthread_utils.h"
27
28 #include "midi++/port.h"
29 #include "ardour/debug.h"
30 #include "ardour/slave.h"
31 #include "ardour/session.h"
32 #include "ardour/audioengine.h"
33 #include "ardour/cycles.h"
34
35 #include "i18n.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace sigc;
40 using namespace MIDI;
41 using namespace PBD;
42
43 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
44         : session (s)
45 {
46         can_notify_on_unknown_rate = true;
47         did_reset_tc_format = false;
48         
49         last_mtc_fps_byte = session.get_mtc_timecode_bits ();
50
51         rebind (p);
52         reset ();
53 }
54
55 MTC_Slave::~MTC_Slave()
56 {
57         if (did_reset_tc_format) {
58                 session.config.set_timecode_format (saved_tc_format);
59         }
60 }
61
62 void
63 MTC_Slave::rebind (MIDI::Port& p)
64 {
65         for (vector<sigc::connection>::iterator i = connections.begin(); i != connections.end(); ++i) {
66                 (*i).disconnect ();
67         }
68
69         port = &p;
70
71         connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
72         connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
73         connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
74 }
75
76 void
77 MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr)
78 {
79         nframes64_t now = session.engine().frame_time();
80
81         DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2, valid-for-time? %3\n", which_qtr, now, qtr_frame_messages_valid_for_time));
82
83         if (qtr_frame_messages_valid_for_time) {
84
85                 if (which_qtr != 7) {
86
87                         /* leave position and speed updates for the last
88                            qtr frame message of the 8 to be taken
89                            care of in update_mtc_time(), invoked
90                            by the Parser right after this.
91                         */
92
93                         nframes_t qtr;
94                         
95                         qtr = (long) (session.frames_per_timecode_frame() / 4);
96                         mtc_frame += qtr;
97                         
98                         double speed = compute_apparent_speed (now);
99                         
100                         current.guard1++;
101                         current.position = mtc_frame;
102                         current.timestamp = now;
103                         current.speed = speed;
104                         current.guard2++;
105                 }
106
107                 last_inbound_frame = now;
108         }
109 }
110
111 void
112 MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
113 {
114         nframes64_t now = session.engine().frame_time();
115         Timecode::Time timecode;
116         TimecodeFormat tc_format;
117         bool reset_tc = true;
118         
119         DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
120         
121         timecode.hours = msg[3];
122         timecode.minutes = msg[2];
123         timecode.seconds = msg[1];
124         timecode.frames = msg[0];
125
126         last_mtc_fps_byte = msg[4];
127
128         switch (msg[4]) {
129         case MTC_24_FPS:
130                 timecode.rate = 24;
131                 timecode.drop = false;
132                 tc_format = timecode_24;
133                 can_notify_on_unknown_rate = true;
134                 break;
135         case MTC_25_FPS:
136                 timecode.rate = 25;
137                 timecode.drop = false;
138                 tc_format = timecode_25;
139                 can_notify_on_unknown_rate = true;
140                 break;
141         case MTC_30_FPS_DROP:
142                 timecode.rate = 30;
143                 timecode.drop = true;
144                 tc_format = timecode_30drop;
145                 can_notify_on_unknown_rate = true;
146                 break;
147         case MTC_30_FPS:
148                 timecode.rate = 30;
149                 timecode.drop = false;
150                 can_notify_on_unknown_rate = true;
151                 tc_format = timecode_30;
152                 break;
153         default:
154                 /* throttle error messages about unknown MTC rates */
155                 if (can_notify_on_unknown_rate) {
156                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
157                                                  (int) msg[4])
158                               << endmsg;
159                         can_notify_on_unknown_rate = false;
160                 }
161                 timecode.rate = session.timecode_frames_per_second();
162                 timecode.drop = session.timecode_drop_frames();
163                 reset_tc = false;
164         }
165
166         if (reset_tc) {
167                 if (!did_reset_tc_format) {
168                         saved_tc_format = session.config.get_timecode_format();
169                         did_reset_tc_format = true;
170                 }
171                 session.config.set_timecode_format (tc_format);
172         }
173
174         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n", 
175                                                  now, timecode, mtc_frame, was_full));
176
177         if (was_full) {
178
179                 session.timecode_to_sample (timecode, mtc_frame, true, false);
180                 session.request_locate (mtc_frame, false);
181                 session.request_transport_speed (0);
182                 update_mtc_status (MIDI::Parser::MTC_Stopped);
183
184                 reset ();
185
186         } else {
187
188                         
189                 /* we've had the first set of 8 qtr frame messages, determine position
190                            and allow continuing qtr frame messages to provide position
191                            and speed information.
192                 */
193                 
194                 qtr_frame_messages_valid_for_time = true;
195                 session.timecode_to_sample (timecode, mtc_frame, true, false);
196                 
197                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
198                    frames) after the instance when the contents of the mtc quarter
199                    frames were decided. Add time to compensate for the elapsed 1.75
200                    frames. Also compensate for audio latency.
201                 */
202                 
203                 mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
204                 
205                 double speed = compute_apparent_speed (now);
206                 
207                 current.guard1++;
208                 current.position = mtc_frame;
209                 current.timestamp = now;
210                 current.speed = speed;
211                 current.guard2++;
212         }
213
214         last_inbound_frame = now;
215 }
216
217 double
218 MTC_Slave::compute_apparent_speed (nframes64_t now)
219 {
220         if (current.timestamp != 0) {
221                 
222                 double speed = (double) ((mtc_frame - current.position) / (double) (now - current.timestamp));
223                 DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 / %3\n",
224                                                          speed, mtc_frame - current.position, now - current.timestamp));
225                 
226                 /* crude low pass filter/smoother for speed */
227
228                 accumulator[accumulator_index++] = speed;
229                 
230                 if (accumulator_index >= accumulator_size) {
231                         have_first_accumulated_speed = true;
232                         accumulator_index = 0;
233                 }
234                 
235                 if (have_first_accumulated_speed) {
236                         double total = 0;
237                         
238                         for (int32_t i = 0; i < accumulator_size; ++i) {
239                                 total += accumulator[i];
240                         }
241                         
242                         speed = total / accumulator_size;
243                         DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
244                 } 
245
246                 return speed;
247                 
248         } else {
249                 
250                 return 0;
251         }
252 }
253
254 void
255 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
256 {
257         MIDI::byte mtc[5];
258
259         mtc[4] = last_mtc_fps_byte;
260         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
261         mtc[2] = mmc_tc[1];
262         mtc[1] = mmc_tc[2];
263         mtc[0] = mmc_tc[3];
264
265         update_mtc_time (mtc, true);
266 }
267
268 void
269 MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
270 {
271         /* XXX !!! thread safety ... called from MIDI I/O context
272            and process() context (via ::speed_and_position())
273         */
274
275         switch (status) {
276         case MTC_Stopped:
277                 mtc_frame = 0;
278
279                 current.guard1++;
280                 current.position = mtc_frame;
281                 current.timestamp = 0;
282                 current.speed = 0;
283                 current.guard2++;
284
285                 break;
286
287         case MTC_Forward:
288                 mtc_frame = 0;
289
290                 current.guard1++;
291                 current.position = mtc_frame;
292                 current.timestamp = 0;
293                 current.speed = 0;
294                 current.guard2++;
295
296                 break;
297
298         case MTC_Backward:
299                 mtc_frame = 0;
300
301                 current.guard1++;
302                 current.position = mtc_frame;
303                 current.timestamp = 0;
304                 current.speed = 0;
305                 current.guard2++;
306
307                 break;
308         }
309 }
310
311 void
312 MTC_Slave::read_current (SafeTime *st) const
313 {
314         int tries = 0;
315
316         do {
317                 if (tries == 10) {
318                         error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
319                         usleep (20);
320                         tries = 0;
321                 }
322                 *st = current;
323                 tries++;
324
325         } while (st->guard1 != st->guard2);
326 }
327
328 bool
329 MTC_Slave::locked () const
330 {
331         return port->input()->mtc_locked();
332 }
333
334 bool
335 MTC_Slave::ok() const
336 {
337         return true;
338 }
339
340 bool
341 MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
342 {
343         nframes64_t now = session.engine().frame_time();
344         SafeTime last;
345         nframes_t elapsed;
346
347         read_current (&last);
348
349         if (last.timestamp == 0) {
350                 speed = 0;
351                 pos = last.position;
352                 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position));
353                 return true;
354         }
355
356         /* no timecode for 1/4 second ? conclude that its stopped */
357
358         if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
359                 speed = 0;
360                 pos = last.position;
361                 session.request_locate (pos, false);
362                 session.request_transport_speed (0);
363                 update_mtc_status (MIDI::Parser::MTC_Stopped);
364                 reset();
365                 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
366                 return false;
367         }
368
369         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position));
370
371         if (last.speed == 0.0f) {
372
373                 elapsed = 0;
374
375         } else {
376
377                 /* scale elapsed time by the current MTC speed */
378
379                 if (last.timestamp && (now > last.timestamp)) {
380                         elapsed = (nframes_t) floor (last.speed * (now - last.timestamp));
381                         DEBUG_TRACE (DEBUG::MTC, string_compose ("last timecode received @ %1, now = %2, elapsed frames = %3 w/speed= %4\n",
382                                                                  last.timestamp, now, elapsed, speed));
383                 } else {
384                         elapsed = 0; /* XXX is this right? */
385                 }
386         }
387
388         /* now add the most recent timecode value plus the estimated elapsed interval */
389
390         pos =  elapsed + last.position;
391         speed = last.speed;
392
393         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos));
394
395         return true;
396 }
397
398 ARDOUR::nframes_t
399 MTC_Slave::resolution() const
400 {
401         return (nframes_t) session.frames_per_timecode_frame();
402 }
403
404 void
405 MTC_Slave::reset ()
406 {
407         /* XXX massive thread safety issue here. MTC could
408            be being updated as we call this. but this
409            supposed to be a realtime-safe call.
410         */
411
412         port->input()->reset_mtc_state ();
413
414         last_inbound_frame = 0;
415         current.guard1++;
416         current.position = 0;
417         current.timestamp = 0;
418         current.speed = 0;
419         current.guard2++;
420         accumulator_index = 0;
421         have_first_accumulated_speed = false;
422         qtr_frame_messages_valid_for_time = false;
423 }