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 /* signal the start of the fade out countdown */
617 session_removal_countdown = -1;
618 session_removed.wait(_process_lock);
622 SessionHandlePtr::set_session (0);
630 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
632 #ifdef USE_TRACKS_CODE_FEATURES
634 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
643 /* called from a signal handler for SIGPIPE */
648 AudioEngine::reset_timebase ()
651 if (_session->config.get_jack_time_master()) {
652 _backend->set_time_master (true);
654 _backend->set_time_master (false);
662 AudioEngine::destroy ()
669 AudioEngine::discover_backends ()
671 vector<std::string> backend_modules;
675 Glib::PatternSpec so_extension_pattern("*backend.so");
676 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
678 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
679 #if defined(DEBUG) || defined(_DEBUG)
680 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
682 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
685 Glib::PatternSpec dll_extension_pattern("*backend.dll");
688 find_files_matching_pattern (backend_modules, backend_search_path (),
689 so_extension_pattern);
691 find_files_matching_pattern (backend_modules, backend_search_path (),
692 dylib_extension_pattern);
694 find_files_matching_pattern (backend_modules, backend_search_path (),
695 dll_extension_pattern);
697 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
699 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
701 AudioBackendInfo* info;
703 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
705 if ((info = backend_discover (*i)) != 0) {
706 _backends.insert (make_pair (info->name, info));
710 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
712 return _backends.size();
716 AudioEngine::backend_discover (const string& path)
718 #ifdef PLATFORM_WINDOWS
719 // do not show popup dialog (e.g. missing libjack.dll)
720 // win7+ should use SetThreadErrorMode()
721 SetErrorMode(SEM_FAILCRITICALERRORS);
723 Glib::Module module (path);
724 #ifdef PLATFORM_WINDOWS
725 SetErrorMode(0); // reset to system default
727 AudioBackendInfo* info;
728 AudioBackendInfo* (*dfunc)(void);
732 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
733 Glib::Module::get_last_error()) << endmsg;
737 if (!module.get_symbol ("descriptor", func)) {
738 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
739 error << Glib::Module::get_last_error() << endmsg;
743 dfunc = (AudioBackendInfo* (*)(void))func;
745 if (!info->available()) {
749 module.make_resident ();
754 vector<const AudioBackendInfo*>
755 AudioEngine::available_backends() const
757 vector<const AudioBackendInfo*> r;
759 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
760 r.push_back (i->second);
767 AudioEngine::current_backend_name() const
770 return _backend->name();
776 AudioEngine::drop_backend ()
780 // Stopped is needed for Graph to explicitly terminate threads
781 Stopped (); /* EMIT SIGNAL */
782 _backend->drop_device ();
788 boost::shared_ptr<AudioBackend>
789 AudioEngine::set_default_backend ()
791 if (_backends.empty()) {
792 return boost::shared_ptr<AudioBackend>();
795 return set_backend (_backends.begin()->first, "", "");
798 boost::shared_ptr<AudioBackend>
799 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
801 BackendMap::iterator b = _backends.find (name);
803 if (b == _backends.end()) {
804 return boost::shared_ptr<AudioBackend>();
810 if (b->second->instantiate (arg1, arg2)) {
811 throw failed_constructor ();
814 _backend = b->second->factory (*this);
816 } catch (exception& e) {
817 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
818 return boost::shared_ptr<AudioBackend>();
824 /* BACKEND PROXY WRAPPERS */
827 AudioEngine::start (bool for_latency)
837 _processed_frames = 0;
838 last_monitor_check = 0;
840 int error_code = _backend->start (for_latency);
842 if (error_code != 0) {
843 _last_backend_error_string =
844 AudioBackend::get_error_string((AudioBackend::ErrorCode)error_code);
851 _session->set_frame_rate (_backend->sample_rate());
853 if (_session->config.get_jack_time_master()) {
854 _backend->set_time_master (true);
860 Running(); /* EMIT SIGNAL */
867 AudioEngine::stop (bool for_latency)
873 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
879 if (_backend->stop ()) {
887 if (_session && _running &&
888 (_session->state_of_the_state() & Session::Loading) == 0 &&
889 (_session->state_of_the_state() & Session::Deletion) == 0) {
890 // it's not a halt, but should be handled the same way:
891 // disable record, stop transport and I/O processign but save the data.
892 _session->engine_halted ();
896 _processed_frames = 0;
897 _measuring_latency = MeasureNone;
898 _latency_output_port = 0;
899 _latency_input_port = 0;
900 _started_for_latency = false;
905 Stopped (); /* EMIT SIGNAL */
912 AudioEngine::freewheel (bool start_stop)
918 /* _freewheeling will be set when first Freewheel signal occurs */
920 return _backend->freewheel (start_stop);
924 AudioEngine::get_dsp_load() const
929 return _backend->dsp_load ();
933 AudioEngine::is_realtime() const
939 return _backend->is_realtime();
943 AudioEngine::connected() const
949 return _backend->available();
953 AudioEngine::transport_start ()
958 return _backend->transport_start ();
962 AudioEngine::transport_stop ()
967 return _backend->transport_stop ();
971 AudioEngine::transport_state ()
974 return TransportStopped;
976 return _backend->transport_state ();
980 AudioEngine::transport_locate (framepos_t pos)
985 return _backend->transport_locate (pos);
989 AudioEngine::transport_frame()
994 return _backend->transport_frame ();
998 AudioEngine::sample_rate () const
1003 return _backend->sample_rate ();
1007 AudioEngine::samples_per_cycle () const
1012 return _backend->buffer_size ();
1016 AudioEngine::usecs_per_cycle () const
1021 return _backend->usecs_per_cycle ();
1025 AudioEngine::raw_buffer_size (DataType t)
1030 return _backend->raw_buffer_size (t);
1034 AudioEngine::sample_time ()
1039 return _backend->sample_time ();
1043 AudioEngine::sample_time_at_cycle_start ()
1048 return _backend->sample_time_at_cycle_start ();
1052 AudioEngine::samples_since_cycle_start ()
1057 return _backend->samples_since_cycle_start ();
1061 AudioEngine::get_sync_offset (pframes_t& offset) const
1066 return _backend->get_sync_offset (offset);
1070 AudioEngine::create_process_thread (boost::function<void()> func)
1075 return _backend->create_process_thread (func);
1079 AudioEngine::join_process_threads ()
1084 return _backend->join_process_threads ();
1088 AudioEngine::in_process_thread ()
1093 return _backend->in_process_thread ();
1097 AudioEngine::process_thread_count ()
1102 return _backend->process_thread_count ();
1106 AudioEngine::set_device_name (const std::string& name)
1111 return _backend->set_device_name (name);
1115 AudioEngine::set_sample_rate (float sr)
1121 return _backend->set_sample_rate (sr);
1125 AudioEngine::set_buffer_size (uint32_t bufsiz)
1130 return _backend->set_buffer_size (bufsiz);
1134 AudioEngine::set_interleaved (bool yn)
1139 return _backend->set_interleaved (yn);
1143 AudioEngine::set_input_channels (uint32_t ic)
1148 return _backend->set_input_channels (ic);
1152 AudioEngine::set_output_channels (uint32_t oc)
1157 return _backend->set_output_channels (oc);
1161 AudioEngine::set_systemic_input_latency (uint32_t il)
1166 return _backend->set_systemic_input_latency (il);
1170 AudioEngine::set_systemic_output_latency (uint32_t ol)
1175 return _backend->set_systemic_output_latency (ol);
1179 AudioEngine::thread_initialised_for_audio_processing ()
1181 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1184 /* END OF BACKEND PROXY API */
1187 AudioEngine::thread_init_callback (void* arg)
1189 /* make sure that anybody who needs to know about this thread
1193 pthread_set_name (X_("audioengine"));
1195 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1197 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1198 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1200 AsyncMIDIPort::set_process_thread (pthread_self());
1203 /* the special thread created/managed by the backend */
1204 AudioEngine::instance()->_main_thread = new ProcessThread;
1209 AudioEngine::sync_callback (TransportState state, framepos_t position)
1212 return _session->backend_sync_callback (state, position);
1218 AudioEngine::freewheel_callback (bool onoff)
1220 _freewheeling = onoff;
1224 AudioEngine::latency_callback (bool for_playback)
1227 _session->update_latency (for_playback);
1232 AudioEngine::update_latencies ()
1235 _backend->update_latencies ();
1240 AudioEngine::halted_callback (const char* why)
1242 if (_in_destructor) {
1243 /* everything is under control */
1249 Port::PortDrop (); /* EMIT SIGNAL */
1251 if (!_started_for_latency) {
1252 Halted (why); /* EMIT SIGNAL */
1257 AudioEngine::setup_required () const
1260 if (_backend->info().already_configured())
1263 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1272 AudioEngine::prepare_for_latency_measurement ()
1275 _stopped_for_latency = true;
1280 _started_for_latency = true;
1288 AudioEngine::start_latency_detection (bool for_midi)
1291 if (prepare_for_latency_measurement ()) {
1296 PortEngine& pe (port_engine());
1304 /* find the ports we will connect to */
1306 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1307 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1314 /* create the ports we will use to read/write data */
1316 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1320 if (pe.connect (_latency_output_port, _latency_output_name)) {
1321 pe.unregister_port (_latency_output_port);
1326 const string portname ("latency_in");
1327 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1328 pe.unregister_port (_latency_input_port);
1329 pe.unregister_port (_latency_output_port);
1333 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1334 pe.unregister_port (_latency_input_port);
1335 pe.unregister_port (_latency_output_port);
1340 _mididm = new MIDIDM (sample_rate());
1344 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1348 if (pe.connect (_latency_output_port, _latency_output_name)) {
1349 pe.unregister_port (_latency_output_port);
1354 const string portname ("latency_in");
1355 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1356 pe.unregister_port (_latency_input_port);
1357 pe.unregister_port (_latency_output_port);
1361 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1362 pe.unregister_port (_latency_input_port);
1363 pe.unregister_port (_latency_output_port);
1368 _mtdm = new MTDM (sample_rate());
1373 _latency_signal_latency = 0;
1374 lr = pe.get_latency_range (in, false);
1375 _latency_signal_latency = lr.max;
1376 lr = pe.get_latency_range (out, true);
1377 _latency_signal_latency += lr.max;
1379 /* all created and connected, lets go */
1380 _latency_flush_frames = samples_per_cycle();
1381 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1387 AudioEngine::stop_latency_detection ()
1389 _measuring_latency = MeasureNone;
1391 if (_latency_output_port) {
1392 port_engine().unregister_port (_latency_output_port);
1393 _latency_output_port = 0;
1395 if (_latency_input_port) {
1396 port_engine().unregister_port (_latency_input_port);
1397 _latency_input_port = 0;
1402 if (_stopped_for_latency) {
1406 _stopped_for_latency = false;
1407 _started_for_latency = false;
1411 AudioEngine::set_latency_output_port (const string& name)
1413 _latency_output_name = name;
1417 AudioEngine::set_latency_input_port (const string& name)
1419 _latency_input_name = name;