2012-10-04 07:26:24

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 00/15] Properties + ObjectManager

Here is a rebased version of the patches. Most notable change is on patch
implementing the Set() method after feedback from Marcel. It doesn't cover the
concerns from Luiz about checking privileges per-property since I think this
could be added in a separate patch. As far as I could see the only user is
MediaTransport interface. The most obvious way would be to add another hook in
GDBusPropertyTable in order to check the privileges. Suggestions?

First 2 patches could be applied nonetheles. Get and GetAll are well tested,
both now and in the previous version of this patch set. Set() is still a
bit raw - the users implementing it are very big (adapter, device) so
they are not converted yet (previous patch doesn't apply anymore and there's a
change in the API that requires them to be rewritten).


Lucas De Marchi (10):
gdbus: Move typedefs up
gdbus: Use macros to add annotations
gdbus: Add skeleton of DBus.Properties interface
gdbus: Implement DBus.Properties.Get method
gdbus: Implement DBus.Properties.GetAll method
gdbus: Implement DBus.Properties.Set method
gdbus: Add properties into Introspectable interface
gdbus: Implement PropertiesChanged signal
Use DBus.Properties on Control interface
Use DBus.Properties on Manager interface

Luiz Augusto von Dentz (5):
gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
gdbus: Group interface changes to reduce the amount of signals
emitted
gdbus: Only export ObjectManager interface on root path
gdbus: Integrates ObjectManager with Properties interface
gdbus: Simplify code for appending properties

audio/control.c | 57 ++--
gdbus/gdbus.h | 74 +++--
gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/manager.c | 81 ++----
4 files changed, 897 insertions(+), 182 deletions(-)

--
1.7.12.2



2012-10-04 19:23:35

by Lucas De Marchi

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

On Thu, Oct 4, 2012 at 4:15 PM, Marcel Holtmann <[email protected]> wrote:
> Hi Lucas,
>
>> >> >> Here is a rebased version of the patches. Most notable change is on patch
>> >> >> implementing the Set() method after feedback from Marcel. It doesn't cover the
>> >> >> concerns from Luiz about checking privileges per-property since I think this
>> >> >> could be added in a separate patch. As far as I could see the only user is
>> >> >> MediaTransport interface. The most obvious way would be to add another hook in
>> >> >> GDBusPropertyTable in order to check the privileges. Suggestions?
>> >> >>
>> >> >> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
>> >> >> both now and in the previous version of this patch set. Set() is still a
>> >> >> bit raw - the users implementing it are very big (adapter, device) so
>> >> >> they are not converted yet (previous patch doesn't apply anymore and there's a
>> >> >> change in the API that requires them to be rewritten).
>> >> >>
>> >> >>
>> >> >> Lucas De Marchi (10):
>> >> >> gdbus: Move typedefs up
>> >> >> gdbus: Use macros to add annotations
>> >> >> gdbus: Add skeleton of DBus.Properties interface
>> >> >> gdbus: Implement DBus.Properties.Get method
>> >> >> gdbus: Implement DBus.Properties.GetAll method
>> >> >> gdbus: Implement DBus.Properties.Set method
>> >> >> gdbus: Add properties into Introspectable interface
>> >> >> gdbus: Implement PropertiesChanged signal
>> >> >> Use DBus.Properties on Control interface
>> >> >> Use DBus.Properties on Manager interface
>> >> >>
>> >> >> Luiz Augusto von Dentz (5):
>> >> >> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
>> >> >> gdbus: Group interface changes to reduce the amount of signals
>> >> >> emitted
>> >> >> gdbus: Only export ObjectManager interface on root path
>> >> >> gdbus: Integrates ObjectManager with Properties interface
>> >> >> gdbus: Simplify code for appending properties
>> >> >>
>> >> >> audio/control.c | 57 ++--
>> >> >> gdbus/gdbus.h | 74 +++--
>> >> >> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>> >> >> src/manager.c | 81 ++----
>> >> >> 4 files changed, 897 insertions(+), 182 deletions(-)
>> >> >
>> >> > This initial set has been applied. Now let's get testing it and fix any
>> >> > pending issues that are found. Also please remember send the adapter and
>> >> > device conversions when you've got them ready so that we get them stress
>> >> > tested at the UPF next week.
>> >>
>> >> Thanks... I'll submit them soonish.
>> >>
>> >> Should we change the interface names to include a version, too? Or
>> >> change the bus name to something like bluez5?
>> >
>> > I am not in favor of that actually. Since this the reverse domain name.
>> > And we do not own bluez5.org and I am not planning to get a new domain
>> > name for every major release.
>> >
>> > We need to think about the versioning at some point, but maybe we leave
>> > that for BlueZ 6.x then. At some point we need to finish this one first.
>>
>>
>> Then if you are going to support both bluez4 and bluez5, there's no
>> way at runtime to determine which backend to use.
>> We already suffered from that with connman, for example. But it had
>> not hit 1.0 so we couldn't do much.
>>
>> Reverse domain name is just a convention, as is the major version
>> number. I'd prefer breaking the former convention rather than screwing
>> with the users or let them checking at compile time.
>>
>> For example, I have this on my desktop:
>>
>> org.freedesktop.PolicyKit1,
>> org.freedesktop.RealtimeKit1,
>> org.freedesktop.login1
>> org.freedesktop.systemd1
>> fi.w1.wpa_supplicant1
>>
>> Do they all have these domains?
>
> yes, and the first 4 are subdomains.
>
>> Another option is to go with subdomains: org.bluez.v5 ;-)
>
> We could. Let the current code ObjectManager get stable first. It will
> get the first real exposure at the UPF next week. Then we see.

Agreed. Thanks.

Lucas De Marchi

2012-10-04 19:15:48

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

Hi Lucas,

> >> >> Here is a rebased version of the patches. Most notable change is on patch
> >> >> implementing the Set() method after feedback from Marcel. It doesn't cover the
> >> >> concerns from Luiz about checking privileges per-property since I think this
> >> >> could be added in a separate patch. As far as I could see the only user is
> >> >> MediaTransport interface. The most obvious way would be to add another hook in
> >> >> GDBusPropertyTable in order to check the privileges. Suggestions?
> >> >>
> >> >> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
> >> >> both now and in the previous version of this patch set. Set() is still a
> >> >> bit raw - the users implementing it are very big (adapter, device) so
> >> >> they are not converted yet (previous patch doesn't apply anymore and there's a
> >> >> change in the API that requires them to be rewritten).
> >> >>
> >> >>
> >> >> Lucas De Marchi (10):
> >> >> gdbus: Move typedefs up
> >> >> gdbus: Use macros to add annotations
> >> >> gdbus: Add skeleton of DBus.Properties interface
> >> >> gdbus: Implement DBus.Properties.Get method
> >> >> gdbus: Implement DBus.Properties.GetAll method
> >> >> gdbus: Implement DBus.Properties.Set method
> >> >> gdbus: Add properties into Introspectable interface
> >> >> gdbus: Implement PropertiesChanged signal
> >> >> Use DBus.Properties on Control interface
> >> >> Use DBus.Properties on Manager interface
> >> >>
> >> >> Luiz Augusto von Dentz (5):
> >> >> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
> >> >> gdbus: Group interface changes to reduce the amount of signals
> >> >> emitted
> >> >> gdbus: Only export ObjectManager interface on root path
> >> >> gdbus: Integrates ObjectManager with Properties interface
> >> >> gdbus: Simplify code for appending properties
> >> >>
> >> >> audio/control.c | 57 ++--
> >> >> gdbus/gdbus.h | 74 +++--
> >> >> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >> >> src/manager.c | 81 ++----
> >> >> 4 files changed, 897 insertions(+), 182 deletions(-)
> >> >
> >> > This initial set has been applied. Now let's get testing it and fix any
> >> > pending issues that are found. Also please remember send the adapter and
> >> > device conversions when you've got them ready so that we get them stress
> >> > tested at the UPF next week.
> >>
> >> Thanks... I'll submit them soonish.
> >>
> >> Should we change the interface names to include a version, too? Or
> >> change the bus name to something like bluez5?
> >
> > I am not in favor of that actually. Since this the reverse domain name.
> > And we do not own bluez5.org and I am not planning to get a new domain
> > name for every major release.
> >
> > We need to think about the versioning at some point, but maybe we leave
> > that for BlueZ 6.x then. At some point we need to finish this one first.
>
>
> Then if you are going to support both bluez4 and bluez5, there's no
> way at runtime to determine which backend to use.
> We already suffered from that with connman, for example. But it had
> not hit 1.0 so we couldn't do much.
>
> Reverse domain name is just a convention, as is the major version
> number. I'd prefer breaking the former convention rather than screwing
> with the users or let them checking at compile time.
>
> For example, I have this on my desktop:
>
> org.freedesktop.PolicyKit1,
> org.freedesktop.RealtimeKit1,
> org.freedesktop.login1
> org.freedesktop.systemd1
> fi.w1.wpa_supplicant1
>
> Do they all have these domains?

yes, and the first 4 are subdomains.

> Another option is to go with subdomains: org.bluez.v5 ;-)

We could. Let the current code ObjectManager get stable first. It will
get the first real exposure at the UPF next week. Then we see.

Regards

Marcel



2012-10-04 18:27:18

by Lucas De Marchi

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

