diff --git a/CMakeLists.txt b/CMakeLists.txt index 696f9fe9378e9df5e0836833958bc91adf51a912..650934e4a4516cdf8daa74752ab48ea35d333a63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(FeatureSummary) -find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core Multimedia Network) +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core Multimedia Network DBus) find_package(KF5 ${KF_MIN_VERSION} REQUIRED COMPONENTS CoreAddons diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 467a26659e0fa11796ff87b4de735e68ce036480..3524fabf113c6c400565f5c1cd799381ef51748f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ set( simplecastengine_SRCS minimediaplayer.cpp simplecastservice.cpp simplecasttcpservice.cpp + mprisinterface.cpp ) add_library(plasma_engine_simplecast ${simplecastengine_SRCS}) @@ -14,6 +15,7 @@ target_link_libraries( plasma_engine_simplecast Qt5::Core Qt5::Multimedia Qt5::Network + Qt5::DBus KF5::Plasma KF5::Service KF5::I18n diff --git a/src/minimediaplayer.cpp b/src/minimediaplayer.cpp index a847ea091f3e9b62139a67db9e9c7d19e3fc238c..1a2d17d67d51aa804851c43916e42b063f13a534 100644 --- a/src/minimediaplayer.cpp +++ b/src/minimediaplayer.cpp @@ -58,6 +58,26 @@ bool MiniMediaPlayer::nextTrack() return false; } +qint64 MiniMediaPlayer::getCurrentPosition() +{ + return m_player->position(); +} + +qint64 MiniMediaPlayer::getTrackDuration() +{ + return m_player->duration(); +} + +int MiniMediaPlayer::getVolume() +{ + return m_player->volume(); +} + +void MiniMediaPlayer::setVolume(int volume) +{ + m_player->setVolume(volume); +} + bool MiniMediaPlayer::playPauseTrack(bool playing) { if(m_player->state() == QMediaPlayer::State::PlayingState && !playing) diff --git a/src/minimediaplayer.h b/src/minimediaplayer.h index 5ca360979ab3014998ca787d984fea65f42ad7a4..51a73ee1f25efe2dbdd9639182030835d9f13ad9 100644 --- a/src/minimediaplayer.h +++ b/src/minimediaplayer.h @@ -43,6 +43,14 @@ public: bool playPauseTrack(bool playing); + qint64 getCurrentPosition(); + + qint64 getTrackDuration(); + + int getVolume(); + + void setVolume(int volume); + signals: void playStateChanged(bool isPlaying); void playlistChanged(QStringList trackTitles); diff --git a/src/mprisinterface.cpp b/src/mprisinterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df9edc3f8caceb3a6975f193170a7bab9687b3b5 --- /dev/null +++ b/src/mprisinterface.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2019 Kevin Whitaker + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "mprisinterface.h" +#include + +MPRISInterface::MPRISInterface(QObject* parent) : QDBusAbstractAdaptor(parent) +{ +} + +bool MPRISInterface::CanQuit() +{ + return false; +} + +bool MPRISInterface::CanRaise() +{ + return false; +} + +bool MPRISInterface::HasTrackList() +{ + return false; //TODO:this might have value implementing. +} + +QString MPRISInterface::Identity() +{ + return "Simple Cast"; +} + +QStringList MPRISInterface::SupportedMimeTypes() +{ + return {"audio/ogg","audio/mpeg","audio/webm"}; +} + +QStringList MPRISInterface::SupportedUriSchemes() +{ + return {"https","http"}; +} + + + +MPRISPlayerInterface::MPRISPlayerInterface(MiniMediaPlayer *player,QObject* parent) : QDBusAbstractAdaptor(parent),player(player) +{ +} + +bool MPRISPlayerInterface::CanControl() +{ + return true; +} + +bool MPRISPlayerInterface::CanGoNext() +{ + return true; +} + +bool MPRISPlayerInterface::CanGoPrevious() +{ + return false; +} + +bool MPRISPlayerInterface::CanSeek() +{ + return false; +} + +bool MPRISPlayerInterface::CanPause() +{ + return true; +} + +bool MPRISPlayerInterface::CanPlay() +{ + return true; +} + +double MPRISPlayerInterface::MaximumRate() +{ + return 1.0; +} + +double MPRISPlayerInterface::MinimumRate() +{ + return 1.0; +} + +void MPRISPlayerInterface::OpenUri(QString uri) +{ + //TODO:this might be another way to add tracks +} + +void MPRISPlayerInterface::Next() +{ + player->nextTrack(); +} + +void MPRISPlayerInterface::Pause() +{ + player->playPauseTrack(false); +} + +void MPRISPlayerInterface::Play() +{ + player->playPauseTrack(true); +} + +void MPRISPlayerInterface::PlayPause() +{ + player->playPauseTrack(!player->isPlaying()); +} + +void MPRISPlayerInterface::Stop() +{ + //TODO: think if worth implementing. +} + +QString MPRISPlayerInterface::PlaybackStatus() +{ + if(player->getTrackNames().size() == 0) + { + return "Stopped"; + } + else if(player->isPlaying()) { + return "Playing"; + } + else + { + return "Paused"; + } +} + +qlonglong MPRISPlayerInterface::Position() +{ + return player->getCurrentPosition() * 1000; //milliseconds to microseconds +} + +double MPRISPlayerInterface::Rate() +{ + return 1.0; +} + +double MPRISPlayerInterface::Volume() +{ + return player->getVolume(); +} + +void MPRISPlayerInterface::setVolume(double volume) +{ + if(volume < 0) player->setVolume(0); + player->setVolume(volume*100); //QMediaPlayer uses 0 to 100 +} + +QMap MPRISPlayerInterface::Metadata() +{ + QMap map; + map.insert("mpris:trackid",QDBusVariant("org.mpris.MediaPlayer2.simplecast.Player."+QString(QCryptographicHash::hash(player->getTrackNames()[0].toUtf8(),QCryptographicHash::Algorithm::Md5)))); + map.insert("mpris:length",QDBusVariant(player->getTrackDuration()*1000)); + map.insert("xesam:title",QDBusVariant(player->getTrackNames()[0])); + return map; +} + + + + + + + + + diff --git a/src/mprisinterface.h b/src/mprisinterface.h new file mode 100644 index 0000000000000000000000000000000000000000..fae223ff3e4e68c013b671416aba8fd7c3d135cb --- /dev/null +++ b/src/mprisinterface.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019 Kevin Whitaker + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MPRISINTERFACE_H +#define MPRISINTERFACE_H + +#include "minimediaplayer.h" +#include +#include +#include +#include + +/** + * Simple DBus interface which registers and provides simple controls over media playing. + */ +class MPRISInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface","org.mpris.MediaPlayer2") + Q_PROPERTY(bool CanQuit READ CanQuit) + Q_PROPERTY(bool CanRaise READ CanRaise) + Q_PROPERTY(bool HasTrackList READ HasTrackList) + Q_PROPERTY(QString Identity READ Identity) + Q_PROPERTY(QStringList SupportedUriSchemes READ SupportedUriSchemes) + Q_PROPERTY(QStringList SupportedMimeTypes READ SupportedMimeTypes) +public: + MPRISInterface(QObject *parent = 0); + bool CanQuit(); + bool CanRaise(); + bool HasTrackList(); + QString Identity(); + QStringList SupportedUriSchemes(); + QStringList SupportedMimeTypes(); +public slots: + Q_NOREPLY void Raise() {}; + Q_NOREPLY void Quit() {}; +}; + +class MPRISPlayerInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface","org.mpris.MediaPlayer2.Player") + Q_PROPERTY(QString PlaybackStatus READ PlaybackStatus) + Q_PROPERTY(double Rate READ Rate WRITE setRate) + Q_PROPERTY(QMapMetadata READ Metadata) + Q_PROPERTY(double Volume READ Volume WRITE setVolume) + Q_PROPERTY(qlonglong Position READ Position) + Q_PROPERTY(double MinimumRate READ MinimumRate) + Q_PROPERTY(double MaximumRate READ MaximumRate) + Q_PROPERTY(bool CanGoNext READ CanGoNext) + Q_PROPERTY(bool CanGoPrevious READ CanGoPrevious) + Q_PROPERTY(bool CanPlay READ CanPlay) + Q_PROPERTY(bool CanPause READ CanPause) + Q_PROPERTY(bool CanSeek READ CanSeek) + Q_PROPERTY(bool CanControl READ CanControl) +public: + MPRISPlayerInterface(MiniMediaPlayer *player,QObject *parent = 0); + QString PlaybackStatus(); + double Rate(); + void setRate(double rate) {}; + QMap Metadata(); + double Volume(); + void setVolume(double volume); + qlonglong Position(); + double MinimumRate(); + double MaximumRate(); + bool CanGoNext(); + bool CanGoPrevious(); + bool CanPlay(); + bool CanPause(); + bool CanSeek(); + bool CanControl(); +public slots: + Q_NOREPLY void Next(); + Q_NOREPLY void Previous() {}; + Q_NOREPLY void Pause(); + Q_NOREPLY void PlayPause(); + Q_NOREPLY void Stop(); + Q_NOREPLY void Play(); + Q_NOREPLY void Seek(qlonglong offset) {}; + Q_NOREPLY void SetPosition(QDBusObjectPath trackId,qlonglong position) {}; + Q_NOREPLY void OpenUri(QString uri); +signals: + void Seeked(qlonglong position); +private: + MiniMediaPlayer *player; +}; + +#endif // MPRISINTERFACE_H diff --git a/src/simplecastengine.cpp b/src/simplecastengine.cpp index 6d5b5cf95415e302a153db7adb616a8af33675cc..f476a8a5d727b5ae446dfe838d20158c4687c8b6 100644 --- a/src/simplecastengine.cpp +++ b/src/simplecastengine.cpp @@ -25,8 +25,16 @@ SimpleCastEngine::SimpleCastEngine(QObject *parent, const QVariantList &args) : Plasma::DataEngine(parent,args), player(new MiniMediaPlayer(this)) { Q_UNUSED(args) + + rootInt = new MPRISInterface(this); + playerInt = new MPRISPlayerInterface(player,this); + QDBusConnection::sessionBus().registerObject("/org/mpris/MediaPlayer2","org.mpris.MediaPlayer2",rootInt); + QDBusConnection::sessionBus().registerObject("/org/mpris/MediaPlayer2","org.mpris.MediaPlayer2.Player",playerInt); + QDBusConnection::sessionBus().registerService("org.mpris.MediaPlayer2.Player.simplecast"); + tcpService = new SimpleCastTcpService(player,this); setMinimumPollingInterval(333); + connect(player,SIGNAL(playStateChanged(bool)),this,SLOT(playStateChanged(bool))); connect(player,SIGNAL(trackDurationChanged(qint64)),this,SLOT(durationChanged(qint64))); connect(player,SIGNAL(trackPositionChanged(qint64)),this,SLOT(positionChanged(qint64))); diff --git a/src/simplecastengine.h b/src/simplecastengine.h index e0fdaab1a3b319ba3342676366cb954228d58773..b0c98c3b3a9b388472a17b46189da732e3a62333 100644 --- a/src/simplecastengine.h +++ b/src/simplecastengine.h @@ -26,6 +26,7 @@ #include #include "minimediaplayer.h" #include "simplecasttcpservice.h" +#include "mprisinterface.h" /** * Simple Cast Engine is a Plasma DataEngine that conveys that status on the media player casting to to other code like Plasmoids. @@ -47,6 +48,8 @@ protected: bool sourceRequestEvent(const QString &source) override; bool updateSourceEvent(const QString &source) override; SimpleCastTcpService *tcpService; + MPRISInterface *rootInt; + MPRISPlayerInterface *playerInt; MiniMediaPlayer *player; };