X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=076700cebfec5a8445d0c473b65c36e3d2eb4618;hb=7204702c3ffbd3a1c6747511104d9c6af1b9c93d;hp=6c9fd442fbc4c45783769872b16cf4be274dc166;hpb=23e7cf10191270d70357ccf0ed9294f020c7b7ab;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 6c9fd442fb..076700cebf 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -81,9 +81,17 @@ AudioEngine::AudioEngine () , _latency_flush_frames (0) , _latency_signal_latency (0) , _stopped_for_latency (false) + , _started_for_latency (false) , _in_destructor (false) + , _hw_reset_event_thread(0) + , _hw_reset_request_count(0) + , _stop_hw_reset_processing(0) + , _hw_devicelist_update_thread(0) + , _hw_devicelist_update_count(0) + , _stop_hw_devicelist_processing(0) { g_atomic_int_set (&m_meter_exit, 0); + start_hw_event_processing(); discover_backends (); } @@ -91,6 +99,7 @@ AudioEngine::~AudioEngine () { _in_destructor = true; stop_metering_thread (); + stop_hw_event_processing(); drop_backend (); } @@ -106,23 +115,6 @@ AudioEngine::create () return _instance; } -void -_thread_init_callback (void * /*arg*/) -{ - /* make sure that anybody who needs to know about this thread - knows about it. - */ - - pthread_set_name (X_("audioengine")); - - PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("Audioengine"), 4096); - PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("Audioengine"), 128); - - SessionEvent::create_per_thread_pool (X_("Audioengine"), 512); - - AsyncMIDIPort::set_process_thread (pthread_self()); -} - void AudioEngine::split_cycle (pframes_t offset) { @@ -164,12 +156,17 @@ AudioEngine::buffer_size_change (pframes_t bufsiz) last_monitor_check = 0; } + BufferSizeChanged (bufsiz); /* EMIT SIGNAL */ + return 0; } /** Method called by our ::process_thread when there is work to be done. * @param nframes Number of frames to process. */ +#ifdef __clang__ +__attribute__((annotate("realtime"))) +#endif int AudioEngine::process_callback (pframes_t nframes) { @@ -376,6 +373,139 @@ AudioEngine::process_callback (pframes_t nframes) } +void +AudioEngine::request_backend_reset() +{ + Glib::Threads::Mutex::Lock guard (_reset_request_lock); + g_atomic_int_inc (&_hw_reset_request_count); + _hw_reset_condition.signal (); +} + + +void +AudioEngine::do_reset_backend() +{ + SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512); + + Glib::Threads::Mutex::Lock guard (_reset_request_lock); + + while (!_stop_hw_reset_processing) { + + if (_hw_reset_request_count && _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" << std::endl; + + // backup the device name + std::string name = _backend->device_name (); + + std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl; + stop(); + + std::cout << "AudioEngine::RESET::Reseting device..." << std::endl; + if ( 0 == _backend->reset_device () ) { + + std::cout << "AudioEngine::RESET::Starting engine..." << std::endl; + start (); + + // inform about possible changes + BufferSizeChanged (_backend->buffer_size() ); + } else { + DeviceError(); + } + + std::cout << "AudioEngine::RESET::Done." << std::endl; + + _reset_request_lock.lock(); + + } else { + + _hw_reset_condition.wait (_reset_request_lock); + + } + } +} + + +void +AudioEngine::request_device_list_update() +{ + Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); + g_atomic_int_inc (&_hw_devicelist_update_count); + _hw_devicelist_update_condition.signal (); +} + + +void +AudioEngine::do_devicelist_update() +{ + SessionEvent::create_per_thread_pool (X_("Device list update processing thread"), 512); + + Glib::Threads::Mutex::Lock guard (_devicelist_update_lock); + + while (!_stop_hw_devicelist_processing) { + + if (_hw_devicelist_update_count) { + + _devicelist_update_lock.unlock(); + + g_atomic_int_dec_and_test (&_hw_devicelist_update_count); + DeviceListChanged (); /* EMIT SIGNAL */ + + _devicelist_update_lock.lock(); + + } else { + _hw_devicelist_update_condition.wait (_devicelist_update_lock); + } + } +} + + +void +AudioEngine::start_hw_event_processing() +{ + if (_hw_reset_event_thread == 0) { + g_atomic_int_set(&_hw_reset_request_count, 0); + g_atomic_int_set(&_stop_hw_reset_processing, 0); + _hw_reset_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this)); + } + + if (_hw_devicelist_update_thread == 0) { + g_atomic_int_set(&_hw_devicelist_update_count, 0); + g_atomic_int_set(&_stop_hw_devicelist_processing, 0); + _hw_devicelist_update_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_devicelist_update, this)); + } +} + + +void +AudioEngine::stop_hw_event_processing() +{ + if (_hw_reset_event_thread) { + g_atomic_int_set(&_stop_hw_reset_processing, 1); + g_atomic_int_set(&_hw_reset_request_count, 0); + _hw_reset_condition.signal (); + _hw_reset_event_thread->join (); + _hw_reset_event_thread = 0; + } + + if (_hw_devicelist_update_thread) { + g_atomic_int_set(&_stop_hw_devicelist_processing, 1); + g_atomic_int_set(&_hw_devicelist_update_count, 0); + _hw_devicelist_update_condition.signal (); + _hw_devicelist_update_thread->join (); + _hw_devicelist_update_thread = 0; + } + +} + + + void AudioEngine::stop_metering_thread () { @@ -456,6 +586,15 @@ AudioEngine::remove_session () } +void +AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs) +{ + if (_session) { + _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs); + } +} + + void AudioEngine::died () { @@ -463,7 +602,7 @@ AudioEngine::died () stop_metering_thread (); - _running = false; + _running = false; } int @@ -537,7 +676,15 @@ AudioEngine::discover_backends () AudioBackendInfo* AudioEngine::backend_discover (const string& path) { +#ifdef PLATFORM_WINDOWS + // do not show popup dialog (e.g. missing libjack.dll) + // win7+ should use SetThreadErrorMode() + SetErrorMode(SEM_FAILCRITICALERRORS); +#endif Glib::Module module (path); +#ifdef PLATFORM_WINDOWS + SetErrorMode(0); // reset to system default +#endif AudioBackendInfo* info; AudioBackendInfo* (*dfunc)(void); void* func = 0; @@ -553,11 +700,14 @@ AudioEngine::backend_discover (const string& path) error << Glib::Module::get_last_error() << endmsg; return 0; } - - module.make_resident (); dfunc = (AudioBackendInfo* (*)(void))func; info = dfunc(); + if (!info->available()) { + return 0; + } + + module.make_resident (); return info; } @@ -588,7 +738,7 @@ AudioEngine::drop_backend () { if (_backend) { _backend->stop (); - _backend->drop_device(); + _backend->drop_device (); _backend.reset (); _running = false; } @@ -658,6 +808,7 @@ AudioEngine::start (bool for_latency) if (_session->config.get_jack_time_master()) { _backend->set_time_master (true); } + } start_metering_thread (); @@ -676,6 +827,12 @@ AudioEngine::stop (bool for_latency) return 0; } + if (_session && _running) { + // it's not a halt, but should be handled the same way: + // disable record, stop transport and I/O processign but save the data. + _session->engine_halted (); + } + Glib::Threads::Mutex::Lock lm (_process_lock); if (_backend->stop ()) { @@ -1028,7 +1185,7 @@ AudioEngine::halted_callback (const char* why) return; } - stop_metering_thread (); + stop_metering_thread (); _running = false; Port::PortDrop (); /* EMIT SIGNAL */