Browse Source

Disable stalled call microphones and close capture asynchronously

master
evgeny 2 days ago
parent
commit
26f6e2ee83
  1. 29
      tools/chatgui/src/call_audio_engine.cpp
  2. 5
      tools/chatgui/src/call_audio_engine.h

29
tools/chatgui/src/call_audio_engine.cpp

@ -8,6 +8,7 @@ extern "C" {
#include "debug_config.h"
}
#include <cstring>
#include <QCoreApplication>
CallAudioEngine* CallAudioEngine::instance() {
static auto* engine = new CallAudioEngine();
@ -32,7 +33,9 @@ CallAudioEngine::CallAudioEngine() {
int CallAudioEngine::start(quint64 callId) {
if (m_active && m_callId == callId && !m_ending) return 0;
if (m_capture.closing()) { DEBUG_WARN(DEBUG_CATEGORY_CALL, "CallAudio: previous microphone is still closing"); return -1; }
stop();
m_captureError.clear(); emit captureErrorChanged();
if (!m_microphone.acquire()) {
DEBUG_WARN(DEBUG_CATEGORY_CALL, "CallAudio: microphone owned by another operation"); return -1;
}
@ -82,9 +85,20 @@ bool CallAudioEngine::openCapture() {
}
void CallAudioEngine::recoverDevices() {
if (!m_active) return;
if (!m_active) {
if (!m_capture.closing()) { m_microphone.release(); m_recoveryTimer.stop(); }
return;
}
auto* manager = SoundManager::instance();
if (!m_outputAttached && manager->context()) m_outputAttached = manager->attachVoice(&m_voice, m_playbackId);
if (!m_ending && m_captureError.isEmpty() && m_capture.captureTimedOut()) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "CallAudio: microphone has no PCM for 1000ms call=%016llx; disabling capture",
(unsigned long long)m_callId.load());
m_captureError = QCoreApplication::translate("ChatGui", "The microphone is not delivering audio. Select another microphone or restart.");
m_capture.closeAsync(); m_voice.stopCapture(); call_audio_reset_io(m_callId.load(), 0);
emit captureErrorChanged();
}
if (!m_captureError.isEmpty() || m_capture.closing()) return;
if (!m_ending && ((m_capture.initialized() && !m_voice.captureRunning()) || m_capture.needsRecovery())) {
m_capture.close(); m_voice.stopCapture();
call_audio_reset_io(m_callId.load(), 0); m_capture.retryLater();
@ -115,14 +129,15 @@ void CallAudioEngine::setPlaybackDevice(const QString& id) {
void CallAudioEngine::setCaptureDevice(const QString& id) {
if (id == m_captureId) return;
m_captureId = id;
m_capture.close(); m_voice.stopCapture(); m_capture.retryNow();
m_capture.closeAsync(); m_voice.stopCapture(); m_capture.retryNow();
m_captureError.clear(); emit captureErrorChanged();
if (m_active) { call_audio_reset_io(m_callId.load(), 0); recoverDevices(); }
}
void CallAudioEngine::beginEnd(quint64 callId) {
if (!m_active || m_callId != callId || m_ending) return;
m_ending = true;
m_capture.close(); m_voice.stopCapture();
m_capture.closeAsync(); m_voice.stopCapture();
call_audio_begin_end(callId);
uint64_t generation = m_generation;
QTimer::singleShot(500, this, [this, generation]() { if (m_generation == generation) stop(); });
@ -130,10 +145,12 @@ void CallAudioEngine::beginEnd(quint64 callId) {
void CallAudioEngine::stop() {
++m_generation;
m_recoveryTimer.stop();
m_active = false;
pauseDevices(); m_voice.stop();
m_microphone.release();
m_capture.closeAsync(); m_voice.stopCapture();
SoundManager::instance()->detachVoice(&m_voice); m_outputAttached = false;
m_voice.stop();
if (m_capture.closing()) m_recoveryTimer.start();
else { m_microphone.release(); m_recoveryTimer.stop(); }
uint64_t id = m_callId.exchange(0);
if (id) call_audio_release(id);
m_muted = false;

5
tools/chatgui/src/call_audio_engine.h

@ -34,6 +34,7 @@ public:
bool isActive() const { return m_active.load(); }
quint64 callId() const { return m_callId.load(); }
VoiceAudioIo::OutputLatency outputLatency() const { return m_voice.outputLatency(); }
QString captureError() const { return m_captureError; }
/* Mute: пир слышит тишину (отправляем нулевые кадры вместо захваченного PCM). */
void setMuted(bool muted);
@ -47,6 +48,9 @@ public:
/* Hardware capture callback: без DSP и растущих буферов. */
void dataCallback(const void* in, void* out, unsigned int frames);
signals:
void captureErrorChanged();
private:
CallAudioEngine();
bool openCapture();
@ -60,6 +64,7 @@ private:
QString m_playbackId; /* только GUI-поток */
QString m_captureId;
QString m_captureError;
AudioDevice m_capture;
AudioCaptureLease m_microphone;
VoiceAudioIo m_voice;

Loading…
Cancel
Save