summaryrefslogtreecommitdiff
path: root/qmafwwatchlet
diff options
context:
space:
mode:
Diffstat (limited to 'qmafwwatchlet')
-rw-r--r--qmafwwatchlet/metawatch-digital.qml52
-rw-r--r--qmafwwatchlet/qmafwwatchlet.cpp45
-rw-r--r--qmafwwatchlet/qmafwwatchlet.h30
-rw-r--r--qmafwwatchlet/qmafwwatchlet.pro39
-rw-r--r--qmafwwatchlet/qmafwwatchlet.qrc5
-rw-r--r--qmafwwatchlet/qmafwwatchletplayer.cpp227
-rw-r--r--qmafwwatchlet/qmafwwatchletplayer.h81
-rw-r--r--qmafwwatchlet/qmafwwatchletplugin.cpp29
-rw-r--r--qmafwwatchlet/qmafwwatchletplugin.h24
9 files changed, 532 insertions, 0 deletions
diff --git a/qmafwwatchlet/metawatch-digital.qml b/qmafwwatchlet/metawatch-digital.qml
new file mode 100644
index 0000000..0ec07cd
--- /dev/null
+++ b/qmafwwatchlet/metawatch-digital.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.0
+
+Rectangle {
+ width: 96
+ height: 96
+
+ color: "white"
+
+ Image {
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ source: player.imageUrl
+ }
+
+ Rectangle {
+ x: 0
+ width: parent.width
+ height: 14
+ anchors.bottom: parent.bottom
+ color: "white"
+
+ Text {
+ anchors.fill: parent
+ text: player.title
+ color: "black"
+ }
+ }
+
+ Connections {
+ target: watch
+ onButtonPressed : {
+ switch(button) {
+ case 1:
+ player.volumeUp();
+ break;
+ case 2:
+ player.volumeDown();
+ break;
+ case 3:
+ player.playPause();
+ break;
+ case 4:
+ player.next();
+ break;
+ case 5:
+ player.previous();
+ break;
+ }
+ }
+ }
+}
diff --git a/qmafwwatchlet/qmafwwatchlet.cpp b/qmafwwatchlet/qmafwwatchlet.cpp
new file mode 100644
index 0000000..e2f41a2
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchlet.cpp
@@ -0,0 +1,45 @@
+#include <MafwShared.h>
+
+#include "qmafwwatchletplayer.h"
+#include "qmafwwatchlet.h"
+
+using namespace sowatch;
+
+class WatchletPlayer : public QObject
+{
+ Q_OBJECT
+};
+
+
+QMafwWatchlet::QMafwWatchlet(WatchServer* server) :
+ DeclarativeWatchlet(server, "com.javispedro.sowatch.qmafw"),
+ _registry(MafwRegistry::instance()),
+ _player(new QMafwWatchletPlayer(this))
+{
+ MafwShared* shared = MafwShared::instance();
+
+ connect(_registry, SIGNAL(rendererAdded(QString, QString)), SLOT(handleRendererAdded(QString)));
+ connect(_registry, SIGNAL(rendererRemoved(QString, QString)), SLOT(handleRendererRemoved(QString)));
+
+ shared->initTracking(_registry);
+
+ connect(this, SIGNAL(activated()), _player, SLOT(activate()));
+ connect(this, SIGNAL(deactivated()), _player, SLOT(deactivate()));
+
+ rootContext()->setContextProperty("player", _player);
+ setSource(QUrl("qrc:/qmafwwatchlet/" + server->watch()->model() + ".qml"));
+}
+
+void QMafwWatchlet::handleRendererAdded(const QString &uuid)
+{
+ if (uuid == "mafw_gst_renderer") {
+ _player->setRenderer(_registry->renderer(uuid));
+ }
+}
+
+void QMafwWatchlet::handleRendererRemoved(const QString &uuid)
+{
+ if (uuid == "mafw_gst_renderer") {
+ _player->setRenderer(0);
+ }
+}
diff --git a/qmafwwatchlet/qmafwwatchlet.h b/qmafwwatchlet/qmafwwatchlet.h
new file mode 100644
index 0000000..d3c2bd2
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchlet.h
@@ -0,0 +1,30 @@
+#ifndef QMAFWWATCHLET_H
+#define QMAFWWATCHLET_H
+
+#include <sowatch.h>
+
+#include <MafwRegistry.h>
+
+namespace sowatch
+{
+
+class QMafwWatchletPlayer;
+
+class QMafwWatchlet : public DeclarativeWatchlet
+{
+ Q_OBJECT
+public:
+ explicit QMafwWatchlet(WatchServer* server);
+
+private:
+ MafwRegistry* _registry;
+ QMafwWatchletPlayer* _player;
+
+private slots:
+ void handleRendererAdded(const QString & uuid);
+ void handleRendererRemoved(const QString & uuid);
+};
+
+}
+
+#endif // QMAFWWATCHLET_H
diff --git a/qmafwwatchlet/qmafwwatchlet.pro b/qmafwwatchlet/qmafwwatchlet.pro
new file mode 100644
index 0000000..2f8db66
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchlet.pro
@@ -0,0 +1,39 @@
+
+TARGET = qmafwwatchlet
+TEMPLATE = lib
+# CONFIG += plugin
+QT += dbus
+CONFIG += link_pkgconfig
+unix: PKGCONFIG += qmafw qmafw-shared
+
+SOURCES += qmafwwatchlet.cpp \
+ qmafwwatchletplugin.cpp \
+ qmafwwatchletplayer.cpp
+HEADERS += qmafwwatchlet.h \
+ qmafwwatchletplugin.h \
+ qmafwwatchletplayer.h
+
+unix: LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
+INCLUDEPATH += $$PWD/../libsowatch
+DEPENDPATH += $$PWD/../libsowatch
+
+unix:!symbian {
+ maemo5 {
+ target.path = /opt/sowatch/watchlets
+ } else {
+ target.path = /usr/lib/sowatch/watchlets
+ }
+ INSTALLS += target
+}
+
+OTHER_FILES += \
+ metawatch-digital.qml
+
+RESOURCES += \
+ qmafwwatchlet.qrc
+
+
+
+
+
+
diff --git a/qmafwwatchlet/qmafwwatchlet.qrc b/qmafwwatchlet/qmafwwatchlet.qrc
new file mode 100644
index 0000000..6b228a2
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchlet.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qmafwwatchlet">
+ <file>metawatch-digital.qml</file>
+ </qresource>
+</RCC>
diff --git a/qmafwwatchlet/qmafwwatchletplayer.cpp b/qmafwwatchlet/qmafwwatchletplayer.cpp
new file mode 100644
index 0000000..018795a
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletplayer.cpp
@@ -0,0 +1,227 @@
+#include <QtCore/QtDebug>
+#include <QtCore/QDir>
+#include <QtCore/QCryptographicHash>
+
+#include <MafwRenderer.h>
+#include <MafwMediaInfo.h>
+#include <MafwMetadata.h>
+
+#include "qmafwwatchlet.h"
+#include "qmafwwatchletplayer.h"
+
+using namespace sowatch;
+
+QMafwWatchletPlayer::QMafwWatchletPlayer(QMafwWatchlet* watchlet) :
+ QObject(watchlet),
+ _active(false),
+ _renderer(0),
+ _state(MafwRenderer::Stopped),
+ _title(tr("No media")),
+ _album(),
+ _imageUrl()
+{
+ Q_ASSERT(watchlet);
+}
+
+QString QMafwWatchletPlayer::title() const
+{
+ return _title;
+}
+
+QString QMafwWatchletPlayer::album() const
+{
+ return _album;
+}
+
+QString QMafwWatchletPlayer::artist() const
+{
+ return _artist;
+}
+
+QUrl QMafwWatchletPlayer::imageUrl() const
+{
+ return _imageUrl;
+}
+
+void QMafwWatchletPlayer::activate()
+{
+ _active = true;
+ reconnect();
+}
+
+void QMafwWatchletPlayer::deactivate()
+{
+ _active = false;
+ reconnect();
+}
+
+void QMafwWatchletPlayer::playPause()
+{
+ if (!_renderer) return;
+ if (_state == MafwRenderer::Playing) {
+ _renderer->pause();
+ } else if (_state == MafwRenderer::Paused) {
+ _renderer->resume();
+ } else {
+ _renderer->play();
+ }
+}
+
+void QMafwWatchletPlayer::play()
+{
+ if (!_renderer) return;
+ _renderer->play();
+}
+
+void QMafwWatchletPlayer::pause()
+{
+ if (!_renderer) return;
+ _renderer->pause();
+}
+
+void QMafwWatchletPlayer::stop()
+{
+ if (!_renderer) return;
+ _renderer->stop();
+}
+
+void QMafwWatchletPlayer::next()
+{
+ if (!_renderer) return;
+ qDebug() << "next";
+ _renderer->next();
+}
+
+void QMafwWatchletPlayer::previous()
+{
+ if (!_renderer) return;
+ _renderer->previous();
+}
+
+void QMafwWatchletPlayer::volumeUp()
+{
+ if (!_renderer) return;
+ QString prop("volume");
+ _renderer->mafwProperty(prop, qobject_cast<QObject*>(this), SLOT(doVolumeUp(QString,QVariant)));
+}
+
+void QMafwWatchletPlayer::volumeDown()
+{
+ if (!_renderer) return;
+ QString prop("volume");
+ _renderer->mafwProperty(prop, qobject_cast<QObject*>(this), SLOT(doVolumeDown(QString,QVariant)));
+}
+
+void QMafwWatchletPlayer::setRenderer(MafwRenderer * renderer)
+{
+ if (_renderer && _active) {
+ disconnect(_renderer, 0, this, 0);
+ }
+ _renderer = renderer;
+ reconnect();
+ if (!_renderer && _active) {
+ _imageUrl.clear();
+ _title = tr("No media");
+ emit imageUrlChanged();
+ emit titleChanged();
+ }
+}
+
+void QMafwWatchletPlayer::reconnect()
+{
+ if (_renderer && _active) {
+ connect(_renderer, SIGNAL(metadataChanged(const QString&, const QList<QVariant>&)),
+ this, SLOT(handleChangedMetadata(const QString&, const QList<QVariant>&)));
+ connect(_renderer, SIGNAL(stateChanged(MafwRenderer::State)),
+ this, SLOT(handleChangedState(MafwRenderer::State)));
+ _renderer->getCurrentMediaInfo(this, SLOT(handleMediaInfo(MafwMediaInfo)));
+ } else if (_renderer) {
+ disconnect(_renderer, 0, this, 0);
+ }
+}
+
+QString QMafwWatchletPlayer::stripAlbumArtComponent(const QString& component)
+{
+ static QRegExp rsb("\\[.*\\]");
+ static QRegExp rfb("{.*}");
+ static QRegExp rrb("\\(.*\\)");
+ static QRegExp stripB("^[()_{}[]!@#$^&*+=|\\\\/\"'?<>~`\\s\\t]*");
+ static QRegExp stripE("[()_{}[]!@#$^&*+=|\\\\/\"'?<>~`\\s\\t]*$");
+ QString s(component);
+ s = s.replace(rsb, "");
+ s = s.replace(rfb, "");
+ s = s.replace(rrb, "");
+ s = s.replace(stripB, "");
+ s = s.replace(stripE, "");
+ s = s.replace(" ", " ");
+ s = s.replace("\t", " ");
+ s = s.toLower();
+ return s;
+}
+
+QString QMafwWatchletPlayer::mediaArtPath() const
+{
+ QDir dir(QDir::homePath() + "/.cache/media-art/");
+ QString album = stripAlbumArtComponent(_album);
+ QString artist = stripAlbumArtComponent(_artist);
+ QByteArray first_hash = QCryptographicHash::hash(artist.toUtf8(), QCryptographicHash::Md5).toHex();
+ QByteArray second_hash = QCryptographicHash::hash(album.toUtf8(), QCryptographicHash::Md5).toHex();
+ QString file = QString("album-%1-%2.jpeg").arg(first_hash.constData()).arg(second_hash.constData());
+ qDebug() << "testing" << file;
+ if (dir.exists(file)) {
+ return dir.absoluteFilePath(file);
+ }
+
+ artist = " ";
+ first_hash = QCryptographicHash::hash(artist.toUtf8(), QCryptographicHash::Md5).toHex();
+ file = QString("album-%1-%2.jpeg").arg(first_hash.constData()).arg(second_hash.constData());
+ qDebug() << "testing" << file;
+ if (dir.exists(file)) {
+ return dir.absoluteFilePath(file);
+ }
+
+ return QString();
+}
+
+void QMafwWatchletPlayer::handleChangedMetadata(const QString &s, const QList<QVariant> &l)
+{
+ if (l.isEmpty()) return;
+ if (s == MAFW_METADATA_KEY_TITLE) {
+ _title = l[0].toString();
+ emit titleChanged();
+ } else if (s == MAFW_METADATA_KEY_ALBUM) {
+ _album = l[0].toString();
+ emit albumChanged();
+ _imageUrl = QUrl::fromLocalFile(mediaArtPath());
+ qDebug() << "got image url (album)" << _album << _imageUrl;
+ emit imageUrlChanged();
+ } else if (s == MAFW_METADATA_KEY_ARTIST) {
+ _artist = l[0].toString();
+ emit artistChanged();
+ _imageUrl = QUrl::fromLocalFile(mediaArtPath());
+ qDebug() << "got image url (artist)" << _album << _imageUrl;
+ emit imageUrlChanged();
+ }
+}
+
+void QMafwWatchletPlayer::handleChangedState(MafwRenderer::State state)
+{
+ _state = state;
+}
+
+void QMafwWatchletPlayer::handleMediaInfo(const MafwMediaInfo &info)
+{
+ const QMap<QString, QList<QVariant> > & data = info.metaData();
+ handleChangedMetadata(MAFW_METADATA_KEY_TITLE, data[MAFW_METADATA_KEY_TITLE]);
+ handleChangedMetadata(MAFW_METADATA_KEY_ALBUM, data[MAFW_METADATA_KEY_ALBUM]);
+}
+
+void QMafwWatchletPlayer::doVolumeUp(const QString& name, const QVariant& value)
+{
+ _renderer->setMafwProperty(name, value.toUInt() + 10);
+}
+
+void QMafwWatchletPlayer::doVolumeDown(const QString& name, const QVariant& value)
+{
+ _renderer->setMafwProperty(name, value.toUInt() - 10);
+}
diff --git a/qmafwwatchlet/qmafwwatchletplayer.h b/qmafwwatchlet/qmafwwatchletplayer.h
new file mode 100644
index 0000000..d85f38c
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletplayer.h
@@ -0,0 +1,81 @@
+#ifndef QMAFWWATCHLETPLAYER_H
+#define QMAFWWATCHLETPLAYER_H
+
+#include <QtCore/QUrl>
+
+#include <sowatch.h>
+
+#include <MafwRenderer.h>
+#include <MafwMediaInfo.h>
+
+namespace sowatch
+{
+
+class QMafwWatchlet;
+
+class QMafwWatchletPlayer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
+ Q_PROPERTY(QString album READ album NOTIFY albumChanged)
+ Q_PROPERTY(QString artist READ artist NOTIFY artistChanged)
+ Q_PROPERTY(QUrl imageUrl READ imageUrl NOTIFY imageUrlChanged)
+
+public:
+ explicit QMafwWatchletPlayer(QMafwWatchlet* watchlet);
+
+ QString title() const;
+ QString album() const;
+ QString artist() const;
+ QUrl imageUrl() const;
+
+signals:
+ void titleChanged();
+ void albumChanged();
+ void artistChanged();
+ void imageUrlChanged();
+
+public slots:
+ void activate();
+ void deactivate();
+
+ void playPause();
+ void play();
+ void pause();
+ void stop();
+ void next();
+ void previous();
+
+ void volumeUp();
+ void volumeDown();
+
+private:
+ bool _active;
+ MafwRenderer* _renderer;
+ MafwRenderer::State _state;
+ QString _title;
+ QString _album;
+ QString _artist;
+ QUrl _imageUrl;
+
+ void setRenderer(MafwRenderer*);
+ void reconnect();
+
+ static QString stripAlbumArtComponent(const QString& component);
+ QString mediaArtPath() const;
+
+private slots:
+ void handleChangedMetadata(const QString& s, const QList<QVariant>& l);
+ void handleChangedState(MafwRenderer::State state);
+ void handleMediaInfo(const MafwMediaInfo& info);
+ void doVolumeUp(const QString& name, const QVariant& value);
+ void doVolumeDown(const QString& name, const QVariant& value);
+
+ friend class QMafwWatchlet;
+};
+
+}
+
+QML_DECLARE_TYPE(sowatch::QMafwWatchletPlayer)
+
+#endif // QMAFWWATCHLETPLAYER_H
diff --git a/qmafwwatchlet/qmafwwatchletplugin.cpp b/qmafwwatchlet/qmafwwatchletplugin.cpp
new file mode 100644
index 0000000..09984b4
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletplugin.cpp
@@ -0,0 +1,29 @@
+#include "qmafwwatchlet.h"
+#include "qmafwwatchletplugin.h"
+
+using namespace sowatch;
+
+QMafwWatchletPlugin::QMafwWatchletPlugin(QObject *parent) :
+ QObject(parent)
+{
+}
+
+QMafwWatchletPlugin::~QMafwWatchletPlugin()
+{
+}
+
+QStringList QMafwWatchletPlugin::watchlets()
+{
+ QStringList l;
+ l << "com.javispedro.sowatch.qmafw";
+ return l;
+}
+
+Watchlet* QMafwWatchletPlugin::getWatchlet(const QString& driver, QSettings& settings, WatchServer *server)
+{
+ Q_UNUSED(driver);
+ Q_UNUSED(settings);
+ return new QMafwWatchlet(server);
+}
+
+Q_EXPORT_PLUGIN2(qmafwwatchlet, QMafwWatchletPlugin)
diff --git a/qmafwwatchlet/qmafwwatchletplugin.h b/qmafwwatchlet/qmafwwatchletplugin.h
new file mode 100644
index 0000000..c4ff3ef
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletplugin.h
@@ -0,0 +1,24 @@
+#ifndef QMAFWPLUGIN_H
+#define QMAFWPLUGIN_H
+
+#include <sowatch.h>
+
+namespace sowatch
+{
+
+class QMafwWatchletPlugin : public QObject, public WatchletPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(sowatch::WatchletPluginInterface)
+
+public:
+ explicit QMafwWatchletPlugin(QObject *parent = 0);
+ ~QMafwWatchletPlugin();
+
+ QStringList watchlets();
+ Watchlet* getWatchlet(const QString& driver, QSettings& settings, WatchServer* server);
+};
+
+}
+
+#endif // QMAFWPLUGIN_H