fix: refine playback shutdown and danmaku sizing

This commit is contained in:
dela
2026-06-21 21:59:54 +08:00
parent cf58267d41
commit 4fcfde8be3
6 changed files with 129 additions and 52 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# Maintainer: local
pkgname=qemby
pkgver=0.0.6
pkgver=0.0.7
pkgrel=1
pkgdesc="Desktop client for Emby and Jellyfin media servers"
arch=('x86_64')
+9 -2
View File
@@ -131,7 +131,7 @@ bool MpvController::init() {
mpv_set_option_string(m_mpv, "sub-hinting", "none");
mpv_set_option_string(m_mpv, "sub-ass-hinting", "none");
mpv_request_log_messages(m_mpv, "info");
mpv_request_log_messages(m_mpv, "warn");
@@ -223,6 +223,10 @@ bool MpvController::init() {
observeProperty("track-list", MPV_FORMAT_NODE);
observeProperty("sid", MPV_FORMAT_NODE);
observeProperty("secondary-sid", MPV_FORMAT_NODE);
observeProperty("video-params/dw", MPV_FORMAT_DOUBLE);
observeProperty("video-params/dh", MPV_FORMAT_DOUBLE);
observeProperty("width", MPV_FORMAT_INT64);
observeProperty("height", MPV_FORMAT_INT64);
observeProperty("paused-for-cache", MPV_FORMAT_FLAG);
@@ -289,7 +293,10 @@ void MpvController::eventHandler() {
auto *msg = static_cast<mpv_event_log_message *>(event->data);
if (msg) {
qDebug().noquote() << QString("[MPV %1] %2").arg(msg->prefix, QString::fromUtf8(msg->text).trimmed());
qWarning().noquote()
<< QString("[MPV %1] %2")
.arg(msg->prefix,
QString::fromUtf8(msg->text).trimmed());
}
break;
}
@@ -215,6 +215,7 @@ void NativeDanmakuOverlay::setRenderOptions(DanmakuRenderOptions options)
const bool appearanceChanged = !renderAppearanceEqual(m_options, options);
m_options = options;
markSurfaceRectDirty();
requestScheduleRebuild(false, appearanceChanged);
}
@@ -274,6 +275,7 @@ void NativeDanmakuOverlay::setBottomSubtitleProtected(bool enabled)
}
m_bottomSubtitleProtected = enabled;
markSurfaceRectDirty();
requestScheduleRebuild(false, false);
}
@@ -291,7 +293,7 @@ void NativeDanmakuOverlay::paintEvent(QPaintEvent *event)
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
const qreal positionMs = currentPositionMsPrecise();
const QRectF surfaceRect = effectiveSurfaceRect();
const QRectF surfaceRect = cachedEffectiveSurfaceRect();
const qreal dpr = std::max<qreal>(1.0, devicePixelRatioF());
const auto alignToDevicePixel = [dpr](qreal value) {
return std::round(value * dpr) / dpr;
@@ -336,6 +338,7 @@ void NativeDanmakuOverlay::paintEvent(QPaintEvent *event)
void NativeDanmakuOverlay::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
markSurfaceRectDirty();
requestScheduleRebuild(false, false);
updateScreenRefreshBinding();
}
@@ -390,7 +393,7 @@ void NativeDanmakuOverlay::rebuildScheduleNow()
return;
}
const QRectF surfaceRect = effectiveSurfaceRect();
const QRectF surfaceRect = cachedEffectiveSurfaceRect();
const qreal viewportScale = viewportScaleForSize(size());
const QStringList blockedKeywords =
normalizeBlockedKeywords(m_options.blockedKeywords);
@@ -738,6 +741,48 @@ void NativeDanmakuOverlay::updateScreenRefreshBinding()
syncFrameTimer();
}
void NativeDanmakuOverlay::markSurfaceRectDirty()
{
m_surfaceRectDirty = true;
}
QRectF NativeDanmakuOverlay::cachedEffectiveSurfaceRect() const
{
if (m_surfaceRectDirty) {
m_cachedSurfaceRect = effectiveSurfaceRect();
m_surfaceRectDirty = false;
}
return m_cachedSurfaceRect;
}
void NativeDanmakuOverlay::updateVideoDisplaySize(const QString &property,
const QVariant &value)
{
qreal *target = nullptr;
if (property == QLatin1String("video-params/dw")) {
target = &m_videoParamsDisplayWidth;
} else if (property == QLatin1String("video-params/dh")) {
target = &m_videoParamsDisplayHeight;
} else if (property == QLatin1String("width")) {
target = &m_videoFallbackWidth;
} else if (property == QLatin1String("height")) {
target = &m_videoFallbackHeight;
}
if (!target) {
return;
}
const qreal newValue = value.toDouble();
if (std::abs(*target - newValue) <= 0.5) {
return;
}
*target = newValue;
markSurfaceRectDirty();
requestScheduleRebuild(false, false);
}
void NativeDanmakuOverlay::refreshBasePosition(qint64 positionMs)
{
m_basePositionMs = std::max<qint64>(0, positionMs);
@@ -769,20 +814,14 @@ QRectF NativeDanmakuOverlay::effectiveSurfaceRect() const
return surface;
}
if (m_controller) {
qreal displayWidth =
m_controller->getProperty(QStringLiteral("video-params/dw")).toDouble();
qreal displayHeight =
m_controller->getProperty(QStringLiteral("video-params/dh")).toDouble();
if (displayWidth <= 0.0 || displayHeight <= 0.0) {
displayWidth =
m_controller->getProperty(QStringLiteral("width")).toDouble();
displayHeight =
m_controller->getProperty(QStringLiteral("height")).toDouble();
}
if (displayWidth > 0.0 && displayHeight > 0.0 &&
surface.width() > 0.0 && surface.height() > 0.0) {
const qreal displayWidth =
m_videoParamsDisplayWidth > 0.0 ? m_videoParamsDisplayWidth
: m_videoFallbackWidth;
const qreal displayHeight =
m_videoParamsDisplayHeight > 0.0 ? m_videoParamsDisplayHeight
: m_videoFallbackHeight;
if (displayWidth > 0.0 && displayHeight > 0.0) {
if (surface.width() > 0.0 && surface.height() > 0.0) {
const qreal videoAspect = displayWidth / displayHeight;
const qreal viewportAspect = surface.width() / surface.height();
if (videoAspect > 0.0 && viewportAspect > 0.0) {
@@ -810,7 +849,7 @@ QRectF NativeDanmakuOverlay::effectiveSurfaceRect() const
qreal NativeDanmakuOverlay::laneTop(const ScheduledItem &item) const
{
const QRectF surfaceRect = effectiveSurfaceRect();
const QRectF surfaceRect = cachedEffectiveSurfaceRect();
if (item.type == ItemType::Bottom) {
return surfaceRect.bottom() - m_bottomMargin -
(item.laneIndex + 1) * m_lineHeight;
@@ -901,10 +940,7 @@ void NativeDanmakuOverlay::handleControllerPropertyChanged(const QString &proper
const qint64 positionMs = currentPositionMs();
m_playbackSpeed = qBound(0.1, value.toDouble(), 16.0);
refreshBasePosition(positionMs);
} else if (property == QLatin1String("video-params/dw") ||
property == QLatin1String("video-params/dh") ||
property == QLatin1String("width") ||
property == QLatin1String("height")) {
requestScheduleRebuild(false, false);
} else {
updateVideoDisplaySize(property, value);
}
}
@@ -73,6 +73,10 @@ private:
int targetFrameIntervalMs() const;
QScreen *targetScreen() const;
void updateScreenRefreshBinding();
void markSurfaceRectDirty();
QRectF cachedEffectiveSurfaceRect() const;
void updateVideoDisplaySize(const QString &property,
const QVariant &value);
void refreshBasePosition(qint64 positionMs);
qreal currentPositionMsPrecise() const;
qint64 currentPositionMs() const;
@@ -111,11 +115,17 @@ private:
qreal m_outlineSize = 0.0;
qreal m_shadowOffset = 0.0;
qreal m_spritePadding = 0.0;
mutable QRectF m_cachedSurfaceRect;
qreal m_videoParamsDisplayWidth = 0.0;
qreal m_videoParamsDisplayHeight = 0.0;
qreal m_videoFallbackWidth = 0.0;
qreal m_videoFallbackHeight = 0.0;
bool m_visibleRequested = false;
bool m_playbackPaused = true;
bool m_bottomSubtitleProtected = false;
bool m_scheduleDirty = false;
bool m_clearSpriteCacheOnNextRebuild = false;
mutable bool m_surfaceRectDirty = true;
};
#endif
+47 -27
View File
@@ -101,23 +101,8 @@ MainWindow::MainWindow(QWidget *parent)
});
}
});
connect(m_trayManager, &TrayManager::quitRequested, this, [this]() {
m_realQuit = true;
if (auto *player = m_homeView->activePlayerView()) {
player->stopAndReport();
QElapsedTimer wait;
wait.start();
while (wait.elapsed() < 500) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
}
}
if(m_core && m_core->authService()) {
m_core->authService()->logout();
}
qApp->quit();
});
connect(m_trayManager, &TrayManager::quitRequested, this,
&MainWindow::requestApplicationQuit);
@@ -1045,6 +1030,46 @@ void MainWindow::navigateToLogin() {
fadeIn->start(QAbstractAnimation::DeleteWhenStopped);
}
void MainWindow::requestApplicationQuit()
{
if (m_quitPending) {
return;
}
m_quitPending = true;
m_realQuit = true;
const bool stoppedPlayback = stopActivePlaybackForQuit();
if (stoppedPlayback) {
QTimer::singleShot(500, this, &MainWindow::finishApplicationQuit);
return;
}
finishApplicationQuit();
}
bool MainWindow::stopActivePlaybackForQuit()
{
if (!m_homeView) {
return false;
}
auto *player = m_homeView->activePlayerView();
if (!player) {
return false;
}
player->stopAndReport();
return true;
}
void MainWindow::finishApplicationQuit()
{
if (m_core && m_core->authService()) {
m_core->authService()->logout();
}
qApp->quit();
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (watched == qApp && event->type() == QEvent::ApplicationStateChange) {
@@ -1172,16 +1197,11 @@ void MainWindow::closeEvent(QCloseEvent *event)
hide();
event->ignore();
} else {
if (auto *player = m_homeView->activePlayerView()) {
player->stopAndReport();
QElapsedTimer wait;
wait.start();
while (wait.elapsed() < 500) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
}
if (!m_quitPending) {
requestApplicationQuit();
event->ignore();
return;
}
event->accept();
event->accept();
}
}
+4
View File
@@ -33,6 +33,9 @@ protected:
void closeEvent(QCloseEvent *event) override;
private:
void requestApplicationQuit();
bool stopActivePlaybackForQuit();
void finishApplicationQuit();
void setupGlobalSearchHistory();
void hideGlobalSearchTransientUi();
void updateGlobalSearchCompleter(const QString &text = QString());
@@ -59,6 +62,7 @@ private:
bool m_themeAnimating{false};
bool m_wasPausedByTray{false};
bool m_viewTransitionInProgress{false};
bool m_quitPending{false};
};
#endif