From 830f729f522ddc82a55ccde10036c6690bc801ba Mon Sep 17 00:00:00 2001 From: Evgeny Date: Mon, 27 Jul 2026 00:38:15 +0300 Subject: [PATCH] fix: pause support + old message skip + stopCurrentPcm - SoundManager: added stopCurrentPcm() for pause/stop of PCM playback - messagedelegate: call stopCurrentPcm on pause, new play, and timer complete - messagelist: skip old double-nested JSON messages (raw starts with '{') - sound_manager.h: void* for ma_audio_buffer to avoid header dependency --- tools/chatgui/src/audiorecorder.cpp | 2 +- tools/chatgui/src/messagedelegate.cpp | 6 +++-- tools/chatgui/src/messagelist.cpp | 4 +++ tools/chatgui/src/sound_manager.cpp | 39 ++++++++++++++++++--------- tools/chatgui/src/sound_manager.h | 3 +++ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/tools/chatgui/src/audiorecorder.cpp b/tools/chatgui/src/audiorecorder.cpp index b28e73ed..d9267265 100644 --- a/tools/chatgui/src/audiorecorder.cpp +++ b/tools/chatgui/src/audiorecorder.cpp @@ -1,6 +1,6 @@ #include "audiorecorder.h" -#include "sound_manager.h" #include "miniaudio.h" +#include "sound_manager.h" #include #include diff --git a/tools/chatgui/src/messagedelegate.cpp b/tools/chatgui/src/messagedelegate.cpp index 43d650d3..d6fd92cc 100644 --- a/tools/chatgui/src/messagedelegate.cpp +++ b/tools/chatgui/src/messagedelegate.cpp @@ -5,6 +5,7 @@ #include "animtimer.h" #include "lottieicon.h" #include "voiceplayback.h" +#include "sound_manager.h" #include #include #include @@ -42,6 +43,7 @@ static void ensureVoiceTimer() { float elapsed = (now - it->startMs) / 1000.0f; if (elapsed >= it->durationSec && it->durationSec > 0) { it->playing = false; + SoundManager::instance()->stopCurrentPcm(); ++it; } else { anyPlaying = true; @@ -76,13 +78,13 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, if (st.playing) { st.playing = false; + SoundManager::instance()->stopCurrentPcm(); model->setData(index, 0, MsgVoicePlayStateRole); } else { - // Stop any other playing voice for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it) it->playing = false; + SoundManager::instance()->stopCurrentPcm(); - // Parse duration QString durStr = index.data(MsgVoiceDurationRole).toString(); durStr.remove('s'); float dur = durStr.toFloat(); diff --git a/tools/chatgui/src/messagelist.cpp b/tools/chatgui/src/messagelist.cpp index 24a2e403..467c8f54 100644 --- a/tools/chatgui/src/messagelist.cpp +++ b/tools/chatgui/src/messagelist.cpp @@ -97,6 +97,10 @@ static void setVoiceMessageRoles(QStandardItem* item, const QByteArray& data, if (ct == "audio/opus") { QString raw = QString::fromUtf8(data); int pipe = raw.indexOf('|'); + if (pipe < 0 && raw.startsWith('{')) { + /* old double-nested JSON from before the fix — skip */ + return; + } QString fname = pipe >= 0 ? raw.left(pipe) : raw; QString dur = pipe >= 0 ? raw.mid(pipe + 1) : QString(); if (!dur.isEmpty()) item->setData(dur + "s", MsgVoiceDurationRole); diff --git a/tools/chatgui/src/sound_manager.cpp b/tools/chatgui/src/sound_manager.cpp index 8e41859c..25e45b28 100644 --- a/tools/chatgui/src/sound_manager.cpp +++ b/tools/chatgui/src/sound_manager.cpp @@ -142,34 +142,47 @@ ma_context* SoundManager::context() { void SoundManager::playRawPcm(const int16_t* pcm, int sampleCount, int sampleRate, int channels) { if (!m_engine || !m_initialized) { - qWarning("SoundManager::playRawPcm: not initialized (engine=%p init=%d)", (void*)m_engine, m_initialized); + DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "SoundManager::playRawPcm: not initialized"); return; } - qDebug("SoundManager::playRawPcm: %d samples %dHz %dch vol=%.2f", sampleCount, sampleRate, channels, m_volume); + stopCurrentPcm(); + DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "SoundManager::playRawPcm: %d samples %dHz %dch", sampleCount, sampleRate, channels); ma_audio_buffer_config bufCfg = ma_audio_buffer_config_init( ma_format_s16, (ma_uint32)channels, (ma_uint64)sampleCount, pcm, NULL); ma_audio_buffer* buf = new ma_audio_buffer; + m_currentPcmBuffer = buf; ma_result r = ma_audio_buffer_init_copy(&bufCfg, buf); if (r != MA_SUCCESS) { - qWarning("SoundManager: audio_buffer_init_copy failed (%d)", r); - delete buf; + DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "SoundManager: audio_buffer_init_copy failed (%d)", r); + delete buf; m_currentPcmBuffer = nullptr; return; } - ma_sound* sound = new ma_sound; - r = ma_sound_init_from_data_source(m_engine, (ma_data_source*)buf, 0, nullptr, sound); + m_currentPcmSound = new ma_sound; + r = ma_sound_init_from_data_source(m_engine, (ma_data_source*)buf, 0, nullptr, m_currentPcmSound); if (r != MA_SUCCESS) { - qWarning("SoundManager: PCM sound init failed (%d)", r); - ma_audio_buffer_uninit(buf); - delete buf; - delete sound; + DEBUG_WARN(DEBUG_CATEGORY_DEBUG, "SoundManager: PCM sound init failed (%d)", r); + ma_audio_buffer_uninit(buf); delete buf; m_currentPcmBuffer = nullptr; + delete m_currentPcmSound; m_currentPcmSound = nullptr; return; } - ma_sound_set_volume(sound, m_volume); - ma_sound_start(sound); - qDebug("SoundManager::playRawPcm: started"); + ma_sound_set_volume(m_currentPcmSound, m_volume); + ma_sound_start(m_currentPcmSound); +} + +void SoundManager::stopCurrentPcm() { + if (m_currentPcmSound) { + ma_sound_stop(m_currentPcmSound); + delete m_currentPcmSound; m_currentPcmSound = nullptr; + } + if (m_currentPcmBuffer) { + ma_audio_buffer* buf = (ma_audio_buffer*)m_currentPcmBuffer; + ma_audio_buffer_uninit(buf); + delete buf; + m_currentPcmBuffer = nullptr; + } } static QString decodeDeviceName(const char* name) { diff --git a/tools/chatgui/src/sound_manager.h b/tools/chatgui/src/sound_manager.h index b79e0184..eb09f6db 100644 --- a/tools/chatgui/src/sound_manager.h +++ b/tools/chatgui/src/sound_manager.h @@ -39,6 +39,7 @@ public: ma_context* context(); void playRawPcm(const int16_t* pcm, int sampleCount, int sampleRate, int channels); + void stopCurrentPcm(); struct DeviceInfo { QString name; @@ -59,6 +60,8 @@ private: ma_engine* m_engine = nullptr; ma_context* m_context = nullptr; + ma_sound* m_currentPcmSound = nullptr; + void* m_currentPcmBuffer = nullptr; bool m_initialized = false; bool m_enabled = true; float m_volume = 0.8f;