From efe9e8311c80bbc98e89a90278c1be64373760b4 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 16 Oct 2026 17:12:51 +0200 Subject: [PATCH] Detach shared capture safely while its audio buffer is resizing --- tools/chatgui/src/audio_capture.cpp | 5 ++++- tools/chatgui/src/audio_capture.h | 2 +- tools/chatgui/src/radio_audio_engine.cpp | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/chatgui/src/audio_capture.cpp b/tools/chatgui/src/audio_capture.cpp index ef10abe0..a6f1ced3 100644 --- a/tools/chatgui/src/audio_capture.cpp +++ b/tools/chatgui/src/audio_capture.cpp @@ -157,7 +157,7 @@ void AudioCapture::close() { /* Callback отсоединён в GUI; session и контекст должны жить до завершения ma_device_uninit. */ void AudioCapture::closeAsync() { - if (closing()) return; + if (!m_closeDone.load(std::memory_order_acquire)) return; if (m_closeThread.joinable()) m_closeThread.join(); auto session = detach(); if (!session) return; @@ -184,6 +184,9 @@ void AudioCapture::closeAsync() { } void AudioCapture::recover() { if (m_session) m_session->recover(); } +bool AudioCapture::closing() const { + return !m_closeDone.load(std::memory_order_acquire) || (m_session && m_session->device.closing()); +} bool AudioCapture::running() const { return m_session && m_prepared && m_session->device.initialized() && ma_device_is_started(m_session->device.device()); } diff --git a/tools/chatgui/src/audio_capture.h b/tools/chatgui/src/audio_capture.h index 53260a8d..52c23dbc 100644 --- a/tools/chatgui/src/audio_capture.h +++ b/tools/chatgui/src/audio_capture.h @@ -31,7 +31,7 @@ public: std::function stopped, Callback callback); void close(); void closeAsync(); // GUI отсоединяет подписчика; последний backend закрывается в worker. - bool closing() const { return !m_closeDone.load(std::memory_order_acquire); } + bool closing() const; // Включает переоткрытие общего backend для подстройки буфера. void recover(); bool subscribed() const { return bool(m_session); } bool running() const; diff --git a/tools/chatgui/src/radio_audio_engine.cpp b/tools/chatgui/src/radio_audio_engine.cpp index 75d5462b..58c0ff0a 100644 --- a/tools/chatgui/src/radio_audio_engine.cpp +++ b/tools/chatgui/src/radio_audio_engine.cpp @@ -48,7 +48,7 @@ RadioAudioEngine::RadioAudioEngine() { auto* manager = SoundManager::instance(); if (m_captureId != manager->captureDevice()) { m_captureId = manager->captureDevice(); - if (!m_capture.closing()) m_capture.close(); + if (m_capture.closing()) m_capture.closeAsync(); else m_capture.close(); m_captureError.clear(); emit stateChanged(); } @@ -192,7 +192,7 @@ void RadioAudioEngine::postSettings(const std::array& values, bool apply void RadioAudioEngine::reconfigureCapture() { DEBUG_INFO(DEBUG_CATEGORY_RADIO, "RadioAudio: reconfigure capture group=%016llx manual=%d auto=%d", (unsigned long long)m_groupId.load(), m_talking.load(), autoEnabled()); - if (!m_capture.closing()) m_capture.close(); + if (m_capture.closing()) m_capture.closeAsync(); else m_capture.close(); m_wantStereo = chat_setting_get_int(gui_bridge_get_inst(), "radio_capture_stereo", 0) != 0; updateState(); recoverDevices(); @@ -291,7 +291,7 @@ void RadioAudioEngine::pauseDevices() { void RadioAudioEngine::stop() { m_recoveryTimer.stop(); - if (!m_capture.closing()) m_capture.close(); + if (m_capture.closing()) m_capture.closeAsync(); else m_capture.close(); SoundManager::instance()->detachVoice(&m_voice); m_outputAttached = false; m_voice.stop(); m_microphone.release();