ardour
audioengine.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002 Paul Davis
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
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <unistd.h>
21 #include <cerrno>
22 #include <vector>
23 #include <exception>
24 #include <stdexcept>
25 #include <sstream>
26 #include <cmath>
27 
28 #include <glibmm/timer.h>
29 #include <glibmm/pattern.h>
30 #include <glibmm/module.h>
31 
32 #include "pbd/epa.h"
33 #include "pbd/file_utils.h"
34 #include "pbd/pthread_utils.h"
35 #include "pbd/stacktrace.h"
36 #include "pbd/unknown_type.h"
37 
38 #include "midi++/port.h"
39 #include "midi++/mmc.h"
40 
41 #include "ardour/async_midi_port.h"
42 #include "ardour/audio_port.h"
43 #include "ardour/audio_backend.h"
44 #include "ardour/audioengine.h"
45 #include "ardour/search_paths.h"
46 #include "ardour/buffer.h"
47 #include "ardour/cycle_timer.h"
48 #include "ardour/internal_send.h"
49 #include "ardour/meter.h"
50 #include "ardour/midi_port.h"
52 #include "ardour/mididm.h"
53 #include "ardour/mtdm.h"
54 #include "ardour/port.h"
55 #include "ardour/process_thread.h"
56 #include "ardour/session.h"
57 
58 #include "i18n.h"
59 
60 using namespace std;
61 using namespace ARDOUR;
62 using namespace PBD;
63 
64 AudioEngine* AudioEngine::_instance = 0;
65 
66 #ifdef SILENCE_AFTER
67 #define SILENCE_AFTER_SECONDS 600
68 #endif
69 
71  : session_remove_pending (false)
72  , session_removal_countdown (-1)
73  , _running (false)
74  , _freewheeling (false)
75  , monitor_check_interval (INT32_MAX)
76  , last_monitor_check (0)
77  , _processed_frames (0)
78  , m_meter_thread (0)
79  , _main_thread (0)
80  , _mtdm (0)
81  , _mididm (0)
82  , _measuring_latency (MeasureNone)
83  , _latency_input_port (0)
84  , _latency_output_port (0)
85  , _latency_flush_frames (0)
86  , _latency_signal_latency (0)
87  , _stopped_for_latency (false)
88  , _started_for_latency (false)
89  , _in_destructor (false)
90  , _hw_reset_event_thread(0)
91  , _hw_reset_request_count(0)
92  , _stop_hw_reset_processing(0)
93  , _hw_devicelist_update_thread(0)
94  , _hw_devicelist_update_count(0)
95  , _stop_hw_devicelist_processing(0)
96 #ifdef SILENCE_AFTER_SECONDS
97  , _silence_countdown (0)
98  , _silence_hit_cnt (0)
99 #endif
100 {
104 }
105 
107 {
108  _in_destructor = true;
110  drop_backend ();
111  for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
112  i->second->deinstantiate();
113  }
114 }
115 
118 {
119  if (_instance) {
120  return _instance;
121  }
122 
123  _instance = new AudioEngine ();
124 
125  return _instance;
126 }
127 
128 void
130 {
131  /* caller must hold process lock */
132 
134 
135  /* tell all Ports that we're going to start a new (split) cycle */
136 
138 
139  for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
140  i->second->cycle_split ();
141  }
142 }
143 
144 int
146 {
147  /* check for monitor input change every 1/10th of second */
148 
149  monitor_check_interval = nframes / 10;
150  last_monitor_check = 0;
151 
152  if (_session) {
153  _session->set_frame_rate (nframes);
154  }
155 
156  SampleRateChanged (nframes); /* EMIT SIGNAL */
157 
158 #ifdef SILENCE_AFTER_SECONDS
159  _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
160 #endif
161 
162  return 0;
163 }
164 
165 int
167 {
168  if (_session) {
169  _session->set_block_size (bufsiz);
170  last_monitor_check = 0;
171  }
172 
173  BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
174 
175  return 0;
176 }
177 
181 #ifdef __clang__
182 __attribute__((annotate("realtime")))
183 #endif
184 int
186 {
187  Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
188 
190  PT_TIMING_CHECK (1);
191 
193  pframes_t next_processed_frames;
194 
195  /* handle wrap around of total frames counter */
196 
197  if (max_framepos - _processed_frames < nframes) {
198  next_processed_frames = nframes - (max_framepos - _processed_frames);
199  } else {
200  next_processed_frames = _processed_frames + nframes;
201  }
202 
203  if (!tm.locked()) {
204  /* return having done nothing */
205  if (_session) {
206  Xrun();
207  }
208  /* really only JACK requires this
209  * (other backends clear the output buffers
210  * before the process_callback. it may even be
211  * jack/alsa only). but better safe than sorry.
212  */
214  return 0;
215  }
216 
217  bool return_after_remove_check = false;
218 
220  /* run a normal cycle from the perspective of the PortManager
221  so that we get silence on all registered ports.
222 
223  we overwrite the silence on the two ports used for latency
224  measurement.
225  */
226 
227  PortManager::cycle_start (nframes);
228  PortManager::silence (nframes);
229 
231  PortEngine& pe (port_engine());
232 
233  Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
234  Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
235 
236  _mtdm->process (nframes, in, out);
237  }
238 
239  PortManager::cycle_end (nframes);
240  return_after_remove_check = true;
241 
242  } else if (_measuring_latency == MeasureMIDI && _mididm) {
243  /* run a normal cycle from the perspective of the PortManager
244  so that we get silence on all registered ports.
245 
246  we overwrite the silence on the two ports used for latency
247  measurement.
248  */
249 
250  PortManager::cycle_start (nframes);
251  PortManager::silence (nframes);
252 
254  PortEngine& pe (port_engine());
255 
256  _mididm->process (nframes, pe,
257  pe.get_buffer (_latency_input_port, nframes),
258  pe.get_buffer (_latency_output_port, nframes));
259  }
260 
261  PortManager::cycle_end (nframes);
262  return_after_remove_check = true;
263 
264  } else if (_latency_flush_frames) {
265 
266  /* wait for the appropriate duration for the MTDM signal to
267  * drain from the ports before we revert to normal behaviour.
268  */
269 
270  PortManager::cycle_start (nframes);
271  PortManager::silence (nframes);
272  PortManager::cycle_end (nframes);
273 
274  if (_latency_flush_frames > nframes) {
275  _latency_flush_frames -= nframes;
276  } else {
278  }
279 
280  return_after_remove_check = true;
281  }
282 
284 
285  /* perform the actual session removal */
286 
287  if (session_removal_countdown < 0) {
288 
289  /* fade out over 1 second */
293 
294  } else if (session_removal_countdown > 0) {
295 
296  /* we'll be fading audio out.
297 
298  if this is the last time we do this as part
299  of session removal, do a MIDI panic now
300  to get MIDI stopped. This relies on the fact
301  that "immediate data" (aka "out of band data") from
302  MIDI tracks is *appended* after any other data,
303  so that it emerges after any outbound note ons, etc.
304  */
305 
306  if (session_removal_countdown <= nframes) {
307  _session->midi_panic ();
308  }
309 
310  } else {
311  /* fade out done */
312  _session = 0;
313  session_removal_countdown = -1; // reset to "not in progress"
314  session_remove_pending = false;
315  session_removed.signal(); // wakes up thread that initiated session removal
316  }
317  }
318 
319  if (return_after_remove_check) {
320  return 0;
321  }
322 
323  if (_session == 0) {
324 
325  if (!_freewheeling) {
326  PortManager::cycle_start (nframes);
327  PortManager::cycle_end (nframes);
328  }
329 
330  _processed_frames = next_processed_frames;
331 
332  return 0;
333  }
334 
335  /* tell all relevant objects that we're starting a new cycle */
336 
337  InternalSend::CycleStart (nframes);
338 
339  /* tell all Ports that we're starting a new cycle */
340 
341  PortManager::cycle_start (nframes);
342 
343  /* test if we are freewheeling and there are freewheel signals connected.
344  ardour should act normally even when freewheeling unless /it/ is
345  exporting (which is what Freewheel.empty() tests for).
346  */
347 
348  if (_freewheeling && !Freewheel.empty()) {
349  Freewheel (nframes);
350  } else {
351  _session->process (nframes);
352  }
353 
354  if (_freewheeling) {
355  PortManager::cycle_end (nframes);
356  return 0;
357  }
358 
359  if (!_running) {
360  _processed_frames = next_processed_frames;
361  return 0;
362  }
363 
364  if (last_monitor_check + monitor_check_interval < next_processed_frames) {
365 
367  last_monitor_check = next_processed_frames;
368  }
369 
370 #ifdef SILENCE_AFTER_SECONDS
371 
372  bool was_silent = (_silence_countdown == 0);
373 
374  if (_silence_countdown >= nframes) {
375  _silence_countdown -= nframes;
376  } else {
377  _silence_countdown = 0;
378  }
379 
380  if (!was_silent && _silence_countdown == 0) {
381  _silence_hit_cnt++;
382  BecameSilent (); /* EMIT SIGNAL */
383  }
384 
385  if (_silence_countdown == 0 || _session->silent()) {
386  PortManager::silence (nframes);
387  }
388 
389 #else
390  if (_session->silent()) {
391  PortManager::silence (nframes);
392  }
393 #endif
394 
396 
398 
399  if (session_removal_countdown > nframes) {
400  session_removal_countdown -= nframes;
401  } else {
403  }
404 
406  }
407 
408  PortManager::cycle_end (nframes);
409 
410  _processed_frames = next_processed_frames;
411 
412  PT_TIMING_CHECK (2);
413 
414  return 0;
415 }
416 
417 void
419 {
420 #ifdef SILENCE_AFTER_SECONDS
421  double sr = 48000; /* default in case there is no backend */
422 
423  sr = sample_rate();
424 
425  _silence_countdown = max (60 * sr, /* 60 seconds */
426  sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
427 
428 #endif
429 }
430 
431 void
433 {
434  if (_state_lock.trylock () ) {
435  _backend->launch_control_app ();
436  _state_lock.unlock ();
437  }
438 }
439 
440 
441 void
443 {
445  g_atomic_int_inc (&_hw_reset_request_count);
446  _hw_reset_condition.signal ();
447 }
448 
449 int
451 {
452  return g_atomic_int_get (&_hw_reset_request_count);
453 }
454 
455 void
457 {
458  SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
459 
461 
462  while (!_stop_hw_reset_processing) {
463 
464  if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
465 
466  _reset_request_lock.unlock();
467 
469  g_atomic_int_dec_and_test (&_hw_reset_request_count);
470 
471  std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
472  DeviceResetStarted(); // notify about device reset to be started
473 
474  // backup the device name
475  std::string name = _backend->device_name ();
476 
477  std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
478  stop();
479 
480  std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
481  if ( 0 == _backend->reset_device () ) {
482 
483  std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
484  start ();
485 
486  // inform about possible changes
487  BufferSizeChanged (_backend->buffer_size() );
488  } else {
489  DeviceError();
490  }
491 
492  std::cout << "AudioEngine::RESET::Done." << std::endl;
493 
494  _reset_request_lock.lock();
495 
496  } else {
497 
499 
500  }
501  }
502 }
503 void
505 {
507  g_atomic_int_inc (&_hw_devicelist_update_count);
509 }
510 
511 
512 void
514 {
515  SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
516 
518 
520 
522 
523  _devicelist_update_lock.unlock();
524 
525  g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
526  DeviceListChanged (); /* EMIT SIGNAL */
527 
529 
530  } else {
532  }
533  }
534 }
535 
536 
537 void
539 {
540  if (_hw_reset_event_thread == 0) {
541  g_atomic_int_set(&_hw_reset_request_count, 0);
542  g_atomic_int_set(&_stop_hw_reset_processing, 0);
543  _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
544  }
545 
546  if (_hw_devicelist_update_thread == 0) {
547  g_atomic_int_set(&_hw_devicelist_update_count, 0);
548  g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
549  _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
550  }
551 }
552 
553 
554 void
556 {
558  g_atomic_int_set(&_stop_hw_reset_processing, 1);
559  g_atomic_int_set(&_hw_reset_request_count, 0);
560  _hw_reset_condition.signal ();
561  _hw_reset_event_thread->join ();
563  }
564 
566  g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
567  g_atomic_int_set(&_hw_devicelist_update_count, 0);
571  }
572 
573 }
574 
575 
576 void
578 {
580 
582 
583  if (_session) {
584 
585  pframes_t blocksize = samples_per_cycle ();
586 
587  PortManager::cycle_start (blocksize);
588 
589  _session->process (blocksize);
590  _session->process (blocksize);
591  _session->process (blocksize);
592  _session->process (blocksize);
593  _session->process (blocksize);
594  _session->process (blocksize);
595  _session->process (blocksize);
596  _session->process (blocksize);
597 
598  PortManager::cycle_end (blocksize);
599  }
600 }
601 
602 void
604 {
606 
607  if (_running) {
608 
609  if (_session) {
610  session_remove_pending = true;
613  }
614 
615  } else {
617  }
618 
619  remove_all_ports ();
620 }
621 
622 
623 void
624 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
625 {
626  if (_session) {
627  _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
628  }
629 }
630 
631 
632 void
634 {
635  /* called from a signal handler for SIGPIPE */
636  _running = false;
637 }
638 
639 int
641 {
642  if (_session) {
643  if (_session->config.get_jack_time_master()) {
644  _backend->set_time_master (true);
645  } else {
646  _backend->set_time_master (false);
647  }
648  }
649  return 0;
650 }
651 
652 
653 void
655 {
656  delete _instance;
657  _instance = 0;
658 }
659 
660 int
662 {
663  vector<std::string> backend_modules;
664 
665  _backends.clear ();
666 
667  Glib::PatternSpec so_extension_pattern("*backend.so");
668  Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
669 
670 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
671  #if defined(DEBUG) || defined(_DEBUG)
672  Glib::PatternSpec dll_extension_pattern("*backendD.dll");
673  #else
674  Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
675  #endif
676 #else
677  Glib::PatternSpec dll_extension_pattern("*backend.dll");
678 #endif
679 
681  so_extension_pattern);
682 
684  dylib_extension_pattern);
685 
687  dll_extension_pattern);
688 
689  DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
690 
691  for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
692 
694 
695  DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
696 
697  if ((info = backend_discover (*i)) != 0) {
698  _backends.insert (make_pair (info->name, info));
699  }
700  }
701 
702  DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
703 
704  return _backends.size();
705 }
706 
708 AudioEngine::backend_discover (const string& path)
709 {
710 #ifdef PLATFORM_WINDOWS
711  // do not show popup dialog (e.g. missing libjack.dll)
712  // win7+ should use SetThreadErrorMode()
713  SetErrorMode(SEM_FAILCRITICALERRORS);
714 #endif
715  Glib::Module module (path);
716 #ifdef PLATFORM_WINDOWS
717  SetErrorMode(0); // reset to system default
718 #endif
720  AudioBackendInfo* (*dfunc)(void);
721  void* func = 0;
722 
723  if (!module) {
724  error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
725  Glib::Module::get_last_error()) << endmsg;
726  return 0;
727  }
728 
729  if (!module.get_symbol ("descriptor", func)) {
730  error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
731  error << Glib::Module::get_last_error() << endmsg;
732  return 0;
733  }
734 
735  dfunc = (AudioBackendInfo* (*)(void))func;
736  info = dfunc();
737  if (!info->available()) {
738  return 0;
739  }
740 
741  module.make_resident ();
742 
743  return info;
744 }
745 
746 vector<const AudioBackendInfo*>
748 {
749  vector<const AudioBackendInfo*> r;
750 
751  for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
752  r.push_back (i->second);
753  }
754 
755  return r;
756 }
757 
758 string
760 {
761  if (_backend) {
762  return _backend->name();
763  }
764  return string();
765 }
766 
767 void
769 {
770  if (_backend) {
771  stop(false);
772  _backend->drop_device ();
773  _backend.reset ();
774  _running = false;
775  }
776 }
777 
780 {
781  if (_backends.empty()) {
783  }
784 
785  return set_backend (_backends.begin()->first, "", "");
786 }
787 
789 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
790 {
791  BackendMap::iterator b = _backends.find (name);
792 
793  if (b == _backends.end()) {
795  }
796 
797  drop_backend ();
798 
799  try {
800  if (b->second->instantiate (arg1, arg2)) {
801  throw failed_constructor ();
802  }
803 
804  _backend = b->second->factory (*this);
805 
806  } catch (exception& e) {
807  error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
809  }
810 
811  return _backend;
812 }
813 
814 /* BACKEND PROXY WRAPPERS */
815 
816 int
817 AudioEngine::start (bool for_latency)
818 {
819  if (!_backend) {
820  return -1;
821  }
822 
823  if (_running) {
824  return 0;
825  }
826 
827  _processed_frames = 0;
828  last_monitor_check = 0;
829 
830  if (_backend->start (for_latency)) {
831  return -1;
832  }
833 
834  _running = true;
835 
836  if (_session) {
837  _session->set_frame_rate (_backend->sample_rate());
838 
839  if (_session->config.get_jack_time_master()) {
840  _backend->set_time_master (true);
841  }
842 
843  }
844 
845  if (!for_latency) {
846  Running(); /* EMIT SIGNAL */
847  }
848 
849  return 0;
850 }
851 
852 int
853 AudioEngine::stop (bool for_latency)
854 {
855  if (!_backend) {
856  return 0;
857  }
858 
859  if (_session && _running) {
860  // it's not a halt, but should be handled the same way:
861  // disable record, stop transport and I/O processign but save the data.
863  }
864 
866 
867  if (_backend->stop ()) {
868  return -1;
869  }
870 
871  _running = false;
872  _processed_frames = 0;
876  _started_for_latency = false;
877 
878  Port::PortDrop ();
879 
880  if (!for_latency) {
881  Stopped (); /* EMIT SIGNAL */
882  }
883 
884  return 0;
885 }
886 
887 int
888 AudioEngine::freewheel (bool start_stop)
889 {
890  if (!_backend) {
891  return -1;
892  }
893 
894  /* _freewheeling will be set when first Freewheel signal occurs */
895 
896  return _backend->freewheel (start_stop);
897 }
898 
899 float
901 {
902  if (!_backend) {
903  return 0.0;
904  }
905  return _backend->dsp_load ();
906 }
907 
908 bool
910 {
911  if (!_backend) {
912  return false;
913  }
914 
915  return _backend->is_realtime();
916 }
917 
918 bool
920 {
921  if (!_backend) {
922  return false;
923  }
924 
925  return _backend->available();
926 }
927 
928 void
930 {
931  if (!_backend) {
932  return;
933  }
934  return _backend->transport_start ();
935 }
936 
937 void
939 {
940  if (!_backend) {
941  return;
942  }
943  return _backend->transport_stop ();
944 }
945 
948 {
949  if (!_backend) {
950  return TransportStopped;
951  }
952  return _backend->transport_state ();
953 }
954 
955 void
957 {
958  if (!_backend) {
959  return;
960  }
961  return _backend->transport_locate (pos);
962 }
963 
966 {
967  if (!_backend) {
968  return 0;
969  }
970  return _backend->transport_frame ();
971 }
972 
975 {
976  if (!_backend) {
977  return 0;
978  }
979  return _backend->sample_rate ();
980 }
981 
982 pframes_t
984 {
985  if (!_backend) {
986  return 0;
987  }
988  return _backend->buffer_size ();
989 }
990 
991 int
993 {
994  if (!_backend) {
995  return -1;
996  }
997  return _backend->usecs_per_cycle ();
998 }
999 
1000 size_t
1002 {
1003  if (!_backend) {
1004  return -1;
1005  }
1006  return _backend->raw_buffer_size (t);
1007 }
1008 
1009 framepos_t
1011 {
1012  if (!_backend) {
1013  return 0;
1014  }
1015  return _backend->sample_time ();
1016 }
1017 
1018 framepos_t
1020 {
1021  if (!_backend) {
1022  return 0;
1023  }
1024  return _backend->sample_time_at_cycle_start ();
1025 }
1026 
1027 pframes_t
1029 {
1030  if (!_backend) {
1031  return 0;
1032  }
1033  return _backend->samples_since_cycle_start ();
1034 }
1035 
1036 bool
1038 {
1039  if (!_backend) {
1040  return false;
1041  }
1042  return _backend->get_sync_offset (offset);
1043 }
1044 
1045 int
1046 AudioEngine::create_process_thread (boost::function<void()> func)
1047 {
1048  if (!_backend) {
1049  return -1;
1050  }
1051  return _backend->create_process_thread (func);
1052 }
1053 
1054 int
1056 {
1057  if (!_backend) {
1058  return -1;
1059  }
1060  return _backend->join_process_threads ();
1061 }
1062 
1063 bool
1065 {
1066  if (!_backend) {
1067  return false;
1068  }
1069  return _backend->in_process_thread ();
1070 }
1071 
1072 uint32_t
1074 {
1075  if (!_backend) {
1076  return 0;
1077  }
1078  return _backend->process_thread_count ();
1079 }
1080 
1081 int
1083 {
1084  if (!_backend) {
1085  return -1;
1086  }
1087  return _backend->set_device_name (name);
1088 }
1089 
1090 int
1092 {
1093  if (!_backend) {
1094  return -1;
1095  }
1096 
1097  return _backend->set_sample_rate (sr);
1098 }
1099 
1100 int
1102 {
1103  if (!_backend) {
1104  return -1;
1105  }
1106  return _backend->set_buffer_size (bufsiz);
1107 }
1108 
1109 int
1111 {
1112  if (!_backend) {
1113  return -1;
1114  }
1115  return _backend->set_interleaved (yn);
1116 }
1117 
1118 int
1120 {
1121  if (!_backend) {
1122  return -1;
1123  }
1124  return _backend->set_input_channels (ic);
1125 }
1126 
1127 int
1129 {
1130  if (!_backend) {
1131  return -1;
1132  }
1133  return _backend->set_output_channels (oc);
1134 }
1135 
1136 int
1138 {
1139  if (!_backend) {
1140  return -1;
1141  }
1142  return _backend->set_systemic_input_latency (il);
1143 }
1144 
1145 int
1147 {
1148  if (!_backend) {
1149  return -1;
1150  }
1151  return _backend->set_systemic_output_latency (ol);
1152 }
1153 
1154 /* END OF BACKEND PROXY API */
1155 
1156 void
1158 {
1159  /* make sure that anybody who needs to know about this thread
1160  knows about it.
1161  */
1162 
1163  pthread_set_name (X_("audioengine"));
1164 
1165  SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1166 
1167  PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1168  PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1169 
1170  AsyncMIDIPort::set_process_thread (pthread_self());
1171 
1172  if (arg) {
1173  /* the special thread created/managed by the backend */
1175  }
1176 }
1177 
1178 int
1180 {
1181  if (_session) {
1182  return _session->backend_sync_callback (state, position);
1183  }
1184  return 0;
1185 }
1186 
1187 void
1189 {
1190  _freewheeling = onoff;
1191 }
1192 
1193 void
1195 {
1196  if (_session) {
1197  _session->update_latency (for_playback);
1198  }
1199 }
1200 
1201 void
1203 {
1204  if (_backend) {
1205  _backend->update_latencies ();
1206  }
1207 }
1208 
1209 void
1211 {
1212  if (_in_destructor) {
1213  /* everything is under control */
1214  return;
1215  }
1216 
1217  _running = false;
1218 
1219  Port::PortDrop (); /* EMIT SIGNAL */
1220 
1221  if (!_started_for_latency) {
1222  Halted (why); /* EMIT SIGNAL */
1223  }
1224 }
1225 
1226 bool
1228 {
1229  if (_backend) {
1230  if (_backend->info().already_configured())
1231  return false;
1232  } else {
1233  if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1234  return false;
1235  }
1236  }
1237 
1238  return true;
1239 }
1240 
1241 int
1243 {
1244  if (running()) {
1245  _stopped_for_latency = true;
1246  stop (true);
1247  }
1248 
1249  if (start (true)) {
1250  _started_for_latency = true;
1251  return -1;
1252  }
1253 
1254  return 0;
1255 }
1256 
1257 int
1259 {
1260  if (!running()) {
1262  return -1;
1263  }
1264  }
1265 
1266  PortEngine& pe (port_engine());
1267 
1268  delete _mtdm;
1269  _mtdm = 0;
1270 
1271  delete _mididm;
1272  _mididm = 0;
1273 
1274  /* find the ports we will connect to */
1275 
1278 
1279  if (!out || !in) {
1280  stop (true);
1281  return -1;
1282  }
1283 
1284  /* create the ports we will use to read/write data */
1285  if (for_midi) {
1286  if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1287  stop (true);
1288  return -1;
1289  }
1292  stop (true);
1293  return -1;
1294  }
1295 
1296  const string portname ("latency_in");
1297  if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1300  stop (true);
1301  return -1;
1302  }
1306  stop (true);
1307  return -1;
1308  }
1309 
1310  _mididm = new MIDIDM (sample_rate());
1311 
1312  } else {
1313 
1314  if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1315  stop (true);
1316  return -1;
1317  }
1320  stop (true);
1321  return -1;
1322  }
1323 
1324  const string portname ("latency_in");
1325  if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1328  stop (true);
1329  return -1;
1330  }
1334  stop (true);
1335  return -1;
1336  }
1337 
1338  _mtdm = new MTDM (sample_rate());
1339 
1340  }
1341 
1342  LatencyRange lr;
1344  lr = pe.get_latency_range (in, false);
1346  lr = pe.get_latency_range (out, true);
1348 
1349  /* all created and connected, lets go */
1352 
1353  return 0;
1354 }
1355 
1356 void
1358 {
1360 
1361  if (_latency_output_port) {
1364  }
1365  if (_latency_input_port) {
1367  _latency_input_port = 0;
1368  }
1369 
1370  stop (true);
1371 
1372  if (_stopped_for_latency) {
1373  start ();
1374  }
1375 
1376  _stopped_for_latency = false;
1377  _started_for_latency = false;
1378 }
1379 
1380 void
1382 {
1384 }
1385 
1386 void
1388 {
1390 }
static void increment_global_port_buffer_offset(pframes_t n)
Definition: port.h:135
framecnt_t _latency_signal_latency
Definition: audioengine.h:275
gain_t session_removal_gain
Definition: audioengine.h:255
void silence_outputs(pframes_t nframes)
SerializedRCUManager< Ports > ports
Definition: port_manager.h:140
pframes_t samples_since_cycle_start()
#define PT_TIMING_REF
Definition: cycle_timer.h:91
std::string to_string(T t, std::ios_base &(*f)(std::ios_base &))
Definition: convert.h:53
Glib::Threads::Mutex _devicelist_update_lock
Definition: audioengine.h:288
void update_latency(bool playback)
Definition: session.cc:5268
int stop(bool for_latency_measurement=false)
Definition: audioengine.cc:853
Glib::Threads::Cond session_removed
Definition: audioengine.h:252
void reconnect_existing_routes(bool withLock, bool reconnect_master=true, bool reconnect_inputs=true, bool reconnect_outputs=true)
Definition: session.cc:2350
PBD::Signal1< int, pframes_t > Freewheel
Definition: audioengine.h:162
void set_session(Session *)
Definition: audioengine.cc:577
uint32_t process_thread_count()
PBD::Signal0< void > Xrun
Definition: audioengine.h:164
bool is_realtime() const
Definition: audioengine.cc:909
int start_latency_detection(bool)
bool running() const
Definition: audioengine.h:130
Definition: mtdm.h:26
framepos_t transport_frame()
Definition: audioengine.cc:965
int backend_sync_callback(TransportState, framepos_t)
pframes_t samples_per_cycle() const
Definition: audioengine.cc:983
int set_buffer_size(uint32_t)
void cycle_end(pframes_t nframes)
static void create_per_thread_pool(const std::string &n, uint32_t nitems)
void reconnect_session_routes(bool reconnect_inputs=true, bool reconnect_outputs=true)
Definition: audioengine.cc:624
Glib::Threads::Thread * _hw_reset_event_thread
Definition: audioengine.h:280
Glib::Threads::RecMutex _state_lock
Definition: audioengine.h:251
int process(size_t len, float *inp, float *out)
Definition: mtdm.cc:54
std::string _latency_output_name
Definition: audioengine.h:274
gint _stop_hw_devicelist_processing
Definition: audioengine.h:289
void request_backend_reset()
Definition: audioengine.cc:442
framecnt_t last_monitor_check
time of the last monitor check in frames
Definition: audioengine.h:262
uint32_t pframes_t
Definition: types.h:61
framecnt_t _processed_frames
the number of frames processed since start() was called
Definition: audioengine.h:264
int start(bool for_latency_measurement=false)
Definition: audioengine.cc:817
int set_sample_rate(float)
Definition: Beats.hpp:239
LIBPBD_API void notify_gui_about_thread_creation(std::string, pthread_t, std::string, int requests=256)
LIBPBD_API Transmitter error
AudioBackendInfo * backend_discover(const std::string &)
Definition: audioengine.cc:708
int usecs_per_cycle() const
Definition: audioengine.cc:992
PBD::Signal0< void > DeviceListChanged
Definition: audioengine.h:177
virtual void * get_buffer(PortHandle, pframes_t)=0
float get_dsp_load() const
Definition: audioengine.cc:900
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
static AudioEngine * _instance
Definition: audioengine.h:248
SessionConfiguration config
Definition: session.h:866
bool silent()
Definition: session.h:594
#define PT_TIMING_CHECK(x)
Definition: cycle_timer.h:92
virtual int connect(const std::string &src, const std::string &dst)=0
framecnt_t monitor_check_interval
number of frames between each check for changes in monitor input
Definition: audioengine.h:260
static AudioEngine * instance()
Definition: audioengine.h:196
PortEngine & port_engine()
gint _hw_devicelist_update_count
Definition: audioengine.h:286
frameoffset_t session_removal_countdown
Definition: audioengine.h:254
framepos_t sample_time()
void stop_hw_event_processing()
Definition: audioengine.cc:555
void set_latency_input_port(const std::string &)
static PBD::Signal0< void > PortDrop
Definition: port.h:126
void reset_silence_countdown()
Definition: audioengine.cc:418
#define _(Text)
Definition: i18n.h:11
std::string current_backend_name() const
Definition: audioengine.cc:759
ProcessThread * _main_thread
Definition: audioengine.h:266
framecnt_t sample_rate() const
Definition: audioengine.cc:974
void request_device_list_update()
Definition: audioengine.cc:504
framecnt_t _latency_flush_frames
Definition: audioengine.h:272
int process(pframes_t nframes, PortEngine &pe, void *midi_in, void *midi_out)
Definition: mididm.cc:71
int sync_callback(TransportState state, framepos_t position)
int freewheel(bool start_stop)
Definition: audioengine.cc:888
#define X_(Text)
Definition: i18n.h:13
Glib::Threads::Cond _hw_reset_condition
Definition: audioengine.h:282
void find_files_matching_pattern(vector< string > &result, const Searchpath &paths, const Glib::PatternSpec &pattern)
Definition: file_utils.cc:168
void set_block_size(pframes_t nframes)
Definition: session.cc:1844
int64_t framecnt_t
Definition: types.h:76
TransportState transport_state()
Definition: audioengine.cc:947
float Sample
Definition: types.h:54
Glib::Threads::Thread * _hw_devicelist_update_thread
Definition: audioengine.h:285
static PBD::Signal1< void, pframes_t > CycleStart
Definition: internal_send.h:60
static AudioEngine * create()
Definition: audioengine.cc:117
gint _stop_hw_reset_processing
Definition: audioengine.h:284
Glib::Threads::Mutex _process_lock
Definition: audioengine.h:250
void fade_out(gain_t, gain_t, pframes_t)
int set_device_name(const std::string &)
Definition: amp.h:29
virtual void unregister_port(PortHandle)=0
PortEngine::PortHandle _latency_input_port
Definition: audioengine.h:270
PBD::Signal1< void, framecnt_t > SampleRateChanged
Definition: audioengine.h:167
LIBARDOUR_API PBD::Searchpath backend_search_path()
Definition: search_paths.cc:51
int set_input_channels(uint32_t)
void process(pframes_t nframes)
void start_hw_event_processing()
Definition: audioengine.cc:538
framepos_t sample_time_at_cycle_start()
int set_output_channels(uint32_t)
boost::shared_ptr< AudioBackend > set_backend(const std::string &, const std::string &arg1, const std::string &arg2)
Definition: audioengine.cc:789
void set_latency_output_port(const std::string &)
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
int64_t framepos_t
Definition: types.h:66
BackendMap _backends
Definition: audioengine.h:297
virtual PortHandle get_port_by_name(const std::string &) const =0
PBD::Signal0< void > BecameSilent
Definition: audioengine.h:242
LIBPBD_API void pthread_set_name(const char *name)
Glib::Threads::Mutex _reset_request_lock
Definition: audioengine.h:283
boost::shared_ptr< AudioBackend > _backend
Definition: port_manager.h:139
int process_callback(pframes_t nframes)
Definition: audioengine.cc:185
PBD::Signal0< void > Running
Definition: audioengine.h:187
LIBPBD_API Transmitter info
PBD::Signal0< void > DeviceResetStarted
Definition: audioengine.h:193
size_t raw_buffer_size(DataType t)
static void destroy()
Definition: audioengine.cc:654
void launch_device_control_app()
Definition: audioengine.cc:432
void silence(pframes_t nframes)
int set_interleaved(bool yn)
static void set_process_thread(pthread_t)
virtual PortHandle register_port(const std::string &shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)=0
const char * name
virtual LatencyRange get_latency_range(PortHandle port, bool for_playback)=0
PortEngine::PortHandle _latency_output_port
Definition: audioengine.h:271
bool setup_required() const
virtual ~AudioEngine()
Definition: audioengine.cc:106
std::vector< const AudioBackendInfo * > available_backends() const
Definition: audioengine.cc:747
Glib::Threads::Cond _hw_devicelist_update_condition
Definition: audioengine.h:287
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
int buffer_size_change(pframes_t nframes)
Definition: audioengine.cc:166
int prepare_for_latency_measurement()
Definition: debug.h:30
void transport_locate(framepos_t pos)
Definition: audioengine.cc:956
PBD::Signal0< void > DeviceError
Definition: audioengine.h:173
PBD::Signal1< void, pframes_t > BufferSizeChanged
Definition: audioengine.h:170
bool get_sync_offset(pframes_t &offset) const
std::string _latency_input_name
Definition: audioengine.h:273
void halted_callback(const char *reason)
int set_systemic_output_latency(uint32_t)
PBD::Signal1< void, const char * > Halted
Definition: audioengine.h:181
static const framepos_t max_framepos
Definition: types.h:78
void split_cycle(pframes_t offset)
Definition: audioengine.cc:129
virtual void set_session(ARDOUR::Session *)
uint32_t max
Definition: types.h:623
PBD::Signal0< void > Stopped
Definition: audioengine.h:188
LIBARDOUR_API uint64_t AudioEngine
Definition: session.h:982
boost::shared_ptr< T > reader() const
Definition: rcu.h:58
void set_frame_rate(framecnt_t nframes)
Definition: session.cc:1819
void freewheel_callback(bool)
LatencyMeasurement _measuring_latency
Definition: audioengine.h:269
int create_process_thread(boost::function< void()> func)
#define GAIN_COEFF_UNITY
Definition: dB.h:28
void cycle_start(pframes_t nframes)
std::string make_port_name_non_relative(const std::string &name) const
Definition: port_manager.cc:96
int sample_rate_change(pframes_t nframes)
Definition: audioengine.cc:145
TransportState
Definition: types.h:600
bool connected() const
Definition: audioengine.cc:919
boost::shared_ptr< AudioBackend > set_default_backend()
Definition: audioengine.cc:779
int set_systemic_input_latency(uint32_t)
ARDOUR::Session * _session
static void thread_init_callback(void *)
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
void latency_callback(bool for_playback)
gain_t session_removal_gain_step
Definition: audioengine.h:256