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();
104 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
105 i->second->deinstantiate();
110 AudioEngine::create ()
116 _instance = new AudioEngine ();
122 AudioEngine::split_cycle (pframes_t offset)
124 /* caller must hold process lock */
126 Port::increment_global_port_buffer_offset (offset);
128 /* tell all Ports that we're going to start a new (split) cycle */
130 boost::shared_ptr<Ports> p = ports.reader();
132 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
133 i->second->cycle_split ();
138 AudioEngine::sample_rate_change (pframes_t nframes)
140 /* check for monitor input change every 1/10th of second */
142 monitor_check_interval = nframes / 10;
143 last_monitor_check = 0;
146 _session->set_frame_rate (nframes);
149 SampleRateChanged (nframes); /* EMIT SIGNAL */
155 AudioEngine::buffer_size_change (pframes_t bufsiz)
158 _session->set_block_size (bufsiz);
159 last_monitor_check = 0;
162 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
167 /** Method called by our ::process_thread when there is work to be done.
168 * @param nframes Number of frames to process.
171 __attribute__((annotate("realtime")))
174 AudioEngine::process_callback (pframes_t nframes)
176 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
181 /// The number of frames that will have been processed when we've finished
182 pframes_t next_processed_frames;
184 /* handle wrap around of total frames counter */
186 if (max_framepos - _processed_frames < nframes) {
187 next_processed_frames = nframes - (max_framepos - _processed_frames);
189 next_processed_frames = _processed_frames + nframes;
193 /* return having done nothing */
194 _processed_frames = next_processed_frames;
198 bool return_after_remove_check = false;
200 if (_measuring_latency == MeasureAudio && _mtdm) {
201 /* run a normal cycle from the perspective of the PortManager
202 so that we get silence on all registered ports.
204 we overwrite the silence on the two ports used for latency
208 PortManager::cycle_start (nframes);
209 PortManager::silence (nframes);
211 if (_latency_input_port && _latency_output_port) {
212 PortEngine& pe (port_engine());
214 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
215 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
217 _mtdm->process (nframes, in, out);
220 PortManager::cycle_end (nframes);
221 return_after_remove_check = true;
223 } else if (_measuring_latency == MeasureMIDI && _mididm) {
224 /* run a normal cycle from the perspective of the PortManager
225 so that we get silence on all registered ports.
227 we overwrite the silence on the two ports used for latency
231 PortManager::cycle_start (nframes);
232 PortManager::silence (nframes);
234 if (_latency_input_port && _latency_output_port) {
235 PortEngine& pe (port_engine());
237 _mididm->process (nframes, pe,
238 pe.get_buffer (_latency_input_port, nframes),
239 pe.get_buffer (_latency_output_port, nframes));
242 PortManager::cycle_end (nframes);
243 return_after_remove_check = true;
245 } else if (_latency_flush_frames) {
247 /* wait for the appropriate duration for the MTDM signal to
248 * drain from the ports before we revert to normal behaviour.
251 PortManager::cycle_start (nframes);
252 PortManager::silence (nframes);
253 PortManager::cycle_end (nframes);
255 if (_latency_flush_frames > nframes) {
256 _latency_flush_frames -= nframes;
258 _latency_flush_frames = 0;
261 return_after_remove_check = true;
264 if (session_remove_pending) {
266 /* perform the actual session removal */
268 if (session_removal_countdown < 0) {
270 /* fade out over 1 second */
271 session_removal_countdown = sample_rate()/2;
272 session_removal_gain = 1.0;
273 session_removal_gain_step = 1.0/session_removal_countdown;
275 } else if (session_removal_countdown > 0) {
277 /* we'll be fading audio out.
279 if this is the last time we do this as part
280 of session removal, do a MIDI panic now
281 to get MIDI stopped. This relies on the fact
282 that "immediate data" (aka "out of band data") from
283 MIDI tracks is *appended* after any other data,
284 so that it emerges after any outbound note ons, etc.
287 if (session_removal_countdown <= nframes) {
288 _session->midi_panic ();
294 session_removal_countdown = -1; // reset to "not in progress"
295 session_remove_pending = false;
296 session_removed.signal(); // wakes up thread that initiated session removal
300 if (return_after_remove_check) {
306 if (!_freewheeling) {
307 PortManager::cycle_start (nframes);
308 PortManager::cycle_end (nframes);
311 _processed_frames = next_processed_frames;
316 /* tell all relevant objects that we're starting a new cycle */
318 InternalSend::CycleStart (nframes);
320 /* tell all Ports that we're starting a new cycle */
322 PortManager::cycle_start (nframes);
324 /* test if we are freewheeling and there are freewheel signals connected.
325 ardour should act normally even when freewheeling unless /it/ is
326 exporting (which is what Freewheel.empty() tests for).
329 if (_freewheeling && !Freewheel.empty()) {
332 _session->process (nframes);
336 PortManager::cycle_end (nframes);
341 PortManager::cycle_end (nframes);
342 _processed_frames = next_processed_frames;
346 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
348 PortManager::check_monitoring ();
349 last_monitor_check = next_processed_frames;
352 if (_session->silent()) {
353 PortManager::silence (nframes);
356 if (session_remove_pending && session_removal_countdown) {
358 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
360 if (session_removal_countdown > nframes) {
361 session_removal_countdown -= nframes;
363 session_removal_countdown = 0;
366 session_removal_gain -= (nframes * session_removal_gain_step);
369 PortManager::cycle_end (nframes);
371 _processed_frames = next_processed_frames;
380 AudioEngine::launch_device_control_app()
382 if (_state_lock.trylock () ) {
383 _backend->launch_control_app ();
384 _state_lock.unlock ();
390 AudioEngine::request_backend_reset()
392 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
393 g_atomic_int_inc (&_hw_reset_request_count);
394 _hw_reset_condition.signal ();
398 AudioEngine::backend_reset_requested()
400 return g_atomic_int_get (&_hw_reset_request_count);
404 AudioEngine::do_reset_backend()
406 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
408 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
410 while (!_stop_hw_reset_processing) {
412 if (_hw_reset_request_count && _backend) {
414 _reset_request_lock.unlock();
416 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 dfunc = (AudioBackendInfo* (*)(void))func;
723 if (!info->available()) {
727 module.make_resident ();
732 vector<const AudioBackendInfo*>
733 AudioEngine::available_backends() const
735 vector<const AudioBackendInfo*> r;
737 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
738 r.push_back (i->second);
745 AudioEngine::current_backend_name() const
748 return _backend->name();
754 AudioEngine::drop_backend ()
758 _backend->drop_device ();
764 boost::shared_ptr<AudioBackend>
765 AudioEngine::set_default_backend ()
767 if (_backends.empty()) {
768 return boost::shared_ptr<AudioBackend>();
771 return set_backend (_backends.begin()->first, "", "");
774 boost::shared_ptr<AudioBackend>
775 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
777 BackendMap::iterator b = _backends.find (name);
779 if (b == _backends.end()) {
780 return boost::shared_ptr<AudioBackend>();
786 if (b->second->instantiate (arg1, arg2)) {
787 throw failed_constructor ();
790 _backend = b->second->factory (*this);
792 } catch (exception& e) {
793 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
794 return boost::shared_ptr<AudioBackend>();
800 /* BACKEND PROXY WRAPPERS */
803 AudioEngine::start (bool for_latency)
813 _processed_frames = 0;
814 last_monitor_check = 0;
816 if (_backend->start (for_latency)) {
823 _session->set_frame_rate (_backend->sample_rate());
825 if (_session->config.get_jack_time_master()) {
826 _backend->set_time_master (true);
831 start_metering_thread ();
834 Running(); /* EMIT SIGNAL */
841 AudioEngine::stop (bool for_latency)
847 if (_session && _running) {
848 // it's not a halt, but should be handled the same way:
849 // disable record, stop transport and I/O processign but save the data.
850 _session->engine_halted ();
853 Glib::Threads::Mutex::Lock lm (_process_lock);
855 if (_backend->stop ()) {
860 _processed_frames = 0;
861 _measuring_latency = MeasureNone;
862 _latency_output_port = 0;
863 _latency_input_port = 0;
864 _started_for_latency = false;
865 stop_metering_thread ();
870 Stopped (); /* EMIT SIGNAL */
877 AudioEngine::freewheel (bool start_stop)
883 /* _freewheeling will be set when first Freewheel signal occurs */
885 return _backend->freewheel (start_stop);
889 AudioEngine::get_dsp_load() const
894 return _backend->dsp_load ();
898 AudioEngine::is_realtime() const
904 return _backend->is_realtime();
908 AudioEngine::connected() const
914 return _backend->available();
918 AudioEngine::transport_start ()
923 return _backend->transport_start ();
927 AudioEngine::transport_stop ()
932 return _backend->transport_stop ();
936 AudioEngine::transport_state ()
939 return TransportStopped;
941 return _backend->transport_state ();
945 AudioEngine::transport_locate (framepos_t pos)
950 return _backend->transport_locate (pos);
954 AudioEngine::transport_frame()
959 return _backend->transport_frame ();
963 AudioEngine::sample_rate () const
968 return _backend->sample_rate ();
972 AudioEngine::samples_per_cycle () const
977 return _backend->buffer_size ();
981 AudioEngine::usecs_per_cycle () const
986 return _backend->usecs_per_cycle ();
990 AudioEngine::raw_buffer_size (DataType t)
995 return _backend->raw_buffer_size (t);
999 AudioEngine::sample_time ()
1004 return _backend->sample_time ();
1008 AudioEngine::sample_time_at_cycle_start ()
1013 return _backend->sample_time_at_cycle_start ();
1017 AudioEngine::samples_since_cycle_start ()
1022 return _backend->samples_since_cycle_start ();
1026 AudioEngine::get_sync_offset (pframes_t& offset) const
1031 return _backend->get_sync_offset (offset);
1035 AudioEngine::create_process_thread (boost::function<void()> func)
1040 return _backend->create_process_thread (func);
1044 AudioEngine::join_process_threads ()
1049 return _backend->join_process_threads ();
1053 AudioEngine::in_process_thread ()
1058 return _backend->in_process_thread ();
1062 AudioEngine::process_thread_count ()
1067 return _backend->process_thread_count ();
1071 AudioEngine::set_device_name (const std::string& name)
1076 return _backend->set_device_name (name);
1080 AudioEngine::set_sample_rate (float sr)
1085 return _backend->set_sample_rate (sr);
1089 AudioEngine::set_buffer_size (uint32_t bufsiz)
1094 return _backend->set_buffer_size (bufsiz);
1098 AudioEngine::set_interleaved (bool yn)
1103 return _backend->set_interleaved (yn);
1107 AudioEngine::set_input_channels (uint32_t ic)
1112 return _backend->set_input_channels (ic);
1116 AudioEngine::set_output_channels (uint32_t oc)
1121 return _backend->set_output_channels (oc);
1125 AudioEngine::set_systemic_input_latency (uint32_t il)
1130 return _backend->set_systemic_input_latency (il);
1134 AudioEngine::set_systemic_output_latency (uint32_t ol)
1139 return _backend->set_systemic_output_latency (ol);
1142 /* END OF BACKEND PROXY API */
1145 AudioEngine::thread_init_callback (void* arg)
1147 /* make sure that anybody who needs to know about this thread
1151 pthread_set_name (X_("audioengine"));
1153 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1155 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1156 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1158 AsyncMIDIPort::set_process_thread (pthread_self());
1161 /* the special thread created/managed by the backend */
1162 AudioEngine::instance()->_main_thread = new ProcessThread;
1167 AudioEngine::sync_callback (TransportState state, framepos_t position)
1170 return _session->backend_sync_callback (state, position);
1176 AudioEngine::freewheel_callback (bool onoff)
1178 _freewheeling = onoff;
1182 AudioEngine::latency_callback (bool for_playback)
1185 _session->update_latency (for_playback);
1190 AudioEngine::update_latencies ()
1193 _backend->update_latencies ();
1198 AudioEngine::halted_callback (const char* why)
1200 if (_in_destructor) {
1201 /* everything is under control */
1205 stop_metering_thread ();
1208 Port::PortDrop (); /* EMIT SIGNAL */
1210 if (!_started_for_latency) {
1211 Halted (why); /* EMIT SIGNAL */
1216 AudioEngine::setup_required () const
1219 if (_backend->info().already_configured())
1222 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1231 AudioEngine::prepare_for_latency_measurement ()
1234 _stopped_for_latency = true;
1239 _started_for_latency = true;
1247 AudioEngine::start_latency_detection (bool for_midi)
1250 if (prepare_for_latency_measurement ()) {
1255 PortEngine& pe (port_engine());
1263 /* find the ports we will connect to */
1265 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1266 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1273 /* create the ports we will use to read/write data */
1275 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1279 if (pe.connect (_latency_output_port, _latency_output_name)) {
1280 pe.unregister_port (_latency_output_port);
1285 const string portname ("latency_in");
1286 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1287 pe.unregister_port (_latency_input_port);
1288 pe.unregister_port (_latency_output_port);
1292 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1293 pe.unregister_port (_latency_input_port);
1294 pe.unregister_port (_latency_output_port);
1299 _mididm = new MIDIDM (sample_rate());
1303 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1307 if (pe.connect (_latency_output_port, _latency_output_name)) {
1308 pe.unregister_port (_latency_output_port);
1313 const string portname ("latency_in");
1314 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1315 pe.unregister_port (_latency_input_port);
1316 pe.unregister_port (_latency_output_port);
1320 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1321 pe.unregister_port (_latency_input_port);
1322 pe.unregister_port (_latency_output_port);
1327 _mtdm = new MTDM (sample_rate());
1332 _latency_signal_latency = 0;
1333 lr = pe.get_latency_range (in, false);
1334 _latency_signal_latency = lr.max;
1335 lr = pe.get_latency_range (out, true);
1336 _latency_signal_latency += lr.max;
1338 /* all created and connected, lets go */
1339 _latency_flush_frames = samples_per_cycle();
1340 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1346 AudioEngine::stop_latency_detection ()
1348 _measuring_latency = MeasureNone;
1350 if (_latency_output_port) {
1351 port_engine().unregister_port (_latency_output_port);
1352 _latency_output_port = 0;
1354 if (_latency_input_port) {
1355 port_engine().unregister_port (_latency_input_port);
1356 _latency_input_port = 0;
1361 if (_stopped_for_latency) {
1365 _stopped_for_latency = false;
1366 _started_for_latency = false;
1370 AudioEngine::set_latency_output_port (const string& name)
1372 _latency_output_name = name;
1376 AudioEngine::set_latency_input_port (const string& name)
1378 _latency_input_name = name;