1 /*
2 * Copyright (C) 2018-2019 Paul Davis <paul@linuxaudiosystems.com>
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 along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "pbd/stateful.h"
20
21 #include "ardour/audioengine.h"
22 #include "ardour/boost_debug.h"
23 #include "ardour/debug.h"
24 #include "ardour/disk_reader.h"
25 #include "ardour/session.h"
26 #include "ardour/rc_configuration.h"
27 #include "ardour/transport_master_manager.h"
28
29 #include "pbd/i18n.h"
30
31 using namespace std;
32 using namespace ARDOUR;
33 using namespace PBD;
34
35 const std::string TransportMasterManager::state_node_name = X_("TransportMasters");
36 TransportMasterManager* TransportMasterManager::_instance = 0;
37
TransportMasterManager()38 TransportMasterManager::TransportMasterManager()
39 : _master_speed (0)
40 , _master_position (0)
41 , _session (0)
42 , _master_invalid_this_cycle (false)
43 , disk_output_blocked (false)
44 , master_dll_initstate (0)
45 {
46 }
47
~TransportMasterManager()48 TransportMasterManager::~TransportMasterManager ()
49 {
50 Glib::Threads::RWLock::WriterLock lm (lock);
51 _current_master.reset ();
52 _transport_masters.clear ();
53 }
54
55 TransportMasterManager&
create()56 TransportMasterManager::create ()
57 {
58 assert (!_instance);
59
60 _instance = new TransportMasterManager;
61
62 XMLNode* tmm_node = Config->transport_master_state ();
63
64 if (tmm_node) {
65 _instance->set_state (*tmm_node, Stateful::current_state_version);
66 } else {
67 _instance->set_default_configuration ();
68 }
69
70 return *_instance;
71 }
72
73 int
set_default_configuration()74 TransportMasterManager::set_default_configuration ()
75 {
76 try {
77
78 clear ();
79
80 /* setup default transport masters. Most people will never need any
81 others
82 */
83
84 add (Engine, X_("JACK Transport"), false);
85 add (MTC, X_("MTC"), false);
86 add (LTC, X_("LTC"), false);
87 add (MIDIClock, X_("MIDI Clock"), false);
88
89 } catch (...) {
90 return -1;
91 }
92
93 _current_master = _transport_masters.back();
94 return 0;
95 }
96
97 void
set_session(Session * s)98 TransportMasterManager::set_session (Session* s)
99 {
100 /* Called by AudioEngine in process context, synchronously with it's
101 * own "adoption" of the Session. The call will occur before the first
102 * call to ::pre_process_transport_masters().
103 */
104
105 Glib::Threads::RWLock::ReaderLock lm (lock);
106
107 maybe_restore_tc_format ();
108
109 config_connection.disconnect ();
110
111 _session = s;
112
113 for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
114 (*tm)->set_session (s);
115 }
116
117 if (_session) {
118 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&TransportMasterManager::parameter_changed, this, _1));
119 }
120
121 }
122
123 void
parameter_changed(std::string const & what)124 TransportMasterManager::parameter_changed (std::string const & what)
125 {
126 if (what == "external-sync") {
127 if (!_session->config.get_external_sync()) {
128 /* disabled */
129 unblock_disk_output ();
130 }
131 }
132 }
133
134 TransportMasterManager&
instance()135 TransportMasterManager::instance()
136 {
137 if (!_instance) {
138 fatal << string_compose (_("programming error:%1"), X_("TransportMasterManager::instance() called without an instance!")) << endmsg;
139 abort (); /* NOTREACHED */
140 }
141 return *_instance;
142 }
143
144 void
destroy()145 TransportMasterManager::destroy()
146 {
147 delete _instance;
148 _instance = 0;
149 }
150
151 // Called from AudioEngine::process_callback() BEFORE Session::process() is called. Each transport master has processed any incoming data for this cycle,
152 // and this method computes the transport speed that Ardour should use to get into and remain in sync with the master.
153 //
154 double
pre_process_transport_masters(pframes_t nframes,samplepos_t now)155 TransportMasterManager::pre_process_transport_masters (pframes_t nframes, samplepos_t now)
156 {
157 Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
158
159 if (!lm.locked()) {
160 return 1.0;
161 }
162
163 boost::optional<samplepos_t> session_pos;
164
165 if (_session) {
166 session_pos = _session->audible_sample();
167 }
168
169 if (Config->get_run_all_transport_masters_always()) {
170 for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
171 if ((*tm)->check_collect()) {
172 (*tm)->pre_process (nframes, now, session_pos);
173 }
174 }
175 }
176
177 if (!_session) {
178 return 1.0;
179 }
180
181 /* if we're not running ALL transport masters, but still have a current
182 * one, then we should run that one all the time so that we know
183 * precisely where it is when we starting chasing it ...
184 */
185
186 if (!Config->get_run_all_transport_masters_always() && _current_master) {
187 _current_master->pre_process (nframes, now, session_pos);
188 }
189
190 if (!_session->config.get_external_sync()) {
191 maybe_restore_tc_format ();
192 DEBUG_TRACE (DEBUG::Slave, string_compose ("no external sync, use session actual speed of %1\n", _session->actual_speed() ? _session->actual_speed() : 1.0));
193 return _session->actual_speed () ? _session->actual_speed() : 1.0;
194 }
195
196 /* --- NOT REACHED UNLESS CHASING (i.e. _session->config.get_external_sync() is true ------*/
197
198 if (!_current_master->ok()) {
199 /* stop */
200 _session->request_stop (false, false, _current_master->request_type());
201 DEBUG_TRACE (DEBUG::Slave, "no roll2 - master has failed\n");
202 _master_invalid_this_cycle = true;
203 return 1.0;
204 }
205
206 if (!_current_master->locked()) {
207 DEBUG_TRACE (DEBUG::Slave, "no roll4 - not locked\n");
208 _master_invalid_this_cycle = true;
209 return 1.0;
210 }
211
212 double engine_speed;
213 samplepos_t ignore1, ignore2;
214
215 if (!_current_master->speed_and_position (_master_speed, _master_position, ignore1, ignore2, now)) {
216 return 1.0;
217 }
218
219 DEBUG_TRACE (DEBUG::Slave, string_compose ("Current master at %1 moving at %2\n", _master_position, _master_speed));
220
221 if (_current_master->sample_clock_synced()) {
222
223 /* No master DLL required. Speed identified by the master is
224 * our speed, quantized to {1.0, 0.0, -1.0}
225 */
226
227 if (_master_speed > 0.0f) {
228 engine_speed = 1.0f;
229 } else if (_master_speed < 0.0f) {
230 engine_speed = -1.0f;
231 } else {
232 engine_speed = 0.0f;
233 }
234
235 DEBUG_TRACE (DEBUG::Slave, string_compose ("S-clock synced master speed %1 used as %2\n", _master_speed, engine_speed));
236
237 } else if (_master_speed != 0.0) {
238
239 samplepos_t delta = _master_position;
240
241 if (_session->compute_audible_delta (delta)) {
242
243 if (master_dll_initstate == 0) {
244
245 init_transport_master_dll (_master_speed, _master_position);
246 DEBUG_TRACE (DEBUG::Slave, string_compose ("initializing master DLL, will be %1 next process cycle\n", master_dll_initstate));
247
248 return _master_speed;
249 }
250
251 /* compute delta or "error" between the computed master_position for
252 * this cycle and the current session position.
253 *
254 * Remember: ::speed_and_position() is being called in process context
255 * but returns the predicted speed+position for the start of this process cycle,
256 * not just the most recent timestamp received by the current master object.
257 */
258
259 DEBUG_TRACE (DEBUG::Slave, string_compose ("master DLL: delta = %1 (%2 vs %3) res: %4\n", delta, _master_position, _session->transport_sample(), _current_master->resolution()));
260
261 if (delta > _current_master->resolution()) {
262
263 // init_transport_master_dll (_master_speed, _master_position);
264
265 if (!_session->actively_recording()) {
266 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave delta %1 greater than slave resolution %2 => no disk output\n", delta, _current_master->resolution()));
267 /* run routes as normal, but no disk output */
268 block_disk_output ();
269 } else {
270 unblock_disk_output ();
271 }
272 } else {
273 unblock_disk_output ();
274 }
275
276 /* inject DLL with new data */
277
278 DEBUG_TRACE (DEBUG::Slave, string_compose ("feed master DLL t0 %1 t1 %2 e %3 %4 e2 %5 sess %6\n", t0, t1, delta, _master_position, e2, _session->transport_sample()));
279
280 const double e = delta;
281
282 t0 = t1;
283 t1 += b * e + e2;
284 e2 += c * e;
285
286 engine_speed = (t1 - t0) / nframes;
287
288 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave @ %1 speed %2 cur delta %3 matching speed %4\n", _master_position, _master_speed, delta, engine_speed));
289
290 /* provide a .1% deadzone to lock the speed */
291 if (fabs (engine_speed - 1.0) <= 0.001) {
292 engine_speed = 1.0;
293 }
294
295 /* speed is set, we're locked, and good to go */
296 DEBUG_TRACE (DEBUG::Slave, string_compose ("%1: computed speed-to-follow-master as %2\n", _current_master->name(), engine_speed));
297
298 } else {
299
300 /* session has not finished with latency compensation yet, so we cannot compute the
301 difference between the master and the session.
302 */
303 engine_speed = 1.0;
304 }
305
306 } else {
307
308 engine_speed = 1.0;
309 }
310
311 _master_invalid_this_cycle = false;
312
313 maybe_set_tc_format ();
314
315 DEBUG_TRACE (DEBUG::Slave, string_compose ("computed resampling ratio as %1 with position = %2 and speed = %3\n", engine_speed, _master_position, _master_speed));
316
317 return engine_speed;
318 }
319
320 void
maybe_restore_tc_format()321 TransportMasterManager::maybe_restore_tc_format ()
322 {
323 if (_session && _session_tc_format) {
324 _session->config.set_timecode_format (*_session_tc_format);
325 }
326 _session_tc_format.reset ();
327 }
328
329 void
maybe_set_tc_format()330 TransportMasterManager::maybe_set_tc_format ()
331 {
332 if (!Config->get_timecode_sync_frame_rate() || !_session) {
333 return;
334 }
335 boost::shared_ptr<TimecodeTransportMaster> tcm;
336 if ((tcm = boost::dynamic_pointer_cast<TimecodeTransportMaster>(_current_master)) == 0) {
337 return;
338 }
339
340 if (!tcm->apparent_timecode_format_valid ()) {
341 return;
342 }
343
344 Timecode::TimecodeFormat stf = _session->config.get_timecode_format();
345 Timecode::TimecodeFormat mtf = tcm->apparent_timecode_format ();
346
347 if (stf == mtf) {
348 return;
349 }
350
351 /* save session's original TC */
352 if (!_session_tc_format) {
353 _session_tc_format = stf;
354 }
355
356 warning << string_compose(_("Transport master adjusted framerate from %1 to %2."),
357 Timecode::timecode_format_name(stf),
358 Timecode::timecode_format_name(mtf))
359 << endmsg;
360
361 _session->config.set_timecode_format (mtf);
362 }
363
364 void
init_transport_master_dll(double speed,samplepos_t pos)365 TransportMasterManager::init_transport_master_dll (double speed, samplepos_t pos)
366 {
367 /* the bandwidth of the DLL is a trade-off,
368 * because the max-speed of the transport in ardour is
369 * limited to +-8.0, a larger bandwidth would cause oscillations
370 *
371 * But this is only really a problem if the user performs manual
372 * seeks while transport is running and slaved to some timecode-y master.
373 */
374
375 AudioEngine* ae = AudioEngine::instance();
376
377 double const omega = 2.0 * M_PI * double(ae->samples_per_cycle()) / 2.0 / double(ae->sample_rate());
378 b = 1.4142135623730950488 * omega;
379 c = omega * omega;
380
381 const int direction = (speed >= 0.0 ? 1 : -1);
382
383 master_dll_initstate = direction;
384
385 e2 = double (direction * ae->samples_per_cycle());
386 t0 = double (pos);
387 t1 = t0 + e2;
388
389 DEBUG_TRACE (DEBUG::Slave, string_compose ("[re-]init ENGINE DLL %1 %2 %3 from %4 %5\n", t0, t1, e2, speed, pos));
390 }
391
392 int
add(SyncSource type,std::string const & name,bool removeable)393 TransportMasterManager::add (SyncSource type, std::string const & name, bool removeable)
394 {
395 int ret = 0;
396 boost::shared_ptr<TransportMaster> tm;
397
398 DEBUG_TRACE (DEBUG::Slave, string_compose ("adding new transport master, type %1 name %2 removeable %3\n", enum_2_string (type), name, removeable));
399
400 {
401 Glib::Threads::RWLock::WriterLock lm (lock);
402
403 for (TransportMasters::const_iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
404 if ((*t)->name() == name) {
405 error << string_compose (_("There is already a transport master named \"%1\" - not duplicated"), name) << endmsg;
406 return -1;
407 }
408 }
409
410 tm = TransportMaster::factory (type, name, removeable);
411
412 if (!tm) {
413 return -1;
414 }
415
416 BOOST_MARK_TMM (tm);
417
418 ret = add_locked (tm);
419 }
420
421 if (ret == 0) {
422 Added (tm);
423 }
424
425 return ret;
426 }
427
428 int
add_locked(boost::shared_ptr<TransportMaster> tm)429 TransportMasterManager::add_locked (boost::shared_ptr<TransportMaster> tm)
430 {
431 if (!tm) {
432 return -1;
433 }
434
435
436 if (_session) {
437 tm->set_session (_session);
438 }
439
440 _transport_masters.push_back (tm);
441 return 0;
442 }
443
444 int
remove(std::string const & name)445 TransportMasterManager::remove (std::string const & name)
446 {
447 int ret = -1;
448 boost::shared_ptr<TransportMaster> tm;
449
450 {
451 Glib::Threads::RWLock::WriterLock lm (lock);
452
453 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
454 if ((*t)->name() == name) {
455 if (!(*t)->removeable()) {
456 return -1;
457 }
458 tm = *t;
459 _transport_masters.erase (t);
460 ret = 0;
461 break;
462 }
463 }
464 }
465
466 if (ret == 0) {
467 Removed (tm);
468 }
469
470 return ret;
471 }
472
473 int
set_current_locked(boost::shared_ptr<TransportMaster> c)474 TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c)
475 {
476 if (c) {
477 if (find (_transport_masters.begin(), _transport_masters.end(), c) == _transport_masters.end()) {
478 warning << string_compose (X_("programming error: attempt to use unknown transport master \"%1\"\n"), c->name());
479 return -1;
480 }
481 }
482
483 maybe_restore_tc_format ();
484
485 if (!c->usable()) {
486 return -1;
487 }
488
489 /* this is called from within the process() call stack, but *after* the
490 * call to ::pre_process_transport_masters()
491 */
492
493 _current_master = c;
494 _master_speed = 0;
495 _master_position = 0;
496 _master_invalid_this_cycle = true;
497
498 master_dll_initstate = 0;
499
500 unblock_disk_output ();
501
502 if (c && c->type() == Engine) {
503
504 /* We cannot sync with an already moving JACK transport mechanism, so
505 * stop it before we start.
506 */
507
508 AudioEngine::instance()->transport_stop ();
509 }
510
511 DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", (c ? c->name() : string ("none"))));
512
513 return 0;
514 }
515
516 int
set_current(boost::shared_ptr<TransportMaster> c)517 TransportMasterManager::set_current (boost::shared_ptr<TransportMaster> c)
518 {
519 int ret = -1;
520 boost::shared_ptr<TransportMaster> old (_current_master);
521
522 {
523 Glib::Threads::RWLock::WriterLock lm (lock);
524 ret = set_current_locked (c);
525 }
526
527 if (ret == 0) {
528 CurrentChanged (old, _current_master); // EMIT SIGNAL
529 }
530
531 return ret;
532 }
533
534 int
set_current(SyncSource ss)535 TransportMasterManager::set_current (SyncSource ss)
536 {
537 int ret = -1;
538 boost::shared_ptr<TransportMaster> old (_current_master);
539
540 {
541 Glib::Threads::RWLock::WriterLock lm (lock);
542
543 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
544 if ((*t)->type() == ss) {
545 ret = set_current_locked (*t);
546 break;
547 }
548 }
549 }
550
551 if (ret == 0) {
552 CurrentChanged (old, _current_master); // EMIT SIGNAL
553 }
554
555 return ret;
556 }
557
558
559 int
set_current(std::string const & str)560 TransportMasterManager::set_current (std::string const & str)
561 {
562 int ret = -1;
563 boost::shared_ptr<TransportMaster> old (_current_master);
564
565 {
566 Glib::Threads::RWLock::WriterLock lm (lock);
567
568 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
569 if ((*t)->name() == str) {
570 ret = set_current_locked (*t);
571 break;
572 }
573 }
574 }
575
576 if (ret == 0) {
577 CurrentChanged (old, _current_master); // EMIT SIGNAL
578 }
579
580 return ret;
581 }
582
583
584 void
clear()585 TransportMasterManager::clear ()
586 {
587 {
588 Glib::Threads::RWLock::WriterLock lm (lock);
589 _current_master.reset ();
590 _transport_masters.clear ();
591 }
592
593 Removed (boost::shared_ptr<TransportMaster>());
594 }
595
596 int
set_state(XMLNode const & node,int version)597 TransportMasterManager::set_state (XMLNode const & node, int version)
598 {
599 assert (node.name() == state_node_name);
600
601 XMLNodeList const & children = node.children();
602
603 {
604 Glib::Threads::RWLock::WriterLock lm (lock);
605
606 _current_master.reset ();
607 #if 0
608 boost_debug_list_ptrs ();
609 #endif
610
611 /* TramsportMasters live for the entire life of the
612 * program. TransportMasterManager::set_state() should only be
613 * called at the start of the program, and there should be no
614 * transport masters at that time.
615 */
616
617 assert (_transport_masters.empty());
618
619 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
620
621 boost::shared_ptr<TransportMaster> tm = TransportMaster::factory (**c);
622
623 if (!tm) {
624 continue;
625 }
626
627 BOOST_MARK_TMM (tm);
628
629 if (add_locked (tm)) {
630 continue;
631 }
632
633 /* we know it is the last thing added to the list of masters */
634
635 _transport_masters.back()->set_state (**c, version);
636 }
637 }
638
639 /* fallback choice, lives on until ::restart() is called after the
640 * engine is running.
641 */
642
643 set_current (MTC);
644
645 return 0;
646 }
647
648 XMLNode&
get_state()649 TransportMasterManager::get_state ()
650 {
651 XMLNode* node = new XMLNode (state_node_name);
652
653 if (_current_master) {
654 node->set_property (X_("current"), _current_master->name());
655 }
656
657 Glib::Threads::RWLock::ReaderLock lm (lock);
658
659 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
660 node->add_child_nocopy ((*t)->get_state());
661 }
662
663 return *node;
664 }
665
666 boost::shared_ptr<TransportMaster>
master_by_type(SyncSource src) const667 TransportMasterManager::master_by_type (SyncSource src) const
668 {
669 Glib::Threads::RWLock::ReaderLock lm (lock);
670
671 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
672 if ((*tm)->type() == src) {
673 return *tm;
674 }
675 }
676
677 return boost::shared_ptr<TransportMaster> ();
678 }
679
680 boost::shared_ptr<TransportMaster>
master_by_port(boost::shared_ptr<Port> const & p) const681 TransportMasterManager::master_by_port (boost::shared_ptr<Port> const &p) const
682 {
683 Glib::Threads::RWLock::ReaderLock lm (lock);
684
685 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
686 if ((*tm)->port() == p) {
687 return *tm;
688 }
689 }
690
691 return boost::shared_ptr<TransportMaster> ();
692
693 }
694
695 void
engine_stopped()696 TransportMasterManager::engine_stopped ()
697 {
698 DEBUG_TRACE (DEBUG::Slave, "engine stopped, reset all transport masters\n");
699 {
700 Glib::Threads::RWLock::ReaderLock lm (lock);
701
702 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
703 (*tm)->reset (false);
704 }
705 }
706 }
707
708 void
restart()709 TransportMasterManager::restart ()
710 {
711 XMLNode* node;
712
713 if ((node = Config->transport_master_state()) != 0) {
714
715 {
716 Glib::Threads::RWLock::ReaderLock lm (lock);
717
718 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
719 (*tm)->connect_port_using_state ();
720 (*tm)->reset (false);
721 }
722 }
723
724 /* engine is running, connections are viable ... try to set current */
725
726 std::string current_master;
727
728 if (node->get_property (X_("current"), current_master)) {
729
730 /* may fal if current_master is not usable */
731
732 set_current (current_master);
733 }
734
735 } else {
736 if (TransportMasterManager::instance().set_default_configuration ()) {
737 error << _("Cannot initialize transport master manager") << endmsg;
738 /* XXX now what? */
739 }
740 }
741 }
742
743 void
reconnect_ports()744 TransportMasterManager::reconnect_ports ()
745 {
746 DEBUG_TRACE (DEBUG::Slave, "reconnecting all transport master ports\n");
747 {
748 Glib::Threads::RWLock::ReaderLock lm (lock);
749
750 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
751 (*tm)->connect_port_using_state ();
752 }
753 }
754 }
755
756 void
block_disk_output()757 TransportMasterManager::block_disk_output ()
758 {
759 if (!disk_output_blocked) {
760 //DiskReader::inc_no_disk_output ();
761 disk_output_blocked = true;
762 }
763 }
764
765 void
unblock_disk_output()766 TransportMasterManager::unblock_disk_output ()
767 {
768 if (disk_output_blocked) {
769 //DiskReader::dec_no_disk_output ();
770 disk_output_blocked = false;
771 }
772 }
773
774 void
reinit(double speed,samplepos_t pos)775 TransportMasterManager::reinit (double speed, samplepos_t pos)
776 {
777 init_transport_master_dll (speed, pos);
778 }
779