New DBus functions and mediaartlocal support
authorNikolay Tischenko <niktischenko@gmail.com>
Fri, 11 Mar 2011 19:06:52 +0000 (01:06 +0600)
committerNikolay Tischenko <niktischenko@gmail.com>
Fri, 11 Mar 2011 19:06:52 +0000 (01:06 +0600)
src/coverfinder.cpp
src/coverfinder.h
src/dbusadaptor.cpp
src/dbusadaptor.h
src/dbusclient.cpp
src/dbusclient.h
src/player/player.cpp
src/player/player.h
src/playerform.cpp
src/track.cpp
src/track.h

index 5d24368..b035419 100644 (file)
@@ -53,6 +53,7 @@ bool CoverFinder::_find(QString path) {
                        pics << item;
                        if (NAMES.contains(item.baseName().toLower())) {
                                emit found(QImage(item.absoluteFilePath()));
+                               emit foundPath(item.absoluteFilePath());
                                return true;
                        }
                }
@@ -68,6 +69,7 @@ bool CoverFinder::_find(QString path) {
                        foreach (QFileInfo item, appropriate_pics) {
                                if (item.baseName().toLower().contains(name)) {
                                        emit found(QImage(item.absoluteFilePath()));
+                                       emit foundPath(item.absoluteFilePath());
                                        return true;
                                }
                        }
@@ -84,11 +86,13 @@ bool CoverFinder::_find(QString path) {
                        foreach (QFileInfo item, appropriate_pics) {
                                if (!unprior.contains(item)) {
                                        emit found(QImage(item.absoluteFilePath()));
+                                       emit foundPath(item.absoluteFilePath());
                                        return true;
                                }
                        }
                }
                emit found(QImage(unprior.at(0).absoluteFilePath()));
+               emit foundPath(unprior.at(0).absoluteFilePath());
                return true;
        }
        foreach(QFileInfo item, dirs) {
@@ -138,11 +142,13 @@ bool CoverFinder::_extract(QString file) {
 
 void CoverFinder::find(Track track) {
        QFileInfo filePath(track.source());
-       QtConcurrent::run(this, &CoverFinder::_async_find, filePath, track.metadata().artist(), track.metadata().album());
+       QtConcurrent::run(this, &CoverFinder::_async_find, filePath, track);
 }
 
-bool CoverFinder::_async_find(QFileInfo filePath, QString artist, QString album) {
-       if (!_find(filePath.absolutePath()) && !_tfind(artist, album) && !_extract(filePath.absoluteFilePath())) {
+bool CoverFinder::_async_find(QFileInfo filePath, Track track) {
+       if (!_find(filePath.absolutePath()) && !_tfind(track.metadata().artist(), track.metadata().album()) &&
+           !_malfind(filePath.absolutePath()+"/.mediaartlocal/"+track.mediaArtLocal()) &&
+           !_extract(filePath.absoluteFilePath())) {
                emit found(_defaultCover);
                return false;
        }
@@ -159,9 +165,20 @@ bool CoverFinder::_tfind(QString artist, QString album) {
        QString fname2 = QDir::homePath()+"/.covers/"+aname+".jpg";
        if (QFile::exists(fname1)) {
                emit found(QImage(fname1));
+               emit foundPath(fname1);
                return true;
        } else if (QFile::exists(fname2)) {
                emit found(QImage(fname2));
+               emit foundPath(fname2);
+               return true;
+       }
+       return false;
+}
+
+bool CoverFinder::_malfind(QString path) {
+       if (QFile::exists(path)) {
+               emit found(QImage(path));
+               emit foundPath(path);
                return true;
        }
        return false;
index 4b574f6..07fd72b 100644 (file)
@@ -36,15 +36,17 @@ public:
 
 signals:
        void found(QImage);
+       void foundPath(QString);
 
 public slots:
        void find(Track track);
        QImage &defaultCover();
 private:
-       bool _async_find(QFileInfo filePath, QString artist, QString album);
+       bool _async_find(QFileInfo filePath, Track track);
        bool _find(QString path);
        bool _extract(QString file);
        bool _tfind(QString artist, QString album);
+       bool _malfind(QString path); // .mediaartlocal
 
 private:
        QImage _defaultCover;
index ac341e0..72a61a1 100644 (file)
 #include <QtCore/QVariant>
 #include <QDebug>
 #include "config.h"
+#include "player/player.h"
 
 /*
  * Implementation of adaptor class DBusAdaptop
  */
 
 DBusAdaptop::DBusAdaptop(QObject *parent)
-    : QDBusAbstractAdaptor(parent)
+       : QDBusAbstractAdaptor(parent)
 {
-    // constructor
-    setAutoRelaySignals(true);
-    // handling signals from bluetooth headset
-    _time = QTime::currentTime();
-    if (!QDBusConnection::systemBus().connect(QString(), QString(),
-       "org.freedesktop.Hal.Device", "Condition", this, SLOT(processBTSignal(QString, QString)))) {
-           qWarning() << "Can not connect to HAL";
-    }
+       // constructor
+       setAutoRelaySignals(true);
+       // handling signals from bluetooth headset
+       _time = QTime::currentTime();
+       if (!QDBusConnection::systemBus().connect(QString(), QString(),
+                                                 "org.freedesktop.Hal.Device", "Condition", this, SLOT(processBTSignal(QString, QString)))) {
+               qWarning() << "Can not connect to HAL";
+       }
+       setAutoRelaySignals(true);
 }
 
 DBusAdaptop::~DBusAdaptop()
 {
-    // destructor
+       // destructor
 }
 
-QString DBusAdaptop::album()
-{
-    // handle method call ru.somebody.someplayer.album
-    QString out0;
-    QMetaObject::invokeMethod(parent(), "album", Q_RETURN_ARG(QString, out0));
-    return out0;
+QString DBusAdaptop::album() {
+       // handle method call ru.somebody.someplayer.album
+       QString out0;
+       QMetaObject::invokeMethod(parent(), "album", Q_RETURN_ARG(QString, out0));
+       return out0;
 }
 
-QString DBusAdaptop::artist()
-{
-    // handle method call ru.somebody.someplayer.artist
-    QString out0;
-    QMetaObject::invokeMethod(parent(), "artist", Q_RETURN_ARG(QString, out0));
-    return out0;
+QString DBusAdaptop::artist() {
+       // handle method call ru.somebody.someplayer.artist
+       QString out0;
+       QMetaObject::invokeMethod(parent(), "artist", Q_RETURN_ARG(QString, out0));
+       return out0;
 }
 
-void DBusAdaptop::next()
-{
-    // handle method call ru.somebody.someplayer.next
-    QMetaObject::invokeMethod(parent(), "next");
+QString DBusAdaptop::title_artist_album() {
+       // handle method call ru.somebody.someplayer.title_artist_album
+       QString album, title, artist;
+       QMetaObject::invokeMethod(parent(), "artist", Q_RETURN_ARG(QString, artist));
+       QMetaObject::invokeMethod(parent(), "title", Q_RETURN_ARG(QString, title));
+       QMetaObject::invokeMethod(parent(), "album", Q_RETURN_ARG(QString, album));
+       return QString("%1\n%2\n%3").arg(title).arg(artist).arg(album);
 }
 
-void DBusAdaptop::prev()
-{
-    // handle method call ru.somebody.someplayer.prev
-    QMetaObject::invokeMethod(parent(), "prev");
+void DBusAdaptop::next() {
+       // handle method call ru.somebody.someplayer.next
+       QMetaObject::invokeMethod(parent(), "next");
 }
 
-void DBusAdaptop::stop()
-{
-    // handle method call ru.somebody.someplayer.stop
-    QMetaObject::invokeMethod(parent(), "stop");
+void DBusAdaptop::prev() {
+       // handle method call ru.somebody.someplayer.prev
+       QMetaObject::invokeMethod(parent(), "prev");
 }
 
-QString DBusAdaptop::title()
-{
-    // handle method call ru.somebody.someplayer.title
-    QString out0;
-    QMetaObject::invokeMethod(parent(), "title", Q_RETURN_ARG(QString, out0));
-    return out0;
+void DBusAdaptop::stop() {
+       // handle method call ru.somebody.someplayer.stop
+       QMetaObject::invokeMethod(parent(), "stop");
 }
 
-void DBusAdaptop::toggle()
-{
-    // handle method call ru.somebody.someplayer.toggle
-    QMetaObject::invokeMethod(parent(), "toggle");
+QString DBusAdaptop::title() {
+       // handle method call ru.somebody.someplayer.title
+       QString out0;
+       QMetaObject::invokeMethod(parent(), "title", Q_RETURN_ARG(QString, out0));
+       return out0;
+}
+
+void DBusAdaptop::toggle() {
+       // handle method call ru.somebody.someplayer.toggle
+       QMetaObject::invokeMethod(parent(), "toggle");
+}
+
+QString DBusAdaptop::state() {
+       // handle method call ru.somebody.someplayer.state
+       QString out0;
+       QMetaObject::invokeMethod(parent(), "stateText", Q_RETURN_ARG(QString, out0));
+       return out0;
+}
+
+QString DBusAdaptop::albumart() {
+       // handle method call ru.somebody.someplayer.albumart
+       QString out0;
+       QMetaObject::invokeMethod(parent(), "albumart", Q_RETURN_ARG(QString, out0));
+       return out0;
 }
 
 void DBusAdaptop::processBTSignal(QString event, QString state) {
index a0fb6cc..d5ecc91 100644 (file)
@@ -38,51 +38,62 @@ class QVariant;
  */
 class DBusAdaptop: public QDBusAbstractAdaptor
 {
-    Q_OBJECT
-    Q_CLASSINFO("D-Bus Interface", "ru.somebody.someplayer")
-    Q_CLASSINFO("D-Bus Introspection", ""
-"  <interface name=\"ru.somebody.someplayer\">\n"
-"    <method name=\"prev\">\n"
-"      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
-"    </method>\n"
-"    <method name=\"next\">\n"
-"      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
-"    </method>\n"
-"    <method name=\"toggle\">\n"
-"      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
-"    </method>\n"
-"    <method name=\"stop\">\n"
-"      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
-"    </method>\n"
-"    <method name=\"artist\">\n"
-"      <arg direction=\"out\" type=\"s\"/>\n"
-"    </method>\n"
-"    <method name=\"album\">\n"
-"      <arg direction=\"out\" type=\"s\"/>\n"
-"    </method>\n"
-"    <method name=\"title\">\n"
-"      <arg direction=\"out\" type=\"s\"/>\n"
-"    </method>\n"
-"  </interface>\n"
-        "")
+       Q_OBJECT
+       Q_CLASSINFO("D-Bus Interface", "ru.somebody.someplayer")
+       Q_CLASSINFO("D-Bus Introspection", ""
+                   "  <interface name=\"ru.somebody.someplayer\">\n"
+                   "    <method name=\"prev\">\n"
+                   "      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"next\">\n"
+                   "      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"toggle\">\n"
+                   "      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"stop\">\n"
+                   "      <annotation value=\"true\" name=\"org.freedesktop.DBus.Method.NoReply\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"artist\">\n"
+                   "      <arg direction=\"out\" type=\"s\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"album\">\n"
+                   "      <arg direction=\"out\" type=\"s\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"title\">\n"
+                   "      <arg direction=\"out\" type=\"s\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"title_artist_album\">\n"
+                   "      <arg direction=\"out\" type=\"s\"/>\n"
+                   "    </method>\n"
+                   "    <method name=\"state\">\n"
+                   "      <arg direction=\"out\" type=\"s\"/>\n"
+                   "    </method>\n"
+                   "  </interface>\n"
+                   "")
 public:
-    DBusAdaptop(QObject *parent);
-    virtual ~DBusAdaptop();
+       DBusAdaptop(QObject *parent);
+       virtual ~DBusAdaptop();
 
 public: // PROPERTIES
 public Q_SLOTS: // METHODS
-    QString album();
-    QString artist();
-    Q_NOREPLY void next();
-    Q_NOREPLY void prev();
-    Q_NOREPLY void stop();
-    QString title();
-    Q_NOREPLY void toggle();
-    Q_NOREPLY void pause();
-    Q_NOREPLY void playIfPaused();
+       QString album();
+       QString artist();
+       Q_NOREPLY void next();
+       Q_NOREPLY void prev();
+       Q_NOREPLY void stop();
+       QString title();
+       QString title_artist_album();
+       QString state();
+       QString albumart();
+       Q_NOREPLY void toggle();
+       Q_NOREPLY void pause();
+       Q_NOREPLY void playIfPaused();
 
-    void processBTSignal(QString, QString);
+       void processBTSignal(QString, QString);
 Q_SIGNALS: // SIGNALS
+       void stateChanged();
+       void albumArt(QString path);
 private:
        QTime _time;
 };
index d839e7d..2ee3c20 100644 (file)
@@ -89,3 +89,4 @@ quint32 DBusClient::getVolume() {
        volume = var.variant();
        return volume.toUInt();
 }
+
index 5945464..0705294 100644 (file)
@@ -24,6 +24,7 @@
 #include <QtDBus/QtDBus>
 #include <QTimer>
 #include <QTime>
+#include "player/player.h"
 
 #define MM_KEY_UP (73)
 #define MM_KEY_DOWN (74)
index f62497f..3bb3039 100644 (file)
@@ -71,6 +71,7 @@ Player::Player(QObject *parent) :
        qsrand(seed);
        _random = _config.getValue("playback/random").toBool();
        _repeat = (RepeatRule) _config.getValue("playback/repeat").toInt();
+       _state = PLAYER_DONE;
 }
 
 void Player::setTrackId(int id) {
@@ -341,3 +342,31 @@ void Player::_truncate_history() {
 Player::~Player() {
        stop();
 }
+
+QString Player::stateText() {
+       QString return_val;
+       switch (_state) {
+       case PLAYER_PLAYING:
+               return_val = "playing";
+               break;
+       case PLAYER_STOPPED:
+               return_val = "stopped";
+               break;
+       case PLAYER_PAUSED:
+               return_val = "paused";
+               break;
+       case PLAYER_DONE:
+               return_val = "idle";
+               break;
+       case PLAYER_LOADING:
+               return_val = "idle";
+               break;
+       case PLAYER_ERROR:
+               return_val = "error";
+               break;
+       default:
+               return_val = "unhandled";
+               break;
+       }
+       return return_val;
+}
index 838bc40..9a00ebf 100644 (file)
@@ -57,7 +57,6 @@ namespace SomePlayer {
                        Phonon::MediaObject* mediaObject() {return _player;}
                        bool equalizerEnabled() {return _equalizer_enabled;}
                        bool equalizerAvailable() {return _equalizer != NULL;}
-                       PlayerState state() {return _state;}
                        Track current();
                        void setAwaitingSeek(int pos) {_awaiting_seek = true; _awaiting_seek_pos = pos;}
                signals:
@@ -89,6 +88,8 @@ namespace SomePlayer {
                        QString artist();
                        QString album();
                        QString title();
+                       PlayerState state() {return _state;}
+                       QString stateText();
                private slots:
                        void _stateChanged(Phonon::State, Phonon::State);
                        void _tick(qint64);
index 58de1b8..b2f1eba 100644 (file)
@@ -174,6 +174,8 @@ PlayerForm::PlayerForm(Library* lib, QWidget *parent) :
 
        // dbus
        _dbusadaptor = new DBusAdaptop(_player);
+       connect(_player, SIGNAL(stateChanged(PlayerState)), _dbusadaptor, SIGNAL(stateChanged()));
+       connect(_coverfinder, SIGNAL(foundPath(QString)), _dbusadaptor, SIGNAL(albumArt(QString)));
        QDBusConnection connection = QDBusConnection::sessionBus();
        bool ret = connection.registerService(_SERVICE_NAME_);
        ret = connection.registerObject("/", _player);
index 0f36353..ac7a877 100644 (file)
@@ -20,6 +20,8 @@
 #include "track.h"
 #include "tagresolver.h"
 #include <QFileInfo>
+#include <QCryptographicHash>
+#include <QDebug>
 
 using namespace SomePlayer::DataObjects;
 
@@ -102,3 +104,23 @@ bool Track::operator >= (const Track &track) const {
 bool Track::operator < (const Track &track) const {
        return (metadata().title().compare(track.metadata().title()) < 0);
 }
+
+QString Track::mediaArtLocal() {
+       QString album = _metadata.album();
+       QRegExp rsb("\\[.*\\]");
+       QRegExp rfb("{.*}");
+       QRegExp rrb("\\(.*\\)");
+       QRegExp stripB("^[()_{}[]!@#$^&*+=|\\\\/\"'?<>~`\\s\\t]*");
+       QRegExp stripE("[()_{}[]!@#$^&*+=|\\\\/\"'?<>~`\\s\\t]*$");
+       album = album.replace(rsb, "");
+       album = album.replace(rfb, "");
+       album = album.replace(rrb, "");
+       album = album.replace(stripB, "");
+       album = album.replace(stripE, "");
+       album = album.replace("  ", " ");
+       album = album.replace("\t", " ");
+       album = album.toLower();
+       QByteArray first_hash = QCryptographicHash::hash(QString(" ").toUtf8(), QCryptographicHash::Md5).toHex();
+       QByteArray second_hash = QCryptographicHash::hash(QString(album).toUtf8(), QCryptographicHash::Md5).toHex();
+       return QString("album-%1-%2.jpeg").arg(first_hash.constData()).arg(second_hash.constData());
+}
index 54810dc..9ae928d 100644 (file)
@@ -49,6 +49,7 @@ namespace SomePlayer {
                        bool operator == (const Track &track) const;
                        bool operator >= (const Track &track) const; // comparing only title
                        bool operator < (const Track &track) const; // comparing only title
+                       QString mediaArtLocal();
 
                private:
                        TrackMetadata _metadata;