Browse Source

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
topo_upd
Evgeny 2 months ago
parent
commit
830f729f52
  1. 2
      tools/chatgui/src/audiorecorder.cpp
  2. 6
      tools/chatgui/src/messagedelegate.cpp
  3. 4
      tools/chatgui/src/messagelist.cpp
  4. 39
      tools/chatgui/src/sound_manager.cpp
  5. 3
      tools/chatgui/src/sound_manager.h

2
tools/chatgui/src/audiorecorder.cpp

@ -1,6 +1,6 @@
#include "audiorecorder.h"
#include "sound_manager.h"
#include "miniaudio.h"
#include "sound_manager.h"
#include <QDebug>
#include <cstring>

6
tools/chatgui/src/messagedelegate.cpp

@ -5,6 +5,7 @@
#include "animtimer.h"
#include "lottieicon.h"
#include "voiceplayback.h"
#include "sound_manager.h"
#include <cmath>
#include <QPainter>
#include <QPainterPath>
@ -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();

4
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);

39
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) {

3
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;

Loading…
Cancel
Save