Browse Source

Update shared Qt playback controls after background decoding

master
evgeny 2 days ago
parent
commit
172cc3a649
  1. 58
      tools/chatgui/src/messagedelegate.cpp
  2. 3
      tools/chatgui/src/messagelist.cpp

58
tools/chatgui/src/messagedelegate.cpp

@ -23,11 +23,13 @@
#include <QUrl>
#include <QDebug>
#include <QImageReader>
#include <QPersistentModelIndex>
MessageDelegate::MessageDelegate(QObject *parent)
: QStyledItemDelegate(parent) {}
struct VoicePlayState {
bool loading = false;
bool playing = false;
bool paused = false;
qint64 startMs = 0;
@ -48,6 +50,7 @@ static void ensureVoiceTimer() {
bool anyActive = false;
SoundManager* sm = SoundManager::instance();
for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it) {
if (it->loading) { anyActive = true; continue; }
if (!it->playing && !it->paused) {
if (it->displayFrac > 0.001f || it->displayElapsed > 0.001f) anyActive = true;
continue;
@ -161,6 +164,7 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
ensureVoiceTimer();
VoicePlayState& st = s_voiceStates[filePath];
if (st.loading) return true;
QString durStr = index.data(MsgVoiceDurationRole).toString();
durStr.remove('s');
@ -175,21 +179,21 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
if (!st.playing && !st.paused) {
/* Start playback then seek */
float actualDur = VoicePlayer::playOpusFile(filePath);
if (actualDur <= 0.0f) return false;
targetSec = clickFrac * actualDur;
st.playing = true;
st.paused = false;
st.durationSec = actualDur;
st.startMs = now - (qint64)(targetSec * 1000.0);
st.pausedPosSec = targetSec;
st.displayFrac = (targetSec > 0 && actualDur > 0) ? (targetSec / actualDur) : 0;
st.displayElapsed = targetSec;
int sr = SoundManager::instance()->currentPcmSampleRate();
if (sr > 0)
SoundManager::instance()->seekCurrentPcm((unsigned long long)(targetSec * sr));
st.loading = true;
QPersistentModelIndex persistent(index);
VoicePlayer::playOpusFile(filePath, this, [filePath, clickFrac, persistent](float actualDur) {
s_voiceStates[filePath].loading = false;
if (actualDur <= 0) return;
MessageDelegate::startAutoPlay(filePath, actualDur);
float position = clickFrac * actualDur;
auto& state = s_voiceStates[filePath];
state.startMs -= (qint64)(position * 1000); state.pausedPosSec = position;
state.displayFrac = clickFrac; state.displayElapsed = position;
int rate = SoundManager::instance()->currentPcmSampleRate();
if (rate > 0) SoundManager::instance()->seekCurrentPcm((unsigned long long)(position * rate));
if (persistent.isValid()) const_cast<QAbstractItemModel*>(persistent.model())->setData(persistent, 1, MsgVoicePlayStateRole);
});
s_voiceTimer->start();
model->setData(index, 1, MsgVoicePlayStateRole);
} else {
/* Currently playing or paused — seek */
st.startMs = now - (qint64)(targetSec * 1000.0);
@ -246,18 +250,15 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
SoundManager::instance()->stopCurrentPcm();
}
float actualDur = VoicePlayer::playOpusFile(filePath);
if (actualDur <= 0.0f) return false;
st.playing = true;
st.paused = false;
st.pausedPosSec = 0;
st.startMs = QDateTime::currentMSecsSinceEpoch();
st.durationSec = actualDur;
st.displayFrac = 0;
st.displayElapsed = 0;
st.loading = true;
QPersistentModelIndex persistent(index);
VoicePlayer::playOpusFile(filePath, this, [filePath, persistent](float actualDur) {
s_voiceStates[filePath].loading = false;
if (actualDur <= 0) return;
MessageDelegate::startAutoPlay(filePath, actualDur);
if (persistent.isValid()) const_cast<QAbstractItemModel*>(persistent.model())->setData(persistent, 1, MsgVoicePlayStateRole);
});
s_voiceTimer->start();
model->setData(index, 1, MsgVoicePlayStateRole);
return true;
}
@ -1492,6 +1493,7 @@ void MessageDelegate::drawAvatar(QPainter *p, const Layout &L,
}
void MessageDelegate::startAutoPlay(const QString& filePath, float actualDurationSec) {
if (actualDurationSec <= 0) return;
ensureVoiceTimer();
VoicePlayState& st = s_voiceStates[filePath];
st.playing = true;
@ -1506,6 +1508,8 @@ void MessageDelegate::startAutoPlay(const QString& filePath, float actualDuratio
}
void MessageDelegate::stopAllAutoPlay() {
for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it)
it->playing = false;
VoicePlayer::cancelPending();
for (auto it = s_voiceStates.begin(); it != s_voiceStates.end(); ++it) {
it->playing = false; it->paused = false; it->loading = false;
}
}

3
tools/chatgui/src/messagelist.cpp

@ -960,8 +960,7 @@ void MessageList::onAttachmentDownloaded(const QString& chId, int64_t msgId) {
if (!fp.isEmpty() && QFile::exists(fp)) {
QTimer::singleShot(500, this, [this, fp]() {
MessageDelegate::stopAllAutoPlay();
float actualDur = VoicePlayer::playOpusFile(fp);
MessageDelegate::startAutoPlay(fp, actualDur);
VoicePlayer::playOpusFile(fp, this, [fp](float actualDur) { MessageDelegate::startAutoPlay(fp, actualDur); });
});
}
}

Loading…
Cancel
Save