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)
870 bool stop_engine = true;
876 Glib::Threads::Mutex::Lock pl (_process_lock, Glib::Threads::NOT_LOCK);
882 if (for_latency && _backend->can_change_systemic_latency_when_running()) {
885 if (_backend->stop ()) {
895 if (_session && _running && stop_engine &&
896 (_session->state_of_the_state() & Session::Loading) == 0 &&
897 (_session->state_of_the_state() & Session::Deletion) == 0) {
898 // it's not a halt, but should be handled the same way:
899 // disable record, stop transport and I/O processign but save the data.
900 _session->engine_halted ();
906 _processed_frames = 0;
907 _measuring_latency = MeasureNone;
908 _latency_output_port = 0;
909 _latency_input_port = 0;
910 _started_for_latency = false;
916 if (!for_latency && stop_engine) {
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
938 if (!_backend || !_running) {
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);
1191 AudioEngine::thread_initialised_for_audio_processing ()
1193 return SessionEvent::has_per_thread_pool () && AsyncMIDIPort::is_process_thread();
1196 /* END OF BACKEND PROXY API */
1199 AudioEngine::thread_init_callback (void* arg)
1201 /* make sure that anybody who needs to know about this thread
1205 pthread_set_name (X_("audioengine"));
1207 SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
1209 PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096);
1210 PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128);
1212 AsyncMIDIPort::set_process_thread (pthread_self());
1215 /* the special thread created/managed by the backend */
1216 AudioEngine::instance()->_main_thread = new ProcessThread;
1221 AudioEngine::sync_callback (TransportState state, framepos_t position)
1224 return _session->backend_sync_callback (state, position);
1230 AudioEngine::freewheel_callback (bool onoff)
1232 _freewheeling = onoff;
1236 AudioEngine::latency_callback (bool for_playback)
1239 _session->update_latency (for_playback);
1244 AudioEngine::update_latencies ()
1247 _backend->update_latencies ();
1252 AudioEngine::halted_callback (const char* why)
1254 if (_in_destructor) {
1255 /* everything is under control */
1261 Port::PortDrop (); /* EMIT SIGNAL */
1263 if (!_started_for_latency) {
1264 Halted (why); /* EMIT SIGNAL */
1269 AudioEngine::setup_required () const
1272 if (_backend->info().already_configured())
1275 if (_backends.size() == 1 && _backends.begin()->second->already_configured()) {
1284 AudioEngine::prepare_for_latency_measurement ()
1290 if (_backend->can_change_systemic_latency_when_running()) {
1294 _backend->set_systemic_input_latency (0);
1295 _backend->set_systemic_output_latency (0);
1300 _stopped_for_latency = true;
1307 _started_for_latency = true;
1313 AudioEngine::start_latency_detection (bool for_midi)
1315 if (prepare_for_latency_measurement ()) {
1319 PortEngine& pe (port_engine());
1327 /* find the ports we will connect to */
1329 PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name);
1330 PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name);
1337 /* create the ports we will use to read/write data */
1339 if ((_latency_output_port = pe.register_port ("latency_out", DataType::MIDI, 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::MIDI, 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 _mididm = new MIDIDM (sample_rate());
1367 if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) {
1371 if (pe.connect (_latency_output_port, _latency_output_name)) {
1372 pe.unregister_port (_latency_output_port);
1377 const string portname ("latency_in");
1378 if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) {
1379 pe.unregister_port (_latency_input_port);
1380 pe.unregister_port (_latency_output_port);
1384 if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) {
1385 pe.unregister_port (_latency_input_port);
1386 pe.unregister_port (_latency_output_port);
1391 _mtdm = new MTDM (sample_rate());
1396 _latency_signal_latency = 0;
1397 lr = pe.get_latency_range (in, false);
1398 _latency_signal_latency = lr.max;
1399 lr = pe.get_latency_range (out, true);
1400 _latency_signal_latency += lr.max;
1402 /* all created and connected, lets go */
1403 _latency_flush_frames = samples_per_cycle();
1404 _measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
1410 AudioEngine::stop_latency_detection ()
1412 _measuring_latency = MeasureNone;
1414 if (_latency_output_port) {
1415 port_engine().unregister_port (_latency_output_port);
1416 _latency_output_port = 0;
1418 if (_latency_input_port) {
1419 port_engine().unregister_port (_latency_input_port);
1420 _latency_input_port = 0;
1423 if (!_backend->can_change_systemic_latency_when_running()) {
1427 if (_stopped_for_latency) {
1431 _stopped_for_latency = false;
1432 _started_for_latency = false;
1436 AudioEngine::set_latency_output_port (const string& name)
1438 _latency_output_name = name;
1442 AudioEngine::set_latency_input_port (const string& name)
1444 _latency_input_name = name;