Browse Source

Update shared Qt playback controls after background decoding

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

Loading…
Cancel
Save