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 , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1))
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 reset_silence_countdown ();
103 start_hw_event_processing();
104 discover_backends ();
107 AudioEngine::~AudioEngine ()
109 _in_destructor = true;
110 stop_hw_event_processing();
112 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
113 i->second->deinstantiate();
118 AudioEngine::create ()
124 _instance = new AudioEngine ();
130 AudioEngine::split_cycle (pframes_t offset)
132 /* caller must hold process lock */
134 Port::increment_global_port_buffer_offset (offset);
136 /* tell all Ports that we're going to start a new (split) cycle */
138 boost::shared_ptr<Ports> p = ports.reader();
140 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
141 i->second->cycle_split ();
146 AudioEngine::sample_rate_change (pframes_t nframes)
148 /* check for monitor input change every 1/10th of second */
150 monitor_check_interval = nframes / 10;
151 last_monitor_check = 0;
154 _session->set_frame_rate (nframes);
157 SampleRateChanged (nframes); /* EMIT SIGNAL */
159 #ifdef SILENCE_AFTER_SECONDS
160 _silence_countdown = nframes * SILENCE_AFTER_SECONDS;
167 AudioEngine::buffer_size_change (pframes_t bufsiz)
170 _session->set_block_size (bufsiz);
171 last_monitor_check = 0;
174 BufferSizeChanged (bufsiz); /* EMIT SIGNAL */
179 /** Method called by our ::process_thread when there is work to be done.
180 * @param nframes Number of frames to process.
183 __attribute__((annotate("realtime")))
186 AudioEngine::process_callback (pframes_t nframes)
188 Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
193 /// The number of frames that will have been processed when we've finished
194 pframes_t next_processed_frames;
196 /* handle wrap around of total frames counter */
198 if (max_framepos - _processed_frames < nframes) {
199 next_processed_frames = nframes - (max_framepos - _processed_frames);
201 next_processed_frames = _processed_frames + nframes;
205 /* return having done nothing */
209 /* really only JACK requires this
210 * (other backends clear the output buffers
211 * before the process_callback. it may even be
212 * jack/alsa only). but better safe than sorry.
214 PortManager::silence_outputs (nframes);
218 bool return_after_remove_check = false;
220 if (_measuring_latency == MeasureAudio && _mtdm) {
221 /* run a normal cycle from the perspective of the PortManager
222 so that we get silence on all registered ports.
224 we overwrite the silence on the two ports used for latency
228 PortManager::cycle_start (nframes);
229 PortManager::silence (nframes);
231 if (_latency_input_port && _latency_output_port) {
232 PortEngine& pe (port_engine());
234 Sample* in = (Sample*) pe.get_buffer (_latency_input_port, nframes);
235 Sample* out = (Sample*) pe.get_buffer (_latency_output_port, nframes);
237 _mtdm->process (nframes, in, out);
240 PortManager::cycle_end (nframes);
241 return_after_remove_check = true;
243 } else if (_measuring_latency == MeasureMIDI && _mididm) {
244 /* run a normal cycle from the perspective of the PortManager
245 so that we get silence on all registered ports.
247 we overwrite the silence on the two ports used for latency
251 PortManager::cycle_start (nframes);
252 PortManager::silence (nframes);
254 if (_latency_input_port && _latency_output_port) {
255 PortEngine& pe (port_engine());
257 _mididm->process (nframes, pe,
258 pe.get_buffer (_latency_input_port, nframes),
259 pe.get_buffer (_latency_output_port, nframes));
262 PortManager::cycle_end (nframes);
263 return_after_remove_check = true;
265 } else if (_latency_flush_frames) {
267 /* wait for the appropriate duration for the MTDM signal to
268 * drain from the ports before we revert to normal behaviour.
271 PortManager::cycle_start (nframes);
272 PortManager::silence (nframes);
273 PortManager::cycle_end (nframes);
275 if (_latency_flush_frames > nframes) {
276 _latency_flush_frames -= nframes;
278 _latency_flush_frames = 0;
281 return_after_remove_check = true;
284 if (session_remove_pending) {
286 /* perform the actual session removal */
288 if (session_removal_countdown < 0) {
290 /* fade out over 1 second */
291 session_removal_countdown = sample_rate()/2;
292 session_removal_gain = GAIN_COEFF_UNITY;
293 session_removal_gain_step = 1.0/session_removal_countdown;
295 } else if (session_removal_countdown > 0) {
297 /* we'll be fading audio out.
299 if this is the last time we do this as part
300 of session removal, do a MIDI panic now
301 to get MIDI stopped. This relies on the fact
302 that "immediate data" (aka "out of band data") from
303 MIDI tracks is *appended* after any other data,
304 so that it emerges after any outbound note ons, etc.
307 if (session_removal_countdown <= nframes) {
308 _session->midi_panic ();
314 session_removal_countdown = -1; // reset to "not in progress"
315 session_remove_pending = false;
316 session_removed.signal(); // wakes up thread that initiated session removal
320 if (return_after_remove_check) {
326 if (!_freewheeling) {
327 PortManager::cycle_start (nframes);
328 PortManager::cycle_end (nframes);
331 _processed_frames = next_processed_frames;
336 /* tell all relevant objects that we're starting a new cycle */
338 InternalSend::CycleStart (nframes);
340 /* tell all Ports that we're starting a new cycle */
342 PortManager::cycle_start (nframes);
344 /* test if we are freewheeling and there are freewheel signals connected.
345 ardour should act normally even when freewheeling unless /it/ is
346 exporting (which is what Freewheel.empty() tests for).
349 if (_freewheeling && !Freewheel.empty()) {
352 _session->process (nframes);
356 PortManager::cycle_end (nframes);
361 _processed_frames = next_processed_frames;
365 if (last_monitor_check + monitor_check_interval < next_processed_frames) {
367 PortManager::check_monitoring ();
368 last_monitor_check = next_processed_frames;
371 #ifdef SILENCE_AFTER_SECONDS
373 bool was_silent = (_silence_countdown == 0);
375 if (_silence_countdown >= nframes) {
376 _silence_countdown -= nframes;
378 _silence_countdown = 0;
381 if (!was_silent && _silence_countdown == 0) {
383 BecameSilent (); /* EMIT SIGNAL */
386 if (_silence_countdown == 0 || _session->silent()) {
387 PortManager::silence (nframes);
391 if (_session->silent()) {
392 PortManager::silence (nframes);
396 if (session_remove_pending && session_removal_countdown) {
398 PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
400 if (session_removal_countdown > nframes) {
401 session_removal_countdown -= nframes;
403 session_removal_countdown = 0;
406 session_removal_gain -= (nframes * session_removal_gain_step);
409 PortManager::cycle_end (nframes);
411 _processed_frames = next_processed_frames;
419 AudioEngine::reset_silence_countdown ()
421 #ifdef SILENCE_AFTER_SECONDS
422 double sr = 48000; /* default in case there is no backend */
426 _silence_countdown = max (60 * sr, /* 60 seconds */
427 sr * (SILENCE_AFTER_SECONDS / ::pow (2.0, (double) _silence_hit_cnt)));
433 AudioEngine::launch_device_control_app()
435 if (_state_lock.trylock () ) {
436 _backend->launch_control_app ();
437 _state_lock.unlock ();
443 AudioEngine::request_backend_reset()
445 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
446 g_atomic_int_inc (&_hw_reset_request_count);
447 _hw_reset_condition.signal ();
451 AudioEngine::backend_reset_requested()
453 return g_atomic_int_get (&_hw_reset_request_count);
457 AudioEngine::do_reset_backend()
459 SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 1024);
461 Glib::Threads::Mutex::Lock guard (_reset_request_lock);
463 while (!_stop_hw_reset_processing) {
465 if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
467 _reset_request_lock.unlock();
469 Glib::Threads::RecMutex::Lock pl (_state_lock);
470 g_atomic_int_dec_and_test (&_hw_reset_request_count);
472 std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
473 DeviceResetStarted(); // notify about device reset to be started
475 // backup the device name
476 std::string name = _backend->device_name ();
478 std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
479 if ( ( 0 == stop () ) &&
480 ( 0 == _backend->reset_device () ) &&
481 ( 0 == start () ) ) {
483 std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
485 // inform about possible changes
486 BufferSizeChanged (_backend->buffer_size() );
487 DeviceResetFinished(); // notify about device reset finish
491 DeviceResetFinished(); // notify about device reset finish
492 // we've got an error
496 std::cout << "AudioEngine::RESET::Done." << std::endl;
498 _reset_request_lock.lock();
502 _hw_reset_condition.wait (_reset_request_lock);
508 AudioEngine::request_device_list_update()
510 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
511 g_atomic_int_inc (&_hw_devicelist_update_count);
512 _hw_devicelist_update_condition.signal ();
517 AudioEngine::do_devicelist_update()
519 SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512);
521 Glib::Threads::Mutex::Lock guard (_devicelist_update_lock);
523 while (!_stop_hw_devicelist_processing) {
525 if (_hw_devicelist_update_count) {
527 _devicelist_update_lock.unlock();
529 Glib::Threads::RecMutex::Lock pl (_state_lock);
531 g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
532 DeviceListChanged (); /* EMIT SIGNAL */
534 _devicelist_update_lock.lock();
537 _hw_devicelist_update_condition.wait (_devicelist_update_lock);
544 AudioEngine::start_hw_event_processing()
546 if (_hw_reset_event_thread == 0) {
547 g_atomic_int_set(&_hw_reset_request_count, 0);
548 g_atomic_int_set(&_stop_hw_reset_processing, 0);
549 _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this));
552 if (_hw_devicelist_update_thread == 0) {
553 g_atomic_int_set(&_hw_devicelist_update_count, 0);
554 g_atomic_int_set(&_stop_hw_devicelist_processing, 0);
555 _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this));
561 AudioEngine::stop_hw_event_processing()
563 if (_hw_reset_event_thread) {
564 g_atomic_int_set(&_stop_hw_reset_processing, 1);
565 g_atomic_int_set(&_hw_reset_request_count, 0);
566 _hw_reset_condition.signal ();
567 _hw_reset_event_thread->join ();
568 _hw_reset_event_thread = 0;
571 if (_hw_devicelist_update_thread) {
572 g_atomic_int_set(&_stop_hw_devicelist_processing, 1);
573 g_atomic_int_set(&_hw_devicelist_update_count, 0);
574 _hw_devicelist_update_condition.signal ();
575 _hw_devicelist_update_thread->join ();
576 _hw_devicelist_update_thread = 0;
583 AudioEngine::set_session (Session *s)
585 Glib::Threads::Mutex::Lock pl (_process_lock);
587 SessionHandlePtr::set_session (s);
591 pframes_t blocksize = samples_per_cycle ();
593 PortManager::cycle_start (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);
602 _session->process (blocksize);
604 PortManager::cycle_end (blocksize);
609 AudioEngine::remove_session ()
611 Glib::Threads::Mutex::Lock lm (_process_lock);
616 session_remove_pending = true;
617 /* signal the start of the fade out countdown */
618 session_removal_countdown = -1;
619 session_removed.wait(_process_lock);
623 SessionHandlePtr::set_session (0);
631 AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs)
633 #ifdef USE_TRACKS_CODE_FEATURES
635 _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
644 /* called from a signal handler for SIGPIPE */
649 AudioEngine::reset_timebase ()
652 if (_session->config.get_jack_time_master()) {
653 _backend->set_time_master (true);
655 _backend->set_time_master (false);
663 AudioEngine::destroy ()
670 AudioEngine::discover_backends ()
672 vector<std::string> backend_modules;
676 Glib::PatternSpec so_extension_pattern("*backend.so");
677 Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
679 #if defined(PLATFORM_WINDOWS) && defined(DEBUGGABLE_BACKENDS)
680 #if defined(DEBUG) || defined(_DEBUG)
681 Glib::PatternSpec dll_extension_pattern("*backendD.dll");
683 Glib::PatternSpec dll_extension_pattern("*backendRDC.dll");
686 Glib::PatternSpec dll_extension_pattern("*backend.dll");
689 find_files_matching_pattern (backend_modules, backend_search_path (),
690 so_extension_pattern);
692 find_files_matching_pattern (backend_modules, backend_search_path (),
693 dylib_extension_pattern);
695 find_files_matching_pattern (backend_modules, backend_search_path (),
696 dll_extension_pattern);
698 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("looking for backends in %1\n", backend_search_path().to_string()));
700 for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
702 AudioBackendInfo* info;
704 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Checking possible backend in %1\n", *i));
706 if ((info = backend_discover (*i)) != 0) {
707 _backends.insert (make_pair (info->name, info));
711 DEBUG_TRACE (DEBUG::AudioEngine, string_compose ("Found %1 backends\n", _backends.size()));
713 return _backends.size();
717 AudioEngine::backend_discover (const string& path)
719 #ifdef PLATFORM_WINDOWS
720 // do not show popup dialog (e.g. missing libjack.dll)
721 // win7+ should use SetThreadErrorMode()
722 SetErrorMode(SEM_FAILCRITICALERRORS);
724 Glib::Module module (path);
725 #ifdef PLATFORM_WINDOWS
726 SetErrorMode(0); // reset to system default
728 AudioBackendInfo* info;
729 AudioBackendInfo* (*dfunc)(void);
733 error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
734 Glib::Module::get_last_error()) << endmsg;
738 if (!module.get_symbol ("descriptor", func)) {
739 error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
740 error << Glib::Module::get_last_error() << endmsg;
744 dfunc = (AudioBackendInfo* (*)(void))func;
746 if (!info->available()) {
750 module.make_resident ();
755 vector<const AudioBackendInfo*>
756 AudioEngine::available_backends() const
758 vector<const AudioBackendInfo*> r;
760 for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
761 r.push_back (i->second);
768 AudioEngine::current_backend_name() const
771 return _backend->name();
777 AudioEngine::drop_backend ()
781 // Stopped is needed for Graph to explicitly terminate threads
782 Stopped (); /* EMIT SIGNAL */
783 _backend->drop_device ();
789 boost::shared_ptr<AudioBackend>
790 AudioEngine::set_default_backend ()
792 if (_backends.empty()) {
793 return boost::shared_ptr<AudioBackend>();
796 return set_backend (_backends.begin()->first, "", "");
799 boost::shared_ptr<AudioBackend>
800 AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
802 BackendMap::iterator b = _backends.find (name);
804 if (b == _backends.end()) {
805 return boost::shared_ptr<AudioBackend>();
811 if (b->second->instantiate (arg1, arg2)) {
812 throw failed_constructor ();
815 _backend = b->second->factory (*this);
817 } catch (exception& e) {
818 error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg;
819 return boost::shared_ptr<AudioBackend>();
825 /* BACKEND PROXY WRAPPERS */
828 AudioEngine::start (bool for_latency)
838 _processed_frames = 0;
839 last_monitor_check = 0;
841 int error_code = _backend->start (for_latency);
843 if (error_code != 0) {
844 _last_backend_error_string =
845 AudioBackend::get_error_string((AudioBackend::ErrorCode)error_code);
852 _session->set_frame_rate (_backend->sample_rate());
854 if (_session->config.get_jack_time_master()) {
855 _backend->set_time_master (true);
861 Running(); /* EMIT SIGNAL */
868 AudioEngine::stop (bool for_latency)
874 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
880 if (_backend->stop ()) {
888 if (_session && _running &&
889 (_session->state_of_the_state() & Session::Loading) == 0 &&
890 (_session->state_of_the_state() & Session::Deletion) == 0) {
891 // it's not a halt, but should be handled the same way:
892 // disable record, stop transport and I/O processign but save the data.
893 _session->engine_halted ();
897 _processed_frames = 0;
898 _measuring_latency = MeasureNone;
899 _latency_output_port = 0;
900 _latency_input_port = 0;
901 _started_for_latency = false;
906 Stopped (); /* EMIT SIGNAL */
913 AudioEngine::freewheel (bool start_stop)
919 /* _freewheeling will be set when first Freewheel signal occurs */
921 return _backend->freewheel (start_stop);
925 AudioEngine::get_dsp_load() const
927 if (!_backend || !_running) {
930 return _backend->dsp_load ();
934 AudioEngine::is_realtime() const
940 return _backend->is_realtime();
944 AudioEngine::connected() const
950 return _backend->available();
954 AudioEngine::transport_start ()
959 return _backend->transport_start ();
963 AudioEngine::transport_stop ()
968 return _backend->transport_stop ();
972 AudioEngine::transport_state ()
975 return TransportStopped;
977 return _backend->transport_state ();
981 AudioEngine::transport_locate (framepos_t pos)
986 return _backend->transport_locate (pos);
990 AudioEngine::transport_frame()
995 return _backend->transport_frame ();
999 AudioEngine::sample_rate () const
1004 return _backend->sample_rate ();
1008 AudioEngine::samples_per_cycle () const
1013 return _backend->buffer_size ();
1017 AudioEngine::usecs_per_cycle () const
1022 return _backend->usecs_per_cycle ();
1026 AudioEngine::raw_buffer_size (DataType t)
1031 return _backend->raw_buffer_size (t);
1035 AudioEngine::sample_time ()
1040 return _backend->sample_time ();
1044 AudioEngine::sample_time_at_cycle_start ()
1049 return _backend->sample_time_at_cycle_start ();
1053 AudioEngine::samples_since_cycle_start ()
1058 return _backend->samples_since_cycle_start ();
1062 AudioEngine::get_sync_offset (pframes_t& offset) const
1067 return _backend->get_sync_offset (offset);
1071 AudioEngine::create_process_thread (boost::function<void()> func)
1076 return _backend->create_process_thread (func);
1080 AudioEngine::join_process_threads ()
1085 return _backend->join_process_threads ();
1089 AudioEngine::in_process_thread ()
1094 return _backend->in_process_thread ();
1098 AudioEngine::process_thread_count ()
1103 return _backend->process_thread_count ();
1107 AudioEngine::set_device_name (const std::string& name)
1112 return _backend->set_device_name (name);
1116 AudioEngine::set_sample_rate (float sr)
1122 return _backend->set_sample_rate (sr);
1126 AudioEngine::set_buffer_size (uint32_t bufsiz)
1131 return _backend->set_buffer_size (bufsiz);
1135 AudioEngine::set_interleaved (bool yn)
1140 return _backend->set_interleaved (yn);
1144 AudioEngine::set_input_channels (uint32_t ic)
1149 return _backend->set_input_channels (ic);
1153 AudioEngine::set_output_channels (uint32_t oc)
1158 return _backend->set_output_channels (oc);
1162 AudioEngine::set_systemic_input_latency (uint32_t il)
1167 return _backend->set_systemic_input_latency (il);
1171 AudioEngine::set_systemic_output_latency (uint32_t ol)
1176 return _backend->set_systemic_output_latency (ol);
1180 AudioEngine::thread_initialised_for_audio_processing ()
1182 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1185 /* END OF BACKEND PROXY API */
1188 AudioEngine::thread_init_callback (void* arg)
1190 /* make sure that anybody who needs to know about this thread
1194 pthread_set_name (X_("audioengine"));
1196 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1198 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1199 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1201 AsyncMIDIPort::set_process_thread (pthread_self());
1204 /* the special thread created/managed by the backend */
1205 AudioEngine::instance()->_main_thread = new ProcessThread;
1210 AudioEngine::sync_callback (TransportState state, framepos_t position)
1213 return _session->backend_sync_callback (state, position);
1219 AudioEngine::freewheel_callback (bool onoff)
1221 _freewheeling = onoff;
1225 AudioEngine::latency_callback (bool for_playback)
1228 _session->update_latency (for_playback);
1233 AudioEngine::update_latencies ()
1236 _backend->update_latencies ();
1241 AudioEngine::halted_callback (const char* why)
1243 if (_in_destructor) {
1244 /* everything is under control */
1250 Port::PortDrop (); /* EMIT SIGNAL */
1252 if (!_started_for_latency) {
1253 Halted (why); /* EMIT SIGNAL */
1258 AudioEngine::setup_required () const
1261 if (_backend->info().already_configured())
1264 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1273 AudioEngine::prepare_for_latency_measurement ()
1276 _stopped_for_latency = true;
1283 _started_for_latency = true;
1289 AudioEngine::start_latency_detection (bool for_midi)
1292 if (prepare_for_latency_measurement ()) {
1297 PortEngine& pe (port_engine());
1305 /* find the ports we will connect to */
1307 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1308 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1315 /* create the ports we will use to read/write data */
1317 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, IsOutput)) == 0) {
1321 if (pe.connect (_latency_output_port, _latency_output_name)) {
1322 pe.unregister_port (_latency_output_port);
1327 const string portname ("latency_in");
1328 if ((_latency_input_port = pe.register_port (portname, DataType::MIDI, IsInput)) == 0) {
1329 pe.unregister_port (_latency_input_port);
1330 pe.unregister_port (_latency_output_port);
1334 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1335 pe.unregister_port (_latency_input_port);
1336 pe.unregister_port (_latency_output_port);
1341 _mididm = new MIDIDM (sample_rate());
1345 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1349 if (pe.connect (_latency_output_port, _latency_output_name)) {
1350 pe.unregister_port (_latency_output_port);
1355 const string portname ("latency_in");
1356 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1357 pe.unregister_port (_latency_input_port);
1358 pe.unregister_port (_latency_output_port);
1362 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1363 pe.unregister_port (_latency_input_port);
1364 pe.unregister_port (_latency_output_port);
1369 _mtdm = new MTDM (sample_rate());
1374 _latency_signal_latency = 0;
1375 lr = pe.get_latency_range (in, false);
1376 _latency_signal_latency = lr.max;
1377 lr = pe.get_latency_range (out, true);
1378 _latency_signal_latency += lr.max;
1380 /* all created and connected, lets go */
1381 _latency_flush_frames = samples_per_cycle();
1382 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1388 AudioEngine::stop_latency_detection ()
1390 _measuring_latency = MeasureNone;
1392 if (_latency_output_port) {
1393 port_engine().unregister_port (_latency_output_port);
1394 _latency_output_port = 0;
1396 if (_latency_input_port) {
1397 port_engine().unregister_port (_latency_input_port);
1398 _latency_input_port = 0;
1403 if (_stopped_for_latency) {
1407 _stopped_for_latency = false;
1408 _started_for_latency = false;
1412 AudioEngine::set_latency_output_port (const string& name)
1414 _latency_output_name = name;
1418 AudioEngine::set_latency_input_port (const string& name)
1420 _latency_input_name = name;