Close failed stream capture without blocking the GUI
This commit is contained in:
1 parent
86da11b2e1
commit
3ba7601ba4
2 files changed
+37
-3
No files matched your search
@@ -98,6 +98,7 @@ AudioCapture::~AudioCapture() { close(); }
|
||||
|
||||
bool AudioCapture::open(const QString& input, Role role, int channels, uint64_t tag, Ready ready,
|
||||
std::function<void()> stopped, Callback callback) {
|
||||
if (closing()) { DEBUG_WARN(DEBUG_CATEGORY_CALL, "capture: previous device is still closing"); return false; }
|
||||
close();
|
||||
static std::vector<std::weak_ptr<Session>> sessions; // Только GUI; владение у подписчиков.
|
||||
QString key = input;
|
||||
@@ -129,13 +130,39 @@ bool AudioCapture::open(const QString& input, Role role, int channels, uint64_t
|
||||
return running();
|
||||
}
|
||||
|
||||
void AudioCapture::close() {
|
||||
if (!m_session) return;
|
||||
std::shared_ptr<AudioCapture::Session> AudioCapture::detach() {
|
||||
if (!m_session) return {};
|
||||
auto& slot = m_session->consumers[m_role == Role::Stream ? 0 : 1];
|
||||
m_session->detach(slot); slot.client = nullptr;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CALL, "capture: detached role=%s remaining=%d", m_role == Role::Stream ? "stream" : "radio",
|
||||
int(m_session->consumers[0].client != nullptr) + int(m_session->consumers[1].client != nullptr));
|
||||
m_session.reset(); m_callback = {}; m_ready = {}; m_stopped = {};
|
||||
m_callback = {}; m_ready = {}; m_stopped = {};
|
||||
return std::move(m_session);
|
||||
}
|
||||
|
||||
void AudioCapture::close() {
|
||||
if (m_closeThread.joinable()) m_closeThread.join();
|
||||
detach().reset();
|
||||
}
|
||||
|
||||
/* Callback отсоединён в GUI; session и контекст должны жить до завершения ma_device_uninit. */
|
||||
void AudioCapture::closeAsync() {
|
||||
if (closing()) return;
|
||||
if (m_closeThread.joinable()) m_closeThread.join();
|
||||
auto session = detach();
|
||||
if (!session) return;
|
||||
m_closeDone.store(false, std::memory_order_release);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CALL, "capture: asynchronous close started shared=%d", session.use_count() > 1);
|
||||
try {
|
||||
m_closeThread = std::thread([this, session = std::move(session)]() mutable {
|
||||
session.reset();
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CALL, "capture: asynchronous close completed");
|
||||
m_closeDone.store(true, std::memory_order_release);
|
||||
});
|
||||
} catch (const std::system_error& error) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "capture: close worker failed: %s", error.what());
|
||||
m_closeDone.store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCapture::recover() { if (m_session) m_session->recover(); }
|
||||
|
||||
Reference in new issue
Block a user