MTC slave: set initial framerates to current value.
[ardour.git] / libs / ardour / mtc_slave.cc
1 /*
2     Copyright (C) 2002-4 Paul Davis
3     Overhaul 2012 Robin Gareus <robin@gareus.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20 #include <iostream>
21 #include <errno.h>
22 #include <poll.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include "pbd/error.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
34 #include "i18n.h"
35
36 using namespace std;
37 using namespace ARDOUR;
38 using namespace MIDI;
39 using namespace PBD;
40 using namespace Timecode;
41
42 /* length (in timecode frames) of the "window" that we consider legal given receipt of
43    a given timecode position. Ardour will try to chase within this window, and will
44    stop+locate+wait+chase if timecode arrives outside of it. The window extends entirely
45    in the current direction of motion, so if any timecode arrives that is before the most
46    recently received position (and without the direction of timecode reversing too), we
47    will stop+locate+wait+chase.
48 */
49 const int MTC_Slave::frame_tolerance = 2;
50
51 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
52         : session (s)
53 {
54         can_notify_on_unknown_rate = true;
55         did_reset_tc_format = false;
56         reset_pending = 0;
57         reset_position = false;
58         mtc_frame = 0;
59         engine_dll_initstate = 0;
60         busy_guard1 = busy_guard2 = 0;
61
62         last_mtc_fps_byte = session.get_mtc_timecode_bits ();
63         quarter_frame_duration = (double(session.frames_per_timecode_frame()) / 4.0);
64
65         mtc_timecode = session.config.get_timecode_format();
66         a3e_timecode = session.config.get_timecode_format();
67         printed_timecode_warning = false;
68
69         reset (true);
70         rebind (p);
71 }
72
73 MTC_Slave::~MTC_Slave()
74 {
75         port_connections.drop_connections();
76
77         while (busy_guard1 != busy_guard2) {
78                 /* make sure MIDI parser is not currently calling any callbacks in here,
79                  * else there's a segfault ahead!
80                  *
81                  * XXX this is called from jack rt-context :(
82                  * TODO fix libs/ardour/session_transport.cc:1321 (delete _slave;)
83                  */
84                 sched_yield();
85         }
86
87         if (did_reset_tc_format) {
88                 session.config.set_timecode_format (saved_tc_format);
89         }
90 }
91
92 void
93 MTC_Slave::rebind (MIDI::Port& p)
94 {
95         port_connections.drop_connections ();
96
97         port = &p;
98
99         port->parser()->mtc_time.connect_same_thread (port_connections,  boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
100         port->parser()->mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
101         port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
102 }
103
104 bool
105 MTC_Slave::give_slave_full_control_over_transport_speed() const
106 {
107         return true; // DLL align to engine transport
108         // return false; // for Session-level computed varispeed
109 }
110
111 ARDOUR::framecnt_t
112 MTC_Slave::resolution () const
113 {
114         return (framecnt_t) quarter_frame_duration * 4.0;
115 }
116
117 ARDOUR::framecnt_t
118 MTC_Slave::seekahead_distance () const
119 {
120         return quarter_frame_duration * 8 * transport_direction;
121 }
122
123 bool
124 MTC_Slave::outside_window (framepos_t pos) const
125 {
126         return ((pos < window_begin) || (pos > window_end));
127 }
128
129
130 bool
131 MTC_Slave::locked () const
132 {
133         return port->parser()->mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
134 }
135
136 bool
137 MTC_Slave::ok() const
138 {
139         return true;
140 }
141
142 void
143 MTC_Slave::queue_reset (bool reset_pos)
144 {
145         Glib::Threads::Mutex::Lock lm (reset_lock);
146         reset_pending++;
147         if (reset_pos) {
148                 reset_position = true;
149         }
150 }
151
152 void
153 MTC_Slave::maybe_reset ()
154 {
155         Glib::Threads::Mutex::Lock lm (reset_lock);
156
157         if (reset_pending) {
158                 reset (reset_position);
159                 reset_pending = 0;
160                 reset_position = false;
161         }
162 }
163
164 void
165 MTC_Slave::reset (bool with_position)
166 {
167         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC_Slave reset %1\n", with_position?"with position":"without position"));
168         if (with_position) {
169                 last_inbound_frame = 0;
170                 current.guard1++;
171                 current.position = 0;
172                 current.timestamp = 0;
173                 current.speed = 0;
174                 current.guard2++;
175         } else {
176                 last_inbound_frame = 0;
177                 current.guard1++;
178                 current.timestamp = 0;
179                 current.speed = 0;
180                 current.guard2++;
181         }
182         first_mtc_timestamp = 0;
183         window_begin = 0;
184         window_end = 0;
185         transport_direction = 1;
186         current_delta = 0;
187 }
188
189 void
190 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
191 {
192         MIDI::byte mtc[5];
193         DEBUG_TRACE (DEBUG::MTC, "MTC_Slave::handle_locate\n");
194
195         mtc[4] = last_mtc_fps_byte;
196         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
197         mtc[2] = mmc_tc[1];
198         mtc[1] = mmc_tc[2];
199         mtc[0] = mmc_tc[3];
200
201         update_mtc_time (mtc, true, 0);
202 }
203
204 void
205 MTC_Slave::read_current (SafeTime *st) const
206 {
207         int tries = 0;
208
209         do {
210                 if (tries == 10) {
211                         error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
212                         usleep (20);
213                         tries = 0;
214                 }
215                 *st = current;
216                 tries++;
217
218         } while (st->guard1 != st->guard2);
219 }
220
221 void
222 MTC_Slave::init_mtc_dll(framepos_t tme, double qtr)
223 {
224         omega = 2.0 * M_PI * qtr / 2.0 / double(session.frame_rate());
225         b = 1.4142135623730950488 * omega;
226         c = omega * omega;
227
228         e2 = qtr;
229         t0 = double(tme);
230         t1 = t0 + e2;
231         DEBUG_TRACE (DEBUG::MTC, string_compose ("[re-]init MTC DLL %1 %2 %3\n", t0, t1, e2));
232 }
233
234
235 /* called from MIDI parser */
236 void
237 MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, framepos_t now)
238 {
239         busy_guard1++;
240         const double qtr_d = quarter_frame_duration;
241         const framepos_t qtr = rint(qtr_d);
242
243         mtc_frame += qtr * transport_direction;
244
245         DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2 -> mtc_frame: %3\n", which_qtr, now, mtc_frame));
246
247         double mtc_speed = 0;
248         if (first_mtc_timestamp != 0) {
249                 /* update MTC DLL and calculate speed */
250                 const double e = mtc_frame - (double(transport_direction) * (double(now) - double(current.timestamp) + t0));
251                 t0 = t1;
252                 t1 += b * e + e2;
253                 e2 += c * e;
254
255                 mtc_speed = (t1 - t0) / qtr_d;
256                 DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, mtc_speed, e2 - qtr_d));
257
258                 current.guard1++;
259                 current.position = mtc_frame;
260                 current.timestamp = now;
261                 current.speed = mtc_speed;
262                 current.guard2++;
263
264                 last_inbound_frame = now;
265         }
266
267         maybe_reset ();
268
269         busy_guard2++;
270 }
271
272 /* called from MIDI parser _after_ update_mtc_qtr()
273  * when a full TC has been received
274  * OR on locate */
275 void
276 MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
277 {
278         busy_guard1++;
279
280         /* "now" can be zero if this is called from a context where we do not have or do not want
281            to use a timestamp indicating when this MTC time was received. example: when we received
282            a locate command via MMC.
283         */
284
285         //DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::update_mtc_time - TID:%1\n", ::pthread_self()));
286         TimecodeFormat tc_format;
287         bool reset_tc = true;
288
289         timecode.hours = msg[3];
290         timecode.minutes = msg[2];
291         timecode.seconds = msg[1];
292         timecode.frames = msg[0];
293
294         last_mtc_fps_byte = msg[4];
295
296         DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
297
298         if (now) {
299                 maybe_reset ();
300         }
301
302         switch (msg[4]) {
303         case MTC_24_FPS:
304                 timecode.rate = 24;
305                 timecode.drop = false;
306                 tc_format = timecode_24;
307                 can_notify_on_unknown_rate = true;
308                 break;
309         case MTC_25_FPS:
310                 timecode.rate = 25;
311                 timecode.drop = false;
312                 tc_format = timecode_25;
313                 can_notify_on_unknown_rate = true;
314                 break;
315         case MTC_30_FPS_DROP:
316                 timecode.rate = (30000.0/1001.0);
317                 timecode.drop = true;
318                 tc_format = timecode_2997drop;
319                 can_notify_on_unknown_rate = true;
320                 break;
321         case MTC_30_FPS:
322                 timecode.rate = 30;
323                 timecode.drop = false;
324                 can_notify_on_unknown_rate = true;
325                 tc_format = timecode_30;
326                 break;
327         default:
328                 /* throttle error messages about unknown MTC rates */
329                 if (can_notify_on_unknown_rate) {
330                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
331                                                  (int) msg[4])
332                               << endmsg;
333                         can_notify_on_unknown_rate = false;
334                 }
335                 timecode.rate = session.timecode_frames_per_second();
336                 timecode.drop = session.timecode_drop_frames();
337                 reset_tc = false;
338         }
339
340         if (reset_tc) {
341                 TimecodeFormat cur_timecode = session.config.get_timecode_format();
342                 if (Config->get_timecode_sync_frame_rate()) {
343                         /* enforce time-code */
344                         if (!did_reset_tc_format) {
345                                 saved_tc_format = cur_timecode;
346                                 did_reset_tc_format = true;
347                         }
348                         if (cur_timecode != tc_format) {
349                                 warning << string_compose(_("Session framerate adjusted from %1 TO: MTC's %2."),
350                                                 Timecode::timecode_format_name(cur_timecode),
351                                                 Timecode::timecode_format_name(tc_format))
352                                         << endmsg;
353                         }
354                         session.config.set_timecode_format (tc_format);
355                 } else {
356                         /* only warn about TC mismatch */
357                         if (mtc_timecode != tc_format) printed_timecode_warning = false;
358                         if (a3e_timecode != cur_timecode) printed_timecode_warning = false;
359
360                         if (cur_timecode != tc_format && ! printed_timecode_warning) {
361                                 warning << string_compose(_("Session and MTC framerate mismatch: MTC:%1 Ardour:%2."),
362                                                 Timecode::timecode_format_name(tc_format),
363                                                 Timecode::timecode_format_name(cur_timecode))
364                                         << endmsg;
365                                 printed_timecode_warning = true;
366                         }
367                 }
368                 mtc_timecode = tc_format;
369                 a3e_timecode = cur_timecode;
370
371                 speedup_due_to_tc_mismatch = timecode.rate / Timecode::timecode_to_frames_per_second(a3e_timecode);
372         }
373
374         /* do a careful conversion of the timecode value to a position
375            so that we take drop/nondrop and all that nonsense into
376            consideration.
377         */
378
379         quarter_frame_duration = (double(session.frame_rate()) / (double) timecode.rate / 4.0);
380
381         Timecode::timecode_to_sample (timecode, mtc_frame, true, false,
382                 double(session.frame_rate()),
383                 session.config.get_subframes_per_frame(),
384                 session.config.get_timecode_offset_negative(), session.config.get_timecode_offset()
385                 );
386
387         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4) tc-ratio %5\n",
388                                                  now, timecode, mtc_frame, was_full, speedup_due_to_tc_mismatch));
389
390         if (was_full || outside_window (mtc_frame)) {
391                 DEBUG_TRACE (DEBUG::MTC, string_compose ("update_mtc_time: full TC or outside window. - TID:%1\n", ::pthread_self()));
392                 session.request_locate (mtc_frame, false);
393                 session.request_transport_speed (0);
394                 update_mtc_status (MIDI::MTC_Stopped);
395                 reset (false);
396                 reset_window (mtc_frame);
397         } else {
398
399                 /* we've had the first set of 8 qtr frame messages, determine position
400                    and allow continuing qtr frame messages to provide position
401                    and speed information.
402                 */
403
404                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
405                    frames) after the instance when the contents of the mtc quarter
406                    frames were decided. Add time to compensate for the elapsed 1.75
407                    frames.
408                 */
409                 double qtr = quarter_frame_duration;
410                 long int mtc_off = (long) rint(7.0 * qtr);
411
412                 DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
413                                                          mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
414
415                 switch (port->parser()->mtc_running()) {
416                 case MTC_Backward:
417                         mtc_frame -= mtc_off;
418                         qtr *= -1.0;
419                         break;
420                 case MTC_Forward:
421                         mtc_frame += mtc_off;
422                         break;
423                 default:
424                         break;
425                 }
426
427                 DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame (w/offset) = %1\n", mtc_frame));
428
429                 if (now) {
430                         if (first_mtc_timestamp == 0 || current.timestamp == 0) {
431                                 first_mtc_timestamp = now;
432                                 init_mtc_dll(mtc_frame, qtr);
433                         }
434                         current.guard1++;
435                         current.position = mtc_frame;
436                         current.timestamp = now;
437                         current.guard2++;
438                         reset_window (mtc_frame);
439                 }
440         }
441
442         if (now) {
443                 last_inbound_frame = now;
444         }
445         busy_guard2++;
446 }
447
448 void
449 MTC_Slave::update_mtc_status (MIDI::MTC_Status status)
450 {
451         /* XXX !!! thread safety ... called from MIDI I/O context
452          * on locate (via ::update_mtc_time())
453          */
454         DEBUG_TRACE (DEBUG::MTC, string_compose("MTC_Slave::update_mtc_status - TID:%1\n", ::pthread_self()));
455         return; // why was this fn needed anyway ? it just messes up things -> use reset.
456         busy_guard1++;
457
458         switch (status) {
459         case MTC_Stopped:
460                 current.guard1++;
461                 current.position = mtc_frame;
462                 current.timestamp = 0;
463                 current.speed = 0;
464                 current.guard2++;
465
466                 break;
467
468         case MTC_Forward:
469                 current.guard1++;
470                 current.position = mtc_frame;
471                 current.timestamp = 0;
472                 current.speed = 0;
473                 current.guard2++;
474                 break;
475
476         case MTC_Backward:
477                 current.guard1++;
478                 current.position = mtc_frame;
479                 current.timestamp = 0;
480                 current.speed = 0;
481                 current.guard2++;
482                 break;
483         }
484         busy_guard2++;
485 }
486
487 void
488 MTC_Slave::reset_window (framepos_t root)
489 {
490         /* if we're waiting for the master to catch us after seeking ahead, keep the window
491            of acceptable MTC frames wide open. otherwise, shrink it down to just 2 video frames
492            ahead of the window root (taking direction into account).
493         */
494         framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
495
496         switch (port->parser()->mtc_running()) {
497         case MTC_Forward:
498                 window_begin = root;
499                 transport_direction = 1;
500                 window_end = root + d;
501                 break;
502
503         case MTC_Backward:
504                 transport_direction = -1;
505                 if (root > d) {
506                         window_begin = root - d;
507                         window_end = root;
508                 } else {
509                         window_begin = 0;
510                 }
511                 window_end = root;
512                 break;
513
514         default:
515                 /* do nothing */
516                 break;
517         }
518
519         DEBUG_TRACE (DEBUG::MTC, string_compose ("legal MTC window now %1 .. %2\n", window_begin, window_end));
520 }
521
522 void
523 MTC_Slave::init_engine_dll (framepos_t pos, framepos_t inc)
524 {
525         /* the bandwidth of the DLL is a trade-off,
526          * because the max-speed of the transport in ardour is
527          * limited to +-8.0, a larger bandwidth would cause oscillations
528          *
529          * But this is only really a problem if the user performs manual
530          * seeks while transport is running and slaved to MTC.
531          */
532         oe = 2.0 * M_PI * double(inc) / 2.0 / double(session.frame_rate());
533         be = 1.4142135623730950488 * oe;
534         ce = oe * oe;
535
536         ee2 = double(transport_direction * inc);
537         te0 = double(pos);
538         te1 = te0 + ee2;
539         DEBUG_TRACE (DEBUG::MTC, string_compose ("[re-]init Engine DLL %1 %2 %3\n", te0, te1, ee2));
540 }
541
542 /* main entry point from session_process.cc
543  * in jack_process callback context */
544 bool
545 MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
546 {
547         framepos_t now = session.engine().frame_time_at_cycle_start();
548         framepos_t sess_pos = session.transport_frame(); // corresponds to now
549         //sess_pos -= session.engine().frames_since_cycle_start();
550
551         SafeTime last;
552         frameoffset_t elapsed;
553         bool engine_dll_reinitialized = false;
554
555         read_current (&last);
556
557         /* re-init engine DLL here when state changed (direction, first_mtc_timestamp) */
558         if (last.timestamp == 0) { engine_dll_initstate = 0; }
559         else if (engine_dll_initstate != transport_direction && last.speed != 0) {
560                 engine_dll_initstate = transport_direction;
561                 init_engine_dll(last.position, session.engine().frames_per_cycle());
562                 engine_dll_reinitialized = true;
563         }
564
565         if (last.timestamp == 0) {
566                 speed = 0;
567                 pos = session.transport_frame() ; // last.position;
568                 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", pos));
569                 return true;
570         }
571
572         /* no timecode for two frames - conclude that it's stopped */
573         if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > labs(seekahead_distance())) {
574                 speed = 0;
575                 pos = last.position;
576                 session.request_locate (pos, false);
577                 session.request_transport_speed (0);
578                 engine_dll_initstate = 0;
579                 queue_reset (false);
580                 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 2 frames - reset pending\n");
581                 return false;
582         }
583
584
585         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position mtc-tme: %1 mtc-pos: %2 mtc-spd: %3\n", last.timestamp, last.position, last.speed));
586         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position eng-tme: %1 eng-pos: %2\n", now, sess_pos));
587
588         double speed_flt = last.speed; ///< MTC speed from MTC-quarter-frame DLL
589
590         /* interpolate position according to speed and time since last quarter-frame*/
591         if (speed_flt == 0.0f) {
592                 elapsed = 0;
593         }
594         else
595         {
596                 /* scale elapsed time by the current MTC speed */
597                 elapsed = (framecnt_t) rint (speed_flt * (now - last.timestamp));
598                 if (give_slave_full_control_over_transport_speed() && !engine_dll_reinitialized) {
599                         /* there is an engine vs MTC position frame-delta.
600                          * This mostly due to quantization and rounding of (speed * nframes)
601                          * but can also due to the session-process not calling
602                          * speed_and_position() every cycle under some circumstances.
603                          * Thus we use an other DLL to align the engine and the MTC
604                          */
605
606                         /* update engine DLL and calculate speed */
607                         const double e = double (last.position + elapsed - sess_pos);
608                         te0 = te1;
609                         te1 += be * e + ee2;
610                         ee2 += ce * e;
611                         speed_flt = (te1 - te0) / double(session.engine().frames_per_cycle());
612                         DEBUG_TRACE (DEBUG::MTC, string_compose ("engine DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", te0, te1, e, speed_flt, ee2 - session.engine().frames_per_cycle() ));
613                 }
614         }
615
616         pos = last.position + elapsed;
617         speed = speed_flt;
618
619         /* may happen if the user performs a seek in the timeline while slaved to running MTC
620          * engine-DLL can oscillate back before 0.
621          * also see note in MTC_Slave::init_engine_dll
622          */
623         if (!session.actively_recording()
624             && speed != 0
625                         && ( (pos < 0) || (labs(pos - sess_pos) > 3 * session.frame_rate()) )
626             ) {
627                 engine_dll_initstate = 0;
628                 queue_reset (false);
629         }
630
631         /* provide a .1% deadzone to lock the speed */
632         if (fabs(speed - 1.0) <= 0.001)
633                 speed = 1.0;
634
635         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTCsync spd: %1 pos: %2 | last-pos: %3 elapsed: %4 delta: %5\n",
636                                                  speed, pos, last.position, elapsed,  pos - sess_pos));
637
638         current_delta = (pos - sess_pos);
639
640         return true;
641 }
642
643 Timecode::TimecodeFormat
644 MTC_Slave::apparent_timecode_format () const
645 {
646         return mtc_timecode;
647 }
648
649 std::string
650 MTC_Slave::approximate_current_position() const
651 {
652         SafeTime last;
653         read_current (&last);
654         if (last.timestamp == 0 || reset_pending) {
655                 return " --:--:--:--";
656         }
657         return Timecode::timecode_format_sampletime(
658                 last.position,
659                 double(session.frame_rate()),
660                 Timecode::timecode_to_frames_per_second(mtc_timecode),
661                 Timecode::timecode_has_drop_frames(mtc_timecode));
662 }
663
664 std::string
665 MTC_Slave::approximate_current_delta() const
666 {
667         char delta[24];
668         SafeTime last;
669         read_current (&last);
670         if (last.timestamp == 0 || reset_pending) {
671                 snprintf(delta, sizeof(delta), "\u2012\u2012\u2012\u2012");
672         } else {
673                 // TODO if current_delta > 1 frame -> display timecode.
674                 snprintf(delta, sizeof(delta), "%s%4" PRIi64 " sm",
675                                 PLUSMINUS(-current_delta), abs(current_delta));
676         }
677         return std::string(delta);
678 }