summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--daemon/musicmanager.cpp217
-rw-r--r--daemon/musicmanager.h15
-rw-r--r--daemon/watchconnector.h3
3 files changed, 126 insertions, 109 deletions
diff --git a/daemon/musicmanager.cpp b/daemon/musicmanager.cpp
index 05e3727..d34ae5c 100644
--- a/daemon/musicmanager.cpp
+++ b/daemon/musicmanager.cpp
@@ -1,69 +1,143 @@
-#include <QtDBus>
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
#include "musicmanager.h"
MusicManager::MusicManager(WatchConnector *watch, QObject *parent)
- : QObject(parent), watch(watch)
+ : QObject(parent), watch(watch), _watcher(new QDBusServiceWatcher(this))
{
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusConnectionInterface *bus_iface = bus.interface();
- // Listen for MPRIS signals from every player
- bus.connect("", "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "PropertiesChanged",
- this, SLOT(handleMprisPropertiesChanged(QString,QMap<QString,QVariant>,QStringList)));
-
- // Listen for D-Bus name registered signals to see if a MPRIS service comes up
- connect(bus_iface, &QDBusConnectionInterface::serviceOwnerChanged,
- this, &MusicManager::handleServiceOwnerChanged);
+ // This watcher will be used to find when the current MPRIS service dies
+ // (and thus we must clear the metadata)
+ _watcher->setConnection(bus);
+ connect(_watcher, &QDBusServiceWatcher::serviceOwnerChanged,
+ this, &MusicManager::handleMprisServiceOwnerChanged);
- // But also try to find an already active MPRIS service
+ // Try to find an active MPRIS service to initially connect to
const QStringList &services = bus_iface->registeredServiceNames();
foreach (QString service, services) {
if (service.startsWith("org.mpris.MediaPlayer2.")) {
switchToService(service);
+ fetchMetadataFromService();
+ // The watch is not connected by this point,
+ // so we don't send the current metadata.
break;
}
}
- // Set up watch endpoint handler for music control
+ // Even if we didn't find any service, we still listen for metadataChanged signals
+ // from every MPRIS-compatible player
+ // If such a signal comes in, we will connect to the source service for that signal
+ bus.connect("", "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "PropertiesChanged",
+ this, SLOT(handleMprisPropertiesChanged(QString,QMap<QString,QVariant>,QStringList)));
+
+ // Now set up the Pebble endpoint handler for music control commands
watch->setEndpointHandler(WatchConnector::watchMUSIC_CONTROL, [this](const QByteArray& data) {
- musicControl(WatchConnector::MusicControl(data.at(0)));
+ handleMusicControl(WatchConnector::MusicControl(data.at(0)));
return true;
});
+
+ // If the watch disconnects, we will send the current metadata when it comes back.
connect(watch, &WatchConnector::connectedChanged,
this, &MusicManager::handleWatchConnected);
}
-void MusicManager::musicControl(WatchConnector::MusicControl operation)
+void MusicManager::switchToService(const QString &service)
+{
+ if (_curService != service) {
+ logger()->debug() << "switching to mpris service" << service;
+ _curService = service;
+
+ if (_curService.isEmpty()) {
+ _watcher->setWatchedServices(QStringList());
+ } else {
+ _watcher->setWatchedServices(QStringList(_curService));
+ }
+ }
+}
+
+void MusicManager::fetchMetadataFromService()
+{
+ _curMetadata.clear();
+
+ if (!_curService.isEmpty()) {
+ QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
+ call << "org.mpris.MediaPlayer2.Player" << "Metadata";
+ QDBusReply<QDBusVariant> reply = QDBusConnection::sessionBus().call(call);
+ if (reply.isValid()) {
+ logger()->debug() << "got mpris metadata from service" << _curService;
+ _curMetadata = qdbus_cast<QVariantMap>(reply.value().variant().value<QDBusArgument>());
+ } else {
+ logger()->error() << reply.error().message();
+ }
+ }
+}
+
+void MusicManager::sendCurrentMprisMetadata()
+{
+ Q_ASSERT(watch->isConnected());
+
+ QString track = _curMetadata.value("xesam:title").toString().left(30);
+ QString album = _curMetadata.value("xesam:album").toString().left(30);
+ QString artist = _curMetadata.value("xesam:artist").toString().left(30);
+
+ logger()->debug() << "sending mpris metadata:" << track << album << artist;
+
+ watch->sendMusicNowPlaying(track, album, artist);
+}
+
+void MusicManager::callMprisMethod(const QString &method)
+{
+ Q_ASSERT(!method.isEmpty());
+ Q_ASSERT(!_curService.isEmpty());
+
+ logger()->debug() << _curService << "->" << method;
+
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ QDBusMessage call = QDBusMessage::createMethodCall(_curService,
+ "/org/mpris/MediaPlayer2",
+ "org.mpris.MediaPlayer2.Player",
+ method);
+
+ QDBusError err = bus.call(call);
+
+ if (err.isValid()) {
+ logger()->error() << "while calling mpris method on" << _curService << ":" << err.message();
+ }
+}
+
+void MusicManager::handleMusicControl(WatchConnector::MusicControl operation)
{
logger()->debug() << "operation from watch:" << operation;
if (_curService.isEmpty()) {
- logger()->info() << "No mpris interface active";
+ logger()->info() << "can't do any music operation, no mpris interface active";
return;
}
- QString method;
-
- switch(operation) {
+ switch (operation) {
case WatchConnector::musicPLAY_PAUSE:
- method = "PlayPause";
+ callMprisMethod("PlayPause");
break;
case WatchConnector::musicPAUSE:
- method = "Pause";
+ callMprisMethod("Pause");
break;
case WatchConnector::musicPLAY:
- method = "Play";
+ callMprisMethod("Play");
break;
case WatchConnector::musicNEXT:
- method = "Next";
+ callMprisMethod("Next");
break;
case WatchConnector::musicPREVIOUS:
- method = "Previous";
+ callMprisMethod("Previous");
break;
+
case WatchConnector::musicVOLUME_UP:
case WatchConnector::musicVOLUME_DOWN: {
QDBusConnection bus = QDBusConnection::sessionBus();
- QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
+ QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2",
+ "org.freedesktop.DBus.Properties", "Get");
call << "org.mpris.MediaPlayer2.Player" << "Volume";
QDBusReply<QDBusVariant> volumeReply = bus.call(call);
if (volumeReply.isValid()) {
@@ -87,79 +161,28 @@ void MusicManager::musicControl(WatchConnector::MusicControl operation)
logger()->error() << volumeReply.error().message();
}
}
- return;
+ break;
+
case WatchConnector::musicGET_NOW_PLAYING:
- setMprisMetadata(_curMetadata);
- return;
+ sendCurrentMprisMetadata();
+ break;
- case WatchConnector::musicSEND_NOW_PLAYING:
default:
logger()->warn() << "Operation" << operation << "not supported";
- return;
- }
-
- if (method.isEmpty()) {
- logger()->error() << "Requested unsupported operation" << operation;
- return;
- }
-
- logger()->debug() << operation << "->" << method;
-
- QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", method);
- QDBusError err = QDBusConnection::sessionBus().call(call);
- if (err.isValid()) {
- logger()->error() << err.message();
- }
-}
-
-void MusicManager::switchToService(const QString &service)
-{
- if (_curService != service) {
- logger()->debug() << "switching to mpris service" << service;
- _curService = service;
- }
-}
-
-void MusicManager::setMprisMetadata(const QVariantMap &metadata)
-{
- _curMetadata = metadata;
- QString track = metadata.value("xesam:title").toString();
- QString album = metadata.value("xesam:album").toString();
- QString artist = metadata.value("xesam:artist").toString();
-
- logger()->debug() << "new mpris metadata:" << track << album << artist;
-
- if (watch->isConnected()) {
- watch->sendMusicNowPlaying(track, album, artist);
- }
-}
-
-void MusicManager::handleServiceRegistered(const QString &service)
-{
- if (service.startsWith("org.mpris.MediaPlayer2.")) {
- if (_curService.isEmpty()) {
- switchToService(service);
- }
- }
-}
-
-void MusicManager::handleServiceUnregistered(const QString &service)
-{
- if (service == _curService) {
- // Oops! Losing the current MPRIS service
- // We must assume it's been closed and thus remove current metadata
- setMprisMetadata(QVariantMap());
- switchToService(QString());
+ break;
}
}
-void MusicManager::handleServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
+void MusicManager::handleMprisServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
Q_UNUSED(oldOwner);
- if (newOwner.isEmpty()) {
- handleServiceUnregistered(name);
- } else {
- handleServiceRegistered(name);
+ if (name == _curService && newOwner.isEmpty()) {
+ // Oops, current service is going away
+ switchToService(QString());
+ _curMetadata.clear();
+ if (watch->isConnected()) {
+ sendCurrentMprisMetadata();
+ }
}
}
@@ -172,32 +195,26 @@ void MusicManager::handleMprisPropertiesChanged(const QString &interface, const
if (changed.contains("Metadata")) {
QVariantMap metadata = qdbus_cast<QVariantMap>(changed.value("Metadata").value<QDBusArgument>());
logger()->debug() << "received new metadata" << metadata;
- setMprisMetadata(metadata);
+ _curMetadata = metadata;
}
if (changed.contains("PlaybackStatus")) {
QString status = changed.value("PlaybackStatus").toString();
if (status == "Stopped") {
- setMprisMetadata(QVariantMap());
+ _curMetadata.clear();
}
}
+ if (watch->isConnected()) {
+ sendCurrentMprisMetadata();
+ }
+
switchToService(message().service());
}
void MusicManager::handleWatchConnected()
{
if (watch->isConnected()) {
- if (!_curService.isEmpty()) {
- QDBusMessage call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get");
- call << "org.mpris.MediaPlayer2.Player" << "Metadata";
- QDBusReply<QDBusVariant> metadata = QDBusConnection::sessionBus().call(call);
- if (metadata.isValid()) {
- setMprisMetadata(qdbus_cast<QVariantMap>(metadata.value().variant().value<QDBusArgument>()));
- } else {
- logger()->error() << metadata.error().message();
- setMprisMetadata(QVariantMap());
- }
- }
+ sendCurrentMprisMetadata();
}
}
diff --git a/daemon/musicmanager.h b/daemon/musicmanager.h
index 88c46c3..89e5fd7 100644
--- a/daemon/musicmanager.h
+++ b/daemon/musicmanager.h
@@ -3,6 +3,7 @@
#include <QObject>
#include <QDBusContext>
+#include <QDBusServiceWatcher>
#include "watchconnector.h"
class MusicManager : public QObject, protected QDBusContext
@@ -14,22 +15,22 @@ public:
explicit MusicManager(WatchConnector *watch, QObject *parent = 0);
private:
- void musicControl(WatchConnector::MusicControl operation);
void switchToService(const QString &service);
- void setMprisMetadata(const QVariantMap &data);
+ void fetchMetadataFromService();
+ void sendCurrentMprisMetadata();
+ void callMprisMethod(const QString &method);
private slots:
- void handleServiceRegistered(const QString &service);
- void handleServiceUnregistered(const QString &service);
- void handleServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
+ void handleMusicControl(WatchConnector::MusicControl operation);
+ void handleMprisServiceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner);
void handleMprisPropertiesChanged(const QString &interface, const QMap<QString,QVariant> &changed, const QStringList &invalidated);
void handleWatchConnected();
private:
WatchConnector *watch;
-
- QVariantMap _curMetadata;
+ QDBusServiceWatcher *_watcher;
QString _curService;
+ QVariantMap _curMetadata;
};
#endif // MUSICMANAGER_H
diff --git a/daemon/watchconnector.h b/daemon/watchconnector.h
index 4194e9a..6546302 100644
--- a/daemon/watchconnector.h
+++ b/daemon/watchconnector.h
@@ -94,8 +94,7 @@ public:
musicPREVIOUS = 5,
musicVOLUME_UP = 6,
musicVOLUME_DOWN = 7,
- musicGET_NOW_PLAYING = 8,
- musicSEND_NOW_PLAYING = 9
+ musicGET_NOW_PLAYING = 8
};
enum SystemMessage {
systemFIRMWARE_AVAILABLE = 0,