diff options
Diffstat (limited to 'qmafwwatchlet')
-rw-r--r-- | qmafwwatchlet/metawatch-digital.qml | 52 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchlet.cpp | 45 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchlet.h | 30 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchlet.pro | 39 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchlet.qrc | 5 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchletplayer.cpp | 227 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchletplayer.h | 81 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchletplugin.cpp | 29 | ||||
-rw-r--r-- | qmafwwatchlet/qmafwwatchletplugin.h | 24 |
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 |