diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-03 16:38:02 +0100 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2015-01-03 19:07:48 +0100 |
| commit | 4e7da1944f5fa75a0739c0757d40a8102f045365 (patch) | |
| tree | 5f3fe179256536e4135eb4d5031a1d754af5e26c /daemon/musicmanager.cpp | |
| parent | 4150005566bec7827ce1cdd759a2397d47eba583 (diff) | |
| parent | e6ec758b364fcaf9fda35e56740c3fcd7e8fe25e (diff) | |
Merge remote-tracking branch 'javispedro/js-testing'
Conflicts:
daemon/daemon.pro
daemon/dbusconnector.cpp
daemon/manager.cpp
daemon/watchcommands.cpp
daemon/watchcommands.h
daemon/watchconnector.cpp
daemon/watchconnector.h
log4qt-debug.conf
log4qt-release.conf
rpm/pebble.spec
rpm/pebble.yaml
Diffstat (limited to 'daemon/musicmanager.cpp')
| -rw-r--r-- | daemon/musicmanager.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/daemon/musicmanager.cpp b/daemon/musicmanager.cpp new file mode 100644 index 0000000..385abbf --- /dev/null +++ b/daemon/musicmanager.cpp @@ -0,0 +1,221 @@ +#include <QDBusConnection> +#include <QDBusConnectionInterface> +#include "musicmanager.h" + +MusicManager::MusicManager(WatchConnector *watch, QObject *parent) + : QObject(parent), l(metaObject()->className()), + watch(watch), _watcher(new QDBusServiceWatcher(this)) +{ + QDBusConnection bus = QDBusConnection::sessionBus(); + QDBusConnectionInterface *bus_iface = bus.interface(); + + // 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); + + // 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; + } + } + + // 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) { + 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::switchToService(const QString &service) +{ + if (_curService != service) { + qCDebug(l) << "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()) { + qCDebug(l) << "got mpris metadata from service" << _curService; + _curMetadata = qdbus_cast<QVariantMap>(reply.value().variant().value<QDBusArgument>()); + } else { + qCWarning(l) << 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); + + qCDebug(l) << "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()); + + qCDebug(l) << _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()) { + qCWarning(l) << "while calling mpris method on" << _curService << ":" << err.message(); + } +} + +void MusicManager::handleMusicControl(WatchConnector::MusicControl operation) +{ + qCDebug(l) << "operation from watch:" << operation; + + if (_curService.isEmpty()) { + qCDebug(l) << "can't do any music operation, no mpris interface active"; + return; + } + + switch (operation) { + case WatchConnector::musicPLAY_PAUSE: + callMprisMethod("PlayPause"); + break; + case WatchConnector::musicPAUSE: + callMprisMethod("Pause"); + break; + case WatchConnector::musicPLAY: + callMprisMethod("Play"); + break; + case WatchConnector::musicNEXT: + callMprisMethod("Next"); + break; + case WatchConnector::musicPREVIOUS: + 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"); + call << "org.mpris.MediaPlayer2.Player" << "Volume"; + QDBusReply<QDBusVariant> volumeReply = bus.call(call); + if (volumeReply.isValid()) { + double volume = volumeReply.value().variant().toDouble(); + if (operation == WatchConnector::musicVOLUME_UP) { + volume += 0.1; + } + else { + volume -= 0.1; + } + qCDebug(l) << "Setting volume" << volume; + + call = QDBusMessage::createMethodCall(_curService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Set"); + call << "org.mpris.MediaPlayer2.Player" << "Volume" << QVariant::fromValue(QDBusVariant(volume)); + + QDBusError err = QDBusConnection::sessionBus().call(call); + if (err.isValid()) { + qCWarning(l) << err.message(); + } + } else { + qCWarning(l) << volumeReply.error().message(); + } + } + break; + + case WatchConnector::musicGET_NOW_PLAYING: + sendCurrentMprisMetadata(); + break; + + default: + qCWarning(l) << "Operation" << operation << "not supported"; + break; + } +} + +void MusicManager::handleMprisServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) +{ + Q_UNUSED(oldOwner); + if (name == _curService && newOwner.isEmpty()) { + // Oops, current service is going away + switchToService(QString()); + _curMetadata.clear(); + if (watch->isConnected()) { + sendCurrentMprisMetadata(); + } + } +} + +void MusicManager::handleMprisPropertiesChanged(const QString &interface, const QMap<QString, QVariant> &changed, const QStringList &invalidated) +{ + Q_ASSERT(calledFromDBus()); + Q_UNUSED(interface); + Q_UNUSED(invalidated); + + if (changed.contains("Metadata")) { + QVariantMap metadata = qdbus_cast<QVariantMap>(changed.value("Metadata").value<QDBusArgument>()); + qCDebug(l) << "received new metadata" << metadata; + _curMetadata = metadata; + } + + if (changed.contains("PlaybackStatus")) { + QString status = changed.value("PlaybackStatus").toString(); + if (status == "Stopped") { + _curMetadata.clear(); + } + } + + if (watch->isConnected()) { + sendCurrentMprisMetadata(); + } + + switchToService(message().service()); +} + +void MusicManager::handleWatchConnected() +{ + if (watch->isConnected()) { + sendCurrentMprisMetadata(); + } +} |