On Thu, Oct 4, 2012 at 3:11 PM, Marcel Holtmann <[email protected]> wrote:
> Hi Lucas,
>
>> >> Here is a rebased version of the patches. Most notable change is on patch
>> >> implementing the Set() method after feedback from Marcel. It doesn't cover the
>> >> concerns from Luiz about checking privileges per-property since I think this
>> >> could be added in a separate patch. As far as I could see the only user is
>> >> MediaTransport interface. The most obvious way would be to add another hook in
>> >> GDBusPropertyTable in order to check the privileges. Suggestions?
>> >>
>> >> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
>> >> both now and in the previous version of this patch set. Set() is still a
>> >> bit raw - the users implementing it are very big (adapter, device) so
>> >> they are not converted yet (previous patch doesn't apply anymore and there's a
>> >> change in the API that requires them to be rewritten).
>> >>
>> >>
>> >> Lucas De Marchi (10):
>> >> gdbus: Move typedefs up
>> >> gdbus: Use macros to add annotations
>> >> gdbus: Add skeleton of DBus.Properties interface
>> >> gdbus: Implement DBus.Properties.Get method
>> >> gdbus: Implement DBus.Properties.GetAll method
>> >> gdbus: Implement DBus.Properties.Set method
>> >> gdbus: Add properties into Introspectable interface
>> >> gdbus: Implement PropertiesChanged signal
>> >> Use DBus.Properties on Control interface
>> >> Use DBus.Properties on Manager interface
>> >>
>> >> Luiz Augusto von Dentz (5):
>> >> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
>> >> gdbus: Group interface changes to reduce the amount of signals
>> >> emitted
>> >> gdbus: Only export ObjectManager interface on root path
>> >> gdbus: Integrates ObjectManager with Properties interface
>> >> gdbus: Simplify code for appending properties
>> >>
>> >> audio/control.c | 57 ++--
>> >> gdbus/gdbus.h | 74 +++--
>> >> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>> >> src/manager.c | 81 ++----
>> >> 4 files changed, 897 insertions(+), 182 deletions(-)
>> >
>> > This initial set has been applied. Now let's get testing it and fix any
>> > pending issues that are found. Also please remember send the adapter and
>> > device conversions when you've got them ready so that we get them stress
>> > tested at the UPF next week.
>>
>> Thanks... I'll submit them soonish.
>>
>> Should we change the interface names to include a version, too? Or
>> change the bus name to something like bluez5?
>
> I am not in favor of that actually. Since this the reverse domain name.
> And we do not own bluez5.org and I am not planning to get a new domain
> name for every major release.
>
> We need to think about the versioning at some point, but maybe we leave
> that for BlueZ 6.x then. At some point we need to finish this one first.


Then if you are going to support both bluez4 and bluez5, there's no
way at runtime to determine which backend to use.
We already suffered from that with connman, for example. But it had
not hit 1.0 so we couldn't do much.

Reverse domain name is just a convention, as is the major version
number. I'd prefer breaking the former convention rather than screwing
with the users or let them checking at compile time.

For example, I have this on my desktop:

org.freedesktop.PolicyKit1,
org.freedesktop.RealtimeKit1,
org.freedesktop.login1
org.freedesktop.systemd1
fi.w1.wpa_supplicant1

Do they all have these domains?

Another option is to go with subdomains: org.bluez.v5 ;-)

Lucas De Marchi

2012-10-04 18:11:08

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

Hi Lucas,

> >> Here is a rebased version of the patches. Most notable change is on patch
> >> implementing the Set() method after feedback from Marcel. It doesn't cover the
> >> concerns from Luiz about checking privileges per-property since I think this
> >> could be added in a separate patch. As far as I could see the only user is
> >> MediaTransport interface. The most obvious way would be to add another hook in
> >> GDBusPropertyTable in order to check the privileges. Suggestions?
> >>
> >> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
> >> both now and in the previous version of this patch set. Set() is still a
> >> bit raw - the users implementing it are very big (adapter, device) so
> >> they are not converted yet (previous patch doesn't apply anymore and there's a
> >> change in the API that requires them to be rewritten).
> >>
> >>
> >> Lucas De Marchi (10):
> >> gdbus: Move typedefs up
> >> gdbus: Use macros to add annotations
> >> gdbus: Add skeleton of DBus.Properties interface
> >> gdbus: Implement DBus.Properties.Get method
> >> gdbus: Implement DBus.Properties.GetAll method
> >> gdbus: Implement DBus.Properties.Set method
> >> gdbus: Add properties into Introspectable interface
> >> gdbus: Implement PropertiesChanged signal
> >> Use DBus.Properties on Control interface
> >> Use DBus.Properties on Manager interface
> >>
> >> Luiz Augusto von Dentz (5):
> >> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
> >> gdbus: Group interface changes to reduce the amount of signals
> >> emitted
> >> gdbus: Only export ObjectManager interface on root path
> >> gdbus: Integrates ObjectManager with Properties interface
> >> gdbus: Simplify code for appending properties
> >>
> >> audio/control.c | 57 ++--
> >> gdbus/gdbus.h | 74 +++--
> >> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >> src/manager.c | 81 ++----
> >> 4 files changed, 897 insertions(+), 182 deletions(-)
> >
> > This initial set has been applied. Now let's get testing it and fix any
> > pending issues that are found. Also please remember send the adapter and
> > device conversions when you've got them ready so that we get them stress
> > tested at the UPF next week.
>
> Thanks... I'll submit them soonish.
>
> Should we change the interface names to include a version, too? Or
> change the bus name to something like bluez5?

I am not in favor of that actually. Since this the reverse domain name.
And we do not own bluez5.org and I am not planning to get a new domain
name for every major release.

We need to think about the versioning at some point, but maybe we leave
that for BlueZ 6.x then. At some point we need to finish this one first.

Regards

Marcel



2012-10-04 14:29:01

by Lucas De Marchi

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

On Thu, Oct 4, 2012 at 11:17 AM, Johan Hedberg <[email protected]> wrote:
> Hi Lucas,
>
> On Thu, Oct 04, 2012, Lucas De Marchi wrote:
>> Here is a rebased version of the patches. Most notable change is on patch
>> implementing the Set() method after feedback from Marcel. It doesn't cover the
>> concerns from Luiz about checking privileges per-property since I think this
>> could be added in a separate patch. As far as I could see the only user is
>> MediaTransport interface. The most obvious way would be to add another hook in
>> GDBusPropertyTable in order to check the privileges. Suggestions?
>>
>> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
>> both now and in the previous version of this patch set. Set() is still a
>> bit raw - the users implementing it are very big (adapter, device) so
>> they are not converted yet (previous patch doesn't apply anymore and there's a
>> change in the API that requires them to be rewritten).
>>
>>
>> Lucas De Marchi (10):
>> gdbus: Move typedefs up
>> gdbus: Use macros to add annotations
>> gdbus: Add skeleton of DBus.Properties interface
>> gdbus: Implement DBus.Properties.Get method
>> gdbus: Implement DBus.Properties.GetAll method
>> gdbus: Implement DBus.Properties.Set method
>> gdbus: Add properties into Introspectable interface
>> gdbus: Implement PropertiesChanged signal
>> Use DBus.Properties on Control interface
>> Use DBus.Properties on Manager interface
>>
>> Luiz Augusto von Dentz (5):
>> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
>> gdbus: Group interface changes to reduce the amount of signals
>> emitted
>> gdbus: Only export ObjectManager interface on root path
>> gdbus: Integrates ObjectManager with Properties interface
>> gdbus: Simplify code for appending properties
>>
>> audio/control.c | 57 ++--
>> gdbus/gdbus.h | 74 +++--
>> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>> src/manager.c | 81 ++----
>> 4 files changed, 897 insertions(+), 182 deletions(-)
>
> This initial set has been applied. Now let's get testing it and fix any
> pending issues that are found. Also please remember send the adapter and
> device conversions when you've got them ready so that we get them stress
> tested at the UPF next week.

Thanks... I'll submit them soonish.

Should we change the interface names to include a version, too? Or
change the bus name to something like bluez5?

"It is also a good idea to include the major version of the interface
in the name, and increment it if incompatible changes are made; this
way, a single object can implement several versions of an interface in
parallel, if necessary." from
http://dbus.freedesktop.org/doc/dbus-specification.html


Lucas De Marchi

2012-10-04 14:22:10

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 14/15] Use DBus.Properties on Control interface

Hi Lizardo,

On Thu, Oct 04, 2012, Anderson Lizardo wrote:
> On Thu, Oct 4, 2012 at 3:26 AM, Lucas De Marchi
> <[email protected]> wrote:
> > @@ -77,13 +76,11 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
> > if (old_state != AVCTP_STATE_CONNECTED)
> > break;
> >
> > - value = FALSE;
> > g_dbus_emit_signal(conn, dev->path,
> > AUDIO_CONTROL_INTERFACE,
> > "Disconnected", DBUS_TYPE_INVALID);
> > - emit_property_changed(dev->path,
> > - AUDIO_CONTROL_INTERFACE, "Connected",
> > - DBUS_TYPE_BOOLEAN, &value);
> > + g_dbus_emit_property_changed(conn, dev->path,
> > + AUDIO_CONTROL_INTERFACE, "Connected");
>
> Out of curiosity, do you know why this API has Connected/Disconnected
> signals besides the PropertyChanged("Connected", ...) ?

I think those should have been marked as deprecated in 4.x and removed
for BlueZ 5.

Johan

2012-10-04 14:17:22

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 00/15] Properties + ObjectManager

Hi Lucas,

