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 if (_session && _running) {
862 // it's not a halt, but should be handled the same way:
863 // disable record, stop transport and I/O processign but save the data.
864 _session->engine_halted ();
867 Glib::Threads::Mutex::Lock lm (_process_lock);
869 if (_backend->stop ()) {
874 _processed_frames = 0;
875 _measuring_latency = MeasureNone;
876 _latency_output_port = 0;
877 _latency_input_port = 0;
878 _started_for_latency = false;
883 Stopped (); /* EMIT SIGNAL */
890 AudioEngine::freewheel (bool start_stop)
896 /* _freewheeling will be set when first Freewheel signal occurs */
898 return _backend->freewheel (start_stop);
902 AudioEngine::get_dsp_load() const
907 return _backend->dsp_load ();
911 AudioEngine::is_realtime() const
917 return _backend->is_realtime();
921 AudioEngine::connected() const
927 return _backend->available();
931 AudioEngine::transport_start ()
936 return _backend->transport_start ();
940 AudioEngine::transport_stop ()
945 return _backend->transport_stop ();
949 AudioEngine::transport_state ()
952 return TransportStopped;
954 return _backend->transport_state ();
958 AudioEngine::transport_locate (framepos_t pos)
963 return _backend->transport_locate (pos);
967 AudioEngine::transport_frame()
972 return _backend->transport_frame ();
976 AudioEngine::sample_rate () const
981 return _backend->sample_rate ();
985 AudioEngine::samples_per_cycle () const
990 return _backend->buffer_size ();
994 AudioEngine::usecs_per_cycle () const
999 return _backend->usecs_per_cycle ();
1003 AudioEngine::raw_buffer_size (DataType t)
1008 return _backend->raw_buffer_size (t);
1012 AudioEngine::sample_time ()
1017 return _backend->sample_time ();
1021 AudioEngine::sample_time_at_cycle_start ()
1026 return _backend->sample_time_at_cycle_start ();
1030 AudioEngine::samples_since_cycle_start ()
1035 return _backend->samples_since_cycle_start ();
1039 AudioEngine::get_sync_offset (pframes_t& offset) const
1044 return _backend->get_sync_offset (offset);
1048 AudioEngine::create_process_thread (boost::function<void()> func)
1053 return _backend->create_process_thread (func);
1057 AudioEngine::join_process_threads ()
1062 return _backend->join_process_threads ();
1066 AudioEngine::in_process_thread ()
1071 return _backend->in_process_thread ();
1075 AudioEngine::process_thread_count ()
1080 return _backend->process_thread_count ();
1084 AudioEngine::set_device_name (const std::string& name)
1089 return _backend->set_device_name (name);
1093 AudioEngine::set_sample_rate (float sr)
1099 return _backend->set_sample_rate (sr);
1103 AudioEngine::set_buffer_size (uint32_t bufsiz)
1108 return _backend->set_buffer_size (bufsiz);
1112 AudioEngine::set_interleaved (bool yn)
1117 return _backend->set_interleaved (yn);
1121 AudioEngine::set_input_channels (uint32_t ic)
1126 return _backend->set_input_channels (ic);
1130 AudioEngine::set_output_channels (uint32_t oc)
1135 return _backend->set_output_channels (oc);
1139 AudioEngine::set_systemic_input_latency (uint32_t il)
1144 return _backend->set_systemic_input_latency (il);
1148 AudioEngine::set_systemic_output_latency (uint32_t ol)
1153 return _backend->set_systemic_output_latency (ol);
1157 AudioEngine::thread_initialised_for_audio_processing ()
1159 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1162 /* END OF BACKEND PROXY API */
1165 AudioEngine::thread_init_callback (void* arg)
1167 /* make sure that anybody who needs to know about this thread
1171 pthread_set_name (X_("audioengine"));
1173 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1175 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1176 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1178 AsyncMIDIPort::set_process_thread (pthread_self());
1181 /* the special thread created/managed by the backend */
1182 AudioEngine::instance()->_main_thread = new ProcessThread;
1187 AudioEngine::sync_callback (TransportState state, framepos_t position)
1190 return _session->backend_sync_callback (state, position);
1196 AudioEngine::freewheel_callback (bool onoff)
1198 _freewheeling = onoff;
1202 AudioEngine::latency_callback (bool for_playback)
1205 _session->update_latency (for_playback);
1210 AudioEngine::update_latencies ()
1213 _backend->update_latencies ();
1218 AudioEngine::halted_callback (const char* why)
1220 if (_in_destructor) {
1221 /* everything is under control */
1227 Port::PortDrop (); /* EMIT SIGNAL */
1229 if (!_started_for_latency) {
1230 Halted (why); /* EMIT SIGNAL */
1235 AudioEngine::setup_required () const
1238 if (_backend->info().already_configured())
1241 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1250 AudioEngine::prepare_for_latency_measurement ()
1253 _stopped_for_latency = true;
1258 _started_for_latency = true;
1266 AudioEngine::start_latency_detection (bool for_midi)
1269 if (prepare_for_latency_measurement ()) {
1274 PortEngine& pe (port_engine());
1282 /* find the ports we will connect to */
1284 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1285 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1292 /* create the ports we will use to read/write data */
1294 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1298 if (pe.connect (_latency_output_port, _latency_output_name)) {
1299 pe.unregister_port (_latency_output_port);
1304 const string portname ("latency_in");
1305 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1306 pe.unregister_port (_latency_input_port);
1307 pe.unregister_port (_latency_output_port);
1311 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1312 pe.unregister_port (_latency_input_port);
1313 pe.unregister_port (_latency_output_port);
1318 _mididm = new MIDIDM (sample_rate());
1322 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1326 if (pe.connect (_latency_output_port, _latency_output_name)) {
1327 pe.unregister_port (_latency_output_port);
1332 const string portname ("latency_in");
1333 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1334 pe.unregister_port (_latency_input_port);
1335 pe.unregister_port (_latency_output_port);
1339 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1340 pe.unregister_port (_latency_input_port);
1341 pe.unregister_port (_latency_output_port);
1346 _mtdm = new MTDM (sample_rate());
1351 _latency_signal_latency = 0;
1352 lr = pe.get_latency_range (in, false);
1353 _latency_signal_latency = lr.max;
1354 lr = pe.get_latency_range (out, true);
1355 _latency_signal_latency += lr.max;
1357 /* all created and connected, lets go */
1358 _latency_flush_frames = samples_per_cycle();
1359 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1365 AudioEngine::stop_latency_detection ()
1367 _measuring_latency = MeasureNone;
1369 if (_latency_output_port) {
1370 port_engine().unregister_port (_latency_output_port);
1371 _latency_output_port = 0;
1373 if (_latency_input_port) {
1374 port_engine().unregister_port (_latency_input_port);
1375 _latency_input_port = 0;
1380 if (_stopped_for_latency) {
1384 _stopped_for_latency = false;
1385 _started_for_latency = false;
1389 AudioEngine::set_latency_output_port (const string& name)
1391 _latency_output_name = name;
1395 AudioEngine::set_latency_input_port (const string& name)
1397 _latency_input_name = name;