From e52cc3eb2930391a19932e69cd27efee79d56ad9 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 4 Aug 2025 15:00:48 -0500 Subject: [PATCH] adding back mpv into git --- .gitignore | 1 - src/cpp/mpv/mpvitem.cpp | 244 ++++++++++++++++++++++++++++++++++++ src/cpp/mpv/mpvitem.h | 104 +++++++++++++++ src/cpp/mpv/mpvproperties.h | 56 +++++++++ 4 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 src/cpp/mpv/mpvitem.cpp create mode 100644 src/cpp/mpv/mpvitem.h create mode 100644 src/cpp/mpv/mpvproperties.h diff --git a/.gitignore b/.gitignore index de9462f..eb083da 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,3 @@ target /log.txt .env clippy.toml -src/cpp/ \ No newline at end of file diff --git a/src/cpp/mpv/mpvitem.cpp b/src/cpp/mpv/mpvitem.cpp new file mode 100644 index 0000000..888fe93 --- /dev/null +++ b/src/cpp/mpv/mpvitem.cpp @@ -0,0 +1,244 @@ +/* + * SPDX-FileCopyrightText: 2023 George Florea Bănuș + * + * SPDX-License-Identifier: MIT + */ + +#include "mpvitem.h" + +#include + +#include "mpvproperties.h" + +MpvItem::MpvItem(QQuickItem *parent) + : MpvAbstractItem(parent) +{ + observeProperty(MpvProperties::self()->MediaTitle, MPV_FORMAT_STRING); + observeProperty(MpvProperties::self()->Position, MPV_FORMAT_DOUBLE); + observeProperty(MpvProperties::self()->Duration, MPV_FORMAT_DOUBLE); + observeProperty(MpvProperties::self()->Pause, MPV_FORMAT_FLAG); + observeProperty(MpvProperties::self()->Volume, MPV_FORMAT_INT64); + + setupConnections(); + + // since this is async the effects are not immediately visible + // to do something after the property was set do it in onAsyncReply + // use the id to identify the correct call + setPropertyAsync(QStringLiteral("volume"), 99, static_cast(MpvItem::AsyncIds::SetVolume)); + setProperty(QStringLiteral("mute"), true); + + // since this is async the effects are not immediately visible + // to get the value do it in onGetPropertyReply + // use the id to identify the correct call + getPropertyAsync(MpvProperties::self()->Volume, static_cast(MpvItem::AsyncIds::GetVolume)); +} + +void MpvItem::setupConnections() +{ + // clang-format off + connect(mpvController(), &MpvController::propertyChanged, + this, &MpvItem::onPropertyChanged, Qt::QueuedConnection); + + connect(mpvController(), &MpvController::fileStarted, + this, &MpvItem::fileStarted, Qt::QueuedConnection); + + connect(mpvController(), &MpvController::fileLoaded, + this, &MpvItem::fileLoaded, Qt::QueuedConnection); + + connect(mpvController(), &MpvController::endFile, + this, &MpvItem::endFile, Qt::QueuedConnection); + + connect(mpvController(), &MpvController::videoReconfig, + this, &MpvItem::videoReconfig, Qt::QueuedConnection); + + connect(mpvController(), &MpvController::asyncReply, + this, &MpvItem::onAsyncReply, Qt::QueuedConnection); + // clang-format on +} + +void MpvItem::onPropertyChanged(const QString &property, const QVariant &value) +{ + if (property == MpvProperties::self()->MediaTitle) { + Q_EMIT mediaTitleChanged(); + + } else if (property == MpvProperties::self()->Position) { + m_formattedPosition = formatTime(value.toDouble()); + Q_EMIT positionChanged(); + + } else if (property == MpvProperties::self()->Duration) { + m_formattedDuration = formatTime(value.toDouble()); + Q_EMIT durationChanged(); + + } else if (property == MpvProperties::self()->Pause) { + Q_EMIT pauseChanged(); + + } else if (property == MpvProperties::self()->Volume) { + Q_EMIT volumeChanged(); + } else if (property == MpvProperties::self()->Mute) { + Q_EMIT mutedChanged(); + } +} + +void MpvItem::onAsyncReply(const QVariant &data, mpv_event event) +{ + switch (static_cast(event.reply_userdata)) { + case AsyncIds::None: { + break; + } + case AsyncIds::SetVolume: { + qDebug() << "onSetPropertyReply" << event.reply_userdata; + break; + } + case AsyncIds::GetVolume: { + qDebug() << "onGetPropertyReply" << event.reply_userdata << data; + break; + } + case AsyncIds::ExpandText: { + qDebug() << "onGetPropertyReply" << event.reply_userdata << data; + break; + } + } +} + +QString MpvItem::formatTime(const double time) +{ + int totalNumberOfSeconds = static_cast(time); + int seconds = totalNumberOfSeconds % 60; + int minutes = (totalNumberOfSeconds / 60) % 60; + int hours = (totalNumberOfSeconds / 60 / 60); + + QString timeString = + QStringLiteral("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0')); + + return timeString; +} + +void MpvItem::loadFile(const QString &file) +{ + auto url = QUrl::fromUserInput(file); + if (m_currentUrl != url) { + m_currentUrl = url; + Q_EMIT currentUrlChanged(); + Q_EMIT sourceChanged(); + } + + Q_EMIT command(QStringList() << QStringLiteral("loadfile") << m_currentUrl.toString(QUrl::PreferLocalFile)); +} + +void MpvItem::seek(const double &value) +{ + setPosition(value); +} + +QString MpvItem::mediaTitle() +{ + return getProperty(MpvProperties::self()->MediaTitle).toString(); +} + +double MpvItem::position() +{ + return getProperty(MpvProperties::self()->Position).toDouble(); +} + +void MpvItem::setPosition(double value) +{ + if (qFuzzyCompare(value, position())) { + return; + } + Q_EMIT setPropertyAsync(MpvProperties::self()->Position, value); +} + +double MpvItem::duration() +{ + return getProperty(MpvProperties::self()->Duration).toDouble(); +} + +bool MpvItem::pause() +{ + return getProperty(MpvProperties::self()->Pause).toBool(); +} + +void MpvItem::setPause(bool value) +{ + if (value == pause()) { + return; + } + Q_EMIT setPropertyAsync(MpvProperties::self()->Pause, value); +} + +int MpvItem::volume() +{ + return getProperty(MpvProperties::self()->Volume).toInt(); +} + +void MpvItem::setVolume(int value) +{ + if (value == volume()) { + return; + } + Q_EMIT setPropertyAsync(MpvProperties::self()->Volume, value); +} + +bool MpvItem::muted() +{ + return getProperty(MpvProperties::self()->Mute).toBool(); +} + +void MpvItem::setMuted(bool value) +{ + Q_EMIT setPropertyAsync(MpvProperties::self()->Mute, value); +} + +bool MpvItem::loop() +{ + return getProperty(MpvProperties::self()->Loop).toBool(); +} + +void MpvItem::setLoop(bool value) +{ + Q_EMIT setPropertyAsync(MpvProperties::self()->Loop, value); +} + +QString MpvItem::formattedDuration() const +{ + return m_formattedDuration; +} + +QString MpvItem::formattedPosition() const +{ + return m_formattedPosition; +} + +QUrl MpvItem::currentUrl() const +{ + return m_currentUrl; +} + +QUrl MpvItem::source() const +{ + return m_currentUrl; +} + +void MpvItem::setSource(const QUrl &source) +{ + if (m_currentUrl != source) { + m_currentUrl = source; + Q_EMIT currentUrlChanged(); + Q_EMIT sourceChanged(); + } + + Q_EMIT command(QStringList() << QStringLiteral("loadfile") << m_currentUrl.toString(QUrl::PreferLocalFile)); +} + +void MpvItem::playPause() +{ + if (getProperty(MpvProperties::self()->Pause).toBool()) { + Q_EMIT setPropertyAsync(MpvProperties::self()->Pause, false); + } else { + Q_EMIT setPropertyAsync(MpvProperties::self()->Pause, true); + } +} + + + +#include "moc_mpvitem.cpp" diff --git a/src/cpp/mpv/mpvitem.h b/src/cpp/mpv/mpvitem.h new file mode 100644 index 0000000..7a7e503 --- /dev/null +++ b/src/cpp/mpv/mpvitem.h @@ -0,0 +1,104 @@ +/* + * SPDX-FileCopyrightText: 2023 George Florea Bănuș + * + * SPDX-License-Identifier: MIT + */ + +#ifndef MPVOBJECT_H +#define MPVOBJECT_H + +#include +#include + +class MpvRenderer; + +class MpvItem : public MpvAbstractItem +{ + Q_OBJECT + QML_ELEMENT +public: + explicit MpvItem(QQuickItem *parent = nullptr); + ~MpvItem() = default; + + enum class AsyncIds { + None, + SetVolume, + GetVolume, + ExpandText, + }; + Q_ENUM(AsyncIds) + + Q_PROPERTY(QString mediaTitle READ mediaTitle NOTIFY mediaTitleChanged) + QString mediaTitle(); + + Q_PROPERTY(double position READ position WRITE setPosition NOTIFY positionChanged) + double position(); + void setPosition(double value); + + Q_PROPERTY(double duration READ duration NOTIFY durationChanged) + double duration(); + + Q_PROPERTY(QString formattedPosition READ formattedPosition NOTIFY positionChanged) + QString formattedPosition() const; + + Q_PROPERTY(QString formattedDuration READ formattedDuration NOTIFY durationChanged) + QString formattedDuration() const; + + Q_PROPERTY(bool pause READ pause WRITE setPause NOTIFY pauseChanged) + bool pause(); + void setPause(bool value); + + Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) + int volume(); + void setVolume(int value); + + Q_PROPERTY(bool muted READ muted WRITE setMuted NOTIFY mutedChanged) + bool muted(); + void setMuted(bool value); + + Q_PROPERTY(bool loop READ loop WRITE setLoop NOTIFY loopChanged) + bool loop(); + void setLoop(bool value); + + Q_PROPERTY(QUrl currentUrl READ currentUrl NOTIFY currentUrlChanged) + QUrl currentUrl() const; + + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + QUrl source() const; + void setSource(const QUrl &source); + + Q_INVOKABLE void loadFile(const QString &file); + Q_INVOKABLE void seek(const double &value); + Q_INVOKABLE void playPause(); + +Q_SIGNALS: + void mediaTitleChanged(); + void currentUrlChanged(); + void positionChanged(); + void durationChanged(); + void pauseChanged(); + void volumeChanged(); + void mutedChanged(); + void sourceChanged(); + void loopChanged(); + + void fileStarted(); + void fileLoaded(); + void endFile(QString reason); + void videoReconfig(); + +private: + void setupConnections(); + void onPropertyChanged(const QString &property, const QVariant &value); + void onAsyncReply(const QVariant &data, mpv_event event); + QString formatTime(const double time); + + double m_position{0.0}; + QString m_formattedPosition; + double m_duration{0.0}; + QString m_formattedDuration; + QUrl m_currentUrl; + bool m_loop; +}; + +#endif // MPVOBJECT_H diff --git a/src/cpp/mpv/mpvproperties.h b/src/cpp/mpv/mpvproperties.h new file mode 100644 index 0000000..9a43f37 --- /dev/null +++ b/src/cpp/mpv/mpvproperties.h @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2023 George Florea Bănuș + * + * SPDX-License-Identifier: MIT + */ + +#ifndef MPVPROPERTIES_H +#define MPVPROPERTIES_H + +#include +#include + +class MpvProperties : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + +public: + explicit MpvProperties(QObject *parent = nullptr) + : QObject(parent) + { + } + + static MpvProperties *self() + { + static MpvProperties p; + return &p; + } + + Q_PROPERTY(QString MediaTitle MEMBER MediaTitle CONSTANT) + const QString MediaTitle{QStringLiteral("media-title")}; + + Q_PROPERTY(QString Position MEMBER Position CONSTANT) + const QString Position{QStringLiteral("time-pos")}; + + Q_PROPERTY(QString Duration MEMBER Duration CONSTANT) + const QString Duration{QStringLiteral("duration")}; + + Q_PROPERTY(QString Pause MEMBER Pause CONSTANT) + const QString Pause{QStringLiteral("pause")}; + + Q_PROPERTY(QString Volume MEMBER Volume CONSTANT) + const QString Volume{QStringLiteral("volume")}; + + Q_PROPERTY(QString Mute MEMBER Mute CONSTANT) + const QString Mute{QStringLiteral("mute")}; + + Q_PROPERTY(QString Loop MEMBER Loop CONSTANT) + const QString Loop{QStringLiteral("loop")}; + +private: + Q_DISABLE_COPY_MOVE(MpvProperties) +}; + +#endif // MPVPROPERTIES_H