Optimize DSP-load calculation, pre-calculate fall-off once
[ardour.git] / libs / ardour / transport_master_manager.cc
1 /*
2  * Copyright (C) 2018 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, or (at your option)
7  * 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 Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
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"
24
25 #include "pbd/boost_debug.cc"
26 #include "pbd/i18n.h"
27
28 #if __cplusplus > 199711L
29 #define local_signbit(x) std::signbit (x)
30 #else
31 #define local_signbit(x) ((((__int64*)(&z))*) & 0x8000000000000000)
32 #endif
33
34 using namespace ARDOUR;
35 using namespace PBD;
36
37 const std::string TransportMasterManager::state_node_name = X_("TransportMasters");
38 TransportMasterManager* TransportMasterManager::_instance = 0;
39
40 TransportMasterManager::TransportMasterManager()
41         : _master_speed (0)
42         , _master_position (0)
43         , _session (0)
44         , _master_invalid_this_cycle (false)
45         , master_dll_initstate (0)
46 {
47 }
48
49 TransportMasterManager::~TransportMasterManager ()
50 {
51         clear ();
52 }
53
54 int
55 TransportMasterManager::set_default_configuration ()
56 {
57         try {
58
59                 clear ();
60
61                 /* setup default transport masters. Most people will never need any
62                    others
63                 */
64
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);
69
70         } catch (...) {
71                 return -1;
72         }
73
74         _current_master = _transport_masters.back();
75         cerr << "default current master (back) is " << _current_master->name() << endl;
76         return 0;
77 }
78
79 void
80 TransportMasterManager::set_session (Session* s)
81 {
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().
85          */
86
87         Glib::Threads::RWLock::ReaderLock lm (lock);
88
89         config_connection.disconnect ();
90
91         _session = s;
92
93         for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
94                 (*tm)->set_session (s);
95         }
96
97         if (_session) {
98                 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&TransportMasterManager::parameter_changed, this, _1));
99         }
100
101 }
102
103 void
104 TransportMasterManager::parameter_changed (std::string const & what)
105 {
106         if (what == "external-sync") {
107                 if (!_session->config.get_external_sync()) {
108                         /* disabled */
109                         DiskReader::set_no_disk_output (false);
110                 }
111         }
112 }
113
114 TransportMasterManager&
115 TransportMasterManager::instance()
116 {
117         if (!_instance) {
118                 _instance = new TransportMasterManager();
119         }
120         return *_instance;
121 }
122
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.
125 //
126 double
127 TransportMasterManager::pre_process_transport_masters (pframes_t nframes, samplepos_t now)
128 {
129         Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
130
131         if (!lm.locked()) {
132                 return 1.0;
133         }
134
135         boost::optional<samplepos_t> session_pos;
136
137         if (_session) {
138                 session_pos = _session->audible_sample();
139         }
140
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);
145                         }
146                 }
147         }
148
149         if (!_session) {
150                 return 1.0;
151         }
152
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 ...
156          */
157
158         if (!Config->get_run_all_transport_masters_always() && _current_master) {
159                 _current_master->pre_process (nframes, now, session_pos);
160         }
161
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;
165         }
166
167         /* --- NOT REACHED UNLESS CHASING (i.e. _session->config.get_external_sync() is true ------*/
168
169         if (!_current_master->ok()) {
170                 /* stop */
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;
174                 return 1.0;
175         }
176
177         if (!_current_master->locked()) {
178                 DEBUG_TRACE (DEBUG::Slave, "no roll4 - not locked\n");
179                 _master_invalid_this_cycle = true;
180                 return 1.0;
181         }
182
183         double engine_speed;
184         samplepos_t ignore1, ignore2;
185
186         if (!_current_master->speed_and_position (_master_speed, _master_position, ignore1, ignore2, now)) {
187                 return 1.0;
188         }
189
190         if (_master_speed != 0.0) {
191
192                 samplepos_t delta = _master_position;
193
194                 if (_session->compute_audible_delta (delta)) {
195
196                         if (master_dll_initstate == 0) {
197
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;
202
203                                 return 1.0;
204                         }
205
206                         /* compute delta or "error" between the computed master_position for
207                          * this cycle and the current session position.
208                          *
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.
212                          */
213
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()));
215
216                         if (delta > _current_master->resolution()) {
217
218                                 // init_transport_master_dll (_master_speed, _master_position);
219
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);
224                                 } else {
225                                         DiskReader::set_no_disk_output (false);
226                                 }
227                         } else {
228                                 DiskReader::set_no_disk_output (false);
229                         }
230
231                         /* inject DLL with new data */
232
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()));
234
235                         const double e = delta;
236
237                         t0 = t1;
238                         t1 += b * e + e2;
239                         e2 += c * e;
240
241                         engine_speed = (t1 - t0) / nframes;
242
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));
244
245                         /* provide a .1% deadzone to lock the speed */
246                         if (fabs (engine_speed - 1.0) <= 0.001) {
247                                 engine_speed = 1.0;
248                         }
249
250                         if (_current_master->sample_clock_synced() && engine_speed != 0.0f) {
251
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).
254                                 */
255                                 if (engine_speed > 0.0) {
256                                         engine_speed = 1.0;
257                                 } else if (engine_speed < 0.0) {
258                                         engine_speed = -1.0;
259                                 }
260                         }
261
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));
264
265                 } else {
266
267                         /* session has not finished with latency compensation yet, so we cannot compute the
268                            difference between the master and the session.
269                         */
270                         engine_speed = 1.0;
271                 }
272
273         } else {
274
275                 engine_speed = 1.0;
276         }
277
278         _master_invalid_this_cycle = false;
279
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));
281
282         return engine_speed;
283 }
284
285
286 void
287 TransportMasterManager::init_transport_master_dll (double speed, samplepos_t pos)
288 {
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
292          *
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.
295          */
296
297         AudioEngine* ae = AudioEngine::instance();
298
299         double const omega = 2.0 * M_PI * double(ae->samples_per_cycle()) / 2.0 / double(ae->sample_rate());
300         b = 1.4142135623730950488 * omega;
301         c = omega * omega;
302
303         const int direction = (speed >= 0.0 ? 1 : -1);
304
305         master_dll_initstate = direction;
306
307         e2 = double (direction * ae->samples_per_cycle());
308         t0 = double (pos);
309         t1 = t0 + e2;
310
311         DEBUG_TRACE (DEBUG::Slave, string_compose ("[re-]init ENGINE DLL %1 %2 %3 from %4 %5\n", t0,  t1, e2, speed, pos));
312 }
313
314 int
315 TransportMasterManager::add (SyncSource type, std::string const & name, bool removeable)
316 {
317         int ret = 0;
318         boost::shared_ptr<TransportMaster> tm;
319
320         DEBUG_TRACE (DEBUG::Slave, string_compose ("adding new transport master, type %1 name %2 removeable %3\n", enum_2_string (type), name, removeable));
321
322         {
323                 Glib::Threads::RWLock::WriterLock lm (lock);
324
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;
328                                 return -1;
329                         }
330                 }
331
332                 tm = TransportMaster::factory (type, name, removeable);
333                 boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
334                 ret = add_locked (tm);
335         }
336
337         if (ret == 0) {
338                 Added (tm);
339         }
340
341         return ret;
342 }
343
344 int
345 TransportMasterManager::add_locked (boost::shared_ptr<TransportMaster> tm)
346 {
347         if (!tm) {
348                 return -1;
349         }
350
351
352         if (_session) {
353                 tm->set_session (_session);
354         }
355
356         _transport_masters.push_back (tm);
357         return 0;
358 }
359
360 int
361 TransportMasterManager::remove (std::string const & name)
362 {
363         int ret = -1;
364         boost::shared_ptr<TransportMaster> tm;
365
366         {
367                 Glib::Threads::RWLock::WriterLock lm (lock);
368
369                 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
370                         if ((*t)->name() == name) {
371                                 if (!(*t)->removeable()) {
372                                         return -1;
373                                 }
374                                 tm = *t;
375                                 _transport_masters.erase (t);
376                                 ret = 0;
377                                 break;
378                         }
379                 }
380         }
381
382         if (ret == 0) {
383                 Removed (tm);
384         }
385
386         return ret;
387 }
388
389 int
390 TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c)
391 {
392         if (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());
395                         return -1;
396                 }
397         }
398
399         _current_master = c;
400         _master_speed = 0;
401         _master_position = 0;
402
403         master_dll_initstate = 0;
404
405         DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", (c ? c->name() : string ("none"))));
406
407         return 0;
408 }
409
410 int
411 TransportMasterManager::set_current (boost::shared_ptr<TransportMaster> c)
412 {
413         int ret = -1;
414         boost::shared_ptr<TransportMaster> old (_current_master);
415
416         {
417                 Glib::Threads::RWLock::WriterLock lm (lock);
418                 ret = set_current_locked (c);
419         }
420
421         if (ret == 0) {
422                 CurrentChanged (old, _current_master); // EMIT SIGNAL
423         }
424
425         return ret;
426 }
427
428 int
429 TransportMasterManager::set_current (SyncSource ss)
430 {
431         int ret = -1;
432         boost::shared_ptr<TransportMaster> old (_current_master);
433
434         {
435                 Glib::Threads::RWLock::WriterLock lm (lock);
436
437                 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
438                         if ((*t)->type() == ss) {
439                                 ret = set_current_locked (*t);
440                                 break;
441                         }
442                 }
443         }
444
445         if (ret == 0) {
446                 CurrentChanged (old, _current_master); // EMIT SIGNAL
447         }
448
449         return ret;
450 }
451
452
453 int
454 TransportMasterManager::set_current (std::string const & str)
455 {
456         int ret = -1;
457         boost::shared_ptr<TransportMaster> old (_current_master);
458
459         {
460                 Glib::Threads::RWLock::WriterLock lm (lock);
461
462                 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
463                         if ((*t)->name() == str) {
464                                 ret = set_current_locked (*t);
465                                 break;
466                         }
467                 }
468         }
469
470         if (ret == 0) {
471                 CurrentChanged (old, _current_master); // EMIT SIGNAL
472         }
473
474         return ret;
475 }
476
477
478 void
479 TransportMasterManager::clear ()
480 {
481         {
482                 Glib::Threads::RWLock::WriterLock lm (lock);
483                 _current_master.reset ();
484                 _transport_masters.clear ();
485         }
486
487         Removed (boost::shared_ptr<TransportMaster>());
488 }
489
490 int
491 TransportMasterManager::set_state (XMLNode const & node, int version)
492 {
493         assert (node.name() == state_node_name);
494
495         XMLNodeList const & children = node.children();
496
497         {
498                 Glib::Threads::RWLock::WriterLock lm (lock);
499
500                 _current_master.reset ();
501                 boost_debug_list_ptrs ();
502
503                 _transport_masters.clear ();
504
505                 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
506
507                         boost::shared_ptr<TransportMaster> tm = TransportMaster::factory (**c);
508                         boost_debug_shared_ptr_mark_interesting (tm.get(), "tm");
509
510                         if (add_locked (tm)) {
511                                 continue;
512                         }
513
514                         /* we know it is the last thing added to the list of masters */
515
516                         _transport_masters.back()->set_state (**c, version);
517                 }
518         }
519
520         std::string current_master;
521         if (node.get_property (X_("current"), current_master)) {
522                 set_current (current_master);
523         } else {
524                 set_current (MTC);
525         }
526
527         return 0;
528 }
529
530 XMLNode&
531 TransportMasterManager::get_state ()
532 {
533         XMLNode* node = new XMLNode (state_node_name);
534
535         if (_current_master) {
536                 node->set_property (X_("current"), _current_master->name());
537         }
538
539         Glib::Threads::RWLock::ReaderLock lm (lock);
540
541         for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
542                 node->add_child_nocopy ((*t)->get_state());
543         }
544
545         return *node;
546 }
547
548 boost::shared_ptr<TransportMaster>
549 TransportMasterManager::master_by_type (SyncSource src) const
550 {
551         Glib::Threads::RWLock::ReaderLock lm (lock);
552
553         for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
554                 if ((*tm)->type() == src) {
555                         return *tm;
556                 }
557         }
558
559         return boost::shared_ptr<TransportMaster> ();
560 }
561
562 void
563 TransportMasterManager::engine_stopped ()
564 {
565         DEBUG_TRACE (DEBUG::Slave, "engine stopped, reset all transport masters\n");
566         {
567                 Glib::Threads::RWLock::ReaderLock lm (lock);
568
569                 for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
570                         (*tm)->reset (false);
571                 }
572         }
573 }
574
575 void
576 TransportMasterManager::restart ()
577 {
578         XMLNode* node;
579
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;
583                         /* XXX now what? */
584                 }
585         } else {
586                 if (TransportMasterManager::instance().set_default_configuration ()) {
587                         error << _("Cannot initialize transport master manager") << endmsg;
588                         /* XXX now what? */
589                 }
590         }
591 }