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"), 512);
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::Stoping engine..." << std::endl;
480 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
481 if ( 0 == _backend->reset_device () ) {
483 std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
486 // inform about possible changes
487 BufferSizeChanged (_backend->buffer_size() );
492 std::cout << "AudioEngine::RESET::Done." << std::endl;
494 _reset_request_lock.lock();
498 _hw_reset_condition.wait (_reset_request_lock);
504 AudioEngine::request_device_list_update()
506 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
507 g_atomic_int_inc (&_hw_devicelist_update_count);
508 _hw_devicelist_update_condition.signal ();
513 AudioEngine::do_devicelist_update()
515 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
517 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
519 while (!_stop_hw_devicelist_processing) {
521 if (_hw_devicelist_update_count) {
523 _devicelist_update_lock.unlock();
525 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
526 DeviceListChanged (); /* EMIT SIGNAL */
528 _devicelist_update_lock.lock();
531 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
538 AudioEngine::start_hw_event_processing()
540 if (_hw_reset_event_thread == 0) {
541 g_atomic_int_set(&_hw_reset_request_count, 0);
542 g_atomic_int_set(&_stop_hw_reset_processing, 0);
543 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
546 if (_hw_devicelist_update_thread == 0) {
547 g_atomic_int_set(&_hw_devicelist_update_count, 0);
548 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
549 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
555 AudioEngine::stop_hw_event_processing()
557 if (_hw_reset_event_thread) {
558 g_atomic_int_set(&_stop_hw_reset_processing, 1);
559 g_atomic_int_set(&_hw_reset_request_count, 0);
560 _hw_reset_condition.signal ();
561 _hw_reset_event_thread->join ();
562 _hw_reset_event_thread = 0;
565 if (_hw_devicelist_update_thread) {
566 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
567 g_atomic_int_set(&_hw_devicelist_update_count, 0);
568 _hw_devicelist_update_condition.signal ();
569 _hw_devicelist_update_thread->join ();
570 _hw_devicelist_update_thread = 0;
577 AudioEngine::set_session (Session *s)
579 Glib::Threads::Mutex::Lock pl (_process_lock);
581 SessionHandlePtr::set_session (s);
585 pframes_t blocksize = samples_per_cycle ();
587 PortManager::cycle_start (blocksize);
589 _session->process (blocksize);
590 _session->process (blocksize);
591 _session->process (blocksize);
592 _session->process (blocksize);
593 _session->process (blocksize);
594 _session->process (blocksize);
595 _session->process (blocksize);
596 _session->process (blocksize);
598 PortManager::cycle_end (blocksize);
603 AudioEngine::remove_session ()
605 Glib::Threads::Mutex::Lock lm (_process_lock);
610 session_remove_pending = true;
611 session_removal_countdown = 0;
612 session_removed.wait(_process_lock);
616 SessionHandlePtr::set_session (0);
624 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
626 #ifdef USE_TRACKS_CODE_FEATURES
628 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
637 /* called from a signal handler for SIGPIPE */
642 AudioEngine::reset_timebase ()
645 if (_session->config.get_jack_time_master()) {
646 _backend->set_time_master (true);
648 _backend->set_time_master (false);
656 AudioEngine::destroy ()
663 AudioEngine::discover_backends ()
665 vector<std::string> backend_modules;
669 Glib::PatternSpec so_extension_pattern("*backend.so");
670 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
672 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
673 #if defined(DEBUG) || defined(_DEBUG)
674 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
676 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
679 Glib::PatternSpec dll_extension_pattern("*backend.dll");
682 find_files_matching_pattern (backend_modules, backend_search_path (),
683 so_extension_pattern);
685 find_files_matching_pattern (backend_modules, backend_search_path (),
686 dylib_extension_pattern);
688 find_files_matching_pattern (backend_modules, backend_search_path (),
689 dll_extension_pattern);
691 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
693 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
695 AudioBackendInfo* info;
697 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
699 if ((info = backend_discover (*i)) != 0) {
700 _backends.insert (make_pair (info->name, info));
704 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
706 return _backends.size();
710 AudioEngine::backend_discover (const string& path)
712 #ifdef PLATFORM_WINDOWS
713 // do not show popup dialog (e.g. missing libjack.dll)
714 // win7+ should use SetThreadErrorMode()
715 SetErrorMode(SEM_FAILCRITICALERRORS);
717 Glib::Module module (path);
718 #ifdef PLATFORM_WINDOWS
719 SetErrorMode(0); // reset to system default
721 AudioBackendInfo* info;
722 AudioBackendInfo* (*dfunc)(void);
726 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
727 Glib::Module::get_last_error()) << endmsg;
731 if (!module.get_symbol ("descriptor", func)) {
732 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
733 error << Glib::Module::get_last_error() << endmsg;
737 dfunc = (AudioBackendInfo* (*)(void))func;
739 if (!info->available()) {
743 module.make_resident ();
748 vector<const AudioBackendInfo*>
749 AudioEngine::available_backends() const
751 vector<const AudioBackendInfo*> r;
753 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
754 r.push_back (i->second);
761 AudioEngine::current_backend_name() const
764 return _backend->name();
770 AudioEngine::drop_backend ()
774 _backend->drop_device ();
780 boost::shared_ptr<AudioBackend>
781 AudioEngine::set_default_backend ()
783 if (_backends.empty()) {
784 return boost::shared_ptr<AudioBackend>();
787 return set_backend (_backends.begin()->first, "", "");
790 boost::shared_ptr<AudioBackend>
791 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
793 BackendMap::iterator b = _backends.find (name);
795 if (b == _backends.end()) {
796 return boost::shared_ptr<AudioBackend>();
802 if (b->second->instantiate (arg1, arg2)) {
803 throw failed_constructor ();
806 _backend = b->second->factory (*this);
808 } catch (exception& e) {
809 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
810 return boost::shared_ptr<AudioBackend>();
816 /* BACKEND PROXY WRAPPERS */
819 AudioEngine::start (bool for_latency)
829 _processed_frames = 0;
830 last_monitor_check = 0;
832 if (_backend->start (for_latency)) {
839 _session->set_frame_rate (_backend->sample_rate());
841 if (_session->config.get_jack_time_master()) {
842 _backend->set_time_master (true);
848 Running(); /* EMIT SIGNAL */
855 AudioEngine::stop (bool for_latency)
861 Glib::Threads::Mutex::Lock lm (_process_lock);
863 if (_backend->stop ()) {
867 if (_session && _running &&
868 (_session->state_of_the_state() & Session::Loading) == 0 &&
869 (_session->state_of_the_state() & Session::Deletion) == 0) {
870 // it's not a halt, but should be handled the same way:
871 // disable record, stop transport and I/O processign but save the data.
872 _session->engine_halted ();
876 _processed_frames = 0;
877 _measuring_latency = MeasureNone;
878 _latency_output_port = 0;
879 _latency_input_port = 0;
880 _started_for_latency = false;
885 Stopped (); /* EMIT SIGNAL */
892 AudioEngine::freewheel (bool start_stop)
898 /* _freewheeling will be set when first Freewheel signal occurs */
900 return _backend->freewheel (start_stop);
904 AudioEngine::get_dsp_load() const
909 return _backend->dsp_load ();
913 AudioEngine::is_realtime() const
919 return _backend->is_realtime();
923 AudioEngine::connected() const
929 return _backend->available();
933 AudioEngine::transport_start ()
938 return _backend->transport_start ();
942 AudioEngine::transport_stop ()
947 return _backend->transport_stop ();
951 AudioEngine::transport_state ()
954 return TransportStopped;
956 return _backend->transport_state ();
960 AudioEngine::transport_locate (framepos_t pos)
965 return _backend->transport_locate (pos);
969 AudioEngine::transport_frame()
974 return _backend->transport_frame ();
978 AudioEngine::sample_rate () const
983 return _backend->sample_rate ();
987 AudioEngine::samples_per_cycle () const
992 return _backend->buffer_size ();
996 AudioEngine::usecs_per_cycle () const
1001 return _backend->usecs_per_cycle ();
1005 AudioEngine::raw_buffer_size (DataType t)
1010 return _backend->raw_buffer_size (t);
1014 AudioEngine::sample_time ()
1019 return _backend->sample_time ();
1023 AudioEngine::sample_time_at_cycle_start ()
1028 return _backend->sample_time_at_cycle_start ();
1032 AudioEngine::samples_since_cycle_start ()
1037 return _backend->samples_since_cycle_start ();
1041 AudioEngine::get_sync_offset (pframes_t& offset) const
1046 return _backend->get_sync_offset (offset);
1050 AudioEngine::create_process_thread (boost::function<void()> func)
1055 return _backend->create_process_thread (func);
1059 AudioEngine::join_process_threads ()
1064 return _backend->join_process_threads ();
1068 AudioEngine::in_process_thread ()
1073 return _backend->in_process_thread ();
1077 AudioEngine::process_thread_count ()
1082 return _backend->process_thread_count ();
1086 AudioEngine::set_device_name (const std::string& name)
1091 return _backend->set_device_name (name);
1095 AudioEngine::set_sample_rate (float sr)
1101 return _backend->set_sample_rate (sr);
1105 AudioEngine::set_buffer_size (uint32_t bufsiz)
1110 return _backend->set_buffer_size (bufsiz);
1114 AudioEngine::set_interleaved (bool yn)
1119 return _backend->set_interleaved (yn);
1123 AudioEngine::set_input_channels (uint32_t ic)
1128 return _backend->set_input_channels (ic);
1132 AudioEngine::set_output_channels (uint32_t oc)
1137 return _backend->set_output_channels (oc);
1141 AudioEngine::set_systemic_input_latency (uint32_t il)
1146 return _backend->set_systemic_input_latency (il);
1150 AudioEngine::set_systemic_output_latency (uint32_t ol)
1155 return _backend->set_systemic_output_latency (ol);
1159 AudioEngine::thread_initialised_for_audio_processing ()
1161 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1164 /* END OF BACKEND PROXY API */
1167 AudioEngine::thread_init_callback (void* arg)
1169 /* make sure that anybody who needs to know about this thread
1173 pthread_set_name (X_("audioengine"));
1175 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1177 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1178 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1180 AsyncMIDIPort::set_process_thread (pthread_self());
1183 /* the special thread created/managed by the backend */
1184 AudioEngine::instance()->_main_thread = new ProcessThread;
1189 AudioEngine::sync_callback (TransportState state, framepos_t position)
1192 return _session->backend_sync_callback (state, position);
1198 AudioEngine::freewheel_callback (bool onoff)
1200 _freewheeling = onoff;
1204 AudioEngine::latency_callback (bool for_playback)
1207 _session->update_latency (for_playback);
1212 AudioEngine::update_latencies ()
1215 _backend->update_latencies ();
1220 AudioEngine::halted_callback (const char* why)
1222 if (_in_destructor) {
1223 /* everything is under control */
1229 Port::PortDrop (); /* EMIT SIGNAL */
1231 if (!_started_for_latency) {
1232 Halted (why); /* EMIT SIGNAL */
1237 AudioEngine::setup_required () const
1240 if (_backend->info().already_configured())
1243 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1252 AudioEngine::prepare_for_latency_measurement ()
1255 _stopped_for_latency = true;
1260 _started_for_latency = true;
1268 AudioEngine::start_latency_detection (bool for_midi)
1271 if (prepare_for_latency_measurement ()) {
1276 PortEngine& pe (port_engine());
1284 /* find the ports we will connect to */
1286 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1287 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1294 /* create the ports we will use to read/write data */
1296 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1300 if (pe.connect (_latency_output_port, _latency_output_name)) {
1301 pe.unregister_port (_latency_output_port);
1306 const string portname ("latency_in");
1307 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1308 pe.unregister_port (_latency_input_port);
1309 pe.unregister_port (_latency_output_port);
1313 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1314 pe.unregister_port (_latency_input_port);
1315 pe.unregister_port (_latency_output_port);
1320 _mididm = new MIDIDM (sample_rate());
1324 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1328 if (pe.connect (_latency_output_port, _latency_output_name)) {
1329 pe.unregister_port (_latency_output_port);
1334 const string portname ("latency_in");
1335 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1336 pe.unregister_port (_latency_input_port);
1337 pe.unregister_port (_latency_output_port);
1341 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1342 pe.unregister_port (_latency_input_port);
1343 pe.unregister_port (_latency_output_port);
1348 _mtdm = new MTDM (sample_rate());
1353 _latency_signal_latency = 0;
1354 lr = pe.get_latency_range (in, false);
1355 _latency_signal_latency = lr.max;
1356 lr = pe.get_latency_range (out, true);
1357 _latency_signal_latency += lr.max;
1359 /* all created and connected, lets go */
1360 _latency_flush_frames = samples_per_cycle();
1361 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1367 AudioEngine::stop_latency_detection ()
1369 _measuring_latency = MeasureNone;
1371 if (_latency_output_port) {
1372 port_engine().unregister_port (_latency_output_port);
1373 _latency_output_port = 0;
1375 if (_latency_input_port) {
1376 port_engine().unregister_port (_latency_input_port);
1377 _latency_input_port = 0;
1382 if (_stopped_for_latency) {
1386 _stopped_for_latency = false;
1387 _started_for_latency = false;
1391 AudioEngine::set_latency_output_port (const string& name)
1393 _latency_output_name = name;
1397 AudioEngine::set_latency_input_port (const string& name)
1399 _latency_input_name = name;