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;
67 #define SILENCE_AFTER_SECONDS 600
70 AudioEngine::AudioEngine ()
71 : session_remove_pending (false)
72 , session_removal_countdown (-1)
74 , _freewheeling (false)
75 , monitor_check_interval (INT32_MAX)
76 , last_monitor_check (0)
77 , _processed_frames (0)
82 , _measuring_latency (MeasureNone)
83 , _latency_input_port (0)
84 , _latency_output_port (0)
85 , _latency_flush_frames (0)
86 , _latency_signal_latency (0)
87 , _stopped_for_latency (false)
88 , _started_for_latency (false)
89 , _in_destructor (false)
90 , _hw_reset_event_thread(0)
91 , _hw_reset_request_count(0)
92 , _stop_hw_reset_processing(0)
93 , _hw_devicelist_update_thread(0)
94 , _hw_devicelist_update_count(0)
95 , _stop_hw_devicelist_processing(0)
96 #ifdef SILENCE_AFTER_SECONDS
97 , _silence_countdown (0)
98 , _silence_hit_cnt (0)
101 reset_silence_countdown ();
102 start_hw_event_processing();
103 discover_backends ();
106 AudioEngine::~AudioEngine ()
108 _in_destructor = true;
109 stop_hw_event_processing();
111 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
112 i->second->deinstantiate();
117 AudioEngine::create ()
123 _instance = new AudioEngine ();
129 AudioEngine::split_cycle (pframes_t offset)
131 /* caller must hold process lock */
133 Port::increment_global_port_buffer_offset (offset);
135 /* tell all Ports that we're going to start a new (split) cycle */
137 boost::shared_ptr<Ports> p = ports.reader();
139 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
140 i->second->cycle_split ();
145 AudioEngine::sample_rate_change (pframes_t nframes)
147 /* check for monitor input change every 1/10th of second */
149 monitor_check_interval = nframes / 10;
150 last_monitor_check = 0;
153 _session->set_frame_rate (nframes);
156 SampleRateChanged (nframes); /* EMIT SIGNAL */
158 #ifdef SILENCE_AFTER_SECONDS
159 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
166 AudioEngine::buffer_size_change (pframes_t bufsiz)
169 _session->set_block_size (bufsiz);
170 last_monitor_check = 0;
173 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
178 /** Method called by our ::process_thread when there is work to be done.
179 * @param nframes Number of frames to process.
182 __attribute__((annotate("realtime")))
185 AudioEngine::process_callback (pframes_t nframes)
187 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
192 /// The number of frames that will have been processed when we've finished
193 pframes_t next_processed_frames;
195 /* handle wrap around of total frames counter */
197 if (max_framepos - _processed_frames < nframes) {
198 next_processed_frames = nframes - (max_framepos - _processed_frames);
200 next_processed_frames = _processed_frames + nframes;
204 /* return having done nothing */
208 /* really only JACK requires this
209 * (other backends clear the output buffers
210 * before the process_callback. it may even be
211 * jack/alsa only). but better safe than sorry.
213 PortManager::silence_outputs (nframes);
217 bool return_after_remove_check = false;
219 if (_measuring_latency == MeasureAudio && _mtdm) {
220 /* run a normal cycle from the perspective of the PortManager
221 so that we get silence on all registered ports.
223 we overwrite the silence on the two ports used for latency
227 PortManager::cycle_start (nframes);
228 PortManager::silence (nframes);
230 if (_latency_input_port && _latency_output_port) {
231 PortEngine& pe (port_engine());
233 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
234 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
236 _mtdm->process (nframes, in, out);
239 PortManager::cycle_end (nframes);
240 return_after_remove_check = true;
242 } else if (_measuring_latency == MeasureMIDI && _mididm) {
243 /* run a normal cycle from the perspective of the PortManager
244 so that we get silence on all registered ports.
246 we overwrite the silence on the two ports used for latency
250 PortManager::cycle_start (nframes);
251 PortManager::silence (nframes);
253 if (_latency_input_port && _latency_output_port) {
254 PortEngine& pe (port_engine());
256 _mididm->process (nframes, pe,
257 pe.get_buffer (_latency_input_port, nframes),
258 pe.get_buffer (_latency_output_port, nframes));
261 PortManager::cycle_end (nframes);
262 return_after_remove_check = true;
264 } else if (_latency_flush_frames) {
266 /* wait for the appropriate duration for the MTDM signal to
267 * drain from the ports before we revert to normal behaviour.
270 PortManager::cycle_start (nframes);
271 PortManager::silence (nframes);
272 PortManager::cycle_end (nframes);
274 if (_latency_flush_frames > nframes) {
275 _latency_flush_frames -= nframes;
277 _latency_flush_frames = 0;
280 return_after_remove_check = true;
283 if (session_remove_pending) {
285 /* perform the actual session removal */
287 if (session_removal_countdown < 0) {
289 /* fade out over 1 second */
290 session_removal_countdown = sample_rate()/2;
291 session_removal_gain = GAIN_COEFF_UNITY;
292 session_removal_gain_step = 1.0/session_removal_countdown;
294 } else if (session_removal_countdown > 0) {
296 /* we'll be fading audio out.
298 if this is the last time we do this as part
299 of session removal, do a MIDI panic now
300 to get MIDI stopped. This relies on the fact
301 that "immediate data" (aka "out of band data") from
302 MIDI tracks is *appended* after any other data,
303 so that it emerges after any outbound note ons, etc.
306 if (session_removal_countdown <= nframes) {
307 _session->midi_panic ();
313 session_removal_countdown = -1; // reset to "not in progress"
314 session_remove_pending = false;
315 session_removed.signal(); // wakes up thread that initiated session removal
319 if (return_after_remove_check) {
325 if (!_freewheeling) {
326 PortManager::cycle_start (nframes);
327 PortManager::cycle_end (nframes);
330 _processed_frames = next_processed_frames;
335 /* tell all relevant objects that we're starting a new cycle */
337 InternalSend::CycleStart (nframes);
339 /* tell all Ports that we're starting a new cycle */
341 PortManager::cycle_start (nframes);
343 /* test if we are freewheeling and there are freewheel signals connected.
344 ardour should act normally even when freewheeling unless /it/ is
345 exporting (which is what Freewheel.empty() tests for).
348 if (_freewheeling && !Freewheel.empty()) {
351 _session->process (nframes);
355 PortManager::cycle_end (nframes);
360 _processed_frames = next_processed_frames;
364 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
366 PortManager::check_monitoring ();
367 last_monitor_check = next_processed_frames;
370 #ifdef SILENCE_AFTER_SECONDS
372 bool was_silent = (_silence_countdown == 0);
374 if (_silence_countdown >= nframes) {
375 _silence_countdown -= nframes;
377 _silence_countdown = 0;
380 if (!was_silent && _silence_countdown == 0) {
382 BecameSilent (); /* EMIT SIGNAL */
385 if (_silence_countdown == 0 || _session->silent()) {
386 PortManager::silence (nframes);
390 if (_session->silent()) {
391 PortManager::silence (nframes);
395 if (session_remove_pending && session_removal_countdown) {
397 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
399 if (session_removal_countdown > nframes) {
400 session_removal_countdown -= nframes;
402 session_removal_countdown = 0;
405 session_removal_gain -= (nframes * session_removal_gain_step);
408 PortManager::cycle_end (nframes);
410 _processed_frames = next_processed_frames;
418 AudioEngine::reset_silence_countdown ()
420 #ifdef SILENCE_AFTER_SECONDS
421 double sr = 48000; /* default in case there is no backend */
425 _silence_countdown = max (60 * sr, /* 60 seconds */
426 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
432 AudioEngine::launch_device_control_app()
434 if (_state_lock.trylock () ) {
435 _backend->launch_control_app ();
436 _state_lock.unlock ();
442 AudioEngine::request_backend_reset()
444 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
445 g_atomic_int_inc (&_hw_reset_request_count);
446 _hw_reset_condition.signal ();
450 AudioEngine::backend_reset_requested()
452 return g_atomic_int_get (&_hw_reset_request_count);
456 AudioEngine::do_reset_backend()
458 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
460 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
462 while (!_stop_hw_reset_processing) {
464 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
466 _reset_request_lock.unlock();
468 Glib::Threads::RecMutex::Lock pl (_state_lock);
469 g_atomic_int_dec_and_test (&_hw_reset_request_count);
471 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
472 DeviceResetStarted(); // notify about device reset to be started
474 // backup the device name
475 std::string name = _backend->device_name ();
477 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
478 if ( ( 0 == stop () ) &&
479 ( 0 == _backend->reset_device () ) &&
480 ( 0 == start () ) ) {
482 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
484 // inform about possible changes
485 BufferSizeChanged (_backend->buffer_size() );
486 DeviceResetFinished(); // notify about device reset finish
490 DeviceResetFinished(); // notify about device reset finish
491 // we've got an error
495 std::cout << "AudioEngine::RESET::Done." << std::endl;
497 _reset_request_lock.lock();
501 _hw_reset_condition.wait (_reset_request_lock);
507 AudioEngine::request_device_list_update()
509 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
510 g_atomic_int_inc (&_hw_devicelist_update_count);
511 _hw_devicelist_update_condition.signal ();
516 AudioEngine::do_devicelist_update()
518 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
520 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
522 while (!_stop_hw_devicelist_processing) {
524 if (_hw_devicelist_update_count) {
526 _devicelist_update_lock.unlock();
528 Glib::Threads::RecMutex::Lock pl (_state_lock);
530 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
531 DeviceListChanged (); /* EMIT SIGNAL */
533 _devicelist_update_lock.lock();
536 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
543 AudioEngine::start_hw_event_processing()
545 if (_hw_reset_event_thread == 0) {
546 g_atomic_int_set(&_hw_reset_request_count, 0);
547 g_atomic_int_set(&_stop_hw_reset_processing, 0);
548 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
551 if (_hw_devicelist_update_thread == 0) {
552 g_atomic_int_set(&_hw_devicelist_update_count, 0);
553 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
554 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
560 AudioEngine::stop_hw_event_processing()
562 if (_hw_reset_event_thread) {
563 g_atomic_int_set(&_stop_hw_reset_processing, 1);
564 g_atomic_int_set(&_hw_reset_request_count, 0);
565 _hw_reset_condition.signal ();
566 _hw_reset_event_thread->join ();
567 _hw_reset_event_thread = 0;
570 if (_hw_devicelist_update_thread) {
571 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
572 g_atomic_int_set(&_hw_devicelist_update_count, 0);
573 _hw_devicelist_update_condition.signal ();
574 _hw_devicelist_update_thread->join ();
575 _hw_devicelist_update_thread = 0;
582 AudioEngine::set_session (Session *s)
584 Glib::Threads::Mutex::Lock pl (_process_lock);
586 SessionHandlePtr::set_session (s);
590 pframes_t blocksize = samples_per_cycle ();
592 PortManager::cycle_start (blocksize);
594 _session->process (blocksize);
595 _session->process (blocksize);
596 _session->process (blocksize);
597 _session->process (blocksize);
598 _session->process (blocksize);
599 _session->process (blocksize);
600 _session->process (blocksize);
601 _session->process (blocksize);
603 PortManager::cycle_end (blocksize);
608 AudioEngine::remove_session ()
610 Glib::Threads::Mutex::Lock lm (_process_lock);
615 session_remove_pending = true;
616 session_removal_countdown = 0;
617 session_removed.wait(_process_lock);
621 SessionHandlePtr::set_session (0);
629 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
631 #ifdef USE_TRACKS_CODE_FEATURES
633 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
642 /* called from a signal handler for SIGPIPE */
647 AudioEngine::reset_timebase ()
650 if (_session->config.get_jack_time_master()) {
651 _backend->set_time_master (true);
653 _backend->set_time_master (false);
661 AudioEngine::destroy ()
668 AudioEngine::discover_backends ()
670 vector<std::string> backend_modules;
674 Glib::PatternSpec so_extension_pattern("*backend.so");
675 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
677 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
678 #if defined(DEBUG) || defined(_DEBUG)
679 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
681 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
684 Glib::PatternSpec dll_extension_pattern("*backend.dll");
687 find_files_matching_pattern (backend_modules, backend_search_path (),
688 so_extension_pattern);
690 find_files_matching_pattern (backend_modules, backend_search_path (),
691 dylib_extension_pattern);
693 find_files_matching_pattern (backend_modules, backend_search_path (),
694 dll_extension_pattern);
696 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
698 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
700 AudioBackendInfo* info;
702 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
704 if ((info = backend_discover (*i)) != 0) {
705 _backends.insert (make_pair (info->name, info));
709 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
711 return _backends.size();
715 AudioEngine::backend_discover (const string& path)
717 #ifdef PLATFORM_WINDOWS
718 // do not show popup dialog (e.g. missing libjack.dll)
719 // win7+ should use SetThreadErrorMode()
720 SetErrorMode(SEM_FAILCRITICALERRORS);
722 Glib::Module module (path);
723 #ifdef PLATFORM_WINDOWS
724 SetErrorMode(0); // reset to system default
726 AudioBackendInfo* info;
727 AudioBackendInfo* (*dfunc)(void);
731 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
732 Glib::Module::get_last_error()) << endmsg;
736 if (!module.get_symbol ("descriptor", func)) {
737 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
738 error << Glib::Module::get_last_error() << endmsg;
742 dfunc = (AudioBackendInfo* (*)(void))func;
744 if (!info->available()) {
748 module.make_resident ();
753 vector<const AudioBackendInfo*>
754 AudioEngine::available_backends() const
756 vector<const AudioBackendInfo*> r;
758 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
759 r.push_back (i->second);
766 AudioEngine::current_backend_name() const
769 return _backend->name();
775 AudioEngine::drop_backend ()
779 // Stopped is needed for Graph to explicitly terminate threads
780 Stopped (); /* EMIT SIGNAL */
781 _backend->drop_device ();
787 boost::shared_ptr<AudioBackend>
788 AudioEngine::set_default_backend ()
790 if (_backends.empty()) {
791 return boost::shared_ptr<AudioBackend>();
794 return set_backend (_backends.begin()->first, "", "");
797 boost::shared_ptr<AudioBackend>
798 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
800 BackendMap::iterator b = _backends.find (name);
802 if (b == _backends.end()) {
803 return boost::shared_ptr<AudioBackend>();
809 if (b->second->instantiate (arg1, arg2)) {
810 throw failed_constructor ();
813 _backend = b->second->factory (*this);
815 } catch (exception& e) {
816 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
817 return boost::shared_ptr<AudioBackend>();
823 /* BACKEND PROXY WRAPPERS */
826 AudioEngine::start (bool for_latency)
836 _processed_frames = 0;
837 last_monitor_check = 0;
839 int error_code = _backend->start (for_latency);
841 if (error_code != 0) {
842 _last_backend_error_string =
843 AudioBackend::get_error_string((AudioBackend::ErrorCode)error_code);
850 _session->set_frame_rate (_backend->sample_rate());
852 if (_session->config.get_jack_time_master()) {
853 _backend->set_time_master (true);
859 Running(); /* EMIT SIGNAL */
866 AudioEngine::stop (bool for_latency)
872 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
878 if (_backend->stop ()) {
886 if (_session && _running &&
887 (_session->state_of_the_state() & Session::Loading) == 0 &&
888 (_session->state_of_the_state() & Session::Deletion) == 0) {
889 // it's not a halt, but should be handled the same way:
890 // disable record, stop transport and I/O processign but save the data.
891 _session->engine_halted ();
895 _processed_frames = 0;
896 _measuring_latency = MeasureNone;
897 _latency_output_port = 0;
898 _latency_input_port = 0;
899 _started_for_latency = false;
904 Stopped (); /* EMIT SIGNAL */
911 AudioEngine::freewheel (bool start_stop)
917 /* _freewheeling will be set when first Freewheel signal occurs */
919 return _backend->freewheel (start_stop);
923 AudioEngine::get_dsp_load() const
928 return _backend->dsp_load ();
932 AudioEngine::is_realtime() const
938 return _backend->is_realtime();
942 AudioEngine::connected() const
948 return _backend->available();
952 AudioEngine::transport_start ()
957 return _backend->transport_start ();
961 AudioEngine::transport_stop ()
966 return _backend->transport_stop ();
970 AudioEngine::transport_state ()
973 return TransportStopped;
975 return _backend->transport_state ();
979 AudioEngine::transport_locate (framepos_t pos)
984 return _backend->transport_locate (pos);
988 AudioEngine::transport_frame()
993 return _backend->transport_frame ();
997 AudioEngine::sample_rate () const
1002 return _backend->sample_rate ();
1006 AudioEngine::samples_per_cycle () const
1011 return _backend->buffer_size ();
1015 AudioEngine::usecs_per_cycle () const
1020 return _backend->usecs_per_cycle ();
1024 AudioEngine::raw_buffer_size (DataType t)
1029 return _backend->raw_buffer_size (t);
1033 AudioEngine::sample_time ()
1038 return _backend->sample_time ();
1042 AudioEngine::sample_time_at_cycle_start ()
1047 return _backend->sample_time_at_cycle_start ();
1051 AudioEngine::samples_since_cycle_start ()
1056 return _backend->samples_since_cycle_start ();
1060 AudioEngine::get_sync_offset (pframes_t& offset) const
1065 return _backend->get_sync_offset (offset);
1069 AudioEngine::create_process_thread (boost::function<void()> func)
1074 return _backend->create_process_thread (func);
1078 AudioEngine::join_process_threads ()
1083 return _backend->join_process_threads ();
1087 AudioEngine::in_process_thread ()
1092 return _backend->in_process_thread ();
1096 AudioEngine::process_thread_count ()
1101 return _backend->process_thread_count ();
1105 AudioEngine::set_device_name (const std::string& name)
1110 return _backend->set_device_name (name);
1114 AudioEngine::set_sample_rate (float sr)
1120 return _backend->set_sample_rate (sr);
1124 AudioEngine::set_buffer_size (uint32_t bufsiz)
1129 return _backend->set_buffer_size (bufsiz);
1133 AudioEngine::set_interleaved (bool yn)
1138 return _backend->set_interleaved (yn);
1142 AudioEngine::set_input_channels (uint32_t ic)
1147 return _backend->set_input_channels (ic);
1151 AudioEngine::set_output_channels (uint32_t oc)
1156 return _backend->set_output_channels (oc);
1160 AudioEngine::set_systemic_input_latency (uint32_t il)
1165 return _backend->set_systemic_input_latency (il);
1169 AudioEngine::set_systemic_output_latency (uint32_t ol)
1174 return _backend->set_systemic_output_latency (ol);
1178 AudioEngine::thread_initialised_for_audio_processing ()
1180 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1183 /* END OF BACKEND PROXY API */
1186 AudioEngine::thread_init_callback (void* arg)
1188 /* make sure that anybody who needs to know about this thread
1192 pthread_set_name (X_("audioengine"));
1194 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1196 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1197 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1199 AsyncMIDIPort::set_process_thread (pthread_self());
1202 /* the special thread created/managed by the backend */
1203 AudioEngine::instance()->_main_thread = new ProcessThread;
1208 AudioEngine::sync_callback (TransportState state, framepos_t position)
1211 return _session->backend_sync_callback (state, position);
1217 AudioEngine::freewheel_callback (bool onoff)
1219 _freewheeling = onoff;
1223 AudioEngine::latency_callback (bool for_playback)
1226 _session->update_latency (for_playback);
1231 AudioEngine::update_latencies ()
1234 _backend->update_latencies ();
1239 AudioEngine::halted_callback (const char* why)
1241 if (_in_destructor) {
1242 /* everything is under control */
1248 Port::PortDrop (); /* EMIT SIGNAL */
1250 if (!_started_for_latency) {
1251 Halted (why); /* EMIT SIGNAL */
1256 AudioEngine::setup_required () const
1259 if (_backend->info().already_configured())
1262 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1271 AudioEngine::prepare_for_latency_measurement ()
1274 _stopped_for_latency = true;
1279 _started_for_latency = true;
1287 AudioEngine::start_latency_detection (bool for_midi)
1290 if (prepare_for_latency_measurement ()) {
1295 PortEngine& pe (port_engine());
1303 /* find the ports we will connect to */
1305 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1306 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1313 /* create the ports we will use to read/write data */
1315 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1319 if (pe.connect (_latency_output_port, _latency_output_name)) {
1320 pe.unregister_port (_latency_output_port);
1325 const string portname ("latency_in");
1326 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1327 pe.unregister_port (_latency_input_port);
1328 pe.unregister_port (_latency_output_port);
1332 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1333 pe.unregister_port (_latency_input_port);
1334 pe.unregister_port (_latency_output_port);
1339 _mididm = new MIDIDM (sample_rate());
1343 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1347 if (pe.connect (_latency_output_port, _latency_output_name)) {
1348 pe.unregister_port (_latency_output_port);
1353 const string portname ("latency_in");
1354 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1355 pe.unregister_port (_latency_input_port);
1356 pe.unregister_port (_latency_output_port);
1360 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1361 pe.unregister_port (_latency_input_port);
1362 pe.unregister_port (_latency_output_port);
1367 _mtdm = new MTDM (sample_rate());
1372 _latency_signal_latency = 0;
1373 lr = pe.get_latency_range (in, false);
1374 _latency_signal_latency = lr.max;
1375 lr = pe.get_latency_range (out, true);
1376 _latency_signal_latency += lr.max;
1378 /* all created and connected, lets go */
1379 _latency_flush_frames = samples_per_cycle();
1380 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1386 AudioEngine::stop_latency_detection ()
1388 _measuring_latency = MeasureNone;
1390 if (_latency_output_port) {
1391 port_engine().unregister_port (_latency_output_port);
1392 _latency_output_port = 0;
1394 if (_latency_input_port) {
1395 port_engine().unregister_port (_latency_input_port);
1396 _latency_input_port = 0;
1401 if (_stopped_for_latency) {
1405 _stopped_for_latency = false;
1406 _started_for_latency = false;
1410 AudioEngine::set_latency_output_port (const string& name)
1412 _latency_output_name = name;
1416 AudioEngine::set_latency_input_port (const string& name)
1418 _latency_input_name = name;