File indexing completed on 2024-05-12 05:04:25
0001 // SPDX-FileCopyrightText: 2019 Linus Jahn <lnj@kaidan.im> 0002 // SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org> 0003 // SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com> 0004 // 0005 // SPDX-License-Identifier: GPL-3.0-or-later 0006 0007 #include "mpvplayer.h" 0008 0009 #include <MpvController> 0010 0011 MpvPlayer::MpvPlayer(QQuickItem *parent) 0012 : MpvAbstractItem(parent) 0013 { 0014 // enable console output 0015 setProperty(QStringLiteral("terminal"), QStringLiteral("yes")); 0016 0017 // don't load user scripts or configs 0018 setProperty(QStringLiteral("config"), QStringLiteral("no")); 0019 setProperty(QStringLiteral("load-scripts"), QStringLiteral("no")); 0020 0021 // force vo to libmpv (which it should be set to anyway) 0022 setProperty(QStringLiteral("vo"), QStringLiteral("libmpv")); 0023 0024 // use safe hardware acceleration 0025 setProperty(QStringLiteral("hwdec"), QStringLiteral("auto-safe")); 0026 0027 // disable OSD and fonts 0028 setProperty(QStringLiteral("osd-level"), QStringLiteral("0")); 0029 setProperty(QStringLiteral("embeddedfonts"), QStringLiteral("no")); 0030 0031 // disable input 0032 setProperty(QStringLiteral("input-builtin-bindings"), QStringLiteral("no")); 0033 setProperty(QStringLiteral("input-default-bindings"), QStringLiteral("no")); 0034 setProperty(QStringLiteral("input-vo-keyboard"), QStringLiteral("no")); 0035 0036 observeProperty(QStringLiteral("duration"), MPV_FORMAT_DOUBLE); 0037 observeProperty(QStringLiteral("time-pos"), MPV_FORMAT_DOUBLE); 0038 observeProperty(QStringLiteral("pause"), MPV_FORMAT_FLAG); 0039 0040 connect(mpvController(), &MpvController::propertyChanged, this, &MpvPlayer::onPropertyChanged, Qt::QueuedConnection); 0041 connect( 0042 mpvController(), 0043 &MpvController::fileLoaded, 0044 this, 0045 [this] { 0046 m_loading = false; 0047 Q_EMIT loadingChanged(); 0048 }, 0049 Qt::QueuedConnection); 0050 connect( 0051 mpvController(), 0052 &MpvController::videoReconfig, 0053 this, 0054 [this] { 0055 const int64_t w = getProperty(QStringLiteral("dwidth")).toInt(); 0056 const int64_t h = getProperty(QStringLiteral("dheight")).toInt(); 0057 if (w > 0 && h > 0) { 0058 const QSize newSize(w, h); 0059 if (newSize != m_sourceSize) { 0060 m_sourceSize = newSize; 0061 Q_EMIT sourceSizeChanged(); 0062 } 0063 } 0064 }, 0065 Qt::QueuedConnection); 0066 } 0067 0068 qreal MpvPlayer::position() const 0069 { 0070 return m_position; 0071 } 0072 0073 qreal MpvPlayer::duration() const 0074 { 0075 return m_duration; 0076 } 0077 0078 bool MpvPlayer::paused() const 0079 { 0080 return m_paused; 0081 } 0082 0083 QSize MpvPlayer::sourceSize() const 0084 { 0085 return m_sourceSize; 0086 } 0087 0088 QString MpvPlayer::source() const 0089 { 0090 return m_source; 0091 } 0092 0093 bool MpvPlayer::loading() const 0094 { 0095 return m_loading; 0096 } 0097 0098 bool MpvPlayer::looping() const 0099 { 0100 return m_looping; 0101 } 0102 0103 bool MpvPlayer::autoPlay() const 0104 { 0105 return m_autoPlay; 0106 } 0107 0108 bool MpvPlayer::stopped() const 0109 { 0110 return m_currentSource.isEmpty(); 0111 } 0112 0113 void MpvPlayer::setSource(const QString &source) 0114 { 0115 if (m_source == source) { 0116 return; 0117 } 0118 0119 m_source = source; 0120 0121 if (m_autoPlay) { 0122 play(); 0123 } 0124 0125 Q_EMIT sourceChanged(); 0126 } 0127 0128 void MpvPlayer::setLooping(bool loop) 0129 { 0130 if (m_looping == loop) { 0131 return; 0132 } 0133 0134 m_looping = loop; 0135 setProperty(QStringLiteral("loop-file"), loop ? QStringLiteral("inf") : QStringLiteral("no")); 0136 0137 Q_EMIT loopingChanged(); 0138 } 0139 0140 void MpvPlayer::setAutoPlay(bool autoPlay) 0141 { 0142 if (m_autoPlay == autoPlay) { 0143 return; 0144 } 0145 0146 m_autoPlay = autoPlay; 0147 0148 Q_EMIT autoPlayChanged(); 0149 } 0150 0151 void MpvPlayer::play() 0152 { 0153 if (!paused() || m_source.isEmpty()) { 0154 return; 0155 } 0156 0157 // setSource doesn't actually load the file into MPV, because the player is always created 0158 // regardless of autoPlay. This incurs a very visible overhead in the UI, so we want to delay 0159 // the loadfile command until the last possible moment (when the user requests to play it). 0160 if (m_currentSource != m_source) { 0161 m_loading = true; 0162 Q_EMIT loadingChanged(); 0163 0164 command(QStringList{QStringLiteral("loadfile"), m_source}); 0165 0166 m_currentSource = m_source; 0167 m_paused = false; 0168 0169 Q_EMIT stoppedChanged(); 0170 Q_EMIT pausedChanged(); 0171 } 0172 0173 setProperty(QStringLiteral("pause"), false); 0174 } 0175 0176 void MpvPlayer::pause() 0177 { 0178 if (paused()) { 0179 return; 0180 } 0181 setProperty(QStringLiteral("pause"), true); 0182 } 0183 0184 void MpvPlayer::stop() 0185 { 0186 setPosition(0); 0187 setProperty(QStringLiteral("pause"), true); 0188 } 0189 0190 void MpvPlayer::setPosition(double value) 0191 { 0192 if (value == position()) { 0193 return; 0194 } 0195 setProperty(QStringLiteral("time-pos"), value); 0196 } 0197 0198 void MpvPlayer::seek(qreal offset) 0199 { 0200 command(QStringList() << QStringLiteral("add") << QStringLiteral("time-pos") << QString::number(offset)); 0201 } 0202 0203 void MpvPlayer::onPropertyChanged(const QString &property, const QVariant &value) 0204 { 0205 if (property == QStringLiteral("time-pos")) { 0206 m_position = value.toDouble(); 0207 Q_EMIT positionChanged(); 0208 } else if (property == QStringLiteral("duration")) { 0209 m_duration = value.toDouble(); 0210 Q_EMIT durationChanged(); 0211 } else if (property == QStringLiteral("pause")) { 0212 // pause is expected to be false if there's no currently loaded media, so skip it 0213 if (!m_currentSource.isEmpty()) { 0214 m_paused = value.toBool(); 0215 Q_EMIT pausedChanged(); 0216 } 0217 } 0218 } 0219 0220 #include "moc_mpvplayer.cpp"