On Thu, Oct 04, 2012, Lucas De Marchi wrote:
> Here is a rebased version of the patches. Most notable change is on patch
> implementing the Set() method after feedback from Marcel. It doesn't cover the
> concerns from Luiz about checking privileges per-property since I think this
> could be added in a separate patch. As far as I could see the only user is
> MediaTransport interface. The most obvious way would be to add another hook in
> GDBusPropertyTable in order to check the privileges. Suggestions?
>
> First 2 patches could be applied nonetheles. Get and GetAll are well tested,
> both now and in the previous version of this patch set. Set() is still a
> bit raw - the users implementing it are very big (adapter, device) so
> they are not converted yet (previous patch doesn't apply anymore and there's a
> change in the API that requires them to be rewritten).
>
>
> Lucas De Marchi (10):
> gdbus: Move typedefs up
> gdbus: Use macros to add annotations
> gdbus: Add skeleton of DBus.Properties interface
> gdbus: Implement DBus.Properties.Get method
> gdbus: Implement DBus.Properties.GetAll method
> gdbus: Implement DBus.Properties.Set method
> gdbus: Add properties into Introspectable interface
> gdbus: Implement PropertiesChanged signal
> Use DBus.Properties on Control interface
> Use DBus.Properties on Manager interface
>
> Luiz Augusto von Dentz (5):
> gdbus: Add support for org.freedesktop.DBus.ObjectManager interface
> gdbus: Group interface changes to reduce the amount of signals
> emitted
> gdbus: Only export ObjectManager interface on root path
> gdbus: Integrates ObjectManager with Properties interface
> gdbus: Simplify code for appending properties
>
> audio/control.c | 57 ++--
> gdbus/gdbus.h | 74 +++--
> gdbus/object.c | 867 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
> src/manager.c | 81 ++----
> 4 files changed, 897 insertions(+), 182 deletions(-)

This initial set has been applied. Now let's get testing it and fix any
pending issues that are found. Also please remember send the adapter and
device conversions when you've got them ready so that we get them stress
tested at the UPF next week.

Johan

2012-10-04 11:42:17

by Anderson Lizardo

[permalink] [raw]
Subject: Re: [PATCH BlueZ v4 14/15] Use DBus.Properties on Control interface

Hi Lucas,

On Thu, Oct 4, 2012 at 3:26 AM, Lucas De Marchi
<[email protected]> wrote:
> @@ -77,13 +76,11 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
> if (old_state != AVCTP_STATE_CONNECTED)
> break;
>
> - value = FALSE;
> g_dbus_emit_signal(conn, dev->path,
> AUDIO_CONTROL_INTERFACE,
> "Disconnected", DBUS_TYPE_INVALID);
> - emit_property_changed(dev->path,
> - AUDIO_CONTROL_INTERFACE, "Connected",
> - DBUS_TYPE_BOOLEAN, &value);
> + g_dbus_emit_property_changed(conn, dev->path,
> + AUDIO_CONTROL_INTERFACE, "Connected");

Out of curiosity, do you know why this API has Connected/Disconnected
signals besides the PropertyChanged("Connected", ...) ?

Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

2012-10-04 07:26:39

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 15/15] Use DBus.Properties on Manager interface

---
src/manager.c | 81 ++++++++++++++++++-----------------------------------------
1 file changed, 25 insertions(+), 56 deletions(-)

diff --git a/src/manager.c b/src/manager.c
index f1f0f4d..2ceeed1 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -132,46 +132,30 @@ done:
return reply;
}

-static DBusMessage *get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static gboolean manager_property_get_adapters(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
{
- DBusMessage *reply;
- DBusMessageIter iter;
- DBusMessageIter dict;
- GSList *list;
- char **array;
- int i;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
+ DBusMessageIter entry;
+ GSList *l;

- 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(iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &entry);

- array = g_new0(char *, g_slist_length(adapters) + 1);
- for (i = 0, list = adapters; list; list = list->next) {
- struct btd_adapter *adapter = list->data;
+ for (l = adapters; l != NULL; l = l->next) {
+ struct btd_adapter *adapter = l->data;
+ const char *path = adapter_get_path(adapter);

- array[i] = (char *) adapter_get_path(adapter);
- i++;
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+ &path);
}
- dict_append_array(&dict, "Adapters", DBUS_TYPE_OBJECT_PATH, &array, i);
- g_free(array);

- dbus_message_iter_close_container(&iter, &dict);
+ dbus_message_iter_close_container(iter, &entry);

- return reply;
+ return TRUE;
}

static const GDBusMethodTable manager_methods[] = {
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- get_properties) },
{ GDBUS_METHOD("DefaultAdapter",
NULL, GDBUS_ARGS({ "adapter", "o" }),
default_adapter) },
@@ -189,8 +173,6 @@ static const GDBusMethodTable manager_methods[] = {
};

static const GDBusSignalTable manager_signals[] = {
- { GDBUS_SIGNAL("PropertyChanged",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
{ GDBUS_SIGNAL("AdapterAdded",
GDBUS_ARGS({ "adapter", "o" })) },
{ GDBUS_SIGNAL("AdapterRemoved",
@@ -200,34 +182,19 @@ static const GDBusSignalTable manager_signals[] = {
{ }
};

+static const GDBusPropertyTable manager_properties[] = {
+ { "Adapters", "ao", manager_property_get_adapters },
+ { }
+};
+
dbus_bool_t manager_init(const char *path)
{
snprintf(base_path, sizeof(base_path), "/org/bluez/%d", getpid());

return g_dbus_register_interface(btd_get_dbus_connection(),
"/", MANAGER_INTERFACE,
- manager_methods, manager_signals, NULL,
- NULL, NULL);
-}
-
-static void manager_update_adapters(void)
-{
- GSList *list;
- char **array;
- int i;
-
- array = g_new0(char *, g_slist_length(adapters) + 1);
- for (i = 0, list = adapters; list; list = list->next) {
- struct btd_adapter *adapter = list->data;
-
- array[i] = (char *) adapter_get_path(adapter);
- i++;
- }
-
- emit_array_property_changed("/", MANAGER_INTERFACE, "Adapters",
- DBUS_TYPE_OBJECT_PATH, &array, i);
-
- g_free(array);
+ manager_methods, manager_signals,
+ manager_properties, NULL, NULL);
}

static void manager_set_default_adapter(int id)
@@ -261,7 +228,8 @@ static void manager_remove_adapter(struct btd_adapter *adapter)

adapters = g_slist_remove(adapters, adapter);

- manager_update_adapters();
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), "/",
+ MANAGER_INTERFACE, "Adapters");

if (default_adapter_id == dev_id || default_adapter_id < 0) {
int new_default = hci_get_route(NULL);
@@ -381,7 +349,8 @@ struct btd_adapter *btd_manager_register_adapter(int id, gboolean up)
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);

- manager_update_adapters();
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), "/",
+ MANAGER_INTERFACE, "Adapters");

btd_stop_exit_timer();

--
1.7.12.2


2012-10-04 07:26:38

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 14/15] Use DBus.Properties on Control interface

---
audio/control.c | 57 ++++++++++++++++++---------------------------------------
1 file changed, 18 insertions(+), 39 deletions(-)

