diff options
| author | Javier S. Pedro <maemo@javispedro.com> | 2012-09-04 03:27:30 +0200 | 
|---|---|---|
| committer | Javier S. Pedro <maemo@javispedro.com> | 2012-09-04 03:27:30 +0200 | 
| commit | 4e10566c9b0c4fb723ad68e44ae4c231e6959323 (patch) | |
| tree | 6f8aaa80a481b08e7827750e40b1c923ffc29046 | |
| parent | 2f631362b54180252d0daa34f359338860a8782b (diff) | |
| download | sowatch-4e10566c9b0c4fb723ad68e44ae4c231e6959323.tar.gz sowatch-4e10566c9b0c4fb723ad68e44ae4c231e6959323.zip | |
improve media player's watchlet volume change
| -rw-r--r-- | qmafwwatchlet/metawatch-digital.qml | 74 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchlet.cpp | 5 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchlet.h | 6 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchlet.pro | 10 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletplayer.cpp | 14 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletplayer.h | 2 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletplugin.cpp | 6 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletplugin.h | 2 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletvolumecontrol.cc | 251 | ||||
| -rw-r--r-- | qmafwwatchlet/qmafwwatchletvolumecontrol.h | 53 | ||||
| -rw-r--r-- | qmapwatchlet/qmapwatchletplugin.cpp | 2 | ||||
| -rw-r--r-- | sowatch.pro | 3 | 
12 files changed, 404 insertions, 24 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 diff --git a/qmapwatchlet/qmapwatchletplugin.cpp b/qmapwatchlet/qmapwatchletplugin.cpp index 32762d0..8f48539 100644 --- a/qmapwatchlet/qmapwatchletplugin.cpp +++ b/qmapwatchlet/qmapwatchletplugin.cpp @@ -42,7 +42,7 @@ WatchletPluginInterface::WatchletInfo QMapWatchletPlugin::describeWatchlet(const  		info.name = tr("Map");  		info.icon = QUrl::fromLocalFile(SOWATCH_QML_DIR "/qmapwatchlet/map-icon.png");  	} else if (id == CompassWatchlet::myId) { -		info.name = tr("Trip computer"); +		info.name = tr("Compass");  		info.icon = QUrl::fromLocalFile(SOWATCH_QML_DIR "/qmapwatchlet/compass-icon.png");  	}  	return info; diff --git a/sowatch.pro b/sowatch.pro index dc181de..3a0e025 100644 --- a/sowatch.pro +++ b/sowatch.pro @@ -9,8 +9,7 @@ metawatch.depends = libsowatch  # Some watchlets  SUBDIRS += notificationswatchlet sysinfowatchlet -SUBDIRS += qmsgwatchlet -SUBDIRS += qmapwatchlet +SUBDIRS += qmsgwatchlet qmapwatchlet  notificationswatchlet.depends = libsowatch  sysinfowatchlet.depends = libsowatch  qmsgwatchlet.depends = libsowatch | 
