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 gint AudioEngine::m_meter_exit;
65 AudioEngine* AudioEngine::_instance = 0;
68 #define SILENCE_AFTER_SECONDS 600
71 AudioEngine::AudioEngine ()
72 : session_remove_pending (false)
73 , session_removal_countdown (-1)
75 , _freewheeling (false)
76 , monitor_check_interval (INT32_MAX)
77 , last_monitor_check (0)
78 , _processed_frames (0)
83 , _measuring_latency (MeasureNone)
84 , _latency_input_port (0)
85 , _latency_output_port (0)
86 , _latency_flush_frames (0)
87 , _latency_signal_latency (0)
88 , _stopped_for_latency (false)
89 , _started_for_latency (false)
90 , _in_destructor (false)
91 , _hw_reset_event_thread(0)
92 , _hw_reset_request_count(0)
93 , _stop_hw_reset_processing(0)
94 , _hw_devicelist_update_thread(0)
95 , _hw_devicelist_update_count(0)
96 , _stop_hw_devicelist_processing(0)
97 #ifdef SILENCE_AFTER_SECONDS
98 , _silence_countdown (0)
99 , _silence_hit_cnt (0)
102 g_atomic_int_set (&m_meter_exit, 0);
103 reset_silence_countdown ();
104 start_hw_event_processing();
105 discover_backends ();
108 AudioEngine::~AudioEngine ()
110 _in_destructor = true;
111 stop_metering_thread ();
112 stop_hw_event_processing();
114 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
115 i->second->deinstantiate();
120 AudioEngine::create ()
126 _instance = new AudioEngine ();
132 AudioEngine::split_cycle (pframes_t offset)
134 /* caller must hold process lock */
136 Port::increment_global_port_buffer_offset (offset);
138 /* tell all Ports that we're going to start a new (split) cycle */
140 boost::shared_ptr<Ports> p = ports.reader();
142 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
143 i->second->cycle_split ();
148 AudioEngine::sample_rate_change (pframes_t nframes)
150 /* check for monitor input change every 1/10th of second */
152 monitor_check_interval = nframes / 10;
153 last_monitor_check = 0;
156 _session->set_frame_rate (nframes);
159 SampleRateChanged (nframes); /* EMIT SIGNAL */
161 #ifdef SILENCE_AFTER_SECONDS
162 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
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 = 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;
573 AudioEngine::stop_metering_thread ()
575 if (m_meter_thread) {
576 g_atomic_int_set (&m_meter_exit, 1);
577 m_meter_thread->join ();
583 AudioEngine::start_metering_thread ()
585 if (m_meter_thread == 0) {
586 g_atomic_int_set (&m_meter_exit, 0);
587 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
592 AudioEngine::meter_thread ()
594 pthread_set_name (X_("meter"));
597 Glib::usleep (10000); /* 1/100th sec interval */
598 if (g_atomic_int_get(&m_meter_exit)) {
606 AudioEngine::set_session (Session *s)
608 Glib::Threads::Mutex::Lock pl (_process_lock);
610 SessionHandlePtr::set_session (s);
614 pframes_t blocksize = samples_per_cycle ();
616 PortManager::cycle_start (blocksize);
618 _session->process (blocksize);
619 _session->process (blocksize);
620 _session->process (blocksize);
621 _session->process (blocksize);
622 _session->process (blocksize);
623 _session->process (blocksize);
624 _session->process (blocksize);
625 _session->process (blocksize);
627 PortManager::cycle_end (blocksize);
632 AudioEngine::remove_session ()
634 Glib::Threads::Mutex::Lock lm (_process_lock);
639 session_remove_pending = true;
640 session_removal_countdown = 0;
641 session_removed.wait(_process_lock);
645 SessionHandlePtr::set_session (0);
653 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
656 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
664 /* called from a signal handler for SIGPIPE */
666 stop_metering_thread ();
672 AudioEngine::reset_timebase ()
675 if (_session->config.get_jack_time_master()) {
676 _backend->set_time_master (true);
678 _backend->set_time_master (false);
686 AudioEngine::destroy ()
693 AudioEngine::discover_backends ()
695 vector<std::string> backend_modules;
699 Glib::PatternSpec so_extension_pattern("*backend.so");
700 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
702 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
703 #if defined(DEBUG) || defined(_DEBUG)
704 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
706 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
709 Glib::PatternSpec dll_extension_pattern("*backend.dll");
712 find_files_matching_pattern (backend_modules, backend_search_path (),
713 so_extension_pattern);
715 find_files_matching_pattern (backend_modules, backend_search_path (),
716 dylib_extension_pattern);
718 find_files_matching_pattern (backend_modules, backend_search_path (),
719 dll_extension_pattern);
721 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
723 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
725 AudioBackendInfo* info;
727 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
729 if ((info = backend_discover (*i)) != 0) {
730 _backends.insert (make_pair (info->name, info));
734 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
736 return _backends.size();
740 AudioEngine::backend_discover (const string& path)
742 #ifdef PLATFORM_WINDOWS
743 // do not show popup dialog (e.g. missing libjack.dll)
744 // win7+ should use SetThreadErrorMode()
745 SetErrorMode(SEM_FAILCRITICALERRORS);
747 Glib::Module module (path);
748 #ifdef PLATFORM_WINDOWS
749 SetErrorMode(0); // reset to system default
751 AudioBackendInfo* info;
752 AudioBackendInfo* (*dfunc)(void);
756 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
757 Glib::Module::get_last_error()) << endmsg;
761 if (!module.get_symbol ("descriptor", func)) {
762 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
763 error << Glib::Module::get_last_error() << endmsg;
767 dfunc = (AudioBackendInfo* (*)(void))func;
769 if (!info->available()) {
773 module.make_resident ();
778 vector<const AudioBackendInfo*>
779 AudioEngine::available_backends() const
781 vector<const AudioBackendInfo*> r;
783 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
784 r.push_back (i->second);
791 AudioEngine::current_backend_name() const
794 return _backend->name();
800 AudioEngine::drop_backend ()
804 _backend->drop_device ();
810 boost::shared_ptr<AudioBackend>
811 AudioEngine::set_default_backend ()
813 if (_backends.empty()) {
814 return boost::shared_ptr<AudioBackend>();
817 return set_backend (_backends.begin()->first, "", "");
820 boost::shared_ptr<AudioBackend>
821 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
823 BackendMap::iterator b = _backends.find (name);
825 if (b == _backends.end()) {
826 return boost::shared_ptr<AudioBackend>();
832 if (b->second->instantiate (arg1, arg2)) {
833 throw failed_constructor ();
836 _backend = b->second->factory (*this);
838 } catch (exception& e) {
839 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
840 return boost::shared_ptr<AudioBackend>();
846 /* BACKEND PROXY WRAPPERS */
849 AudioEngine::start (bool for_latency)
859 _processed_frames = 0;
860 last_monitor_check = 0;
862 if (_backend->start (for_latency)) {
869 _session->set_frame_rate (_backend->sample_rate());
871 if (_session->config.get_jack_time_master()) {
872 _backend->set_time_master (true);
877 start_metering_thread ();
880 Running(); /* EMIT SIGNAL */
887 AudioEngine::stop (bool for_latency)
893 if (_session && _running) {
894 // it's not a halt, but should be handled the same way:
895 // disable record, stop transport and I/O processign but save the data.
896 _session->engine_halted ();
899 Glib::Threads::Mutex::Lock lm (_process_lock);
901 if (_backend->stop ()) {
906 _processed_frames = 0;
907 _measuring_latency = MeasureNone;
908 _latency_output_port = 0;
909 _latency_input_port = 0;
910 _started_for_latency = false;
911 stop_metering_thread ();
916 Stopped (); /* EMIT SIGNAL */
923 AudioEngine::freewheel (bool start_stop)
929 /* _freewheeling will be set when first Freewheel signal occurs */
931 return _backend->freewheel (start_stop);
935 AudioEngine::get_dsp_load() const
940 return _backend->dsp_load ();
944 AudioEngine::is_realtime() const
950 return _backend->is_realtime();
954 AudioEngine::connected() const
960 return _backend->available();
964 AudioEngine::transport_start ()
969 return _backend->transport_start ();
973 AudioEngine::transport_stop ()
978 return _backend->transport_stop ();
982 AudioEngine::transport_state ()
985 return TransportStopped;
987 return _backend->transport_state ();
991 AudioEngine::transport_locate (framepos_t pos)
996 return _backend->transport_locate (pos);
1000 AudioEngine::transport_frame()
1005 return _backend->transport_frame ();
1009 AudioEngine::sample_rate () const
1014 return _backend->sample_rate ();
1018 AudioEngine::samples_per_cycle () const
1023 return _backend->buffer_size ();
1027 AudioEngine::usecs_per_cycle () const
1032 return _backend->usecs_per_cycle ();
1036 AudioEngine::raw_buffer_size (DataType t)
1041 return _backend->raw_buffer_size (t);
1045 AudioEngine::sample_time ()
1050 return _backend->sample_time ();
1054 AudioEngine::sample_time_at_cycle_start ()
1059 return _backend->sample_time_at_cycle_start ();
1063 AudioEngine::samples_since_cycle_start ()
1068 return _backend->samples_since_cycle_start ();
1072 AudioEngine::get_sync_offset (pframes_t& offset) const
1077 return _backend->get_sync_offset (offset);
1081 AudioEngine::create_process_thread (boost::function<void()> func)
1086 return _backend->create_process_thread (func);
1090 AudioEngine::join_process_threads ()
1095 return _backend->join_process_threads ();
1099 AudioEngine::in_process_thread ()
1104 return _backend->in_process_thread ();
1108 AudioEngine::process_thread_count ()
1113 return _backend->process_thread_count ();
1117 AudioEngine::set_device_name (const std::string& name)
1122 return _backend->set_device_name (name);
1126 AudioEngine::set_sample_rate (float sr)
1132 return _backend->set_sample_rate (sr);
1136 AudioEngine::set_buffer_size (uint32_t bufsiz)
1141 return _backend->set_buffer_size (bufsiz);
1145 AudioEngine::set_interleaved (bool yn)
1150 return _backend->set_interleaved (yn);
1154 AudioEngine::set_input_channels (uint32_t ic)
1159 return _backend->set_input_channels (ic);
1163 AudioEngine::set_output_channels (uint32_t oc)
1168 return _backend->set_output_channels (oc);
1172 AudioEngine::set_systemic_input_latency (uint32_t il)
1177 return _backend->set_systemic_input_latency (il);
1181 AudioEngine::set_systemic_output_latency (uint32_t ol)
1186 return _backend->set_systemic_output_latency (ol);
1189 /* END OF BACKEND PROXY API */
1192 AudioEngine::thread_init_callback (void* arg)
1194 /* make sure that anybody who needs to know about this thread
1198 pthread_set_name (X_("audioengine"));
1200 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1202 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1203 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1205 AsyncMIDIPort::set_process_thread (pthread_self());
1208 /* the special thread created/managed by the backend */
1209 AudioEngine::instance()->_main_thread = new ProcessThread;
1214 AudioEngine::sync_callback (TransportState state, framepos_t position)
1217 return _session->backend_sync_callback (state, position);
1223 AudioEngine::freewheel_callback (bool onoff)
1225 _freewheeling = onoff;
1229 AudioEngine::latency_callback (bool for_playback)
1232 _session->update_latency (for_playback);
1237 AudioEngine::update_latencies ()
1240 _backend->update_latencies ();
1245 AudioEngine::halted_callback (const char* why)
1247 if (_in_destructor) {
1248 /* everything is under control */
1252 stop_metering_thread ();
1255 Port::PortDrop (); /* EMIT SIGNAL */
1257 if (!_started_for_latency) {
1258 Halted (why); /* EMIT SIGNAL */
1263 AudioEngine::setup_required () const
1266 if (_backend->info().already_configured())
1269 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1278 AudioEngine::prepare_for_latency_measurement ()
1281 _stopped_for_latency = true;
1286 _started_for_latency = true;
1294 AudioEngine::start_latency_detection (bool for_midi)
1297 if (prepare_for_latency_measurement ()) {
1302 PortEngine& pe (port_engine());
1310 /* find the ports we will connect to */
1312 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1313 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1320 /* create the ports we will use to read/write data */
1322 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, 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::MIDI, 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 _mididm = new MIDIDM (sample_rate());
1350 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1354 if (pe.connect (_latency_output_port, _latency_output_name)) {
1355 pe.unregister_port (_latency_output_port);
1360 const string portname ("latency_in");
1361 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1362 pe.unregister_port (_latency_input_port);
1363 pe.unregister_port (_latency_output_port);
1367 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1368 pe.unregister_port (_latency_input_port);
1369 pe.unregister_port (_latency_output_port);
1374 _mtdm = new MTDM (sample_rate());
1379 _latency_signal_latency = 0;
1380 lr = pe.get_latency_range (in, false);
1381 _latency_signal_latency = lr.max;
1382 lr = pe.get_latency_range (out, true);
1383 _latency_signal_latency += lr.max;
1385 /* all created and connected, lets go */
1386 _latency_flush_frames = samples_per_cycle();
1387 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1393 AudioEngine::stop_latency_detection ()
1395 _measuring_latency = MeasureNone;
1397 if (_latency_output_port) {
1398 port_engine().unregister_port (_latency_output_port);
1399 _latency_output_port = 0;
1401 if (_latency_input_port) {
1402 port_engine().unregister_port (_latency_input_port);
1403 _latency_input_port = 0;
1408 if (_stopped_for_latency) {
1412 _stopped_for_latency = false;
1413 _started_for_latency = false;
1417 AudioEngine::set_latency_output_port (const string& name)
1419 _latency_output_name = name;
1423 AudioEngine::set_latency_input_port (const string& name)
1425 _latency_input_name = name;