diff --git a/audio/control.c b/audio/control.c
index 896bc48..5ec8ca3 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -68,7 +68,6 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
{
DBusConnection *conn = btd_get_dbus_connection();
struct control *control = dev->control;
- gboolean value;

switch (new_state) {
case AVCTP_STATE_DISCONNECTED:
@@ -77,13 +76,11 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,
if (old_state != AVCTP_STATE_CONNECTED)
break;

- value = FALSE;
g_dbus_emit_signal(conn, dev->path,
AUDIO_CONTROL_INTERFACE,
"Disconnected", DBUS_TYPE_INVALID);
- emit_property_changed(dev->path,
- AUDIO_CONTROL_INTERFACE, "Connected",
- DBUS_TYPE_BOOLEAN, &value);
+ g_dbus_emit_property_changed(conn, dev->path,
+ AUDIO_CONTROL_INTERFACE, "Connected");

break;
case AVCTP_STATE_CONNECTING:
@@ -94,13 +91,11 @@ static void state_changed(struct audio_device *dev, avctp_state_t old_state,

break;
case AVCTP_STATE_CONNECTED:
- value = TRUE;
g_dbus_emit_signal(conn, dev->path,
AUDIO_CONTROL_INTERFACE, "Connected",
DBUS_TYPE_INVALID);
- emit_property_changed(dev->path,
- AUDIO_CONTROL_INTERFACE, "Connected",
- DBUS_TYPE_BOOLEAN, &value);
+ g_dbus_emit_property_changed(conn, dev->path,
+ AUDIO_CONTROL_INTERFACE, "Connected");
break;
default:
return;
@@ -168,42 +163,22 @@ static DBusMessage *volume_down(DBusConnection *conn, DBusMessage *msg,
return dbus_message_new_method_return(msg);
}

-static DBusMessage *control_get_properties(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static gboolean control_property_get_connected(
+ const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
{
struct audio_device *device = data;
- DBusMessage *reply;
- DBusMessageIter iter;
- DBusMessageIter dict;
- gboolean value;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
+ dbus_bool_t value = (device->control->session != NULL);

- 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_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);

- /* Connected */
- value = (device->control->session != NULL);
- dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &value);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- return reply;
+ return TRUE;
}

static const GDBusMethodTable control_methods[] = {
{ GDBUS_DEPRECATED_METHOD("IsConnected",
NULL, GDBUS_ARGS({ "connected", "b" }),
control_is_connected) },
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- control_get_properties) },
{ GDBUS_METHOD("VolumeUp", NULL, NULL, volume_up) },
{ GDBUS_METHOD("VolumeDown", NULL, NULL, volume_down) },
{ }
@@ -212,8 +187,11 @@ static const GDBusMethodTable control_methods[] = {
static const GDBusSignalTable control_signals[] = {
{ GDBUS_DEPRECATED_SIGNAL("Connected", NULL) },
{ GDBUS_DEPRECATED_SIGNAL("Disconnected", NULL) },
- { GDBUS_SIGNAL("PropertyChanged",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+ { }
+};
+
+static const GDBusPropertyTable control_properties[] = {
+ { "Connected", "b", control_property_get_connected },
{ }
};

@@ -250,8 +228,9 @@ struct control *control_init(struct audio_device *dev, GSList *uuids)

if (!g_dbus_register_interface(btd_get_dbus_connection(), dev->path,
AUDIO_CONTROL_INTERFACE,
- control_methods, control_signals, NULL,
- dev, path_unregister))
+ control_methods, control_signals,
+ control_properties, dev,
+ path_unregister))
return NULL;

DBG("Registered interface %s on path %s",
--
1.7.12.2


2012-10-04 07:26:37

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 13/15] gdbus: Implement PropertiesChanged signal

From: Lucas De Marchi <[email protected]>

---
gdbus/gdbus.h | 3 ++
gdbus/object.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index ec7b1ef..a96c97f 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -254,6 +254,9 @@ void g_dbus_pending_property_error_valist(DBusConnection *connection,
void g_dbus_pending_property_error(DBusConnection *connection,
GDBusPendingReply id, const char *name,
const char *format, ...);
+void g_dbus_emit_property_changed(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name);

#ifdef __cplusplus
}
diff --git a/gdbus/object.c b/gdbus/object.c
index bb0aa4d..b352fc4 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -48,6 +48,7 @@ struct generic_data {
GSList *added;
GSList *removed;
guint process_id;
+ gboolean pending_prop;
char *introspect;
struct generic_data *parent;
};
@@ -57,6 +58,7 @@ struct interface_data {
const GDBusMethodTable *methods;
const GDBusSignalTable *signals;
const GDBusPropertyTable *properties;
+ GSList *pending_prop;
void *user_data;
GDBusDestroyFunction destroy;
};
@@ -74,6 +76,9 @@ struct property_data {
};

static gboolean process_changes(gpointer user_data);
+static void process_properties_from_interface(struct generic_data *data,
+ struct interface_data *iface);
+static void process_property_changes(struct generic_data *data);

static void print_arguments(GString *gstr, const GDBusArgInfo *args,
const char *direction)
@@ -952,6 +957,10 @@ static gboolean process_changes(gpointer user_data)
if (data->added != NULL)
emit_interfaces_added(data);

+ /* Flush pending properties */
+ if (data->pending_prop == TRUE)
+ process_property_changes(data);
+
if (data->removed != NULL)
emit_interfaces_removed(data);

@@ -968,8 +977,7 @@ static void generic_unregister(DBusConnection *connection, void *user_data)

if (data->process_id > 0) {
g_source_remove(data->process_id);
- if (data->removed != NULL)
- emit_interfaces_removed(data);
+ process_changes(data);
}

g_slist_foreach(data->objects, reset_parent, data->parent);
@@ -1481,3 +1489,99 @@ gboolean g_dbus_emit_signal_valist(DBusConnection *connection,
return emit_signal_valist(connection, path, interface,
name, type, args);
}
+
+static void process_properties_from_interface(struct generic_data *data,
+ struct interface_data *iface)
+{
+ GSList *l;
+ DBusMessage *signal;
+ DBusMessageIter iter, dict, array;
+
+ if (iface->pending_prop == NULL)
+ return;
+
+ signal = dbus_message_new_signal(data->path,
+ DBUS_INTERFACE_PROPERTIES, "PropertiesChanged");
+ if (signal == NULL) {
+ error("Unable to allocate new " DBUS_INTERFACE_PROPERTIES
+ ".PropertiesChanged signal");
+ return;
+ }
+
+ iface->pending_prop = g_slist_reverse(iface->pending_prop);
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface->name);
+ 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);
+
+ for (l = iface->pending_prop; l != NULL; l = l->next) {
+ GDBusPropertyTable *p = l->data;
+
+ if (p->get == NULL)
+ continue;
+
+ if (p->exists != NULL && !p->exists(p, iface->user_data))
+ continue;
+
+ append_property(iface, p, &dict);
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+ dbus_message_iter_close_container(&iter, &array);
+
+ g_dbus_send_message(data->conn, signal);
+
+ g_slist_free(iface->pending_prop);
+ iface->pending_prop = NULL;
+}
+
+static void process_property_changes(struct generic_data *data)
+{
+ GSList *l;
+
+ for (l = data->interfaces; l != NULL; l = l->next) {
+ struct interface_data *iface = l->data;
+
+ process_properties_from_interface(data, iface);
+ }
+
+ data->pending_prop = FALSE;
+}
+
+void g_dbus_emit_property_changed(DBusConnection *connection,
+ const char *path, const char *interface,
+ const char *name)
+{
+ const GDBusPropertyTable *property;
+ struct generic_data *data;
+ struct interface_data *iface;
+
+ if (!dbus_connection_get_object_path_data(connection, path,
+ (void **) &data) || data == NULL)
+ return;
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return;
+
+ property = find_property(iface->properties, name);
+ if (property == NULL) {
+ error("Could not find property %s in %p", name,
+ iface->properties);
+ return;
+ }
+
+ data->pending_prop = TRUE;
+ iface->pending_prop = g_slist_prepend(iface->pending_prop,
+ (void *) property);
+
+ if (!data->process_id) {
+ data->process_id = g_idle_add(process_changes, data);
+ return;
+ }
+}
--
1.7.12.2


2012-10-04 07:26:36

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 12/15] gdbus: Simplify code for appending properties

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

This reuse append_properties for GetAll and GetManagedObjects
---
gdbus/object.c | 34 ++--------------------------------
1 file changed, 2 insertions(+), 32 deletions(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index 066f1a6..bb0aa4d 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -784,9 +784,8 @@ static DBusMessage *properties_get_all(DBusConnection *connection,
{
struct generic_data *data = user_data;
struct interface_data *iface;
- const GDBusPropertyTable *p;
const char *interface;
- DBusMessageIter iter, dict;
+ DBusMessageIter iter;
DBusMessage *reply;

if (!dbus_message_get_args(message, NULL,
@@ -804,37 +803,8 @@ static DBusMessage *properties_get_all(DBusConnection *connection,
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);
-
- for (p = iface->properties; p && p->name; p++) {
- DBusMessageIter entry, value;
-
- if (p->get == NULL)
- continue;
-
- if (p->exists != NULL && !p->exists(p, iface->user_data))
- continue;
-
- dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
- NULL, &entry);
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
- p->name);
- dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
- p->type, &value);
-
- if (!p->get(p, &value, iface->user_data)) {
- dbus_message_unref(reply);
- return NULL;
- }
-
- dbus_message_iter_close_container(&entry, &value);
- dbus_message_iter_close_container(&dict, &entry);
- }

- dbus_message_iter_close_container(&iter, &dict);
+ append_properties(iface, &iter);

return reply;
}
--
1.7.12.2


2012-10-04 07:26:35

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 11/15] gdbus: Integrates ObjectManager with Properties interface

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

This appends the properties and its values when using ObjectManager.
---
gdbus/object.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index e96a2bf..066f1a6 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -496,10 +496,28 @@ static void reset_parent(gpointer data, gpointer user_data)
child->parent = parent;
}

+static void append_property(struct interface_data *iface,
+ const GDBusPropertyTable *p, DBusMessageIter *dict)
+{
+ DBusMessageIter entry, value;
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL,
+ &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &p->name);
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, p->type,
+ &value);
+
+ p->get(p, &value, iface->user_data);
+
+ dbus_message_iter_close_container(&entry, &value);
+ dbus_message_iter_close_container(dict, &entry);
+}
+
static void append_properties(struct interface_data *data,
DBusMessageIter *iter)
{
DBusMessageIter dict;
+ const GDBusPropertyTable *p;

dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
@@ -507,7 +525,15 @@ static void append_properties(struct interface_data *data,
DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);

- /* TODO: list properties */
+ for (p = data->properties; p && p->name; p++) {
+ if (p->get == NULL)
+ continue;
+
+ if (p->exists != NULL && !p->exists(p, data->user_data))
+ continue;
+
+ append_property(data, p, &dict);
+ }

dbus_message_iter_close_container(iter, &dict);
}
--
1.7.12.2


2012-10-04 07:26:34

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 10/15] gdbus: Only export ObjectManager interface on root path

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

ObjectManager should be exported only in the root path and list all
the children paths.
---
gdbus/object.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index 5b5dc7e..e96a2bf 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -534,6 +534,10 @@ static void emit_interfaces_added(struct generic_data *data)
if (parent == NULL)
return;

+ /* Find root data */
+ while (parent->parent)
+ parent = parent->parent;
+
signal = dbus_message_new_signal(parent->path,
DBUS_INTERFACE_OBJECT_MANAGER,
"InterfacesAdded");
@@ -918,6 +922,10 @@ static void emit_interfaces_removed(struct generic_data *data)
if (parent == NULL)
return;

+ /* Find root data */
+ while (parent->parent)
+ parent = parent->parent;
+
signal = dbus_message_new_signal(parent->path,
DBUS_INTERFACE_OBJECT_MANAGER,
"InterfacesRemoved");
@@ -1054,6 +1062,8 @@ static void append_object(gpointer data, gpointer user_data)
&child->path);
append_interfaces(child, &entry);
dbus_message_iter_close_container(array, &entry);
+
+ g_slist_foreach(child->objects, append_object, user_data);
}

static DBusMessage *get_objects(DBusConnection *connection,
@@ -1168,8 +1178,11 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, introspect_methods,
NULL, NULL, data, NULL);

- add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER, manager_methods,
- manager_signals, NULL, data, NULL);
+ /* Only root path export ObjectManager interface */
+ if (data->parent == NULL)
+ add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER,
+ manager_methods, manager_signals,
+ NULL, data, NULL);

add_interface(data, DBUS_INTERFACE_PROPERTIES, properties_methods,
properties_signals, NULL, data, NULL);
--
1.7.12.2


2012-10-04 07:26:33

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 09/15] gdbus: Group interface changes to reduce the amount of signals emitted

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

