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 _processed_frames = next_processed_frames;
212 bool return_after_remove_check = false;
214 if (_measuring_latency == MeasureAudio && _mtdm) {
215 /* run a normal cycle from the perspective of the PortManager
216 so that we get silence on all registered ports.
218 we overwrite the silence on the two ports used for latency
222 PortManager::cycle_start (nframes);
223 PortManager::silence (nframes);
225 if (_latency_input_port && _latency_output_port) {
226 PortEngine& pe (port_engine());
228 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
229 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
231 _mtdm->process (nframes, in, out);
234 PortManager::cycle_end (nframes);
235 return_after_remove_check = true;
237 } else if (_measuring_latency == MeasureMIDI && _mididm) {
238 /* run a normal cycle from the perspective of the PortManager
239 so that we get silence on all registered ports.
241 we overwrite the silence on the two ports used for latency
245 PortManager::cycle_start (nframes);
246 PortManager::silence (nframes);
248 if (_latency_input_port && _latency_output_port) {
249 PortEngine& pe (port_engine());
251 _mididm->process (nframes, pe,
252 pe.get_buffer (_latency_input_port, nframes),
253 pe.get_buffer (_latency_output_port, nframes));
256 PortManager::cycle_end (nframes);
257 return_after_remove_check = true;
259 } else if (_latency_flush_frames) {
261 /* wait for the appropriate duration for the MTDM signal to
262 * drain from the ports before we revert to normal behaviour.
265 PortManager::cycle_start (nframes);
266 PortManager::silence (nframes);
267 PortManager::cycle_end (nframes);
269 if (_latency_flush_frames > nframes) {
270 _latency_flush_frames -= nframes;
272 _latency_flush_frames = 0;
275 return_after_remove_check = true;
278 if (session_remove_pending) {
280 /* perform the actual session removal */
282 if (session_removal_countdown < 0) {
284 /* fade out over 1 second */
285 session_removal_countdown = sample_rate()/2;
286 session_removal_gain = GAIN_COEFF_UNITY;
287 session_removal_gain_step = 1.0/session_removal_countdown;
289 } else if (session_removal_countdown > 0) {
291 /* we'll be fading audio out.
293 if this is the last time we do this as part
294 of session removal, do a MIDI panic now
295 to get MIDI stopped. This relies on the fact
296 that "immediate data" (aka "out of band data") from
297 MIDI tracks is *appended* after any other data,
298 so that it emerges after any outbound note ons, etc.
301 if (session_removal_countdown <= nframes) {
302 _session->midi_panic ();
308 session_removal_countdown = -1; // reset to "not in progress"
309 session_remove_pending = false;
310 session_removed.signal(); // wakes up thread that initiated session removal
314 if (return_after_remove_check) {
320 if (!_freewheeling) {
321 PortManager::cycle_start (nframes);
322 PortManager::cycle_end (nframes);
325 _processed_frames = next_processed_frames;
330 /* tell all relevant objects that we're starting a new cycle */
332 InternalSend::CycleStart (nframes);
334 /* tell all Ports that we're starting a new cycle */
336 PortManager::cycle_start (nframes);
338 /* test if we are freewheeling and there are freewheel signals connected.
339 ardour should act normally even when freewheeling unless /it/ is
340 exporting (which is what Freewheel.empty() tests for).
343 if (_freewheeling && !Freewheel.empty()) {
346 _session->process (nframes);
350 PortManager::cycle_end (nframes);
355 _processed_frames = next_processed_frames;
359 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
361 PortManager::check_monitoring ();
362 last_monitor_check = next_processed_frames;
365 #ifdef SILENCE_AFTER_SECONDS
367 bool was_silent = (_silence_countdown == 0);
369 if (_silence_countdown >= nframes) {
370 _silence_countdown -= nframes;
372 _silence_countdown = 0;
375 if (!was_silent && _silence_countdown == 0) {
377 BecameSilent (); /* EMIT SIGNAL */
380 if (_silence_countdown == 0 || _session->silent()) {
381 PortManager::silence (nframes);
385 if (_session->silent()) {
386 PortManager::silence (nframes);
390 if (session_remove_pending && session_removal_countdown) {
392 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
394 if (session_removal_countdown > nframes) {
395 session_removal_countdown -= nframes;
397 session_removal_countdown = 0;
400 session_removal_gain -= (nframes * session_removal_gain_step);
403 PortManager::cycle_end (nframes);
405 _processed_frames = next_processed_frames;
413 AudioEngine::reset_silence_countdown ()
415 #ifdef SILENCE_AFTER_SECONDS
416 double sr = 48000; /* default in case there is no backend */
420 _silence_countdown = max (60 * sr, /* 60 seconds */
421 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
427 AudioEngine::launch_device_control_app()
429 if (_state_lock.trylock () ) {
430 _backend->launch_control_app ();
431 _state_lock.unlock ();
437 AudioEngine::request_backend_reset()
439 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
440 g_atomic_int_inc (&_hw_reset_request_count);
441 _hw_reset_condition.signal ();
445 AudioEngine::backend_reset_requested()
447 return g_atomic_int_get (&_hw_reset_request_count);
451 AudioEngine::do_reset_backend()
453 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
455 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
457 while (!_stop_hw_reset_processing) {
459 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
461 _reset_request_lock.unlock();
463 Glib::Threads::RecMutex::Lock pl (_state_lock);
464 g_atomic_int_dec_and_test (&_hw_reset_request_count);
466 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
467 DeviceResetStarted(); // notify about device reset to be started
469 // backup the device name
470 std::string name = _backend->device_name ();
472 std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
475 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
476 if ( 0 == _backend->reset_device () ) {
478 std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
481 // inform about possible changes
482 BufferSizeChanged (_backend->buffer_size() );
487 std::cout << "AudioEngine::RESET::Done." << std::endl;
489 _reset_request_lock.lock();
493 _hw_reset_condition.wait (_reset_request_lock);
499 AudioEngine::request_device_list_update()
501 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
502 g_atomic_int_inc (&_hw_devicelist_update_count);
503 _hw_devicelist_update_condition.signal ();
508 AudioEngine::do_devicelist_update()
510 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
512 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
514 while (!_stop_hw_devicelist_processing) {
516 if (_hw_devicelist_update_count) {
518 _devicelist_update_lock.unlock();
520 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
521 DeviceListChanged (); /* EMIT SIGNAL */
523 _devicelist_update_lock.lock();
526 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
533 AudioEngine::start_hw_event_processing()
535 if (_hw_reset_event_thread == 0) {
536 g_atomic_int_set(&_hw_reset_request_count, 0);
537 g_atomic_int_set(&_stop_hw_reset_processing, 0);
538 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
541 if (_hw_devicelist_update_thread == 0) {
542 g_atomic_int_set(&_hw_devicelist_update_count, 0);
543 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
544 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
550 AudioEngine::stop_hw_event_processing()
552 if (_hw_reset_event_thread) {
553 g_atomic_int_set(&_stop_hw_reset_processing, 1);
554 g_atomic_int_set(&_hw_reset_request_count, 0);
555 _hw_reset_condition.signal ();
556 _hw_reset_event_thread->join ();
557 _hw_reset_event_thread = 0;
560 if (_hw_devicelist_update_thread) {
561 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
562 g_atomic_int_set(&_hw_devicelist_update_count, 0);
563 _hw_devicelist_update_condition.signal ();
564 _hw_devicelist_update_thread->join ();
565 _hw_devicelist_update_thread = 0;
572 AudioEngine::set_session (Session *s)
574 Glib::Threads::Mutex::Lock pl (_process_lock);
576 SessionHandlePtr::set_session (s);
580 pframes_t blocksize = samples_per_cycle ();
582 PortManager::cycle_start (blocksize);
584 _session->process (blocksize);
585 _session->process (blocksize);
586 _session->process (blocksize);
587 _session->process (blocksize);
588 _session->process (blocksize);
589 _session->process (blocksize);
590 _session->process (blocksize);
591 _session->process (blocksize);
593 PortManager::cycle_end (blocksize);
598 AudioEngine::remove_session ()
600 Glib::Threads::Mutex::Lock lm (_process_lock);
605 session_remove_pending = true;
606 session_removal_countdown = 0;
607 session_removed.wait(_process_lock);
611 SessionHandlePtr::set_session (0);
619 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
622 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
630 /* called from a signal handler for SIGPIPE */
635 AudioEngine::reset_timebase ()
638 if (_session->config.get_jack_time_master()) {
639 _backend->set_time_master (true);
641 _backend->set_time_master (false);
649 AudioEngine::destroy ()
656 AudioEngine::discover_backends ()
658 vector<std::string> backend_modules;
662 Glib::PatternSpec so_extension_pattern("*backend.so");
663 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
665 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
666 #if defined(DEBUG) || defined(_DEBUG)
667 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
669 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
672 Glib::PatternSpec dll_extension_pattern("*backend.dll");
675 find_files_matching_pattern (backend_modules, backend_search_path (),
676 so_extension_pattern);
678 find_files_matching_pattern (backend_modules, backend_search_path (),
679 dylib_extension_pattern);
681 find_files_matching_pattern (backend_modules, backend_search_path (),
682 dll_extension_pattern);
684 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
686 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
688 AudioBackendInfo* info;
690 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
692 if ((info = backend_discover (*i)) != 0) {
693 _backends.insert (make_pair (info->name, info));
697 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
699 return _backends.size();
703 AudioEngine::backend_discover (const string& path)
705 #ifdef PLATFORM_WINDOWS
706 // do not show popup dialog (e.g. missing libjack.dll)
707 // win7+ should use SetThreadErrorMode()
708 SetErrorMode(SEM_FAILCRITICALERRORS);
710 Glib::Module module (path);
711 #ifdef PLATFORM_WINDOWS
712 SetErrorMode(0); // reset to system default
714 AudioBackendInfo* info;
715 AudioBackendInfo* (*dfunc)(void);
719 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
720 Glib::Module::get_last_error()) << endmsg;
724 if (!module.get_symbol ("descriptor", func)) {
725 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
726 error << Glib::Module::get_last_error() << endmsg;
730 dfunc = (AudioBackendInfo* (*)(void))func;
732 if (!info->available()) {
736 module.make_resident ();
741 vector<const AudioBackendInfo*>
742 AudioEngine::available_backends() const
744 vector<const AudioBackendInfo*> r;
746 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
747 r.push_back (i->second);
754 AudioEngine::current_backend_name() const
757 return _backend->name();
763 AudioEngine::drop_backend ()
767 _backend->drop_device ();
773 boost::shared_ptr<AudioBackend>
774 AudioEngine::set_default_backend ()
776 if (_backends.empty()) {
777 return boost::shared_ptr<AudioBackend>();
780 return set_backend (_backends.begin()->first, "", "");
783 boost::shared_ptr<AudioBackend>
784 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
786 BackendMap::iterator b = _backends.find (name);
788 if (b == _backends.end()) {
789 return boost::shared_ptr<AudioBackend>();
795 if (b->second->instantiate (arg1, arg2)) {
796 throw failed_constructor ();
799 _backend = b->second->factory (*this);
801 } catch (exception& e) {
802 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
803 return boost::shared_ptr<AudioBackend>();
809 /* BACKEND PROXY WRAPPERS */
812 AudioEngine::start (bool for_latency)
822 _processed_frames = 0;
823 last_monitor_check = 0;
825 if (_backend->start (for_latency)) {
832 _session->set_frame_rate (_backend->sample_rate());
834 if (_session->config.get_jack_time_master()) {
835 _backend->set_time_master (true);
841 Running(); /* EMIT SIGNAL */
848 AudioEngine::stop (bool for_latency)
854 if (_session && _running) {
855 // it's not a halt, but should be handled the same way:
856 // disable record, stop transport and I/O processign but save the data.
857 _session->engine_halted ();
860 Glib::Threads::Mutex::Lock lm (_process_lock);
862 if (_backend->stop ()) {
867 _processed_frames = 0;
868 _measuring_latency = MeasureNone;
869 _latency_output_port = 0;
870 _latency_input_port = 0;
871 _started_for_latency = false;
876 Stopped (); /* EMIT SIGNAL */
883 AudioEngine::freewheel (bool start_stop)
889 /* _freewheeling will be set when first Freewheel signal occurs */
891 return _backend->freewheel (start_stop);
895 AudioEngine::get_dsp_load() const
900 return _backend->dsp_load ();
904 AudioEngine::is_realtime() const
910 return _backend->is_realtime();
914 AudioEngine::connected() const
920 return _backend->available();
924 AudioEngine::transport_start ()
929 return _backend->transport_start ();
933 AudioEngine::transport_stop ()
938 return _backend->transport_stop ();
942 AudioEngine::transport_state ()
945 return TransportStopped;
947 return _backend->transport_state ();
951 AudioEngine::transport_locate (framepos_t pos)
956 return _backend->transport_locate (pos);
960 AudioEngine::transport_frame()
965 return _backend->transport_frame ();
969 AudioEngine::sample_rate () const
974 return _backend->sample_rate ();
978 AudioEngine::samples_per_cycle () const
983 return _backend->buffer_size ();
987 AudioEngine::usecs_per_cycle () const
992 return _backend->usecs_per_cycle ();
996 AudioEngine::raw_buffer_size (DataType t)
1001 return _backend->raw_buffer_size (t);
1005 AudioEngine::sample_time ()
1010 return _backend->sample_time ();
1014 AudioEngine::sample_time_at_cycle_start ()
1019 return _backend->sample_time_at_cycle_start ();
1023 AudioEngine::samples_since_cycle_start ()
1028 return _backend->samples_since_cycle_start ();
1032 AudioEngine::get_sync_offset (pframes_t& offset) const
1037 return _backend->get_sync_offset (offset);
1041 AudioEngine::create_process_thread (boost::function<void()> func)
1046 return _backend->create_process_thread (func);
1050 AudioEngine::join_process_threads ()
1055 return _backend->join_process_threads ();
1059 AudioEngine::in_process_thread ()
1064 return _backend->in_process_thread ();
1068 AudioEngine::process_thread_count ()
1073 return _backend->process_thread_count ();
1077 AudioEngine::set_device_name (const std::string& name)
1082 return _backend->set_device_name (name);
1086 AudioEngine::set_sample_rate (float sr)
1092 return _backend->set_sample_rate (sr);
1096 AudioEngine::set_buffer_size (uint32_t bufsiz)
1101 return _backend->set_buffer_size (bufsiz);
1105 AudioEngine::set_interleaved (bool yn)
1110 return _backend->set_interleaved (yn);
1114 AudioEngine::set_input_channels (uint32_t ic)
1119 return _backend->set_input_channels (ic);
1123 AudioEngine::set_output_channels (uint32_t oc)
1128 return _backend->set_output_channels (oc);
1132 AudioEngine::set_systemic_input_latency (uint32_t il)
1137 return _backend->set_systemic_input_latency (il);
1141 AudioEngine::set_systemic_output_latency (uint32_t ol)
1146 return _backend->set_systemic_output_latency (ol);
1149 /* END OF BACKEND PROXY API */
1152 AudioEngine::thread_init_callback (void* arg)
1154 /* make sure that anybody who needs to know about this thread
1158 pthread_set_name (X_("audioengine"));
1160 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1162 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1163 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1165 AsyncMIDIPort::set_process_thread (pthread_self());
1168 /* the special thread created/managed by the backend */
1169 AudioEngine::instance()->_main_thread = new ProcessThread;
1174 AudioEngine::sync_callback (TransportState state, framepos_t position)
1177 return _session->backend_sync_callback (state, position);
1183 AudioEngine::freewheel_callback (bool onoff)
1185 _freewheeling = onoff;
1189 AudioEngine::latency_callback (bool for_playback)
1192 _session->update_latency (for_playback);
1197 AudioEngine::update_latencies ()
1200 _backend->update_latencies ();
1205 AudioEngine::halted_callback (const char* why)
1207 if (_in_destructor) {
1208 /* everything is under control */
1214 Port::PortDrop (); /* EMIT SIGNAL */
1216 if (!_started_for_latency) {
1217 Halted (why); /* EMIT SIGNAL */
1222 AudioEngine::setup_required () const
1225 if (_backend->info().already_configured())
1228 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1237 AudioEngine::prepare_for_latency_measurement ()
1240 _stopped_for_latency = true;
1245 _started_for_latency = true;
1253 AudioEngine::start_latency_detection (bool for_midi)
1256 if (prepare_for_latency_measurement ()) {
1261 PortEngine& pe (port_engine());
1269 /* find the ports we will connect to */
1271 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1272 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1279 /* create the ports we will use to read/write data */
1281 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1285 if (pe.connect (_latency_output_port, _latency_output_name)) {
1286 pe.unregister_port (_latency_output_port);
1291 const string portname ("latency_in");
1292 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1293 pe.unregister_port (_latency_input_port);
1294 pe.unregister_port (_latency_output_port);
1298 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1299 pe.unregister_port (_latency_input_port);
1300 pe.unregister_port (_latency_output_port);
1305 _mididm = new MIDIDM (sample_rate());
1309 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1313 if (pe.connect (_latency_output_port, _latency_output_name)) {
1314 pe.unregister_port (_latency_output_port);
1319 const string portname ("latency_in");
1320 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1321 pe.unregister_port (_latency_input_port);
1322 pe.unregister_port (_latency_output_port);
1326 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1327 pe.unregister_port (_latency_input_port);
1328 pe.unregister_port (_latency_output_port);
1333 _mtdm = new MTDM (sample_rate());
1338 _latency_signal_latency = 0;
1339 lr = pe.get_latency_range (in, false);
1340 _latency_signal_latency = lr.max;
1341 lr = pe.get_latency_range (out, true);
1342 _latency_signal_latency += lr.max;
1344 /* all created and connected, lets go */
1345 _latency_flush_frames = samples_per_cycle();
1346 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1352 AudioEngine::stop_latency_detection ()
1354 _measuring_latency = MeasureNone;
1356 if (_latency_output_port) {
1357 port_engine().unregister_port (_latency_output_port);
1358 _latency_output_port = 0;
1360 if (_latency_input_port) {
1361 port_engine().unregister_port (_latency_input_port);
1362 _latency_input_port = 0;
1367 if (_stopped_for_latency) {
1371 _stopped_for_latency = false;
1372 _started_for_latency = false;
1376 AudioEngine::set_latency_output_port (const string& name)
1378 _latency_output_name = name;
1382 AudioEngine::set_latency_input_port (const string& name)
1384 _latency_input_name = name;