X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=84bfab11f8b18bf4e390ede04ca2f2a107915b67;hb=0a52b325f4e1eaf39be65a24f9a594ffe1f66e79;hp=50284128de31d25571b3183fa2e8b4b1c1786db3;hpb=4dc63966f0872efe768dad61eb9b8785d06b92d1;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 50284128de..84bfab11f8 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -63,6 +63,8 @@ using namespace PBD; AudioEngine* AudioEngine::_instance = 0; +static gint audioengine_thread_cnt = 1; + #ifdef SILENCE_AFTER #define SILENCE_AFTER_SECONDS 600 #endif @@ -87,6 +89,7 @@ AudioEngine::AudioEngine () , _stopped_for_latency (false) , _started_for_latency (false) , _in_destructor (false) + , _last_backend_error_string(AudioBackend::get_error_string((AudioBackend::ErrorCode)-1)) , _hw_reset_event_thread(0) , _hw_reset_request_count(0) , _stop_hw_reset_processing(0) @@ -111,6 +114,7 @@ AudioEngine::~AudioEngine () for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) { i->second->deinstantiate(); } + delete _main_thread; } AudioEngine* @@ -121,7 +125,7 @@ AudioEngine::create () } _instance = new AudioEngine (); - + return _instance; } @@ -158,7 +162,7 @@ AudioEngine::sample_rate_change (pframes_t nframes) #ifdef SILENCE_AFTER_SECONDS _silence_countdown = nframes * SILENCE_AFTER_SECONDS; #endif - + return 0; } @@ -214,16 +218,36 @@ AudioEngine::process_callback (pframes_t nframes) return 0; } + /* The coreaudio-backend calls thread_init_callback() if + * the hardware changes or pthread_self() changes. + * + * However there are cases when neither holds true, yet + * the thread-pool changes: e.g. connect a headphone to + * a shared mic/headphone jack. + * It's probably related to, or caused by clocksource changes. + * + * For reasons yet unknown Glib::Threads::Private() can + * use a different thread-private in the same pthread + * (coreaudio render callback). + * + * Coreaudio must set something which influences + * pthread_key_t uniqness or reset the key using + * pthread_getspecific(). + */ + if (! SessionEvent::has_per_thread_pool ()) { + thread_init_callback (NULL); + } + bool return_after_remove_check = false; if (_measuring_latency == MeasureAudio && _mtdm) { /* run a normal cycle from the perspective of the PortManager so that we get silence on all registered ports. - + we overwrite the silence on the two ports used for latency measurement. */ - + PortManager::cycle_start (nframes); PortManager::silence (nframes); @@ -262,7 +286,7 @@ AudioEngine::process_callback (pframes_t nframes) return_after_remove_check = true; } else if (_latency_flush_frames) { - + /* wait for the appropriate duration for the MTDM signal to * drain from the ports before we revert to normal behaviour. */ @@ -270,7 +294,7 @@ AudioEngine::process_callback (pframes_t nframes) PortManager::cycle_start (nframes); PortManager::silence (nframes); PortManager::cycle_end (nframes); - + if (_latency_flush_frames > nframes) { _latency_flush_frames -= nframes; } else { @@ -294,7 +318,7 @@ AudioEngine::process_callback (pframes_t nframes) } else if (session_removal_countdown > 0) { /* we'll be fading audio out. - + if this is the last time we do this as part of session removal, do a MIDI panic now to get MIDI stopped. This relies on the fact @@ -362,7 +386,7 @@ AudioEngine::process_callback (pframes_t nframes) } if (last_monitor_check + monitor_check_interval < next_processed_frames) { - + PortManager::check_monitoring (); last_monitor_check = next_processed_frames; } @@ -370,7 +394,7 @@ AudioEngine::process_callback (pframes_t nframes) #ifdef SILENCE_AFTER_SECONDS bool was_silent = (_silence_countdown == 0); - + if (_silence_countdown >= nframes) { _silence_countdown -= nframes; } else { @@ -385,17 +409,17 @@ AudioEngine::process_callback (pframes_t nframes) if (_silence_countdown == 0 || _session->silent()) { PortManager::silence (nframes); } - -#else + +#else if (_session->silent()) { - PortManager::silence (nframes); + PortManager::silence (nframes, _session); } #endif - + if (session_remove_pending && session_removal_countdown) { PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes); - + if (session_removal_countdown > nframes) { session_removal_countdown -= nframes; } else { @@ -410,7 +434,7 @@ AudioEngine::process_callback (pframes_t nframes) _processed_frames = next_processed_frames; PT_TIMING_CHECK (2); - + return 0; } @@ -462,12 +486,12 @@ AudioEngine::do_reset_backend() while (!_stop_hw_reset_processing) { if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) { - + _reset_request_lock.unlock(); - + Glib::Threads::RecMutex::Lock pl (_state_lock); g_atomic_int_dec_and_test (&_hw_reset_request_count); - + std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl; DeviceResetStarted(); // notify about device reset to be started @@ -478,9 +502,9 @@ AudioEngine::do_reset_backend() if ( ( 0 == stop () ) && ( 0 == _backend->reset_device () ) && ( 0 == start () ) ) { - + std::cout << "AudioEngine::RESET::Engine started..." << std::endl; - + // inform about possible changes BufferSizeChanged (_backend->buffer_size() ); DeviceResetFinished(); // notify about device reset finish @@ -491,7 +515,7 @@ AudioEngine::do_reset_backend() // we've got an error DeviceError(); } - + std::cout << "AudioEngine::RESET::Done." << std::endl; _reset_request_lock.lock(); @@ -574,7 +598,7 @@ AudioEngine::stop_hw_event_processing() _hw_devicelist_update_thread->join (); _hw_devicelist_update_thread = 0; } - + } @@ -633,7 +657,7 @@ AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_out if (_session) { _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs); } -#endif +#endif } @@ -733,13 +757,13 @@ AudioEngine::backend_discover (const string& path) Glib::Module::get_last_error()) << endmsg; return 0; } - + if (!module.get_symbol ("descriptor", func)) { error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg; error << Glib::Module::get_last_error() << endmsg; return 0; } - + dfunc = (AudioBackendInfo* (*)(void))func; info = dfunc(); if (!info->available()) { @@ -747,7 +771,7 @@ AudioEngine::backend_discover (const string& path) } module.make_resident (); - + return info; } @@ -755,7 +779,7 @@ vector AudioEngine::available_backends() const { vector r; - + for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) { r.push_back (i->second); } @@ -805,12 +829,12 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons } drop_backend (); - + try { if (b->second->instantiate (arg1, arg2)) { throw failed_constructor (); } - + _backend = b->second->factory (*this); } catch (exception& e) { @@ -846,26 +870,28 @@ AudioEngine::start (bool for_latency) } _running = true; - + if (_session) { _session->set_frame_rate (_backend->sample_rate()); - + if (_session->config.get_jack_time_master()) { _backend->set_time_master (true); } } - + if (!for_latency) { Running(); /* EMIT SIGNAL */ } - + return 0; } int AudioEngine::stop (bool for_latency) { + bool stop_engine = true; + if (!_backend) { return 0; } @@ -876,15 +902,20 @@ AudioEngine::stop (bool for_latency) pl.acquire (); } - if (_backend->stop ()) { - return -1; + if (for_latency && _backend->can_change_systemic_latency_when_running()) { + stop_engine = false; + } else { + if (_backend->stop ()) { + pl.release (); + return -1; + } } if (pl.locked ()) { pl.release (); } - if (_session && _running && + if (_session && _running && stop_engine && (_session->state_of_the_state() & Session::Loading) == 0 && (_session->state_of_the_state() & Session::Deletion) == 0) { // it's not a halt, but should be handled the same way: @@ -892,19 +923,23 @@ AudioEngine::stop (bool for_latency) _session->engine_halted (); } - _running = false; + if (stop_engine) { + _running = false; + } _processed_frames = 0; _measuring_latency = MeasureNone; _latency_output_port = 0; _latency_input_port = 0; _started_for_latency = false; - - Port::PortDrop (); - if (!for_latency) { + if (stop_engine) { + Port::PortDrop (); + } + + if (!for_latency && stop_engine) { Stopped (); /* EMIT SIGNAL */ } - + return 0; } @@ -923,7 +958,7 @@ AudioEngine::freewheel (bool start_stop) float AudioEngine::get_dsp_load() const { - if (!_backend) { + if (!_backend || !_running) { return 0.0; } return _backend->dsp_load (); @@ -1192,14 +1227,15 @@ AudioEngine::thread_init_callback (void* arg) pthread_set_name (X_("audioengine")); - SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512); - - PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096); - PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128); + const int thread_num = g_atomic_int_add (&audioengine_thread_cnt, 1); + const string thread_name = string_compose (X_("AudioEngine %1"), thread_num); + SessionEvent::create_per_thread_pool (thread_name, 512); + PBD::notify_event_loops_about_thread_creation (pthread_self(), thread_name, 4096); AsyncMIDIPort::set_process_thread (pthread_self()); if (arg) { + delete AudioEngine::instance()->_main_thread; /* the special thread created/managed by the backend */ AudioEngine::instance()->_main_thread = new ProcessThread; } @@ -1264,22 +1300,35 @@ AudioEngine::setup_required () const return false; } } - + return true; } int AudioEngine::prepare_for_latency_measurement () { + if (!_backend) { + return -1; + } + + if (_backend->can_change_systemic_latency_when_running()) { + if (start()) { + return -1; + } + _backend->set_systemic_input_latency (0); + _backend->set_systemic_output_latency (0); + return 0; + } + if (running()) { _stopped_for_latency = true; stop (true); } if (start (true)) { - _started_for_latency = true; return -1; } + _started_for_latency = true; return 0; } @@ -1287,10 +1336,8 @@ AudioEngine::prepare_for_latency_measurement () int AudioEngine::start_latency_detection (bool for_midi) { - if (!running()) { - if (prepare_for_latency_measurement ()) { - return -1; - } + if (prepare_for_latency_measurement ()) { + return -1; } PortEngine& pe (port_engine()); @@ -1397,7 +1444,9 @@ AudioEngine::stop_latency_detection () _latency_input_port = 0; } - stop (true); + if (!_backend->can_change_systemic_latency_when_running()) { + stop (true); + } if (_stopped_for_latency) { start ();