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/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"
51 #include "ardour/midiport_manager.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/rc_configuration.h"
57 #include "ardour/session.h"
62 using namespace ARDOUR;
65 AudioEngine* AudioEngine::_instance = 0;
67 static gint audioengine_thread_cnt = 1;
70 #define SILENCE_AFTER_SECONDS 600
73 AudioEngine::AudioEngine ()
74 : session_remove_pending (false)
75 , session_removal_countdown (-1)
77 , _freewheeling (false)
78 , monitor_check_interval (INT32_MAX)
79 , last_monitor_check (0)
80 , _processed_samples (0)
85 , _measuring_latency (MeasureNone)
86 , _latency_input_port (0)
87 , _latency_output_port (0)
88 , _latency_flush_samples (0)
89 , _latency_signal_latency (0)
90 , _stopped_for_latency (false)
91 , _started_for_latency (false)
92 , _in_destructor (false)
93 , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
94 , _hw_reset_event_thread(0)
95 , _hw_reset_request_count(0)
96 , _stop_hw_reset_processing(0)
97 , _hw_devicelist_update_thread(0)
98 , _hw_devicelist_update_count(0)
99 , _stop_hw_devicelist_processing(0)
100 #ifdef SILENCE_AFTER_SECONDS
101 , _silence_countdown (0)
102 , _silence_hit_cnt (0)
105 reset_silence_countdown ();
106 start_hw_event_processing();
107 discover_backends ();
110 AudioEngine::~AudioEngine ()
112 _in_destructor = true;
113 stop_hw_event_processing();
115 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
116 i->second->deinstantiate();
122 AudioEngine::create ()
128 _instance = new AudioEngine ();
134 AudioEngine::split_cycle (pframes_t offset)
136 /* caller must hold process lock */
138 Port::increment_global_port_buffer_offset (offset);
140 /* tell all Ports that we're going to start a new (split) cycle */
142 boost::shared_ptr<Ports> p = ports.reader();
144 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
145 i->second->cycle_split ();
150 AudioEngine::sample_rate_change (pframes_t nframes)
152 /* check for monitor input change every 1/10th of second */
154 monitor_check_interval = nframes / 10;
155 last_monitor_check = 0;
158 _session->set_sample_rate (nframes);
161 SampleRateChanged (nframes); /* EMIT SIGNAL */
163 #ifdef SILENCE_AFTER_SECONDS
164 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
171 AudioEngine::buffer_size_change (pframes_t bufsiz)
174 _session->set_block_size (bufsiz);
175 last_monitor_check = 0;
178 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
183 /** Method called by our ::process_thread when there is work to be done.
184 * @param nframes Number of samples to process.
187 __attribute__((annotate("realtime")))
190 AudioEngine::process_callback (pframes_t nframes)
192 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
193 Port::set_speed_ratio (1.0);
198 /// The number of samples that will have been processed when we've finished
199 pframes_t next_processed_samples;
201 /* handle wrap around of total samples counter */
203 if (max_samplepos - _processed_samples < nframes) {
204 next_processed_samples = nframes - (max_samplepos - _processed_samples);
206 next_processed_samples = _processed_samples + nframes;
210 /* return having done nothing */
214 /* really only JACK requires this
215 * (other backends clear the output buffers
216 * before the process_callback. it may even be
217 * jack/alsa only). but better safe than sorry.
219 PortManager::silence_outputs (nframes);
223 /* The coreaudio-backend calls thread_init_callback() if
224 * the hardware changes or pthread_self() changes.
226 * However there are cases when neither holds true, yet
227 * the thread-pool changes: e.g. connect a headphone to
228 * a shared mic/headphone jack.
229 * It's probably related to, or caused by clocksource changes.
231 * For reasons yet unknown Glib::Threads::Private() can
232 * use a different thread-private in the same pthread
233 * (coreaudio render callback).
235 * Coreaudio must set something which influences
236 * pthread_key_t uniqness or reset the key using
237 * pthread_getspecific().
239 if (! SessionEvent::has_per_thread_pool ()) {
240 thread_init_callback (NULL);
243 bool return_after_remove_check = false;
245 if (_measuring_latency == MeasureAudio && _mtdm) {
246 /* run a normal cycle from the perspective of the PortManager
247 so that we get silence on all registered ports.
249 we overwrite the silence on the two ports used for latency
253 PortManager::cycle_start (nframes);
254 PortManager::silence (nframes);
256 if (_latency_input_port && _latency_output_port) {
257 PortEngine& pe (port_engine());
259 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
260 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
262 _mtdm->process (nframes, in, out);
265 PortManager::cycle_end (nframes);
266 return_after_remove_check = true;
268 } else if (_measuring_latency == MeasureMIDI && _mididm) {
269 /* run a normal cycle from the perspective of the PortManager
270 so that we get silence on all registered ports.
272 we overwrite the silence on the two ports used for latency
276 PortManager::cycle_start (nframes);
277 PortManager::silence (nframes);
279 if (_latency_input_port && _latency_output_port) {
280 PortEngine& pe (port_engine());
282 _mididm->process (nframes, pe,
283 pe.get_buffer (_latency_input_port, nframes),
284 pe.get_buffer (_latency_output_port, nframes));
287 PortManager::cycle_end (nframes);
288 return_after_remove_check = true;
290 } else if (_latency_flush_samples) {
292 /* wait for the appropriate duration for the MTDM signal to
293 * drain from the ports before we revert to normal behaviour.
296 PortManager::cycle_start (nframes);
297 PortManager::silence (nframes);
298 PortManager::cycle_end (nframes);
300 if (_latency_flush_samples > nframes) {
301 _latency_flush_samples -= nframes;
303 _latency_flush_samples = 0;
306 return_after_remove_check = true;
309 if (session_remove_pending) {
311 /* perform the actual session removal */
313 if (session_removal_countdown < 0) {
315 /* fade out over 1 second */
316 session_removal_countdown = sample_rate()/2;
317 session_removal_gain = GAIN_COEFF_UNITY;
318 session_removal_gain_step = 1.0/session_removal_countdown;
320 } else if (session_removal_countdown > 0) {
322 /* we'll be fading audio out.
324 if this is the last time we do this as part
325 of session removal, do a MIDI panic now
326 to get MIDI stopped. This relies on the fact
327 that "immediate data" (aka "out of band data") from
328 MIDI tracks is *appended* after any other data,
329 so that it emerges after any outbound note ons, etc.
332 if (session_removal_countdown <= nframes) {
333 _session->midi_panic ();
339 session_removal_countdown = -1; // reset to "not in progress"
340 session_remove_pending = false;
341 session_removed.signal(); // wakes up thread that initiated session removal
345 if (return_after_remove_check) {
351 if (!_freewheeling) {
352 PortManager::silence_outputs (nframes);
355 _processed_samples = next_processed_samples;
360 if (!_freewheeling || Freewheel.empty()) {
361 // run a list of slaves here
362 // - multiple slaves (ow_many_dsp_threads() in paralell)
363 // - session can pick one (ask for position & speed)
364 // - GUI can display all
365 Port::set_speed_ratio (_session->engine_speed ());
368 /* tell all relevant objects that we're starting a new cycle */
370 InternalSend::CycleStart (nframes);
372 /* tell all Ports that we're starting a new cycle */
374 PortManager::cycle_start (nframes, _session);
376 /* test if we are freewheeling and there are freewheel signals connected.
377 * ardour should act normally even when freewheeling unless /it/ is
378 * exporting (which is what Freewheel.empty() tests for).
381 if (_freewheeling && !Freewheel.empty()) {
384 if (Port::cycle_nframes () <= nframes) {
385 _session->process (Port::cycle_nframes ());
387 pframes_t remain = Port::cycle_nframes ();
389 pframes_t nf = std::min (remain, nframes);
390 _session->process (nf);
400 PortManager::cycle_end (nframes, _session);
405 _processed_samples = next_processed_samples;
409 if (last_monitor_check + monitor_check_interval < next_processed_samples) {
411 PortManager::check_monitoring ();
412 last_monitor_check = next_processed_samples;
415 #ifdef SILENCE_AFTER_SECONDS
417 bool was_silent = (_silence_countdown == 0);
419 if (_silence_countdown >= nframes) {
420 _silence_countdown -= nframes;
422 _silence_countdown = 0;
425 if (!was_silent && _silence_countdown == 0) {
427 BecameSilent (); /* EMIT SIGNAL */
430 if (_silence_countdown == 0 || _session->silent()) {
431 PortManager::silence (nframes);
435 if (_session->silent()) {
436 PortManager::silence (nframes, _session);
440 if (session_remove_pending && session_removal_countdown) {
442 PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session);
444 if (session_removal_countdown > nframes) {
445 session_removal_countdown -= nframes;
447 session_removal_countdown = 0;
450 session_removal_gain -= (nframes * session_removal_gain_step);
452 PortManager::cycle_end (nframes, _session);
455 _processed_samples = next_processed_samples;
463 AudioEngine::reset_silence_countdown ()
465 #ifdef SILENCE_AFTER_SECONDS
466 double sr = 48000; /* default in case there is no backend */
470 _silence_countdown = max (60 * sr, /* 60 seconds */
471 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
477 AudioEngine::launch_device_control_app()
479 if (_state_lock.trylock () ) {
480 _backend->launch_control_app ();
481 _state_lock.unlock ();
487 AudioEngine::request_backend_reset()
489 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
490 g_atomic_int_inc (&_hw_reset_request_count);
491 _hw_reset_condition.signal ();
495 AudioEngine::backend_reset_requested()
497 return g_atomic_int_get (&_hw_reset_request_count);
501 AudioEngine::do_reset_backend()
503 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
505 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
507 while (!_stop_hw_reset_processing) {
509 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
511 _reset_request_lock.unlock();
513 Glib::Threads::RecMutex::Lock pl (_state_lock);
514 g_atomic_int_dec_and_test (&_hw_reset_request_count);
516 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
517 DeviceResetStarted(); // notify about device reset to be started
519 // backup the device name
520 std::string name = _backend->device_name ();
522 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
523 if ( ( 0 == stop () ) &&
524 ( 0 == _backend->reset_device () ) &&
525 ( 0 == start () ) ) {
527 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
529 // inform about possible changes
530 BufferSizeChanged (_backend->buffer_size() );
531 DeviceResetFinished(); // notify about device reset finish
535 DeviceResetFinished(); // notify about device reset finish
536 // we've got an error
540 std::cout << "AudioEngine::RESET::Done." << std::endl;
542 _reset_request_lock.lock();
546 _hw_reset_condition.wait (_reset_request_lock);
553 AudioEngine::request_device_list_update()
555 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
556 g_atomic_int_inc (&_hw_devicelist_update_count);
557 _hw_devicelist_update_condition.signal ();
561 AudioEngine::do_devicelist_update()
563 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
565 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
567 while (!_stop_hw_devicelist_processing) {
569 if (_hw_devicelist_update_count) {
571 _devicelist_update_lock.unlock();
573 Glib::Threads::RecMutex::Lock pl (_state_lock);
575 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
576 DeviceListChanged (); /* EMIT SIGNAL */
578 _devicelist_update_lock.lock();
581 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
588 AudioEngine::start_hw_event_processing()
590 if (_hw_reset_event_thread == 0) {
591 g_atomic_int_set(&_hw_reset_request_count, 0);
592 g_atomic_int_set(&_stop_hw_reset_processing, 0);
593 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
596 if (_hw_devicelist_update_thread == 0) {
597 g_atomic_int_set(&_hw_devicelist_update_count, 0);
598 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
599 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
605 AudioEngine::stop_hw_event_processing()
607 if (_hw_reset_event_thread) {
608 g_atomic_int_set(&_stop_hw_reset_processing, 1);
609 g_atomic_int_set(&_hw_reset_request_count, 0);
610 _hw_reset_condition.signal ();
611 _hw_reset_event_thread->join ();
612 _hw_reset_event_thread = 0;
615 if (_hw_devicelist_update_thread) {
616 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
617 g_atomic_int_set(&_hw_devicelist_update_count, 0);
618 _hw_devicelist_update_condition.signal ();
619 _hw_devicelist_update_thread->join ();
620 _hw_devicelist_update_thread = 0;
625 AudioEngine::set_session (Session *s)
627 Glib::Threads::Mutex::Lock pl (_process_lock);
629 SessionHandlePtr::set_session (s);
633 pframes_t blocksize = samples_per_cycle ();
635 PortManager::cycle_start (blocksize);
637 _session->process (blocksize);
638 _session->process (blocksize);
639 _session->process (blocksize);
640 _session->process (blocksize);
641 _session->process (blocksize);
642 _session->process (blocksize);
643 _session->process (blocksize);
644 _session->process (blocksize);
646 PortManager::cycle_end (blocksize);
651 AudioEngine::remove_session ()
653 Glib::Threads::Mutex::Lock lm (_process_lock);
658 session_remove_pending = true;
659 /* signal the start of the fade out countdown */
660 session_removal_countdown = -1;
661 session_removed.wait(_process_lock);
665 SessionHandlePtr::set_session (0);
673 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
675 #ifdef USE_TRACKS_CODE_FEATURES
677 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
686 /* called from a signal handler for SIGPIPE */
691 AudioEngine::reset_timebase ()
694 if (_session->config.get_jack_time_master()) {
695 _backend->set_time_master (true);
697 _backend->set_time_master (false);
705 AudioEngine::destroy ()
712 AudioEngine::discover_backends ()
714 vector<std::string> backend_modules;
718 Glib::PatternSpec so_extension_pattern("*backend.so");
719 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
721 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
722 #if defined(DEBUG) || defined(_DEBUG)
723 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
725 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
728 Glib::PatternSpec dll_extension_pattern("*backend.dll");
731 find_files_matching_pattern (backend_modules, backend_search_path (),
732 so_extension_pattern);
734 find_files_matching_pattern (backend_modules, backend_search_path (),
735 dylib_extension_pattern);
737 find_files_matching_pattern (backend_modules, backend_search_path (),
738 dll_extension_pattern);
740 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
742 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
744 AudioBackendInfo* info;
746 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
748 if ((info = backend_discover (*i)) != 0) {
749 _backends.insert (make_pair (info->name, info));
753 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
755 return _backends.size();
759 AudioEngine::backend_discover (const string& path)
761 #ifdef PLATFORM_WINDOWS
762 // do not show popup dialog (e.g. missing libjack.dll)
763 // win7+ should use SetThreadErrorMode()
764 SetErrorMode(SEM_FAILCRITICALERRORS);
766 Glib::Module module (path);
767 #ifdef PLATFORM_WINDOWS
768 SetErrorMode(0); // reset to system default
770 AudioBackendInfo* info;
771 AudioBackendInfo* (*dfunc)(void);
775 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
776 Glib::Module::get_last_error()) << endmsg;
780 if (!module.get_symbol ("descriptor", func)) {
781 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
782 error << Glib::Module::get_last_error() << endmsg;
786 dfunc = (AudioBackendInfo* (*)(void))func;
788 if (!info->available()) {
792 module.make_resident ();
798 static bool running_from_source_tree ()
800 // dup ARDOUR_UI_UTILS::running_from_source_tree ()
801 gchar const *x = g_getenv ("ARDOUR_THEMES_PATH");
802 return x && (string (x).find ("gtk2_ardour") != string::npos);
806 vector<const AudioBackendInfo*>
807 AudioEngine::available_backends() const
809 vector<const AudioBackendInfo*> r;
811 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
813 if (i->first == "None (Dummy)" && !running_from_source_tree () && Config->get_hide_dummy_backend ()) {
817 r.push_back (i->second);
824 AudioEngine::current_backend_name() const
827 return _backend->name();
833 AudioEngine::drop_backend ()
837 // Stopped is needed for Graph to explicitly terminate threads
838 Stopped (); /* EMIT SIGNAL */
839 _backend->drop_device ();
845 boost::shared_ptr<AudioBackend>
846 AudioEngine::set_default_backend ()
848 if (_backends.empty()) {
849 return boost::shared_ptr<AudioBackend>();
852 return set_backend (_backends.begin()->first, "", "");
855 boost::shared_ptr<AudioBackend>
856 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
858 BackendMap::iterator b = _backends.find (name);
860 if (b == _backends.end()) {
861 return boost::shared_ptr<AudioBackend>();
867 if (b->second->instantiate (arg1, arg2)) {
868 throw failed_constructor ();
871 _backend = b->second->factory (*this);
873 } catch (exception& e) {
874 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
875 return boost::shared_ptr<AudioBackend>();
881 /* BACKEND PROXY WRAPPERS */
884 AudioEngine::start (bool for_latency)
894 _processed_samples = 0;
895 last_monitor_check = 0;
897 int error_code = _backend->start (for_latency);
899 if (error_code != 0) {
900 _last_backend_error_string = AudioBackend::get_error_string((AudioBackend::ErrorCode) error_code);
907 _session->set_sample_rate (_backend->sample_rate());
909 if (_session->config.get_jack_time_master()) {
910 _backend->set_time_master (true);
915 /* XXX MIDI ports may not actually be available here yet .. */
917 PortManager::fill_midi_port_info ();
920 Running(); /* EMIT SIGNAL */
927 AudioEngine::stop (bool for_latency)
929 bool stop_engine = true;
935 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
941 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
944 _backend->start (false); // keep running, reload latencies
947 if (_backend->stop ()) {
959 if (_session && _running && stop_engine &&
960 (_session->state_of_the_state() & Session::Loading) == 0 &&
961 (_session->state_of_the_state() & Session::Deletion) == 0) {
962 // it's not a halt, but should be handled the same way:
963 // disable record, stop transport and I/O processign but save the data.
964 _session->engine_halted ();
967 if (stop_engine && _running) {
970 _started_for_latency = false;
971 } else if (!_started_for_latency) {
972 _stopped_for_latency = true;
975 _processed_samples = 0;
976 _measuring_latency = MeasureNone;
977 _latency_output_port = 0;
978 _latency_input_port = 0;
985 Stopped (); /* EMIT SIGNAL */
992 AudioEngine::freewheel (bool start_stop)
998 /* _freewheeling will be set when first Freewheel signal occurs */
1000 return _backend->freewheel (start_stop);
1004 AudioEngine::get_dsp_load() const
1006 if (!_backend || !_running) {
1009 return _backend->dsp_load ();
1013 AudioEngine::is_realtime() const
1019 return _backend->is_realtime();
1023 AudioEngine::connected() const
1029 return _backend->available();
1033 AudioEngine::transport_start ()
1038 return _backend->transport_start ();
1042 AudioEngine::transport_stop ()
1047 return _backend->transport_stop ();
1051 AudioEngine::transport_state ()
1054 return TransportStopped;
1056 return _backend->transport_state ();
1060 AudioEngine::transport_locate (samplepos_t pos)
1065 return _backend->transport_locate (pos);
1069 AudioEngine::transport_sample()
1074 return _backend->transport_sample ();
1078 AudioEngine::sample_rate () const
1083 return _backend->sample_rate ();
1087 AudioEngine::samples_per_cycle () const
1092 return _backend->buffer_size ();
1096 AudioEngine::usecs_per_cycle () const
1101 return _backend->usecs_per_cycle ();
1105 AudioEngine::raw_buffer_size (DataType t)
1110 return _backend->raw_buffer_size (t);
1114 AudioEngine::sample_time ()
1119 return _backend->sample_time ();
1123 AudioEngine::sample_time_at_cycle_start ()
1128 return _backend->sample_time_at_cycle_start ();
1132 AudioEngine::samples_since_cycle_start ()
1137 return _backend->samples_since_cycle_start ();
1141 AudioEngine::get_sync_offset (pframes_t& offset) const
1146 return _backend->get_sync_offset (offset);
1150 AudioEngine::create_process_thread (boost::function<void()> func)
1155 return _backend->create_process_thread (func);
1159 AudioEngine::join_process_threads ()
1164 return _backend->join_process_threads ();
1168 AudioEngine::in_process_thread ()
1173 return _backend->in_process_thread ();
1177 AudioEngine::process_thread_count ()
1182 return _backend->process_thread_count ();
1186 AudioEngine::set_device_name (const std::string& name)
1191 return _backend->set_device_name (name);
1195 AudioEngine::set_sample_rate (float sr)
1201 return _backend->set_sample_rate (sr);
1205 AudioEngine::set_buffer_size (uint32_t bufsiz)
1210 return _backend->set_buffer_size (bufsiz);
1214 AudioEngine::set_interleaved (bool yn)
1219 return _backend->set_interleaved (yn);
1223 AudioEngine::set_input_channels (uint32_t ic)
1228 return _backend->set_input_channels (ic);
1232 AudioEngine::set_output_channels (uint32_t oc)
1237 return _backend->set_output_channels (oc);
1241 AudioEngine::set_systemic_input_latency (uint32_t il)
1246 return _backend->set_systemic_input_latency (il);
1250 AudioEngine::set_systemic_output_latency (uint32_t ol)
1255 return _backend->set_systemic_output_latency (ol);
1259 AudioEngine::thread_initialised_for_audio_processing ()
1261 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1264 /* END OF BACKEND PROXY API */
1267 AudioEngine::thread_init_callback (void* arg)
1269 /* make sure that anybody who needs to know about this thread
1273 pthread_set_name (X_("audioengine"));
1275 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1276 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1278 SessionEvent::create_per_thread_pool (thread_name, 512);
1279 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1280 AsyncMIDIPort::set_process_thread (pthread_self());
1283 delete AudioEngine::instance()->_main_thread;
1284 /* the special thread created/managed by the backend */
1285 AudioEngine::instance()->_main_thread = new ProcessThread;
1290 AudioEngine::sync_callback (TransportState state, samplepos_t position)
1293 return _session->backend_sync_callback (state, position);
1299 AudioEngine::freewheel_callback (bool onoff)
1301 _freewheeling = onoff;
1305 AudioEngine::latency_callback (bool for_playback)
1308 _session->update_latency (for_playback);
1313 AudioEngine::update_latencies ()
1316 _backend->update_latencies ();
1321 AudioEngine::halted_callback (const char* why)
1323 if (_in_destructor) {
1324 /* everything is under control */
1330 Port::PortDrop (); /* EMIT SIGNAL */
1332 if (!_started_for_latency) {
1333 Halted (why); /* EMIT SIGNAL */
1338 AudioEngine::setup_required () const
1341 if (_backend->info().already_configured())
1344 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1353 AudioEngine::prepare_for_latency_measurement ()
1359 if (running() && _started_for_latency) {
1363 if (_backend->can_change_systemic_latency_when_running()) {
1365 _backend->start (true); // zero latency reporting of running backend
1366 } else if (start (true)) {
1369 _started_for_latency = true;
1380 _started_for_latency = true;
1385 AudioEngine::start_latency_detection (bool for_midi)
1387 if (prepare_for_latency_measurement ()) {
1391 PortEngine& pe (port_engine());
1399 /* find the ports we will connect to */
1401 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1402 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1409 /* create the ports we will use to read/write data */
1411 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1415 if (pe.connect (_latency_output_port, _latency_output_name)) {
1416 pe.unregister_port (_latency_output_port);
1421 const string portname ("latency_in");
1422 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1423 pe.unregister_port (_latency_input_port);
1424 pe.unregister_port (_latency_output_port);
1428 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1429 pe.unregister_port (_latency_input_port);
1430 pe.unregister_port (_latency_output_port);
1435 _mididm = new MIDIDM (sample_rate());
1439 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1443 if (pe.connect (_latency_output_port, _latency_output_name)) {
1444 pe.unregister_port (_latency_output_port);
1449 const string portname ("latency_in");
1450 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1451 pe.unregister_port (_latency_input_port);
1452 pe.unregister_port (_latency_output_port);
1456 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1457 pe.unregister_port (_latency_input_port);
1458 pe.unregister_port (_latency_output_port);
1463 _mtdm = new MTDM (sample_rate());
1468 _latency_signal_latency = 0;
1469 lr = pe.get_latency_range (in, false);
1470 _latency_signal_latency = lr.max;
1471 lr = pe.get_latency_range (out, true);
1472 _latency_signal_latency += lr.max;
1474 /* all created and connected, lets go */
1475 _latency_flush_samples = samples_per_cycle();
1476 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1482 AudioEngine::stop_latency_detection ()
1484 _measuring_latency = MeasureNone;
1486 if (_latency_output_port) {
1487 port_engine().unregister_port (_latency_output_port);
1488 _latency_output_port = 0;
1490 if (_latency_input_port) {
1491 port_engine().unregister_port (_latency_input_port);
1492 _latency_input_port = 0;
1495 if (_running && _backend->can_change_systemic_latency_when_running()) {
1496 if (_started_for_latency) {
1497 _running = false; // force reload: reset latencies and emit Running()
1502 if (_running && !_started_for_latency) {
1503 assert (!_stopped_for_latency);
1507 if (!_backend->can_change_systemic_latency_when_running()) {
1511 if (_stopped_for_latency) {
1515 _stopped_for_latency = false;
1516 _started_for_latency = false;
1520 AudioEngine::set_latency_output_port (const string& name)
1522 _latency_output_name = name;
1526 AudioEngine::set_latency_input_port (const string& name)
1528 _latency_input_name = name;
1532 AudioEngine::add_pending_port_deletion (Port* p)
1535 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1536 if (_port_deletions_pending.write (&p, 1) != 1) {
1537 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1539 _session->auto_connect_thread_wakeup ();
1541 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));