feat: add Kirigami app skeleton with libmpv playback
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
1eb67b829c
8 files changed
+540
No files matched your search
@@ -0,0 +1,140 @@
|
||||
#include "mpvitem.h"
|
||||
|
||||
#include <MpvController>
|
||||
|
||||
#include <utility>
|
||||
|
||||
MpvItem::MpvItem(QQuickItem *parent)
|
||||
: MpvAbstractItem(parent)
|
||||
{
|
||||
// Leave the player on the last frame at end of file instead of unloading it.
|
||||
setPropertyAsync(QStringLiteral("keep-open"), QStringLiteral("yes"));
|
||||
setPropertyAsync(QStringLiteral("hwdec"), QStringLiteral("auto-safe"));
|
||||
|
||||
observeProperty(QStringLiteral("media-title"), MPV_FORMAT_STRING);
|
||||
observeProperty(QStringLiteral("time-pos"), MPV_FORMAT_DOUBLE);
|
||||
observeProperty(QStringLiteral("duration"), MPV_FORMAT_DOUBLE);
|
||||
observeProperty(QStringLiteral("pause"), MPV_FORMAT_FLAG);
|
||||
|
||||
// MpvController lives on a worker thread; queue its signals back to the GUI thread.
|
||||
connect(mpvController(), &MpvController::propertyChanged, this, &MpvItem::onPropertyChanged, Qt::QueuedConnection);
|
||||
connect(
|
||||
mpvController(),
|
||||
&MpvController::fileLoaded,
|
||||
this,
|
||||
[this] {
|
||||
setFileLoaded(true);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
connect(
|
||||
mpvController(),
|
||||
&MpvController::endFile,
|
||||
this,
|
||||
[this] {
|
||||
setFileLoaded(false);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
// The render context only exists once Qt Quick has rendered the item for the first
|
||||
// time; a file loaded before that plays without video. Hold it until ready() fires.
|
||||
connect(this, &MpvAbstractItem::ready, this, [this] {
|
||||
m_ready = true;
|
||||
if (m_pendingUrl.isValid()) {
|
||||
loadFile(std::exchange(m_pendingUrl, {}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QUrl MpvItem::currentUrl() const
|
||||
{
|
||||
return m_currentUrl;
|
||||
}
|
||||
|
||||
QString MpvItem::mediaTitle() const
|
||||
{
|
||||
return m_mediaTitle;
|
||||
}
|
||||
|
||||
double MpvItem::position() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
double MpvItem::duration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
bool MpvItem::paused() const
|
||||
{
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
void MpvItem::setPaused(bool paused)
|
||||
{
|
||||
if (paused == m_paused) {
|
||||
return;
|
||||
}
|
||||
// m_paused is updated when mpv reports the "pause" property back.
|
||||
setPropertyAsync(QStringLiteral("pause"), paused);
|
||||
}
|
||||
|
||||
bool MpvItem::isFileLoaded() const
|
||||
{
|
||||
return m_fileLoaded;
|
||||
}
|
||||
|
||||
void MpvItem::loadFile(const QUrl &url)
|
||||
{
|
||||
if (!url.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentUrl = url;
|
||||
Q_EMIT currentUrlChanged();
|
||||
|
||||
if (!m_ready) {
|
||||
m_pendingUrl = url;
|
||||
return;
|
||||
}
|
||||
|
||||
const QString target = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||
commandAsync(QStringList{QStringLiteral("loadfile"), target});
|
||||
setPropertyAsync(QStringLiteral("pause"), false);
|
||||
}
|
||||
|
||||
void MpvItem::togglePause()
|
||||
{
|
||||
setPaused(!m_paused);
|
||||
}
|
||||
|
||||
void MpvItem::seek(double seconds)
|
||||
{
|
||||
commandAsync(QStringList{QStringLiteral("seek"), QString::number(seconds), QStringLiteral("absolute")});
|
||||
}
|
||||
|
||||
void MpvItem::onPropertyChanged(const QString &property, const QVariant &value)
|
||||
{
|
||||
if (property == u"media-title") {
|
||||
m_mediaTitle = value.toString();
|
||||
Q_EMIT mediaTitleChanged();
|
||||
} else if (property == u"time-pos") {
|
||||
m_position = value.toDouble();
|
||||
Q_EMIT positionChanged();
|
||||
} else if (property == u"duration") {
|
||||
m_duration = value.toDouble();
|
||||
Q_EMIT durationChanged();
|
||||
} else if (property == u"pause") {
|
||||
m_paused = value.toBool();
|
||||
Q_EMIT pausedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void MpvItem::setFileLoaded(bool loaded)
|
||||
{
|
||||
if (loaded == m_fileLoaded) {
|
||||
return;
|
||||
}
|
||||
m_fileLoaded = loaded;
|
||||
Q_EMIT fileLoadedChanged();
|
||||
}
|
||||
Reference in new issue
Block a user