2 Copyright (C) 2002 Paul Davis
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.
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
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <glibmm/timer.h>
29 #include <glibmm/pattern.h>
30 #include <glibmm/module.h>
33 #include "pbd/file_utils.h"
34 #include "pbd/pthread_utils.h"
35 #include "pbd/stacktrace.h"
36 #include "pbd/unknown_type.h"
38 #include "midi++/port.h"
39 #include "midi++/mmc.h"
41 #include "ardour/async_midi_port.h"
42 #include "ardour/ardour.h"
43 #include "ardour/audio_port.h"
44 #include "ardour/audio_backend.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/search_paths.h"
47 #include "ardour/buffer.h"
48 #include "ardour/cycle_timer.h"
49 #include "ardour/internal_send.h"
50 #include "ardour/meter.h"
51 #include "ardour/midi_port.h"
52 #include "ardour/midiport_manager.h"
53 #include "ardour/mididm.h"
54 #include "ardour/mtdm.h"
55 #include "ardour/port.h"
56 #include "ardour/process_thread.h"
57 #include "ardour/rc_configuration.h"
58 #include "ardour/session.h"
59 #include "ardour/transport_master_manager.h"
64 using namespace ARDOUR;
67 AudioEngine* AudioEngine::_instance = 0;
69 static gint audioengine_thread_cnt = 1;
72 #define SILENCE_AFTER_SECONDS 600
75 AudioEngine::AudioEngine ()
76 : session_remove_pending (false)
77 , session_removal_countdown (-1)
79 , _freewheeling (false)
80 , monitor_check_interval (INT32_MAX)
81 , last_monitor_check (0)
82 , _processed_samples (-1)
87 , _measuring_latency (MeasureNone)
88 , _latency_input_port (0)
89 , _latency_output_port (0)
90 , _latency_flush_samples (0)
91 , _latency_signal_latency (0)
92 , _stopped_for_latency (false)
93 , _started_for_latency (false)
94 , _in_destructor (false)
95 , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
96 , _hw_reset_event_thread(0)
97 , _hw_reset_request_count(0)
98 , _stop_hw_reset_processing(0)
99 , _hw_devicelist_update_thread(0)
100 , _hw_devicelist_update_count(0)
101 , _stop_hw_devicelist_processing(0)
103 #ifdef SILENCE_AFTER_SECONDS
104 , _silence_countdown (0)
105 , _silence_hit_cnt (0)
108 reset_silence_countdown ();
109 start_hw_event_processing();
110 discover_backends ();
113 AudioEngine::~AudioEngine ()
115 _in_destructor = true;
116 stop_hw_event_processing();
118 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
119 i->second->deinstantiate();
125 AudioEngine::create ()
131 _instance = new AudioEngine ();
137 AudioEngine::split_cycle (pframes_t offset)
139 /* caller must hold process lock */
141 Port::increment_global_port_buffer_offset (offset);
143 /* tell all Ports that we're going to start a new (split) cycle */
145 boost::shared_ptr<Ports> p = ports.reader();
147 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
148 i->second->cycle_split ();
153 AudioEngine::sample_rate_change (pframes_t nframes)
155 /* check for monitor input change every 1/10th of second */
157 monitor_check_interval = nframes / 10;
158 last_monitor_check = 0;
161 _session->set_sample_rate (nframes);
164 SampleRateChanged (nframes); /* EMIT SIGNAL */
166 #ifdef SILENCE_AFTER_SECONDS
167 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
174 AudioEngine::buffer_size_change (pframes_t bufsiz)
177 _session->set_block_size (bufsiz);
178 last_monitor_check = 0;
181 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
186 /** Method called by our ::process_thread when there is work to be done.
187 * @param nframes Number of samples to process.
190 __attribute__((annotate("realtime")))
193 AudioEngine::process_callback (pframes_t nframes)
195 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
196 Port::set_speed_ratio (1.0);
201 /// The number of samples that will have been processed when we've finished
202 pframes_t next_processed_samples;
204 if (_processed_samples < 0) {
205 _processed_samples = sample_time();
206 cerr << "IIIIINIT PS to " << _processed_samples << endl;
209 /* handle wrap around of total samples counter */
211 if (max_samplepos - _processed_samples < nframes) {
212 next_processed_samples = nframes - (max_samplepos - _processed_samples);
214 next_processed_samples = _processed_samples + nframes;
218 /* return having done nothing */
222 /* really only JACK requires this
223 * (other backends clear the output buffers
224 * before the process_callback. it may even be
225 * jack/alsa only). but better safe than sorry.
227 PortManager::silence_outputs (nframes);
231 /* The coreaudio-backend calls thread_init_callback() if
232 * the hardware changes or pthread_self() changes.
234 * However there are cases when neither holds true, yet
235 * the thread-pool changes: e.g. connect a headphone to
236 * a shared mic/headphone jack.
237 * It's probably related to, or caused by clocksource changes.
239 * For reasons yet unknown Glib::Threads::Private() can
240 * use a different thread-private in the same pthread
241 * (coreaudio render callback).
243 * Coreaudio must set something which influences
244 * pthread_key_t uniqness or reset the key using
245 * pthread_getspecific().
247 if (! SessionEvent::has_per_thread_pool ()) {
248 thread_init_callback (NULL);
251 bool return_after_remove_check = false;
253 if (_measuring_latency == MeasureAudio && _mtdm) {
254 /* run a normal cycle from the perspective of the PortManager
255 so that we get silence on all registered ports.
257 we overwrite the silence on the two ports used for latency
261 PortManager::cycle_start (nframes);
262 PortManager::silence (nframes);
264 if (_latency_input_port && _latency_output_port) {
265 PortEngine& pe (port_engine());
267 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
268 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
270 _mtdm->process (nframes, in, out);
273 PortManager::cycle_end (nframes);
274 return_after_remove_check = true;
276 } else if (_measuring_latency == MeasureMIDI && _mididm) {
277 /* run a normal cycle from the perspective of the PortManager
278 so that we get silence on all registered ports.
280 we overwrite the silence on the two ports used for latency
284 PortManager::cycle_start (nframes);
285 PortManager::silence (nframes);
287 if (_latency_input_port && _latency_output_port) {
288 PortEngine& pe (port_engine());
290 _mididm->process (nframes, pe,
291 pe.get_buffer (_latency_input_port, nframes),
292 pe.get_buffer (_latency_output_port, nframes));
295 PortManager::cycle_end (nframes);
296 return_after_remove_check = true;
298 } else if (_latency_flush_samples) {
300 /* wait for the appropriate duration for the MTDM signal to
301 * drain from the ports before we revert to normal behaviour.
304 PortManager::cycle_start (nframes);
305 PortManager::silence (nframes);
306 PortManager::cycle_end (nframes);
308 if (_latency_flush_samples > nframes) {
309 _latency_flush_samples -= nframes;
311 _latency_flush_samples = 0;
314 return_after_remove_check = true;
317 if (session_remove_pending) {
319 /* perform the actual session removal */
321 if (session_removal_countdown < 0) {
323 /* fade out over 1 second */
324 session_removal_countdown = sample_rate()/2;
325 session_removal_gain = GAIN_COEFF_UNITY;
326 session_removal_gain_step = 1.0/session_removal_countdown;
328 } else if (session_removal_countdown > 0) {
330 /* we'll be fading audio out.
332 if this is the last time we do this as part
333 of session removal, do a MIDI panic now
334 to get MIDI stopped. This relies on the fact
335 that "immediate data" (aka "out of band data") from
336 MIDI tracks is *appended* after any other data,
337 so that it emerges after any outbound note ons, etc.
340 if (session_removal_countdown <= nframes) {
341 _session->midi_panic ();
347 session_removal_countdown = -1; // reset to "not in progress"
348 session_remove_pending = false;
349 session_removed.signal(); // wakes up thread that initiated session removal
353 if (return_after_remove_check) {
357 TransportMasterManager& tmm (TransportMasterManager::instance());
359 /* make sure the TMM is up to date about the current session */
361 if (_session != tmm.session()) {
362 tmm.set_session (_session);
367 if (!_freewheeling) {
368 PortManager::silence_outputs (nframes);
371 _processed_samples = next_processed_samples;
376 if (!_freewheeling || Freewheel.empty()) {
377 const double engine_speed = tmm.pre_process_transport_masters (nframes, sample_time_at_cycle_start());
378 Port::set_speed_ratio (engine_speed);
379 DEBUG_TRACE (DEBUG::Slave, string_compose ("transport master (current=%1) gives speed %2 (ports using %3)\n", tmm.current() ? tmm.current()->name() : string("[]"), engine_speed, Port::speed_ratio()));
382 /* tell all relevant objects that we're starting a new cycle */
384 InternalSend::CycleStart (nframes);
386 /* tell all Ports that we're starting a new cycle */
388 PortManager::cycle_start (nframes, _session);
390 /* test if we are freewheeling and there are freewheel signals connected.
391 * ardour should act normally even when freewheeling unless /it/ is
392 * exporting (which is what Freewheel.empty() tests for).
395 if (_freewheeling && !Freewheel.empty()) {
398 if (Port::cycle_nframes () <= nframes) {
399 _session->process (Port::cycle_nframes ());
401 pframes_t remain = Port::cycle_nframes ();
403 pframes_t nf = std::min (remain, nframes);
404 _session->process (nf);
414 PortManager::cycle_end (nframes, _session);
419 _processed_samples = next_processed_samples;
423 if (last_monitor_check + monitor_check_interval < next_processed_samples) {
425 PortManager::check_monitoring ();
426 last_monitor_check = next_processed_samples;
429 #ifdef SILENCE_AFTER_SECONDS
431 bool was_silent = (_silence_countdown == 0);
433 if (_silence_countdown >= nframes) {
434 _silence_countdown -= nframes;
436 _silence_countdown = 0;
439 if (!was_silent && _silence_countdown == 0) {
441 BecameSilent (); /* EMIT SIGNAL */
444 if (_silence_countdown == 0 || _session->silent()) {
445 PortManager::silence (nframes);
449 if (_session->silent()) {
450 PortManager::silence (nframes, _session);
454 if (session_remove_pending && session_removal_countdown) {
456 PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session);
458 if (session_removal_countdown > nframes) {
459 session_removal_countdown -= nframes;
461 session_removal_countdown = 0;
464 session_removal_gain -= (nframes * session_removal_gain_step);
466 PortManager::cycle_end (nframes, _session);
469 _processed_samples = next_processed_samples;
477 AudioEngine::reset_silence_countdown ()
479 #ifdef SILENCE_AFTER_SECONDS
480 double sr = 48000; /* default in case there is no backend */
484 _silence_countdown = max (60 * sr, /* 60 seconds */
485 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
491 AudioEngine::launch_device_control_app()
493 if (_state_lock.trylock () ) {
494 _backend->launch_control_app ();
495 _state_lock.unlock ();
501 AudioEngine::request_backend_reset()
503 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
504 g_atomic_int_inc (&_hw_reset_request_count);
505 _hw_reset_condition.signal ();
509 AudioEngine::backend_reset_requested()
511 return g_atomic_int_get (&_hw_reset_request_count);
515 AudioEngine::do_reset_backend()
517 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
519 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
521 while (!_stop_hw_reset_processing) {
523 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
525 _reset_request_lock.unlock();
527 Glib::Threads::RecMutex::Lock pl (_state_lock);
528 g_atomic_int_dec_and_test (&_hw_reset_request_count);
530 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
531 DeviceResetStarted(); // notify about device reset to be started
533 // backup the device name
534 std::string name = _backend->device_name ();
536 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
537 if ( ( 0 == stop () ) &&
538 ( 0 == _backend->reset_device () ) &&
539 ( 0 == start () ) ) {
541 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
543 // inform about possible changes
544 BufferSizeChanged (_backend->buffer_size() );
545 DeviceResetFinished(); // notify about device reset finish
549 DeviceResetFinished(); // notify about device reset finish
550 // we've got an error
554 std::cout << "AudioEngine::RESET::Done." << std::endl;
556 _reset_request_lock.lock();
560 _hw_reset_condition.wait (_reset_request_lock);
567 AudioEngine::request_device_list_update()
569 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
570 g_atomic_int_inc (&_hw_devicelist_update_count);
571 _hw_devicelist_update_condition.signal ();
575 AudioEngine::do_devicelist_update()
577 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
579 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
581 while (!_stop_hw_devicelist_processing) {
583 if (g_atomic_int_get (&_hw_devicelist_update_count)) {
585 _devicelist_update_lock.unlock();
587 Glib::Threads::RecMutex::Lock pl (_state_lock);
589 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
590 DeviceListChanged (); /* EMIT SIGNAL */
592 _devicelist_update_lock.lock();
595 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
602 AudioEngine::start_hw_event_processing()
604 if (_hw_reset_event_thread == 0) {
605 g_atomic_int_set(&_hw_reset_request_count, 0);
606 g_atomic_int_set(&_stop_hw_reset_processing, 0);
607 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
610 if (_hw_devicelist_update_thread == 0) {
611 g_atomic_int_set(&_hw_devicelist_update_count, 0);
612 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
613 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
619 AudioEngine::stop_hw_event_processing()
621 if (_hw_reset_event_thread) {
622 g_atomic_int_set(&_stop_hw_reset_processing, 1);
623 g_atomic_int_set(&_hw_reset_request_count, 0);
624 _hw_reset_condition.signal ();
625 _hw_reset_event_thread->join ();
626 _hw_reset_event_thread = 0;
629 if (_hw_devicelist_update_thread) {
630 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
631 g_atomic_int_set(&_hw_devicelist_update_count, 0);
632 _hw_devicelist_update_condition.signal ();
633 _hw_devicelist_update_thread->join ();
634 _hw_devicelist_update_thread = 0;
639 AudioEngine::set_session (Session *s)
641 Glib::Threads::Mutex::Lock pl (_process_lock);
643 SessionHandlePtr::set_session (s);
647 pframes_t blocksize = samples_per_cycle ();
649 PortManager::cycle_start (blocksize);
651 _session->process (blocksize);
652 _session->process (blocksize);
653 _session->process (blocksize);
654 _session->process (blocksize);
655 _session->process (blocksize);
656 _session->process (blocksize);
657 _session->process (blocksize);
658 _session->process (blocksize);
660 PortManager::cycle_end (blocksize);
665 AudioEngine::remove_session ()
667 Glib::Threads::Mutex::Lock lm (_process_lock);
672 session_remove_pending = true;
673 /* signal the start of the fade out countdown */
674 session_removal_countdown = -1;
675 session_removed.wait(_process_lock);
679 SessionHandlePtr::set_session (0);
687 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
689 #ifdef USE_TRACKS_CODE_FEATURES
691 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
700 /* called from a signal handler for SIGPIPE */
705 AudioEngine::reset_timebase ()
708 if (_session->config.get_jack_time_master()) {
709 _backend->set_time_master (true);
711 _backend->set_time_master (false);
719 AudioEngine::destroy ()
726 AudioEngine::discover_backends ()
728 vector<std::string> backend_modules;
732 Glib::PatternSpec so_extension_pattern("*backend.so");
733 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
735 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
736 #if defined(DEBUG) || defined(_DEBUG)
737 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
739 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
742 Glib::PatternSpec dll_extension_pattern("*backend.dll");
745 find_files_matching_pattern (backend_modules, backend_search_path (),
746 so_extension_pattern);
748 find_files_matching_pattern (backend_modules, backend_search_path (),
749 dylib_extension_pattern);
751 find_files_matching_pattern (backend_modules, backend_search_path (),
752 dll_extension_pattern);
754 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
756 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
758 AudioBackendInfo* info;
760 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
762 if ((info = backend_discover (*i)) != 0) {
763 _backends.insert (make_pair (info->name, info));
767 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
769 return _backends.size();
773 AudioEngine::backend_discover (const string& path)
775 #ifdef PLATFORM_WINDOWS
776 // do not show popup dialog (e.g. missing libjack.dll)
777 // win7+ should use SetThreadErrorMode()
778 SetErrorMode(SEM_FAILCRITICALERRORS);
780 Glib::Module module (path);
781 #ifdef PLATFORM_WINDOWS
782 SetErrorMode(0); // reset to system default
784 AudioBackendInfo* info;
785 AudioBackendInfo* (*dfunc)(void);
789 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
790 Glib::Module::get_last_error()) << endmsg;
794 if (!module.get_symbol ("descriptor", func)) {
795 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
796 error << Glib::Module::get_last_error() << endmsg;
800 dfunc = (AudioBackendInfo* (*)(void))func;
802 if (!info->available()) {
806 module.make_resident ();
812 static bool running_from_source_tree ()
814 // dup ARDOUR_UI_UTILS::running_from_source_tree ()
815 gchar const *x = g_getenv ("ARDOUR_THEMES_PATH");
816 return x && (string (x).find ("gtk2_ardour") != string::npos);
820 vector<const AudioBackendInfo*>
821 AudioEngine::available_backends() const
823 vector<const AudioBackendInfo*> r;
825 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
827 if (i->first == "None (Dummy)" && !running_from_source_tree () && Config->get_hide_dummy_backend ()) {
831 r.push_back (i->second);
838 AudioEngine::current_backend_name() const
841 return _backend->name();
847 AudioEngine::drop_backend ()
851 // Stopped is needed for Graph to explicitly terminate threads
852 Stopped (); /* EMIT SIGNAL */
853 _backend->drop_device ();
859 boost::shared_ptr<AudioBackend>
860 AudioEngine::set_default_backend ()
862 if (_backends.empty()) {
863 return boost::shared_ptr<AudioBackend>();
866 return set_backend (_backends.begin()->first, "", "");
869 boost::shared_ptr<AudioBackend>
870 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
872 BackendMap::iterator b = _backends.find (name);
874 if (b == _backends.end()) {
875 return boost::shared_ptr<AudioBackend>();
881 if (b->second->instantiate (arg1, arg2)) {
882 throw failed_constructor ();
885 _backend = b->second->factory (*this);
887 } catch (exception& e) {
888 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
889 return boost::shared_ptr<AudioBackend>();
895 /* BACKEND PROXY WRAPPERS */
898 AudioEngine::start (bool for_latency)
908 _processed_samples = 0;
909 last_monitor_check = 0;
911 int error_code = _backend->start (for_latency);
913 if (error_code != 0) {
914 _last_backend_error_string = AudioBackend::get_error_string((AudioBackend::ErrorCode) error_code);
921 _session->set_sample_rate (_backend->sample_rate());
923 if (_session->config.get_jack_time_master()) {
924 _backend->set_time_master (true);
929 /* XXX MIDI ports may not actually be available here yet .. */
931 PortManager::fill_midi_port_info ();
934 /* Call the library-wide ::init_post_engine() before emitting
935 * running to ensure that its tasks are complete before any
936 * signal handlers execute. PBD::Signal does not ensure
937 * ordering of signal handlers so even if ::init_post_engine()
938 * is connected first, it may not run first.
941 ARDOUR::init_post_engine (_start_cnt);
943 Running (_start_cnt); /* EMIT SIGNAL */
945 /* latency start/stop cycles do not count as "starts" */
955 AudioEngine::stop (bool for_latency)
957 bool stop_engine = true;
963 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
969 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
972 _backend->start (false); // keep running, reload latencies
975 if (_backend->stop ()) {
987 const bool was_running_will_stop = (_running && stop_engine);
989 if (was_running_will_stop) {
993 if (_session && was_running_will_stop &&
994 (_session->state_of_the_state() & Session::Loading) == 0 &&
995 (_session->state_of_the_state() & Session::Deletion) == 0) {
996 // it's not a halt, but should be handled the same way:
997 // disable record, stop transport and I/O processign but save the data.
998 _session->engine_halted ();
1001 if (was_running_will_stop) {
1003 _started_for_latency = false;
1004 } else if (!_started_for_latency) {
1005 _stopped_for_latency = true;
1008 _processed_samples = 0;
1009 _measuring_latency = MeasureNone;
1010 _latency_output_port = 0;
1011 _latency_input_port = 0;
1018 TransportMasterManager& tmm (TransportMasterManager::instance());
1019 tmm.engine_stopped ();
1020 Stopped (); /* EMIT SIGNAL */
1027 AudioEngine::freewheel (bool start_stop)
1033 /* _freewheeling will be set when first Freewheel signal occurs */
1035 return _backend->freewheel (start_stop);
1039 AudioEngine::get_dsp_load() const
1041 if (!_backend || !_running) {
1044 return _backend->dsp_load ();
1048 AudioEngine::is_realtime() const
1054 return _backend->is_realtime();
1058 AudioEngine::transport_start ()
1063 return _backend->transport_start ();
1067 AudioEngine::transport_stop ()
1072 return _backend->transport_stop ();
1076 AudioEngine::transport_state ()
1079 return TransportStopped;
1081 return _backend->transport_state ();
1085 AudioEngine::transport_locate (samplepos_t pos)
1090 return _backend->transport_locate (pos);
1094 AudioEngine::transport_sample()
1099 return _backend->transport_sample ();
1103 AudioEngine::sample_rate () const
1108 return _backend->sample_rate ();
1112 AudioEngine::samples_per_cycle () const
1117 return _backend->buffer_size ();
1121 AudioEngine::usecs_per_cycle () const
1126 return _backend->usecs_per_cycle ();
1130 AudioEngine::raw_buffer_size (DataType t)
1135 return _backend->raw_buffer_size (t);
1139 AudioEngine::sample_time ()
1144 return _backend->sample_time ();
1148 AudioEngine::sample_time_at_cycle_start ()
1153 return _backend->sample_time_at_cycle_start ();
1157 AudioEngine::samples_since_cycle_start ()
1162 return _backend->samples_since_cycle_start ();
1166 AudioEngine::get_sync_offset (pframes_t& offset) const
1171 return _backend->get_sync_offset (offset);
1175 AudioEngine::create_process_thread (boost::function<void()> func)
1180 return _backend->create_process_thread (func);
1184 AudioEngine::join_process_threads ()
1189 return _backend->join_process_threads ();
1193 AudioEngine::in_process_thread ()
1198 return _backend->in_process_thread ();
1202 AudioEngine::process_thread_count ()
1207 return _backend->process_thread_count ();
1211 AudioEngine::set_device_name (const std::string& name)
1216 return _backend->set_device_name (name);
1220 AudioEngine::set_sample_rate (float sr)
1226 return _backend->set_sample_rate (sr);
1230 AudioEngine::set_buffer_size (uint32_t bufsiz)
1235 return _backend->set_buffer_size (bufsiz);
1239 AudioEngine::set_interleaved (bool yn)
1244 return _backend->set_interleaved (yn);
1248 AudioEngine::set_input_channels (uint32_t ic)
1253 return _backend->set_input_channels (ic);
1257 AudioEngine::set_output_channels (uint32_t oc)
1262 return _backend->set_output_channels (oc);
1266 AudioEngine::set_systemic_input_latency (uint32_t il)
1271 return _backend->set_systemic_input_latency (il);
1275 AudioEngine::set_systemic_output_latency (uint32_t ol)
1280 return _backend->set_systemic_output_latency (ol);
1284 AudioEngine::thread_initialised_for_audio_processing ()
1286 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1289 /* END OF BACKEND PROXY API */
1292 AudioEngine::thread_init_callback (void* arg)
1294 /* make sure that anybody who needs to know about this thread
1298 pthread_set_name (X_("audioengine"));
1300 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1301 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1303 SessionEvent::create_per_thread_pool (thread_name, 512);
1304 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1305 AsyncMIDIPort::set_process_thread (pthread_self());
1308 delete AudioEngine::instance()->_main_thread;
1309 /* the special thread created/managed by the backend */
1310 AudioEngine::instance()->_main_thread = new ProcessThread;
1315 AudioEngine::sync_callback (TransportState state, samplepos_t position)
1318 return _session->backend_sync_callback (state, position);
1324 AudioEngine::freewheel_callback (bool onoff)
1326 _freewheeling = onoff;
1330 AudioEngine::latency_callback (bool for_playback)
1333 _session->update_latency (for_playback);
1338 AudioEngine::update_latencies ()
1341 _backend->update_latencies ();
1346 AudioEngine::halted_callback (const char* why)
1348 if (_in_destructor) {
1349 /* everything is under control */
1355 Port::PortDrop (); /* EMIT SIGNAL */
1357 if (!_started_for_latency) {
1358 Halted (why); /* EMIT SIGNAL */
1363 AudioEngine::setup_required () const
1366 if (_backend->info().already_configured())
1369 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1378 AudioEngine::prepare_for_latency_measurement ()
1384 if (running() && _started_for_latency) {
1388 if (_backend->can_change_systemic_latency_when_running()) {
1390 _backend->start (true); // zero latency reporting of running backend
1391 } else if (start (true)) {
1394 _started_for_latency = true;
1405 _started_for_latency = true;
1410 AudioEngine::start_latency_detection (bool for_midi)
1412 if (prepare_for_latency_measurement ()) {
1416 PortEngine& pe (port_engine());
1424 /* find the ports we will connect to */
1426 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1427 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1434 /* create the ports we will use to read/write data */
1436 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1440 if (pe.connect (_latency_output_port, _latency_output_name)) {
1441 pe.unregister_port (_latency_output_port);
1446 const string portname ("latency_in");
1447 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1448 pe.unregister_port (_latency_input_port);
1449 pe.unregister_port (_latency_output_port);
1453 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1454 pe.unregister_port (_latency_input_port);
1455 pe.unregister_port (_latency_output_port);
1460 _mididm = new MIDIDM (sample_rate());
1464 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1468 if (pe.connect (_latency_output_port, _latency_output_name)) {
1469 pe.unregister_port (_latency_output_port);
1474 const string portname ("latency_in");
1475 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1476 pe.unregister_port (_latency_input_port);
1477 pe.unregister_port (_latency_output_port);
1481 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1482 pe.unregister_port (_latency_input_port);
1483 pe.unregister_port (_latency_output_port);
1488 _mtdm = new MTDM (sample_rate());
1493 _latency_signal_latency = 0;
1494 lr = pe.get_latency_range (in, false);
1495 _latency_signal_latency = lr.max;
1496 lr = pe.get_latency_range (out, true);
1497 _latency_signal_latency += lr.max;
1499 /* all created and connected, lets go */
1500 _latency_flush_samples = samples_per_cycle();
1501 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1507 AudioEngine::stop_latency_detection ()
1509 _measuring_latency = MeasureNone;
1511 if (_latency_output_port) {
1512 port_engine().unregister_port (_latency_output_port);
1513 _latency_output_port = 0;
1515 if (_latency_input_port) {
1516 port_engine().unregister_port (_latency_input_port);
1517 _latency_input_port = 0;
1520 if (_running && _backend->can_change_systemic_latency_when_running()) {
1521 if (_started_for_latency) {
1522 _running = false; // force reload: reset latencies and emit Running()
1527 if (_running && !_started_for_latency) {
1528 assert (!_stopped_for_latency);
1532 if (!_backend->can_change_systemic_latency_when_running()) {
1536 if (_stopped_for_latency) {
1540 _stopped_for_latency = false;
1541 _started_for_latency = false;
1545 AudioEngine::set_latency_output_port (const string& name)
1547 _latency_output_name = name;
1551 AudioEngine::set_latency_input_port (const string& name)
1553 _latency_input_name = name;
1557 AudioEngine::add_pending_port_deletion (Port* p)
1560 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1561 if (_port_deletions_pending.write (&p, 1) != 1) {
1562 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1564 _session->auto_connect_thread_wakeup ();
1566 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));