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.
27 #include <glibmm/timer.h>
28 #include <glibmm/pattern.h>
29 #include <glibmm/module.h>
32 #include "pbd/file_utils.h"
33 #include "pbd/pthread_utils.h"
34 #include "pbd/stacktrace.h"
35 #include "pbd/unknown_type.h"
37 #include "midi++/port.h"
38 #include "midi++/mmc.h"
40 #include "ardour/async_midi_port.h"
41 #include "ardour/audio_port.h"
42 #include "ardour/audio_backend.h"
43 #include "ardour/audioengine.h"
44 #include "ardour/search_paths.h"
45 #include "ardour/buffer.h"
46 #include "ardour/cycle_timer.h"
47 #include "ardour/internal_send.h"
48 #include "ardour/meter.h"
49 #include "ardour/midi_port.h"
50 #include "ardour/midiport_manager.h"
51 #include "ardour/mididm.h"
52 #include "ardour/mtdm.h"
53 #include "ardour/port.h"
54 #include "ardour/process_thread.h"
55 #include "ardour/session.h"
60 using namespace ARDOUR;
63 gint AudioEngine::m_meter_exit;
64 AudioEngine* AudioEngine::_instance = 0;
66 AudioEngine::AudioEngine ()
67 : session_remove_pending (false)
68 , session_removal_countdown (-1)
70 , _freewheeling (false)
71 , monitor_check_interval (INT32_MAX)
72 , last_monitor_check (0)
73 , _processed_frames (0)
78 , _measuring_latency (MeasureNone)
79 , _latency_input_port (0)
80 , _latency_output_port (0)
81 , _latency_flush_frames (0)
82 , _latency_signal_latency (0)
83 , _stopped_for_latency (false)
84 , _started_for_latency (false)
85 , _in_destructor (false)
86 , _hw_reset_event_thread(0)
87 , _hw_reset_request_count(0)
88 , _stop_hw_reset_processing(0)
89 , _hw_devicelist_update_thread(0)
90 , _hw_devicelist_update_count(0)
91 , _stop_hw_devicelist_processing(0)
93 g_atomic_int_set (&m_meter_exit, 0);
94 start_hw_event_processing();
98 AudioEngine::~AudioEngine ()
100 _in_destructor = true;
101 stop_metering_thread ();
102 stop_hw_event_processing();
107 AudioEngine::create ()
113 _instance = new AudioEngine ();
119 _thread_init_callback (void * /*arg*/)
121 /* make sure that anybody who needs to know about this thread
125 pthread_set_name (X_("audioengine"));
127 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096);
128 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128);
130 SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
132 AsyncMIDIPort::set_process_thread (pthread_self());
136 AudioEngine::split_cycle (pframes_t offset)
138 /* caller must hold process lock */
140 Port::increment_global_port_buffer_offset (offset);
142 /* tell all Ports that we're going to start a new (split) cycle */
144 boost::shared_ptr<Ports> p = ports.reader();
146 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
147 i->second->cycle_split ();
152 AudioEngine::sample_rate_change (pframes_t nframes)
154 /* check for monitor input change every 1/10th of second */
156 monitor_check_interval = nframes / 10;
157 last_monitor_check = 0;
160 _session->set_frame_rate (nframes);
163 SampleRateChanged (nframes); /* EMIT SIGNAL */
169 AudioEngine::buffer_size_change (pframes_t bufsiz)
172 _session->set_block_size (bufsiz);
173 last_monitor_check = 0;
176 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
181 /** Method called by our ::process_thread when there is work to be done.
182 * @param nframes Number of frames to process.
185 __attribute__((annotate("realtime")))
188 AudioEngine::process_callback (pframes_t nframes)
190 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
195 /// The number of frames that will have been processed when we've finished
196 pframes_t next_processed_frames;
198 /* handle wrap around of total frames counter */
200 if (max_framepos - _processed_frames < nframes) {
201 next_processed_frames = nframes - (max_framepos - _processed_frames);
203 next_processed_frames = _processed_frames + nframes;
207 /* 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 = 1.0;
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()) {
347 _session->process (nframes);
356 _processed_frames = next_processed_frames;
360 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
362 PortManager::check_monitoring ();
363 last_monitor_check = next_processed_frames;
366 if (_session->silent()) {
367 PortManager::silence (nframes);
370 if (session_remove_pending && session_removal_countdown) {
372 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
374 if (session_removal_countdown > nframes) {
375 session_removal_countdown -= nframes;
377 session_removal_countdown = 0;
380 session_removal_gain -= (nframes * session_removal_gain_step);
383 PortManager::cycle_end (nframes);
385 _processed_frames = next_processed_frames;
394 AudioEngine::request_backend_reset()
396 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
397 g_atomic_int_inc (&_hw_reset_request_count);
398 _hw_reset_condition.signal ();
403 AudioEngine::do_reset_backend()
405 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
407 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
409 while (!_stop_hw_reset_processing) {
411 if (_hw_reset_request_count && _backend) {
413 _reset_request_lock.unlock();
415 Glib::Threads::RecMutex::Lock pl (_state_lock);
417 g_atomic_int_dec_and_test (&_hw_reset_request_count);
419 std::cout << "AudioEngine::RESET::Reset request processing" << std::endl;
421 // backup the device name
422 std::string name = _backend->device_name ();
424 std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
427 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
428 if ( 0 == _backend->reset_device () ) {
430 std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
433 // inform about possible changes
434 BufferSizeChanged (_backend->buffer_size() );
439 std::cout << "AudioEngine::RESET::Done." << std::endl;
441 _reset_request_lock.lock();
445 _hw_reset_condition.wait (_reset_request_lock);
453 AudioEngine::request_device_list_update()
455 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
456 g_atomic_int_inc (&_hw_devicelist_update_count);
457 _hw_devicelist_update_condition.signal ();
462 AudioEngine::do_devicelist_update()
464 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
466 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
468 while (!_stop_hw_devicelist_processing) {
470 if (_hw_devicelist_update_count) {
472 _devicelist_update_lock.unlock();
474 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
475 DeviceListChanged (); /* EMIT SIGNAL */
477 _devicelist_update_lock.lock();
480 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
487 AudioEngine::start_hw_event_processing()
489 if (_hw_reset_event_thread == 0) {
490 g_atomic_int_set(&_hw_reset_request_count, 0);
491 g_atomic_int_set(&_stop_hw_reset_processing, 0);
492 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
495 if (_hw_devicelist_update_thread == 0) {
496 g_atomic_int_set(&_hw_devicelist_update_count, 0);
497 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
498 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
504 AudioEngine::stop_hw_event_processing()
506 if (_hw_reset_event_thread) {
507 g_atomic_int_set(&_stop_hw_reset_processing, 1);
508 g_atomic_int_set(&_hw_reset_request_count, 0);
509 _hw_reset_condition.signal ();
510 _hw_reset_event_thread->join ();
511 _hw_reset_event_thread = 0;
514 if (_hw_devicelist_update_thread) {
515 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
516 g_atomic_int_set(&_hw_devicelist_update_count, 0);
517 _hw_devicelist_update_condition.signal ();
518 _hw_devicelist_update_thread->join ();
519 _hw_devicelist_update_thread = 0;
527 AudioEngine::stop_metering_thread ()
529 if (m_meter_thread) {
530 g_atomic_int_set (&m_meter_exit, 1);
531 m_meter_thread->join ();
537 AudioEngine::start_metering_thread ()
539 if (m_meter_thread == 0) {
540 g_atomic_int_set (&m_meter_exit, 0);
541 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
546 AudioEngine::meter_thread ()
548 pthread_set_name (X_("meter"));
551 Glib::usleep (10000); /* 1/100th sec interval */
552 if (g_atomic_int_get(&m_meter_exit)) {
560 AudioEngine::set_session (Session *s)
562 Glib::Threads::Mutex::Lock pl (_process_lock);
564 SessionHandlePtr::set_session (s);
568 pframes_t blocksize = samples_per_cycle ();
570 PortManager::cycle_start (blocksize);
572 _session->process (blocksize);
573 _session->process (blocksize);
574 _session->process (blocksize);
575 _session->process (blocksize);
576 _session->process (blocksize);
577 _session->process (blocksize);
578 _session->process (blocksize);
579 _session->process (blocksize);
581 PortManager::cycle_end (blocksize);
586 AudioEngine::remove_session ()
588 Glib::Threads::Mutex::Lock lm (_process_lock);
593 session_remove_pending = true;
594 session_removal_countdown = 0;
595 session_removed.wait(_process_lock);
599 SessionHandlePtr::set_session (0);
607 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
610 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
618 /* called from a signal handler for SIGPIPE */
620 stop_metering_thread ();
626 AudioEngine::reset_timebase ()
629 if (_session->config.get_jack_time_master()) {
630 _backend->set_time_master (true);
632 _backend->set_time_master (false);
640 AudioEngine::destroy ()
647 AudioEngine::discover_backends ()
649 vector<std::string> backend_modules;
653 Glib::PatternSpec so_extension_pattern("*backend.so");
654 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
656 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
657 #if defined(DEBUG) || defined(_DEBUG)
658 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
660 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
663 Glib::PatternSpec dll_extension_pattern("*backend.dll");
666 find_files_matching_pattern (backend_modules, backend_search_path (),
667 so_extension_pattern);
669 find_files_matching_pattern (backend_modules, backend_search_path (),
670 dylib_extension_pattern);
672 find_files_matching_pattern (backend_modules, backend_search_path (),
673 dll_extension_pattern);
675 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
677 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
679 AudioBackendInfo* info;
681 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
683 if ((info = backend_discover (*i)) != 0) {
684 _backends.insert (make_pair (info->name, info));
688 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
690 return _backends.size();
694 AudioEngine::backend_discover (const string& path)
696 #ifdef PLATFORM_WINDOWS
697 // do not show popup dialog (e.g. missing libjack.dll)
698 // win7+ should use SetThreadErrorMode()
699 SetErrorMode(SEM_FAILCRITICALERRORS);
701 Glib::Module module (path);
702 #ifdef PLATFORM_WINDOWS
703 SetErrorMode(0); // reset to system default
705 AudioBackendInfo* info;
706 AudioBackendInfo* (*dfunc)(void);
710 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
711 Glib::Module::get_last_error()) << endmsg;
715 if (!module.get_symbol ("descriptor", func)) {
716 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
717 error << Glib::Module::get_last_error() << endmsg;
721 module.make_resident ();
723 dfunc = (AudioBackendInfo* (*)(void))func;
729 vector<const AudioBackendInfo*>
730 AudioEngine::available_backends() const
732 vector<const AudioBackendInfo*> r;
734 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
735 r.push_back (i->second);
742 AudioEngine::current_backend_name() const
745 return _backend->name();
751 AudioEngine::drop_backend ()
755 _backend->drop_device ();
761 boost::shared_ptr<AudioBackend>
762 AudioEngine::set_default_backend ()
764 if (_backends.empty()) {
765 return boost::shared_ptr<AudioBackend>();
768 return set_backend (_backends.begin()->first, "", "");
771 boost::shared_ptr<AudioBackend>
772 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
774 BackendMap::iterator b = _backends.find (name);
776 if (b == _backends.end()) {
777 return boost::shared_ptr<AudioBackend>();
783 if (b->second->instantiate (arg1, arg2)) {
784 throw failed_constructor ();
787 _backend = b->second->factory (*this);
789 } catch (exception& e) {
790 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
791 return boost::shared_ptr<AudioBackend>();
797 /* BACKEND PROXY WRAPPERS */
800 AudioEngine::start (bool for_latency)
810 _processed_frames = 0;
811 last_monitor_check = 0;
813 if (_backend->start (for_latency)) {
820 _session->set_frame_rate (_backend->sample_rate());
822 if (_session->config.get_jack_time_master()) {
823 _backend->set_time_master (true);
828 start_metering_thread ();
831 Running(); /* EMIT SIGNAL */
838 AudioEngine::stop (bool for_latency)
844 if (_session && _running) {
845 // it's not a halt, but should be handled the same way:
846 // disable record, stop transport and I/O processign but save the data.
847 _session->engine_halted ();
850 Glib::Threads::Mutex::Lock lm (_process_lock);
852 if (_backend->stop ()) {
857 _processed_frames = 0;
858 _measuring_latency = MeasureNone;
859 _latency_output_port = 0;
860 _latency_input_port = 0;
861 _started_for_latency = false;
862 stop_metering_thread ();
867 Stopped (); /* EMIT SIGNAL */
874 AudioEngine::freewheel (bool start_stop)
880 /* _freewheeling will be set when first Freewheel signal occurs */
882 return _backend->freewheel (start_stop);
886 AudioEngine::get_dsp_load() const
891 return _backend->dsp_load ();
895 AudioEngine::is_realtime() const
901 return _backend->is_realtime();
905 AudioEngine::connected() const
911 return _backend->available();
915 AudioEngine::transport_start ()
920 return _backend->transport_start ();
924 AudioEngine::transport_stop ()
929 return _backend->transport_stop ();
933 AudioEngine::transport_state ()
936 return TransportStopped;
938 return _backend->transport_state ();
942 AudioEngine::transport_locate (framepos_t pos)
947 return _backend->transport_locate (pos);
951 AudioEngine::transport_frame()
956 return _backend->transport_frame ();
960 AudioEngine::sample_rate () const
965 return _backend->sample_rate ();
969 AudioEngine::samples_per_cycle () const
974 return _backend->buffer_size ();
978 AudioEngine::usecs_per_cycle () const
983 return _backend->usecs_per_cycle ();
987 AudioEngine::raw_buffer_size (DataType t)
992 return _backend->raw_buffer_size (t);
996 AudioEngine::sample_time ()
1001 return _backend->sample_time ();
1005 AudioEngine::sample_time_at_cycle_start ()
1010 return _backend->sample_time_at_cycle_start ();
1014 AudioEngine::samples_since_cycle_start ()
1019 return _backend->samples_since_cycle_start ();
1023 AudioEngine::get_sync_offset (pframes_t& offset) const
1028 return _backend->get_sync_offset (offset);
1032 AudioEngine::create_process_thread (boost::function<void()> func)
1037 return _backend->create_process_thread (func);
1041 AudioEngine::join_process_threads ()
1046 return _backend->join_process_threads ();
1050 AudioEngine::in_process_thread ()
1055 return _backend->in_process_thread ();
1059 AudioEngine::process_thread_count ()
1064 return _backend->process_thread_count ();
1068 AudioEngine::set_device_name (const std::string& name)
1073 return _backend->set_device_name (name);
1077 AudioEngine::set_sample_rate (float sr)
1082 return _backend->set_sample_rate (sr);
1086 AudioEngine::set_buffer_size (uint32_t bufsiz)
1091 return _backend->set_buffer_size (bufsiz);
1095 AudioEngine::set_interleaved (bool yn)
1100 return _backend->set_interleaved (yn);
1104 AudioEngine::set_input_channels (uint32_t ic)
1109 return _backend->set_input_channels (ic);
1113 AudioEngine::set_output_channels (uint32_t oc)
1118 return _backend->set_output_channels (oc);
1122 AudioEngine::set_systemic_input_latency (uint32_t il)
1127 return _backend->set_systemic_input_latency (il);
1131 AudioEngine::set_systemic_output_latency (uint32_t ol)
1136 return _backend->set_systemic_output_latency (ol);
1139 /* END OF BACKEND PROXY API */
1142 AudioEngine::thread_init_callback (void* arg)
1144 /* make sure that anybody who needs to know about this thread
1148 pthread_set_name (X_("audioengine"));
1150 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1151 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1153 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1155 AsyncMIDIPort::set_process_thread (pthread_self());
1158 /* the special thread created/managed by the backend */
1159 AudioEngine::instance()->_main_thread = new ProcessThread;
1164 AudioEngine::sync_callback (TransportState state, framepos_t position)
1167 return _session->backend_sync_callback (state, position);
1173 AudioEngine::freewheel_callback (bool onoff)
1175 _freewheeling = onoff;
1179 AudioEngine::latency_callback (bool for_playback)
1182 _session->update_latency (for_playback);
1187 AudioEngine::update_latencies ()
1190 _backend->update_latencies ();
1195 AudioEngine::halted_callback (const char* why)
1197 if (_in_destructor) {
1198 /* everything is under control */
1202 stop_metering_thread ();
1205 Port::PortDrop (); /* EMIT SIGNAL */
1207 if (!_started_for_latency) {
1208 Halted (why); /* EMIT SIGNAL */
1213 AudioEngine::setup_required () const
1216 if (_backend->info().already_configured())
1219 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1228 AudioEngine::prepare_for_latency_measurement ()
1231 _stopped_for_latency = true;
1236 _started_for_latency = true;
1244 AudioEngine::start_latency_detection (bool for_midi)
1247 if (prepare_for_latency_measurement ()) {
1252 PortEngine& pe (port_engine());
1260 /* find the ports we will connect to */
1262 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1263 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1270 /* create the ports we will use to read/write data */
1272 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1276 if (pe.connect (_latency_output_port, _latency_output_name)) {
1277 pe.unregister_port (_latency_output_port);
1282 const string portname ("latency_in");
1283 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1284 pe.unregister_port (_latency_input_port);
1285 pe.unregister_port (_latency_output_port);
1289 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1290 pe.unregister_port (_latency_input_port);
1291 pe.unregister_port (_latency_output_port);
1296 _mididm = new MIDIDM (sample_rate());
1300 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1304 if (pe.connect (_latency_output_port, _latency_output_name)) {
1305 pe.unregister_port (_latency_output_port);
1310 const string portname ("latency_in");
1311 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1312 pe.unregister_port (_latency_input_port);
1313 pe.unregister_port (_latency_output_port);
1317 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1318 pe.unregister_port (_latency_input_port);
1319 pe.unregister_port (_latency_output_port);
1324 _mtdm = new MTDM (sample_rate());
1329 _latency_signal_latency = 0;
1330 lr = pe.get_latency_range (in, false);
1331 _latency_signal_latency = lr.max;
1332 lr = pe.get_latency_range (out, true);
1333 _latency_signal_latency += lr.max;
1335 /* all created and connected, lets go */
1336 _latency_flush_frames = samples_per_cycle();
1337 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1343 AudioEngine::stop_latency_detection ()
1345 _measuring_latency = MeasureNone;
1347 if (_latency_output_port) {
1348 port_engine().unregister_port (_latency_output_port);
1349 _latency_output_port = 0;
1351 if (_latency_input_port) {
1352 port_engine().unregister_port (_latency_input_port);
1353 _latency_input_port = 0;
1358 if (_stopped_for_latency) {
1362 _stopped_for_latency = false;
1363 _started_for_latency = false;
1367 AudioEngine::set_latency_output_port (const string& name)
1369 _latency_output_name = name;
1373 AudioEngine::set_latency_input_port (const string& name)
1375 _latency_input_name = name;