3f045e26d43b1fef391c16f463e079787f3eed8d
[ardour.git] / libs / ardour / mtc_slave.cc
1 /*
2  * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
3  * Copyright (C) 2008-2019 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2012-2017 Robin Gareus <robin@gareus.org>
6  * Copyright (C) 2013-2018 John Emmas <john@creativepost.co.uk>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 #include <iostream>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include "pbd/error.h"
28 #include "pbd/pthread_utils.h"
29
30 #include "ardour/audioengine.h"
31 #include "ardour/debug.h"
32 #include "ardour/midi_buffer.h"
33 #include "ardour/midi_port.h"
34 #include "ardour/session.h"
35 #include "ardour/transport_master.h"
36
37 #include "pbd/i18n.h"
38
39 using namespace std;
40 using namespace ARDOUR;
41 using namespace MIDI;
42 using namespace PBD;
43 using namespace Timecode;
44
45 /* length (in timecode frames) of the "window" that we consider legal given receipt of
46    a given timecode position. Ardour will try to chase within this window, and will
47    stop+locate+wait+chase if timecode arrives outside of it. The window extends entirely
48    in the current direction of motion, so if any timecode arrives that is before the most
49    recently received position (and without the direction of timecode reversing too), we
50    will stop+locate+wait+chase.
51 */
52 const int MTC_TransportMaster::sample_tolerance = 2;
53
54 MTC_TransportMaster::MTC_TransportMaster (std::string const & name)
55         : TimecodeTransportMaster (name, MTC)
56         , can_notify_on_unknown_rate (true)
57         , mtc_frame (0)
58         , mtc_frame_dll (0)
59         , last_inbound_frame (0)
60         , window_begin (0)
61         , window_end (0)
62         , first_mtc_timestamp (0)
63         , did_reset_tc_format (false)
64         , reset_pending (0)
65         , reset_position (false)
66         , transport_direction (1)
67         , busy_guard1 (0)
68         , busy_guard2 (0)
69         , printed_timecode_warning (false)
70 {
71         if ((_port = create_midi_port (string_compose ("%1 in", name))) == 0) {
72                 throw failed_constructor();
73         }
74
75         DEBUG_TRACE (DEBUG::Slave, string_compose ("MTC registered %1\n", _port->name()));
76
77         init ();
78 }
79
80 MTC_TransportMaster::~MTC_TransportMaster()
81 {
82         port_connections.drop_connections();
83         config_connection.disconnect();
84
85         while (busy_guard1 != busy_guard2) {
86                 /* make sure MIDI parser is not currently calling any callbacks in here,
87                  * else there's a segfault ahead!
88                  *
89                  * XXX this is called from jack rt-context :(
90                  * TODO fix libs/ardour/session_transport.cc:1321 (delete _slave;)
91                  */
92                 sched_yield();
93         }
94
95         if (did_reset_tc_format) {
96                 _session->config.set_timecode_format (saved_tc_format);
97         }
98 }
99
100 void
101 MTC_TransportMaster::init ()
102 {
103         reset (true);
104 }
105
106 void
107 MTC_TransportMaster::set_session (Session *s)
108 {
109         config_connection.disconnect ();
110         port_connections.drop_connections();
111
112         _session = s;
113
114         if (_session) {
115
116                 last_mtc_fps_byte = _session->get_mtc_timecode_bits ();
117                 quarter_frame_duration = (double) (_session->samples_per_timecode_frame() / 4.0);
118                 mtc_timecode = _session->config.get_timecode_format();
119                 a3e_timecode = _session->config.get_timecode_format();
120
121                 parse_timecode_offset ();
122                 reset (true);
123
124                 parser.mtc_time.connect_same_thread (port_connections,  boost::bind (&MTC_TransportMaster::update_mtc_time, this, _1, _2, _3));
125                 parser.mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_TransportMaster::update_mtc_qtr, this, _1, _2, _3));
126                 parser.mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_TransportMaster::update_mtc_status, this, _1));
127
128                 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_TransportMaster::parameter_changed, this, _1));
129         }
130 }
131
132 void
133 MTC_TransportMaster::pre_process (MIDI::pframes_t nframes, samplepos_t now, boost::optional<samplepos_t> session_pos)
134 {
135         /* Read and parse incoming MIDI */
136
137         maybe_reset ();
138
139         _midi_port->read_and_parse_entire_midi_buffer_with_no_speed_adjustment (nframes, parser, now);
140
141         if (session_pos) {
142                 const samplepos_t current_pos = current.position + ((now - current.timestamp) * current.speed);
143                 _current_delta = current_pos - *session_pos;
144         } else {
145                 _current_delta = 0;
146         }
147 }
148
149 void
150 MTC_TransportMaster::parse_timecode_offset() {
151         Timecode::Time offset_tc;
152         Timecode::parse_timecode_format (_session->config.get_slave_timecode_offset(), offset_tc);
153         offset_tc.rate = _session->timecode_frames_per_second();
154         offset_tc.drop = _session->timecode_drop_frames();
155         _session->timecode_to_sample(offset_tc, timecode_offset, false, false);
156         timecode_negative_offset = offset_tc.negative;
157 }
158
159 void
160 MTC_TransportMaster::parameter_changed (std::string const & p)
161 {
162         if (p == "slave-timecode-offset"
163                         || p == "timecode-format"
164                         ) {
165                 parse_timecode_offset();
166         }
167 }
168
169 ARDOUR::samplecnt_t
170 MTC_TransportMaster::update_interval() const
171 {
172         if (timecode.rate) {
173                 return AudioEngine::instance()->sample_rate() / timecode.rate;
174         }
175
176         return AudioEngine::instance()->sample_rate(); /* useless but what other answer is there? */
177 }
178
179 ARDOUR::samplecnt_t
180 MTC_TransportMaster::resolution () const
181 {
182         return (samplecnt_t) quarter_frame_duration * 4.0;
183 }
184
185 ARDOUR::samplecnt_t
186 MTC_TransportMaster::seekahead_distance () const
187 {
188         return quarter_frame_duration * 8 * transport_direction;
189 }
190
191 bool
192 MTC_TransportMaster::outside_window (samplepos_t pos) const
193 {
194         return ((pos < window_begin) || (pos > window_end));
195 }
196
197
198 bool
199 MTC_TransportMaster::locked () const
200 {
201         DEBUG_TRACE (DEBUG::MTC, string_compose ("locked ? %1 last %2\n", parser.mtc_locked(), last_inbound_frame));
202         return parser.mtc_locked() && last_inbound_frame !=0;
203 }
204
205 bool
206 MTC_TransportMaster::ok() const
207 {
208         return true;
209 }
210
211 void
212 MTC_TransportMaster::queue_reset (bool reset_pos)
213 {
214         Glib::Threads::Mutex::Lock lm (reset_lock);
215         reset_pending++;
216         if (reset_pos) {
217                 reset_position = true;
218         }
219 }
220
221 void
222 MTC_TransportMaster::maybe_reset ()
223 {
224         Glib::Threads::Mutex::Lock lm (reset_lock);
225
226         if (reset_pending) {
227                 reset (reset_position);
228                 reset_pending = 0;
229                 reset_position = false;
230         }
231 }
232
233 void
234 MTC_TransportMaster::reset (bool with_position)
235 {
236         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC_TransportMaster reset %1\n", with_position?"with position":"without position"));
237
238         if (with_position) {
239                 current.update (current.position, 0, 0);
240         } else {
241                 current.reset ();
242         }
243         first_mtc_timestamp = 0;
244         window_begin = 0;
245         window_end = 0;
246         transport_direction = 1;
247         _current_delta = 0;
248 }
249
250 void
251 MTC_TransportMaster::handle_locate (const MIDI::byte* mmc_tc)
252 {
253         MIDI::byte mtc[5];
254         DEBUG_TRACE (DEBUG::MTC, "MTC_TransportMaster::handle_locate\n");
255
256         mtc[4] = last_mtc_fps_byte;
257         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
258         mtc[2] = mmc_tc[1];
259         mtc[1] = mmc_tc[2];
260         mtc[0] = mmc_tc[3];
261
262         update_mtc_time (mtc, true, 0);
263 }
264
265 void
266 MTC_TransportMaster::init_mtc_dll(samplepos_t tme, double qtr)
267 {
268         const double omega = 2.0 * M_PI * qtr / 2.0 / double(_session->sample_rate());
269         b = 1.4142135623730950488 * omega;
270         c = omega * omega;
271
272         e2 = qtr;
273         t0 = double(tme);
274         t1 = t0 + e2;
275         DEBUG_TRACE (DEBUG::MTC, string_compose ("[re-]init MTC DLL %1 %2 %3\n", t0, t1, e2));
276 }
277
278 /* called from MIDI parser */
279 void
280 MTC_TransportMaster::update_mtc_qtr (Parser& p, int which_qtr, samplepos_t now)
281 {
282         busy_guard1++;
283         const double qtr_d = quarter_frame_duration;
284
285         mtc_frame_dll += qtr_d * (double) transport_direction;
286         mtc_frame = rint(mtc_frame_dll);
287
288         DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr sample %1 at %2 -> mtc_frame: %3\n", which_qtr, now, mtc_frame));
289
290         double mtc_speed = 0;
291         if (first_mtc_timestamp != 0) {
292                 /* update MTC DLL and calculate speed */
293                 const double e = mtc_frame_dll - (double)transport_direction * ((double)now - (double)current.timestamp + t0);
294                 t0 = t1;
295                 t1 += b * e + e2;
296                 e2 += c * e;
297
298                 mtc_speed = (t1 - t0) / qtr_d;
299                 DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr sample DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, mtc_speed, e2 - qtr_d));
300
301                 current.update (mtc_frame, now, mtc_speed);
302
303                 last_inbound_frame = now;
304         }
305
306         maybe_reset ();
307
308         busy_guard2++;
309 }
310
311 /* called from MIDI parser _after_ update_mtc_qtr()
312  * when a full TC has been received
313  * OR on locate */
314 void
315 MTC_TransportMaster::update_mtc_time (const MIDI::byte *msg, bool was_full, samplepos_t now)
316 {
317         busy_guard1++;
318
319         /* "now" can be zero if this is called from a context where we do not have or do not want
320            to use a timestamp indicating when this MTC time was received. example: when we received
321            a locate command via MMC.
322         */
323         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::update_mtc_time - TID:%1\n", pthread_name()));
324         TimecodeFormat tc_format;
325         bool reset_tc = true;
326
327         timecode.hours = msg[3];
328         timecode.minutes = msg[2];
329         timecode.seconds = msg[1];
330         timecode.frames = msg[0];
331
332         last_mtc_fps_byte = msg[4];
333
334         DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
335
336         if (now) {
337                 maybe_reset ();
338         }
339
340         switch (msg[4]) {
341         case MTC_24_FPS:
342                 timecode.rate = 24;
343                 timecode.drop = false;
344                 tc_format = timecode_24;
345                 can_notify_on_unknown_rate = true;
346                 break;
347         case MTC_25_FPS:
348                 timecode.rate = 25;
349                 timecode.drop = false;
350                 tc_format = timecode_25;
351                 can_notify_on_unknown_rate = true;
352                 break;
353         case MTC_30_FPS_DROP:
354                 if (fr2997()) {
355                         tc_format = Timecode::timecode_2997000drop;
356                         timecode.rate = (29970.0/1000.0);
357                 } else {
358                         tc_format = timecode_2997drop;
359                         timecode.rate = (30000.0/1001.0);
360                 }
361                 timecode.drop = true;
362                 can_notify_on_unknown_rate = true;
363                 break;
364         case MTC_30_FPS:
365                 timecode.rate = 30;
366                 timecode.drop = false;
367                 can_notify_on_unknown_rate = true;
368                 tc_format = timecode_30;
369                 break;
370         default:
371                 /* throttle error messages about unknown MTC rates */
372                 if (can_notify_on_unknown_rate) {
373                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
374                                                  (int) msg[4])
375                               << endmsg;
376                         can_notify_on_unknown_rate = false;
377                 }
378                 timecode.rate = _session->timecode_frames_per_second();
379                 timecode.drop = _session->timecode_drop_frames();
380                 reset_tc = false;
381         }
382
383         if (reset_tc) {
384                 TimecodeFormat cur_timecode = _session->config.get_timecode_format();
385                 if (Config->get_timecode_sync_frame_rate()) {
386                         /* enforce time-code */
387                         if (!did_reset_tc_format) {
388                                 saved_tc_format = cur_timecode;
389                                 did_reset_tc_format = true;
390                         }
391                         if (cur_timecode != tc_format) {
392                                 if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
393                                         warning << string_compose(_("Session framerate adjusted from %1 TO: MTC's %2."),
394                                                         Timecode::timecode_format_name(cur_timecode),
395                                                         Timecode::timecode_format_name(tc_format))
396                                                 << endmsg;
397                                 }
398                         }
399                         _session->config.set_timecode_format (tc_format);
400                 } else {
401                         /* only warn about TC mismatch */
402                         if (mtc_timecode != tc_format) printed_timecode_warning = false;
403                         if (a3e_timecode != cur_timecode) printed_timecode_warning = false;
404
405                         if (cur_timecode != tc_format && ! printed_timecode_warning) {
406                                 if (ceil(Timecode::timecode_to_frames_per_second(cur_timecode)) != ceil(Timecode::timecode_to_frames_per_second(tc_format))) {
407                                         warning << string_compose(_("Session and MTC framerate mismatch: MTC:%1 %2:%3."),
408                                                                   Timecode::timecode_format_name(tc_format),
409                                                                   PROGRAM_NAME,
410                                                                   Timecode::timecode_format_name(cur_timecode))
411                                                 << endmsg;
412                                 }
413                                 printed_timecode_warning = true;
414                         }
415                 }
416                 mtc_timecode = tc_format;
417                 a3e_timecode = cur_timecode;
418
419                 speedup_due_to_tc_mismatch = timecode.rate / Timecode::timecode_to_frames_per_second(a3e_timecode);
420         }
421
422         /* do a careful conversion of the timecode value to a position
423            so that we take drop/nondrop and all that nonsense into
424            consideration.
425         */
426
427         quarter_frame_duration = (double(_session->sample_rate()) / (double) timecode.rate / 4.0);
428
429         Timecode::timecode_to_sample (timecode, mtc_frame, true, false,
430                 double(_session->sample_rate()),
431                 _session->config.get_subframes_per_frame(),
432                 timecode_negative_offset, timecode_offset
433                 );
434
435         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC at %1 TC %2 = mtc_frame %3 (from full message ? %4) tc-ratio %5\n",
436                                                  now, timecode, mtc_frame, was_full, speedup_due_to_tc_mismatch));
437
438         if (was_full || outside_window (mtc_frame)) {
439                 DEBUG_TRACE (DEBUG::MTC, string_compose ("update_mtc_time: full TC %1 or outside window %2 MTC %3\n", was_full, outside_window (mtc_frame), mtc_frame));
440                 _session->set_requested_return_sample (-1);
441                 _session->request_transport_speed (0, TRS_MTC);
442                 _session->request_locate (mtc_frame, false, TRS_MTC);
443                 update_mtc_status (MIDI::MTC_Stopped);
444                 reset (false);
445                 reset_window (mtc_frame);
446         } else {
447
448                 /* we've had the first set of 8 qtr sample messages, determine position
449                    and allow continuing qtr sample messages to provide position
450                    and speed information.
451                 */
452
453                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
454                    samples) after the instance when the contents of the mtc quarter
455                    samples were decided. Add time to compensate for the elapsed 1.75
456                    samples.
457                 */
458                 double qtr = quarter_frame_duration;
459                 long int mtc_off = (long) rint(7.0 * qtr);
460
461                 DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
462                                                          mtc_frame, (4.0*qtr), _session->samples_per_timecode_frame()));
463
464                 switch (parser.mtc_running()) {
465                 case MTC_Backward:
466                         mtc_frame -= mtc_off;
467                         qtr *= -1.0;
468                         break;
469                 case MTC_Forward:
470                         mtc_frame += mtc_off;
471                         break;
472                 default:
473                         break;
474                 }
475
476                 DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame (w/offset) = %1\n", mtc_frame));
477
478                 if (now) {
479                         if (first_mtc_timestamp == 0 || current.timestamp == 0) {
480                                 first_mtc_timestamp = now;
481                                 init_mtc_dll(mtc_frame, qtr);
482                                 mtc_frame_dll = mtc_frame;
483                         }
484                         current.update (mtc_frame, now, current.speed);
485                         reset_window (mtc_frame);
486                 }
487         }
488
489         busy_guard2++;
490 }
491
492 void
493 MTC_TransportMaster::update_mtc_status (MIDI::MTC_Status status)
494 {
495         /* XXX !!! thread safety ... called from MIDI I/O context
496          * on locate (via ::update_mtc_time())
497          */
498         DEBUG_TRACE (DEBUG::MTC, string_compose("MTC_TransportMaster::update_mtc_status - TID:%1 MTC:%2\n", pthread_name(), mtc_frame));
499         return; // why was this fn needed anyway ? it just messes up things -> use reset.
500         busy_guard1++;
501
502         switch (status) {
503         case MTC_Stopped:
504                 current.update (mtc_frame, 0, 0);
505                 break;
506
507         case MTC_Forward:
508                 current.update (mtc_frame, 0, 0);
509                 break;
510
511         case MTC_Backward:
512                 current.update (mtc_frame, 0, 0);
513                 break;
514         }
515         busy_guard2++;
516 }
517
518 void
519 MTC_TransportMaster::reset_window (samplepos_t root)
520 {
521         /* if we're waiting for the master to catch us after seeking ahead, keep the window
522            of acceptable MTC samples wide open. otherwise, shrink it down to just 2 video frames
523            ahead of the window root (taking direction into account).
524         */
525
526         samplecnt_t const d = (quarter_frame_duration * 4 * sample_tolerance);
527
528         switch (parser.mtc_running()) {
529         case MTC_Forward:
530                 window_begin = root;
531                 transport_direction = 1;
532                 window_end = root + d;
533                 break;
534
535         case MTC_Backward:
536                 transport_direction = -1;
537                 if (root > d) {
538                         window_begin = root - d;
539                         window_end = root;
540                 } else {
541                         window_begin = 0;
542                 }
543                 window_end = root;
544                 break;
545
546         default:
547                 /* do nothing */
548                 break;
549         }
550
551         DEBUG_TRACE (DEBUG::MTC, string_compose ("reset MTC window @ %3, now %1 .. %2\n", window_begin, window_end, root));
552 }
553
554 Timecode::TimecodeFormat
555 MTC_TransportMaster::apparent_timecode_format () const
556 {
557         return mtc_timecode;
558 }
559
560 std::string
561 MTC_TransportMaster::position_string() const
562 {
563         SafeTime last;
564         current.safe_read (last);
565         if (last.timestamp == 0 || reset_pending) {
566                 return " --:--:--:--";
567         }
568         return Timecode::timecode_format_sampletime(
569                 last.position,
570                 double(_session->sample_rate()),
571                 Timecode::timecode_to_frames_per_second(mtc_timecode),
572                 Timecode::timecode_has_drop_frames(mtc_timecode));
573 }
574
575 std::string
576 MTC_TransportMaster::delta_string () const
577 {
578         char delta[80];
579         SafeTime last;
580         current.safe_read (last);
581
582         delta[0] = '\0';
583
584         if (last.timestamp == 0 || reset_pending) {
585                 snprintf(delta, sizeof(delta), "\u2012\u2012\u2012\u2012");
586         } else {
587                 snprintf(delta, sizeof(delta), "\u0394<span foreground=\"green\" face=\"monospace\" >%s%s%" PRIi64 "</span>sm",
588                                 LEADINGZERO(abs(_current_delta)), PLUSMINUS(-_current_delta), abs(_current_delta));
589         }
590         return std::string(delta);
591 }
592
593 void
594 MTC_TransportMaster::unregister_port ()
595 {
596         _midi_port.reset ();
597         TransportMaster::unregister_port ();
598 }