5 * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <dbus/dbus.h>
35 DBusConnection *dbus_conn;
39 GPtrArray *match_rules;
40 DBusPendingCall *pending_call;
41 GDBusWatchFunction connect_func;
43 GDBusWatchFunction disconn_func;
45 GDBusMessageFunction signal_func;
47 GDBusProxyFunction proxy_added;
48 GDBusProxyFunction proxy_removed;
49 GDBusPropertyFunction property_changed;
59 GHashTable *prop_list;
69 static void modify_match_reply(DBusPendingCall *call, void *user_data)
71 DBusMessage *reply = dbus_pending_call_steal_reply(call);
74 dbus_error_init(&error);
76 if (dbus_set_error_from_message(&error, reply) == TRUE)
77 dbus_error_free(&error);
79 dbus_message_unref(reply);
82 static gboolean modify_match(DBusConnection *conn, const char *member,
86 DBusPendingCall *call;
88 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
89 DBUS_INTERFACE_DBUS, member);
93 dbus_message_append_args(msg, DBUS_TYPE_STRING, &rule,
96 if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) {
97 dbus_message_unref(msg);
101 dbus_pending_call_set_notify(call, modify_match_reply, NULL, NULL);
102 dbus_pending_call_unref(call);
104 dbus_message_unref(msg);
109 static void iter_append_iter(DBusMessageIter *base, DBusMessageIter *iter)
113 type = dbus_message_iter_get_arg_type(iter);
115 if (dbus_type_is_basic(type)) {
118 dbus_message_iter_get_basic(iter, &value);
119 dbus_message_iter_append_basic(base, type, &value);
120 } else if (dbus_type_is_container(type)) {
121 DBusMessageIter iter_sub, base_sub;
124 dbus_message_iter_recurse(iter, &iter_sub);
127 case DBUS_TYPE_ARRAY:
128 case DBUS_TYPE_VARIANT:
129 sig = dbus_message_iter_get_signature(&iter_sub);
136 dbus_message_iter_open_container(base, type, sig, &base_sub);
141 while (dbus_message_iter_get_arg_type(&iter_sub) !=
143 iter_append_iter(&base_sub, &iter_sub);
144 dbus_message_iter_next(&iter_sub);
147 dbus_message_iter_close_container(base, &base_sub);
151 static void prop_entry_update(struct prop_entry *prop, DBusMessageIter *iter)
154 DBusMessageIter base;
156 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
160 dbus_message_iter_init_append(msg, &base);
161 iter_append_iter(&base, iter);
163 if (prop->msg != NULL)
164 dbus_message_unref(prop->msg);
166 prop->msg = dbus_message_copy(msg);
167 dbus_message_unref(msg);
170 static struct prop_entry *prop_entry_new(const char *name,
171 DBusMessageIter *iter)
173 struct prop_entry *prop;
175 prop = g_try_new0(struct prop_entry, 1);
179 prop->name = g_strdup(name);
180 prop->type = dbus_message_iter_get_arg_type(iter);
182 prop_entry_update(prop, iter);
187 static void prop_entry_free(gpointer data)
189 struct prop_entry *prop = data;
191 if (prop->msg != NULL)
192 dbus_message_unref(prop->msg);
199 static GDBusProxy *proxy_new(GDBusClient *client, const char *path,
200 const char *interface)
204 proxy = g_try_new0(GDBusProxy, 1);
208 proxy->client = client;
209 proxy->obj_path = g_strdup(path);
210 proxy->interface = g_strdup(interface);
212 proxy->prop_list = g_hash_table_new_full(g_str_hash, g_str_equal,
213 NULL, prop_entry_free);
215 proxy->match_rule = g_strdup_printf("type='signal',"
216 "sender='%s',path='%s',interface='%s',"
217 "member='PropertiesChanged',arg0='%s'",
218 client->service_name, proxy->obj_path,
219 DBUS_INTERFACE_PROPERTIES, proxy->interface);
221 modify_match(client->dbus_conn, "AddMatch", proxy->match_rule);
223 return g_dbus_proxy_ref(proxy);
226 static void proxy_free(gpointer data)
228 GDBusProxy *proxy = data;
231 GDBusClient *client = proxy->client;
233 if (client->proxy_removed)
234 client->proxy_removed(proxy, client->user_data);
236 modify_match(client->dbus_conn, "RemoveMatch",
239 g_free(proxy->match_rule);
240 proxy->match_rule = NULL;
242 g_hash_table_remove_all(proxy->prop_list);
244 proxy->client = NULL;
247 g_dbus_proxy_unref(proxy);
250 static void proxy_remove(GDBusClient *client, const char *path,
251 const char *interface)
255 for (list = g_list_first(client->proxy_list); list;
256 list = g_list_next(list)) {
257 GDBusProxy *proxy = list->data;
259 if (g_str_equal(proxy->interface, interface) == TRUE &&
260 g_str_equal(proxy->obj_path, path) == TRUE) {
262 g_list_delete_link(client->proxy_list, list);
269 GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy)
274 g_atomic_int_inc(&proxy->ref_count);
279 void g_dbus_proxy_unref(GDBusProxy *proxy)
284 if (g_atomic_int_dec_and_test(&proxy->ref_count) == FALSE)
287 g_hash_table_destroy(proxy->prop_list);
289 g_free(proxy->obj_path);
290 g_free(proxy->interface);
295 const char *g_dbus_proxy_get_path(GDBusProxy *proxy)
300 return proxy->obj_path;
303 const char *g_dbus_proxy_get_interface(GDBusProxy *proxy)
308 return proxy->interface;
311 gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name,
312 DBusMessageIter *iter)
314 struct prop_entry *prop;
316 if (proxy == NULL || name == NULL)
319 prop = g_hash_table_lookup(proxy->prop_list, name);
323 if (prop->msg == NULL)
326 if (dbus_message_iter_init(prop->msg, iter) == FALSE)
332 struct set_property_data {
333 GDBusResultFunction function;
335 GDBusDestroyFunction destroy;
338 static void set_property_reply(DBusPendingCall *call, void *user_data)
340 struct set_property_data *data = user_data;
341 DBusMessage *reply = dbus_pending_call_steal_reply(call);
344 dbus_error_init(&error);
346 dbus_set_error_from_message(&error, reply);
349 data->function(&error, data->user_data);
352 data->destroy(data->user_data);
354 dbus_error_free(&error);
356 dbus_message_unref(reply);
359 gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
360 const char *name, int type, const void *value,
361 GDBusResultFunction function, void *user_data,
362 GDBusDestroyFunction destroy)
364 struct set_property_data *data;
367 DBusMessageIter iter, variant;
368 DBusPendingCall *call;
371 if (proxy == NULL || name == NULL || value == NULL)
374 if (dbus_type_is_basic(type) == FALSE)
377 client = proxy->client;
381 data = g_try_new0(struct set_property_data, 1);
385 data->function = function;
386 data->user_data = user_data;
387 data->destroy = destroy;
389 msg = dbus_message_new_method_call(client->service_name,
390 proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Set");
396 type_as_str[0] = (char) type;
397 type_as_str[1] = '\0';
399 dbus_message_iter_init_append(msg, &iter);
400 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
402 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
404 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
405 type_as_str, &variant);
406 dbus_message_iter_append_basic(&variant, type, value);
407 dbus_message_iter_close_container(&iter, &variant);
409 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
410 &call, -1) == FALSE) {
411 dbus_message_unref(msg);
416 dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
417 dbus_pending_call_unref(call);
419 dbus_message_unref(msg);
424 struct method_call_data {
425 GDBusReturnFunction function;
427 GDBusDestroyFunction destroy;
430 static void method_call_reply(DBusPendingCall *call, void *user_data)
432 struct method_call_data *data = user_data;
433 DBusMessage *reply = dbus_pending_call_steal_reply(call);
436 data->function(reply, data->user_data);
439 data->destroy(data->user_data);
441 dbus_message_unref(reply);
444 gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
445 GDBusSetupFunction setup,
446 GDBusReturnFunction function, void *user_data,
447 GDBusDestroyFunction destroy)
449 struct method_call_data *data;
452 DBusPendingCall *call;
454 if (proxy == NULL || method == NULL)
457 client = proxy->client;
461 data = g_try_new0(struct method_call_data, 1);
465 data->function = function;
466 data->user_data = user_data;
467 data->destroy = destroy;
469 msg = dbus_message_new_method_call(client->service_name,
470 proxy->obj_path, proxy->interface, method);
477 DBusMessageIter iter;
479 dbus_message_iter_init_append(msg, &iter);
480 setup(&iter, data->user_data);
483 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
484 &call, -1) == FALSE) {
485 dbus_message_unref(msg);
490 dbus_pending_call_set_notify(call, method_call_reply, data, g_free);
491 dbus_pending_call_unref(call);
493 dbus_message_unref(msg);
498 static void add_property(GDBusProxy *proxy, const char *name,
499 DBusMessageIter *iter)
501 DBusMessageIter value;
502 struct prop_entry *prop;
504 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
507 dbus_message_iter_recurse(iter, &value);
509 prop = g_hash_table_lookup(proxy->prop_list, name);
511 GDBusClient *client = proxy->client;
513 prop_entry_update(prop, &value);
518 if (client->property_changed)
519 client->property_changed(proxy, name, &value,
524 prop = prop_entry_new(name, &value);
528 g_hash_table_replace(proxy->prop_list, prop->name, prop);
531 static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter)
533 DBusMessageIter dict;
535 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
538 dbus_message_iter_recurse(iter, &dict);
540 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
541 DBusMessageIter entry;
544 dbus_message_iter_recurse(&dict, &entry);
546 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
549 dbus_message_iter_get_basic(&entry, &name);
550 dbus_message_iter_next(&entry);
552 add_property(proxy, name, &entry);
554 dbus_message_iter_next(&dict);
558 static void properties_changed(GDBusClient *client, const char *path,
561 GDBusProxy *proxy = NULL;
562 DBusMessageIter iter, entry;
563 const char *interface;
566 if (dbus_message_iter_init(msg, &iter) == FALSE)
569 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
572 dbus_message_iter_get_basic(&iter, &interface);
573 dbus_message_iter_next(&iter);
575 for (list = g_list_first(client->proxy_list); list;
576 list = g_list_next(list)) {
577 GDBusProxy *data = list->data;
579 if (g_str_equal(data->interface, interface) == TRUE &&
580 g_str_equal(data->obj_path, path) == TRUE) {
589 update_properties(proxy, &iter);
591 dbus_message_iter_next(&iter);
593 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
596 dbus_message_iter_recurse(&iter, &entry);
598 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
601 dbus_message_iter_get_basic(&entry, &name);
603 g_hash_table_remove(proxy->prop_list, name);
605 if (client->property_changed)
606 client->property_changed(proxy, name, NULL,
609 dbus_message_iter_next(&entry);
613 static void parse_properties(GDBusClient *client, const char *path,
614 const char *interface, DBusMessageIter *iter)
618 if (g_str_equal(interface, DBUS_INTERFACE_INTROSPECTABLE) == TRUE)
621 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE)
624 proxy = proxy_new(client, path, interface);
628 update_properties(proxy, iter);
630 if (client->proxy_added)
631 client->proxy_added(proxy, client->user_data);
633 client->proxy_list = g_list_append(client->proxy_list, proxy);
636 static void parse_interfaces(GDBusClient *client, const char *path,
637 DBusMessageIter *iter)
639 DBusMessageIter dict;
641 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
644 dbus_message_iter_recurse(iter, &dict);
646 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
647 DBusMessageIter entry;
648 const char *interface;
650 dbus_message_iter_recurse(&dict, &entry);
652 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
655 dbus_message_iter_get_basic(&entry, &interface);
656 dbus_message_iter_next(&entry);
658 parse_properties(client, path, interface, &entry);
660 dbus_message_iter_next(&dict);
664 static void interfaces_added(GDBusClient *client, DBusMessage *msg)
666 DBusMessageIter iter;
669 if (dbus_message_iter_init(msg, &iter) == FALSE)
672 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
675 dbus_message_iter_get_basic(&iter, &path);
676 dbus_message_iter_next(&iter);
678 parse_interfaces(client, path, &iter);
681 static void interfaces_removed(GDBusClient *client, DBusMessage *msg)
683 DBusMessageIter iter, entry;
686 if (dbus_message_iter_init(msg, &iter) == FALSE)
689 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
692 dbus_message_iter_get_basic(&iter, &path);
693 dbus_message_iter_next(&iter);
695 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
698 dbus_message_iter_recurse(&iter, &entry);
700 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
701 const char *interface;
703 dbus_message_iter_get_basic(&entry, &interface);
704 proxy_remove(client, path, interface);
705 dbus_message_iter_next(&entry);
709 static void parse_managed_objects(GDBusClient *client, DBusMessage *msg)
711 DBusMessageIter iter, dict;
713 if (dbus_message_iter_init(msg, &iter) == FALSE)
716 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
719 dbus_message_iter_recurse(&iter, &dict);
721 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
722 DBusMessageIter entry;
725 dbus_message_iter_recurse(&dict, &entry);
727 if (dbus_message_iter_get_arg_type(&entry) !=
728 DBUS_TYPE_OBJECT_PATH)
731 dbus_message_iter_get_basic(&entry, &path);
732 dbus_message_iter_next(&entry);
734 parse_interfaces(client, path, &entry);
736 dbus_message_iter_next(&dict);
740 static void get_managed_objects_reply(DBusPendingCall *call, void *user_data)
742 GDBusClient *client = user_data;
743 DBusMessage *reply = dbus_pending_call_steal_reply(call);
746 dbus_error_init(&error);
748 if (dbus_set_error_from_message(&error, reply) == TRUE) {
749 dbus_error_free(&error);
753 parse_managed_objects(client, reply);
756 dbus_message_unref(reply);
758 dbus_pending_call_unref(client->pending_call);
759 client->pending_call = NULL;
761 g_dbus_client_unref(client);
764 static void get_managed_objects(GDBusClient *client)
768 msg = dbus_message_new_method_call("org.bluez", "/",
769 DBUS_INTERFACE_DBUS ".ObjectManager",
770 "GetManagedObjects");
774 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
776 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
777 &client->pending_call, -1) == FALSE) {
778 dbus_message_unref(msg);
782 g_dbus_client_ref(client);
784 dbus_pending_call_set_notify(client->pending_call,
785 get_managed_objects_reply, client, NULL);
787 dbus_message_unref(msg);
790 static void get_name_owner_reply(DBusPendingCall *call, void *user_data)
792 GDBusClient *client = user_data;
793 DBusMessage *reply = dbus_pending_call_steal_reply(call);
797 dbus_error_init(&error);
799 if (dbus_set_error_from_message(&error, reply) == TRUE) {
800 dbus_error_free(&error);
804 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &name,
805 DBUS_TYPE_INVALID) == FALSE)
808 g_free(client->unique_name);
809 client->unique_name = g_strdup(name);
811 g_dbus_client_ref(client);
813 if (client->connect_func)
814 client->connect_func(client->dbus_conn, client->connect_data);
817 dbus_message_unref(reply);
819 dbus_pending_call_unref(client->pending_call);
820 client->pending_call = NULL;
822 get_managed_objects(client);
824 g_dbus_client_unref(client);
827 static void get_name_owner(GDBusClient *client, const char *name)
831 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
832 DBUS_INTERFACE_DBUS, "GetNameOwner");
836 dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
839 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
840 &client->pending_call, -1) == FALSE) {
841 dbus_message_unref(msg);
845 dbus_pending_call_set_notify(client->pending_call,
846 get_name_owner_reply, client, NULL);
848 dbus_message_unref(msg);
851 static DBusHandlerResult message_filter(DBusConnection *connection,
852 DBusMessage *message, void *user_data)
854 GDBusClient *client = user_data;
857 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
858 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
860 sender = dbus_message_get_sender(message);
862 if (g_str_equal(sender, DBUS_SERVICE_DBUS) == TRUE) {
863 const char *interface, *member;
864 const char *name, *old, *new;
866 interface = dbus_message_get_interface(message);
868 if (g_str_equal(interface, DBUS_INTERFACE_DBUS) == FALSE)
869 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
871 member = dbus_message_get_member(message);
873 if (g_str_equal(member, "NameOwnerChanged") == FALSE)
874 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
876 if (dbus_message_get_args(message, NULL,
877 DBUS_TYPE_STRING, &name,
878 DBUS_TYPE_STRING, &old,
879 DBUS_TYPE_STRING, &new,
880 DBUS_TYPE_INVALID) == FALSE)
881 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
883 if (g_str_equal(name, client->service_name) == FALSE)
884 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
887 if (client->disconn_func)
888 client->disconn_func(client->dbus_conn,
889 client->disconn_data);
891 g_free(client->unique_name);
892 client->unique_name = NULL;
893 } else if (*old == '\0') {
894 g_free(client->unique_name);
895 client->unique_name = g_strdup(new);
897 if (client->connect_func)
898 client->connect_func(client->dbus_conn,
899 client->connect_data);
901 get_managed_objects(client);
904 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
907 if (client->unique_name == NULL)
908 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
910 if (g_str_equal(sender, client->unique_name) == TRUE) {
911 const char *path, *interface, *member;
913 path = dbus_message_get_path(message);
914 interface = dbus_message_get_interface(message);
915 member = dbus_message_get_member(message);
917 if (g_str_equal(path, "/") == TRUE) {
918 if (g_str_equal(interface, DBUS_INTERFACE_DBUS
919 ".ObjectManager") == FALSE)
920 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
922 if (g_str_equal(member, "InterfacesAdded") == TRUE) {
923 interfaces_added(client, message);
924 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
927 if (g_str_equal(member, "InterfacesRemoved") == TRUE) {
928 interfaces_removed(client, message);
929 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
932 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
935 if (g_str_has_prefix(path, client->base_path) == FALSE)
936 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
938 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE) {
939 if (g_str_equal(member, "PropertiesChanged") == TRUE)
940 properties_changed(client, path, message);
942 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
945 if (client->signal_func)
946 client->signal_func(client->dbus_conn,
947 message, client->signal_data);
950 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
953 GDBusClient *g_dbus_client_new(DBusConnection *connection,
954 const char *service, const char *path)
959 if (connection == NULL)
962 client = g_try_new0(GDBusClient, 1);
966 if (dbus_connection_add_filter(connection, message_filter,
967 client, NULL) == FALSE) {
972 client->dbus_conn = dbus_connection_ref(connection);
973 client->service_name = g_strdup(service);
974 client->base_path = g_strdup(path);
976 get_name_owner(client, client->service_name);
978 client->match_rules = g_ptr_array_new_full(4, g_free);
980 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
981 "sender='%s',path='%s',interface='%s',"
982 "member='NameOwnerChanged',arg0='%s'",
983 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
984 DBUS_INTERFACE_DBUS, client->service_name));
985 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
987 "path='/',interface='%s.ObjectManager',"
988 "member='InterfacesAdded'",
989 client->service_name, DBUS_INTERFACE_DBUS));
990 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
992 "path='/',interface='%s.ObjectManager',"
993 "member='InterfacesRemoved'",
994 client->service_name, DBUS_INTERFACE_DBUS));
995 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
996 "sender='%s',path_namespace='%s'",
997 client->service_name, client->base_path));
999 for (i = 0; i < client->match_rules->len; i++) {
1000 modify_match(client->dbus_conn, "AddMatch",
1001 g_ptr_array_index(client->match_rules, i));
1004 return g_dbus_client_ref(client);
1007 GDBusClient *g_dbus_client_ref(GDBusClient *client)
1012 g_atomic_int_inc(&client->ref_count);
1017 void g_dbus_client_unref(GDBusClient *client)
1024 if (g_atomic_int_dec_and_test(&client->ref_count) == FALSE)
1027 if (client->pending_call != NULL) {
1028 dbus_pending_call_cancel(client->pending_call);
1029 dbus_pending_call_unref(client->pending_call);
1032 for (i = 0; i < client->match_rules->len; i++) {
1033 modify_match(client->dbus_conn, "RemoveMatch",
1034 g_ptr_array_index(client->match_rules, i));
1037 g_ptr_array_free(client->match_rules, TRUE);
1039 dbus_connection_remove_filter(client->dbus_conn,
1040 message_filter, client);
1042 g_list_free_full(client->proxy_list, proxy_free);
1044 if (client->disconn_func)
1045 client->disconn_func(client->dbus_conn, client->disconn_data);
1047 dbus_connection_unref(client->dbus_conn);
1049 g_free(client->service_name);
1050 g_free(client->unique_name);
1051 g_free(client->base_path);
1056 gboolean g_dbus_client_set_connect_watch(GDBusClient *client,
1057 GDBusWatchFunction function, void *user_data)
1062 client->connect_func = function;
1063 client->connect_data = user_data;
1068 gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client,
1069 GDBusWatchFunction function, void *user_data)
1074 client->disconn_func = function;
1075 client->disconn_data = user_data;
1080 gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
1081 GDBusMessageFunction function, void *user_data)
1086 client->signal_func = function;
1087 client->signal_data = user_data;
1092 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
1093 GDBusProxyFunction proxy_added,
1094 GDBusProxyFunction proxy_removed,
1095 GDBusPropertyFunction property_changed,
1101 client->proxy_added = proxy_added;
1102 client->proxy_removed = proxy_removed;
1103 client->property_changed = property_changed;
1104 client->user_data = user_data;