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"), 1024);
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::Reseting device..." << std::endl;
478 if ( ( 0 == stop () ) &&
479 ( 0 == _backend->reset_device () ) &&
480 ( 0 == start () ) ) {
482 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
484 // inform about possible changes
485 BufferSizeChanged (_backend->buffer_size() );
486 DeviceResetFinished(); // notify about device reset finish
490 DeviceResetFinished(); // notify about device reset finish
491 // we've got an error
495 std::cout << "AudioEngine::RESET::Done." << std::endl;
497 _reset_request_lock.lock();
501 _hw_reset_condition.wait (_reset_request_lock);
507 AudioEngine::request_device_list_update()
509 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
510 g_atomic_int_inc (&_hw_devicelist_update_count);
511 _hw_devicelist_update_condition.signal ();
516 AudioEngine::do_devicelist_update()
518 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
520 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
522 while (!_stop_hw_devicelist_processing) {
524 if (_hw_devicelist_update_count) {
526 _devicelist_update_lock.unlock();
528 Glib::Threads::RecMutex::Lock pl (_state_lock);
530 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
531 DeviceListChanged (); /* EMIT SIGNAL */
533 _devicelist_update_lock.lock();
536 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
543 AudioEngine::start_hw_event_processing()
545 if (_hw_reset_event_thread == 0) {
546 g_atomic_int_set(&_hw_reset_request_count, 0);
547 g_atomic_int_set(&_stop_hw_reset_processing, 0);
548 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
551 if (_hw_devicelist_update_thread == 0) {
552 g_atomic_int_set(&_hw_devicelist_update_count, 0);
553 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
554 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
560 AudioEngine::stop_hw_event_processing()
562 if (_hw_reset_event_thread) {
563 g_atomic_int_set(&_stop_hw_reset_processing, 1);
564 g_atomic_int_set(&_hw_reset_request_count, 0);
565 _hw_reset_condition.signal ();
566 _hw_reset_event_thread->join ();
567 _hw_reset_event_thread = 0;
570 if (_hw_devicelist_update_thread) {
571 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
572 g_atomic_int_set(&_hw_devicelist_update_count, 0);
573 _hw_devicelist_update_condition.signal ();
574 _hw_devicelist_update_thread->join ();
575 _hw_devicelist_update_thread = 0;
582 AudioEngine::set_session (Session *s)
584 Glib::Threads::Mutex::Lock pl (_process_lock);
586 SessionHandlePtr::set_session (s);
590 pframes_t blocksize = samples_per_cycle ();
592 PortManager::cycle_start (blocksize);
594 _session->process (blocksize);
595 _session->process (blocksize);
596 _session->process (blocksize);
597 _session->process (blocksize);
598 _session->process (blocksize);
599 _session->process (blocksize);
600 _session->process (blocksize);
601 _session->process (blocksize);
603 PortManager::cycle_end (blocksize);
608 AudioEngine::remove_session ()
610 Glib::Threads::Mutex::Lock lm (_process_lock);
615 session_remove_pending = true;
616 session_removal_countdown = 0;
617 session_removed.wait(_process_lock);
621 SessionHandlePtr::set_session (0);
629 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
631 #ifdef USE_TRACKS_CODE_FEATURES
633 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
642 /* called from a signal handler for SIGPIPE */
647 AudioEngine::reset_timebase ()
650 if (_session->config.get_jack_time_master()) {
651 _backend->set_time_master (true);
653 _backend->set_time_master (false);
661 AudioEngine::destroy ()
668 AudioEngine::discover_backends ()
670 vector<std::string> backend_modules;
674 Glib::PatternSpec so_extension_pattern("*backend.so");
675 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
677 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
678 #if defined(DEBUG) || defined(_DEBUG)
679 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
681 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
684 Glib::PatternSpec dll_extension_pattern("*backend.dll");
687 find_files_matching_pattern (backend_modules, backend_search_path (),
688 so_extension_pattern);
690 find_files_matching_pattern (backend_modules, backend_search_path (),
691 dylib_extension_pattern);
693 find_files_matching_pattern (backend_modules, backend_search_path (),
694 dll_extension_pattern);
696 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
698 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
700 AudioBackendInfo* info;
702 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
704 if ((info = backend_discover (*i)) != 0) {
705 _backends.insert (make_pair (info->name, info));
709 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
711 return _backends.size();
715 AudioEngine::backend_discover (const string& path)
717 #ifdef PLATFORM_WINDOWS
718 // do not show popup dialog (e.g. missing libjack.dll)
719 // win7+ should use SetThreadErrorMode()
720 SetErrorMode(SEM_FAILCRITICALERRORS);
722 Glib::Module module (path);
723 #ifdef PLATFORM_WINDOWS
724 SetErrorMode(0); // reset to system default
726 AudioBackendInfo* info;
727 AudioBackendInfo* (*dfunc)(void);
731 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
732 Glib::Module::get_last_error()) << endmsg;
736 if (!module.get_symbol ("descriptor", func)) {
737 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
738 error << Glib::Module::get_last_error() << endmsg;
742 dfunc = (AudioBackendInfo* (*)(void))func;
744 if (!info->available()) {
748 module.make_resident ();
753 vector<const AudioBackendInfo*>
754 AudioEngine::available_backends() const
756 vector<const AudioBackendInfo*> r;
758 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
759 r.push_back (i->second);
766 AudioEngine::current_backend_name() const
769 return _backend->name();
775 AudioEngine::drop_backend ()
779 // Stopped is needed for Graph to explicitly terminate threads
780 Stopped (); /* EMIT SIGNAL */
781 _backend->drop_device ();
787 boost::shared_ptr<AudioBackend>
788 AudioEngine::set_default_backend ()
790 if (_backends.empty()) {
791 return boost::shared_ptr<AudioBackend>();
794 return set_backend (_backends.begin()->first, "", "");
797 boost::shared_ptr<AudioBackend>
798 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
800 BackendMap::iterator b = _backends.find (name);
802 if (b == _backends.end()) {
803 return boost::shared_ptr<AudioBackend>();
809 if (b->second->instantiate (arg1, arg2)) {
810 throw failed_constructor ();
813 _backend = b->second->factory (*this);
815 } catch (exception& e) {
816 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
817 return boost::shared_ptr<AudioBackend>();
823 /* BACKEND PROXY WRAPPERS */
826 AudioEngine::start (bool for_latency)
836 _processed_frames = 0;
837 last_monitor_check = 0;
839 if (_backend->start (for_latency)) {
846 _session->set_frame_rate (_backend->sample_rate());
848 if (_session->config.get_jack_time_master()) {
849 _backend->set_time_master (true);
855 Running(); /* EMIT SIGNAL */
862 AudioEngine::stop (bool for_latency)
868 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
874 if (_backend->stop ()) {
882 if (_session && _running &&
883 (_session->state_of_the_state() & Session::Loading) == 0 &&
884 (_session->state_of_the_state() & Session::Deletion) == 0) {
885 // it's not a halt, but should be handled the same way:
886 // disable record, stop transport and I/O processign but save the data.
887 _session->engine_halted ();
891 _processed_frames = 0;
892 _measuring_latency = MeasureNone;
893 _latency_output_port = 0;
894 _latency_input_port = 0;
895 _started_for_latency = false;
900 Stopped (); /* EMIT SIGNAL */
907 AudioEngine::freewheel (bool start_stop)
913 /* _freewheeling will be set when first Freewheel signal occurs */
915 return _backend->freewheel (start_stop);
919 AudioEngine::get_dsp_load() const
924 return _backend->dsp_load ();
928 AudioEngine::is_realtime() const
934 return _backend->is_realtime();
938 AudioEngine::connected() const
944 return _backend->available();
948 AudioEngine::transport_start ()
953 return _backend->transport_start ();
957 AudioEngine::transport_stop ()
962 return _backend->transport_stop ();
966 AudioEngine::transport_state ()
969 return TransportStopped;
971 return _backend->transport_state ();
975 AudioEngine::transport_locate (framepos_t pos)
980 return _backend->transport_locate (pos);
984 AudioEngine::transport_frame()
989 return _backend->transport_frame ();
993 AudioEngine::sample_rate () const
998 return _backend->sample_rate ();
1002 AudioEngine::samples_per_cycle () const
1007 return _backend->buffer_size ();
1011 AudioEngine::usecs_per_cycle () const
1016 return _backend->usecs_per_cycle ();
1020 AudioEngine::raw_buffer_size (DataType t)
1025 return _backend->raw_buffer_size (t);
1029 AudioEngine::sample_time ()
1034 return _backend->sample_time ();
1038 AudioEngine::sample_time_at_cycle_start ()
1043 return _backend->sample_time_at_cycle_start ();
1047 AudioEngine::samples_since_cycle_start ()
1052 return _backend->samples_since_cycle_start ();
1056 AudioEngine::get_sync_offset (pframes_t& offset) const
1061 return _backend->get_sync_offset (offset);
1065 AudioEngine::create_process_thread (boost::function<void()> func)
1070 return _backend->create_process_thread (func);
1074 AudioEngine::join_process_threads ()
1079 return _backend->join_process_threads ();
1083 AudioEngine::in_process_thread ()
1088 return _backend->in_process_thread ();
1092 AudioEngine::process_thread_count ()
1097 return _backend->process_thread_count ();
1101 AudioEngine::set_device_name (const std::string& name)
1106 return _backend->set_device_name (name);
1110 AudioEngine::set_sample_rate (float sr)
1116 return _backend->set_sample_rate (sr);
1120 AudioEngine::set_buffer_size (uint32_t bufsiz)
1125 return _backend->set_buffer_size (bufsiz);
1129 AudioEngine::set_interleaved (bool yn)
1134 return _backend->set_interleaved (yn);
1138 AudioEngine::set_input_channels (uint32_t ic)
1143 return _backend->set_input_channels (ic);
1147 AudioEngine::set_output_channels (uint32_t oc)
1152 return _backend->set_output_channels (oc);
1156 AudioEngine::set_systemic_input_latency (uint32_t il)
1161 return _backend->set_systemic_input_latency (il);
1165 AudioEngine::set_systemic_output_latency (uint32_t ol)
1170 return _backend->set_systemic_output_latency (ol);
1174 AudioEngine::thread_initialised_for_audio_processing ()
1176 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1179 /* END OF BACKEND PROXY API */
1182 AudioEngine::thread_init_callback (void* arg)
1184 /* make sure that anybody who needs to know about this thread
1188 pthread_set_name (X_("audioengine"));
1190 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1192 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1193 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1195 AsyncMIDIPort::set_process_thread (pthread_self());
1198 /* the special thread created/managed by the backend */
1199 AudioEngine::instance()->_main_thread = new ProcessThread;
1204 AudioEngine::sync_callback (TransportState state, framepos_t position)
1207 return _session->backend_sync_callback (state, position);
1213 AudioEngine::freewheel_callback (bool onoff)
1215 _freewheeling = onoff;
1219 AudioEngine::latency_callback (bool for_playback)
1222 _session->update_latency (for_playback);
1227 AudioEngine::update_latencies ()
1230 _backend->update_latencies ();
1235 AudioEngine::halted_callback (const char* why)
1237 if (_in_destructor) {
1238 /* everything is under control */
1244 Port::PortDrop (); /* EMIT SIGNAL */
1246 if (!_started_for_latency) {
1247 Halted (why); /* EMIT SIGNAL */
1252 AudioEngine::setup_required () const
1255 if (_backend->info().already_configured())
1258 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1267 AudioEngine::prepare_for_latency_measurement ()
1270 _stopped_for_latency = true;
1275 _started_for_latency = true;
1283 AudioEngine::start_latency_detection (bool for_midi)
1286 if (prepare_for_latency_measurement ()) {
1291 PortEngine& pe (port_engine());
1299 /* find the ports we will connect to */
1301 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1302 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1309 /* create the ports we will use to read/write data */
1311 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1315 if (pe.connect (_latency_output_port, _latency_output_name)) {
1316 pe.unregister_port (_latency_output_port);
1321 const string portname ("latency_in");
1322 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1323 pe.unregister_port (_latency_input_port);
1324 pe.unregister_port (_latency_output_port);
1328 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1329 pe.unregister_port (_latency_input_port);
1330 pe.unregister_port (_latency_output_port);
1335 _mididm = new MIDIDM (sample_rate());
1339 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1343 if (pe.connect (_latency_output_port, _latency_output_name)) {
1344 pe.unregister_port (_latency_output_port);
1349 const string portname ("latency_in");
1350 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1351 pe.unregister_port (_latency_input_port);
1352 pe.unregister_port (_latency_output_port);
1356 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1357 pe.unregister_port (_latency_input_port);
1358 pe.unregister_port (_latency_output_port);
1363 _mtdm = new MTDM (sample_rate());
1368 _latency_signal_latency = 0;
1369 lr = pe.get_latency_range (in, false);
1370 _latency_signal_latency = lr.max;
1371 lr = pe.get_latency_range (out, true);
1372 _latency_signal_latency += lr.max;
1374 /* all created and connected, lets go */
1375 _latency_flush_frames = samples_per_cycle();
1376 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1382 AudioEngine::stop_latency_detection ()
1384 _measuring_latency = MeasureNone;
1386 if (_latency_output_port) {
1387 port_engine().unregister_port (_latency_output_port);
1388 _latency_output_port = 0;
1390 if (_latency_input_port) {
1391 port_engine().unregister_port (_latency_input_port);
1392 _latency_input_port = 0;
1397 if (_stopped_for_latency) {
1401 _stopped_for_latency = false;
1402 _started_for_latency = false;
1406 AudioEngine::set_latency_output_port (const string& name)
1408 _latency_output_name = name;
1412 AudioEngine::set_latency_input_port (const string& name)
1414 _latency_input_name = name;