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"
58 #include "ardour/transport_master_manager.h"
63 using namespace ARDOUR;
66 AudioEngine* AudioEngine::_instance = 0;
68 static gint audioengine_thread_cnt = 1;
71 #define SILENCE_AFTER_SECONDS 600
74 AudioEngine::AudioEngine ()
75 : session_remove_pending (false)
76 , session_removal_countdown (-1)
78 , _freewheeling (false)
79 , monitor_check_interval (INT32_MAX)
80 , last_monitor_check (0)
81 , _processed_samples (-1)
86 , _measuring_latency (MeasureNone)
87 , _latency_input_port (0)
88 , _latency_output_port (0)
89 , _latency_flush_samples (0)
90 , _latency_signal_latency (0)
91 , _stopped_for_latency (false)
92 , _started_for_latency (false)
93 , _in_destructor (false)
94 , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
95 , _hw_reset_event_thread(0)
96 , _hw_reset_request_count(0)
97 , _stop_hw_reset_processing(0)
98 , _hw_devicelist_update_thread(0)
99 , _hw_devicelist_update_count(0)
100 , _stop_hw_devicelist_processing(0)
101 #ifdef SILENCE_AFTER_SECONDS
102 , _silence_countdown (0)
103 , _silence_hit_cnt (0)
106 reset_silence_countdown ();
107 start_hw_event_processing();
108 discover_backends ();
111 AudioEngine::~AudioEngine ()
113 _in_destructor = true;
114 stop_hw_event_processing();
116 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
117 i->second->deinstantiate();
123 AudioEngine::create ()
129 _instance = new AudioEngine ();
135 AudioEngine::split_cycle (pframes_t offset)
137 /* caller must hold process lock */
139 Port::increment_global_port_buffer_offset (offset);
141 /* tell all Ports that we're going to start a new (split) cycle */
143 boost::shared_ptr<Ports> p = ports.reader();
145 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
146 i->second->cycle_split ();
151 AudioEngine::sample_rate_change (pframes_t nframes)
153 /* check for monitor input change every 1/10th of second */
155 monitor_check_interval = nframes / 10;
156 last_monitor_check = 0;
159 _session->set_sample_rate (nframes);
162 SampleRateChanged (nframes); /* EMIT SIGNAL */
164 #ifdef SILENCE_AFTER_SECONDS
165 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
172 AudioEngine::buffer_size_change (pframes_t bufsiz)
175 _session->set_block_size (bufsiz);
176 last_monitor_check = 0;
179 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
184 /** Method called by our ::process_thread when there is work to be done.
185 * @param nframes Number of samples to process.
188 __attribute__((annotate("realtime")))
191 AudioEngine::process_callback (pframes_t nframes)
193 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
194 Port::set_speed_ratio (1.0);
199 /// The number of samples that will have been processed when we've finished
200 pframes_t next_processed_samples;
202 if (_processed_samples < 0) {
203 _processed_samples = sample_time();
204 cerr << "IIIIINIT PS to " << _processed_samples << endl;
207 /* handle wrap around of total samples counter */
209 if (max_samplepos - _processed_samples < nframes) {
210 next_processed_samples = nframes - (max_samplepos - _processed_samples);
212 next_processed_samples = _processed_samples + nframes;
216 /* return having done nothing */
220 /* really only JACK requires this
221 * (other backends clear the output buffers
222 * before the process_callback. it may even be
223 * jack/alsa only). but better safe than sorry.
225 PortManager::silence_outputs (nframes);
229 /* The coreaudio-backend calls thread_init_callback() if
230 * the hardware changes or pthread_self() changes.
232 * However there are cases when neither holds true, yet
233 * the thread-pool changes: e.g. connect a headphone to
234 * a shared mic/headphone jack.
235 * It's probably related to, or caused by clocksource changes.
237 * For reasons yet unknown Glib::Threads::Private() can
238 * use a different thread-private in the same pthread
239 * (coreaudio render callback).
241 * Coreaudio must set something which influences
242 * pthread_key_t uniqness or reset the key using
243 * pthread_getspecific().
245 if (! SessionEvent::has_per_thread_pool ()) {
246 thread_init_callback (NULL);
249 bool return_after_remove_check = false;
251 if (_measuring_latency == MeasureAudio && _mtdm) {
252 /* run a normal cycle from the perspective of the PortManager
253 so that we get silence on all registered ports.
255 we overwrite the silence on the two ports used for latency
259 PortManager::cycle_start (nframes);
260 PortManager::silence (nframes);
262 if (_latency_input_port && _latency_output_port) {
263 PortEngine& pe (port_engine());
265 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
266 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
268 _mtdm->process (nframes, in, out);
271 PortManager::cycle_end (nframes);
272 return_after_remove_check = true;
274 } else if (_measuring_latency == MeasureMIDI && _mididm) {
275 /* run a normal cycle from the perspective of the PortManager
276 so that we get silence on all registered ports.
278 we overwrite the silence on the two ports used for latency
282 PortManager::cycle_start (nframes);
283 PortManager::silence (nframes);
285 if (_latency_input_port && _latency_output_port) {
286 PortEngine& pe (port_engine());
288 _mididm->process (nframes, pe,
289 pe.get_buffer (_latency_input_port, nframes),
290 pe.get_buffer (_latency_output_port, nframes));
293 PortManager::cycle_end (nframes);
294 return_after_remove_check = true;
296 } else if (_latency_flush_samples) {
298 /* wait for the appropriate duration for the MTDM signal to
299 * drain from the ports before we revert to normal behaviour.
302 PortManager::cycle_start (nframes);
303 PortManager::silence (nframes);
304 PortManager::cycle_end (nframes);
306 if (_latency_flush_samples > nframes) {
307 _latency_flush_samples -= nframes;
309 _latency_flush_samples = 0;
312 return_after_remove_check = true;
315 if (session_remove_pending) {
317 /* perform the actual session removal */
319 if (session_removal_countdown < 0) {
321 /* fade out over 1 second */
322 session_removal_countdown = sample_rate()/2;
323 session_removal_gain = GAIN_COEFF_UNITY;
324 session_removal_gain_step = 1.0/session_removal_countdown;
326 } else if (session_removal_countdown > 0) {
328 /* we'll be fading audio out.
330 if this is the last time we do this as part
331 of session removal, do a MIDI panic now
332 to get MIDI stopped. This relies on the fact
333 that "immediate data" (aka "out of band data") from
334 MIDI tracks is *appended* after any other data,
335 so that it emerges after any outbound note ons, etc.
338 if (session_removal_countdown <= nframes) {
339 _session->midi_panic ();
345 session_removal_countdown = -1; // reset to "not in progress"
346 session_remove_pending = false;
347 session_removed.signal(); // wakes up thread that initiated session removal
351 if (return_after_remove_check) {
355 TransportMasterManager& tmm (TransportMasterManager::instance());
357 /* make sure the TMM is up to date about the current session */
359 if (_session != tmm.session()) {
360 tmm.set_session (_session);
365 if (!_freewheeling) {
366 PortManager::silence_outputs (nframes);
369 _processed_samples = next_processed_samples;
374 if (!_freewheeling || Freewheel.empty()) {
375 const double engine_speed = tmm.pre_process_transport_masters (nframes, sample_time_at_cycle_start());
376 Port::set_speed_ratio (engine_speed);
377 DEBUG_TRACE (DEBUG::Slave, string_compose ("transport master (current=%1) gives speed %2 (ports using %3)\n", tmm.current() ? tmm.current()->name() : string("[]"), engine_speed, Port::speed_ratio()));
380 /* tell all relevant objects that we're starting a new cycle */
382 InternalSend::CycleStart (nframes);
384 /* tell all Ports that we're starting a new cycle */
386 PortManager::cycle_start (nframes, _session);
388 /* test if we are freewheeling and there are freewheel signals connected.
389 * ardour should act normally even when freewheeling unless /it/ is
390 * exporting (which is what Freewheel.empty() tests for).
393 if (_freewheeling && !Freewheel.empty()) {
396 if (Port::cycle_nframes () <= nframes) {
397 _session->process (Port::cycle_nframes ());
399 pframes_t remain = Port::cycle_nframes ();
401 pframes_t nf = std::min (remain, nframes);
402 _session->process (nf);
412 PortManager::cycle_end (nframes, _session);
417 _processed_samples = next_processed_samples;
421 if (last_monitor_check + monitor_check_interval < next_processed_samples) {
423 PortManager::check_monitoring ();
424 last_monitor_check = next_processed_samples;
427 #ifdef SILENCE_AFTER_SECONDS
429 bool was_silent = (_silence_countdown == 0);
431 if (_silence_countdown >= nframes) {
432 _silence_countdown -= nframes;
434 _silence_countdown = 0;
437 if (!was_silent && _silence_countdown == 0) {
439 BecameSilent (); /* EMIT SIGNAL */
442 if (_silence_countdown == 0 || _session->silent()) {
443 PortManager::silence (nframes);
447 if (_session->silent()) {
448 PortManager::silence (nframes, _session);
452 if (session_remove_pending && session_removal_countdown) {
454 PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session);
456 if (session_removal_countdown > nframes) {
457 session_removal_countdown -= nframes;
459 session_removal_countdown = 0;
462 session_removal_gain -= (nframes * session_removal_gain_step);
464 PortManager::cycle_end (nframes, _session);
467 _processed_samples = next_processed_samples;
475 AudioEngine::reset_silence_countdown ()
477 #ifdef SILENCE_AFTER_SECONDS
478 double sr = 48000; /* default in case there is no backend */
482 _silence_countdown = max (60 * sr, /* 60 seconds */
483 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
489 AudioEngine::launch_device_control_app()
491 if (_state_lock.trylock () ) {
492 _backend->launch_control_app ();
493 _state_lock.unlock ();
499 AudioEngine::request_backend_reset()
501 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
502 g_atomic_int_inc (&_hw_reset_request_count);
503 _hw_reset_condition.signal ();
507 AudioEngine::backend_reset_requested()
509 return g_atomic_int_get (&_hw_reset_request_count);
513 AudioEngine::do_reset_backend()
515 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
517 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
519 while (!_stop_hw_reset_processing) {
521 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
523 _reset_request_lock.unlock();
525 Glib::Threads::RecMutex::Lock pl (_state_lock);
526 g_atomic_int_dec_and_test (&_hw_reset_request_count);
528 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
529 DeviceResetStarted(); // notify about device reset to be started
531 // backup the device name
532 std::string name = _backend->device_name ();
534 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
535 if ( ( 0 == stop () ) &&
536 ( 0 == _backend->reset_device () ) &&
537 ( 0 == start () ) ) {
539 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
541 // inform about possible changes
542 BufferSizeChanged (_backend->buffer_size() );
543 DeviceResetFinished(); // notify about device reset finish
547 DeviceResetFinished(); // notify about device reset finish
548 // we've got an error
552 std::cout << "AudioEngine::RESET::Done." << std::endl;
554 _reset_request_lock.lock();
558 _hw_reset_condition.wait (_reset_request_lock);
565 AudioEngine::request_device_list_update()
567 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
568 g_atomic_int_inc (&_hw_devicelist_update_count);
569 _hw_devicelist_update_condition.signal ();
573 AudioEngine::do_devicelist_update()
575 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
577 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
579 while (!_stop_hw_devicelist_processing) {
581 if (_hw_devicelist_update_count) {
583 _devicelist_update_lock.unlock();
585 Glib::Threads::RecMutex::Lock pl (_state_lock);
587 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
588 DeviceListChanged (); /* EMIT SIGNAL */
590 _devicelist_update_lock.lock();
593 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
600 AudioEngine::start_hw_event_processing()
602 if (_hw_reset_event_thread == 0) {
603 g_atomic_int_set(&_hw_reset_request_count, 0);
604 g_atomic_int_set(&_stop_hw_reset_processing, 0);
605 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
608 if (_hw_devicelist_update_thread == 0) {
609 g_atomic_int_set(&_hw_devicelist_update_count, 0);
610 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
611 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
617 AudioEngine::stop_hw_event_processing()
619 if (_hw_reset_event_thread) {
620 g_atomic_int_set(&_stop_hw_reset_processing, 1);
621 g_atomic_int_set(&_hw_reset_request_count, 0);
622 _hw_reset_condition.signal ();
623 _hw_reset_event_thread->join ();
624 _hw_reset_event_thread = 0;
627 if (_hw_devicelist_update_thread) {
628 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
629 g_atomic_int_set(&_hw_devicelist_update_count, 0);
630 _hw_devicelist_update_condition.signal ();
631 _hw_devicelist_update_thread->join ();
632 _hw_devicelist_update_thread = 0;
637 AudioEngine::set_session (Session *s)
639 Glib::Threads::Mutex::Lock pl (_process_lock);
641 SessionHandlePtr::set_session (s);
645 pframes_t blocksize = samples_per_cycle ();
647 PortManager::cycle_start (blocksize);
649 _session->process (blocksize);
650 _session->process (blocksize);
651 _session->process (blocksize);
652 _session->process (blocksize);
653 _session->process (blocksize);
654 _session->process (blocksize);
655 _session->process (blocksize);
656 _session->process (blocksize);
658 PortManager::cycle_end (blocksize);
663 AudioEngine::remove_session ()
665 Glib::Threads::Mutex::Lock lm (_process_lock);
670 session_remove_pending = true;
671 /* signal the start of the fade out countdown */
672 session_removal_countdown = -1;
673 session_removed.wait(_process_lock);
677 SessionHandlePtr::set_session (0);
685 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
687 #ifdef USE_TRACKS_CODE_FEATURES
689 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
698 /* called from a signal handler for SIGPIPE */
703 AudioEngine::reset_timebase ()
706 if (_session->config.get_jack_time_master()) {
707 _backend->set_time_master (true);
709 _backend->set_time_master (false);
717 AudioEngine::destroy ()
724 AudioEngine::discover_backends ()
726 vector<std::string> backend_modules;
730 Glib::PatternSpec so_extension_pattern("*backend.so");
731 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
733 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
734 #if defined(DEBUG) || defined(_DEBUG)
735 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
737 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
740 Glib::PatternSpec dll_extension_pattern("*backend.dll");
743 find_files_matching_pattern (backend_modules, backend_search_path (),
744 so_extension_pattern);
746 find_files_matching_pattern (backend_modules, backend_search_path (),
747 dylib_extension_pattern);
749 find_files_matching_pattern (backend_modules, backend_search_path (),
750 dll_extension_pattern);
752 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
754 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
756 AudioBackendInfo* info;
758 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
760 if ((info = backend_discover (*i)) != 0) {
761 _backends.insert (make_pair (info->name, info));
765 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
767 return _backends.size();
771 AudioEngine::backend_discover (const string& path)
773 #ifdef PLATFORM_WINDOWS
774 // do not show popup dialog (e.g. missing libjack.dll)
775 // win7+ should use SetThreadErrorMode()
776 SetErrorMode(SEM_FAILCRITICALERRORS);
778 Glib::Module module (path);
779 #ifdef PLATFORM_WINDOWS
780 SetErrorMode(0); // reset to system default
782 AudioBackendInfo* info;
783 AudioBackendInfo* (*dfunc)(void);
787 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
788 Glib::Module::get_last_error()) << endmsg;
792 if (!module.get_symbol ("descriptor", func)) {
793 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
794 error << Glib::Module::get_last_error() << endmsg;
798 dfunc = (AudioBackendInfo* (*)(void))func;
800 if (!info->available()) {
804 module.make_resident ();
810 static bool running_from_source_tree ()
812 // dup ARDOUR_UI_UTILS::running_from_source_tree ()
813 gchar const *x = g_getenv ("ARDOUR_THEMES_PATH");
814 return x && (string (x).find ("gtk2_ardour") != string::npos);
818 vector<const AudioBackendInfo*>
819 AudioEngine::available_backends() const
821 vector<const AudioBackendInfo*> r;
823 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
825 if (i->first == "None (Dummy)" && !running_from_source_tree () && Config->get_hide_dummy_backend ()) {
829 r.push_back (i->second);
836 AudioEngine::current_backend_name() const
839 return _backend->name();
845 AudioEngine::drop_backend ()
849 // Stopped is needed for Graph to explicitly terminate threads
850 Stopped (); /* EMIT SIGNAL */
851 _backend->drop_device ();
857 boost::shared_ptr<AudioBackend>
858 AudioEngine::set_default_backend ()
860 if (_backends.empty()) {
861 return boost::shared_ptr<AudioBackend>();
864 return set_backend (_backends.begin()->first, "", "");
867 boost::shared_ptr<AudioBackend>
868 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
870 BackendMap::iterator b = _backends.find (name);
872 if (b == _backends.end()) {
873 return boost::shared_ptr<AudioBackend>();
879 if (b->second->instantiate (arg1, arg2)) {
880 throw failed_constructor ();
883 _backend = b->second->factory (*this);
885 } catch (exception& e) {
886 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
887 return boost::shared_ptr<AudioBackend>();
893 /* BACKEND PROXY WRAPPERS */
896 AudioEngine::start (bool for_latency)
906 _processed_samples = 0;
907 last_monitor_check = 0;
909 int error_code = _backend->start (for_latency);
911 if (error_code != 0) {
912 _last_backend_error_string = AudioBackend::get_error_string((AudioBackend::ErrorCode) error_code);
919 _session->set_sample_rate (_backend->sample_rate());
921 if (_session->config.get_jack_time_master()) {
922 _backend->set_time_master (true);
927 /* XXX MIDI ports may not actually be available here yet .. */
929 PortManager::fill_midi_port_info ();
932 Running(); /* EMIT SIGNAL */
939 AudioEngine::stop (bool for_latency)
941 bool stop_engine = true;
947 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
953 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
956 _backend->start (false); // keep running, reload latencies
959 if (_backend->stop ()) {
971 const bool was_running_will_stop = (_running && stop_engine);
973 if (was_running_will_stop) {
977 if (_session && was_running_will_stop &&
978 (_session->state_of_the_state() & Session::Loading) == 0 &&
979 (_session->state_of_the_state() & Session::Deletion) == 0) {
980 // it's not a halt, but should be handled the same way:
981 // disable record, stop transport and I/O processign but save the data.
982 _session->engine_halted ();
985 if (was_running_will_stop) {
987 _started_for_latency = false;
988 } else if (!_started_for_latency) {
989 _stopped_for_latency = true;
992 _processed_samples = 0;
993 _measuring_latency = MeasureNone;
994 _latency_output_port = 0;
995 _latency_input_port = 0;
1002 Stopped (); /* EMIT SIGNAL */
1009 AudioEngine::freewheel (bool start_stop)
1015 /* _freewheeling will be set when first Freewheel signal occurs */
1017 return _backend->freewheel (start_stop);
1021 AudioEngine::get_dsp_load() const
1023 if (!_backend || !_running) {
1026 return _backend->dsp_load ();
1030 AudioEngine::is_realtime() const
1036 return _backend->is_realtime();
1040 AudioEngine::transport_start ()
1045 return _backend->transport_start ();
1049 AudioEngine::transport_stop ()
1054 return _backend->transport_stop ();
1058 AudioEngine::transport_state ()
1061 return TransportStopped;
1063 return _backend->transport_state ();
1067 AudioEngine::transport_locate (samplepos_t pos)
1072 return _backend->transport_locate (pos);
1076 AudioEngine::transport_sample()
1081 return _backend->transport_sample ();
1085 AudioEngine::sample_rate () const
1090 return _backend->sample_rate ();
1094 AudioEngine::samples_per_cycle () const
1099 return _backend->buffer_size ();
1103 AudioEngine::usecs_per_cycle () const
1108 return _backend->usecs_per_cycle ();
1112 AudioEngine::raw_buffer_size (DataType t)
1117 return _backend->raw_buffer_size (t);
1121 AudioEngine::sample_time ()
1126 return _backend->sample_time ();
1130 AudioEngine::sample_time_at_cycle_start ()
1135 return _backend->sample_time_at_cycle_start ();
1139 AudioEngine::samples_since_cycle_start ()
1144 return _backend->samples_since_cycle_start ();
1148 AudioEngine::get_sync_offset (pframes_t& offset) const
1153 return _backend->get_sync_offset (offset);
1157 AudioEngine::create_process_thread (boost::function<void()> func)
1162 return _backend->create_process_thread (func);
1166 AudioEngine::join_process_threads ()
1171 return _backend->join_process_threads ();
1175 AudioEngine::in_process_thread ()
1180 return _backend->in_process_thread ();
1184 AudioEngine::process_thread_count ()
1189 return _backend->process_thread_count ();
1193 AudioEngine::set_device_name (const std::string& name)
1198 return _backend->set_device_name (name);
1202 AudioEngine::set_sample_rate (float sr)
1208 return _backend->set_sample_rate (sr);
1212 AudioEngine::set_buffer_size (uint32_t bufsiz)
1217 return _backend->set_buffer_size (bufsiz);
1221 AudioEngine::set_interleaved (bool yn)
1226 return _backend->set_interleaved (yn);
1230 AudioEngine::set_input_channels (uint32_t ic)
1235 return _backend->set_input_channels (ic);
1239 AudioEngine::set_output_channels (uint32_t oc)
1244 return _backend->set_output_channels (oc);
1248 AudioEngine::set_systemic_input_latency (uint32_t il)
1253 return _backend->set_systemic_input_latency (il);
1257 AudioEngine::set_systemic_output_latency (uint32_t ol)
1262 return _backend->set_systemic_output_latency (ol);
1266 AudioEngine::thread_initialised_for_audio_processing ()
1268 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1271 /* END OF BACKEND PROXY API */
1274 AudioEngine::thread_init_callback (void* arg)
1276 /* make sure that anybody who needs to know about this thread
1280 pthread_set_name (X_("audioengine"));
1282 const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1);
1283 const string thread_name = string_compose (X_("AudioEngine %1"), thread_num);
1285 SessionEvent::create_per_thread_pool (thread_name, 512);
1286 PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096);
1287 AsyncMIDIPort::set_process_thread (pthread_self());
1290 delete AudioEngine::instance()->_main_thread;
1291 /* the special thread created/managed by the backend */
1292 AudioEngine::instance()->_main_thread = new ProcessThread;
1297 AudioEngine::sync_callback (TransportState state, samplepos_t position)
1300 return _session->backend_sync_callback (state, position);
1306 AudioEngine::freewheel_callback (bool onoff)
1308 _freewheeling = onoff;
1312 AudioEngine::latency_callback (bool for_playback)
1315 _session->update_latency (for_playback);
1320 AudioEngine::update_latencies ()
1323 _backend->update_latencies ();
1328 AudioEngine::halted_callback (const char* why)
1330 if (_in_destructor) {
1331 /* everything is under control */
1337 Port::PortDrop (); /* EMIT SIGNAL */
1339 if (!_started_for_latency) {
1340 Halted (why); /* EMIT SIGNAL */
1345 AudioEngine::setup_required () const
1348 if (_backend->info().already_configured())
1351 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1360 AudioEngine::prepare_for_latency_measurement ()
1366 if (running() && _started_for_latency) {
1370 if (_backend->can_change_systemic_latency_when_running()) {
1372 _backend->start (true); // zero latency reporting of running backend
1373 } else if (start (true)) {
1376 _started_for_latency = true;
1387 _started_for_latency = true;
1392 AudioEngine::start_latency_detection (bool for_midi)
1394 if (prepare_for_latency_measurement ()) {
1398 PortEngine& pe (port_engine());
1406 /* find the ports we will connect to */
1408 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1409 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1416 /* create the ports we will use to read/write data */
1418 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1422 if (pe.connect (_latency_output_port, _latency_output_name)) {
1423 pe.unregister_port (_latency_output_port);
1428 const string portname ("latency_in");
1429 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1430 pe.unregister_port (_latency_input_port);
1431 pe.unregister_port (_latency_output_port);
1435 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1436 pe.unregister_port (_latency_input_port);
1437 pe.unregister_port (_latency_output_port);
1442 _mididm = new MIDIDM (sample_rate());
1446 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1450 if (pe.connect (_latency_output_port, _latency_output_name)) {
1451 pe.unregister_port (_latency_output_port);
1456 const string portname ("latency_in");
1457 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1458 pe.unregister_port (_latency_input_port);
1459 pe.unregister_port (_latency_output_port);
1463 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1464 pe.unregister_port (_latency_input_port);
1465 pe.unregister_port (_latency_output_port);
1470 _mtdm = new MTDM (sample_rate());
1475 _latency_signal_latency = 0;
1476 lr = pe.get_latency_range (in, false);
1477 _latency_signal_latency = lr.max;
1478 lr = pe.get_latency_range (out, true);
1479 _latency_signal_latency += lr.max;
1481 /* all created and connected, lets go */
1482 _latency_flush_samples = samples_per_cycle();
1483 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1489 AudioEngine::stop_latency_detection ()
1491 _measuring_latency = MeasureNone;
1493 if (_latency_output_port) {
1494 port_engine().unregister_port (_latency_output_port);
1495 _latency_output_port = 0;
1497 if (_latency_input_port) {
1498 port_engine().unregister_port (_latency_input_port);
1499 _latency_input_port = 0;
1502 if (_running && _backend->can_change_systemic_latency_when_running()) {
1503 if (_started_for_latency) {
1504 _running = false; // force reload: reset latencies and emit Running()
1509 if (_running && !_started_for_latency) {
1510 assert (!_stopped_for_latency);
1514 if (!_backend->can_change_systemic_latency_when_running()) {
1518 if (_stopped_for_latency) {
1522 _stopped_for_latency = false;
1523 _started_for_latency = false;
1527 AudioEngine::set_latency_output_port (const string& name)
1529 _latency_output_name = name;
1533 AudioEngine::set_latency_input_port (const string& name)
1535 _latency_input_name = name;
1539 AudioEngine::add_pending_port_deletion (Port* p)
1542 DEBUG_TRACE (DEBUG::Ports, string_compose ("adding %1 to pending port deletion list\n", p->name()));
1543 if (_port_deletions_pending.write (&p, 1) != 1) {
1544 error << string_compose (_("programming error: port %1 could not be placed on the pending deletion queue\n"), p->name()) << endmsg;
1546 _session->auto_connect_thread_wakeup ();
1548 DEBUG_TRACE (DEBUG::Ports, string_compose ("Directly delete port %1\n", p->name()));