2012-11-27 12:51:20

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 1/6] gdbus: Add g_dbus_add_properties_watch function

From: Luiz Augusto von Dentz <[email protected]>

Convenient function to create watches for D-Bus properties.
---
gdbus/gdbus.h | 5 +++++
gdbus/watch.c | 28 ++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index ba49621..8b6dfe5 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -243,6 +243,11 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
const char *interface, const char *member,
GDBusSignalFunction function, void *user_data,
GDBusDestroyFunction destroy);
+guint g_dbus_add_properties_watch(DBusConnection *connection,
+ const char *sender, const char *path,
+ const char *interface,
+ GDBusSignalFunction function, void *user_data,
+ GDBusDestroyFunction destroy);
gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
void g_dbus_remove_all_watches(DBusConnection *connection);

diff --git a/gdbus/watch.c b/gdbus/watch.c
index 1cd1211..9e4f994 100644
--- a/gdbus/watch.c
+++ b/gdbus/watch.c
@@ -752,6 +752,34 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
return cb->id;
}

+guint g_dbus_add_properties_watch(DBusConnection *connection,
+ const char *sender, const char *path,
+ const char *interface,
+ GDBusSignalFunction function, void *user_data,
+ GDBusDestroyFunction destroy)
+{
+ struct filter_data *data;
+ struct filter_callback *cb;
+
+ data = filter_data_get(connection, signal_filter, sender, path,
+ DBUS_INTERFACE_PROPERTIES, "PropertiesChanged",
+ interface);
+ if (data == NULL)
+ return 0;
+
+ cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
+ user_data);
+ if (cb == NULL)
+ return 0;
+
+ if (data->name != NULL && data->name_watch == 0)
+ data->name_watch = g_dbus_add_service_watch(connection,
+ data->name, NULL,
+ NULL, NULL, NULL);
+
+ return cb->id;
+}
+
gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
{
struct filter_data *data;
--
1.7.11.7



2012-11-30 08:31:32

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/6] gdbus: Add g_dbus_add_properties_watch function

Hi Luiz,

On Tue, Nov 27, 2012, Luiz Augusto von Dentz wrote:
> Convenient function to create watches for D-Bus properties.
> ---
> gdbus/gdbus.h | 5 +++++
> gdbus/watch.c | 28 ++++++++++++++++++++++++++++
> 2 files changed, 33 insertions(+)

All patches in this set have been applied. Thanks.

Johan

2012-11-29 13:10:58

by Lucas De Marchi

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/6] gdbus: Add g_dbus_add_properties_watch function

On Thu, Nov 29, 2012 at 6:52 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Lucas, Marcel,
>
> On Tue, Nov 27, 2012 at 2:51 PM, Luiz Augusto von Dentz
> <[email protected]> wrote:
>> From: Luiz Augusto von Dentz <[email protected]>
>>
>> Convenient function to create watches for D-Bus properties.
>> ---
>> gdbus/gdbus.h | 5 +++++
>> gdbus/watch.c | 28 ++++++++++++++++++++++++++++
>> 2 files changed, 33 insertions(+)
>>
>> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
>> index ba49621..8b6dfe5 100644
>> --- a/gdbus/gdbus.h
>> +++ b/gdbus/gdbus.h
>> @@ -243,6 +243,11 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>> const char *interface, const char *member,
>> GDBusSignalFunction function, void *user_data,
>> GDBusDestroyFunction destroy);
>> +guint g_dbus_add_properties_watch(DBusConnection *connection,
>> + const char *sender, const char *path,
>> + const char *interface,
>> + GDBusSignalFunction function, void *user_data,
>> + GDBusDestroyFunction destroy);
>> gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
>> void g_dbus_remove_all_watches(DBusConnection *connection);
>>
>> diff --git a/gdbus/watch.c b/gdbus/watch.c
>> index 1cd1211..9e4f994 100644
>> --- a/gdbus/watch.c
>> +++ b/gdbus/watch.c
>> @@ -752,6 +752,34 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>> return cb->id;
>> }
>>
>> +guint g_dbus_add_properties_watch(DBusConnection *connection,
>> + const char *sender, const char *path,
>> + const char *interface,
>> + GDBusSignalFunction function, void *user_data,
>> + GDBusDestroyFunction destroy)
>> +{
>> + struct filter_data *data;
>> + struct filter_callback *cb;
>> +
>> + data = filter_data_get(connection, signal_filter, sender, path,
>> + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged",
>> + interface);
>> + if (data == NULL)
>> + return 0;
>> +
>> + cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
>> + user_data);
>> + if (cb == NULL)
>> + return 0;
>> +
>> + if (data->name != NULL && data->name_watch == 0)
>> + data->name_watch = g_dbus_add_service_watch(connection,
>> + data->name, NULL,
>> + NULL, NULL, NULL);
>> +
>> + return cb->id;
>> +}
>> +
>> gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
>> {
>> struct filter_data *data;
>> --
>> 1.7.11.7
>
> Anything regarding this function? The point here is to be able to
> listen to properties specific to one interface which is not possible
> with g_dbus_add_signal_watch.

Ack

Lucas De Marchi

2012-11-29 08:52:28

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 1/6] gdbus: Add g_dbus_add_properties_watch function

