2 * Copyright (C) 2018 Paul Davis (paul@linuxaudiosystems.com)
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, or (at your option)
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.
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 Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "ardour/audioengine.h"
20 #include "ardour/debug.h"
21 #include "ardour/disk_reader.h"
22 #include "ardour/session.h"
23 #include "ardour/transport_master_manager.h"
25 #include "pbd/boost_debug.cc"
28 #if __cplusplus > 199711L
29 #define local_signbit(x) std::signbit (x)
31 #define local_signbit(x) ((((__int64*)(&z))*) & 0x8000000000000000)
34 using namespace ARDOUR;
37 const std::string TransportMasterManager::state_node_name = X_("TransportMasters");
38 TransportMasterManager* TransportMasterManager::_instance = 0;
40 TransportMasterManager::TransportMasterManager()
42 , _master_position (0)
44 , _master_invalid_this_cycle (false)
45 , master_dll_initstate (0)
49 TransportMasterManager::~TransportMasterManager ()
55 TransportMasterManager::set_default_configuration ()
61 /* setup default transport masters. Most people will never need any
65 add (Engine, X_("JACK Transport"), false);
66 add (MTC, X_("MTC"), false);
67 add (LTC, X_("LTC"), false);
68 add (MIDIClock, X_("MIDI Clock"), false);
74 _current_master = _transport_masters.back();
75 cerr << "default current master (back) is " << _current_master->name() << endl;
80 TransportMasterManager::set_session (Session* s)
82 /* Called by AudioEngine in process context, synchronously with it's
83 * own "adoption" of the Session. The call will occur before the first
84 * call to ::pre_process_transport_masters().
87 Glib::Threads::RWLock::ReaderLock lm (lock);
89 config_connection.disconnect ();
93 for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
94 (*tm)->set_session (s);
98 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&TransportMasterManager::parameter_changed, this, _1));
104 TransportMasterManager::parameter_changed (std::string const & what)
106 if (what == "external-sync") {
107 if (!_session->config.get_external_sync()) {
109 DiskReader::set_no_disk_output (false);
114 TransportMasterManager&
115 TransportMasterManager::instance()
118 _instance = new TransportMasterManager();
123 // Called from AudioEngine::process_callback() BEFORE Session::process() is called. Each transport master has processed any incoming data for this cycle,
124 // and this method computes the transport speed that Ardour should use to get into and remain in sync with the master.
127 TransportMasterManager::pre_process_transport_masters (pframes_t nframes, samplepos_t now)
129 Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
135 boost::optional<samplepos_t> session_pos;
138 session_pos = _session->audible_sample();
141 if (Config->get_run_all_transport_masters_always()) {
142 for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
143 if ((*tm)->check_collect()) {
144 (*tm)->pre_process (nframes, now, session_pos);
153 /* if we're not running ALL transport masters, but still have a current
154 * one, then we should run that one all the time so that we know
155 * precisely where it is when we starting chasing it ...
158 if (!Config->get_run_all_transport_masters_always() && _current_master) {
159 _current_master->pre_process (nframes, now, session_pos);
162 if (!_session->config.get_external_sync()) {
163 DEBUG_TRACE (DEBUG::Slave, string_compose ("no external sync, use session actual speed of %1\n", _session->actual_speed() ? _session->actual_speed() : 1.0));
164 return _session->actual_speed () ? _session->actual_speed() : 1.0;
167 /* --- NOT REACHED UNLESS CHASING (i.e. _session->config.get_external_sync() is true ------*/
169 if (!_current_master->ok()) {
171 _session->request_transport_speed (0.0, false, _current_master->request_type());
172 DEBUG_TRACE (DEBUG::Slave, "no roll2 - master has failed\n");
173 _master_invalid_this_cycle = true;
177 if (!_current_master->locked()) {
178 DEBUG_TRACE (DEBUG::Slave, "no roll4 - not locked\n");
179 _master_invalid_this_cycle = true;
184 samplepos_t ignore1, ignore2;
186 if (!_current_master->speed_and_position (_master_speed, _master_position, ignore1, ignore2, now)) {
190 if (_master_speed != 0.0) {
192 samplepos_t delta = _master_position;
194 if (_session->compute_audible_delta (delta)) {
196 if (master_dll_initstate == 0) {
198 init_transport_master_dll (_master_speed, _master_position);
199 // _master_invalid_this_cycle = true;
200 DEBUG_TRACE (DEBUG::Slave, "no roll3 - still initializing master DLL\n");
201 master_dll_initstate = _master_speed > 0.0 ? 1 : -1;
206 /* compute delta or "error" between the computed master_position for
207 * this cycle and the current session position.
209 * Remember: ::speed_and_position() is being called in process context
210 * but returns the predicted speed+position for the start of this process cycle,
211 * not just the most recent timestamp received by the current master object.
214 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()));
216 if (delta > _current_master->resolution()) {
218 // init_transport_master_dll (_master_speed, _master_position);
220 if (!_session->actively_recording()) {
221 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave delta %1 greater than slave resolution %2 => no disk output\n", delta, _current_master->resolution()));
222 /* run routes as normal, but no disk output */
223 DiskReader::set_no_disk_output (true);
225 DiskReader::set_no_disk_output (false);
228 DiskReader::set_no_disk_output (false);
231 /* inject DLL with new data */
233 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()));
235 const double e = delta;
241 engine_speed = (t1 - t0) / nframes;
243 DEBUG_TRACE (DEBUG::Slave, string_compose ("slave @ %1 speed %2 cur delta %3 matching speed %4\n", _master_position, _master_speed, delta, engine_speed));
245 /* provide a .1% deadzone to lock the speed */
246 if (fabs (engine_speed - 1.0) <= 0.001) {
250 if (_current_master->sample_clock_synced() && engine_speed != 0.0f) {
252 /* if the master is synced to our audio interface via word-clock or similar, then we assume that its speed is binary: 0.0 or 1.0
253 (since our sample clock cannot change with respect to it).
255 if (engine_speed > 0.0) {
257 } else if (engine_speed < 0.0) {
262 /* speed is set, we're locked, and good to go */
263 DEBUG_TRACE (DEBUG::Slave, string_compose ("%1: computed speed-to-follow-master as %2\n", _current_master->name(), engine_speed));
267 /* session has not finished with latency compensation yet, so we cannot compute the
268 difference between the master and the session.
278 _master_invalid_this_cycle = false;
280 DEBUG_TRACE (DEBUG::Slave, string_compose ("computed resampling ratio as %1 with position = %2 and speed = %3\n", engine_speed, _master_position, _master_speed));
287 TransportMasterManager::init_transport_master_dll (double speed, samplepos_t pos)
289 /* the bandwidth of the DLL is a trade-off,
290 * because the max-speed of the transport in ardour is
291 * limited to +-8.0, a larger bandwidth would cause oscillations
293 * But this is only really a problem if the user performs manual
294 * seeks while transport is running and slaved to some timecode-y master.
297 AudioEngine* ae = AudioEngine::instance();
299 double const omega = 2.0 * M_PI * double(ae->samples_per_cycle()) / 2.0 / double(ae->sample_rate());
300 b = 1.4142135623730950488 * omega;
303 const int direction = (speed >= 0.0 ? 1 : -1);
305 master_dll_initstate = direction;
307 e2 = double (direction * ae->samples_per_cycle());
311 DEBUG_TRACE (DEBUG::Slave, string_compose ("[re-]init ENGINE DLL %1 %2 %3 from %4 %5\n", t0, t1, e2, speed, pos));
315 TransportMasterManager::add (SyncSource type, std::string const & name, bool removeable)
318 boost::shared_ptr<TransportMaster> tm;
320 DEBUG_TRACE (DEBUG::Slave, string_compose ("adding new transport master, type %1 name %2 removeable %3\n", enum_2_string (type), name, removeable));
323 Glib::Threads::RWLock::WriterLock lm (lock);
325 for (TransportMasters::const_iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
326 if ((*t)->name() == name) {
327 error << string_compose (_("There is already a transport master named \"%1\" - not duplicated"), name) << endmsg;
332 tm = TransportMaster::factory (type, name, removeable);
333 boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
334 ret = add_locked (tm);
345 TransportMasterManager::add_locked (boost::shared_ptr<TransportMaster> tm)
353 tm->set_session (_session);
356 _transport_masters.push_back (tm);
361 TransportMasterManager::remove (std::string const & name)
364 boost::shared_ptr<TransportMaster> tm;
367 Glib::Threads::RWLock::WriterLock lm (lock);
369 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
370 if ((*t)->name() == name) {
371 if (!(*t)->removeable()) {
375 _transport_masters.erase (t);
390 TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c)
393 if (find (_transport_masters.begin(), _transport_masters.end(), c) == _transport_masters.end()) {
394 warning << string_compose (X_("programming error: attempt to use unknown transport master \"%1\"\n"), c->name());
401 _master_position = 0;
403 master_dll_initstate = 0;
405 DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", (c ? c->name() : string ("none"))));
411 TransportMasterManager::set_current (boost::shared_ptr<TransportMaster> c)
414 boost::shared_ptr<TransportMaster> old (_current_master);
417 Glib::Threads::RWLock::WriterLock lm (lock);
418 ret = set_current_locked (c);
422 CurrentChanged (old, _current_master); // EMIT SIGNAL
429 TransportMasterManager::set_current (SyncSource ss)
432 boost::shared_ptr<TransportMaster> old (_current_master);
435 Glib::Threads::RWLock::WriterLock lm (lock);
437 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
438 if ((*t)->type() == ss) {
439 ret = set_current_locked (*t);
446 CurrentChanged (old, _current_master); // EMIT SIGNAL
454 TransportMasterManager::set_current (std::string const & str)
457 boost::shared_ptr<TransportMaster> old (_current_master);
460 Glib::Threads::RWLock::WriterLock lm (lock);
462 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
463 if ((*t)->name() == str) {
464 ret = set_current_locked (*t);
471 CurrentChanged (old, _current_master); // EMIT SIGNAL
479 TransportMasterManager::clear ()
482 Glib::Threads::RWLock::WriterLock lm (lock);
483 _current_master.reset ();
484 _transport_masters.clear ();
487 Removed (boost::shared_ptr<TransportMaster>());
491 TransportMasterManager::set_state (XMLNode const & node, int version)
493 assert (node.name() == state_node_name);
495 XMLNodeList const & children = node.children();
498 Glib::Threads::RWLock::WriterLock lm (lock);
500 _current_master.reset ();
501 boost_debug_list_ptrs ();
503 _transport_masters.clear ();
505 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
507 boost::shared_ptr<TransportMaster> tm = TransportMaster::factory (**c);
508 boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
510 if (add_locked (tm)) {
514 /* we know it is the last thing added to the list of masters */
516 _transport_masters.back()->set_state (**c, version);
520 std::string current_master;
521 if (node.get_property (X_("current"), current_master)) {
522 set_current (current_master);
531 TransportMasterManager::get_state ()
533 XMLNode* node = new XMLNode (state_node_name);
535 if (_current_master) {
536 node->set_property (X_("current"), _current_master->name());
539 Glib::Threads::RWLock::ReaderLock lm (lock);
541 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
542 node->add_child_nocopy ((*t)->get_state());
548 boost::shared_ptr<TransportMaster>
549 TransportMasterManager::master_by_type (SyncSource src) const
551 Glib::Threads::RWLock::ReaderLock lm (lock);
553 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
554 if ((*tm)->type() == src) {
559 return boost::shared_ptr<TransportMaster> ();
563 TransportMasterManager::engine_stopped ()
565 DEBUG_TRACE (DEBUG::Slave, "engine stopped, reset all transport masters\n");
567 Glib::Threads::RWLock::ReaderLock lm (lock);
569 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
570 (*tm)->reset (false);
576 TransportMasterManager::restart ()
580 if ((node = Config->transport_master_state()) != 0) {
581 if (TransportMasterManager::instance().set_state (*node, Stateful::loading_state_version)) {
582 error << _("Cannot restore transport master manager") << endmsg;
586 if (TransportMasterManager::instance().set_default_configuration ()) {
587 error << _("Cannot initialize transport master manager") << endmsg;