InterfacesAdded and InterfacesRemoved can group all the interfaces
changes together in one message.
---
gdbus/object.c | 362 +++++++++++++++++++++++++++++++++------------------------
1 file changed, 208 insertions(+), 154 deletions(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index 6f5958a..5b5dc7e 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -45,6 +45,9 @@ struct generic_data {
char *path;
GSList *interfaces;
GSList *objects;
+ GSList *added;
+ GSList *removed;
+ guint process_id;
char *introspect;
struct generic_data *parent;
};
@@ -70,6 +73,8 @@ struct property_data {
DBusMessage *message;
};

+static gboolean process_changes(gpointer user_data);
+
static void print_arguments(GString *gstr, const GDBusArgInfo *args,
const char *direction)
{
@@ -491,21 +496,71 @@ static void reset_parent(gpointer data, gpointer user_data)
child->parent = parent;
}

-static void generic_unregister(DBusConnection *connection, void *user_data)
+static void append_properties(struct interface_data *data,
+ DBusMessageIter *iter)
{
- struct generic_data *data = user_data;
+ DBusMessageIter dict;
+
+ 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);
+
+ /* TODO: list properties */
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static void append_interface(gpointer data, gpointer user_data)
+{
+ struct interface_data *iface = data;
+ DBusMessageIter *array = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
+ &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &iface->name);
+ append_properties(data, &entry);
+ dbus_message_iter_close_container(array, &entry);
+}
+
+static void emit_interfaces_added(struct generic_data *data)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
struct generic_data *parent = data->parent;

- if (parent != NULL)
- parent->objects = g_slist_remove(parent->objects, data);
+ if (parent == NULL)
+ return;

- g_slist_foreach(data->objects, reset_parent, data->parent);
- g_slist_free(data->objects);
+ signal = dbus_message_new_signal(parent->path,
+ DBUS_INTERFACE_OBJECT_MANAGER,
+ "InterfacesAdded");
+ if (signal == NULL)
+ return;

- dbus_connection_unref(data->conn);
- g_free(data->introspect);
- g_free(data->path);
- g_free(data);
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &data->path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
+
+ g_slist_foreach(data->added, append_interface, &array);
+ g_slist_free(data->added);
+ data->added = NULL;
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ g_dbus_send_message(data->conn, signal);
}

static struct interface_data *find_interface(GSList *interfaces,
@@ -546,45 +601,37 @@ static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args,
return TRUE;
}

-static DBusHandlerResult generic_message(DBusConnection *connection,
- DBusMessage *message, void *user_data)
+static gboolean remove_interface(struct generic_data *data, const char *name)
{
- struct generic_data *data = user_data;
struct interface_data *iface;
- const GDBusMethodTable *method;
- const char *interface;

- interface = dbus_message_get_interface(message);
-
- iface = find_interface(data->interfaces, interface);
+ iface = find_interface(data->interfaces, name);
if (iface == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- for (method = iface->methods; method &&
- method->name && method->function; method++) {
- if (dbus_message_is_method_call(message, iface->name,
- method->name) == FALSE)
- continue;
+ return FALSE;

- if (g_dbus_args_have_signature(method->in_args,
- message) == FALSE)
- continue;
+ data->interfaces = g_slist_remove(data->interfaces, iface);

- if (check_privilege(connection, message, method,
- iface->user_data) == TRUE)
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (iface->destroy) {
+ iface->destroy(iface->user_data);
+ iface->user_data = NULL;
+ }

- return process_message(connection, message, method,
- iface->user_data);
+ if (data->parent == NULL) {
+ g_free(iface->name);
+ g_free(iface);
+ return TRUE;
}

- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
+ data->removed = g_slist_prepend(data->removed, iface->name);
+ g_free(iface);

-static DBusObjectPathVTable generic_table = {
- .unregister_function = generic_unregister,
- .message_function = generic_message,
-};
+ if (data->process_id > 0)
+ return TRUE;
+
+ data->process_id = g_idle_add(process_changes, data);
+
+ return TRUE;
+}

static struct generic_data *invalidate_parent_data(DBusConnection *conn,
const char *child_path)
@@ -636,12 +683,6 @@ done:
return data;
}

-static const GDBusMethodTable introspect_methods[] = {
- { GDBUS_METHOD("Introspect", NULL,
- GDBUS_ARGS({ "xml", "s" }), introspect) },
- { }
-};
-
static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *properties,
const char *name)
{
@@ -860,35 +901,128 @@ static const GDBusSignalTable properties_signals[] = {
{ }
};

-static void append_properties(struct interface_data *data,
- DBusMessageIter *iter)
+static void append_name(gpointer data, gpointer user_data)
{
- DBusMessageIter dict;
+ char *name = data;
+ DBusMessageIter *iter = user_data;

- 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_append_basic(iter, DBUS_TYPE_STRING, &name);
+}

- /* TODO: list properties */
+static void emit_interfaces_removed(struct generic_data *data)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
+ struct generic_data *parent = data->parent;

- dbus_message_iter_close_container(iter, &dict);
+ if (parent == NULL)
+ return;
+
+ signal = dbus_message_new_signal(parent->path,
+ DBUS_INTERFACE_OBJECT_MANAGER,
+ "InterfacesRemoved");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &data->path);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+
+ g_slist_foreach(data->removed, append_name, &array);
+ g_slist_free_full(data->removed, g_free);
+ data->removed = NULL;
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ g_dbus_send_message(data->conn, signal);
}

-static void append_interface(gpointer data, gpointer user_data)
+static gboolean process_changes(gpointer user_data)
{
- struct interface_data *iface = data;
- DBusMessageIter *array = user_data;
- DBusMessageIter entry;
+ struct generic_data *data = user_data;

- dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
- &entry);
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &iface->name);
- append_properties(data, &entry);
- dbus_message_iter_close_container(array, &entry);
+ data->process_id = 0;
+
+ if (data->added != NULL)
+ emit_interfaces_added(data);
+
+ if (data->removed != NULL)
+ emit_interfaces_removed(data);
+
+ return FALSE;
}

