// SPDX-FileCopyrightText: 2019 Linus Jahn // SPDX-FileCopyrightText: 2022 Devin Lin // SPDX-FileCopyrightText: 2023 Joshua Goins // SPDX-License-Identifier: GPL-3.0-or-later #include "utils/mpvplayer.h" #include MpvPlayer::MpvPlayer(QQuickItem *parent) : MpvAbstractItem(parent) { // enable console output setProperty(QStringLiteral("terminal"), QStringLiteral("yes")); // don't load user scripts or configs setProperty(QStringLiteral("config"), QStringLiteral("no")); setProperty(QStringLiteral("load-scripts"), QStringLiteral("no")); // force vo to libmpv (which it should be set to anyway) setProperty(QStringLiteral("vo"), QStringLiteral("libmpv")); // use safe hardware acceleration setProperty(QStringLiteral("hwdec"), QStringLiteral("auto-safe")); // disable OSD and fonts setProperty(QStringLiteral("osd-level"), QStringLiteral("0")); setProperty(QStringLiteral("embeddedfonts"), QStringLiteral("no")); // disable input setProperty(QStringLiteral("input-builtin-bindings"), QStringLiteral("no")); setProperty(QStringLiteral("input-default-bindings"), QStringLiteral("no")); setProperty(QStringLiteral("input-vo-keyboard"), QStringLiteral("no")); // shut up output setProperty(QStringLiteral("msg-level"), QStringLiteral("all=warn")); observeProperty(QStringLiteral("duration"), MPV_FORMAT_DOUBLE); observeProperty(QStringLiteral("time-pos"), MPV_FORMAT_DOUBLE); observeProperty(QStringLiteral("pause"), MPV_FORMAT_FLAG); connect(mpvController(), &MpvController::propertyChanged, this, &MpvPlayer::onPropertyChanged, Qt::QueuedConnection); connect( mpvController(), &MpvController::fileLoaded, this, [this] { m_loading = false; Q_EMIT loadingChanged(); }, Qt::QueuedConnection); connect( mpvController(), &MpvController::videoReconfig, this, [this] { const int64_t w = getProperty(QStringLiteral("dwidth")).toInt(); const int64_t h = getProperty(QStringLiteral("dheight")).toInt(); if (w > 0 && h > 0) { const QSize newSize(w, h); if (newSize != m_sourceSize) { m_sourceSize = newSize; Q_EMIT sourceSizeChanged(); } } }, Qt::QueuedConnection); } qreal MpvPlayer::position() const { return m_position; } qreal MpvPlayer::duration() const { return m_duration; } bool MpvPlayer::paused() const { return m_paused; } QSize MpvPlayer::sourceSize() const { return m_sourceSize; } QString MpvPlayer::source() const { return m_source; } bool MpvPlayer::loading() const { return m_loading; } bool MpvPlayer::looping() const { return m_looping; } bool MpvPlayer::autoPlay() const { return m_autoPlay; } bool MpvPlayer::stopped() const { return m_currentSource.isEmpty(); } void MpvPlayer::setSource(const QString &source) { if (m_source == source) { return; } m_source = source; if (m_autoPlay) { play(); } Q_EMIT sourceChanged(); } void MpvPlayer::setLooping(bool loop) { if (m_looping == loop) { return; } m_looping = loop; setProperty(QStringLiteral("loop-file"), loop ? QStringLiteral("inf") : QStringLiteral("no")); Q_EMIT loopingChanged(); } void MpvPlayer::setAutoPlay(bool autoPlay) { if (m_autoPlay == autoPlay) { return; } m_autoPlay = autoPlay; Q_EMIT autoPlayChanged(); } void MpvPlayer::play() { if (!paused() || m_source.isEmpty()) { return; } // setSource doesn't actually load the file into MPV, because the player is always created // regardless of autoPlay. This incurs a very visible overhead in the UI, so we want to delay // the loadfile command until the last possible moment (when the user requests to play it). if (m_currentSource != m_source) { m_loading = true; Q_EMIT loadingChanged(); command(QStringList{QStringLiteral("loadfile"), m_source}); m_currentSource = m_source; m_paused = false; Q_EMIT stoppedChanged(); Q_EMIT pausedChanged(); } setProperty(QStringLiteral("pause"), false); } void MpvPlayer::pause() { if (paused()) { return; } setProperty(QStringLiteral("pause"), true); } void MpvPlayer::stop() { setPosition(0); setProperty(QStringLiteral("pause"), true); } void MpvPlayer::setPosition(double value) { if (value == position()) { return; } setProperty(QStringLiteral("time-pos"), value); } void MpvPlayer::seek(qreal offset) { command(QStringList() << QStringLiteral("add") << QStringLiteral("time-pos") << QString::number(offset)); } void MpvPlayer::onPropertyChanged(const QString &property, const QVariant &value) { if (property == QStringLiteral("time-pos")) { m_position = value.toDouble(); Q_EMIT positionChanged(); } else if (property == QStringLiteral("duration")) { m_duration = value.toDouble(); Q_EMIT durationChanged(); } else if (property == QStringLiteral("pause")) { // pause is expected to be false if there's no currently loaded media, so skip it if (!m_currentSource.isEmpty()) { m_paused = value.toBool(); Q_EMIT pausedChanged(); } } } #include "moc_mpvplayer.cpp"