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 = 1.0;
287 session_removal_gain_step = 1.0/session_removal_countdown;
289 } else if (session_removal_countdown > 0) {
291 /* we'll be fading audio out.
293 if this is the last time we do this as part
294 of session removal, do a MIDI panic now
295 to get MIDI stopped. This relies on the fact
296 that "immediate data" (aka "out of band data") from
297 MIDI tracks is *appended* after any other data,
298 so that it emerges after any outbound note ons, etc.
301 if (session_removal_countdown <= nframes) {
302 _session->midi_panic ();
308 session_removal_countdown = -1; // reset to "not in progress"
309 session_remove_pending = false;
310 session_removed.signal(); // wakes up thread that initiated session removal
314 if (return_after_remove_check) {
320 if (!_freewheeling) {
321 PortManager::cycle_start (nframes);
322 PortManager::cycle_end (nframes);
325 _processed_frames = next_processed_frames;
330 /* tell all relevant objects that we're starting a new cycle */
332 InternalSend::CycleStart (nframes);
334 /* tell all Ports that we're starting a new cycle */
336 PortManager::cycle_start (nframes);
338 /* test if we are freewheeling and there are freewheel signals connected.
339 ardour should act normally even when freewheeling unless /it/ is
340 exporting (which is what Freewheel.empty() tests for).
343 if (_freewheeling && !Freewheel.empty()) {
346 _session->process (nframes);
350 PortManager::cycle_end (nframes);
355 PortManager::cycle_end (nframes);
356 _processed_frames = next_processed_frames;
360 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
362 PortManager::check_monitoring ();
363 last_monitor_check = next_processed_frames;
366 #ifdef SILENCE_AFTER_SECONDS
368 bool was_silent = (_silence_countdown == 0);
370 if (_silence_countdown >= nframes) {
371 _silence_countdown -= nframes;
373 _silence_countdown = 0;
376 if (!was_silent && _silence_countdown == 0) {
378 BecameSilent (); /* EMIT SIGNAL */
381 if (_silence_countdown == 0 || _session->silent()) {
382 PortManager::silence (nframes);
386 if (_session->silent()) {
387 PortManager::silence (nframes);
391 if (session_remove_pending && session_removal_countdown) {
393 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
395 if (session_removal_countdown > nframes) {
396 session_removal_countdown -= nframes;
398 session_removal_countdown = 0;
401 session_removal_gain -= (nframes * session_removal_gain_step);
404 PortManager::cycle_end (nframes);
406 _processed_frames = next_processed_frames;
414 AudioEngine::reset_silence_countdown ()
416 #ifdef SILENCE_AFTER_SECONDS
417 double sr = 48000; /* default in case there is no backend */
421 _silence_countdown = max (60 * sr, /* 60 seconds */
422 sr * (SILENCE_AFTER_SECONDS / pow (2, _silence_hit_cnt)));
428 AudioEngine::launch_device_control_app()
430 if (_state_lock.trylock () ) {
431 _backend->launch_control_app ();
432 _state_lock.unlock ();
438 AudioEngine::request_backend_reset()
440 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
441 g_atomic_int_inc (&_hw_reset_request_count);
442 _hw_reset_condition.signal ();
446 AudioEngine::backend_reset_requested()
448 return g_atomic_int_get (&_hw_reset_request_count);
452 AudioEngine::do_reset_backend()
454 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512);
456 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
458 while (!_stop_hw_reset_processing) {
460 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
462 _reset_request_lock.unlock();
464 Glib::Threads::RecMutex::Lock pl (_state_lock);
465 g_atomic_int_dec_and_test (&_hw_reset_request_count);
467 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
468 DeviceResetStarted(); // notify about device reset to be started
470 // backup the device name
471 std::string name = _backend->device_name ();
473 std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
476 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
477 if ( 0 == _backend->reset_device () ) {
479 std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
482 // inform about possible changes
483 BufferSizeChanged (_backend->buffer_size() );
488 std::cout << "AudioEngine::RESET::Done." << std::endl;
490 _reset_request_lock.lock();
494 _hw_reset_condition.wait (_reset_request_lock);
500 AudioEngine::request_device_list_update()
502 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
503 g_atomic_int_inc (&_hw_devicelist_update_count);
504 _hw_devicelist_update_condition.signal ();
509 AudioEngine::do_devicelist_update()
511 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
513 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
515 while (!_stop_hw_devicelist_processing) {
517 if (_hw_devicelist_update_count) {
519 _devicelist_update_lock.unlock();
521 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
522 DeviceListChanged (); /* EMIT SIGNAL */
524 _devicelist_update_lock.lock();
527 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
534 AudioEngine::start_hw_event_processing()
536 if (_hw_reset_event_thread == 0) {
537 g_atomic_int_set(&_hw_reset_request_count, 0);
538 g_atomic_int_set(&_stop_hw_reset_processing, 0);
539 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
542 if (_hw_devicelist_update_thread == 0) {
543 g_atomic_int_set(&_hw_devicelist_update_count, 0);
544 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
545 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
551 AudioEngine::stop_hw_event_processing()
553 if (_hw_reset_event_thread) {
554 g_atomic_int_set(&_stop_hw_reset_processing, 1);
555 g_atomic_int_set(&_hw_reset_request_count, 0);
556 _hw_reset_condition.signal ();
557 _hw_reset_event_thread->join ();
558 _hw_reset_event_thread = 0;
561 if (_hw_devicelist_update_thread) {
562 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
563 g_atomic_int_set(&_hw_devicelist_update_count, 0);
564 _hw_devicelist_update_condition.signal ();
565 _hw_devicelist_update_thread->join ();
566 _hw_devicelist_update_thread = 0;
574 AudioEngine::stop_metering_thread ()
576 if (m_meter_thread) {
577 g_atomic_int_set (&m_meter_exit, 1);
578 m_meter_thread->join ();
584 AudioEngine::start_metering_thread ()
586 if (m_meter_thread == 0) {
587 g_atomic_int_set (&m_meter_exit, 0);
588 m_meter_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::meter_thread, this));
593 AudioEngine::meter_thread ()
595 pthread_set_name (X_("meter"));
598 Glib::usleep (10000); /* 1/100th sec interval */
599 if (g_atomic_int_get(&m_meter_exit)) {
607 AudioEngine::set_session (Session *s)
609 Glib::Threads::Mutex::Lock pl (_process_lock);
611 SessionHandlePtr::set_session (s);
615 pframes_t blocksize = samples_per_cycle ();
617 PortManager::cycle_start (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);
626 _session->process (blocksize);
628 PortManager::cycle_end (blocksize);
633 AudioEngine::remove_session ()
635 Glib::Threads::Mutex::Lock lm (_process_lock);
640 session_remove_pending = true;
641 session_removal_countdown = 0;
642 session_removed.wait(_process_lock);
646 SessionHandlePtr::set_session (0);
654 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
657 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
665 /* called from a signal handler for SIGPIPE */
667 stop_metering_thread ();
673 AudioEngine::reset_timebase ()
676 if (_session->config.get_jack_time_master()) {
677 _backend->set_time_master (true);
679 _backend->set_time_master (false);
687 AudioEngine::destroy ()
694 AudioEngine::discover_backends ()
696 vector<std::string> backend_modules;
700 Glib::PatternSpec so_extension_pattern("*backend.so");
701 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
703 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
704 #if defined(DEBUG) || defined(_DEBUG)
705 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
707 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
710 Glib::PatternSpec dll_extension_pattern("*backend.dll");
713 find_files_matching_pattern (backend_modules, backend_search_path (),
714 so_extension_pattern);
716 find_files_matching_pattern (backend_modules, backend_search_path (),
717 dylib_extension_pattern);
719 find_files_matching_pattern (backend_modules, backend_search_path (),
720 dll_extension_pattern);
722 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
724 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
726 AudioBackendInfo* info;
728 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
730 if ((info = backend_discover (*i)) != 0) {
731 _backends.insert (make_pair (info->name, info));
735 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
737 return _backends.size();
741 AudioEngine::backend_discover (const string& path)
743 #ifdef PLATFORM_WINDOWS
744 // do not show popup dialog (e.g. missing libjack.dll)
745 // win7+ should use SetThreadErrorMode()
746 SetErrorMode(SEM_FAILCRITICALERRORS);
748 Glib::Module module (path);
749 #ifdef PLATFORM_WINDOWS
750 SetErrorMode(0); // reset to system default
752 AudioBackendInfo* info;
753 AudioBackendInfo* (*dfunc)(void);
757 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
758 Glib::Module::get_last_error()) << endmsg;
762 if (!module.get_symbol ("descriptor", func)) {
763 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
764 error << Glib::Module::get_last_error() << endmsg;
768 dfunc = (AudioBackendInfo* (*)(void))func;
770 if (!info->available()) {
774 module.make_resident ();
779 vector<const AudioBackendInfo*>
780 AudioEngine::available_backends() const
782 vector<const AudioBackendInfo*> r;
784 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
785 r.push_back (i->second);
792 AudioEngine::current_backend_name() const
795 return _backend->name();
801 AudioEngine::drop_backend ()
805 _backend->drop_device ();
811 boost::shared_ptr<AudioBackend>
812 AudioEngine::set_default_backend ()
814 if (_backends.empty()) {
815 return boost::shared_ptr<AudioBackend>();
818 return set_backend (_backends.begin()->first, "", "");
821 boost::shared_ptr<AudioBackend>
822 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
824 BackendMap::iterator b = _backends.find (name);
826 if (b == _backends.end()) {
827 return boost::shared_ptr<AudioBackend>();
833 if (b->second->instantiate (arg1, arg2)) {
834 throw failed_constructor ();
837 _backend = b->second->factory (*this);
839 } catch (exception& e) {
840 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
841 return boost::shared_ptr<AudioBackend>();
847 /* BACKEND PROXY WRAPPERS */
850 AudioEngine::start (bool for_latency)
860 _processed_frames = 0;
861 last_monitor_check = 0;
863 if (_backend->start (for_latency)) {
870 _session->set_frame_rate (_backend->sample_rate());
872 if (_session->config.get_jack_time_master()) {
873 _backend->set_time_master (true);
878 start_metering_thread ();
881 Running(); /* EMIT SIGNAL */
888 AudioEngine::stop (bool for_latency)
894 if (_session && _running) {
895 // it's not a halt, but should be handled the same way:
896 // disable record, stop transport and I/O processign but save the data.
897 _session->engine_halted ();
900 Glib::Threads::Mutex::Lock lm (_process_lock);
902 if (_backend->stop ()) {
907 _processed_frames = 0;
908 _measuring_latency = MeasureNone;
909 _latency_output_port = 0;
910 _latency_input_port = 0;
911 _started_for_latency = false;
912 stop_metering_thread ();
917 Stopped (); /* EMIT SIGNAL */
924 AudioEngine::freewheel (bool start_stop)
930 /* _freewheeling will be set when first Freewheel signal occurs */
932 return _backend->freewheel (start_stop);
936 AudioEngine::get_dsp_load() const
941 return _backend->dsp_load ();
945 AudioEngine::is_realtime() const
951 return _backend->is_realtime();
955 AudioEngine::connected() const
961 return _backend->available();
965 AudioEngine::transport_start ()
970 return _backend->transport_start ();
974 AudioEngine::transport_stop ()
979 return _backend->transport_stop ();
983 AudioEngine::transport_state ()
986 return TransportStopped;
988 return _backend->transport_state ();
992 AudioEngine::transport_locate (framepos_t pos)
997 return _backend->transport_locate (pos);
1001 AudioEngine::transport_frame()
1006 return _backend->transport_frame ();
1010 AudioEngine::sample_rate () const
1015 return _backend->sample_rate ();
1019 AudioEngine::samples_per_cycle () const
1024 return _backend->buffer_size ();
1028 AudioEngine::usecs_per_cycle () const
1033 return _backend->usecs_per_cycle ();
1037 AudioEngine::raw_buffer_size (DataType t)
1042 return _backend->raw_buffer_size (t);
1046 AudioEngine::sample_time ()
1051 return _backend->sample_time ();
1055 AudioEngine::sample_time_at_cycle_start ()
1060 return _backend->sample_time_at_cycle_start ();
1064 AudioEngine::samples_since_cycle_start ()
1069 return _backend->samples_since_cycle_start ();
1073 AudioEngine::get_sync_offset (pframes_t& offset) const
1078 return _backend->get_sync_offset (offset);
1082 AudioEngine::create_process_thread (boost::function<void()> func)
1087 return _backend->create_process_thread (func);
1091 AudioEngine::join_process_threads ()
1096 return _backend->join_process_threads ();
1100 AudioEngine::in_process_thread ()
1105 return _backend->in_process_thread ();
1109 AudioEngine::process_thread_count ()
1114 return _backend->process_thread_count ();
1118 AudioEngine::set_device_name (const std::string& name)
1123 return _backend->set_device_name (name);
1127 AudioEngine::set_sample_rate (float sr)
1133 return _backend->set_sample_rate (sr);
1137 AudioEngine::set_buffer_size (uint32_t bufsiz)
1142 return _backend->set_buffer_size (bufsiz);
1146 AudioEngine::set_interleaved (bool yn)
1151 return _backend->set_interleaved (yn);
1155 AudioEngine::set_input_channels (uint32_t ic)
1160 return _backend->set_input_channels (ic);
1164 AudioEngine::set_output_channels (uint32_t oc)
1169 return _backend->set_output_channels (oc);
1173 AudioEngine::set_systemic_input_latency (uint32_t il)
1178 return _backend->set_systemic_input_latency (il);
1182 AudioEngine::set_systemic_output_latency (uint32_t ol)
1187 return _backend->set_systemic_output_latency (ol);
1190 /* END OF BACKEND PROXY API */
1193 AudioEngine::thread_init_callback (void* arg)
1195 /* make sure that anybody who needs to know about this thread
1199 pthread_set_name (X_("audioengine"));
1201 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1203 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1204 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1206 AsyncMIDIPort::set_process_thread (pthread_self());
1209 /* the special thread created/managed by the backend */
1210 AudioEngine::instance()->_main_thread = new ProcessThread;
1215 AudioEngine::sync_callback (TransportState state, framepos_t position)
1218 return _session->backend_sync_callback (state, position);
1224 AudioEngine::freewheel_callback (bool onoff)
1226 _freewheeling = onoff;
1230 AudioEngine::latency_callback (bool for_playback)
1233 _session->update_latency (for_playback);
1238 AudioEngine::update_latencies ()
1241 _backend->update_latencies ();
1246 AudioEngine::halted_callback (const char* why)
1248 if (_in_destructor) {
1249 /* everything is under control */
1253 stop_metering_thread ();
1256 Port::PortDrop (); /* EMIT SIGNAL */
1258 if (!_started_for_latency) {
1259 Halted (why); /* EMIT SIGNAL */
1264 AudioEngine::setup_required () const
1267 if (_backend->info().already_configured())
1270 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1279 AudioEngine::prepare_for_latency_measurement ()
1282 _stopped_for_latency = true;
1287 _started_for_latency = true;
1295 AudioEngine::start_latency_detection (bool for_midi)
1298 if (prepare_for_latency_measurement ()) {
1303 PortEngine& pe (port_engine());
1311 /* find the ports we will connect to */
1313 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1314 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1321 /* create the ports we will use to read/write data */
1323 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1327 if (pe.connect (_latency_output_port, _latency_output_name)) {
1328 pe.unregister_port (_latency_output_port);
1333 const string portname ("latency_in");
1334 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1335 pe.unregister_port (_latency_input_port);
1336 pe.unregister_port (_latency_output_port);
1340 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1341 pe.unregister_port (_latency_input_port);
1342 pe.unregister_port (_latency_output_port);
1347 _mididm = new MIDIDM (sample_rate());
1351 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1355 if (pe.connect (_latency_output_port, _latency_output_name)) {
1356 pe.unregister_port (_latency_output_port);
1361 const string portname ("latency_in");
1362 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1363 pe.unregister_port (_latency_input_port);
1364 pe.unregister_port (_latency_output_port);
1368 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1369 pe.unregister_port (_latency_input_port);
1370 pe.unregister_port (_latency_output_port);
1375 _mtdm = new MTDM (sample_rate());
1380 _latency_signal_latency = 0;
1381 lr = pe.get_latency_range (in, false);
1382 _latency_signal_latency = lr.max;
1383 lr = pe.get_latency_range (out, true);
1384 _latency_signal_latency += lr.max;
1386 /* all created and connected, lets go */
1387 _latency_flush_frames = samples_per_cycle();
1388 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1394 AudioEngine::stop_latency_detection ()
1396 _measuring_latency = MeasureNone;
1398 if (_latency_output_port) {
1399 port_engine().unregister_port (_latency_output_port);
1400 _latency_output_port = 0;
1402 if (_latency_input_port) {
1403 port_engine().unregister_port (_latency_input_port);
1404 _latency_input_port = 0;
1409 if (_stopped_for_latency) {
1413 _stopped_for_latency = false;
1414 _started_for_latency = false;
1418 AudioEngine::set_latency_output_port (const string& name)
1420 _latency_output_name = name;
1424 AudioEngine::set_latency_input_port (const string& name)
1426 _latency_input_name = name;