aboutsummaryrefslogtreecommitdiff
path: root/mpris-plugin
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2023-11-26 01:10:36 -0500
committerGravatar Chris Xiong <chirs241097@gmail.com> 2023-11-26 01:10:36 -0500
commit60989e52b3f3bc0a95d3e61bd8e59fa4d9b7ab83 (patch)
treeaf08e5b6f7019c6f70bf3800a419ec78db140988 /mpris-plugin
parent382d85b15ce9cc4580a2522b39f5dd4ce43a24b0 (diff)
downloadQMidiPlayer-60989e52b3f3bc0a95d3e61bd8e59fa4d9b7ab83.tar.xz
The 2 year constipation. (mpris plugin)
Probably buggy as hell.
Diffstat (limited to 'mpris-plugin')
-rw-r--r--mpris-plugin/CMakeLists.txt30
-rw-r--r--mpris-plugin/qmpmpris.cpp29
-rw-r--r--mpris-plugin/qmpmpris.hpp32
-rw-r--r--mpris-plugin/qmpmprisimpl.cpp206
-rw-r--r--mpris-plugin/qmpmprisimpl.hpp72
-rw-r--r--mpris-plugin/qmprisdbusinterface.cpp200
-rw-r--r--mpris-plugin/qmprisdbusinterface.hpp148
-rw-r--r--mpris-plugin/qmpriswrapper.cpp77
-rw-r--r--mpris-plugin/qmpriswrapper.hpp53
9 files changed, 847 insertions, 0 deletions
diff --git a/mpris-plugin/CMakeLists.txt b/mpris-plugin/CMakeLists.txt
new file mode 100644
index 0000000..c0395c0
--- /dev/null
+++ b/mpris-plugin/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(qmpmpris_SOURCES
+ qmpmpris.hpp
+ qmprisdbusinterface.hpp
+ qmpriswrapper.hpp
+ qmpmprisimpl.hpp
+ qmpmpris.cpp
+ qmprisdbusinterface.cpp
+ qmpriswrapper.cpp
+ qmpmprisimpl.cpp
+)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+find_package(Qt5 REQUIRED COMPONENTS DBus)
+
+include_directories(${PROJECT_SOURCE_DIR}/include/)
+
+add_library(qmpmpris MODULE
+ ${qmpmpris_SOURCES}
+)
+
+target_link_libraries(qmpmpris
+ Qt5::Core
+ Qt5::Widgets
+ Qt5::DBus
+)
+
+install(TARGETS qmpmpris LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/qmidiplayer/)
diff --git a/mpris-plugin/qmpmpris.cpp b/mpris-plugin/qmpmpris.cpp
new file mode 100644
index 0000000..2eb18fd
--- /dev/null
+++ b/mpris-plugin/qmpmpris.cpp
@@ -0,0 +1,29 @@
+#include <cstdio>
+#include "qmpmpris.hpp"
+#include "qmpriswrapper.hpp"
+#include "qmpmprisimpl.hpp"
+
+qmpMPrisPlugin::qmpMPrisPlugin(qmpPluginAPI *_api)
+{
+ api = _api;
+}
+qmpMPrisPlugin::~qmpMPrisPlugin()
+{
+ api = nullptr;
+}
+void qmpMPrisPlugin::init()
+{
+ mw = QMPrisWrapper::create<QMPPlayer, QMPMediaPlayer2, QMPTrackList>("qmidiplayer", api);
+}
+void qmpMPrisPlugin::deinit()
+{
+ delete mw;
+}
+const char *qmpMPrisPlugin::pluginGetName()
+{
+ return "QMidiPlayer MPris Support";
+}
+const char *qmpMPrisPlugin::pluginGetVersion()
+{
+ return "0.8.8";
+}
diff --git a/mpris-plugin/qmpmpris.hpp b/mpris-plugin/qmpmpris.hpp
new file mode 100644
index 0000000..fbc8bfa
--- /dev/null
+++ b/mpris-plugin/qmpmpris.hpp
@@ -0,0 +1,32 @@
+#ifndef QMPMPRIS_HPP
+#define QMPMPRIS_HPP
+
+#include "../include/qmpcorepublic.hpp"
+
+class QMPrisWrapper;
+class qmpMPrisPlugin: public qmpPluginIntf
+{
+private:
+ qmpPluginAPI *api;
+ QMPrisWrapper *mw = nullptr;
+public:
+ qmpMPrisPlugin(qmpPluginAPI *_api);
+ ~qmpMPrisPlugin();
+ void init();
+ void deinit();
+ const char *pluginGetName();
+ const char *pluginGetVersion();
+};
+
+extern "C" {
+ EXPORTSYM qmpPluginIntf *qmpPluginGetInterface(qmpPluginAPI *api)
+ {
+ return new qmpMPrisPlugin(api);
+ }
+ EXPORTSYM const char *qmpPluginGetAPIRev()
+ {
+ return QMP_PLUGIN_API_REV;
+ }
+}
+
+#endif
diff --git a/mpris-plugin/qmpmprisimpl.cpp b/mpris-plugin/qmpmprisimpl.cpp
new file mode 100644
index 0000000..335a638
--- /dev/null
+++ b/mpris-plugin/qmpmprisimpl.cpp
@@ -0,0 +1,206 @@
+#include <QMetaEnum>
+
+#include "../include/qmpcorepublic.hpp"
+#include "../qmidiplayer-desktop/qmpmainwindow.hpp"
+#include "qmpmprisimpl.hpp"
+
+inline QVariantMap get_metadata(qmpPluginAPI *api)
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ return {
+ {"mpris:trackid", QDBusObjectPath("/org/chrisoft/qmidiplayer/dummylist/0")},
+ {"xesam:url", QString::fromStdWString(api->getWFilePath())},
+ {"xesam:title", QString::fromStdWString(api->getWTitle())},
+ {"mpris:length", qlonglong(ps.maxtime_ms * 1000)}
+ };
+}
+
+QMPPlayer::QMPPlayer(qmpPluginAPI *_api, QObject *parent) :
+ api(_api),
+ QMPrisPlayer(parent)
+{
+ qmw = static_cast<qmpMainWindow*>(api->getMainWindow());
+}
+
+QString QMPPlayer::getPlaybackStatus()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ QMPrisPlayer::PlaybackStatus r = QMPrisPlayer::PlaybackStatus::Stopped;
+ if (!ps.stopped)
+ r = ps.paused ? QMPrisPlayer::PlaybackStatus::Paused : QMPrisPlayer::PlaybackStatus::Playing;
+ return QMetaEnum::fromType<QMPrisPlayer::PlaybackStatus>().key(r);
+}
+
+QString QMPPlayer::getLoopStatus()
+{
+ return QMetaEnum::fromType<QMPrisPlayer::LoopStatus>().key(QMPrisPlayer::LoopStatus::None);
+}
+
+double QMPPlayer::getRate()
+{
+ return 1;
+}
+
+bool QMPPlayer::getShuffle()
+{
+ return false;
+}
+
+QVariantMap QMPPlayer::getMetadata()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ if (ps.stopped) return {};
+ return get_metadata(api);
+}
+
+qlonglong QMPPlayer::getPosition()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ fprintf(stderr, "%lu\n", ps.curtime_ms);
+ return ps.curtime_ms * 1000;
+}
+
+bool QMPPlayer::getCanGoNext()
+{
+ return getCanPlay();
+}
+
+bool QMPPlayer::getCanGoPrevious()
+{
+ return getCanPlay();
+}
+
+bool QMPPlayer::getCanPlay()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ return !ps.stopped;
+}
+
+bool QMPPlayer::getCanPause()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ return !ps.stopped && !ps.paused;
+}
+
+bool QMPPlayer::getCanSeek()
+{
+ return getCanPlay();
+}
+
+bool QMPPlayer::getCanControl()
+{
+ return true;
+}
+
+void QMPPlayer::Pause()
+{
+ api->playbackControl(PlaybackControlCommand::Pause, nullptr);
+}
+
+void QMPPlayer::PlayPause()
+{
+ api->playbackControl(PlaybackControlCommand::TogglePause, nullptr);
+}
+
+void QMPPlayer::Stop()
+{
+ api->playbackControl(PlaybackControlCommand::Stop, nullptr);
+}
+
+void QMPPlayer::Play()
+{
+ api->playbackControl(PlaybackControlCommand::Play, nullptr);
+}
+
+void QMPPlayer::Next()
+{
+ api->playbackControl(PlaybackControlCommand::NextTrack, nullptr);
+}
+
+void QMPPlayer::Previous()
+{
+ api->playbackControl(PlaybackControlCommand::PrevTrack, nullptr);
+}
+
+void QMPPlayer::Seek(qlonglong t)
+{
+ double td = t / 1e6;
+ api->playbackControl(PlaybackControlCommand::SeekAbs, &td);
+}
+
+void QMPPlayer::SetPosition(QDBusObjectPath o, qlonglong t)
+{
+ if (o.path() == QString("/org/chrisoft/qmidiplayer/dummylist/0"))
+ {
+ double td = t / 1e6;
+ api->playbackControl(PlaybackControlCommand::SeekAbs, &td);
+ }
+}
+
+QMPMediaPlayer2::QMPMediaPlayer2(qmpPluginAPI *_api, QObject *parent) :
+ api(_api),
+ QMPrisMediaPlayer2(parent)
+{
+ qmw = static_cast<qmpMainWindow*>(api->getMainWindow());
+}
+
+void QMPMediaPlayer2::Raise()
+{
+ qmw->raise();
+}
+
+void QMPMediaPlayer2::Quit()
+{
+ qmw->close();
+}
+
+bool QMPMediaPlayer2::getCanQuit()
+{
+ return true;
+}
+
+bool QMPMediaPlayer2::getCanRaise()
+{
+ return true;
+}
+
+QString QMPMediaPlayer2::getIdentity()
+{
+ return QString("QMidiPlayer");
+}
+
+QString QMPMediaPlayer2::getDesktopEntry()
+{
+ return QString("qmidiplayer");
+}
+
+bool QMPMediaPlayer2::getHasTrackList()
+{
+ return true;
+}
+
+QMPTrackList::QMPTrackList(qmpPluginAPI *_api, QObject *parent) :
+ api(_api),
+ QMPrisTrackList(parent)
+{
+}
+
+QList<QVariantMap> QMPTrackList::GetTracksMetaData(QList<QDBusObjectPath> trackIds)
+{
+ QList<QVariantMap> ret;
+ for (auto &i : trackIds)
+ {
+ if (i.path() == QString("/org/chrisoft/qmidiplayer/dummylist/0"))
+ ret.push_back(get_metadata(api));
+ else ret.push_back({});
+ }
+ return ret;
+}
+
+QList<QDBusObjectPath> QMPTrackList::getTracks()
+{
+ ::PlaybackStatus ps = api->getPlaybackStatus();
+ if (ps.stopped)
+ return {};
+ return {QDBusObjectPath("/org/chrisoft/qmidiplayer/dummylist/0")};
+}
diff --git a/mpris-plugin/qmpmprisimpl.hpp b/mpris-plugin/qmpmprisimpl.hpp
new file mode 100644
index 0000000..b9dec93
--- /dev/null
+++ b/mpris-plugin/qmpmprisimpl.hpp
@@ -0,0 +1,72 @@
+#ifndef QMPMPRISIMPL_HPP
+#define QMPMPRISIMPL_HPP
+
+#include "qmprisdbusinterface.hpp"
+
+class qmpPluginAPI;
+class qmpMainWindow;
+
+class QMPPlayer : public QMPrisPlayer
+{
+public:
+ explicit QMPPlayer(qmpPluginAPI *_api, QObject *parent=nullptr);
+
+ QString getPlaybackStatus();
+ QString getLoopStatus();
+ double getRate();
+ bool getShuffle();
+ QVariantMap getMetadata();
+ //double getVolume();
+ qlonglong getPosition();
+ //double getMinimumRate();
+ //double getMaximumRate();
+ bool getCanGoNext();
+ bool getCanGoPrevious();
+ bool getCanPlay();
+ bool getCanPause();
+ bool getCanSeek();
+ bool getCanControl();
+
+ void Pause();
+ void PlayPause();
+ void Stop();
+ void Play();
+ void Next();
+ void Previous();
+ void Seek(qlonglong t);
+ void SetPosition(QDBusObjectPath o, qlonglong t);
+private:
+ qmpPluginAPI *api;
+ qmpMainWindow *qmw;
+};
+
+class QMPTrackList : public QMPrisTrackList
+{
+public:
+ explicit QMPTrackList(qmpPluginAPI *_api, QObject *parent=nullptr);
+
+ QList<QVariantMap> GetTracksMetaData(QList<QDBusObjectPath> trackIds);
+ QList<QDBusObjectPath> getTracks();
+private:
+ qmpPluginAPI *api;
+};
+
+class QMPMediaPlayer2 : public QMPrisMediaPlayer2
+{
+public:
+ explicit QMPMediaPlayer2(qmpPluginAPI *_api, QObject *parent=nullptr);
+
+ void Raise() override;
+ void Quit() override;
+
+ bool getCanQuit() override;
+ bool getCanRaise() override;
+ QString getIdentity() override;
+ QString getDesktopEntry() override;
+ bool getHasTrackList() override;
+private:
+ qmpPluginAPI *api;
+ qmpMainWindow *qmw;
+};
+
+#endif
diff --git a/mpris-plugin/qmprisdbusinterface.cpp b/mpris-plugin/qmprisdbusinterface.cpp
new file mode 100644
index 0000000..822a705
--- /dev/null
+++ b/mpris-plugin/qmprisdbusinterface.cpp
@@ -0,0 +1,200 @@
+#include "qmprisdbusinterface.hpp"
+#include "qmpriswrapper.hpp"
+
+#include <QMetaEnum>
+
+QMPrisPlayer::QMPrisPlayer(QObject* parent) : QDBusAbstractAdaptor(parent)
+{
+}
+
+QString QMPrisPlayer::getPlaybackStatus()
+{
+ /*if (par->pbstgetter)
+ return QMetaEnum::fromType<QMPrisWrapper::PlaybackStatus>().key(par->pbstgetter());*/
+ return QString();
+}
+QString QMPrisPlayer::getLoopStatus()
+{
+ /*if (par->lpstgetter)
+ return QMetaEnum::fromType<QMPrisWrapper::LoopStatus>().key(par->lpstgetter());*/
+ return QString();
+}
+double QMPrisPlayer::getRate()
+{
+ return 1.0;
+}
+bool QMPrisPlayer::getShuffle()
+{
+ return false;
+}
+QVariantMap QMPrisPlayer::getMetadata()
+{
+ return {};
+}
+double QMPrisPlayer::getVolume()
+{
+ return 1.0;
+}
+qlonglong QMPrisPlayer::getPosition()
+{
+ return 0;
+}
+double QMPrisPlayer::getMinimumRate()
+{
+ return 1;
+}
+double QMPrisPlayer::getMaximumRate()
+{
+ return 1;
+}
+bool QMPrisPlayer::getCanGoNext()
+{
+ return false;
+}
+bool QMPrisPlayer::getCanGoPrevious()
+{
+ return false;
+}
+bool QMPrisPlayer::getCanPlay()
+{
+ return false;
+}
+bool QMPrisPlayer::getCanPause()
+{
+ return false;
+}
+bool QMPrisPlayer::getCanSeek()
+{
+ return false;
+}
+bool QMPrisPlayer::getCanControl()
+{
+ return false;
+}
+
+void QMPrisPlayer::setLoopStatus(QString loopStatus)
+{
+}
+void QMPrisPlayer::setRate(double playbackRate)
+{
+}
+bool QMPrisPlayer::setShuffle(bool shuffle)
+{
+ return false;
+}
+void QMPrisPlayer::setVolume(double volume)
+{
+}
+
+void QMPrisPlayer::Next()
+{
+}
+void QMPrisPlayer::Previous()
+{
+}
+void QMPrisPlayer::Pause()
+{
+}
+void QMPrisPlayer::PlayPause()
+{
+}
+void QMPrisPlayer::Stop()
+{
+}
+void QMPrisPlayer::Play()
+{
+}
+void QMPrisPlayer::Seek(qlonglong t)
+{
+}
+
+void QMPrisPlayer::SetPosition(QDBusObjectPath o, qlonglong t)
+{
+}
+void QMPrisPlayer::OpenUri(QString s)
+{
+}
+
+void QMPrisMediaPlayer2::Raise()
+{
+}
+void QMPrisMediaPlayer2::Quit()
+{
+}
+
+QMPrisMediaPlayer2::QMPrisMediaPlayer2(QObject *parent) : QDBusAbstractAdaptor(parent)
+{
+}
+
+bool QMPrisMediaPlayer2::getCanQuit()
+{
+ return false;
+}
+bool QMPrisMediaPlayer2::getCanRaise()
+{
+ return false;
+}
+bool QMPrisMediaPlayer2::getFullscreen()
+{
+ return false;
+}
+bool QMPrisMediaPlayer2::getCanSetFullscreen()
+{
+ return false;
+}
+bool QMPrisMediaPlayer2::getHasTrackList()
+{
+ return false;
+}
+
+QString QMPrisMediaPlayer2::getIdentity()
+{
+ return QString();
+}
+QString QMPrisMediaPlayer2::getDesktopEntry()
+{
+ return QString();
+}
+QStringList QMPrisMediaPlayer2::getSupportedUriSchemes()
+{
+ return {};
+}
+QStringList QMPrisMediaPlayer2::getSupportedMimeTypes()
+{
+ return {};
+}
+
+void QMPrisMediaPlayer2::setFullscreen(bool fullscreen)
+{
+}
+
+QList<QVariantMap> QMPrisTrackList::GetTracksMetaData(QList<QDBusObjectPath> trackIds)
+{
+ return {};
+}
+
+void QMPrisTrackList::AddTrack(QString uri, QDBusObjectPath after, bool setCurrent)
+{
+}
+
+void QMPrisTrackList::RemoveTrack(QDBusObjectPath trackId)
+{
+}
+
+void QMPrisTrackList::GoTo(QDBusObjectPath trackId)
+{
+}
+
+QMPrisTrackList::QMPrisTrackList(QObject *parent) : QDBusAbstractAdaptor(parent)
+{
+}
+
+QList<QDBusObjectPath> QMPrisTrackList::getTracks()
+{
+ return {};
+}
+
+bool QMPrisTrackList::getCanEditTracks()
+{
+ return false;
+}
diff --git a/mpris-plugin/qmprisdbusinterface.hpp b/mpris-plugin/qmprisdbusinterface.hpp
new file mode 100644
index 0000000..071c509
--- /dev/null
+++ b/mpris-plugin/qmprisdbusinterface.hpp
@@ -0,0 +1,148 @@
+/*
+ * DBus adaptor for the MPRIS Interface
+ * Based on MPRIS D-Bus Interface Specification Version 2.2:
+ * https://specifications.freedesktop.org/mpris-spec/2.2/index.html
+ */
+#ifndef QMPRISDBUSINTERFACE_HPP
+#define QMPRISDBUSINTERFACE_HPP
+
+#include <QDBusAbstractAdaptor>
+#include <QDBusObjectPath>
+#include <QVariant>
+
+class QMPrisWrapper;
+
+class QMPrisPlayer : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player")
+
+ Q_PROPERTY(QString PlaybackStatus READ getPlaybackStatus)
+ Q_PROPERTY(QString LoopStatus READ getLoopStatus WRITE setLoopStatus)
+ Q_PROPERTY(double Rate READ getRate WRITE setRate)
+ Q_PROPERTY(bool Shuffle READ getShuffle WRITE setShuffle)
+ Q_PROPERTY(QVariantMap Metadata READ getMetadata)
+ Q_PROPERTY(double Volume READ getVolume WRITE setVolume)
+ Q_PROPERTY(qlonglong Position READ getPosition)
+ Q_PROPERTY(double MinimumRate READ getMinimumRate)
+ Q_PROPERTY(double MaximumRate READ getMaximumRate)
+
+ Q_PROPERTY(bool CanGoNext READ getCanGoNext)
+ Q_PROPERTY(bool CanGoPrevious READ getCanGoPrevious)
+ Q_PROPERTY(bool CanPlay READ getCanPlay)
+ Q_PROPERTY(bool CanPause READ getCanPause)
+ Q_PROPERTY(bool CanSeek READ getCanSeek)
+ Q_PROPERTY(bool CanControl READ getCanControl)
+public:
+ enum PlaybackStatus
+ {
+ Playing,
+ Paused,
+ Stopped
+ };
+ Q_ENUM(PlaybackStatus)
+
+ enum LoopStatus
+ {
+ None,
+ Track,
+ Playlist
+ };
+ Q_ENUM(LoopStatus)
+
+ explicit QMPrisPlayer(QObject *parent=nullptr);
+
+ virtual QString getPlaybackStatus();
+ virtual QString getLoopStatus();
+ virtual double getRate();
+ virtual bool getShuffle();
+ virtual QVariantMap getMetadata();
+ virtual double getVolume();
+ virtual qlonglong getPosition();
+ virtual double getMinimumRate();
+ virtual double getMaximumRate();
+ virtual bool getCanGoNext();
+ virtual bool getCanGoPrevious();
+ virtual bool getCanPlay();
+ virtual bool getCanPause();
+ virtual bool getCanSeek();
+ virtual bool getCanControl();
+
+ virtual void setLoopStatus(QString loopStatus);
+ virtual void setRate(double playbackRate);
+ virtual bool setShuffle(bool shuffle);
+ virtual void setVolume(double volume);
+
+public slots:
+ virtual void Next();
+ virtual void Previous();
+ virtual void Pause();
+ virtual void PlayPause();
+ virtual void Stop();
+ virtual void Play();
+ virtual void Seek(qlonglong t);
+ virtual void SetPosition(QDBusObjectPath o, qlonglong t);
+ virtual void OpenUri(QString s);
+
+signals:
+ void Seeked(qlonglong t);
+};
+
+class QMPrisTrackList : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.TrackList")
+ Q_PROPERTY(QList<QDBusObjectPath> Tracks READ getTracks)
+ Q_PROPERTY(bool CanEditTracks READ getCanEditTracks)
+public slots:
+ virtual QList<QVariantMap> GetTracksMetaData(QList<QDBusObjectPath> trackIds);
+ virtual void AddTrack(QString uri, QDBusObjectPath after, bool setCurrent);
+ virtual void RemoveTrack(QDBusObjectPath trackId);
+ virtual void GoTo(QDBusObjectPath trackId);
+signals:
+ void TrackListReplaced(QList<QDBusObjectPath> tracks, QDBusObjectPath currentTrack);
+ void TrackAdded(QVariantMap metadata, QDBusObjectPath after);
+ void TrackRemoved(QDBusObjectPath track);
+ void TrackMetadataChanged(QDBusObjectPath track, QVariantMap metadata);
+public:
+ explicit QMPrisTrackList(QObject *parent=nullptr);
+ virtual QList<QDBusObjectPath> getTracks();
+ virtual bool getCanEditTracks();
+};
+
+class QMPrisMediaPlayer2 : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2")
+
+ Q_PROPERTY(bool CanQuit READ getCanQuit)
+ Q_PROPERTY(bool CanRaise READ getCanRaise)
+ Q_PROPERTY(bool Fullscreen READ getFullscreen WRITE setFullscreen)
+ Q_PROPERTY(bool CanSetFullscreen READ getCanSetFullscreen)
+ Q_PROPERTY(bool HasTrackList READ getHasTrackList)
+ Q_PROPERTY(QString Identity READ getIdentity)
+ Q_PROPERTY(QString DesktopEntry READ getDesktopEntry)
+ Q_PROPERTY(QStringList SupportedUriSchemes READ getSupportedUriSchemes)
+ Q_PROPERTY(QStringList SupportedMimeTypes READ getSupportedMimeTypes)
+
+public slots:
+ virtual void Raise();
+ virtual void Quit();
+
+public:
+ explicit QMPrisMediaPlayer2(QObject *parent=nullptr);
+
+ virtual bool getCanQuit();
+ virtual bool getCanRaise();
+ virtual bool getFullscreen();
+ virtual bool getCanSetFullscreen();
+ virtual bool getHasTrackList();
+ virtual QString getIdentity();
+ virtual QString getDesktopEntry();
+ virtual QStringList getSupportedUriSchemes();
+ virtual QStringList getSupportedMimeTypes();
+
+ virtual void setFullscreen(bool fullscreen);
+};
+
+#endif // QMPRISDBUSINTERFACE_HPP
diff --git a/mpris-plugin/qmpriswrapper.cpp b/mpris-plugin/qmpriswrapper.cpp
new file mode 100644
index 0000000..8a3f273
--- /dev/null
+++ b/mpris-plugin/qmpriswrapper.cpp
@@ -0,0 +1,77 @@
+#include "qmpriswrapper.hpp"
+#include "qmprisdbusinterface.hpp"
+#include <QDBusMetaType>
+#include <QDBusConnection>
+#include <QDBusMessage>
+
+#include "../include/qmpcorepublic.hpp"
+
+QMPrisWrapper::QMPrisWrapper(QString serviceSuffix, qmpPluginAPI *_api, QObject *parent) :
+ api(_api),
+ QObject(parent),
+ svcsuffix(serviceSuffix)
+{
+ qDBusRegisterMetaType<QStringList>();
+ qDBusRegisterMetaType<QVariantMap>();
+ qDBusRegisterMetaType<QList<QVariantMap>>();
+ qDBusRegisterMetaType<QList<QDBusObjectPath>>();
+}
+
+void QMPrisWrapper::post_creation()
+{
+ QDBusConnection sessbus = QDBusConnection::sessionBus();
+ sessbus.registerService("org.mpris.MediaPlayer2." + svcsuffix);
+ sessbus.registerObject("/org/mpris/MediaPlayer2", this);
+ api->registerUIHook("main.stop", [this](const void* a, void* _) {
+ tracklist->TrackListReplaced({}, QDBusObjectPath("/"));
+ this->notifyPropertyChange(PLAYER_INTERFACE, "Metadata", player->getMetadata());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "PlaybackStatus", player->getPlaybackStatus());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPause", player->getCanPause());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPlay", player->getCanPlay());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanSeek", player->getCanSeek());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoNext", player->getCanGoNext());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoPrevious", player->getCanGoPrevious());
+ }, nullptr);
+ api->registerUIHook("main.start", [this](const void* a, void* _) {
+ tracklist->TrackListReplaced(tracklist->getTracks(), QDBusObjectPath("/org/chrisoft/qmidiplayer/dummylist/0"));
+ this->notifyPropertyChange(PLAYER_INTERFACE, "Metadata", player->getMetadata());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "PlaybackStatus", player->getPlaybackStatus());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPause", player->getCanPause());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPlay", player->getCanPlay());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanSeek", player->getCanSeek());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoNext", player->getCanGoNext());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoPrevious", player->getCanGoPrevious());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "Rate", player->getRate());
+ }, nullptr);
+ api->registerUIHook("main.pause", [this](const void* a, void* _) {
+ this->notifyPropertyChange(PLAYER_INTERFACE, "PlaybackStatus", player->getPlaybackStatus());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPause", player->getCanPause());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanPlay", player->getCanPlay());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanSeek", player->getCanSeek());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoNext", player->getCanGoNext());
+ this->notifyPropertyChange(PLAYER_INTERFACE, "CanGoPrevious", player->getCanGoPrevious());
+ }, nullptr);
+ api->registerUIHook("main.seek", [this](const void* a, void *_) {
+ auto ps = static_cast<const ::PlaybackStatus*>(a);
+ player->Seeked(ps->curtime_ms * 1000);
+ }, nullptr);
+}
+
+QMPrisWrapper::~QMPrisWrapper()
+{
+ QDBusConnection sessbus = QDBusConnection::sessionBus();
+ sessbus.unregisterObject("/org/mpris/MediaPlayer2");
+ sessbus.unregisterService("org.mpris.MediaPlayer2." + svcsuffix);
+}
+
+void QMPrisWrapper::notifyPropertyChange(QString intf, QString prop, QVariant val)
+{
+ QDBusConnection sessbus = QDBusConnection::sessionBus();
+ auto signal = QDBusMessage::createSignal("/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "PropertiesChanged");
+ signal.setArguments({
+ intf,
+ QVariantMap{{prop, val}},
+ QStringList{}
+ });
+ sessbus.send(signal);
+}
diff --git a/mpris-plugin/qmpriswrapper.hpp b/mpris-plugin/qmpriswrapper.hpp
new file mode 100644
index 0000000..54186d2
--- /dev/null
+++ b/mpris-plugin/qmpriswrapper.hpp
@@ -0,0 +1,53 @@
+#ifndef QMPRISWRAPPER_HPP
+#define QMPRISWRAPPER_HPP
+
+#include <QObject>
+
+class QMPrisMediaPlayer2;
+class QMPrisPlayer;
+class QMPrisTrackList;
+class qmpPluginAPI;
+
+class QMPrisWrapper : public QObject
+{
+ Q_OBJECT
+public:
+ ~QMPrisWrapper();
+
+ template <class TP, class TM, class TT>
+ static QMPrisWrapper *create(QString serviceSuffix, qmpPluginAPI *api, QObject *parent = nullptr)
+ {
+ static_assert(std::is_base_of<QMPrisPlayer, TP>(), "TP must be a subclass of QMPrisPlayer");
+ static_assert(std::is_base_of<QMPrisMediaPlayer2, TM>(), "TM must be a subclass of QMPrisMediaPlayer2");
+ static_assert(std::is_base_of<QMPrisTrackList, TT>(), "TT must be a subclass of QMPrisTrackList");
+
+ auto w = new QMPrisWrapper(serviceSuffix, api, parent);
+ auto p = new TP(api, w);
+ auto t = new TT(api, w);
+ auto mp = new TM(api, w);
+ w->player = p;
+ w->tracklist = t;
+ w->mediaplayer = mp;
+ w->post_creation();
+
+ return w;
+ }
+
+ static void notifyPropertyChange(QString intf, QString prop, QVariant val);
+
+private:
+ explicit QMPrisWrapper(QString serviceSuffix, qmpPluginAPI *_api, QObject *parent = nullptr);
+ void post_creation();
+ QMPrisPlayer *player = nullptr;
+ QMPrisMediaPlayer2 *mediaplayer = nullptr;
+ QMPrisTrackList *tracklist = nullptr;
+ QString svcsuffix;
+ qmpPluginAPI *api;
+
+ const QString PLAYER_INTERFACE = "org.mpris.MediaPlayer2.Player";
+
+ friend class QMPrisPlayer;
+ friend class QMPrisMediaPlayer2;
+};
+
+#endif // QMPRISWRAPPER_HPP