summaryrefslogtreecommitdiff
path: root/qmafwwatchlet
diff options
context:
space:
mode:
authorJavier S. Pedro <maemo@javispedro.com>2012-09-04 03:27:30 +0200
committerJavier S. Pedro <maemo@javispedro.com>2012-09-04 03:27:30 +0200
commit4e10566c9b0c4fb723ad68e44ae4c231e6959323 (patch)
tree6f8aaa80a481b08e7827750e40b1c923ffc29046 /qmafwwatchlet
parent2f631362b54180252d0daa34f359338860a8782b (diff)
downloadsowatch-4e10566c9b0c4fb723ad68e44ae4c231e6959323.tar.gz
sowatch-4e10566c9b0c4fb723ad68e44ae4c231e6959323.zip
improve media player's watchlet volume change
Diffstat (limited to 'qmafwwatchlet')
-rw-r--r--qmafwwatchlet/metawatch-digital.qml74
-rw-r--r--qmafwwatchlet/qmafwwatchlet.cpp5
-rw-r--r--qmafwwatchlet/qmafwwatchlet.h6
-rw-r--r--qmafwwatchlet/qmafwwatchlet.pro10
-rw-r--r--qmafwwatchlet/qmafwwatchletplayer.cpp14
-rw-r--r--qmafwwatchlet/qmafwwatchletplayer.h2
-rw-r--r--qmafwwatchlet/qmafwwatchletplugin.cpp6
-rw-r--r--qmafwwatchlet/qmafwwatchletplugin.h2
-rw-r--r--qmafwwatchlet/qmafwwatchletvolumecontrol.cc251
-rw-r--r--qmafwwatchlet/qmafwwatchletvolumecontrol.h53
10 files changed, 402 insertions, 21 deletions
diff --git a/qmafwwatchlet/metawatch-digital.qml b/qmafwwatchlet/metawatch-digital.qml
index d9370a6..02a5460 100644
--- a/qmafwwatchlet/metawatch-digital.qml
+++ b/qmafwwatchlet/metawatch-digital.qml
@@ -38,16 +38,82 @@ Rectangle {
}
}
+ Rectangle {
+ id: volumeBar
+ width: 18
+
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+
+ color: "white"
+
+ visible: false
+
+ Image {
+ id: volumeIcon
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: 2
+
+ source: "volume.png"
+ }
+
+ Rectangle {
+ id: volumeBarBox
+
+ anchors.top: volumeIcon.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: 2
+
+ color: "black"
+
+ Rectangle {
+ id: volumeBarThing
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 4
+
+ visible: volumeBar.visible
+ height: (volumeControl.volume * (parent.height - anchors.margins*2)) / (volumeControl.max - volumeControl.min)
+
+ color: "white"
+ }
+ }
+
+ Timer {
+ id: autoHideTimer
+ interval: 3000
+ repeat: false
+ onTriggered: {
+ volumeBar.visible = false;
+ }
+ }
+
+ function show() {
+ volumeBar.visible = true;
+ autoHideTimer.restart();
+ }
+ }
+
Connections {
target: watch
onButtonPressed : {
switch(button) {
- case 1:
- player.volumeUp();
+ case 1: {
+ volumeControl.up();
+ volumeBar.show();
break;
- case 2:
- player.volumeDown();
+ }
+ case 2: {
+ volumeControl.down();
+ volumeBar.show();
break;
+ }
case 4:
player.playPause();
break;
diff --git a/qmafwwatchlet/qmafwwatchlet.cpp b/qmafwwatchlet/qmafwwatchlet.cpp
index fb537a6..84c5ea9 100644
--- a/qmafwwatchlet/qmafwwatchlet.cpp
+++ b/qmafwwatchlet/qmafwwatchlet.cpp
@@ -1,6 +1,7 @@
#include <MafwShared.h>
#include "qmafwwatchletplayer.h"
+#include "qmafwwatchletvolumecontrol.h"
#include "qmafwwatchlet.h"
using namespace sowatch;
@@ -8,7 +9,8 @@ using namespace sowatch;
QMafwWatchlet::QMafwWatchlet(WatchServer* server) :
DeclarativeWatchlet(server, "com.javispedro.sowatch.qmafw"),
_registry(MafwRegistry::instance()),
- _player(new QMafwWatchletPlayer(this))
+ _player(new QMafwWatchletPlayer(this)),
+ _volumeControl(new QMafwWatchletVolumeControl(this))
{
MafwShared* shared = MafwShared::instance();
@@ -21,6 +23,7 @@ QMafwWatchlet::QMafwWatchlet(WatchServer* server) :
connect(this, SIGNAL(deactivated()), _player, SLOT(deactivate()));
rootContext()->setContextProperty("player", _player);
+ rootContext()->setContextProperty("volumeControl", _volumeControl);
setSource(QUrl(SOWATCH_QML_DIR "/qmafwwatchlet/" + server->watch()->model() + ".qml"));
}
diff --git a/qmafwwatchlet/qmafwwatchlet.h b/qmafwwatchlet/qmafwwatchlet.h
index d3c2bd2..09cdf81 100644
--- a/qmafwwatchlet/qmafwwatchlet.h
+++ b/qmafwwatchlet/qmafwwatchlet.h
@@ -9,6 +9,7 @@ namespace sowatch
{
class QMafwWatchletPlayer;
+class QMafwWatchletVolumeControl;
class QMafwWatchlet : public DeclarativeWatchlet
{
@@ -17,8 +18,9 @@ public:
explicit QMafwWatchlet(WatchServer* server);
private:
- MafwRegistry* _registry;
- QMafwWatchletPlayer* _player;
+ MafwRegistry *_registry;
+ QMafwWatchletPlayer *_player;
+ QMafwWatchletVolumeControl *_volumeControl;
private slots:
void handleRendererAdded(const QString & uuid);
diff --git a/qmafwwatchlet/qmafwwatchlet.pro b/qmafwwatchlet/qmafwwatchlet.pro
index 4a59ff5..8dc89d4 100644
--- a/qmafwwatchlet/qmafwwatchlet.pro
+++ b/qmafwwatchlet/qmafwwatchlet.pro
@@ -4,16 +4,18 @@ TEMPLATE = lib
CONFIG += plugin
QT += dbus
CONFIG += link_pkgconfig
-PKGCONFIG += qmafw qmafw-shared
+PKGCONFIG += dbus-glib-1 qmafw qmafw-shared
SOURCES += qmafwwatchlet.cpp \
qmafwwatchletplugin.cpp \
- qmafwwatchletplayer.cpp
+ qmafwwatchletplayer.cpp \
+ qmafwwatchletvolumecontrol.cc
HEADERS += qmafwwatchlet.h \
qmafwwatchletplugin.h \
- qmafwwatchletplayer.h
+ qmafwwatchletplayer.h \
+ qmafwwatchletvolumecontrol.h
-qml_files.files = metawatch-digital.qml icon.png
+qml_files.files = metawatch-digital.qml icon.png volume.png
LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch
INCLUDEPATH += $$PWD/../libsowatch
diff --git a/qmafwwatchlet/qmafwwatchletplayer.cpp b/qmafwwatchlet/qmafwwatchletplayer.cpp
index 8f51fbf..0e8b436 100644
--- a/qmafwwatchlet/qmafwwatchletplayer.cpp
+++ b/qmafwwatchlet/qmafwwatchletplayer.cpp
@@ -11,6 +11,8 @@
using namespace sowatch;
+const QLatin1String QMafwWatchletPlayer::_volumeProp("volume");
+
QMafwWatchletPlayer::QMafwWatchletPlayer(QMafwWatchlet* watchlet) :
QObject(watchlet),
_active(false),
@@ -102,15 +104,19 @@ void QMafwWatchletPlayer::previous()
void QMafwWatchletPlayer::volumeUp()
{
if (!_renderer) return;
- QString prop("volume");
- _renderer->mafwProperty(prop, qobject_cast<QObject*>(this), SLOT(doVolumeUp(QString,QVariant)));
+ QString prop(_volumeProp);
+ _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)));
+ QString prop(_volumeProp);
+ _renderer->mafwProperty(prop,
+ qobject_cast<QObject*>(this),
+ SLOT(doVolumeDown(QString,QVariant)));
}
void QMafwWatchletPlayer::setRenderer(MafwRenderer * renderer)
diff --git a/qmafwwatchlet/qmafwwatchletplayer.h b/qmafwwatchlet/qmafwwatchletplayer.h
index 625635c..fe79689 100644
--- a/qmafwwatchlet/qmafwwatchletplayer.h
+++ b/qmafwwatchlet/qmafwwatchletplayer.h
@@ -60,6 +60,8 @@ private:
QString _rendererArt;
QUrl _mediaArt;
+ static const QLatin1String _volumeProp;
+
void setRenderer(MafwRenderer*);
void reconnect();
diff --git a/qmafwwatchlet/qmafwwatchletplugin.cpp b/qmafwwatchlet/qmafwwatchletplugin.cpp
index 713c199..f2ec355 100644
--- a/qmafwwatchlet/qmafwwatchletplugin.cpp
+++ b/qmafwwatchlet/qmafwwatchletplugin.cpp
@@ -8,10 +8,6 @@ QMafwWatchletPlugin::QMafwWatchletPlugin(QObject *parent) :
{
}
-QMafwWatchletPlugin::~QMafwWatchletPlugin()
-{
-}
-
QStringList QMafwWatchletPlugin::watchlets()
{
QStringList l;
@@ -23,7 +19,7 @@ WatchletPluginInterface::WatchletInfo QMafwWatchletPlugin::describeWatchlet(cons
{
WatchletInfo info;
if (id != "com.javispedro.sowatch.qmafw") return info;
- info.name = "Music player";
+ info.name = tr("Music player");
info.icon = QUrl::fromLocalFile(SOWATCH_QML_DIR "/qmafwwatchlet/icon.png");
return info;
}
diff --git a/qmafwwatchlet/qmafwwatchletplugin.h b/qmafwwatchlet/qmafwwatchletplugin.h
index 11e99af..7087a1a 100644
--- a/qmafwwatchlet/qmafwwatchletplugin.h
+++ b/qmafwwatchlet/qmafwwatchletplugin.h
@@ -1,6 +1,7 @@
#ifndef QMAFWPLUGIN_H
#define QMAFWPLUGIN_H
+#include <QtDBus/QDBusConnection>
#include <sowatch.h>
namespace sowatch
@@ -13,7 +14,6 @@ class QMafwWatchletPlugin : public QObject, public WatchletPluginInterface
public:
explicit QMafwWatchletPlugin(QObject *parent = 0);
- ~QMafwWatchletPlugin();
QStringList watchlets();
WatchletInfo describeWatchlet(const QString &id);
diff --git a/qmafwwatchlet/qmafwwatchletvolumecontrol.cc b/qmafwwatchlet/qmafwwatchletvolumecontrol.cc
new file mode 100644
index 0000000..f4876a8
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletvolumecontrol.cc
@@ -0,0 +1,251 @@
+#include <QtCore/QDebug>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "qmafwwatchletvolumecontrol.h"
+
+#define DEFAULT_ADDRESS "unix:path=/var/run/pulse/dbus-socket"
+
+#define VOLUME_SV "com.Nokia.MainVolume1"
+#define VOLUME_PATH "/com/meego/mainvolume1"
+#define VOLUME_IF "com.Nokia.MainVolume1"
+
+using namespace sowatch;
+
+QMafwWatchletVolumeControl::QMafwWatchletVolumeControl(QObject *parent) :
+ QObject(parent), _conn(0), _curStep(0), _maxStep(1)
+{
+ _openConnection();
+}
+
+QMafwWatchletVolumeControl::~QMafwWatchletVolumeControl()
+{
+ if (_conn) {
+ dbus_connection_remove_filter(_conn, handleDBusSignal, this);
+ dbus_connection_unref(_conn);
+ }
+}
+
+int QMafwWatchletVolumeControl::volume() const
+{
+ return _curStep;
+}
+
+int QMafwWatchletVolumeControl::max() const
+{
+ return _maxStep - 1;
+}
+
+int QMafwWatchletVolumeControl::min() const
+{
+ return 0;
+}
+
+void QMafwWatchletVolumeControl::setVolume(int vol)
+{
+ if (!_conn) return;
+ DBusMessage *msg;
+ quint32 value = vol;
+ const char *volume_if = VOLUME_IF;
+ const char *prop = "CurrentStep";
+
+ msg = dbus_message_new_method_call(VOLUME_SV, VOLUME_PATH,
+ "org.freedesktop.DBus.Properties", "Set");
+ Q_ASSERT(msg);
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &volume_if,
+ DBUS_TYPE_STRING, &prop,
+ DBUS_TYPE_INVALID);
+
+ DBusMessageIter iter, iter_variant;
+ dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_open_container(&iter,
+ DBUS_TYPE_VARIANT,
+ DBUS_TYPE_UINT32_AS_STRING,
+ &iter_variant);
+ dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &value);
+ dbus_message_iter_close_container(&iter, &iter_variant);
+
+ dbus_connection_send(_conn, msg, 0);
+
+ dbus_message_unref(msg);
+}
+
+void QMafwWatchletVolumeControl::up()
+{
+ if (_curStep < _maxStep - 1) {
+ setVolume(_curStep + 1);
+ }
+}
+
+void QMafwWatchletVolumeControl::down()
+{
+ if (_curStep > 0) {
+ setVolume(_curStep - 1);
+ }
+}
+
+void QMafwWatchletVolumeControl::_openConnection()
+{
+ DBusError err;
+
+ // Allow for an alternative PulseAudio D-Bus server address
+ char *pa_bus_address = getenv("PULSE_DBUS_SERVER");
+ if (!pa_bus_address)
+ pa_bus_address = (char *) DEFAULT_ADDRESS;
+
+ dbus_error_init(&err);
+
+ _conn = dbus_connection_open(pa_bus_address, &err);
+ if (!_conn) {
+ qWarning() << "Failed to open connection to PulseAudio D-Bus server:"
+ << err.message;
+ return;
+ }
+
+ dbus_connection_setup_with_g_main(_conn, NULL);
+ dbus_connection_add_filter(_conn, handleDBusSignal, this, 0);
+
+ _listenForSignal();
+ _fetchValues();
+}
+
+void QMafwWatchletVolumeControl::_listenForSignal()
+{
+ DBusMessage *msg;
+ const char *signal = "com.Nokia.MainVolume1.StepsUpdated";
+ char **empty_array = { 0 };
+
+ msg = dbus_message_new_method_call(NULL, "/org/pulseaudio/core1", NULL,
+ "ListenForSignal");
+
+ if (!msg) {
+ qWarning() << "Cannot create ListenForSignal message";
+ return;
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &signal,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &empty_array, 0,
+ DBUS_TYPE_INVALID);
+ dbus_connection_send(_conn, msg, 0);
+
+ dbus_message_unref(msg);
+}
+
+void QMafwWatchletVolumeControl::_fetchValues()
+{
+ DBusMessage *msg, *reply;
+ DBusError err;
+
+ dbus_error_init(&err);
+
+ msg = dbus_message_new_method_call(VOLUME_SV, VOLUME_PATH,
+ "org.freedesktop.DBus.Properties",
+ "GetAll");
+ if (!msg) {
+ qWarning() << "Cannot create GetAll message";
+ return;
+ }
+
+
+ const char *volume_if = VOLUME_IF;
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &volume_if,
+ DBUS_TYPE_INVALID);
+
+ DBusPendingCall *pending;
+ if (!dbus_connection_send_with_reply(_conn, msg, &pending, -1)) {
+ qWarning() << "Cannot send GetAll message";
+ return;
+ }
+
+ dbus_message_unref(msg);
+
+ if (pending) {
+ if (!dbus_pending_call_set_notify(pending, handleFetchReply, this, 0)) {
+ qWarning() << "Cannot set GetAll notify";
+ return;
+ }
+ }
+}
+
+void QMafwWatchletVolumeControl::handleFetchReply(DBusPendingCall *pending, void *user_data)
+{
+ QMafwWatchletVolumeControl *self = static_cast<QMafwWatchletVolumeControl*>(user_data);
+ DBusMessage *reply = dbus_pending_call_steal_reply(pending);
+
+ if (!reply || dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+ qWarning() << "Received something that is not a method return";
+ }
+
+ DBusMessageIter iter;
+ dbus_message_iter_init(reply, &iter);
+ while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
+ DBusMessageIter iter_dict;
+ Q_ASSERT(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
+ dbus_message_iter_recurse(&iter, &iter_dict);
+
+ while (dbus_message_iter_get_arg_type(&iter_dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter iter_entry;
+ Q_ASSERT(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY);
+ dbus_message_iter_recurse(&iter_dict, &iter_entry);
+
+ char *prop_name;
+ Q_ASSERT(dbus_message_iter_get_arg_type(&iter_entry) == DBUS_TYPE_STRING);
+ dbus_message_iter_get_basic(&iter_entry, &prop_name);
+ dbus_message_iter_next(&iter_entry);
+
+ Q_ASSERT(dbus_message_iter_get_arg_type(&iter_entry) == DBUS_TYPE_VARIANT);
+ DBusMessageIter iter_variant;
+ dbus_message_iter_recurse(&iter_entry, &iter_variant);
+
+ if (prop_name &&
+ dbus_message_iter_get_arg_type(&iter_variant) == DBUS_TYPE_UINT32) {
+ quint32 value;
+ dbus_message_iter_get_basic(&iter_variant, &value);
+
+ if (strcmp(prop_name, "StepCount")) {
+ self->_maxStep = value;
+ } else if (strcmp(prop_name, "CurrentStep")) {
+ self->_curStep = value;
+ }
+ qDebug() << prop_name << value;
+ }
+
+ dbus_message_iter_next(&iter_dict);
+ }
+
+ dbus_message_iter_next(&iter);
+ }
+
+ emit self->maxChanged();
+ emit self->volumeChanged();
+
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+DBusHandlerResult QMafwWatchletVolumeControl::handleDBusSignal(DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ QMafwWatchletVolumeControl *self = static_cast<QMafwWatchletVolumeControl*>(user_data);
+ if (dbus_message_is_signal(message, VOLUME_IF, "StepsUpdated")) {
+ DBusError err;
+ quint32 curStep, maxStep;
+
+ dbus_error_init(&err);
+ if (dbus_message_get_args(message, &err,
+ DBUS_TYPE_UINT32, &maxStep,
+ DBUS_TYPE_UINT32, &curStep,
+ DBUS_TYPE_INVALID)) {
+ if (self->_maxStep != maxStep) {
+ self->_maxStep = maxStep;
+ emit self->maxChanged();
+ }
+ if (self->_curStep != curStep) {
+ self->_curStep = curStep;
+ emit self->volumeChanged();
+ }
+ }
+ }
+}
diff --git a/qmafwwatchlet/qmafwwatchletvolumecontrol.h b/qmafwwatchlet/qmafwwatchletvolumecontrol.h
new file mode 100644
index 0000000..1e1261a
--- /dev/null
+++ b/qmafwwatchlet/qmafwwatchletvolumecontrol.h
@@ -0,0 +1,53 @@
+#ifndef QMAFWWATCHLETVOLUMECONTROL_H
+#define QMAFWWATCHLETVOLUMECONTROL_H
+
+#include <QtCore/QObject>
+#include <dbus/dbus.h>
+
+class MainVolumeControlProxy;
+
+namespace sowatch
+{
+
+class QMafwWatchletVolumeControl : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged)
+ Q_PROPERTY(int min READ min NOTIFY minChanged)
+ Q_PROPERTY(int max READ max NOTIFY maxChanged)
+
+public:
+ explicit QMafwWatchletVolumeControl(QObject *parent = 0);
+ ~QMafwWatchletVolumeControl();
+
+ int volume() const;
+ int min() const;
+ int max() const;
+
+ void setVolume(int vol);
+
+signals:
+ void volumeChanged();
+ void minChanged();
+ void maxChanged();
+
+public slots:
+ void up();
+ void down();
+
+private:
+ void _openConnection();
+ void _listenForSignal();
+ void _fetchValues();
+ static void handleFetchReply(DBusPendingCall *pending, void *user_data);
+ static DBusHandlerResult handleDBusSignal(DBusConnection *connection, DBusMessage *message, void *user_data);
+
+private:
+ DBusConnection *_conn;
+ uint _curStep;
+ uint _maxStep;
+};
+
+}
+
+#endif // QMAFWWATCHLETVOLUMECONTROL_H