Hi Lucas, Marcel,

On Tue, Nov 27, 2012 at 2:51 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> Convenient function to create watches for D-Bus properties.
> ---
> gdbus/gdbus.h | 5 +++++
> gdbus/watch.c | 28 ++++++++++++++++++++++++++++
> 2 files changed, 33 insertions(+)
>
> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
> index ba49621..8b6dfe5 100644
> --- a/gdbus/gdbus.h
> +++ b/gdbus/gdbus.h
> @@ -243,6 +243,11 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
> const char *interface, const char *member,
> GDBusSignalFunction function, void *user_data,
> GDBusDestroyFunction destroy);
> +guint g_dbus_add_properties_watch(DBusConnection *connection,
> + const char *sender, const char *path,
> + const char *interface,
> + GDBusSignalFunction function, void *user_data,
> + GDBusDestroyFunction destroy);
> gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
> void g_dbus_remove_all_watches(DBusConnection *connection);
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index 1cd1211..9e4f994 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -752,6 +752,34 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
> return cb->id;
> }
>
> +guint g_dbus_add_properties_watch(DBusConnection *connection,
> + const char *sender, const char *path,
> + const char *interface,
> + GDBusSignalFunction function, void *user_data,
> + GDBusDestroyFunction destroy)
> +{
> + struct filter_data *data;
> + struct filter_callback *cb;
> +
> + data = filter_data_get(connection, signal_filter, sender, path,
> + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged",
> + interface);
> + if (data == NULL)
> + return 0;
> +
> + cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
> + user_data);
> + if (cb == NULL)
> + return 0;
> +
> + if (data->name != NULL && data->name_watch == 0)
> + data->name_watch = g_dbus_add_service_watch(connection,
> + data->name, NULL,
> + NULL, NULL, NULL);
> +
> + return cb->id;
> +}
> +
> gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
> {
> struct filter_data *data;
> --
> 1.7.11.7

Anything regarding this function? The point here is to be able to
listen to properties specific to one interface which is not possible
with g_dbus_add_signal_watch.


--
Luiz Augusto von Dentz

2012-11-27 12:51:25

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 6/6] test: Convert simple-player to use DBus properties interface

From: Luiz Augusto von Dentz <[email protected]>

---
test/simple-player | 40 ++++++++++++++++++++++------------------
1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/test/simple-player b/test/simple-player
index 9e72f3e..0037f3a 100755
--- a/test/simple-player
+++ b/test/simple-player
@@ -17,14 +17,16 @@ class Player(dbus.service.Object):
bus = dbus.SystemBus()
mp = dbus.Interface(bus.get_object("org.bluez", obj),
"org.bluez.MediaPlayer")
+ prop = dbus.Interface(bus.get_object("org.bluez", obj),
+ "org.freedesktop.DBus.Properties")

- self.properties = mp.GetProperties()
+ self.properties = prop.GetAll("org.bluez.MediaPlayer")
self.metadata = mp.GetTrack()

- bus.add_signal_receiver(self.property_changed,
+ bus.add_signal_receiver(self.properties_changed,
path = obj,
- dbus_interface = "org.bluez.MediaPlayer",
- signal_name = "PropertyChanged")
+ dbus_interface = "org.freedesktop.DBus.Properties",
+ signal_name = "PropertiesChanged")