+static void generic_unregister(DBusConnection *connection, void *user_data)
+{
+ struct generic_data *data = user_data;
+ struct generic_data *parent = data->parent;
+
+ if (parent != NULL)
+ parent->objects = g_slist_remove(parent->objects, data);
+
+ if (data->process_id > 0) {
+ g_source_remove(data->process_id);
+ if (data->removed != NULL)
+ emit_interfaces_removed(data);
+ }
+
+ g_slist_foreach(data->objects, reset_parent, data->parent);
+ g_slist_free(data->objects);
+
+ dbus_connection_unref(data->conn);
+ g_free(data->introspect);
+ g_free(data->path);
+ g_free(data);
+}
+
+static DBusHandlerResult generic_message(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct generic_data *data = user_data;
+ struct interface_data *iface;
+ const GDBusMethodTable *method;
+ const char *interface;
+
+ interface = dbus_message_get_interface(message);
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ for (method = iface->methods; method &&
+ method->name && method->function; method++) {
+ if (dbus_message_is_method_call(message, iface->name,
+ method->name) == FALSE)
+ continue;
+
+ if (g_dbus_args_have_signature(method->in_args,
+ message) == FALSE)
+ continue;
+
+ if (check_privilege(connection, message, method,
+ iface->user_data) == TRUE)
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+ return process_message(connection, message, method,
+ iface->user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusObjectPathVTable generic_table = {
+ .unregister_function = generic_unregister,
+ .message_function = generic_message,
+};
+
+static const GDBusMethodTable introspect_methods[] = {
+ { GDBUS_METHOD("Introspect", NULL,
+ GDBUS_ARGS({ "xml", "s" }), introspect) },
+ { }
+};
+
static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
{
DBusMessageIter array;
@@ -973,43 +1107,6 @@ static const GDBusSignalTable manager_signals[] = {
{ }
};

-static void emit_interface_added(struct generic_data *data,
- struct interface_data *iface)
-{
- DBusMessage *signal;
- DBusMessageIter iter, array;
- struct generic_data *parent = data->parent;
-
- if (parent == NULL)
- return;
-
- signal = dbus_message_new_signal(parent->path,
- DBUS_INTERFACE_OBJECT_MANAGER,
- "InterfacesAdded");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
- &data->path);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_ARRAY_AS_STRING
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
-
- append_interface(iface, &array);
-
- dbus_message_iter_close_container(&iter, &array);
-
- g_dbus_send_message(data->conn, signal);
-}
-
static void add_interface(struct generic_data *data,
const char *name,
const GDBusMethodTable *methods,
@@ -1029,8 +1126,14 @@ static void add_interface(struct generic_data *data,
iface->destroy = destroy;

data->interfaces = g_slist_append(data->interfaces, iface);
+ if (data->parent == NULL)
+ return;
+
+ data->added = g_slist_append(data->added, iface);
+ if (data->process_id > 0)
+ return;

- emit_interface_added(data, iface);
+ data->process_id = g_idle_add(process_changes, data);
}

static struct generic_data *object_path_ref(DBusConnection *connection,
@@ -1074,55 +1177,6 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
return data;
}

-static void emit_interface_remove(struct generic_data *data,
- struct interface_data *iface)
-{
- DBusMessage *signal;
- DBusMessageIter iter, array;
- struct generic_data *parent = data->parent;
-
- if (parent == NULL)
- return;
-
- signal = dbus_message_new_signal(parent->path,
- DBUS_INTERFACE_OBJECT_MANAGER,
- "InterfacesRemoved");
- if (signal == NULL)
- return;
-
- dbus_message_iter_init_append(signal, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
- &data->path);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_STRING_AS_STRING, &array);
- dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &iface->name);
- dbus_message_iter_close_container(&iter, &array);
-
- g_dbus_send_message(data->conn, signal);
-}
-
-static gboolean remove_interface(struct generic_data *data, const char *name)
-{
- struct interface_data *iface;
-
- iface = find_interface(data->interfaces, name);
- if (iface == NULL)
- return FALSE;
-
- emit_interface_remove(data, iface);
-
- data->interfaces = g_slist_remove(data->interfaces, iface);
-
- if (iface->destroy)
- iface->destroy(iface->user_data);
-
- g_free(iface->name);
- g_free(iface);
-
- return TRUE;
-}
-
static void object_path_unref(DBusConnection *connection, const char *path)
{
struct generic_data *data = NULL;
@@ -1143,9 +1197,9 @@ static void object_path_unref(DBusConnection *connection, const char *path)
remove_interface(data, DBUS_INTERFACE_PROPERTIES);
remove_interface(data, DBUS_INTERFACE_OBJECT_MANAGER);

- invalidate_parent_data(connection, path);
+ invalidate_parent_data(data->conn, data->path);

- dbus_connection_unregister_object_path(connection, path);
+ dbus_connection_unregister_object_path(data->conn, data->path);
}

static gboolean check_signal(DBusConnection *conn, const char *path,
@@ -1270,7 +1324,7 @@ gboolean g_dbus_unregister_interface(DBusConnection *connection,
g_free(data->introspect);
data->introspect = NULL;

- object_path_unref(connection, path);
+ object_path_unref(connection, data->path);

return TRUE;
}
--
1.7.12.2


2012-10-04 07:26:32

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 08/15] gdbus: Add support for org.freedesktop.DBus.ObjectManager interface

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

This implements initial support for ObjectManager, it automatically adds
objects to its parents so no action is needed by daemons to get their
objects managed by this interface.

ObjectManager is part of D-Bus spec since revision 0.17:
http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
---
gdbus/object.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 237 insertions(+), 10 deletions(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index c145328..6f5958a 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -37,10 +37,16 @@
#define error(fmt...)
#define debug(fmt...)

+#define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager"
+
struct generic_data {
unsigned int refcount;
+ DBusConnection *conn;
+ char *path;
GSList *interfaces;
+ GSList *objects;
char *introspect;
+ struct generic_data *parent;
};

struct interface_data {
@@ -477,11 +483,28 @@ void g_dbus_pending_property_error(DBusConnection *connection,
va_end(args);
}

+static void reset_parent(gpointer data, gpointer user_data)
+{
+ struct generic_data *child = data;
+ struct generic_data *parent = user_data;
+
+ child->parent = parent;
+}
+
static void generic_unregister(DBusConnection *connection, void *user_data)
{
struct generic_data *data = user_data;
+ struct generic_data *parent = data->parent;

+ if (parent != NULL)
+ parent->objects = g_slist_remove(parent->objects, data);
+
+ g_slist_foreach(data->objects, reset_parent, data->parent);
+ g_slist_free(data->objects);
+
+ dbus_connection_unref(data->conn);
g_free(data->introspect);
+ g_free(data->path);
g_free(data);
}

@@ -563,9 +586,10 @@ static DBusObjectPathVTable generic_table = {
.message_function = generic_message,
};

-static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
+static struct generic_data *invalidate_parent_data(DBusConnection *conn,
+ const char *child_path)
{
- struct generic_data *data = NULL;
+ struct generic_data *data = NULL, *child = NULL, *parent = NULL;
char *parent_path, *slash;

parent_path = g_strdup(child_path);
@@ -586,16 +610,30 @@ static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
goto done;
}

- invalidate_parent_data(conn, parent_path);
+ parent = invalidate_parent_data(conn, parent_path);

- if (data == NULL)
- goto done;
+ if (data == NULL) {
+ data = parent;
+ if (data == NULL)
+ goto done;
+ }

g_free(data->introspect);
data->introspect = NULL;

+ if (!dbus_connection_get_object_path_data(conn, child_path,
+ (void *) &child))
+ goto done;
+
+ if (child == NULL || g_slist_find(data->objects, child) != NULL)
+ goto done;
+
+ data->objects = g_slist_prepend(data->objects, child);
+ child->parent = data;
+
done:
g_free(parent_path);
+ return data;
}

static const GDBusMethodTable introspect_methods[] = {
@@ -822,7 +860,158 @@ static const GDBusSignalTable properties_signals[] = {
{ }
};

-static void add_interface(struct generic_data *data, const char *name,
+static void append_properties(struct interface_data *data,
+ DBusMessageIter *iter)
+{
+ DBusMessageIter dict;
+
+ 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);
+
+ /* TODO: list properties */
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static void append_interface(gpointer data, gpointer user_data)
+{
+ struct interface_data *iface = data;
+ DBusMessageIter *array = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
+ &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &iface->name);
+ append_properties(data, &entry);
+ dbus_message_iter_close_container(array, &entry);
+}
+
+static void append_interfaces(struct generic_data *data, DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
+
+ g_slist_foreach(data->interfaces, append_interface, &array);
+
+ dbus_message_iter_close_container(iter, &array);
+}
+
+static void append_object(gpointer data, gpointer user_data)
+{
+ struct generic_data *child = data;
+ DBusMessageIter *array = user_data;
+ DBusMessageIter entry;
+
+ dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL,
+ &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+ &child->path);
+ append_interfaces(child, &entry);
+ dbus_message_iter_close_container(array, &entry);
+}
+
+static DBusMessage *get_objects(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct generic_data *data = user_data;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter array;
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ 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_OBJECT_PATH_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array);
+
+ g_slist_foreach(data->objects, append_object, &array);
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ return reply;
+}
+
+static const GDBusMethodTable manager_methods[] = {
+ { GDBUS_METHOD("GetManagedObjects", NULL,
+ GDBUS_ARGS({ "objects", "a{oa{sa{sv}}}" }), get_objects) },
+ { }
+};
+
+static const GDBusSignalTable manager_signals[] = {
+ { GDBUS_SIGNAL("InterfacesAdded",
+ GDBUS_ARGS({ "object", "o" },
+ { "interfaces", "a{sa{sv}}" })) },
+ { GDBUS_SIGNAL("InterfacesRemoved",
+ GDBUS_ARGS({ "object", "o" }, { "interfaces", "as" })) },
+ { }
+};
+
+static void emit_interface_added(struct generic_data *data,
+ struct interface_data *iface)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
+ struct generic_data *parent = data->parent;
+
+ if (parent == NULL)
+ return;
+
+ signal = dbus_message_new_signal(parent->path,
+ DBUS_INTERFACE_OBJECT_MANAGER,
+ "InterfacesAdded");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &data->path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array);
+
+ append_interface(iface, &array);
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ g_dbus_send_message(data->conn, signal);
+}
+
+static void add_interface(struct generic_data *data,
+ const char *name,
const GDBusMethodTable *methods,
const GDBusSignalTable *signals,
const GDBusPropertyTable *properties,
@@ -840,6 +1029,8 @@ static void add_interface(struct generic_data *data, const char *name,
iface->destroy = destroy;

data->interfaces = g_slist_append(data->interfaces, iface);
+
+ emit_interface_added(data, iface);
}

static struct generic_data *object_path_ref(DBusConnection *connection,
@@ -856,6 +1047,8 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
}

data = g_new0(struct generic_data, 1);
+ data->conn = dbus_connection_ref(connection);
+ data->path = g_strdup(path);
data->refcount = 1;

data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>");
@@ -869,8 +1062,11 @@ static struct generic_data *object_path_ref(DBusConnection *connection,

invalidate_parent_data(connection, path);

- add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
- introspect_methods, NULL, NULL, data, NULL);
+ add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, introspect_methods,
+ NULL, NULL, data, NULL);
+
+ add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER, manager_methods,
+ manager_signals, NULL, data, NULL);

add_interface(data, DBUS_INTERFACE_PROPERTIES, properties_methods,
properties_signals, NULL, data, NULL);
@@ -878,6 +1074,34 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
return data;
}

+static void emit_interface_remove(struct generic_data *data,
+ struct interface_data *iface)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
+ struct generic_data *parent = data->parent;
+
+ if (parent == NULL)
+ return;
+
+ signal = dbus_message_new_signal(parent->path,
+ DBUS_INTERFACE_OBJECT_MANAGER,
+ "InterfacesRemoved");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+ &data->path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+ dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &iface->name);
+ dbus_message_iter_close_container(&iter, &array);
+
+ g_dbus_send_message(data->conn, signal);
+}
+
static gboolean remove_interface(struct generic_data *data, const char *name)
{
struct interface_data *iface;
@@ -886,6 +1110,8 @@ static gboolean remove_interface(struct generic_data *data, const char *name)
if (iface == NULL)
return FALSE;

+ emit_interface_remove(data, iface);
+
data->interfaces = g_slist_remove(data->interfaces, iface);

if (iface->destroy)
@@ -915,6 +1141,7 @@ static void object_path_unref(DBusConnection *connection, const char *path)

remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
remove_interface(data, DBUS_INTERFACE_PROPERTIES);
+ remove_interface(data, DBUS_INTERFACE_OBJECT_MANAGER);

invalidate_parent_data(connection, path);

@@ -1013,8 +1240,8 @@ gboolean g_dbus_register_interface(DBusConnection *connection,
return FALSE;
}

- add_interface(data, name, methods, signals,
- properties, user_data, destroy);
+ add_interface(data, name, methods, signals, properties, user_data,
+ destroy);

g_free(data->introspect);
data->introspect = NULL;
--
1.7.12.2


2012-10-04 07:26:31

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 07/15] gdbus: Add properties into Introspectable interface

From: Lucas De Marchi <[email protected]>

---
gdbus/object.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/gdbus/object.c b/gdbus/object.c
index 4509f76..c145328 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -95,6 +95,7 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
{
const GDBusMethodTable *method;
const GDBusSignalTable *signal;
+ const GDBusPropertyTable *property;

for (method = iface->methods; method && method->name; method++) {
gboolean deprecated = method->flags &
@@ -147,6 +148,24 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
g_string_append_printf(gstr, "\t\t</signal>\n");
}
}
+
+ for (property = iface->properties; property && property->name;
+ property++) {
+ gboolean deprecated = property->flags &
+ G_DBUS_PROPERTY_FLAG_DEPRECATED;
+
+ g_string_append_printf(gstr, "\t\t<property name=\"%s\""
+ " type=\"%s\" access=\"%s%s\"",
+ property->name, property->type,
+ property->get ? "read" : "",
+ property->set ? "write" : "");
+
+ if (!deprecated)
+ g_string_append_printf(gstr, "/>\n");
+ else
+ g_string_append_printf(gstr,
+ G_DBUS_ANNOTATE_DEPRECATED(">\n\t\t\t"));
+ }
}

static void generate_introspection_xml(DBusConnection *conn,
--
1.7.12.2


2012-10-04 07:26:30

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 06/15] gdbus: Implement DBus.Properties.Set method

From: Lucas De Marchi <[email protected]>

Contrary to Get() and GetAll(), Set() is asynchronous so we pass an id
to the setter so later it can declare the Set() as successful or
otherwise.
---
gdbus/gdbus.h | 16 +++++++
gdbus/object.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index b2e78c4..ec7b1ef 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -69,6 +69,12 @@ typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
typedef gboolean (*GDBusPropertyGetter)(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data);

+typedef guint32 GDBusPendingPropertySet;
+
+typedef void (*GDBusPropertySetter)(const GDBusPropertyTable *property,
+ DBusMessageIter *value, GDBusPendingPropertySet id,
+ void *data);
+
typedef gboolean (*GDBusPropertyExists)(const GDBusPropertyTable *property,
void *data);

@@ -123,6 +129,7 @@ struct GDBusPropertyTable {
const char *name;
const char *type;
GDBusPropertyGetter get;
+ GDBusPropertySetter set;
GDBusPropertyExists exists;
GDBusPropertyFlags flags;
};
@@ -239,6 +246,15 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
void g_dbus_remove_all_watches(DBusConnection *connection);

+void g_dbus_pending_property_success(DBusConnection *connection,
+ GDBusPendingPropertySet id);
+void g_dbus_pending_property_error_valist(DBusConnection *connection,
+ GDBusPendingReply id, const char *name,
+ const char *format, va_list args);
+void g_dbus_pending_property_error(DBusConnection *connection,
+ GDBusPendingReply id, const char *name,
+ const char *format, ...);
+
#ifdef __cplusplus
}
#endif
diff --git a/gdbus/object.c b/gdbus/object.c
index c6e4a53..4509f76 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -59,6 +59,11 @@ struct security_data {
void *iface_user_data;
};

+struct property_data {
+ GDBusPendingPropertySet id;
+ DBusMessage *message;
+};
+
static void print_arguments(GString *gstr, const GDBusArgInfo *args,
const char *direction)
{
@@ -380,6 +385,79 @@ static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
return FALSE;
}

+static GDBusPendingPropertySet next_pending_property = 1;
+static GSList *pending_property_set;
+
+static struct property_data *remove_pending_property_data(
+ GDBusPendingPropertySet id)
+{
+ struct property_data *propdata;
+ GSList *l;
+
+ for (l = pending_property_set; l != NULL; l = l->next) {
+ propdata = l->data;
+ if (propdata->id != id)
+ continue;
+ }
+
+ if (l == NULL)
+ return NULL;
+
+ pending_property_set = g_slist_delete_link(pending_property_set, l);
+
+ return propdata;
+}
+
+void g_dbus_pending_property_success(DBusConnection *connection,
+ GDBusPendingPropertySet id)
+{
+ struct property_data *propdata;
+
+ propdata = remove_pending_property_data(id);
+ if (propdata == NULL)
+ return;
+
+ g_dbus_send_reply(connection, propdata->message, DBUS_TYPE_INVALID);
+ dbus_message_unref(propdata->message);
+ g_free(propdata);
+}
+
+void g_dbus_pending_property_error_valist(DBusConnection *connection,
+ GDBusPendingReply id, const char *name,
+ const char *format, va_list args)
+{
+ struct property_data *propdata;
+ DBusMessage *reply;
+
+ propdata = remove_pending_property_data(id);
+ if (propdata == NULL)
+ return;
+
+ reply = g_dbus_create_error_valist(propdata->message, name, format,
+ args);
+ if (reply != NULL) {
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+
+ dbus_message_unref(propdata->message);
+ g_free(propdata);
+}
+
+void g_dbus_pending_property_error(DBusConnection *connection,
+ GDBusPendingReply id, const char *name,
+ const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ g_dbus_pending_property_error_valist(connection, id, name, format,
+ args);
+
+ va_end(args);
+}
+
static void generic_unregister(DBusConnection *connection, void *user_data)
{
struct generic_data *data = user_data;
@@ -636,7 +714,69 @@ static DBusMessage *properties_get_all(DBusConnection *connection,
static DBusMessage *properties_set(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
- return dbus_message_new_method_return(message);
+ struct generic_data *data = user_data;
+ DBusMessageIter iter, sub;
+ struct interface_data *iface;
+ const GDBusPropertyTable *property;
+ const char *name, *interface;
+ struct property_data *propdata;
+
+ if (!dbus_message_iter_init(message, &iter))
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No arguments given");
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid argument type: '%c'",
+ dbus_message_iter_get_arg_type(&iter));
+
+ dbus_message_iter_get_basic(&iter, &name);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid argument type: '%c'",
+ dbus_message_iter_get_arg_type(&iter));
+
+ dbus_message_iter_get_basic(&iter, &interface);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid argument type: '%c'",
+ dbus_message_iter_get_arg_type(&iter));
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No such interface '%s'", interface);
+
+ property = find_property(iface->properties, name);
+ if (property == NULL)
+ return g_dbus_create_error(message,
+ DBUS_ERROR_UNKNOWN_PROPERTY,
+ "No such property '%s'", name);
+
+ if (property->set == NULL)
+ return g_dbus_create_error(message,
+ DBUS_ERROR_PROPERTY_READ_ONLY,
+ "Property '%s' is not writable", name);
+
+ if (property->exists != NULL &&
+ !property->exists(property, iface->user_data))
+ return g_dbus_create_error(message,
+ DBUS_ERROR_UNKNOWN_PROPERTY,
+ "No such property '%s'", name);
+
+ propdata = g_new(struct property_data, 1);
+ propdata->id = next_pending_property++;
+ propdata->message = dbus_message_ref(message);
+
+ property->set(property, &sub, propdata->id, iface->user_data);
+
+ return NULL;
}

static const GDBusMethodTable properties_methods[] = {
--
1.7.12.2


2012-10-04 07:26:29

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 05/15] gdbus: Implement DBus.Properties.GetAll method

From: Lucas De Marchi <[email protected]>

---
gdbus/object.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index 89138f7..c6e4a53 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -576,7 +576,61 @@ static DBusMessage *properties_get(DBusConnection *connection,
static DBusMessage *properties_get_all(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
- return NULL;
+ struct generic_data *data = user_data;
+ struct interface_data *iface;
+ const GDBusPropertyTable *p;
+ const char *interface;
+ DBusMessageIter iter, dict;
+ DBusMessage *reply;
+
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No such interface '%s'", interface);
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ 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);
+
+ for (p = iface->properties; p && p->name; p++) {
+ DBusMessageIter entry, value;
+
+ if (p->get == NULL)
+ continue;
+
+ if (p->exists != NULL && !p->exists(p, iface->user_data))
+ continue;
+
+ dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
+ p->name);
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ p->type, &value);
+
+ if (!p->get(p, &value, iface->user_data)) {
+ dbus_message_unref(reply);
+ return NULL;
+ }
+
+ dbus_message_iter_close_container(&entry, &value);
+ dbus_message_iter_close_container(&dict, &entry);
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
}

static DBusMessage *properties_set(DBusConnection *connection,
--
1.7.12.2


2012-10-04 07:26:27

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 03/15] gdbus: Add skeleton of DBus.Properties interface

From: Lucas De Marchi <[email protected]>

This interface is responsible for handling properties of all objects in
a given path. Right now it only registers itself, doing nothing useful.
A conversion to this new layout will be done by subsequent patches.

org.freedesktop.org.DBus.Properties spec can be found at
http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties
---
gdbus/object.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)

diff --git a/gdbus/object.c b/gdbus/object.c
index 24e8285..6c11528 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -507,6 +507,48 @@ static const GDBusMethodTable introspect_methods[] = {
{ }
};

+static DBusMessage *properties_get(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ return NULL;
+}
+
+static DBusMessage *properties_get_all(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ return NULL;
+}
+
+static DBusMessage *properties_set(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ return dbus_message_new_method_return(message);
+}
+
+static const GDBusMethodTable properties_methods[] = {
+ { GDBUS_METHOD("Get",
+ GDBUS_ARGS({ "interface", "s" }, { "name", "s" }),
+ GDBUS_ARGS({ "value", "v" }),
+ properties_get) },
+ { GDBUS_ASYNC_METHOD("Set", NULL,
+ GDBUS_ARGS({ "interface", "s" }, { "name", "s" },
+ { "value", "v" }),
+ properties_set) },
+ { GDBUS_METHOD("GetAll",
+ GDBUS_ARGS({ "interface", "s" }),
+ GDBUS_ARGS({ "properties", "a{sv}" }),
+ properties_get_all) },
+ { }
+};
+
+static const GDBusSignalTable properties_signals[] = {
+ { GDBUS_SIGNAL("PropertiesChanged",
+ GDBUS_ARGS({ "interface", "s" },
+ { "changed_properties", "a{sv}" },
+ { "invalidated_properties", "as"})) },
+ { }
+};
+
static void add_interface(struct generic_data *data, const char *name,
const GDBusMethodTable *methods,
const GDBusSignalTable *signals,
@@ -557,6 +599,9 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
add_interface(data, DBUS_INTERFACE_INTROSPECTABLE,
introspect_methods, NULL, NULL, data, NULL);

+ add_interface(data, DBUS_INTERFACE_PROPERTIES, properties_methods,
+ properties_signals, NULL, data, NULL);
+
return data;
}

@@ -596,6 +641,7 @@ static void object_path_unref(DBusConnection *connection, const char *path)
return;

remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE);
+ remove_interface(data, DBUS_INTERFACE_PROPERTIES);

invalidate_parent_data(connection, path);

--
1.7.12.2


2012-10-04 07:26:28

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 04/15] gdbus: Implement DBus.Properties.Get method

From: Lucas De Marchi <[email protected]>

---
gdbus/gdbus.h | 8 ++++++++
gdbus/object.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 34e3cb3..b2e78c4 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -66,6 +66,12 @@ typedef void (* GDBusDestroyFunction) (void *user_data);
typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection,
DBusMessage *message, void *user_data);

+typedef gboolean (*GDBusPropertyGetter)(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data);
+
+typedef gboolean (*GDBusPropertyExists)(const GDBusPropertyTable *property,
+ void *data);
+
typedef guint32 GDBusPendingReply;

typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
@@ -116,6 +122,8 @@ struct GDBusSignalTable {
struct GDBusPropertyTable {
const char *name;
const char *type;
+ GDBusPropertyGetter get;
+ GDBusPropertyExists exists;
GDBusPropertyFlags flags;
};

diff --git a/gdbus/object.c b/gdbus/object.c
index 6c11528..89138f7 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -507,10 +507,70 @@ static const GDBusMethodTable introspect_methods[] = {
{ }
};

+static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *properties,
+ const char *name)
+{
+ const GDBusPropertyTable *p;
+
+ for (p = properties; p && p->name; p++) {
+ if (strcmp(name, p->name) == 0)
+ return p;
+ }
+
+ return NULL;
+}
+
static DBusMessage *properties_get(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
- return NULL;
+ struct generic_data *data = user_data;
+ struct interface_data *iface;
+ const GDBusPropertyTable *property;
+ const char *interface, *name;
+ DBusMessageIter iter, value;
+ DBusMessage *reply;
+
+ if (!dbus_message_get_args(message, NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ iface = find_interface(data->interfaces, interface);
+ if (iface == NULL)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No such interface '%s'", interface);
+
+ property = find_property(iface->properties, name);
+ if (property == NULL)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No such property '%s'", name);
+
+ if (property->exists != NULL &&
+ !property->exists(property, iface->user_data))
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "No such property '%s'", name);
+
+ if (property->get == NULL)
+ return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Property '%s' is not readable", name);
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+ property->type, &value);
+
+ if (!property->get(property, &value, iface->user_data)) {
+ dbus_message_unref(reply);
+ return NULL;
+ }
+
+ dbus_message_iter_close_container(&iter, &value);
+
+ return reply;
}

static DBusMessage *properties_get_all(DBusConnection *connection,
--
1.7.12.2


2012-10-04 07:26:26

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 02/15] gdbus: Use macros to add annotations

From: Lucas De Marchi <[email protected]>

Besides being more readable this way it avoids going over 80 chars.
---
gdbus/object.c | 40 ++++++++++++++++++++++++++++------------
1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/gdbus/object.c b/gdbus/object.c
index 9689006..24e8285 100644
--- a/gdbus/object.c
+++ b/gdbus/object.c
@@ -76,6 +76,16 @@ static void print_arguments(GString *gstr, const GDBusArgInfo *args,
}
}

+#define G_DBUS_ANNOTATE(prefix_, name_, value_) \
+ prefix_ "<annotation name=\"org.freedesktop.DBus." name_ "\" " \
+ "value=\"" value_ "\"/>\n"
+
+#define G_DBUS_ANNOTATE_DEPRECATED(prefix_) \
+ G_DBUS_ANNOTATE(prefix_, "Deprecated", "true")
+
+#define G_DBUS_ANNOTATE_NOREPLY(prefix_) \
+ G_DBUS_ANNOTATE(prefix_, "Method.NoReply", "true")
+
static void generate_interface_xml(GString *gstr, struct interface_data *iface)
{
const GDBusMethodTable *method;
@@ -90,19 +100,22 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
if (!deprecated && !noreply &&
!(method->in_args && method->in_args->name) &&
!(method->out_args && method->out_args->name))
- g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
- method->name);
+ g_string_append_printf(gstr,
+ "\t\t<method name=\"%s\"/>\n",
+ method->name);
else {
- g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
- method->name);
+ g_string_append_printf(gstr,
+ "\t\t<method name=\"%s\">\n",
+ method->name);
print_arguments(gstr, method->in_args, "in");
print_arguments(gstr, method->out_args, "out");

if (deprecated)
- g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
-
+ g_string_append_printf(gstr,
+ G_DBUS_ANNOTATE_DEPRECATED("\t\t\t"));
if (noreply)
- g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n");
+ g_string_append_printf(gstr,
+ G_DBUS_ANNOTATE_NOREPLY("\t\t\t"));

g_string_append_printf(gstr, "\t\t</method>\n");
}
@@ -113,15 +126,18 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
G_DBUS_SIGNAL_FLAG_DEPRECATED;

if (!deprecated && !(signal->args && signal->args->name))
- g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
- signal->name);
+ g_string_append_printf(gstr,
+ "\t\t<signal name=\"%s\"/>\n",
+ signal->name);
else {
- g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
- signal->name);
+ g_string_append_printf(gstr,
+ "\t\t<signal name=\"%s\">\n",
+ signal->name);
print_arguments(gstr, signal->args, NULL);

if (deprecated)
- g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
+ g_string_append_printf(gstr,
+ G_DBUS_ANNOTATE_DEPRECATED("\t\t\t"));

g_string_append_printf(gstr, "\t\t</signal>\n");
}
--
1.7.12.2


2012-10-04 07:26:25

by Lucas De Marchi

[permalink] [raw]
Subject: [PATCH BlueZ v4 01/15] gdbus: Move typedefs up

From: Lucas De Marchi <[email protected]>

Move the typedefs up so they can be used by functions and callbacks.
---
gdbus/gdbus.h | 47 +++++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
index 0a8a27c..34e3cb3 100644
--- a/gdbus/gdbus.h
+++ b/gdbus/gdbus.h
@@ -31,6 +31,17 @@ extern "C" {
#include <dbus/dbus.h>
#include <glib.h>

+typedef enum GDBusMethodFlags GDBusMethodFlags;
+typedef enum GDBusSignalFlags GDBusSignalFlags;
+typedef enum GDBusPropertyFlags GDBusPropertyFlags;
+typedef enum GDBusSecurityFlags GDBusSecurityFlags;
+
+typedef struct GDBusArgInfo GDBusArgInfo;
+typedef struct GDBusMethodTable GDBusMethodTable;
+typedef struct GDBusSignalTable GDBusSignalTable;
+typedef struct GDBusPropertyTable GDBusPropertyTable;
+typedef struct GDBusSecurityTable GDBusSecurityTable;
+
typedef void (* GDBusWatchFunction) (DBusConnection *connection,
void *user_data);

@@ -62,58 +73,58 @@ typedef void (* GDBusSecurityFunction) (DBusConnection *connection,
gboolean interaction,
GDBusPendingReply pending);

-typedef enum {
+enum GDBusMethodFlags {
G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0),
G_DBUS_METHOD_FLAG_NOREPLY = (1 << 1),
G_DBUS_METHOD_FLAG_ASYNC = (1 << 2),
-} GDBusMethodFlags;
+};

-typedef enum {
+enum GDBusSignalFlags {
G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0),
-} GDBusSignalFlags;
+};

-typedef enum {
+enum GDBusPropertyFlags {
G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0),
-} GDBusPropertyFlags;
+};

-typedef enum {
+enum GDBusSecurityFlags {
G_DBUS_SECURITY_FLAG_DEPRECATED = (1 << 0),
G_DBUS_SECURITY_FLAG_BUILTIN = (1 << 1),
G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION = (1 << 2),
-} GDBusSecurityFlags;
+};

-typedef struct {
+struct GDBusArgInfo {
const char *name;
const char *signature;
-} GDBusArgInfo;
+};

-typedef struct {
+struct GDBusMethodTable {
const char *name;
GDBusMethodFunction function;
GDBusMethodFlags flags;
unsigned int privilege;
const GDBusArgInfo *in_args;
const GDBusArgInfo *out_args;
-} GDBusMethodTable;
+};

-typedef struct {
+struct GDBusSignalTable {
const char *name;
GDBusSignalFlags flags;
const GDBusArgInfo *args;
-} GDBusSignalTable;
+};

-typedef struct {
+struct GDBusPropertyTable {
const char *name;
const char *type;
GDBusPropertyFlags flags;
-} GDBusPropertyTable;
+};

-typedef struct {
+struct GDBusSecurityTable {
unsigned int privilege;
const char *action;
GDBusSecurityFlags flags;
GDBusSecurityFunction function;
-} GDBusSecurityTable;
+};

#define GDBUS_ARGS(args...) (const GDBusArgInfo[]) { args, { } }

--
1.7.12.2