Update shared Qt playback controls after background decoding
This commit is contained in:
1 parent
d4a27d1975
commit
172cc3a649
2 files changed
+32
-29
No files matched your search
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user