[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [simon] plugins/Commands/MprisPlayer: Add the feature to play a media from media player's tracklist 
From:       Ashish Madeti <ashishmadeti () gmail ! com>
Date:       2014-07-30 8:18:53
Message-ID: E1XCP65-0006uA-72 () scm ! kde ! org
[Download RAW message or body]

Git commit 4c2ff5e33b7358edfcb907ac58ece763b21904ae by Ashish Madeti.
Committed on 30/07/2014 at 08:11.
Pushed by madeti into branch 'master'.

Add the feature to play a media from media player's tracklist to \
MprisPlayer plug-in

REVIEW: 119286

M  +1    -0    plugins/Commands/MprisPlayer/CMakeLists.txt
M  +1    -1    plugins/Commands/MprisPlayer/createmprisplayercommandwidget.cpp
 M  +10   -1    plugins/Commands/MprisPlayer/mprisconstants.h
M  +28   -5    plugins/Commands/MprisPlayer/mprisplayercommand.cpp
M  +17   -1    plugins/Commands/MprisPlayer/mprisplayercommand.h
M  +198  -7    plugins/Commands/MprisPlayer/mprisplayercommandmanager.cpp
M  +12   -1    plugins/Commands/MprisPlayer/mprisplayercommandmanager.h
M  +1    -1    plugins/Commands/MprisPlayer/mprisplayerconfiguration.cpp
A  +188  -0    plugins/Commands/MprisPlayer/player.cpp     [License: GPL \
(v2)] A  +65   -0    plugins/Commands/MprisPlayer/player.h     [License: \
GPL (v2)]

http://commits.kde.org/simon/4c2ff5e33b7358edfcb907ac58ece763b21904ae

diff --git a/plugins/Commands/MprisPlayer/CMakeLists.txt \
b/plugins/Commands/MprisPlayer/CMakeLists.txt index 3fc5c1c..92bd5b7 100644
--- a/plugins/Commands/MprisPlayer/CMakeLists.txt
+++ b/plugins/Commands/MprisPlayer/CMakeLists.txt
@@ -3,6 +3,7 @@ set (simonmprisplayerplugin_SRCS
   mprisplayerconfiguration.cpp
   mprisplayercommand.cpp
   createmprisplayercommandwidget.cpp
+  player.cpp
 )
 
 kde4_add_ui_files(simonmprisplayerplugin_SRCS
diff --git a/plugins/Commands/MprisPlayer/createmprisplayercommandwidget.cpp \
b/plugins/Commands/MprisPlayer/createmprisplayercommandwidget.cpp index \
                d25137b..92338fd 100644
--- a/plugins/Commands/MprisPlayer/createmprisplayercommandwidget.cpp
+++ b/plugins/Commands/MprisPlayer/createmprisplayercommandwidget.cpp
@@ -46,7 +46,7 @@ CreateMprisPlayerCommandWidget::~CreateMprisPlayerCommandWidget()
  {
 }
 
-Command *CreateMprisPlayerCommandWidget::createCommand(const QString \
&name, const QString &iconSrc, const QString &description) +Command \
*CreateMprisPlayerCommandWidget::createCommand(const QString& name, const \
QString& iconSrc, const QString& description)  {
     CommandRole role = \
static_cast<CommandRole>(ui.cbCommand->itemData(ui.cbCommand->currentIndex()).toInt());
  return new MprisPlayerCommand(name, iconSrc, description, role);
diff --git a/plugins/Commands/MprisPlayer/mprisconstants.h \
b/plugins/Commands/MprisPlayer/mprisconstants.h index bfff506..a736967 \
                100644
--- a/plugins/Commands/MprisPlayer/mprisconstants.h
+++ b/plugins/Commands/MprisPlayer/mprisconstants.h
@@ -20,6 +20,9 @@
 #ifndef SIMON_MPRIS_CONSTANTS_H_9A22E03B797C494599B9629C6B47E478
 #define SIMON_MPRIS_CONSTANTS_H_9A22E03B797C494599B9629C6B47E478
 
+typedef QPair<QString, QString> Track;
+typedef QList<Track> TrackList;
+
 enum CommandRole
 {
     PlayPause,
@@ -31,13 +34,19 @@ enum CommandRole
     VolumeUp,
     VolumeDown,
     SeekAhead,
-    SeekBack
+    SeekBack,
+    PlayParticular
 };
 
 static const QString MprisPlayerPrefix("org.mpris.MediaPlayer2.");
 static const QString DBusMprisPath("/org/mpris/MediaPlayer2");
 static const QString PlayerInterface("org.mpris.MediaPlayer2.Player");
+static const QString \
TracklistInterface("org.mpris.MediaPlayer2.TrackList");  static const \
QString PropertiesInterface("org.freedesktop.DBus.Properties"); +
+static const QString titleMetadata("xesam:title");
+static const QString trackIdMetadata("mpris:trackid");
+
 static const double volumeChange = 0.05;
 static const qlonglong seekOffset = 1000000; // 1 second
 
diff --git a/plugins/Commands/MprisPlayer/mprisplayercommand.cpp \
b/plugins/Commands/MprisPlayer/mprisplayercommand.cpp index \
                d732901..e503e81 100644
--- a/plugins/Commands/MprisPlayer/mprisplayercommand.cpp
+++ b/plugins/Commands/MprisPlayer/mprisplayercommand.cpp
@@ -55,6 +55,16 @@ CommandRole MprisPlayerCommand::role()
     return m_role;
 }
 
+QString MprisPlayerCommand::trackId()
+{
+    return m_trackId.path();
+}
+
+QString MprisPlayerCommand::serviceName()
+{
+    return m_serviceName;
+}
+
 QDomElement MprisPlayerCommand::serializePrivate(QDomDocument *doc, \
QDomElement& commandElem)  {
     QDomElement roleElem = doc->createElement("role");
@@ -111,6 +121,9 @@ const QMap<QString,QVariant> \
MprisPlayerCommand::getValueMapPrivate() const  case SeekBack:
         typeString = i18nc("Rewind to some time back", "Seek Back");
         break;
+    case PlayParticular:
+        typeString = i18nc("Play a particular track from a playlist", \
"Play Particular"); +        break;
     }
     out.insert(i18nc("Type of the command", "Type"), typeString);
     return out;
@@ -124,6 +137,10 @@ bool MprisPlayerCommand::triggerPrivate(int *state)
 
     QString method;
     QList<QVariant> args;
+    QDBusMessage m;
+    qlonglong offset;
+    double currentVolume, change;
+
     bool success = true;
     switch (m_role) {
     case PlayPause:
@@ -146,7 +163,6 @@ bool MprisPlayerCommand::triggerPrivate(int *state)
         break;
     case VolumeUp:
     case VolumeDown:
-        double currentVolume, change;
         change = volumeChange;
         if (m_role == VolumeDown) {
             change *= -1.0;
@@ -160,16 +176,23 @@ bool MprisPlayerCommand::triggerPrivate(int *state)
         return success;
     case SeekAhead:
     case SeekBack:
-        qlonglong offset = seekOffset;
+        offset = seekOffset;
         if (m_role == SeekBack) {
             offset *= -1;
         }
         args << offset;
         method = "Seek";
         break;
+    case PlayParticular:
+        m = QDBusMessage::createMethodCall(m_serviceName, DBusMprisPath,
+                                                        \
TracklistInterface, +                                                       \
"GoTo"); +        args << QVariant::fromValue(m_trackId);
+        m.setArguments(args);
+        success = QDBusConnection::sessionBus().send(m);
+        return success;
     }
 
-    QDBusMessage m;
     foreach (const QString& service, playersList) {
         m = QDBusMessage::createMethodCall(service, DBusMprisPath, \
PlayerInterface, method);  m.setArguments(args);
@@ -180,7 +203,7 @@ bool MprisPlayerCommand::triggerPrivate(int *state)
     return success;
 }
 
-QDBusReply<QVariant> MprisPlayerCommand::getPropertyValue(const QString \
&service, const QString &interfaceName, const QString &propertyName) \
+QDBusReply<QVariant> MprisPlayerCommand::getPropertyValue(const QString& \
service, const QString& interfaceName, const QString& propertyName)  {
     QDBusInterface *iface = new QDBusInterface(service, DBusMprisPath, \
                PropertiesInterface,
                                                \
QDBusConnection::sessionBus()); @@ -190,7 +213,7 @@ QDBusReply<QVariant> \
MprisPlayerCommand::getPropertyValue(const QString &service  return reply;
 }
 
-bool MprisPlayerCommand::setPropertyValue(const QString &service, const \
QString &interfaceName, const QString &propertyName, const QVariant& \
propValue) +bool MprisPlayerCommand::setPropertyValue(const QString& \
service, const QString& interfaceName, const QString& propertyName, const \
QVariant& propValue)  {
     QDBusInterface *iface = new QDBusInterface(service, DBusMprisPath, \
                PropertiesInterface,
                                                \
                QDBusConnection::sessionBus());
diff --git a/plugins/Commands/MprisPlayer/mprisplayercommand.h \
b/plugins/Commands/MprisPlayer/mprisplayercommand.h index d7287a3..d076018 \
                100644
--- a/plugins/Commands/MprisPlayer/mprisplayercommand.h
+++ b/plugins/Commands/MprisPlayer/mprisplayercommand.h
@@ -53,14 +53,26 @@ class MprisPlayerCommand : public Command
         m_role(role)
     {
     }
+    MprisPlayerCommand(const QString& name, const QString& iconSrc,
+                       const QString& description, const QString& \
serviceName, +                       const QString& trackId) :
+        Command(name, iconSrc, description),
+        m_role(PlayParticular),
+        m_serviceName(serviceName),
+        m_trackId(trackId)
+    {
+    }
+
     ~MprisPlayerCommand() {}
 
     CommandRole role();
+    QString trackId();
+    QString serviceName();
 
     STATIC_CREATE_INSTANCE_H(MprisPlayerCommand)
 
   protected:
-    const QMap<QString,QVariant> getValueMapPrivate() const;
+    const QMap<QString, QVariant> getValueMapPrivate() const;
     bool triggerPrivate(int *state);
     MprisPlayerCommand() {}
 
@@ -71,6 +83,10 @@ class MprisPlayerCommand : public Command
                           const QString& propertyName, const QVariant& \
propValue);  
     CommandRole m_role;
+
+    //These members used only for "PlayParticular" CommandRole
+    QString m_serviceName;
+    QDBusObjectPath m_trackId;
 };
 
 #endif // SIMON_MPRISPLAYERCOMMAND_H_1822E03B797C494599B9629C6B47E478
diff --git a/plugins/Commands/MprisPlayer/mprisplayercommandmanager.cpp \
b/plugins/Commands/MprisPlayer/mprisplayercommandmanager.cpp index \
                f41e757..ea59b0a 100644
--- a/plugins/Commands/MprisPlayer/mprisplayercommandmanager.cpp
+++ b/plugins/Commands/MprisPlayer/mprisplayercommandmanager.cpp
@@ -1,5 +1,6 @@
 /*
  *   Copyright (C) 2014 Ashish Madeti <ashishmadeti@gmail.com>
+ *   Copyright (C) 2014 Peter Grasch <peter.grasch@bedahr.org>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -20,8 +21,11 @@
 #include "mprisplayercommandmanager.h"
 #include "mprisplayerconfiguration.h"
 #include "mprisplayercommand.h"
-#include "mprisconstants.h"
 #include "createmprisplayercommandwidget.h"
+#include "player.h"
+#include <simonactions/actionmanager.h>
+#include <simonscenarios/scenario.h>
+#include <simonscenarios/activevocabulary.h>
 
 #include <QDBusConnection>
 #include <QDBusConnectionInterface>
@@ -34,7 +38,9 @@ K_PLUGIN_FACTORY( MprisPlayerPluginFactory,
 
 K_EXPORT_PLUGIN( MprisPlayerPluginFactory("simoncommandmprisplayer") )
 
-MprisPlayerCommandManager::MprisPlayerCommandManager(QObject *parent, \
const QVariantList &args) +const QString MprisCategoryPrefix("MPRIS_");
+
+MprisPlayerCommandManager::MprisPlayerCommandManager(QObject *parent, \
const QVariantList& args)  : CommandManager((Scenario*) parent, args)
 {
 }
@@ -59,6 +65,11 @@ const QString MprisPlayerCommandManager::name() const
     return i18n("Media Player Control");
 }
 
+void MprisPlayerCommandManager::finalize()
+{
+    cleanupCommandsAndWords();
+}
+
 const QStringList MprisPlayerCommandManager::targetServices()
 {
     if (static_cast<MprisPlayerConfiguration*>(config)->supportAll()) {
@@ -74,16 +85,87 @@ const QStringList \
MprisPlayerCommandManager::runningMediaPlayerServices()  return \
m_mediaPlayerList;  }
 
+void MprisPlayerCommandManager::cleanupCommandsAndWords()
+{
+    removeWordsWithCategoryPrefix(MprisCategoryPrefix);
+
+    ScenarioManager::getInstance()->startGroup();
+
+    CommandList oldCommands = commands;
+    foreach (Command *c, oldCommands) {
+        MprisPlayerCommand *mpCommand = \
static_cast<MprisPlayerCommand*>(c); +        if (mpCommand && \
mpCommand->role() == PlayParticular) { +            deleteCommand(c);
+        }
+    }
+
+    ScenarioManager::getInstance()->commitGroup();
+}
+
+void MprisPlayerCommandManager::cleanupCommandsAndWords(const QString& \
serviceName) +{
+    QString categoryPrefix = MprisCategoryPrefix + \
serviceName.mid(MprisPlayerPrefix.size()); +    \
removeWordsWithCategoryPrefix(categoryPrefix); +
+    ScenarioManager::getInstance()->startGroup();
+
+    CommandList oldCommands = commands;
+    foreach (Command *c, oldCommands) {
+        MprisPlayerCommand *mpCommand = \
static_cast<MprisPlayerCommand*>(c); +        if (mpCommand && \
mpCommand->serviceName() == serviceName) { +            deleteCommand(c);
+            oldCommands.removeAll(c);
+        }
+    }
+
+    ScenarioManager::getInstance()->commitGroup();
+}
+
+void MprisPlayerCommandManager::removeWordsWithCategoryPrefix(const \
QString& prefix) +{
+    ScenarioManager::getInstance()->startGroup();
+
+    Vocabulary *vocab = parentScenario->vocabulary();
+    QList<Word*> internalWords = vocab->getWords();
+
+    foreach (Word *w, internalWords) {
+        if (w->getCategory().startsWith(prefix)) {
+            vocab->removeWord(w, true);
+            internalWords.removeAll(w);
+        }
+    }
+
+    ScenarioManager::getInstance()->commitGroup();
+}
+
 CreateCommandWidget* \
MprisPlayerCommandManager::getCreateCommandWidget(QWidget *parent)  {
     return new CreateMprisPlayerCommandWidget(this, parent);
 }
 
-bool MprisPlayerCommandManager::deSerializeConfig(const QDomElement &elem)
+bool MprisPlayerCommandManager::deSerializeConfig(const QDomElement& elem)
 {
     config = new MprisPlayerConfiguration(parentScenario);
     config->deSerialize(elem);
 
+    return true;
+}
+
+bool MprisPlayerCommandManager::deSerializeCommandsPrivate(const \
QDomElement& elem) +{
+    if (elem.isNull()) {
+        return false;
+    }
+    QDomElement commandElem = elem.firstChildElement("command");
+    while(!commandElem.isNull())
+    {
+        Command *c = MprisPlayerCommand::createInstance(commandElem);
+        if (c) {
+            commands.append(c);
+        }
+        commandElem = commandElem.nextSiblingElement("command");
+    }
+
     QDBusConnection sessionConn = QDBusConnection::sessionBus();
     QDBusReply<QStringList> reply = \
sessionConn.interface()->registeredServiceNames();  if (reply.isValid()) {
@@ -104,20 +186,129 @@ bool \
MprisPlayerCommandManager::deSerializeConfig(const QDomElement &elem)  \
return true;  }
 
-DEFAULT_DESERIALIZE_COMMANDS_PRIVATE_C(MprisPlayerCommandManager, \
                MprisPlayerCommand)
-
 MprisPlayerCommandManager::~MprisPlayerCommandManager()
 {
+    delete m_registerWatcher;
+    delete m_unregisterWatcher;
 }
 
-void MprisPlayerCommandManager::serviceRegistered(const QString \
&serviceName) +void MprisPlayerCommandManager::serviceRegistered(const \
QString& serviceName)  {
+    Player *player;
     if (serviceName.startsWith(MprisPlayerPrefix) && \
!m_mediaPlayerList.contains(serviceName)) {  m_mediaPlayerList << \
serviceName; +
+        player = new Player(serviceName, this);
+        m_players.insert(serviceName, player);
     }
 }
 
-void MprisPlayerCommandManager::serviceUnregistered(const QString \
&serviceName) +void MprisPlayerCommandManager::serviceUnregistered(const \
QString& serviceName)  {
     m_mediaPlayerList.removeAll(serviceName);
+
+    Player *player = m_players.take(serviceName);
+    if (player != 0) {
+        player->deleteLater();
+        cleanupCommandsAndWords(serviceName);
+    }
+}
+
+void MprisPlayerCommandManager::addToCommandlist(const TrackList& \
trackList, const QString& serviceName) +{
+    ScenarioManager::getInstance()->startGroup();
+
+    Vocabulary *vocab = parentScenario->vocabulary();
+    QList<Word*> internalWords = vocab->getWords();
+    CommandList oldCommands = commands;
+
+    //pairs of word and category name
+    QList< QPair<QString, QString> > pseudoWordsToAdd;
+    QStringList toTranscribe;
+
+    QString categoryPrefix = MprisCategoryPrefix + \
serviceName.mid(MprisPlayerPrefix.size()) +  "_"; +
+    QString trackTitle;
+    QString trackId;
+    foreach (const Track& t, trackList) {
+        trackId = t.first;
+        trackTitle = t.second;
+
+        //create safe trigger word
+        trackTitle.remove(QRegExp(QLatin1String("\\(.*\\)")));
+        trackTitle.remove(QLatin1String("("));
+        trackTitle.remove(QLatin1String(")"));
+        trackTitle.remove(QLatin1String("$"));
+        trackTitle.remove(QLatin1String("/"));
+        trackTitle.replace(' ', '_');
+        trackTitle = trackTitle.trimmed();
+
+
+        QString category = categoryPrefix + \
trackId.mid(trackId.lastIndexOf("/") + 1); +        toTranscribe << \
trackTitle.split('_', QString::SkipEmptyParts); +        \
pseudoWordsToAdd.append(QPair<QString, QString>(trackTitle, category)); +
+        //check if we already have the required command
+        bool isNew = true;
+        foreach (Command *c, oldCommands) {
+            if (static_cast<MprisPlayerCommand*>(c)->trackId() == trackId
+                    && static_cast<MprisPlayerCommand*>(c)->serviceName() \
== serviceName) { +                isNew = false;
+                break;
+            }
+        }
+
+        //if not, add the command
+        if (isNew) {
+            addCommand(new MprisPlayerCommand(trackTitle,
+                                              "applications-multimedia",
+                                              i18n("Play media: %1", \
trackTitle), serviceName, +                                              \
trackId)); +        }
+    }
+
+    //add the (pseudo) words
+    QHash<QString,QString> transcriptions = \
ScenarioManager::getInstance()->transcribe(toTranscribe); +    \
QPair<QString, QString> wordToBe; +    foreach (wordToBe, pseudoWordsToAdd) \
{ +        QStringList transcription;
+        foreach (const QString realWord, wordToBe.first.split('_'))
+            transcription.append(transcriptions.value(realWord.toUpper()));
 +        parentScenario->addWord(new Word(wordToBe.first, \
transcription.join(" "), wordToBe.second)); +    }
+
+    ScenarioManager::getInstance()->commitGroup();
+}
+
+void MprisPlayerCommandManager::removeFromCommandlist(const QStringList& \
removedTracksList, const QString& serviceName) +{
+    ScenarioManager::getInstance()->startGroup();
+
+    Vocabulary *vocab = parentScenario->vocabulary();
+    QList<Word*> internalWords = vocab->getWords();
+    CommandList oldCommands = commands;
+
+    QString categoryPrefix = MprisCategoryPrefix + \
serviceName.mid(MprisPlayerPrefix.size()) +  "_"; +
+    foreach (const QString& trackId, removedTracksList) {
+        foreach (Command *c, oldCommands) {
+            MprisPlayerCommand *mpCommand = \
static_cast<MprisPlayerCommand*>(c); +            if (mpCommand && \
mpCommand->trackId() == trackId && +                    \
mpCommand->serviceName() == serviceName) { +                \
deleteCommand(c); +                oldCommands.removeAll(c);
+                break;
+            }
+        }
+
+        QString category = categoryPrefix + \
trackId.mid(trackId.lastIndexOf("/") + 1); +        foreach (Word *w, \
internalWords) { +            if (w->getCategory().startsWith(category)) {
+                vocab->removeWord(w, true);
+                internalWords.removeAll(w);
+            }
+        }
+    }
+
+    ScenarioManager::getInstance()->commitGroup();
 }
diff --git a/plugins/Commands/MprisPlayer/mprisplayercommandmanager.h \
b/plugins/Commands/MprisPlayer/mprisplayercommandmanager.h index \
                f2c091b..6c029a0 100644
--- a/plugins/Commands/MprisPlayer/mprisplayercommandmanager.h
+++ b/plugins/Commands/MprisPlayer/mprisplayercommandmanager.h
@@ -21,10 +21,12 @@
 #define SIMON_MPRISPLAYERCOMMANDMANAGER_H_7A7B9100FF5245329569C1B540119C37
 
 #include <simonscenarios/commandmanager.h>
+#include "mprisconstants.h"
 
 #include <QDBusServiceWatcher>
 
 class MprisPlayerConfiguration;
+class Player;
 
 /**
  *	@class MprisPlayerCommandManager
@@ -45,13 +47,18 @@ class MprisPlayerCommandManager : public CommandManager
     const QString preferredTrigger() const;
     const QString iconSrc() const;
     const QString name() const;
+    void finalize();
 
     const QStringList targetServices();
+    void addToCommandlist(const TrackList& trackIdTitleMap,
+                          const QString& serviceName);
+    void removeFromCommandlist(const QStringList& removedTracksList,
+                          const QString& serviceName);
 
     CreateCommandWidget* getCreateCommandWidget(QWidget *parent);
 
     bool deSerializeConfig(const QDomElement& elem);
-    DEFAULT_DESERIALIZE_COMMANDS_PRIVATE_H
+    bool deSerializeCommandsPrivate(const QDomElement& elem);
 
     MprisPlayerCommandManager(QObject* parent, const QVariantList& args);
     ~MprisPlayerCommandManager();
@@ -62,10 +69,14 @@ class MprisPlayerCommandManager : public CommandManager
 
   private:
     const QStringList runningMediaPlayerServices();
+    void cleanupCommandsAndWords();
+    void cleanupCommandsAndWords(const QString& serviceName);
+    void removeWordsWithCategoryPrefix(const QString& prefix);
 
     QStringList m_mediaPlayerList;
     QDBusServiceWatcher* m_registerWatcher;
     QDBusServiceWatcher* m_unregisterWatcher;
+    QHash<QString, Player*> m_players;
 };
 
 #endif // SIMON_MPRISPLAYERCOMMANDMANAGER_H_7A7B9100FF5245329569C1B540119C37
                
diff --git a/plugins/Commands/MprisPlayer/mprisplayerconfiguration.cpp \
b/plugins/Commands/MprisPlayer/mprisplayerconfiguration.cpp index \
                4f25541..0a73db6 100644
--- a/plugins/Commands/MprisPlayer/mprisplayerconfiguration.cpp
+++ b/plugins/Commands/MprisPlayer/mprisplayerconfiguration.cpp
@@ -92,7 +92,7 @@ void MprisPlayerConfiguration::populateMediaServices()
     QStringList services = reply.value();
     foreach (const QString& serviceName, services) {
         if (serviceName.startsWith(MprisPlayerPrefix)
-                && ui.cbMediaServiceNames->findText(serviceName) == -1) {
+               && ui.cbMediaServiceNames->findText(serviceName) == -1) {
             ui.cbMediaServiceNames->addItem(serviceName);
         }
     }
diff --git a/plugins/Commands/MprisPlayer/player.cpp \
b/plugins/Commands/MprisPlayer/player.cpp new file mode 100644
index 0000000..3dce705
--- /dev/null
+++ b/plugins/Commands/MprisPlayer/player.cpp
@@ -0,0 +1,188 @@
+/*
+ *   Copyright (C) 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 version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   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 "player.h"
+#include "mprisconstants.h"
+#include "mprisplayercommand.h"
+#include "mprisplayercommandmanager.h"
+
+#include <QDBusConnection>
+#include <QDBusObjectPath>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include <QDBusPendingCallWatcher>
+
+Player::Player(const QString& serviceName, QObject *parent)
+    : QObject(parent),
+      m_serviceName(serviceName)
+{
+    qDBusRegisterMetaType< QList<QVariantMap> >();
+    getAllTracks();
+    connectTracklistSignals();
+}
+
+Player::~Player()
+{
+}
+
+void Player::trackAdded(const QVariantMap& metadata, const \
QDBusObjectPath& afterTrack) +{
+    Q_UNUSED(afterTrack)
+
+    QString trackId = \
metadata[trackIdMetadata].value<QDBusObjectPath>().path(); +    QString \
title = metadata[titleMetadata].toString(); +    \
m_currentTracklist[trackId] = title; +
+    TrackList m;
+    m << Track(trackId, title);
+    static_cast<MprisPlayerCommandManager*>(parent())->
+            addToCommandlist(m, m_serviceName);
+}
+
+void Player::trackRemoved(const QDBusObjectPath& trackId)
+{
+    m_currentTracklist.remove(trackId.path());
+    static_cast<MprisPlayerCommandManager*>(parent())->
+            removeFromCommandlist(QStringList() << trackId.path(), \
m_serviceName); +}
+
+void Player::trackMetadataChanged(const QDBusObjectPath& trackId, const \
QVariantMap& metadata) +{
+    QString newTrackId;
+    QString newTitle;
+    if (m_currentTracklist.contains(trackId.path())) {
+        newTrackId = \
metadata[trackIdMetadata].value<QDBusObjectPath>().path(); +        \
newTitle = metadata[titleMetadata].toString(); +        \
m_currentTracklist[newTrackId] = newTitle; +        if (trackId.path() != \
newTrackId) { +            m_currentTracklist.remove(trackId.path());
+        }
+
+        static_cast<MprisPlayerCommandManager*>(parent())->
+                removeFromCommandlist(QStringList() << trackId.path(), \
m_serviceName); +
+        TrackList m;
+        m << Track(newTrackId, newTitle);
+        static_cast<MprisPlayerCommandManager*>(parent())->
+                addToCommandlist(m, m_serviceName);
+    }
+}
+
+void Player::tracklistReplaced(const QList<QDBusObjectPath>& tracks, const \
QDBusObjectPath& currentTrack) +{
+    Q_UNUSED(currentTrack)
+
+    QDBusInterface iface(m_serviceName, DBusMprisPath, \
TracklistInterface); +    QDBusPendingCall pendingCall = \
iface.asyncCall("GetTracksMetadata", +                                      \
QVariant::fromValue< QList<QDBusObjectPath> >(tracks)); +
+    connect(new QDBusPendingCallWatcher(pendingCall, this),
+            SIGNAL(finished(QDBusPendingCallWatcher*)),
+            this, SLOT(tracksMetadataReceived(QDBusPendingCallWatcher*)));
+}
+
+void Player::tracksMetadataReceived(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply< QList<QVariantMap> > reply = *watcher;
+
+    if (reply.error().isValid()) {
+        kDebug() << "GetTracksMetadata for service " << m_serviceName
+                 << " failed with error: " << reply.error().message();
+        return;
+    }
+
+    static_cast<MprisPlayerCommandManager*>(parent())->
+            removeFromCommandlist(m_currentTracklist.uniqueKeys(), \
m_serviceName); +    m_currentTracklist.clear();
+
+    QString trackId;
+    TrackList m;
+    foreach (const QVariantMap& metadata, reply.value()) {
+        trackId = metadata[trackIdMetadata].value<QDBusObjectPath>().path();
 +        m_currentTracklist[trackId] = metadata[titleMetadata].toString();
+        m << Track(trackId, metadata[titleMetadata].toString());
+    }
+
+    static_cast<MprisPlayerCommandManager*>(parent())->
+            addToCommandlist(m, m_serviceName);
+
+    watcher->deleteLater();
+}
+
+void Player::connectTracklistSignals()
+{
+
+    QDBusConnection::sessionBus().connect(m_serviceName,
+                                          DBusMprisPath,
+                                          TracklistInterface,
+                                          "TrackAdded",
+                                          this,
+                                          \
SLOT(trackAdded(QVariantMap,QDBusObjectPath))); +    \
QDBusConnection::sessionBus().connect(m_serviceName, +                      \
DBusMprisPath, +                                          \
TracklistInterface, +                                          \
"TrackRemoved", +                                          this,
+                                          \
SLOT(trackRemoved(QDBusObjectPath))); +    \
QDBusConnection::sessionBus().connect(m_serviceName, +                      \
DBusMprisPath, +                                          \
TracklistInterface, +                                          \
"TrackMetadataChanged", +                                          this,
+                                          \
SLOT(trackMetadataChanged(QDBusObjectPath,QVariantMap))); +    \
QDBusConnection::sessionBus().connect(m_serviceName, +                      \
DBusMprisPath, +                                          \
TracklistInterface, +                                          \
"TrackListReplaced", +                                          this,
+                                          \
SLOT(tracklistReplaced(QList<QDBusObjectPath>,QDBusObjectPath))); +}
+
+void Player::getAllTracks()
+{
+    QDBusInterface propsIface(m_serviceName, DBusMprisPath, \
PropertiesInterface); +    QDBusPendingCall pendingCall = \
propsIface.asyncCall("Get",TracklistInterface, "Tracks"); +
+    connect(new QDBusPendingCallWatcher(pendingCall, this),
+            SIGNAL(finished(QDBusPendingCallWatcher*)),
+            this, SLOT(tracksPropertyReceived(QDBusPendingCallWatcher*)));
+
+}
+
+void Player::tracksPropertyReceived(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<QVariant> reply = *watcher;
+    if (reply.isError()) {
+        kDebug() << "\"Get\" for property \"Tracks\" for service "
+                 << m_serviceName << " failed with error: "
+                 << reply.error().message();
+        return;
+    }
+
+    QList<QDBusObjectPath> tracks;
+    const QDBusArgument& arg = reply.value().value<QDBusArgument>();
+    arg.beginArray();
+    while (!arg.atEnd()) {
+        tracks << arg.asVariant().value<QDBusObjectPath>();
+    }
+    arg.endArray();
+
+    tracklistReplaced(tracks, QDBusObjectPath());
+    watcher->deleteLater();
+}
diff --git a/plugins/Commands/MprisPlayer/player.h \
b/plugins/Commands/MprisPlayer/player.h new file mode 100644
index 0000000..ce74d2e
--- /dev/null
+++ b/plugins/Commands/MprisPlayer/player.h
@@ -0,0 +1,65 @@
+/*
+ *   Copyright (C) 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 version 2,
+ *   or (at your option) any later version, as published by the Free
+ *   Software Foundation
+ *
+ *   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 SIMON_PLAYER_H_ABC0C7EC08DA40FEBD5B5BA233D7AC7C
+#define SIMON_PLAYER_H_ABC0C7EC08DA40FEBD5B5BA233D7AC7C
+
+#include <QDBusMetaType>
+
+Q_DECLARE_METATYPE(QList<QVariantMap>)
+
+class QDBusObjectPath;
+class QDBusPendingCallWatcher;
+
+/**
+ *	@class Player
+ *	@brief Manages Tracklist of an MPRIS media player
+ *
+ *	@version 0.1
+ *	@date 29.06.2014
+ *	@author Ashish Madeti
+ */
+
+class Player : public QObject
+{
+    Q_OBJECT
+
+public:
+    Player(const QString& serviceName, QObject *parent = 0);
+    ~Player();
+
+public slots:
+    void trackAdded(const QVariantMap& metadata, const QDBusObjectPath& \
afterTrack); +    void trackRemoved(const QDBusObjectPath& trackId);
+    void trackMetadataChanged(const QDBusObjectPath& trackId, const \
QVariantMap& metadata); +    void tracklistReplaced(const \
QList<QDBusObjectPath>& tracks, const QDBusObjectPath& currentTrack); +
+private slots:
+    void tracksPropertyReceived(QDBusPendingCallWatcher* watcher);
+    void tracksMetadataReceived(QDBusPendingCallWatcher* watcher);
+
+private:
+    void connectTracklistSignals();
+    void getAllTracks();
+
+    QHash<QString, QString> m_currentTracklist;
+    QString m_serviceName;
+};
+
+#endif // SIMON_PLAYER_H_ABC0C7EC08DA40FEBD5B5BA233D7AC7C


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic