diff --git a/daemon/devicelinks/tcpdevicelink.cpp b/daemon/devicelinks/tcpdevicelink.cpp index bc357d019..16a558e5e 100644 --- a/daemon/devicelinks/tcpdevicelink.cpp +++ b/daemon/devicelinks/tcpdevicelink.cpp @@ -45,7 +45,7 @@ void TcpDeviceLink::dataReceived() if (package.length() < 3) continue; - NetworkPackage np; + NetworkPackage np(""); NetworkPackage::unserialize(package,&np); emit receivedPackage(np); diff --git a/daemon/linkproviders/avahitcplinkprovider.cpp b/daemon/linkproviders/avahitcplinkprovider.cpp index 02033614f..d7b77a399 100644 --- a/daemon/linkproviders/avahitcplinkprovider.cpp +++ b/daemon/linkproviders/avahitcplinkprovider.cpp @@ -49,7 +49,7 @@ void AvahiTcpLinkProvider::newConnection() connect(socket,SIGNAL(readyRead()),this,SLOT(dataReceived())); - NetworkPackage np; + NetworkPackage np(PACKAGE_TYPE_IDENTITY); NetworkPackage::createIdentityPackage(&np); int written = socket->write(np.serialize()); @@ -64,7 +64,7 @@ void AvahiTcpLinkProvider::dataReceived() qDebug() << "AvahiTcpLinkProvider received reply:" << data; - NetworkPackage np; + NetworkPackage np(""); NetworkPackage::unserialize(data,&np); if (np.version() > 0 && np.type() == PACKAGE_TYPE_IDENTITY) { diff --git a/daemon/linkproviders/loopbacklinkprovider.cpp b/daemon/linkproviders/loopbacklinkprovider.cpp index c286bbb09..bb476f055 100644 --- a/daemon/linkproviders/loopbacklinkprovider.cpp +++ b/daemon/linkproviders/loopbacklinkprovider.cpp @@ -24,6 +24,7 @@ #include LoopbackLinkProvider::LoopbackLinkProvider() + : identityPackage(PACKAGE_TYPE_IDENTITY) { echoDeviceLink = new EchoDeviceLink("fake", this); NetworkPackage::createIdentityPackage(&identityPackage); diff --git a/daemon/networkpackage.h b/daemon/networkpackage.h index ce65f4cf3..5ac0c382c 100644 --- a/daemon/networkpackage.h +++ b/daemon/networkpackage.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "default_args.h" @@ -38,7 +39,6 @@ class NetworkPackage : public QObject public: - NetworkPackage() {}; NetworkPackage(QString type); static void unserialize(QByteArray, NetworkPackage*); @@ -52,10 +52,12 @@ public: int version() const { return mVersion; } //Get and set info from body. Note that id, type and version can not be accessed through these. - template T get(const QString& property, const T& defaultValue = default_arg::get()) const { - return mBody.value(property,defaultValue).template value(); //Important note: Awesome template syntax is awesome + template T get(const QString& key, const T& defaultValue = default_arg::get()) const { + return mBody.value(key,defaultValue).template value(); //Important note: Awesome template syntax is awesome } - template void set(const QString& property, const T& value) { mBody[property] = value; } + template void set(const QString& key, const T& value) { mBody[key] = QVariant(value); } + + bool has(const QString& key) { return mBody.contains(key); } private: void setId(long id) { mId = id; } @@ -70,5 +72,7 @@ private: }; +//Set specialization need this awesome-to-the-max syntax: +//template<> inline void NetworkPackage::set(const QString& key, const QStringList& value) { mBody[key] = QVariant(value); } #endif // NETWORKPACKAGE_H diff --git a/daemon/packageinterfaces/mpriscontrolpackageinterface.cpp b/daemon/packageinterfaces/mpriscontrolpackageinterface.cpp index 71b20ecaa..976416274 100644 --- a/daemon/packageinterfaces/mpriscontrolpackageinterface.cpp +++ b/daemon/packageinterfaces/mpriscontrolpackageinterface.cpp @@ -29,7 +29,60 @@ MprisControlPackageInterface::MprisControlPackageInterface() { - //TODO: Emit info read form mpris to the phone + + //Detect new interfaces + connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), + this, SLOT(serviceOwnerChanged(QString,QString,QString))); + + //Add existing interfaces + QStringList interfaces = QDBusConnection::sessionBus().interface()->registeredServiceNames().value(); + Q_FOREACH (const QString& iface, interfaces) { + if (iface.startsWith("org.mpris.MediaPlayer2")) { + addPlayer(iface); + } + } + +} + +void MprisControlPackageInterface::serviceOwnerChanged(const QString &name, + const QString &oldOwner, + const QString &newOwner) +{ + Q_UNUSED(oldOwner); + + if (name.startsWith("org.mpris.MediaPlayer2")) { + + qDebug() << "Something registered in bus" << name << oldOwner << newOwner; + + if (oldOwner.isEmpty()) { + addPlayer(name); + } else if (newOwner.isEmpty()) { + removePlayer(name); + } + } +} + +void MprisControlPackageInterface::addPlayer(const QString& ifaceName) +{ + QDBusInterface interface(ifaceName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2"); + //TODO: Make this async + QString identity = interface.property("Identity").toString(); + playerList[identity] = ifaceName; + qDebug() << "addPlayer" << ifaceName << identity; + sendPlayerList(); +} + +void MprisControlPackageInterface::removePlayer(const QString& ifaceName) +{ + playerList.remove(playerList.key(ifaceName)); + sendPlayerList(); +} + +void MprisControlPackageInterface::sendPlayerList() +{ + NetworkPackage np(PACKAGE_TYPE_MPRIS); + np.set("playerList",playerList.keys()); + sendPackage(np); } bool MprisControlPackageInterface::receivePackage (const Device& device, const NetworkPackage& np) @@ -38,16 +91,40 @@ bool MprisControlPackageInterface::receivePackage (const Device& device, const N if (np.type() != PACKAGE_TYPE_MPRIS) return false; - QString action = np.get("action"); - QStringList interfaces = QDBusConnection::sessionBus().interface()->registeredServiceNames().value(); - Q_FOREACH (const QString& iface, interfaces) { - if (iface.startsWith("org.mpris.MediaPlayer2")) { - QDBusInterface mprisInterface(iface, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player"); - mprisInterface.asyncCall(action); - } + QString player = np.get("player"); + if (!playerList.contains(player)) { + sendPlayerList(); + return true; + } + + QDBusInterface mprisInterface(playerList[player], "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player"); + + if (np.get("requestPlayerList")) { + sendPlayerList(); + } + + QString action = np.get("action"); + if (!action.isEmpty()) { + qDebug() << "Calling action" << action << "in" << playerList[player]; + mprisInterface.call(action); + sendNowPlaying(mprisInterface); + } else if (np.get("requestNowPlaying")) { + sendNowPlaying(mprisInterface); } return true; } + +void MprisControlPackageInterface::sendNowPlaying(const QDBusInterface& mprisInterface) +{ + QVariantMap nowPlayingMap = mprisInterface.property("Metadata").toMap(); + QString nowPlaying = nowPlayingMap["xesam:title"].toString(); + if (nowPlayingMap.contains("xesam:artist")) { + nowPlaying = nowPlayingMap["xesam:artist"].toString() + " - " + nowPlaying; + } + NetworkPackage np(PACKAGE_TYPE_MPRIS); + np.set("nowPlaying",nowPlaying); + sendPackage(np); +} diff --git a/daemon/packageinterfaces/mpriscontrolpackageinterface.h b/daemon/packageinterfaces/mpriscontrolpackageinterface.h index 02d8eecb3..1f1ebe12a 100644 --- a/daemon/packageinterfaces/mpriscontrolpackageinterface.h +++ b/daemon/packageinterfaces/mpriscontrolpackageinterface.h @@ -25,14 +25,29 @@ #include #include +#include +#include class MprisControlPackageInterface : public PackageInterface { + Q_OBJECT + public: MprisControlPackageInterface(); virtual bool receivePackage(const Device& device, const NetworkPackage& np); +public Q_SLOTS: + void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + +private: + QHash playerList; + void addPlayer(const QString& ifaceName); + void removePlayer(const QString& ifaceName); + void sendPlayerList(); + void sendNowPlaying(const QDBusInterface& interface); + + }; #endif