bus.add_signal_receiver(self.track_changed,
path = obj,
@@ -59,18 +61,20 @@ class Player(dbus.service.Object):
print("Release")
mainloop.quit()

- @dbus.service.method("org.bluez.MediaPlayer",
- in_signature="sv", out_signature="")
- def SetProperty(self, key, value):
- print("SetProperty (%s, %s)" % (key, value), file=sys.stderr)
+ @dbus.service.method("org.freedesktop.DBus.Properties",
+ in_signature="ssv", out_signature="")
+ def Set(self, interface, key, value):
+ print("Set (%s, %s)" % (key, value), file=sys.stderr)
return

- @dbus.service.signal("org.bluez.MediaPlayer", signature="sv")
- def PropertyChanged(self, setting, value):
- """PropertyChanged(setting, value)
+ @dbus.service.signal("org.freedesktop.DBus.Properties",
+ signature="sa{sv}as")
+ def PropertiesChanged(self, interface, properties,
+ invalidated = dbus.Array()):
+ """PropertiesChanged(interface, properties, invalidated)

- Send a PropertyChanged signal. 'setting' and 'value' are
- string parameters as specified in doc/media-api.txt.
+ Send a PropertiesChanged signal. 'properties' is a dictionary
+ containing string parameters as specified in doc/media-api.txt.
"""
pass

@@ -86,10 +90,10 @@ class Player(dbus.service.Object):
def help(self, func):
help(self.__class__.__dict__[func])

- def property_changed(self, setting, value):
- print("property_changed(%s, %s)" % (setting, value))
+ def properties_changed(self, interface, properties, invalidated):
+ print("properties_changed(%s, %s)" % (properties, invalidated))

- self.PropertyChanged(setting, value)
+ self.PropertiesChanged(interface, properties, invalidated)

def track_changed(self, metadata):
print("track_changed(%s)" % (metadata))
@@ -98,8 +102,8 @@ class Player(dbus.service.Object):

class InputHandler:
commands = { 'TrackChanged': '(metadata)',
- 'PropertyChanged': '(key, value)',
- 'help': '(cmd)' }
+ 'PropertiesChanged': '(interface, properties)',
+ 'help': '(cmd)' }
def __init__(self, player):
self.player = player
print('\n\nAvailable commands:')
--
1.7.11.7


2012-11-27 12:51:24

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 5/6] test: Convert mpris-player to use DBus properties interface

From: Luiz Augusto von Dentz <[email protected]>

---
test/mpris-player.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/test/mpris-player.c b/test/mpris-player.c
index 13f5c85..7985cdd 100644
--- a/test/mpris-player.c
+++ b/test/mpris-player.c
@@ -114,17 +114,18 @@ static void dict_append_entry(DBusMessageIter *dict, const char *key, int type,
dbus_message_iter_close_container(dict, &entry);
}

-static dbus_bool_t emit_property_changed(DBusConnection *conn,
+static dbus_bool_t emit_properties_changed(DBusConnection *conn,
const char *path,
const char *interface,
const char *name,
int type, void *value)
{
DBusMessage *signal;
- DBusMessageIter iter;
+ DBusMessageIter iter, dict, entry, array;
dbus_bool_t result;

- signal = dbus_message_new_signal(path, interface, "PropertyChanged");
+ signal = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES,
+ "PropertiesChanged");

if (!signal) {
fprintf(stderr, "Unable to allocate new %s.PropertyChanged"
@@ -133,10 +134,23 @@ static dbus_bool_t emit_property_changed(DBusConnection *conn,
}

dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
+ &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name);
+ append_variant(&entry, type, value);
+ dbus_message_iter_close_container(&dict, &entry);

- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_close_container(&iter, &dict);

- append_variant(&iter, type, value);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+ dbus_message_iter_close_container(&iter, &array);

result = dbus_connection_send(conn, signal, NULL);
dbus_message_unref(signal);
@@ -171,7 +185,7 @@ static int parse_property(DBusConnection *conn, const char *path,
dict_append_entry(properties, "Status",
DBUS_TYPE_STRING, &value);
else
- emit_property_changed(sys, path,
+ emit_properties_changed(sys, path,
"org.bluez.MediaPlayer", "Status",
DBUS_TYPE_STRING, &value);
} else if (strcasecmp(key, "Position") == 0) {
@@ -188,7 +202,7 @@ static int parse_property(DBusConnection *conn, const char *path,
dict_append_entry(properties, "Position",
DBUS_TYPE_UINT32, &msec);
else
- emit_property_changed(sys, path,
+ emit_properties_changed(sys, path,
"org.bluez.MediaPlayer", "Position",
DBUS_TYPE_UINT32, &msec);
} else if (strcasecmp(key, "Shuffle") == 0) {
@@ -206,9 +220,9 @@ static int parse_property(DBusConnection *conn, const char *path,
dict_append_entry(properties, "Shuffle",
DBUS_TYPE_STRING, &str);
else
- emit_property_changed(sys, path,
+ emit_properties_changed(sys, path,
"org.bluez.MediaPlayer", "Shuffle",
- DBUS_TYPE_UINT32, &str);
+ DBUS_TYPE_STRING, &str);
}

return 0;
--
1.7.11.7


2012-11-27 12:51:23

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 4/6] media-api: Update documentation of MediaPlayer interface

From: Luiz Augusto von Dentz <[email protected]>

---
doc/media-api.txt | 21 ++-------------------
1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/doc/media-api.txt b/doc/media-api.txt
index b4f2fc6..a814b60 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -133,24 +133,12 @@ Object path freely definable (Target role)
[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/playerX
(Controller role)

-Methods dict GetProperties()
-
- Returns all properties for the interface. See the
- properties section for available properties.
-
- dict GetTrack()
+Methods dict GetTrack()

Returns known metadata of the current track.

See TrackChanged for possible values.

- void SetProperty(string property, variant value)
-
- Changes the value of the specified property. Only
- properties that are listed as read-write can be changed.
-
- On success this will emit a PropertyChanged signal.
-
void Release()

This method gets called when the service daemon
@@ -159,12 +147,7 @@ Methods dict GetProperties()
player, because when this method gets called it has
already been unregistered.

-Signals PropertyChanged(string setting, variant value)
-
- This signal indicates a changed value of the given
- property.
-
- TrackChanged(dict metadata)
+Signals TrackChanged(dict metadata)

This signal indicates that current track has changed.
All available metadata for the new track shall be set
--
1.7.11.7


2012-11-27 12:51:22

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 3/6] media: Convert target MediaPlayer interface to use D-Bus Properties

From: Luiz Augusto von Dentz <[email protected]>

---
profiles/audio/media.c | 100 ++++++++++++++++++++++---------------------------
1 file changed, 45 insertions(+), 55 deletions(-)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 588d61e..f2fba7b 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -96,7 +96,7 @@ struct media_player {
GHashTable *settings; /* Player settings */
GHashTable *track; /* Player current track */
guint watch;
- guint property_watch;
+ guint properties_watch;
guint track_watch;
char *status;
uint32_t position;
@@ -916,7 +916,7 @@ static void media_player_free(gpointer data)
}

g_dbus_remove_watch(conn, mp->watch);
- g_dbus_remove_watch(conn, mp->property_watch);
+ g_dbus_remove_watch(conn, mp->properties_watch);
g_dbus_remove_watch(conn, mp->track_watch);

if (mp->track)
@@ -980,6 +980,7 @@ static const char *get_setting(const char *key, void *user_data)
static int set_setting(const char *key, const char *value, void *user_data)
{
struct media_player *mp = user_data;
+ const char *iface = MEDIA_PLAYER_INTERFACE;
DBusMessage *msg;
DBusMessageIter iter, var;

@@ -989,14 +990,14 @@ static int set_setting(const char *key, const char *value, void *user_data)
return -EINVAL;

msg = dbus_message_new_method_call(mp->sender, mp->path,
- MEDIA_PLAYER_INTERFACE,
- "SetProperty");
+ DBUS_INTERFACE_PROPERTIES, "Set");
if (msg == NULL) {
error("Couldn't allocate D-Bus message");
return -ENOMEM;
}

dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);

dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
@@ -1218,29 +1219,55 @@ static gboolean set_player_property(struct media_player *mp, const char *key,
return TRUE;
}

-static gboolean property_changed(DBusConnection *connection, DBusMessage *msg,
+static gboolean parse_player_properties(struct media_player *mp,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter dict;
+ int ctype;
+
+ ctype = dbus_message_iter_get_arg_type(iter);
+ if (ctype != DBUS_TYPE_ARRAY)
+ return FALSE;
+
+ dbus_message_iter_recurse(iter, &dict);
+
+ while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
+ DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key;
+
+ if (ctype != DBUS_TYPE_DICT_ENTRY)
+ return FALSE;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return FALSE;
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (set_player_property(mp, key, &entry) == FALSE)
+ return FALSE;
+
+ dbus_message_iter_next(&dict);
+ }
+
+ return TRUE;
+}
+
+static gboolean properties_changed(DBusConnection *connection, DBusMessage *msg,
void *user_data)
{
struct media_player *mp = user_data;
DBusMessageIter iter;
- const char *property;

DBG("sender=%s path=%s", mp->sender, mp->path);

dbus_message_iter_init(msg, &iter);

- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
- error("Unexpected signature in %s.%s signal",
- dbus_message_get_interface(msg),
- dbus_message_get_member(msg));
- return TRUE;
- }
-
- dbus_message_iter_get_basic(&iter, &property);
-
dbus_message_iter_next(&iter);

- set_player_property(mp, property, &iter);
+ parse_player_properties(mp, &iter);

return TRUE;
}
@@ -1407,10 +1434,9 @@ static struct media_player *media_player_create(struct media_adapter *adapter,
mp->watch = g_dbus_add_disconnect_watch(conn, sender,
media_player_exit, mp,
NULL);
- mp->property_watch = g_dbus_add_signal_watch(conn, sender,
+ mp->properties_watch = g_dbus_add_properties_watch(conn, sender,
path, MEDIA_PLAYER_INTERFACE,
- "PropertyChanged",
- property_changed,
+ properties_changed,
mp, NULL);
mp->track_watch = g_dbus_add_signal_watch(conn, sender,
path, MEDIA_PLAYER_INTERFACE,
@@ -1439,42 +1465,6 @@ static struct media_player *media_player_create(struct media_adapter *adapter,
return mp;
}

-static gboolean parse_player_properties(struct media_player *mp,
- DBusMessageIter *iter)
-{
- DBusMessageIter dict;
- int ctype;
-
- ctype = dbus_message_iter_get_arg_type(iter);
- if (ctype != DBUS_TYPE_ARRAY)
- return FALSE;
-
- dbus_message_iter_recurse(iter, &dict);
-
- while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
- DBUS_TYPE_INVALID) {
- DBusMessageIter entry;
- const char *key;
-
- if (ctype != DBUS_TYPE_DICT_ENTRY)
- return FALSE;
-
- dbus_message_iter_recurse(&dict, &entry);
- if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
- return FALSE;
-
- dbus_message_iter_get_basic(&entry, &key);
- dbus_message_iter_next(&entry);
-
- if (set_player_property(mp, key, &entry) == FALSE)
- return FALSE;
-
- dbus_message_iter_next(&dict);
- }
-
- return TRUE;
-}
-
static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
void *data)
{
--
1.7.11.7


2012-11-27 12:51:21

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH BlueZ 2/6] audio: Convert controller MediaPlayer interface to use D-Bus Properties

From: Luiz Augusto von Dentz <[email protected]>

---
profiles/audio/player.c | 222 +++++++++++++++++++++++-------------------------
1 file changed, 106 insertions(+), 116 deletions(-)

diff --git a/profiles/audio/player.c b/profiles/audio/player.c
index e83b761..34b1f20 100644
--- a/profiles/audio/player.c
+++ b/profiles/audio/player.c
@@ -50,7 +50,7 @@ struct player_callback {
};

struct pending_req {
- DBusMessage *msg;
+ GDBusPendingPropertySet id;
const char *key;
const char *value;
};
@@ -67,13 +67,6 @@ struct media_player {
GSList *pending;
};

-static void append_settings(void *key, void *value, void *user_data)
-{
- DBusMessageIter *dict = user_data;
-
- dict_append_entry(dict, key, DBUS_TYPE_STRING, &value);
-}
-
static void append_metadata(void *key, void *value, void *user_data)
{
DBusMessageIter *dict = user_data;
@@ -89,39 +82,6 @@ static void append_metadata(void *key, void *value, void *user_data)
dict_append_entry(dict, key, DBUS_TYPE_STRING, &value);
}

-static DBusMessage *media_player_get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct media_player *mp = data;
- DBusMessage *reply;
- DBusMessageIter iter, dict;
- uint32_t position;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
- &dict);
-
- position = media_player_get_position(mp);
- dict_append_entry(&dict, "Position", DBUS_TYPE_UINT32, &position);
-
- dict_append_entry(&dict, "Status", DBUS_TYPE_STRING, &mp->status);
-
- g_hash_table_foreach(mp->settings, append_settings, &dict);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- return reply;
-}
-
static DBusMessage *media_player_get_track(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -164,111 +124,142 @@ static struct pending_req *find_pending(struct media_player *mp,
return NULL;
}

-static struct pending_req *pending_new(DBusMessage *msg, const char *key,
- const char *value)
+static struct pending_req *pending_new(GDBusPendingPropertySet id,
+ const char *key, const char *value)
{
struct pending_req *p;

p = g_new0(struct pending_req, 1);
- p->msg = dbus_message_ref(msg);
+ p->id = id;
p->key = key;
p->value = value;

return p;
}

-static DBusMessage *player_set_setting(struct media_player *mp,
- DBusMessage *msg, const char *key,
- const char *value)
+static gboolean get_position(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
{
- struct player_callback *cb = mp->cb;
- struct pending_req *p;
+ struct media_player *mp = data;

- if (cb == NULL || cb->cbs->set_setting == NULL)
- return btd_error_not_supported(msg);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &mp->position);

- p = find_pending(mp, key);
- if (p != NULL)
- return btd_error_in_progress(msg);
+ return TRUE;
+}

- if (!cb->cbs->set_setting(mp, key, value, cb->user_data))
- return btd_error_invalid_args(msg);
+static gboolean status_exists(const GDBusPropertyTable *property, void *data)
+{
+ struct media_player *mp = data;
+
+ return mp->status != NULL;
+}

- p = pending_new(msg, key, value);
+static gboolean get_status(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;

- mp->pending = g_slist_append(mp->pending, p);
+ if (mp->status == NULL)
+ return FALSE;

- return NULL;
+ DBG("%s", mp->status);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &mp->status);
+
+ return TRUE;
}

-static DBusMessage *media_player_set_property(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static gboolean setting_exists(const GDBusPropertyTable *property, void *data)
{
struct media_player *mp = data;
- DBusMessageIter iter;
- DBusMessageIter var;
- const char *key, *value, *curval;

- if (!dbus_message_iter_init(msg, &iter))
- return btd_error_invalid_args(msg);
+ return g_hash_table_contains(mp->settings, property->name);
+}

- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return btd_error_invalid_args(msg);
+static gboolean get_setting(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct media_player *mp = data;
+ const char *value;

- dbus_message_iter_get_basic(&iter, &key);
- dbus_message_iter_next(&iter);
+ value = g_hash_table_lookup(mp->settings, property->name);
+ if (value == NULL)
+ return FALSE;

- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- return btd_error_invalid_args(msg);
+ DBG("%s %s", property->name, value);

- dbus_message_iter_recurse(&iter, &var);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &value);

- if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
- return btd_error_invalid_args(msg);
+ return TRUE;
+}

- dbus_message_iter_get_basic(&var, &value);
+static void player_set_setting(struct media_player *mp,
+ GDBusPendingPropertySet id,
+ const char *key, const char *value)
+{
+ struct player_callback *cb = mp->cb;
+ struct pending_req *p;

- if (g_strcmp0(key, "Equalizer") != 0 &&
- g_strcmp0(key, "Repeat") != 0 &&
- g_strcmp0(key, "Shuffle") != 0 &&
- g_strcmp0(key, "Scan") != 0)
- return btd_error_invalid_args(msg);
+ if (cb == NULL || cb->cbs->set_setting == NULL)
+ return g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".NotSupported",
+ "Operation is not supported");

- curval = g_hash_table_lookup(mp->settings, key);
- if (g_strcmp0(curval, value) == 0)
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ p = find_pending(mp, key);
+ if (p != NULL)
+ return g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InProgress",
+ "Operation already in progress");

- return player_set_setting(mp, msg, key, value);
+ if (!cb->cbs->set_setting(mp, key, value, cb->user_data))
+ return g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+
+ p = pending_new(id, key, value);
+
+ mp->pending = g_slist_append(mp->pending, p);
+}
+
+static void set_setting(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, GDBusPendingPropertySet id,
+ void *data)
+{
+ struct media_player *mp = data;
+ const char *value;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING)
+ return g_dbus_pending_property_error(id,
+ ERROR_INTERFACE ".InvalidArguments",
+ "Invalid arguments in method call");
+
+ dbus_message_iter_get_basic(iter, &value);
+
+ player_set_setting(mp, id, property->name, value);
}

static const GDBusMethodTable media_player_methods[] = {
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- media_player_get_properties) },
{ GDBUS_METHOD("GetTrack",
NULL, GDBUS_ARGS({ "metadata", "a{sv}" }),
media_player_get_track) },
- { GDBUS_ASYNC_METHOD("SetProperty",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
- NULL, media_player_set_property) },
{ }
};

static const GDBusSignalTable media_player_signals[] = {
- { GDBUS_SIGNAL("PropertyChanged",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
{ GDBUS_SIGNAL("TrackChanged",
GDBUS_ARGS({ "metadata", "a{sv}" })) },
{ }
};

-static void pending_free(void *data)
-{
- struct pending_req *p = data;
-
- dbus_message_unref(p->msg);
- g_free(p);
-}
+static const GDBusPropertyTable media_player_properties[] = {
+ { "Position", "u", get_position },
+ { "Status", "s", get_status, NULL, status_exists },
+ { "Equalizer", "s", get_setting, set_setting, setting_exists },
+ { "Repeat", "s", get_setting, set_setting, setting_exists },
+ { "Shuffle", "s", get_setting, set_setting, setting_exists },
+ { "Scan", "s", get_setting, set_setting, setting_exists },
+ { }
+};

void media_player_destroy(struct media_player *mp)
{
@@ -286,7 +277,7 @@ void media_player_destroy(struct media_player *mp)
if (mp->process_id > 0)
g_source_remove(mp->process_id);

- g_slist_free_full(mp->pending, pending_free);
+ g_slist_free_full(mp->pending, g_free);

g_timer_destroy(mp->progress);
g_free(mp->cb);
@@ -311,7 +302,7 @@ struct media_player *media_player_controller_create(const char *path)
mp->path, MEDIA_PLAYER_INTERFACE,
media_player_methods,
media_player_signals,
- NULL, mp, NULL)) {
+ media_player_properties, mp, NULL)) {
error("D-Bus failed to register %s path", mp->path);
media_player_destroy(mp);
return NULL;
@@ -345,8 +336,8 @@ void media_player_set_position(struct media_player *mp, uint32_t position)
mp->position = position;
g_timer_start(mp->progress);

- emit_property_changed(mp->path, MEDIA_PLAYER_INTERFACE, "Position",
- DBUS_TYPE_UINT32, &mp->position);
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path,
+ MEDIA_PLAYER_INTERFACE, "Position");
}

void media_player_set_setting(struct media_player *mp, const char *key,
@@ -354,7 +345,6 @@ void media_player_set_setting(struct media_player *mp, const char *key,
{
char *curval;
struct pending_req *p;
- DBusMessage *reply;

DBG("%s: %s", key, value);

@@ -363,7 +353,8 @@ void media_player_set_setting(struct media_player *mp, const char *key,
if (p == NULL)
return;

- reply = btd_error_failed(p->msg, value);
+ g_dbus_pending_property_error(p->id, ERROR_INTERFACE ".Failed",
+ value);
goto send;
}

@@ -372,9 +363,8 @@ void media_player_set_setting(struct media_player *mp, const char *key,
goto done;

g_hash_table_replace(mp->settings, g_strdup(key), g_strdup(value));
-
- emit_property_changed(mp->path, MEDIA_PLAYER_INTERFACE, key,
- DBUS_TYPE_STRING, &value);
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path,
+ MEDIA_PLAYER_INTERFACE, key);

done:
p = find_pending(mp, key);
@@ -382,15 +372,15 @@ done:
return;

if (strcasecmp(value, p->value) == 0)
- reply = g_dbus_create_reply(p->msg, DBUS_TYPE_INVALID);
+ g_dbus_pending_property_success(p->id);
else
- reply = btd_error_not_supported(p->msg);
+ g_dbus_pending_property_error(p->id,
+ ERROR_INTERFACE ".NotSupported",
+ "Operation is not supported");

send:
- g_dbus_send_message(btd_get_dbus_connection(), reply);
-
mp->pending = g_slist_remove(mp->pending, p);
- pending_free(p);
+ g_free(p);

return;
}
@@ -410,8 +400,8 @@ void media_player_set_status(struct media_player *mp, const char *status)
g_free(mp->status);
mp->status = g_strdup(status);

- emit_property_changed(mp->path, MEDIA_PLAYER_INTERFACE, "Status",
- DBUS_TYPE_STRING, &status);
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path,
+ MEDIA_PLAYER_INTERFACE, "Status");

mp->position = media_player_get_position(mp);
g_timer_start(mp->progress);
--
1.7.11.7