From 9cdb799f3b483d8e7adcae414c1d299689ac5263 Mon Sep 17 00:00:00 2001 From: Greg Zharun Date: Tue, 1 Jul 2014 14:25:03 +0300 Subject: [PATCH] Implemented Tracks backend/engine reaction on device configuration changes (like I/O layout changes etc.) on Windows --- gtk2_ardour/tracks_control_panel.logic.cc | 25 +++++------- libs/ardour/ardour/audioengine.h | 6 +++ libs/ardour/audioengine.cc | 40 ++++++++++++++++++- .../backends/wavesaudio/waves_audiobackend.cc | 12 ++++-- .../WCMRPortAudioDeviceManager.cpp | 5 +-- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/gtk2_ardour/tracks_control_panel.logic.cc b/gtk2_ardour/tracks_control_panel.logic.cc index c5c70a694e..10de2b2367 100644 --- a/gtk2_ardour/tracks_control_panel.logic.cc +++ b/gtk2_ardour/tracks_control_panel.logic.cc @@ -669,12 +669,11 @@ TracksControlPanel::populate_sample_rate_combo() PBD::Unwinder protect_ignore_changes (_ignore_changes, _ignore_changes + 1); set_popdown_strings (_sample_rate_combo, s); _sample_rate_combo.set_sensitive (s.size() > 1); - } - if (!s.empty() ) { - std::string active_sr = rate_as_string(EngineStateController::instance()->get_current_sample_rate() ); - - _sample_rate_combo.set_active_text(active_sr); + if (!s.empty() ) { + std::string active_sr = rate_as_string(EngineStateController::instance()->get_current_sample_rate() ); + _sample_rate_combo.set_active_text(active_sr); + } } } @@ -694,11 +693,11 @@ TracksControlPanel::populate_buffer_size_combo() PBD::Unwinder protect_ignore_changes (_ignore_changes, _ignore_changes + 1); set_popdown_strings (_buffer_size_combo, s); _buffer_size_combo.set_sensitive (s.size() > 1); - } - if (!s.empty() ) { - std::string active_bs = bufsize_as_string(EngineStateController::instance()->get_current_buffer_size()); - _buffer_size_combo.set_active_text(active_bs); + if (!s.empty() ) { + std::string active_bs = bufsize_as_string(EngineStateController::instance()->get_current_buffer_size()); + _buffer_size_combo.set_active_text(active_bs); + } } } @@ -1133,12 +1132,8 @@ TracksControlPanel::sample_rate_changed() void TracksControlPanel::engine_running () { - _buffer_size_combo.set_active_text (bufsize_as_string (EngineStateController::instance()->get_current_buffer_size() ) ); - - _sample_rate_combo.set_active_text (rate_as_string (EngineStateController::instance()->get_current_sample_rate() ) ); - - _buffer_size_combo.set_sensitive (true); - _sample_rate_combo.set_sensitive (true); + populate_buffer_size_combo(); + populate_sample_rate_combo(); } diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 41076427ea..d405185c3a 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -107,6 +107,8 @@ public: bool in_process_thread (); uint32_t process_thread_count (); + void request_backend_reset(); + bool is_realtime() const; bool connected() const; @@ -230,6 +232,7 @@ public: /// the number of frames processed since start() was called framecnt_t _processed_frames; Glib::Threads::Thread* m_meter_thread; + Glib::Threads::Thread* m_hw_event_thread; ProcessThread* _main_thread; MTDM* _mtdm; bool _measuring_latency; @@ -243,6 +246,9 @@ public: bool _started_for_latency; bool _in_destructor; + void do_reset_backend(); + void wait_hw_event_processing_complete(); + void meter_thread (); void start_metering_thread (); void stop_metering_thread (); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 27d719f73e..4e763006bc 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -89,6 +89,7 @@ AudioEngine::~AudioEngine () { _in_destructor = true; stop_metering_thread (); + wait_hw_event_processing_complete(); drop_backend (); } @@ -362,6 +363,44 @@ AudioEngine::process_callback (pframes_t nframes) } +void +AudioEngine::request_backend_reset() +{ + if (m_hw_event_thread != 0) { + m_hw_event_thread->join (); + m_hw_event_thread = 0; + } + + m_hw_event_thread = Glib::Threads::Thread::create (boost::bind (&AudioEngine::do_reset_backend, this)); +} + + +void +AudioEngine::do_reset_backend() +{ + SessionEvent::create_per_thread_pool (X_("Backend reset processing thread"), 512); + + if (_backend) { + std::string name = _backend->device_name (); + stop(); + _backend->drop_device(); + _backend->set_device_name(name); + start(); + SampleRateChanged(_backend->sample_rate() ); + BufferSizeChanged(_backend->buffer_size() ); + } +} + + +void +AudioEngine::wait_hw_event_processing_complete() +{ + m_hw_event_thread->join (); + m_hw_event_thread = 0; +} + + + void AudioEngine::stop_metering_thread () { @@ -653,7 +692,6 @@ AudioEngine::start (bool for_latency) _backend->set_time_master (true); } - _session->reconnect_existing_routes (true, true); } start_metering_thread (); diff --git a/libs/backends/wavesaudio/waves_audiobackend.cc b/libs/backends/wavesaudio/waves_audiobackend.cc index 4691163f6d..f20cc3a521 100644 --- a/libs/backends/wavesaudio/waves_audiobackend.cc +++ b/libs/backends/wavesaudio/waves_audiobackend.cc @@ -28,13 +28,16 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso switch (reason) { case WCMRAudioDeviceManagerClient::DeviceDebugInfo: std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " << (char*)parameter << std::endl; - break; + break; case WCMRAudioDeviceManagerClient::BufferSizeChanged: std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl; _buffer_size_change(*(uint32_t*)parameter); - break; + break; case WCMRAudioDeviceManagerClient::RequestReset: + { std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl; + engine.request_backend_reset(); + } break; case WCMRAudioDeviceManagerClient::RequestResync: std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl; @@ -43,6 +46,9 @@ void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reaso std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl; set_sample_rate(*(float*)parameter); break; + case WCMRAudioDeviceManagerClient::Dropout: + std::cout << "------------------------------- WCMRAudioDeviceManagerClient::Dropout: " << std::endl; + break; case WCMRAudioDeviceManagerClient::DeviceDroppedSamples: std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDroppedSamples" << std::endl; break; @@ -816,7 +822,7 @@ WavesAudioBackend::_audio_device_callback (const float* input_buffer, uint64_t dsp_end_time_nanos = __get_time_nanos(); _dsp_load_accumulator -= *_dsp_load_history.begin(); - _dsp_load_history.pop_front(); + _dsp_load_history.pop_front(); uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos; _dsp_load_accumulator += dsp_load_nanos; _dsp_load_history.push_back(dsp_load_nanos); diff --git a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp index 057dc1d0e6..ca8bc170f3 100644 --- a/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp +++ b/libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp @@ -998,9 +998,6 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ ) bool wasStreaming = Streaming(); bool wasActive = Active(); - // Notify the Application about reset - m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); - // Reset the device stopStreaming(); deactivateDevice(); @@ -1080,7 +1077,7 @@ long WCMRPortAudioDevice::ASIOMessageHook (long selector, long WCUNUSEDPARAM(val case kAsioResetRequest: m_ResetRequested++; std::cout << "\t\t\tWCMRPortAudioDevice::ASIOMessageHook -- kAsioResetRequest" << std::endl; - SetEvent(m_hResetFromDevRequestedEvent); + m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::RequestReset); break; case kAsioResyncRequest: