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_frames (0)
85 , _measuring_latency (MeasureNone)
86 , _latency_input_port (0)
87 , _latency_output_port (0)
88 , _latency_flush_frames (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_frame_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 frames 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);
197 /// The number of frames that will have been processed when we've finished
198 pframes_t next_processed_frames;
200 /* handle wrap around of total frames counter */
202 if (max_framepos - _processed_frames < nframes) {
203 next_processed_frames = nframes - (max_framepos - _processed_frames);
205 next_processed_frames = _processed_frames + nframes;
209 /* return having done nothing */
213 /* really only JACK requires this
214 * (other backends clear the output buffers
215 * before the process_callback. it may even be
216 * jack/alsa only). but better safe than sorry.
218 PortManager::silence_outputs (nframes);
222 /* The coreaudio-backend calls thread_init_callback() if
223 * the hardware changes or pthread_self() changes.
225 * However there are cases when neither holds true, yet
226 * the thread-pool changes: e.g. connect a headphone to
227 * a shared mic/headphone jack.
228 * It's probably related to, or caused by clocksource changes.
230 * For reasons yet unknown Glib::Threads::Private() can
231 * use a different thread-private in the same pthread
232 * (coreaudio render callback).
234 * Coreaudio must set something which influences
235 * pthread_key_t uniqness or reset the key using
236 * pthread_getspecific().
238 if (! SessionEvent::has_per_thread_pool ()) {
239 thread_init_callback (NULL);
242 bool return_after_remove_check = false;
244 if (_measuring_latency == MeasureAudio && _mtdm) {
245 /* run a normal cycle from the perspective of the PortManager
246 so that we get silence on all registered ports.
248 we overwrite the silence on the two ports used for latency
252 PortManager::cycle_start (nframes);
253 PortManager::silence (nframes);
255 if (_latency_input_port && _latency_output_port) {
256 PortEngine& pe (port_engine());
258 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
259 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
261 _mtdm->process (nframes, in, out);
264 PortManager::cycle_end (nframes);
265 return_after_remove_check = true;
267 } else if (_measuring_latency == MeasureMIDI && _mididm) {
268 /* run a normal cycle from the perspective of the PortManager
269 so that we get silence on all registered ports.
271 we overwrite the silence on the two ports used for latency
275 PortManager::cycle_start (nframes);
276 PortManager::silence (nframes);
278 if (_latency_input_port && _latency_output_port) {
279 PortEngine& pe (port_engine());
281 _mididm->process (nframes, pe,
282 pe.get_buffer (_latency_input_port, nframes),
283 pe.get_buffer (_latency_output_port, nframes));
286 PortManager::cycle_end (nframes);
287 return_after_remove_check = true;
289 } else if (_latency_flush_frames) {
291 /* wait for the appropriate duration for the MTDM signal to
292 * drain from the ports before we revert to normal behaviour.
295 PortManager::cycle_start (nframes);
296 PortManager::silence (nframes);
297 PortManager::cycle_end (nframes);
299 if (_latency_flush_frames > nframes) {
300 _latency_flush_frames -= nframes;
302 _latency_flush_frames = 0;
305 return_after_remove_check = true;
308 if (session_remove_pending) {
310 /* perform the actual session removal */
312 if (session_removal_countdown < 0) {
314 /* fade out over 1 second */
315 session_removal_countdown = sample_rate()/2;
316 session_removal_gain = GAIN_COEFF_UNITY;
317 session_removal_gain_step = 1.0/session_removal_countdown;
319 } else if (session_removal_countdown > 0) {
321 /* we'll be fading audio out.
323 if this is the last time we do this as part
324 of session removal, do a MIDI panic now
325 to get MIDI stopped. This relies on the fact
326 that "immediate data" (aka "out of band data") from
327 MIDI tracks is *appended* after any other data,
328 so that it emerges after any outbound note ons, etc.
331 if (session_removal_countdown <= nframes) {
332 _session->midi_panic ();
338 session_removal_countdown = -1; // reset to "not in progress"
339 session_remove_pending = false;
340 session_removed.signal(); // wakes up thread that initiated session removal
344 if (return_after_remove_check) {
350 if (!_freewheeling) {
351 PortManager::cycle_start (nframes);
352 PortManager::cycle_end (nframes);
355 _processed_frames = next_processed_frames;
360 /* tell all relevant objects that we're starting a new cycle */
362 InternalSend::CycleStart (nframes);
364 /* tell all Ports that we're starting a new cycle */
366 PortManager::cycle_start (nframes);
368 /* test if we are freewheeling and there are freewheel signals connected.
369 * ardour should act normally even when freewheeling unless /it/ is
370 * exporting (which is what Freewheel.empty() tests for).
373 if (_freewheeling && !Freewheel.empty()) {
376 _session->process (nframes);
380 PortManager::cycle_end (nframes);
385 _processed_frames = next_processed_frames;
389 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
391 PortManager::check_monitoring ();
392 last_monitor_check = next_processed_frames;
395 #ifdef SILENCE_AFTER_SECONDS
397 bool was_silent = (_silence_countdown == 0);
399 if (_silence_countdown >= nframes) {
400 _silence_countdown -= nframes;
402 _silence_countdown = 0;
405 if (!was_silent && _silence_countdown == 0) {
407 BecameSilent (); /* EMIT SIGNAL */
410 if (_silence_countdown == 0 || _session->silent()) {
411 PortManager::silence (nframes);
415 if (_session->silent()) {
416 PortManager::silence (nframes, _session);
420 if (session_remove_pending && session_removal_countdown) {
422 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
424 if (session_removal_countdown > nframes) {
425 session_removal_countdown -= nframes;
427 session_removal_countdown = 0;
430 session_removal_gain -= (nframes * session_removal_gain_step);
433 PortManager::cycle_end (nframes);
435 _processed_frames = next_processed_frames;
443 AudioEngine::reset_silence_countdown ()
445 #ifdef SILENCE_AFTER_SECONDS
446 double sr = 48000; /* default in case there is no backend */
450 _silence_countdown = max (60 * sr, /* 60 seconds */
451 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
457 AudioEngine::launch_device_control_app()
459 if (_state_lock.trylock () ) {
460 _backend->launch_control_app ();
461 _state_lock.unlock ();
467 AudioEngine::request_backend_reset()
469 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
470 g_atomic_int_inc (&_hw_reset_request_count);
471 _hw_reset_condition.signal ();
475 AudioEngine::backend_reset_requested()
477 return g_atomic_int_get (&_hw_reset_request_count);
481 AudioEngine::do_reset_backend()
483 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
485 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
487 while (!_stop_hw_reset_processing) {
489 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
491 _reset_request_lock.unlock();
493 Glib::Threads::RecMutex::Lock pl (_state_lock);
494 g_atomic_int_dec_and_test (&_hw_reset_request_count);
496 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
497 DeviceResetStarted(); // notify about device reset to be started
499 // backup the device name
500 std::string name = _backend->device_name ();
502 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
503 if ( ( 0 == stop () ) &&
504 ( 0 == _backend->reset_device () ) &&
505 ( 0 == start () ) ) {
507 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
509 // inform about possible changes
510 BufferSizeChanged (_backend->buffer_size() );
511 DeviceResetFinished(); // notify about device reset finish
515 DeviceResetFinished(); // notify about device reset finish
516 // we've got an error
520 std::cout << "AudioEngine::RESET::Done." << std::endl;
522 _reset_request_lock.lock();
526 _hw_reset_condition.wait (_reset_request_lock);
533 AudioEngine::request_device_list_update()
535 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
536 g_atomic_int_inc (&_hw_devicelist_update_count);
537 _hw_devicelist_update_condition.signal ();
541 AudioEngine::do_devicelist_update()
543 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
545 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
547 while (!_stop_hw_devicelist_processing) {
549 if (_hw_devicelist_update_count) {
551 _devicelist_update_lock.unlock();
553 Glib::Threads::RecMutex::Lock pl (_state_lock);
555 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
556 DeviceListChanged (); /* EMIT SIGNAL */
558 _devicelist_update_lock.lock();
561 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
568 AudioEngine::start_hw_event_processing()
570 if (_hw_reset_event_thread == 0) {
571 g_atomic_int_set(&_hw_reset_request_count, 0);
572 g_atomic_int_set(&_stop_hw_reset_processing, 0);
573 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
576 if (_hw_devicelist_update_thread == 0) {
577 g_atomic_int_set(&_hw_devicelist_update_count, 0);
578 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
579 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
585 AudioEngine::stop_hw_event_processing()
587 if (_hw_reset_event_thread) {
588 g_atomic_int_set(&_stop_hw_reset_processing, 1);
589 g_atomic_int_set(&_hw_reset_request_count, 0);
590 _hw_reset_condition.signal ();
591 _hw_reset_event_thread->join ();
592 _hw_reset_event_thread = 0;
595 if (_hw_devicelist_update_thread) {
596 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
597 g_atomic_int_set(&_hw_devicelist_update_count, 0);
598 _hw_devicelist_update_condition.signal ();
599 _hw_devicelist_update_thread->join ();
600 _hw_devicelist_update_thread = 0;
605 AudioEngine::set_session (Session *s)
607 Glib::Threads::Mutex::Lock pl (_process_lock);
609 SessionHandlePtr::set_session (s);
613 pframes_t blocksize = samples_per_cycle ();
615 PortManager::cycle_start (blocksize);
617 _session->process (blocksize);
618 _session->process (blocksize);
619 _session->process (blocksize);
620 _session->process (blocksize);
621 _session->process (blocksize);
622 _session->process (blocksize);
623 _session->process (blocksize);
624 _session->process (blocksize);
626 PortManager::cycle_end (blocksize);
631 AudioEngine::remove_session ()
633 Glib::Threads::Mutex::Lock lm (_process_lock);
638 session_remove_pending = true;
639 /* signal the start of the fade out countdown */
640 session_removal_countdown = -1;
641 session_removed.wait(_process_lock);
645 SessionHandlePtr::set_session (0);
653 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
655 #ifdef USE_TRACKS_CODE_FEATURES
657 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
666 /* called from a signal handler for SIGPIPE */
671 AudioEngine::reset_timebase ()
674 if (_session->config.get_jack_time_master()) {
675 _backend->set_time_master (true);
677 _backend->set_time_master (false);
685 AudioEngine::destroy ()
692 AudioEngine::discover_backends ()
694 vector<std::string> backend_modules;
698 Glib::PatternSpec so_extension_pattern("*backend.so");
699 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
701 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
702 #if defined(DEBUG) || defined(_DEBUG)
703 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
705 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
708 Glib::PatternSpec dll_extension_pattern("*backend.dll");
711 find_files_matching_pattern (backend_modules, backend_search_path (),
712 so_extension_pattern);
714 find_files_matching_pattern (backend_modules, backend_search_path (),
715 dylib_extension_pattern);
717 find_files_matching_pattern (backend_modules, backend_search_path (),
718 dll_extension_pattern);
720 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
722 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
724 AudioBackendInfo* info;
726 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
728 if ((info = backend_discover (*i)) != 0) {
729 _backends.insert (make_pair (info->name, info));
733 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
735 return _backends.size();
739 AudioEngine::backend_discover (const string& path)
741 #ifdef PLATFORM_WINDOWS
742 // do not show popup dialog (e.g. missing libjack.dll)
743 // win7+ should use SetThreadErrorMode()
744 SetErrorMode(SEM_FAILCRITICALERRORS);
746 Glib::Module module (path);
747 #ifdef PLATFORM_WINDOWS
748 SetErrorMode(0); // reset to system default
750 AudioBackendInfo* info;
751 AudioBackendInfo* (*dfunc)(void);
755 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
756 Glib::Module::get_last_error()) << endmsg;
760 if (!module.get_symbol ("descriptor", func)) {
761 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
762 error << Glib::Module::get_last_error() << endmsg;
766 dfunc = (AudioBackendInfo* (*)(void))func;
768 if (!info->available()) {
772 module.make_resident ();
778 static bool running_from_source_tree ()
780 // dup ARDOUR_UI_UTILS::running_from_source_tree ()
781 gchar const *x = g_getenv ("ARDOUR_THEMES_PATH");
782 return x && (string (x).find ("gtk2_ardour") != string::npos);
786 vector<const AudioBackendInfo*>
787 AudioEngine::available_backends() const
789 vector<const AudioBackendInfo*> r;
791 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
793 if (i->first == "None (Dummy)" && !running_from_source_tree () && Config->get_hide_dummy_backend ()) {
797 r.push_back (i->second);
804 AudioEngine::current_backend_name() const
807 return _backend->name();
813 AudioEngine::drop_backend ()
817 // Stopped is needed for Graph to explicitly terminate threads
818 Stopped (); /* EMIT SIGNAL */
819 _backend->drop_device ();
825 boost::shared_ptr<AudioBackend>
826 AudioEngine::set_default_backend ()
828 if (_backends.empty()) {
829 return boost::shared_ptr<AudioBackend>();
832 return set_backend (_backends.begin()->first, "", "");
835 boost::shared_ptr<AudioBackend>
836 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
838 BackendMap::iterator b = _backends.find (name);
840 if (b == _backends.end()) {
841 return boost::shared_ptr<AudioBackend>();
847 if (b->second->instantiate (arg1, arg2)) {
848 throw failed_constructor ();
851 _backend = b->second->factory (*this);
853 } catch (exception& e) {
854 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
855 return boost::shared_ptr<AudioBackend>();
861 /* BACKEND PROXY WRAPPERS */
864 AudioEngine::start (bool for_latency)
874 _processed_frames = 0;
875 last_monitor_check = 0;
877 int error_code = _backend->start (for_latency);
879 if (error_code != 0) {
880 _last_backend_error_string = AudioBackend::get_error_string((AudioBackend::ErrorCode) error_code);
887 _session->set_frame_rate (_backend->sample_rate());
889 if (_session->config.get_jack_time_master()) {
890 _backend->set_time_master (true);
895 /* XXX MIDI ports may not actually be available here yet .. */
897 PortManager::fill_midi_port_info ();
900 Running(); /* EMIT SIGNAL */
907 AudioEngine::stop (bool for_latency)
909 bool stop_engine = true;
915 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
921 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
924 _backend->start (false); // keep running, reload latencies
927 if (_backend->stop ()) {
939 if (_session && _running && stop_engine &&
940 (_session->state_of_the_state() & Session::Loading) == 0 &&
941 (_session->state_of_the_state() & Session::Deletion) == 0) {
942 // it's not a halt, but should be handled the same way:
943 // disable record, stop transport and I/O processign but save the data.
944 _session->engine_halted ();
947 if (stop_engine && _running) {
950 _started_for_latency = false;
951 } else if (!_started_for_latency) {
952 _stopped_for_latency = true;
955 _processed_frames = 0;
956 _measuring_latency = MeasureNone;
957 _latency_output_port = 0;
958 _latency_input_port = 0;
965 Stopped (); /* EMIT SIGNAL */
972 AudioEngine::freewheel (bool start_stop)
978 /* _freewheeling will be set when first Freewheel signal occurs */
980 return _backend->freewheel (start_stop);
984 AudioEngine::get_dsp_load() const
986 if (!_backend || !_running) {
989 return _backend->dsp_load ();
993 AudioEngine::is_realtime() const
999 return _backend->is_realtime();
1003 AudioEngine::connected() const
1009 return _backend->available();
1013 AudioEngine::transport_start ()
1018 return _backend->transport_start ();
1022 AudioEngine::transport_stop ()
1027 return _backend->transport_stop ();
1031 AudioEngine::transport_state ()
1034 return TransportStopped;
1036 return _backend->transport_state ();
1040 AudioEngine::transport_locate (framepos_t pos)
1045 return _backend->transport_locate (pos);
1049 AudioEngine::transport_frame()
1054 return _backend->transport_frame ();
1058 AudioEngine::sample_rate () const
1063 return _backend->sample_rate ();
1067 AudioEngine::samples_per_cycle () const
1072 return _backend->buffer_size ();
1076 AudioEngine::usecs_per_cycle () const
1081 return _backend->usecs_per_cycle ();
1085 AudioEngine::raw_buffer_size (DataType t)
1090 return _backend->raw_buffer_size (t);
1094 AudioEngine::sample_time ()
1099 return _backend->sample_time ();
1103 AudioEngine::sample_time_at_cycle_start ()
1108 return _backend->sample_time_at_cycle_start ();
1112 AudioEngine::samples_since_cycle_start ()
1117 return _backend->samples_since_cycle_start ();
1121 AudioEngine::get_sync_offset (pframes_t& offset) const
1126 return _backend->get_sync_offset (offset);
1130 AudioEngine::create_process_thread (boost::function<void()> func)
1135 return _backend->create_process_thread (func);
1139 AudioEngine::join_process_threads ()
1144 return _backend->join_process_threads ();
1148 AudioEngine::in_process_thread ()
1153 return _backend->in_process_thread ();
1157 AudioEngine::process_thread_count ()
1162 return _backend->process_thread_count ();
1166 AudioEngine::set_device_name (const std::string& name)
1171 return _backend->set_device_name (name);
1175 AudioEngine::set_sample_rate (float sr)
1181 return _backend->set_sample_rate (sr);
1185 AudioEngine::set_buffer_size (uint32_t bufsiz)
1190 return _backend->set_buffer_size (bufsiz);
1194 AudioEngine::set_interleaved (bool yn)
1199 return _backend->set_interleaved (yn);
1203 AudioEngine::set_input_channels (uint32_t ic)
1208 return _backend->set_input_channels (ic);
1212 AudioEngine::set_output_channels (uint32_t oc)
1217 return _backend->set_output_channels (oc);
1221 AudioEngine::set_systemic_input_latency (uint32_t il)
1226 return _backend->set_systemic_input_latency (il);
1230 AudioEngine::set_systemic_output_latency (uint32_t ol)
1235 return _backend->set_systemic_output_latency (ol);
1239 AudioEngine::thread_initialised_for_audio_processing ()
1241 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1244 /* END OF BACKEND PROXY API */
1247 AudioEngine::thread_init_callback (void* arg)
1249 /* make sure that anybody who needs to know about this thread
1253 pthread_set_name (X_("audioengine"));
1255 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1256 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1258 SessionEvent::create_per_thread_pool (thread_name, 512);
1259 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1260 AsyncMIDIPort::set_process_thread (pthread_self());
1263 delete AudioEngine::instance()->_main_thread;
1264 /* the special thread created/managed by the backend */
1265 AudioEngine::instance()->_main_thread = new ProcessThread;
1270 AudioEngine::sync_callback (TransportState state, framepos_t position)
1273 return _session->backend_sync_callback (state, position);
1279 AudioEngine::freewheel_callback (bool onoff)
1281 _freewheeling = onoff;
1285 AudioEngine::latency_callback (bool for_playback)
1288 _session->update_latency (for_playback);
1293 AudioEngine::update_latencies ()
1296 _backend->update_latencies ();
1301 AudioEngine::halted_callback (const char* why)
1303 if (_in_destructor) {
1304 /* everything is under control */
1310 Port::PortDrop (); /* EMIT SIGNAL */
1312 if (!_started_for_latency) {
1313 Halted (why); /* EMIT SIGNAL */
1318 AudioEngine::setup_required () const
1321 if (_backend->info().already_configured())
1324 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1333 AudioEngine::prepare_for_latency_measurement ()
1339 if (running() && _started_for_latency) {
1343 if (_backend->can_change_systemic_latency_when_running()) {
1345 _backend->start (true); // zero latency reporting of running backend
1346 } else if (start (true)) {
1349 _started_for_latency = true;
1360 _started_for_latency = true;
1365 AudioEngine::start_latency_detection (bool for_midi)
1367 if (prepare_for_latency_measurement ()) {
1371 PortEngine& pe (port_engine());
1379 /* find the ports we will connect to */
1381 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1382 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1389 /* create the ports we will use to read/write data */
1391 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1395 if (pe.connect (_latency_output_port, _latency_output_name)) {
1396 pe.unregister_port (_latency_output_port);
1401 const string portname ("latency_in");
1402 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1403 pe.unregister_port (_latency_input_port);
1404 pe.unregister_port (_latency_output_port);
1408 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1409 pe.unregister_port (_latency_input_port);
1410 pe.unregister_port (_latency_output_port);
1415 _mididm = new MIDIDM (sample_rate());
1419 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1423 if (pe.connect (_latency_output_port, _latency_output_name)) {
1424 pe.unregister_port (_latency_output_port);
1429 const string portname ("latency_in");
1430 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1431 pe.unregister_port (_latency_input_port);
1432 pe.unregister_port (_latency_output_port);
1436 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1437 pe.unregister_port (_latency_input_port);
1438 pe.unregister_port (_latency_output_port);
1443 _mtdm = new MTDM (sample_rate());
1448 _latency_signal_latency = 0;
1449 lr = pe.get_latency_range (in, false);
1450 _latency_signal_latency = lr.max;
1451 lr = pe.get_latency_range (out, true);
1452 _latency_signal_latency += lr.max;
1454 /* all created and connected, lets go */
1455 _latency_flush_frames = samples_per_cycle();
1456 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1462 AudioEngine::stop_latency_detection ()
1464 _measuring_latency = MeasureNone;
1466 if (_latency_output_port) {
1467 port_engine().unregister_port (_latency_output_port);
1468 _latency_output_port = 0;
1470 if (_latency_input_port) {
1471 port_engine().unregister_port (_latency_input_port);
1472 _latency_input_port = 0;
1475 if (_running && _backend->can_change_systemic_latency_when_running()) {
1476 if (_started_for_latency) {
1477 _running = false; // force reload: reset latencies and emit Running()
1482 if (_running && !_started_for_latency) {
1483 assert (!_stopped_for_latency);
1487 if (!_backend->can_change_systemic_latency_when_running()) {
1491 if (_stopped_for_latency) {
1495 _stopped_for_latency = false;
1496 _started_for_latency = false;
1500 AudioEngine::set_latency_output_port (const string& name)
1502 _latency_output_name = name;
1506 AudioEngine::set_latency_input_port (const string& name)
1508 _latency_input_name = name;
1512 AudioEngine::add_pending_port_deletion (Port* p)
1515 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1516 if (_port_deletions_pending.write (&p, 1) != 1) {
1517 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1519 _session->auto_connect_thread_wakeup ();
1521 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));