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 // TODO: Run a list of slaves here
362 // - multiple TC slaves (how_many_dsp_threads() in parallel)
363 // (note this can be multiple slaves of each type. e.g.
364 // 3 LTC slaves on different ports, 2 MTC..)
365 // - GUI can display all slaves, user picks one.
366 // - active "slave" is a session property.
367 // - here we ask the session about the active slave
368 // and get playback speed (for this cycle) here.
369 // - Internal Transport is-a Slave too (!)
370 Port::set_speed_ratio (_session->engine_speed ()); // HACK
373 /* tell all relevant objects that we're starting a new cycle */
375 InternalSend::CycleStart (nframes);
377 /* tell all Ports that we're starting a new cycle */
379 PortManager::cycle_start (nframes, _session);
381 /* test if we are freewheeling and there are freewheel signals connected.
382 * ardour should act normally even when freewheeling unless /it/ is
383 * exporting (which is what Freewheel.empty() tests for).
386 if (_freewheeling && !Freewheel.empty()) {
389 if (Port::cycle_nframes () <= nframes) {
390 _session->process (Port::cycle_nframes ());
392 pframes_t remain = Port::cycle_nframes ();
394 pframes_t nf = std::min (remain, nframes);
395 _session->process (nf);
405 PortManager::cycle_end (nframes, _session);
410 _processed_samples = next_processed_samples;
414 if (last_monitor_check + monitor_check_interval < next_processed_samples) {
416 PortManager::check_monitoring ();
417 last_monitor_check = next_processed_samples;
420 #ifdef SILENCE_AFTER_SECONDS
422 bool was_silent = (_silence_countdown == 0);
424 if (_silence_countdown >= nframes) {
425 _silence_countdown -= nframes;
427 _silence_countdown = 0;
430 if (!was_silent && _silence_countdown == 0) {
432 BecameSilent (); /* EMIT SIGNAL */
435 if (_silence_countdown == 0 || _session->silent()) {
436 PortManager::silence (nframes);
440 if (_session->silent()) {
441 PortManager::silence (nframes, _session);
445 if (session_remove_pending && session_removal_countdown) {
447 PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session);
449 if (session_removal_countdown > nframes) {
450 session_removal_countdown -= nframes;
452 session_removal_countdown = 0;
455 session_removal_gain -= (nframes * session_removal_gain_step);
457 PortManager::cycle_end (nframes, _session);
460 _processed_samples = next_processed_samples;
468 AudioEngine::reset_silence_countdown ()
470 #ifdef SILENCE_AFTER_SECONDS
471 double sr = 48000; /* default in case there is no backend */
475 _silence_countdown = max (60 * sr, /* 60 seconds */
476 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
482 AudioEngine::launch_device_control_app()
484 if (_state_lock.trylock () ) {
485 _backend->launch_control_app ();
486 _state_lock.unlock ();
492 AudioEngine::request_backend_reset()
494 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
495 g_atomic_int_inc (&_hw_reset_request_count);
496 _hw_reset_condition.signal ();
500 AudioEngine::backend_reset_requested()
502 return g_atomic_int_get (&_hw_reset_request_count);
506 AudioEngine::do_reset_backend()
508 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
510 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
512 while (!_stop_hw_reset_processing) {
514 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
516 _reset_request_lock.unlock();
518 Glib::Threads::RecMutex::Lock pl (_state_lock);
519 g_atomic_int_dec_and_test (&_hw_reset_request_count);
521 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
522 DeviceResetStarted(); // notify about device reset to be started
524 // backup the device name
525 std::string name = _backend->device_name ();
527 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
528 if ( ( 0 == stop () ) &&
529 ( 0 == _backend->reset_device () ) &&
530 ( 0 == start () ) ) {
532 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
534 // inform about possible changes
535 BufferSizeChanged (_backend->buffer_size() );
536 DeviceResetFinished(); // notify about device reset finish
540 DeviceResetFinished(); // notify about device reset finish
541 // we've got an error
545 std::cout << "AudioEngine::RESET::Done." << std::endl;
547 _reset_request_lock.lock();
551 _hw_reset_condition.wait (_reset_request_lock);
558 AudioEngine::request_device_list_update()
560 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
561 g_atomic_int_inc (&_hw_devicelist_update_count);
562 _hw_devicelist_update_condition.signal ();
566 AudioEngine::do_devicelist_update()
568 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
570 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
572 while (!_stop_hw_devicelist_processing) {
574 if (_hw_devicelist_update_count) {
576 _devicelist_update_lock.unlock();
578 Glib::Threads::RecMutex::Lock pl (_state_lock);
580 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
581 DeviceListChanged (); /* EMIT SIGNAL */
583 _devicelist_update_lock.lock();
586 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
593 AudioEngine::start_hw_event_processing()
595 if (_hw_reset_event_thread == 0) {
596 g_atomic_int_set(&_hw_reset_request_count, 0);
597 g_atomic_int_set(&_stop_hw_reset_processing, 0);
598 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
601 if (_hw_devicelist_update_thread == 0) {
602 g_atomic_int_set(&_hw_devicelist_update_count, 0);
603 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
604 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
610 AudioEngine::stop_hw_event_processing()
612 if (_hw_reset_event_thread) {
613 g_atomic_int_set(&_stop_hw_reset_processing, 1);
614 g_atomic_int_set(&_hw_reset_request_count, 0);
615 _hw_reset_condition.signal ();
616 _hw_reset_event_thread->join ();
617 _hw_reset_event_thread = 0;
620 if (_hw_devicelist_update_thread) {
621 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
622 g_atomic_int_set(&_hw_devicelist_update_count, 0);
623 _hw_devicelist_update_condition.signal ();
624 _hw_devicelist_update_thread->join ();
625 _hw_devicelist_update_thread = 0;
630 AudioEngine::set_session (Session *s)
632 Glib::Threads::Mutex::Lock pl (_process_lock);
634 SessionHandlePtr::set_session (s);
638 pframes_t blocksize = samples_per_cycle ();
640 PortManager::cycle_start (blocksize);
642 _session->process (blocksize);
643 _session->process (blocksize);
644 _session->process (blocksize);
645 _session->process (blocksize);
646 _session->process (blocksize);
647 _session->process (blocksize);
648 _session->process (blocksize);
649 _session->process (blocksize);
651 PortManager::cycle_end (blocksize);
656 AudioEngine::remove_session ()
658 Glib::Threads::Mutex::Lock lm (_process_lock);
663 session_remove_pending = true;
664 /* signal the start of the fade out countdown */
665 session_removal_countdown = -1;
666 session_removed.wait(_process_lock);
670 SessionHandlePtr::set_session (0);
678 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
680 #ifdef USE_TRACKS_CODE_FEATURES
682 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
691 /* called from a signal handler for SIGPIPE */
696 AudioEngine::reset_timebase ()
699 if (_session->config.get_jack_time_master()) {
700 _backend->set_time_master (true);
702 _backend->set_time_master (false);
710 AudioEngine::destroy ()
717 AudioEngine::discover_backends ()
719 vector<std::string> backend_modules;
723 Glib::PatternSpec so_extension_pattern("*backend.so");
724 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
726 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
727 #if defined(DEBUG) || defined(_DEBUG)
728 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
730 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
733 Glib::PatternSpec dll_extension_pattern("*backend.dll");
736 find_files_matching_pattern (backend_modules, backend_search_path (),
737 so_extension_pattern);
739 find_files_matching_pattern (backend_modules, backend_search_path (),
740 dylib_extension_pattern);
742 find_files_matching_pattern (backend_modules, backend_search_path (),
743 dll_extension_pattern);
745 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
747 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
749 AudioBackendInfo* info;
751 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
753 if ((info = backend_discover (*i)) != 0) {
754 _backends.insert (make_pair (info->name, info));
758 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
760 return _backends.size();
764 AudioEngine::backend_discover (const string& path)
766 #ifdef PLATFORM_WINDOWS
767 // do not show popup dialog (e.g. missing libjack.dll)
768 // win7+ should use SetThreadErrorMode()
769 SetErrorMode(SEM_FAILCRITICALERRORS);
771 Glib::Module module (path);
772 #ifdef PLATFORM_WINDOWS
773 SetErrorMode(0); // reset to system default
775 AudioBackendInfo* info;
776 AudioBackendInfo* (*dfunc)(void);
780 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
781 Glib::Module::get_last_error()) << endmsg;
785 if (!module.get_symbol ("descriptor", func)) {
786 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
787 error << Glib::Module::get_last_error() << endmsg;
791 dfunc = (AudioBackendInfo* (*)(void))func;
793 if (!info->available()) {
797 module.make_resident ();
803 static bool running_from_source_tree ()
805 // dup ARDOUR_UI_UTILS::running_from_source_tree ()
806 gchar const *x = g_getenv ("ARDOUR_THEMES_PATH");
807 return x && (string (x).find ("gtk2_ardour") != string::npos);
811 vector<const AudioBackendInfo*>
812 AudioEngine::available_backends() const
814 vector<const AudioBackendInfo*> r;
816 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
818 if (i->first == "None (Dummy)" && !running_from_source_tree () && Config->get_hide_dummy_backend ()) {
822 r.push_back (i->second);
829 AudioEngine::current_backend_name() const
832 return _backend->name();
838 AudioEngine::drop_backend ()
842 // Stopped is needed for Graph to explicitly terminate threads
843 Stopped (); /* EMIT SIGNAL */
844 _backend->drop_device ();
850 boost::shared_ptr<AudioBackend>
851 AudioEngine::set_default_backend ()
853 if (_backends.empty()) {
854 return boost::shared_ptr<AudioBackend>();
857 return set_backend (_backends.begin()->first, "", "");
860 boost::shared_ptr<AudioBackend>
861 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
863 BackendMap::iterator b = _backends.find (name);
865 if (b == _backends.end()) {
866 return boost::shared_ptr<AudioBackend>();
872 if (b->second->instantiate (arg1, arg2)) {
873 throw failed_constructor ();
876 _backend = b->second->factory (*this);
878 } catch (exception& e) {
879 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
880 return boost::shared_ptr<AudioBackend>();
886 /* BACKEND PROXY WRAPPERS */
889 AudioEngine::start (bool for_latency)
899 _processed_samples = 0;
900 last_monitor_check = 0;
902 int error_code = _backend->start (for_latency);
904 if (error_code != 0) {
905 _last_backend_error_string = AudioBackend::get_error_string((AudioBackend::ErrorCode) error_code);
912 _session->set_sample_rate (_backend->sample_rate());
914 if (_session->config.get_jack_time_master()) {
915 _backend->set_time_master (true);
920 /* XXX MIDI ports may not actually be available here yet .. */
922 PortManager::fill_midi_port_info ();
925 Running(); /* EMIT SIGNAL */
932 AudioEngine::stop (bool for_latency)
934 bool stop_engine = true;
940 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
946 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
949 _backend->start (false); // keep running, reload latencies
952 if (_backend->stop ()) {
964 if (_session && _running && stop_engine &&
965 (_session->state_of_the_state() & Session::Loading) == 0 &&
966 (_session->state_of_the_state() & Session::Deletion) == 0) {
967 // it's not a halt, but should be handled the same way:
968 // disable record, stop transport and I/O processign but save the data.
969 _session->engine_halted ();
972 if (stop_engine && _running) {
975 _started_for_latency = false;
976 } else if (!_started_for_latency) {
977 _stopped_for_latency = true;
980 _processed_samples = 0;
981 _measuring_latency = MeasureNone;
982 _latency_output_port = 0;
983 _latency_input_port = 0;
990 Stopped (); /* EMIT SIGNAL */
997 AudioEngine::freewheel (bool start_stop)
1003 /* _freewheeling will be set when first Freewheel signal occurs */
1005 return _backend->freewheel (start_stop);
1009 AudioEngine::get_dsp_load() const
1011 if (!_backend || !_running) {
1014 return _backend->dsp_load ();
1018 AudioEngine::is_realtime() const
1024 return _backend->is_realtime();
1028 AudioEngine::connected() const
1034 return _backend->available();
1038 AudioEngine::transport_start ()
1043 return _backend->transport_start ();
1047 AudioEngine::transport_stop ()
1052 return _backend->transport_stop ();
1056 AudioEngine::transport_state ()
1059 return TransportStopped;
1061 return _backend->transport_state ();
1065 AudioEngine::transport_locate (samplepos_t pos)
1070 return _backend->transport_locate (pos);
1074 AudioEngine::transport_sample()
1079 return _backend->transport_sample ();
1083 AudioEngine::sample_rate () const
1088 return _backend->sample_rate ();
1092 AudioEngine::samples_per_cycle () const
1097 return _backend->buffer_size ();
1101 AudioEngine::usecs_per_cycle () const
1106 return _backend->usecs_per_cycle ();
1110 AudioEngine::raw_buffer_size (DataType t)
1115 return _backend->raw_buffer_size (t);
1119 AudioEngine::sample_time ()
1124 return _backend->sample_time ();
1128 AudioEngine::sample_time_at_cycle_start ()
1133 return _backend->sample_time_at_cycle_start ();
1137 AudioEngine::samples_since_cycle_start ()
1142 return _backend->samples_since_cycle_start ();
1146 AudioEngine::get_sync_offset (pframes_t& offset) const
1151 return _backend->get_sync_offset (offset);
1155 AudioEngine::create_process_thread (boost::function<void()> func)
1160 return _backend->create_process_thread (func);
1164 AudioEngine::join_process_threads ()
1169 return _backend->join_process_threads ();
1173 AudioEngine::in_process_thread ()
1178 return _backend->in_process_thread ();
1182 AudioEngine::process_thread_count ()
1187 return _backend->process_thread_count ();
1191 AudioEngine::set_device_name (const std::string& name)
1196 return _backend->set_device_name (name);
1200 AudioEngine::set_sample_rate (float sr)
1206 return _backend->set_sample_rate (sr);
1210 AudioEngine::set_buffer_size (uint32_t bufsiz)
1215 return _backend->set_buffer_size (bufsiz);
1219 AudioEngine::set_interleaved (bool yn)
1224 return _backend->set_interleaved (yn);
1228 AudioEngine::set_input_channels (uint32_t ic)
1233 return _backend->set_input_channels (ic);
1237 AudioEngine::set_output_channels (uint32_t oc)
1242 return _backend->set_output_channels (oc);
1246 AudioEngine::set_systemic_input_latency (uint32_t il)
1251 return _backend->set_systemic_input_latency (il);
1255 AudioEngine::set_systemic_output_latency (uint32_t ol)
1260 return _backend->set_systemic_output_latency (ol);
1264 AudioEngine::thread_initialised_for_audio_processing ()
1266 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1269 /* END OF BACKEND PROXY API */
1272 AudioEngine::thread_init_callback (void* arg)
1274 /* make sure that anybody who needs to know about this thread
1278 pthread_set_name (X_("audioengine"));
1280 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1281 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1283 SessionEvent::create_per_thread_pool (thread_name, 512);
1284 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1285 AsyncMIDIPort::set_process_thread (pthread_self());
1288 delete AudioEngine::instance()->_main_thread;
1289 /* the special thread created/managed by the backend */
1290 AudioEngine::instance()->_main_thread = new ProcessThread;
1295 AudioEngine::sync_callback (TransportState state, samplepos_t position)
1298 return _session->backend_sync_callback (state, position);
1304 AudioEngine::freewheel_callback (bool onoff)
1306 _freewheeling = onoff;
1310 AudioEngine::latency_callback (bool for_playback)
1313 _session->update_latency (for_playback);
1318 AudioEngine::update_latencies ()
1321 _backend->update_latencies ();
1326 AudioEngine::halted_callback (const char* why)
1328 if (_in_destructor) {
1329 /* everything is under control */
1335 Port::PortDrop (); /* EMIT SIGNAL */
1337 if (!_started_for_latency) {
1338 Halted (why); /* EMIT SIGNAL */
1343 AudioEngine::setup_required () const
1346 if (_backend->info().already_configured())
1349 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1358 AudioEngine::prepare_for_latency_measurement ()
1364 if (running() && _started_for_latency) {
1368 if (_backend->can_change_systemic_latency_when_running()) {
1370 _backend->start (true); // zero latency reporting of running backend
1371 } else if (start (true)) {
1374 _started_for_latency = true;
1385 _started_for_latency = true;
1390 AudioEngine::start_latency_detection (bool for_midi)
1392 if (prepare_for_latency_measurement ()) {
1396 PortEngine& pe (port_engine());
1404 /* find the ports we will connect to */
1406 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1407 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1414 /* create the ports we will use to read/write data */
1416 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1420 if (pe.connect (_latency_output_port, _latency_output_name)) {
1421 pe.unregister_port (_latency_output_port);
1426 const string portname ("latency_in");
1427 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1428 pe.unregister_port (_latency_input_port);
1429 pe.unregister_port (_latency_output_port);
1433 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1434 pe.unregister_port (_latency_input_port);
1435 pe.unregister_port (_latency_output_port);
1440 _mididm = new MIDIDM (sample_rate());
1444 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1448 if (pe.connect (_latency_output_port, _latency_output_name)) {
1449 pe.unregister_port (_latency_output_port);
1454 const string portname ("latency_in");
1455 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1456 pe.unregister_port (_latency_input_port);
1457 pe.unregister_port (_latency_output_port);
1461 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1462 pe.unregister_port (_latency_input_port);
1463 pe.unregister_port (_latency_output_port);
1468 _mtdm = new MTDM (sample_rate());
1473 _latency_signal_latency = 0;
1474 lr = pe.get_latency_range (in, false);
1475 _latency_signal_latency = lr.max;
1476 lr = pe.get_latency_range (out, true);
1477 _latency_signal_latency += lr.max;
1479 /* all created and connected, lets go */
1480 _latency_flush_samples = samples_per_cycle();
1481 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1487 AudioEngine::stop_latency_detection ()
1489 _measuring_latency = MeasureNone;
1491 if (_latency_output_port) {
1492 port_engine().unregister_port (_latency_output_port);
1493 _latency_output_port = 0;
1495 if (_latency_input_port) {
1496 port_engine().unregister_port (_latency_input_port);
1497 _latency_input_port = 0;
1500 if (_running && _backend->can_change_systemic_latency_when_running()) {
1501 if (_started_for_latency) {
1502 _running = false; // force reload: reset latencies and emit Running()
1507 if (_running && !_started_for_latency) {
1508 assert (!_stopped_for_latency);
1512 if (!_backend->can_change_systemic_latency_when_running()) {
1516 if (_stopped_for_latency) {
1520 _stopped_for_latency = false;
1521 _started_for_latency = false;
1525 AudioEngine::set_latency_output_port (const string& name)
1527 _latency_output_name = name;
1531 AudioEngine::set_latency_input_port (const string& name)
1533 _latency_input_name = name;
1537 AudioEngine::add_pending_port_deletion (Port* p)
1540 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1541 if (_port_deletions_pending.write (&p, 1) != 1) {
1542 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1544 _session->auto_connect_thread_wakeup ();
1546 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));