Update classkeys to match new total LuaSignal count (windows only)
[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/i18n.h"
26
27 #if __cplusplus > 199711L
28 #define local_signbit(x) std::signbit (x)
29 #else
30 #define local_signbit(x) ((((__int64*)(&z))*) & 0x8000000000000000)
31 #endif
32
33 using namespace ARDOUR;
34 using namespace PBD;
35
36 const std::string TransportMasterManager::state_node_name = X_("TransportMasters");
37 TransportMasterManager* TransportMasterManager::_instance = 0;
38
39 TransportMasterManager::TransportMasterManager()
40         : _master_speed (0)
41         , _master_position (0)
42         , _session (0)
43         , _master_invalid_this_cycle (false)
44         , master_dll_initstate (0)
45 {
46 }
47
48 TransportMasterManager::~TransportMasterManager ()
49 {
50         clear ();
51 }
52
53 int
54 TransportMasterManager::set_default_configuration ()
55 {
56         try {
57                 /* setup default transport masters. Most people will never need any
58                    others
59                 */
60                 add (Engine, X_("JACK Transport"), false);
61                 add (MTC, X_("MTC"), false);
62                 add (LTC, X_("LTC"), false);
63                 add (MIDIClock, X_("MIDI Clock"), false);
64         } catch (...) {
65                 return -1;
66         }
67
68         _current_master = _transport_masters.back();
69
70         return 0;
71 }
72
73 void
74 TransportMasterManager::set_session (Session* s)
75 {
76         /* Called by AudioEngine in process context, synchronously with it's
77          * own "adoption" of the Session. The call will occur before the first
78          * call to ::pre_process_transport_masters().
79          */
80
81         Glib::Threads::RWLock::ReaderLock lm (lock);
82
83         config_connection.disconnect ();
84
85         _session = s;
86
87         for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
88                 (*tm)->set_session (s);
89         }
90
91         if (_session) {
92                 _session->config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&TransportMasterManager::parameter_changed, this, _1));
93         }
94
95 }
96
97 void
98 TransportMasterManager::parameter_changed (std::string const & what)
99 {
100         if (what == "external-sync") {
101                 if (!_session->config.get_external_sync()) {
102                         /* disabled */
103                         DiskReader::set_no_disk_output (false);
104                 }
105         }
106 }
107
108 TransportMasterManager&
109 TransportMasterManager::instance()
110 {
111         if (!_instance) {
112                 _instance = new TransportMasterManager();
113         }
114         return *_instance;
115 }
116
117 // Called from AudioEngine::process_callback() BEFORE Session::process() is called. Each transport master has processed any incoming data for this cycle,
118 // and this method computes the transport speed that Ardour should use to get into and remain in sync with the master.
119 //
120 double
121 TransportMasterManager::pre_process_transport_masters (pframes_t nframes, samplepos_t now)
122 {
123         Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
124
125         if (!lm.locked()) {
126                 return 1.0;
127         }
128
129         boost::optional<samplepos_t> session_pos;
130
131         if (_session) {
132                 session_pos = _session->audible_sample();
133         }
134
135         if (Config->get_run_all_transport_masters_always()) {
136                 for (TransportMasters::iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
137                         if ((*tm)->check_collect()) {
138                                 (*tm)->pre_process (nframes, now, session_pos);
139                         }
140                 }
141         }
142
143         if (!_session) {
144                 return 1.0;
145         }
146
147         /* if we're not running ALL transport masters, but still have a current
148          * one, then we should run that one all the time so that we know
149          * precisely where it is when we starting chasing it ...
150          */
151
152         if (!Config->get_run_all_transport_masters_always() && _current_master) {
153                 _current_master->pre_process (nframes, now, session_pos);
154         }
155
156         if (!_session->config.get_external_sync()) {
157                 DEBUG_TRACE (DEBUG::Slave, string_compose ("no external sync, use session actual speed of %1\n", _session->actual_speed() ? _session->actual_speed() : 1.0));
158                 return _session->actual_speed () ? _session->actual_speed() : 1.0;
159         }
160
161         /* --- NOT REACHED UNLESS CHASING (i.e. _session->config.get_external_sync() is true ------*/
162
163         if (!_current_master->ok()) {
164                 /* stop */
165                 _session->request_transport_speed (0.0, false, _current_master->request_type());
166                 DEBUG_TRACE (DEBUG::Slave, "no roll2 - master has failed\n");
167                 _master_invalid_this_cycle = true;
168                 return 1.0;
169         }
170
171         if (!_current_master->locked()) {
172                 DEBUG_TRACE (DEBUG::Slave, "no roll4 - not locked\n");
173                 _master_invalid_this_cycle = true;
174                 return 1.0;
175         }
176
177         double engine_speed;
178         samplepos_t ignore1, ignore2;
179
180         if (!_current_master->speed_and_position (_master_speed, _master_position, ignore1, ignore2, now)) {
181                 return 1.0;
182         }
183
184         if (_master_speed != 0.0) {
185
186                 samplepos_t delta = _master_position;
187
188                 if (_session->compute_audible_delta (delta)) {
189
190                         if (master_dll_initstate == 0) {
191
192                                 init_transport_master_dll (_master_speed, _master_position);
193                                 // _master_invalid_this_cycle = true;
194                                 DEBUG_TRACE (DEBUG::Slave, "no roll3 - still initializing master DLL\n");
195                                 master_dll_initstate = _master_speed > 0.0 ? 1 : -1;
196
197                                 return 1.0;
198                         }
199
200                         /* compute delta or "error" between the computed master_position for
201                          * this cycle and the current session position.
202                          *
203                          * Remember: ::speed_and_position() is being called in process context
204                          * but returns the predicted speed+position for the start of this process cycle,
205                          * not just the most recent timestamp received by the current master object.
206                          */
207
208                         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()));
209
210                         if (delta > _current_master->resolution()) {
211
212                                 // init_transport_master_dll (_master_speed, _master_position);
213
214                                 if (!_session->actively_recording()) {
215                                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave delta %1 greater than slave resolution %2 => no disk output\n", delta, _current_master->resolution()));
216                                         /* run routes as normal, but no disk output */
217                                         DiskReader::set_no_disk_output (true);
218                                 } else {
219                                         DiskReader::set_no_disk_output (false);
220                                 }
221                         } else {
222                                 DiskReader::set_no_disk_output (false);
223                         }
224
225                         /* inject DLL with new data */
226
227                         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()));
228
229                         const double e = delta;
230
231                         t0 = t1;
232                         t1 += b * e + e2;
233                         e2 += c * e;
234
235                         engine_speed = (t1 - t0) / nframes;
236
237                         DEBUG_TRACE (DEBUG::Slave, string_compose ("slave @ %1 speed %2 cur delta %3 matching speed %4\n", _master_position, _master_speed, delta, engine_speed));
238
239                         /* provide a .1% deadzone to lock the speed */
240                         if (fabs (engine_speed - 1.0) <= 0.001) {
241                                 engine_speed = 1.0;
242                         }
243
244                         if (_current_master->sample_clock_synced() && engine_speed != 0.0f) {
245
246                                 /* 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
247                                    (since our sample clock cannot change with respect to it).
248                                 */
249                                 if (engine_speed > 0.0) {
250                                         engine_speed = 1.0;
251                                 } else if (engine_speed < 0.0) {
252                                         engine_speed = -1.0;
253                                 }
254                         }
255
256                         /* speed is set, we're locked, and good to go */
257                         DEBUG_TRACE (DEBUG::Slave, string_compose ("%1: computed speed-to-follow-master as %2\n", _current_master->name(), engine_speed));
258
259                 } else {
260
261                         /* session has not finished with latency compensation yet, so we cannot compute the
262                            difference between the master and the session.
263                         */
264                         engine_speed = 1.0;
265                 }
266
267         } else {
268
269                 engine_speed = 1.0;
270         }
271
272         _master_invalid_this_cycle = false;
273
274         DEBUG_TRACE (DEBUG::Slave, string_compose ("computed resampling ratio as %1 with position = %2 and speed = %3\n", engine_speed, _master_position, _master_speed));
275
276         return engine_speed;
277 }
278
279
280 void
281 TransportMasterManager::init_transport_master_dll (double speed, samplepos_t pos)
282 {
283         /* the bandwidth of the DLL is a trade-off,
284          * because the max-speed of the transport in ardour is
285          * limited to +-8.0, a larger bandwidth would cause oscillations
286          *
287          * But this is only really a problem if the user performs manual
288          * seeks while transport is running and slaved to some timecode-y master.
289          */
290
291         AudioEngine* ae = AudioEngine::instance();
292
293         double const omega = 2.0 * M_PI * double(ae->samples_per_cycle()) / 2.0 / double(ae->sample_rate());
294         b = 1.4142135623730950488 * omega;
295         c = omega * omega;
296
297         const int direction = (speed >= 0.0 ? 1 : -1);
298
299         master_dll_initstate = direction;
300
301         e2 = double (direction * ae->samples_per_cycle());
302         t0 = double (pos);
303         t1 = t0 + e2;
304
305         DEBUG_TRACE (DEBUG::Slave, string_compose ("[re-]init ENGINE DLL %1 %2 %3 from %4 %5\n", t0,  t1, e2, speed, pos));
306 }
307
308 int
309 TransportMasterManager::add (SyncSource type, std::string const & name, bool removeable)
310 {
311         int ret = 0;
312         boost::shared_ptr<TransportMaster> tm;
313
314         DEBUG_TRACE (DEBUG::Slave, string_compose ("adding new transport master, type %1 name %2 removeable %3\n", enum_2_string (type), name, removeable));
315
316         {
317                 Glib::Threads::RWLock::WriterLock lm (lock);
318
319                 for (TransportMasters::const_iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
320                         if ((*t)->name() == name) {
321                                 error << string_compose (_("There is already a transport master named \"%1\" - not duplicated"), name) << endmsg;
322                                 return -1;
323                         }
324                 }
325
326                 tm = TransportMaster::factory (type, name, removeable);
327                 ret = add_locked (tm);
328         }
329
330         if (ret == 0) {
331                 Added (tm);
332         }
333
334         return ret;
335 }
336
337 int
338 TransportMasterManager::add_locked (boost::shared_ptr<TransportMaster> tm)
339 {
340         if (!tm) {
341                 return -1;
342         }
343
344
345         if (_session) {
346                 tm->set_session (_session);
347         }
348
349         _transport_masters.push_back (tm);
350         return 0;
351 }
352
353 int
354 TransportMasterManager::remove (std::string const & name)
355 {
356         int ret = -1;
357         boost::shared_ptr<TransportMaster> tm;
358
359         {
360                 Glib::Threads::RWLock::WriterLock lm (lock);
361
362                 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
363                         if ((*t)->name() == name) {
364                                 if (!(*t)->removeable()) {
365                                         return -1;
366                                 }
367                                 tm = *t;
368                                 _transport_masters.erase (t);
369                                 ret = 0;
370                                 break;
371                         }
372                 }
373         }
374
375         if (ret == 0) {
376                 Removed (tm);
377         }
378
379         return ret;
380 }
381
382 int
383 TransportMasterManager::set_current_locked (boost::shared_ptr<TransportMaster> c)
384 {
385         if (find (_transport_masters.begin(), _transport_masters.end(), c) == _transport_masters.end()) {
386                 warning << string_compose (X_("programming error: attempt to use unknown transport master named \"%1\"\n"), c->name());
387                 return -1;
388         }
389
390         _current_master = c;
391         _master_speed = 0;
392         _master_position = 0;
393
394         master_dll_initstate = 0;
395
396         DEBUG_TRACE (DEBUG::Slave, string_compose ("current transport master set to %1\n", c->name()));
397
398         return 0;
399 }
400
401 int
402 TransportMasterManager::set_current (boost::shared_ptr<TransportMaster> c)
403 {
404         int ret = -1;
405         boost::shared_ptr<TransportMaster> old (_current_master);
406
407         {
408                 Glib::Threads::RWLock::WriterLock lm (lock);
409                 ret = set_current_locked (c);
410         }
411
412         if (ret == 0) {
413                 CurrentChanged (old, _current_master); // EMIT SIGNAL
414         }
415
416         return ret;
417 }
418
419 int
420 TransportMasterManager::set_current (SyncSource ss)
421 {
422         int ret = -1;
423         boost::shared_ptr<TransportMaster> old (_current_master);
424
425         {
426                 Glib::Threads::RWLock::WriterLock lm (lock);
427
428                 for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
429                         if ((*t)->type() == ss) {
430                                 ret = set_current_locked (*t);
431                                 break;
432                         }
433                 }
434         }
435
436         if (ret == 0) {
437                 CurrentChanged (old, _current_master); // EMIT SIGNAL
438         }
439
440         return ret;
441 }
442
443
444 int
445 TransportMasterManager::set_current (std::string const & str)
446 {
447         int ret = -1;
448         boost::shared_ptr<TransportMaster> old (_current_master);
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() == str) {
455                                 ret = set_current_locked (*t);
456                                 break;
457                         }
458                 }
459         }
460
461         if (ret == 0) {
462                 CurrentChanged (old, _current_master); // EMIT SIGNAL
463         }
464
465         return ret;
466 }
467
468
469 void
470 TransportMasterManager::clear ()
471 {
472         {
473                 Glib::Threads::RWLock::WriterLock lm (lock);
474                 _transport_masters.clear ();
475         }
476
477         Removed (boost::shared_ptr<TransportMaster>());
478 }
479
480 int
481 TransportMasterManager::set_state (XMLNode const & node, int version)
482 {
483         assert (node.name() == state_node_name);
484
485         XMLNodeList const & children = node.children();
486
487
488         if (!children.empty()) {
489                 _transport_masters.clear ();
490         }
491
492         {
493                 Glib::Threads::RWLock::WriterLock lm (lock);
494
495
496                 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
497
498                         boost::shared_ptr<TransportMaster> tm = TransportMaster::factory (**c);
499
500                         if (add_locked (tm)) {
501                                 continue;
502                         }
503
504                         /* we know it is the last thing added to the list of masters */
505
506                         _transport_masters.back()->set_state (**c, version);
507                 }
508         }
509
510         std::string current_master;
511         if (node.get_property (X_("current"), current_master)) {
512                 set_current (current_master);
513         } else {
514                 set_current (MTC);
515         }
516
517         return 0;
518 }
519
520 XMLNode&
521 TransportMasterManager::get_state ()
522 {
523         XMLNode* node = new XMLNode (state_node_name);
524
525         if (_current_master) {
526                 node->set_property (X_("current"), _current_master->name());
527         }
528
529         Glib::Threads::RWLock::ReaderLock lm (lock);
530
531         for (TransportMasters::iterator t = _transport_masters.begin(); t != _transport_masters.end(); ++t) {
532                 node->add_child_nocopy ((*t)->get_state());
533         }
534
535         return *node;
536 }
537
538 boost::shared_ptr<TransportMaster>
539 TransportMasterManager::master_by_type (SyncSource src) const
540 {
541         Glib::Threads::RWLock::ReaderLock lm (lock);
542
543         for (TransportMasters::const_iterator tm = _transport_masters.begin(); tm != _transport_masters.end(); ++tm) {
544                 if ((*tm)->type() == src) {
545                         return *tm;
546                 }
547         }
548
549         return boost::shared_ptr<TransportMaster> ();
550 }