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/session.h"
61 using namespace ARDOUR;
64 AudioEngine* AudioEngine::_instance = 0;
66 static gint audioengine_thread_cnt = 1;
69 #define SILENCE_AFTER_SECONDS 600
72 AudioEngine::AudioEngine ()
73 : session_remove_pending (false)
74 , session_removal_countdown (-1)
76 , _freewheeling (false)
77 , monitor_check_interval (INT32_MAX)
78 , last_monitor_check (0)
79 , _processed_frames (0)
84 , _measuring_latency (MeasureNone)
85 , _latency_input_port (0)
86 , _latency_output_port (0)
87 , _latency_flush_frames (0)
88 , _latency_signal_latency (0)
89 , _stopped_for_latency (false)
90 , _started_for_latency (false)
91 , _in_destructor (false)
92 , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
93 , _hw_reset_event_thread(0)
94 , _hw_reset_request_count(0)
95 , _stop_hw_reset_processing(0)
96 , _hw_devicelist_update_thread(0)
97 , _hw_devicelist_update_count(0)
98 , _stop_hw_devicelist_processing(0)
99 #ifdef SILENCE_AFTER_SECONDS
100 , _silence_countdown (0)
101 , _silence_hit_cnt (0)
104 reset_silence_countdown ();
105 start_hw_event_processing();
106 discover_backends ();
109 AudioEngine::~AudioEngine ()
111 _in_destructor = true;
112 stop_hw_event_processing();
114 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
115 i->second->deinstantiate();
121 AudioEngine::create ()
127 _instance = new AudioEngine ();
133 AudioEngine::split_cycle (pframes_t offset)
135 /* caller must hold process lock */
137 Port::increment_global_port_buffer_offset (offset);
139 /* tell all Ports that we're going to start a new (split) cycle */
141 boost::shared_ptr<Ports> p = ports.reader();
143 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
144 i->second->cycle_split ();
149 AudioEngine::sample_rate_change (pframes_t nframes)
151 /* check for monitor input change every 1/10th of second */
153 monitor_check_interval = nframes / 10;
154 last_monitor_check = 0;
157 _session->set_frame_rate (nframes);
160 SampleRateChanged (nframes); /* EMIT SIGNAL */
162 #ifdef SILENCE_AFTER_SECONDS
163 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
170 AudioEngine::buffer_size_change (pframes_t bufsiz)
173 _session->set_block_size (bufsiz);
174 last_monitor_check = 0;
177 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
182 /** Method called by our ::process_thread when there is work to be done.
183 * @param nframes Number of frames to process.
186 __attribute__((annotate("realtime")))
189 AudioEngine::process_callback (pframes_t nframes)
191 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
196 /// The number of frames that will have been processed when we've finished
197 pframes_t next_processed_frames;
199 /* handle wrap around of total frames counter */
201 if (max_framepos - _processed_frames < nframes) {
202 next_processed_frames = nframes - (max_framepos - _processed_frames);
204 next_processed_frames = _processed_frames + nframes;
208 /* return having done nothing */
212 /* really only JACK requires this
213 * (other backends clear the output buffers
214 * before the process_callback. it may even be
215 * jack/alsa only). but better safe than sorry.
217 PortManager::silence_outputs (nframes);
221 /* The coreaudio-backend calls thread_init_callback() if
222 * the hardware changes or pthread_self() changes.
224 * However there are cases when neither holds true, yet
225 * the thread-pool changes: e.g. connect a headphone to
226 * a shared mic/headphone jack.
227 * It's probably related to, or caused by clocksource changes.
229 * For reasons yet unknown Glib::Threads::Private() can
230 * use a different thread-private in the same pthread
231 * (coreaudio render callback).
233 * Coreaudio must set something which influences
234 * pthread_key_t uniqness or reset the key using
235 * pthread_getspecific().
237 if (! SessionEvent::has_per_thread_pool ()) {
238 thread_init_callback (NULL);
241 bool return_after_remove_check = false;
243 if (_measuring_latency == MeasureAudio && _mtdm) {
244 /* run a normal cycle from the perspective of the PortManager
245 so that we get silence on all registered ports.
247 we overwrite the silence on the two ports used for latency
251 PortManager::cycle_start (nframes);
252 PortManager::silence (nframes);
254 if (_latency_input_port && _latency_output_port) {
255 PortEngine& pe (port_engine());
257 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
258 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
260 _mtdm->process (nframes, in, out);
263 PortManager::cycle_end (nframes);
264 return_after_remove_check = true;
266 } else if (_measuring_latency == MeasureMIDI && _mididm) {
267 /* run a normal cycle from the perspective of the PortManager
268 so that we get silence on all registered ports.
270 we overwrite the silence on the two ports used for latency
274 PortManager::cycle_start (nframes);
275 PortManager::silence (nframes);
277 if (_latency_input_port && _latency_output_port) {
278 PortEngine& pe (port_engine());
280 _mididm->process (nframes, pe,
281 pe.get_buffer (_latency_input_port, nframes),
282 pe.get_buffer (_latency_output_port, nframes));
285 PortManager::cycle_end (nframes);
286 return_after_remove_check = true;
288 } else if (_latency_flush_frames) {
290 /* wait for the appropriate duration for the MTDM signal to
291 * drain from the ports before we revert to normal behaviour.
294 PortManager::cycle_start (nframes);
295 PortManager::silence (nframes);
296 PortManager::cycle_end (nframes);
298 if (_latency_flush_frames > nframes) {
299 _latency_flush_frames -= nframes;
301 _latency_flush_frames = 0;
304 return_after_remove_check = true;
307 if (session_remove_pending) {
309 /* perform the actual session removal */
311 if (session_removal_countdown < 0) {
313 /* fade out over 1 second */
314 session_removal_countdown = sample_rate()/2;
315 session_removal_gain = GAIN_COEFF_UNITY;
316 session_removal_gain_step = 1.0/session_removal_countdown;
318 } else if (session_removal_countdown > 0) {
320 /* we'll be fading audio out.
322 if this is the last time we do this as part
323 of session removal, do a MIDI panic now
324 to get MIDI stopped. This relies on the fact
325 that "immediate data" (aka "out of band data") from
326 MIDI tracks is *appended* after any other data,
327 so that it emerges after any outbound note ons, etc.
330 if (session_removal_countdown <= nframes) {
331 _session->midi_panic ();
337 session_removal_countdown = -1; // reset to "not in progress"
338 session_remove_pending = false;
339 session_removed.signal(); // wakes up thread that initiated session removal
343 if (return_after_remove_check) {
349 if (!_freewheeling) {
350 PortManager::cycle_start (nframes);
351 PortManager::cycle_end (nframes);
354 _processed_frames = next_processed_frames;
359 /* tell all relevant objects that we're starting a new cycle */
361 InternalSend::CycleStart (nframes);
363 /* tell all Ports that we're starting a new cycle */
365 PortManager::cycle_start (nframes);
367 /* test if we are freewheeling and there are freewheel signals connected.
368 ardour should act normally even when freewheeling unless /it/ is
369 exporting (which is what Freewheel.empty() tests for).
372 if (_freewheeling && !Freewheel.empty()) {
375 _session->process (nframes);
379 PortManager::cycle_end (nframes);
384 _processed_frames = next_processed_frames;
388 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
390 PortManager::check_monitoring ();
391 last_monitor_check = next_processed_frames;
394 #ifdef SILENCE_AFTER_SECONDS
396 bool was_silent = (_silence_countdown == 0);
398 if (_silence_countdown >= nframes) {
399 _silence_countdown -= nframes;
401 _silence_countdown = 0;
404 if (!was_silent && _silence_countdown == 0) {
406 BecameSilent (); /* EMIT SIGNAL */
409 if (_silence_countdown == 0 || _session->silent()) {
410 PortManager::silence (nframes);
414 if (_session->silent()) {
415 PortManager::silence (nframes, _session);
419 if (session_remove_pending && session_removal_countdown) {
421 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
423 if (session_removal_countdown > nframes) {
424 session_removal_countdown -= nframes;
426 session_removal_countdown = 0;
429 session_removal_gain -= (nframes * session_removal_gain_step);
432 PortManager::cycle_end (nframes);
434 _processed_frames = next_processed_frames;
442 AudioEngine::reset_silence_countdown ()
444 #ifdef SILENCE_AFTER_SECONDS
445 double sr = 48000; /* default in case there is no backend */
449 _silence_countdown = max (60 * sr, /* 60 seconds */
450 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
456 AudioEngine::launch_device_control_app()
458 if (_state_lock.trylock () ) {
459 _backend->launch_control_app ();
460 _state_lock.unlock ();
466 AudioEngine::request_backend_reset()
468 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
469 g_atomic_int_inc (&_hw_reset_request_count);
470 _hw_reset_condition.signal ();
474 AudioEngine::backend_reset_requested()
476 return g_atomic_int_get (&_hw_reset_request_count);
480 AudioEngine::do_reset_backend()
482 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
484 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
486 while (!_stop_hw_reset_processing) {
488 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
490 _reset_request_lock.unlock();
492 Glib::Threads::RecMutex::Lock pl (_state_lock);
493 g_atomic_int_dec_and_test (&_hw_reset_request_count);
495 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
496 DeviceResetStarted(); // notify about device reset to be started
498 // backup the device name
499 std::string name = _backend->device_name ();
501 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
502 if ( ( 0 == stop () ) &&
503 ( 0 == _backend->reset_device () ) &&
504 ( 0 == start () ) ) {
506 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
508 // inform about possible changes
509 BufferSizeChanged (_backend->buffer_size() );
510 DeviceResetFinished(); // notify about device reset finish
514 DeviceResetFinished(); // notify about device reset finish
515 // we've got an error
519 std::cout << "AudioEngine::RESET::Done." << std::endl;
521 _reset_request_lock.lock();
525 _hw_reset_condition.wait (_reset_request_lock);
531 AudioEngine::request_device_list_update()
533 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
534 g_atomic_int_inc (&_hw_devicelist_update_count);
535 _hw_devicelist_update_condition.signal ();
540 AudioEngine::do_devicelist_update()
542 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
544 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
546 while (!_stop_hw_devicelist_processing) {
548 if (_hw_devicelist_update_count) {
550 _devicelist_update_lock.unlock();
552 Glib::Threads::RecMutex::Lock pl (_state_lock);
554 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
555 DeviceListChanged (); /* EMIT SIGNAL */
557 _devicelist_update_lock.lock();
560 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
567 AudioEngine::start_hw_event_processing()
569 if (_hw_reset_event_thread == 0) {
570 g_atomic_int_set(&_hw_reset_request_count, 0);
571 g_atomic_int_set(&_stop_hw_reset_processing, 0);
572 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
575 if (_hw_devicelist_update_thread == 0) {
576 g_atomic_int_set(&_hw_devicelist_update_count, 0);
577 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
578 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
584 AudioEngine::stop_hw_event_processing()
586 if (_hw_reset_event_thread) {
587 g_atomic_int_set(&_stop_hw_reset_processing, 1);
588 g_atomic_int_set(&_hw_reset_request_count, 0);
589 _hw_reset_condition.signal ();
590 _hw_reset_event_thread->join ();
591 _hw_reset_event_thread = 0;
594 if (_hw_devicelist_update_thread) {
595 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
596 g_atomic_int_set(&_hw_devicelist_update_count, 0);
597 _hw_devicelist_update_condition.signal ();
598 _hw_devicelist_update_thread->join ();
599 _hw_devicelist_update_thread = 0;
606 AudioEngine::set_session (Session *s)
608 Glib::Threads::Mutex::Lock pl (_process_lock);
610 SessionHandlePtr::set_session (s);
614 pframes_t blocksize = samples_per_cycle ();
616 PortManager::cycle_start (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);
625 _session->process (blocksize);
627 PortManager::cycle_end (blocksize);
632 AudioEngine::remove_session ()
634 Glib::Threads::Mutex::Lock lm (_process_lock);
639 session_remove_pending = true;
640 /* signal the start of the fade out countdown */
641 session_removal_countdown = -1;
642 session_removed.wait(_process_lock);
646 SessionHandlePtr::set_session (0);
654 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
656 #ifdef USE_TRACKS_CODE_FEATURES
658 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
667 /* called from a signal handler for SIGPIPE */
672 AudioEngine::reset_timebase ()
675 if (_session->config.get_jack_time_master()) {
676 _backend->set_time_master (true);
678 _backend->set_time_master (false);
686 AudioEngine::destroy ()
693 AudioEngine::discover_backends ()
695 vector<std::string> backend_modules;
699 Glib::PatternSpec so_extension_pattern("*backend.so");
700 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
702 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
703 #if defined(DEBUG) || defined(_DEBUG)
704 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
706 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
709 Glib::PatternSpec dll_extension_pattern("*backend.dll");
712 find_files_matching_pattern (backend_modules, backend_search_path (),
713 so_extension_pattern);
715 find_files_matching_pattern (backend_modules, backend_search_path (),
716 dylib_extension_pattern);
718 find_files_matching_pattern (backend_modules, backend_search_path (),
719 dll_extension_pattern);
721 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
723 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
725 AudioBackendInfo* info;
727 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
729 if ((info = backend_discover (*i)) != 0) {
730 _backends.insert (make_pair (info->name, info));
734 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
736 return _backends.size();
740 AudioEngine::backend_discover (const string& path)
742 #ifdef PLATFORM_WINDOWS
743 // do not show popup dialog (e.g. missing libjack.dll)
744 // win7+ should use SetThreadErrorMode()
745 SetErrorMode(SEM_FAILCRITICALERRORS);
747 Glib::Module module (path);
748 #ifdef PLATFORM_WINDOWS
749 SetErrorMode(0); // reset to system default
751 AudioBackendInfo* info;
752 AudioBackendInfo* (*dfunc)(void);
756 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
757 Glib::Module::get_last_error()) << endmsg;
761 if (!module.get_symbol ("descriptor", func)) {
762 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
763 error << Glib::Module::get_last_error() << endmsg;
767 dfunc = (AudioBackendInfo* (*)(void))func;
769 if (!info->available()) {
773 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);
785 vector<const AudioBackendInfo*>
786 AudioEngine::available_backends() const
788 vector<const AudioBackendInfo*> r;
790 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
792 if (i->first == "None (Dummy)" && !running_from_source_tree ()) {
796 r.push_back (i->second);
803 AudioEngine::current_backend_name() const
806 return _backend->name();
812 AudioEngine::drop_backend ()
816 // Stopped is needed for Graph to explicitly terminate threads
817 Stopped (); /* EMIT SIGNAL */
818 _backend->drop_device ();
824 boost::shared_ptr<AudioBackend>
825 AudioEngine::set_default_backend ()
827 if (_backends.empty()) {
828 return boost::shared_ptr<AudioBackend>();
831 return set_backend (_backends.begin()->first, "", "");
834 boost::shared_ptr<AudioBackend>
835 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
837 BackendMap::iterator b = _backends.find (name);
839 if (b == _backends.end()) {
840 return boost::shared_ptr<AudioBackend>();
846 if (b->second->instantiate (arg1, arg2)) {
847 throw failed_constructor ();
850 _backend = b->second->factory (*this);
852 } catch (exception& e) {
853 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
854 return boost::shared_ptr<AudioBackend>();
860 /* BACKEND PROXY WRAPPERS */
863 AudioEngine::start (bool for_latency)
873 _processed_frames = 0;
874 last_monitor_check = 0;
876 int error_code = _backend->start (for_latency);
878 if (error_code != 0) {
879 _last_backend_error_string =
880 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);
896 Running(); /* EMIT SIGNAL */
903 AudioEngine::stop (bool for_latency)
905 bool stop_engine = true;
911 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
917 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
920 if (_backend->stop ()) {
932 if (_session && _running && stop_engine &&
933 (_session->state_of_the_state() & Session::Loading) == 0 &&
934 (_session->state_of_the_state() & Session::Deletion) == 0) {
935 // it's not a halt, but should be handled the same way:
936 // disable record, stop transport and I/O processign but save the data.
937 _session->engine_halted ();
943 _processed_frames = 0;
944 _measuring_latency = MeasureNone;
945 _latency_output_port = 0;
946 _latency_input_port = 0;
947 _started_for_latency = false;
953 if (!for_latency && stop_engine) {
954 Stopped (); /* EMIT SIGNAL */
961 AudioEngine::freewheel (bool start_stop)
967 /* _freewheeling will be set when first Freewheel signal occurs */
969 return _backend->freewheel (start_stop);
973 AudioEngine::get_dsp_load() const
975 if (!_backend || !_running) {
978 return _backend->dsp_load ();
982 AudioEngine::is_realtime() const
988 return _backend->is_realtime();
992 AudioEngine::connected() const
998 return _backend->available();
1002 AudioEngine::transport_start ()
1007 return _backend->transport_start ();
1011 AudioEngine::transport_stop ()
1016 return _backend->transport_stop ();
1020 AudioEngine::transport_state ()
1023 return TransportStopped;
1025 return _backend->transport_state ();
1029 AudioEngine::transport_locate (framepos_t pos)
1034 return _backend->transport_locate (pos);
1038 AudioEngine::transport_frame()
1043 return _backend->transport_frame ();
1047 AudioEngine::sample_rate () const
1052 return _backend->sample_rate ();
1056 AudioEngine::samples_per_cycle () const
1061 return _backend->buffer_size ();
1065 AudioEngine::usecs_per_cycle () const
1070 return _backend->usecs_per_cycle ();
1074 AudioEngine::raw_buffer_size (DataType t)
1079 return _backend->raw_buffer_size (t);
1083 AudioEngine::sample_time ()
1088 return _backend->sample_time ();
1092 AudioEngine::sample_time_at_cycle_start ()
1097 return _backend->sample_time_at_cycle_start ();
1101 AudioEngine::samples_since_cycle_start ()
1106 return _backend->samples_since_cycle_start ();
1110 AudioEngine::get_sync_offset (pframes_t& offset) const
1115 return _backend->get_sync_offset (offset);
1119 AudioEngine::create_process_thread (boost::function<void()> func)
1124 return _backend->create_process_thread (func);
1128 AudioEngine::join_process_threads ()
1133 return _backend->join_process_threads ();
1137 AudioEngine::in_process_thread ()
1142 return _backend->in_process_thread ();
1146 AudioEngine::process_thread_count ()
1151 return _backend->process_thread_count ();
1155 AudioEngine::set_device_name (const std::string& name)
1160 return _backend->set_device_name (name);
1164 AudioEngine::set_sample_rate (float sr)
1170 return _backend->set_sample_rate (sr);
1174 AudioEngine::set_buffer_size (uint32_t bufsiz)
1179 return _backend->set_buffer_size (bufsiz);
1183 AudioEngine::set_interleaved (bool yn)
1188 return _backend->set_interleaved (yn);
1192 AudioEngine::set_input_channels (uint32_t ic)
1197 return _backend->set_input_channels (ic);
1201 AudioEngine::set_output_channels (uint32_t oc)
1206 return _backend->set_output_channels (oc);
1210 AudioEngine::set_systemic_input_latency (uint32_t il)
1215 return _backend->set_systemic_input_latency (il);
1219 AudioEngine::set_systemic_output_latency (uint32_t ol)
1224 return _backend->set_systemic_output_latency (ol);
1228 AudioEngine::thread_initialised_for_audio_processing ()
1230 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1233 /* END OF BACKEND PROXY API */
1236 AudioEngine::thread_init_callback (void* arg)
1238 /* make sure that anybody who needs to know about this thread
1242 pthread_set_name (X_("audioengine"));
1244 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1245 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1247 SessionEvent::create_per_thread_pool (thread_name, 512);
1248 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1249 AsyncMIDIPort::set_process_thread (pthread_self());
1252 delete AudioEngine::instance()->_main_thread;
1253 /* the special thread created/managed by the backend */
1254 AudioEngine::instance()->_main_thread = new ProcessThread;
1259 AudioEngine::sync_callback (TransportState state, framepos_t position)
1262 return _session->backend_sync_callback (state, position);
1268 AudioEngine::freewheel_callback (bool onoff)
1270 _freewheeling = onoff;
1274 AudioEngine::latency_callback (bool for_playback)
1277 _session->update_latency (for_playback);
1282 AudioEngine::update_latencies ()
1285 _backend->update_latencies ();
1290 AudioEngine::halted_callback (const char* why)
1292 if (_in_destructor) {
1293 /* everything is under control */
1299 Port::PortDrop (); /* EMIT SIGNAL */
1301 if (!_started_for_latency) {
1302 Halted (why); /* EMIT SIGNAL */
1307 AudioEngine::setup_required () const
1310 if (_backend->info().already_configured())
1313 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1322 AudioEngine::prepare_for_latency_measurement ()
1328 if (_backend->can_change_systemic_latency_when_running()) {
1332 _backend->set_systemic_input_latency (0);
1333 _backend->set_systemic_output_latency (0);
1338 _stopped_for_latency = true;
1345 _started_for_latency = true;
1351 AudioEngine::start_latency_detection (bool for_midi)
1353 if (prepare_for_latency_measurement ()) {
1357 PortEngine& pe (port_engine());
1365 /* find the ports we will connect to */
1367 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1368 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1375 /* create the ports we will use to read/write data */
1377 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1381 if (pe.connect (_latency_output_port, _latency_output_name)) {
1382 pe.unregister_port (_latency_output_port);
1387 const string portname ("latency_in");
1388 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1389 pe.unregister_port (_latency_input_port);
1390 pe.unregister_port (_latency_output_port);
1394 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1395 pe.unregister_port (_latency_input_port);
1396 pe.unregister_port (_latency_output_port);
1401 _mididm = new MIDIDM (sample_rate());
1405 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1409 if (pe.connect (_latency_output_port, _latency_output_name)) {
1410 pe.unregister_port (_latency_output_port);
1415 const string portname ("latency_in");
1416 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1417 pe.unregister_port (_latency_input_port);
1418 pe.unregister_port (_latency_output_port);
1422 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1423 pe.unregister_port (_latency_input_port);
1424 pe.unregister_port (_latency_output_port);
1429 _mtdm = new MTDM (sample_rate());
1434 _latency_signal_latency = 0;
1435 lr = pe.get_latency_range (in, false);
1436 _latency_signal_latency = lr.max;
1437 lr = pe.get_latency_range (out, true);
1438 _latency_signal_latency += lr.max;
1440 /* all created and connected, lets go */
1441 _latency_flush_frames = samples_per_cycle();
1442 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1448 AudioEngine::stop_latency_detection ()
1450 _measuring_latency = MeasureNone;
1452 if (_latency_output_port) {
1453 port_engine().unregister_port (_latency_output_port);
1454 _latency_output_port = 0;
1456 if (_latency_input_port) {
1457 port_engine().unregister_port (_latency_input_port);
1458 _latency_input_port = 0;
1461 if (!_backend->can_change_systemic_latency_when_running()) {
1465 if (_stopped_for_latency) {
1469 _stopped_for_latency = false;
1470 _started_for_latency = false;
1474 AudioEngine::set_latency_output_port (const string& name)
1476 _latency_output_name = name;
1480 AudioEngine::set_latency_input_port (const string& name)
1482 _latency_input_name = name;
1486 AudioEngine::add_pending_port_deletion (Port* p)
1489 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1490 if (_port_deletions_pending.write (&p, 1) != 1) {
1491 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1493 _session->auto_connect_thread_wakeup ();
1495 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));