Commit c7b34cde authored by Matthieu Gallien's avatar Matthieu Gallien 🎵
Browse files

add very basic Mpris2 support thanks to Plasma Media Center code

parent 2620b569
......@@ -21,6 +21,7 @@ find_package(KF5I18n CONFIG QUIET)
find_package(KF5CoreAddons CONFIG QUIET)
find_package(KF5Baloo CONFIG QUIET)
find_package(KF5FileMetaData CONFIG QUIET)
find_package(KF5Service CONFIG QUIET)
find_package(KDSoap CONFIG QUIET)
find_package(UPNPQT CONFIG QUIET)
......@@ -45,5 +46,5 @@ add_subdirectory(src)
#add_subdirectory(tests)
#add_subdirectory(autotests)
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
......@@ -7,3 +7,5 @@
#cmakedefine01 KF5Baloo_FOUND
#cmakedefine01 UPNPQT_FOUND
#cmakedefine01 Qt5DBus_FOUND
......@@ -55,6 +55,16 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
endif()
endif()
if (Qt5DBus_FOUND)
set(elisa_SOURCES
${elisa_SOURCES}
mpris2/mpris2.cpp
mpris2/mediaplayer2.cpp
mpris2/mediaplayer2player.cpp
mpris2/mediaplayer2tracklist.cpp
)
endif()
if (UPNPQT_FOUND)
set(elisa_SOURCES
${elisa_SOURCES}
......@@ -133,6 +143,13 @@ if (Qt5Quick_FOUND AND Qt5Widgets_FOUND)
)
endif()
if (KF5Service_FOUND)
target_link_libraries(elisa
LINK_PRIVATE
KF5::Service
)
endif()
if (UPNPQT_FOUND)
target_link_libraries(elisa
LINK_PRIVATE
......
......@@ -82,6 +82,12 @@ ApplicationWindow {
onTriggered: Qt.quit()
}
Mpris2 {
id: mpris2Interface
playerName: 'elisa'
}
UpnpSsdpEngine {
id: mySsdpEngine
......
/***************************************************************************
* Copyright 2014 Sujith Haridasan <sujith.haridasan@kdemail.net> *
* Copyright 2014 Ashish Madeti <ashishmadeti@gmail.com> *
* *
* 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 2 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "mediaplayer2.h"
#include <QCoreApplication>
#include <KService>
MediaPlayer2::MediaPlayer2(QObject* parent)
: QDBusAbstractAdaptor(parent)
{
}
MediaPlayer2::~MediaPlayer2()
{
}
bool MediaPlayer2::CanQuit() const
{
return true;
}
bool MediaPlayer2::CanRaise() const
{
return true;
}
bool MediaPlayer2::HasTrackList() const
{
return false;
}
void MediaPlayer2::Quit() const
{
QCoreApplication::quit();
}
void MediaPlayer2::Raise() const
{
emit raisePMC();
}
QString MediaPlayer2::Identity() const
{
return QString(); //KCmdLineArgs::aboutData()->programName();
}
QString MediaPlayer2::DesktopEntry() const
{
// KService::Ptr app = KService::serviceByDesktopName(KCmdLineArgs::aboutData()->appName());
// if (app) {
// return app->desktopEntryName();
// }
return QString();
}
QStringList MediaPlayer2::SupportedUriSchemes() const
{
return QStringList() << QStringLiteral("file");
}
QStringList MediaPlayer2::SupportedMimeTypes() const
{
// KService::Ptr app = KService::serviceByDesktopName(KCmdLineArgs::aboutData()->appName());
// if (app) {
// return app->mimeTypes();
// }
return QStringList();
}
/***************************************************************************
* Copyright 2014 Sujith Haridasan <sujith.haridasan@kdemail.net> *
* Copyright 2014 Ashish Madeti <ashishmadeti@gmail.com> *
* *
* 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 2 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#ifndef MEDIACENTER_MEDIAPLAYER2_H
#define MEDIACENTER_MEDIAPLAYER2_H
#include <QDBusAbstractAdaptor>
#include <QStringList>
class MediaPlayer2 : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2") // Docs: http://specifications.freedesktop.org/mpris-spec/latest/Media_Player.html
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(QString DesktopEntry READ DesktopEntry)
Q_PROPERTY(QStringList SupportedUriSchemes READ SupportedUriSchemes)
Q_PROPERTY(QStringList SupportedMimeTypes READ SupportedMimeTypes)
public:
explicit MediaPlayer2(QObject* parent = 0);
~MediaPlayer2();
bool CanQuit() const;
bool CanRaise() const;
bool HasTrackList() const;
QString Identity() const;
QString DesktopEntry() const;
QStringList SupportedUriSchemes() const;
QStringList SupportedMimeTypes() const;
public Q_SLOTS:
void Quit() const;
void Raise() const;
Q_SIGNALS:
void raisePMC() const;
};
#endif //MEDIACENTER_MEDIAPLAYER2_H
/***************************************************************************
* Copyright 2014 Sujith Haridasan <sujith.haridasan@kdemail.net> *
* Copyright 2014 Ashish Madeti <ashishmadeti@gmail.com> *
* *
* 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 2 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "mediaplayer2player.h"
#include "mpris2.h"
#include <QCryptographicHash>
#include <QStringList>
#include <QMetaClassInfo>
#include <QDBusMessage>
#include <QDBusConnection>
static const double MAX_RATE = 32.0;
static const double MIN_RATE = 0.0;
MediaPlayer2Player::MediaPlayer2Player(QObject* parent)
: QDBusAbstractAdaptor(parent),
m_rate(0)/*,
m_status(RuntimeData::PmcStatus::Stopped)*/
{
}
MediaPlayer2Player::~MediaPlayer2Player()
{
}
QString MediaPlayer2Player::PlaybackStatus() const
{
/*if (m_status == RuntimeData::PmcStatus::Stopped) {
return QLatin1String("Stopped");
} else if (m_status == RuntimeData::PmcStatus::Paused) {
return QLatin1String("Paused");
} else*/
return QLatin1String("Playing");
}
bool MediaPlayer2Player::CanGoNext() const
{
return mediaPlayerPresent();
}
void MediaPlayer2Player::Next() const
{
emit next();
}
bool MediaPlayer2Player::CanGoPrevious() const
{
return mediaPlayerPresent();
}
void MediaPlayer2Player::Previous() const
{
emit previous();
}
bool MediaPlayer2Player::CanPause() const
{
return mediaPlayerPresent();
}
void MediaPlayer2Player::Pause() const
{
/*if (m_status == RuntimeData::PmcStatus::Playing) {
emit playPause();
}*/
}
void MediaPlayer2Player::PlayPause()
{
emit playPause();
}
void MediaPlayer2Player::Stop() const
{
emit stop();
}
bool MediaPlayer2Player::CanPlay() const
{
return mediaPlayerPresent();
}
void MediaPlayer2Player::Play() const
{
/*if (m_status != RuntimeData::PmcStatus::Playing) {
emit playPause();
}*/
}
double MediaPlayer2Player::Volume() const
{
return m_volume;
}
void MediaPlayer2Player::setVolume(double volume)
{
m_volume= qBound(0.0, volume, 1.0);
emit volumeChanged(m_volume);
signalPropertiesChange(QStringLiteral("Volume"), Volume());
}
QVariantMap MediaPlayer2Player::Metadata() const
{
return m_metadata;
}
qlonglong MediaPlayer2Player::Position() const
{
return m_position;
}
void MediaPlayer2Player::setPropertyPosition(int newPositionInMs)
{
m_position = qlonglong(newPositionInMs)*1000;
//PMC stores postion in milli-seconds, Mpris likes it in micro-seconds
}
double MediaPlayer2Player::Rate() const
{
return m_rate;
}
void MediaPlayer2Player::setRate(double newRate)
{
if (newRate == 0) {
Pause();
} else {
m_rate = qBound(MinimumRate(), newRate, MaximumRate());
emit rateChanged(m_rate);
signalPropertiesChange(QStringLiteral("Rate"), Rate());
}
}
double MediaPlayer2Player::MinimumRate() const
{
return MIN_RATE;
}
double MediaPlayer2Player::MaximumRate() const
{
return MAX_RATE;
}
bool MediaPlayer2Player::CanSeek() const
{
return mediaPlayerPresent();
}
bool MediaPlayer2Player::CanControl() const
{
return true;
}
void MediaPlayer2Player::Seek(qlonglong Offset) const
{
if (mediaPlayerPresent()) {
//The seekTo function (to which this signal is linked to) accepts offset in milliseconds
int offset = Offset/1000;
emit seek(offset);
}
}
void MediaPlayer2Player::emitSeeked(int pos)
{
emit Seeked(qlonglong(pos)*1000);
}
void MediaPlayer2Player::SetPosition(const QDBusObjectPath& trackId, qlonglong pos)
{
if (trackId.path() == static_cast<Mpris2*>(parent())->getCurrentTrackId()) {
emit seek((pos - Position())/1000);
}
}
void MediaPlayer2Player::OpenUri(QString uri) const
{
QUrl url(uri);
if (url.isLocalFile()) {
emit playUrl(url);
}
}
QString MediaPlayer2Player::currentTrack() const
{
return m_currentTrack;
}
void MediaPlayer2Player::setCurrentTrack(QString newTrack)
{
m_currentTrack = newTrack;
m_metadata = static_cast<Mpris2*>(parent())->getMetadataOf(m_currentTrack);
signalPropertiesChange(QStringLiteral("Metadata"), Metadata());
}
/*void MediaPlayer2Player::setPmcStatus(RuntimeData::PmcStatus status)
{
m_status = status;
signalPropertiesChange("PlaybackStatus", PlaybackStatus());
}*/
int MediaPlayer2Player::mediaPlayerPresent() const
{
return m_mediaPlayerPresent;
}
/*RuntimeData::PmcStatus MediaPlayer2Player::pmcStatus() const
{
return m_status;
}*/
void MediaPlayer2Player::setMediaPlayerPresent(int status)
{
if (m_mediaPlayerPresent != status) {
m_mediaPlayerPresent = status;
signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext());
signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious());
signalPropertiesChange(QStringLiteral("CanPause"), CanPause());
signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay());
signalPropertiesChange(QStringLiteral("CanSeek"), CanSeek());
}
}
void MediaPlayer2Player::signalPropertiesChange(const QString &property, const QVariant &value)
{
QVariantMap properties;
properties[property] = value;
const int ifaceIndex = metaObject()->indexOfClassInfo("D-Bus Interface");
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"),
QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"));
msg << QLatin1String(metaObject()->classInfo(ifaceIndex).value());
msg << properties;
msg << QStringList();
QDBusConnection::sessionBus().send(msg);
}
/***************************************************************************
* Copyright 2014 Sujith Haridasan <sujith.haridasan@kdemail.net> *
* Copyright 2014 Ashish Madeti <ashishmadeti@gmail.com> *
* *
* 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 2 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#ifndef MEDIAPLAYER2PLAYER_H
#define MEDIAPLAYER2PLAYER_H
#include <QDBusAbstractAdaptor>
#include <QDBusObjectPath>
#include <QPointer>
#include <QUrl>
class MediaPlayer2Player : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player") // Docs: http://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html
Q_PROPERTY(QString PlaybackStatus READ PlaybackStatus)
Q_PROPERTY(double Rate READ Rate WRITE setRate NOTIFY rateChanged)
Q_PROPERTY(QVariantMap Metadata READ Metadata)
Q_PROPERTY(double Volume READ Volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(qlonglong Position READ Position WRITE setPropertyPosition)
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 CanControl READ CanControl)
Q_PROPERTY(bool CanSeek READ CanSeek)
Q_PROPERTY(QString currentTrack READ currentTrack WRITE setCurrentTrack)
Q_PROPERTY(int mediaPlayerPresent READ mediaPlayerPresent WRITE setMediaPlayerPresent)
public:
explicit MediaPlayer2Player(QObject* parent = 0);
~MediaPlayer2Player();
QString PlaybackStatus() const;
double Rate() const;
QVariantMap Metadata() const;
double Volume() const;
qlonglong Position() const;
double MinimumRate() const;
double MaximumRate() const;
bool CanGoNext() const;
bool CanGoPrevious() const;
bool CanPlay() const;
bool CanPause() const;
bool CanSeek() const;
bool CanControl() const;
QString currentTrack() const;
int mediaPlayerPresent() const;
Q_SIGNALS:
void Seeked(qlonglong Position) const;
void rateChanged(double newRate) const;
void volumeChanged(double newVol) const;
void next() const;
void previous() const;
void playPause() const;
void stop() const;
void seek(int offset) const;
void playUrl(QUrl url) const;
public Q_SLOTS:
void emitSeeked(int pos);
void Next() const;
void Previous() const;
void Pause() const;
void PlayPause();
void Stop() const;
void Play() const;
void Seek(qlonglong Offset) const;
void SetPosition(const QDBusObjectPath& trackId, qlonglong pos);
void OpenUri(QString uri) const;
private:
void signalPropertiesChange(const QString &property, const QVariant &value);
void setMediaPlayerPresent(int status);
void setRate(double newRate);
void setVolume(double volume);
void setPropertyPosition(int newPositionInMs);
void setCurrentTrack(QString newTrack);
QVariantMap m_metadata;
QString m_currentTrack;
double m_rate;
double m_volume;
bool m_paused;
bool m_stopped;
int m_mediaPlayerPresent;
qlonglong m_position;
};
#endif // MEDIAPLAYER2PLAYER_H
/***************************************************************************
* Copyright 2014 Ashish Madeti <ashishmadeti@gmail.com> *
* *
* 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 2 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, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
#include "mediaplayer2tracklist.h"
#include "mpris2.h"
static const QString playlistTidPrefix(QStringLiteral("/org/kde/plasmamediacenter/playlist/"));
static const QDBusObjectPath mprisNoTrack(QStringLiteral("/org/mpris/MediaPlayer2/TrackList/NoTrack"));
MediaPlayer2Tracklist::MediaPlayer2Tracklist(QObject *parent)