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>
33 #define METHOD_CALL_TIMEOUT (300 * 1000)
37 DBusConnection *dbus_conn;
41 GPtrArray *match_rules;
42 DBusPendingCall *pending_call;
43 GDBusWatchFunction connect_func;
45 GDBusWatchFunction disconn_func;
47 GDBusMessageFunction signal_func;
49 GDBusProxyFunction proxy_added;
50 GDBusProxyFunction proxy_removed;
51 GDBusPropertyFunction property_changed;
61 GHashTable *prop_list;
71 static void modify_match_reply(DBusPendingCall *call, void *user_data)
73 DBusMessage *reply = dbus_pending_call_steal_reply(call);
76 dbus_error_init(&error);
78 if (dbus_set_error_from_message(&error, reply) == TRUE)
79 dbus_error_free(&error);
81 dbus_message_unref(reply);
84 static gboolean modify_match(DBusConnection *conn, const char *member,
88 DBusPendingCall *call;
90 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
91 DBUS_INTERFACE_DBUS, member);
95 dbus_message_append_args(msg, DBUS_TYPE_STRING, &rule,
98 if (dbus_connection_send_with_reply(conn, msg, &call, -1) == FALSE) {
99 dbus_message_unref(msg);
103 dbus_pending_call_set_notify(call, modify_match_reply, NULL, NULL);
104 dbus_pending_call_unref(call);
106 dbus_message_unref(msg);
111 static void iter_append_iter(DBusMessageIter *base, DBusMessageIter *iter)
115 type = dbus_message_iter_get_arg_type(iter);
117 if (dbus_type_is_basic(type)) {
120 dbus_message_iter_get_basic(iter, &value);
121 dbus_message_iter_append_basic(base, type, &value);
122 } else if (dbus_type_is_container(type)) {
123 DBusMessageIter iter_sub, base_sub;
126 dbus_message_iter_recurse(iter, &iter_sub);
129 case DBUS_TYPE_ARRAY:
130 case DBUS_TYPE_VARIANT:
131 sig = dbus_message_iter_get_signature(&iter_sub);
138 dbus_message_iter_open_container(base, type, sig, &base_sub);
143 while (dbus_message_iter_get_arg_type(&iter_sub) !=
145 iter_append_iter(&base_sub, &iter_sub);
146 dbus_message_iter_next(&iter_sub);
149 dbus_message_iter_close_container(base, &base_sub);
153 static void prop_entry_update(struct prop_entry *prop, DBusMessageIter *iter)
156 DBusMessageIter base;
158 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
162 dbus_message_iter_init_append(msg, &base);
163 iter_append_iter(&base, iter);
165 if (prop->msg != NULL)
166 dbus_message_unref(prop->msg);
168 prop->msg = dbus_message_copy(msg);
169 dbus_message_unref(msg);
172 static struct prop_entry *prop_entry_new(const char *name,
173 DBusMessageIter *iter)
175 struct prop_entry *prop;
177 prop = g_try_new0(struct prop_entry, 1);
181 prop->name = g_strdup(name);
182 prop->type = dbus_message_iter_get_arg_type(iter);
184 prop_entry_update(prop, iter);
189 static void prop_entry_free(gpointer data)
191 struct prop_entry *prop = data;
193 if (prop->msg != NULL)
194 dbus_message_unref(prop->msg);
201 static GDBusProxy *proxy_lookup(GDBusClient *client, const char *path,
202 const char *interface)
206 for (list = g_list_first(client->proxy_list); list;
207 list = g_list_next(list)) {
208 GDBusProxy *proxy = list->data;
210 if (g_str_equal(proxy->interface, interface) == TRUE &&
211 g_str_equal(proxy->obj_path, path) == TRUE)
218 static GDBusProxy *proxy_new(GDBusClient *client, const char *path,
219 const char *interface)
223 proxy = g_try_new0(GDBusProxy, 1);
227 proxy->client = client;
228 proxy->obj_path = g_strdup(path);
229 proxy->interface = g_strdup(interface);
231 proxy->prop_list = g_hash_table_new_full(g_str_hash, g_str_equal,
232 NULL, prop_entry_free);
234 proxy->match_rule = g_strdup_printf("type='signal',"
235 "sender='%s',path='%s',interface='%s',"
236 "member='PropertiesChanged',arg0='%s'",
237 client->service_name, proxy->obj_path,
238 DBUS_INTERFACE_PROPERTIES, proxy->interface);
240 modify_match(client->dbus_conn, "AddMatch", proxy->match_rule);
242 return g_dbus_proxy_ref(proxy);
245 static void proxy_free(gpointer data)
247 GDBusProxy *proxy = data;
250 GDBusClient *client = proxy->client;
252 if (client->proxy_removed)
253 client->proxy_removed(proxy, client->user_data);
255 modify_match(client->dbus_conn, "RemoveMatch",
258 g_free(proxy->match_rule);
259 proxy->match_rule = NULL;
261 g_hash_table_remove_all(proxy->prop_list);
263 proxy->client = NULL;
266 g_dbus_proxy_unref(proxy);
269 static void proxy_remove(GDBusClient *client, const char *path,
270 const char *interface)
274 for (list = g_list_first(client->proxy_list); list;
275 list = g_list_next(list)) {
276 GDBusProxy *proxy = list->data;
278 if (g_str_equal(proxy->interface, interface) == TRUE &&
279 g_str_equal(proxy->obj_path, path) == TRUE) {
281 g_list_delete_link(client->proxy_list, list);
288 GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy)
293 g_atomic_int_inc(&proxy->ref_count);
298 void g_dbus_proxy_unref(GDBusProxy *proxy)
303 if (g_atomic_int_dec_and_test(&proxy->ref_count) == FALSE)
306 g_hash_table_destroy(proxy->prop_list);
308 g_free(proxy->obj_path);
309 g_free(proxy->interface);
314 const char *g_dbus_proxy_get_path(GDBusProxy *proxy)
319 return proxy->obj_path;
322 const char *g_dbus_proxy_get_interface(GDBusProxy *proxy)
327 return proxy->interface;
330 gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name,
331 DBusMessageIter *iter)
333 struct prop_entry *prop;
335 if (proxy == NULL || name == NULL)
338 prop = g_hash_table_lookup(proxy->prop_list, name);
342 if (prop->msg == NULL)
345 if (dbus_message_iter_init(prop->msg, iter) == FALSE)
351 struct set_property_data {
352 GDBusResultFunction function;
354 GDBusDestroyFunction destroy;
357 static void set_property_reply(DBusPendingCall *call, void *user_data)
359 struct set_property_data *data = user_data;
360 DBusMessage *reply = dbus_pending_call_steal_reply(call);
363 dbus_error_init(&error);
365 dbus_set_error_from_message(&error, reply);
368 data->function(&error, data->user_data);
371 data->destroy(data->user_data);
373 dbus_error_free(&error);
375 dbus_message_unref(reply);
378 gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
379 const char *name, int type, const void *value,
380 GDBusResultFunction function, void *user_data,
381 GDBusDestroyFunction destroy)
383 struct set_property_data *data;
386 DBusMessageIter iter, variant;
387 DBusPendingCall *call;
390 if (proxy == NULL || name == NULL || value == NULL)
393 if (dbus_type_is_basic(type) == FALSE)
396 client = proxy->client;
400 data = g_try_new0(struct set_property_data, 1);
404 data->function = function;
405 data->user_data = user_data;
406 data->destroy = destroy;
408 msg = dbus_message_new_method_call(client->service_name,
409 proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Set");
415 type_as_str[0] = (char) type;
416 type_as_str[1] = '\0';
418 dbus_message_iter_init_append(msg, &iter);
419 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
421 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
423 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
424 type_as_str, &variant);
425 dbus_message_iter_append_basic(&variant, type, value);
426 dbus_message_iter_close_container(&iter, &variant);
428 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
429 &call, -1) == FALSE) {
430 dbus_message_unref(msg);
435 dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
436 dbus_pending_call_unref(call);
438 dbus_message_unref(msg);
443 struct method_call_data {
444 GDBusReturnFunction function;
446 GDBusDestroyFunction destroy;
449 static void method_call_reply(DBusPendingCall *call, void *user_data)
451 struct method_call_data *data = user_data;
452 DBusMessage *reply = dbus_pending_call_steal_reply(call);
455 data->function(reply, data->user_data);
458 data->destroy(data->user_data);
460 dbus_message_unref(reply);
463 gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
464 GDBusSetupFunction setup,
465 GDBusReturnFunction function, void *user_data,
466 GDBusDestroyFunction destroy)
468 struct method_call_data *data;
471 DBusPendingCall *call;
473 if (proxy == NULL || method == NULL)
476 client = proxy->client;
480 data = g_try_new0(struct method_call_data, 1);
484 data->function = function;
485 data->user_data = user_data;
486 data->destroy = destroy;
488 msg = dbus_message_new_method_call(client->service_name,
489 proxy->obj_path, proxy->interface, method);
496 DBusMessageIter iter;
498 dbus_message_iter_init_append(msg, &iter);
499 setup(&iter, data->user_data);
502 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
503 &call, METHOD_CALL_TIMEOUT) == FALSE) {
504 dbus_message_unref(msg);
509 dbus_pending_call_set_notify(call, method_call_reply, data, g_free);
510 dbus_pending_call_unref(call);
512 dbus_message_unref(msg);
517 static void add_property(GDBusProxy *proxy, const char *name,
518 DBusMessageIter *iter)
520 DBusMessageIter value;
521 struct prop_entry *prop;
523 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
526 dbus_message_iter_recurse(iter, &value);
528 prop = g_hash_table_lookup(proxy->prop_list, name);
530 GDBusClient *client = proxy->client;
532 prop_entry_update(prop, &value);
537 if (client->property_changed)
538 client->property_changed(proxy, name, &value,
543 prop = prop_entry_new(name, &value);
547 g_hash_table_replace(proxy->prop_list, prop->name, prop);
550 static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter)
552 DBusMessageIter dict;
554 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
557 dbus_message_iter_recurse(iter, &dict);
559 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
560 DBusMessageIter entry;
563 dbus_message_iter_recurse(&dict, &entry);
565 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
568 dbus_message_iter_get_basic(&entry, &name);
569 dbus_message_iter_next(&entry);
571 add_property(proxy, name, &entry);
573 dbus_message_iter_next(&dict);
577 static void properties_changed(GDBusClient *client, const char *path,
580 GDBusProxy *proxy = NULL;
581 DBusMessageIter iter, entry;
582 const char *interface;
585 if (dbus_message_iter_init(msg, &iter) == FALSE)
588 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
591 dbus_message_iter_get_basic(&iter, &interface);
592 dbus_message_iter_next(&iter);
594 for (list = g_list_first(client->proxy_list); list;
595 list = g_list_next(list)) {
596 GDBusProxy *data = list->data;
598 if (g_str_equal(data->interface, interface) == TRUE &&
599 g_str_equal(data->obj_path, path) == TRUE) {
608 update_properties(proxy, &iter);
610 dbus_message_iter_next(&iter);
612 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
615 dbus_message_iter_recurse(&iter, &entry);
617 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
620 dbus_message_iter_get_basic(&entry, &name);
622 g_hash_table_remove(proxy->prop_list, name);
624 if (client->property_changed)
625 client->property_changed(proxy, name, NULL,
628 dbus_message_iter_next(&entry);
632 static void parse_properties(GDBusClient *client, const char *path,
633 const char *interface, DBusMessageIter *iter)
637 if (g_str_equal(interface, DBUS_INTERFACE_INTROSPECTABLE) == TRUE)
640 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE)
643 proxy = proxy_lookup(client, path, interface);
645 update_properties(proxy, iter);
649 proxy = proxy_new(client, path, interface);
653 update_properties(proxy, iter);
655 if (client->proxy_added)
656 client->proxy_added(proxy, client->user_data);
658 client->proxy_list = g_list_append(client->proxy_list, proxy);
661 static void parse_interfaces(GDBusClient *client, const char *path,
662 DBusMessageIter *iter)
664 DBusMessageIter dict;
666 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
669 dbus_message_iter_recurse(iter, &dict);
671 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
672 DBusMessageIter entry;
673 const char *interface;
675 dbus_message_iter_recurse(&dict, &entry);
677 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
680 dbus_message_iter_get_basic(&entry, &interface);
681 dbus_message_iter_next(&entry);
683 parse_properties(client, path, interface, &entry);
685 dbus_message_iter_next(&dict);
689 static void interfaces_added(GDBusClient *client, DBusMessage *msg)
691 DBusMessageIter iter;
694 if (dbus_message_iter_init(msg, &iter) == FALSE)
697 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
700 dbus_message_iter_get_basic(&iter, &path);
701 dbus_message_iter_next(&iter);
703 g_dbus_client_ref(client);
705 parse_interfaces(client, path, &iter);
707 g_dbus_client_unref(client);
710 static void interfaces_removed(GDBusClient *client, DBusMessage *msg)
712 DBusMessageIter iter, entry;
715 if (dbus_message_iter_init(msg, &iter) == FALSE)
718 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
721 dbus_message_iter_get_basic(&iter, &path);
722 dbus_message_iter_next(&iter);
724 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
727 dbus_message_iter_recurse(&iter, &entry);
729 g_dbus_client_ref(client);
731 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
732 const char *interface;
734 dbus_message_iter_get_basic(&entry, &interface);
735 proxy_remove(client, path, interface);
736 dbus_message_iter_next(&entry);
739 g_dbus_client_unref(client);
742 static void parse_managed_objects(GDBusClient *client, DBusMessage *msg)
744 DBusMessageIter iter, dict;
746 if (dbus_message_iter_init(msg, &iter) == FALSE)
749 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
752 dbus_message_iter_recurse(&iter, &dict);
754 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
755 DBusMessageIter entry;
758 dbus_message_iter_recurse(&dict, &entry);
760 if (dbus_message_iter_get_arg_type(&entry) !=
761 DBUS_TYPE_OBJECT_PATH)
764 dbus_message_iter_get_basic(&entry, &path);
765 dbus_message_iter_next(&entry);
767 parse_interfaces(client, path, &entry);
769 dbus_message_iter_next(&dict);
773 static void get_managed_objects_reply(DBusPendingCall *call, void *user_data)
775 GDBusClient *client = user_data;
776 DBusMessage *reply = dbus_pending_call_steal_reply(call);
779 dbus_error_init(&error);
781 if (dbus_set_error_from_message(&error, reply) == TRUE) {
782 dbus_error_free(&error);
786 parse_managed_objects(client, reply);
789 dbus_message_unref(reply);
791 dbus_pending_call_unref(client->pending_call);
792 client->pending_call = NULL;
794 g_dbus_client_unref(client);
797 static void get_managed_objects(GDBusClient *client)
801 msg = dbus_message_new_method_call("org.bluez", "/",
802 DBUS_INTERFACE_DBUS ".ObjectManager",
803 "GetManagedObjects");
807 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
809 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
810 &client->pending_call, -1) == FALSE) {
811 dbus_message_unref(msg);
815 g_dbus_client_ref(client);
817 dbus_pending_call_set_notify(client->pending_call,
818 get_managed_objects_reply, client, NULL);
820 dbus_message_unref(msg);
823 static void get_name_owner_reply(DBusPendingCall *call, void *user_data)
825 GDBusClient *client = user_data;
826 DBusMessage *reply = dbus_pending_call_steal_reply(call);
830 dbus_error_init(&error);
832 if (dbus_set_error_from_message(&error, reply) == TRUE) {
833 dbus_error_free(&error);
837 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &name,
838 DBUS_TYPE_INVALID) == FALSE)
841 g_free(client->unique_name);
842 client->unique_name = g_strdup(name);
844 g_dbus_client_ref(client);
846 if (client->connect_func)
847 client->connect_func(client->dbus_conn, client->connect_data);
850 dbus_message_unref(reply);
852 dbus_pending_call_unref(client->pending_call);
853 client->pending_call = NULL;
855 get_managed_objects(client);
857 g_dbus_client_unref(client);
860 static void get_name_owner(GDBusClient *client, const char *name)
864 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
865 DBUS_INTERFACE_DBUS, "GetNameOwner");
869 dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
872 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
873 &client->pending_call, -1) == FALSE) {
874 dbus_message_unref(msg);
878 dbus_pending_call_set_notify(client->pending_call,
879 get_name_owner_reply, client, NULL);
881 dbus_message_unref(msg);
884 static DBusHandlerResult message_filter(DBusConnection *connection,
885 DBusMessage *message, void *user_data)
887 GDBusClient *client = user_data;
890 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
891 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
893 sender = dbus_message_get_sender(message);
895 if (g_str_equal(sender, DBUS_SERVICE_DBUS) == TRUE) {
896 const char *interface, *member;
897 const char *name, *old, *new;
899 interface = dbus_message_get_interface(message);
901 if (g_str_equal(interface, DBUS_INTERFACE_DBUS) == FALSE)
902 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
904 member = dbus_message_get_member(message);
906 if (g_str_equal(member, "NameOwnerChanged") == FALSE)
907 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
909 if (dbus_message_get_args(message, NULL,
910 DBUS_TYPE_STRING, &name,
911 DBUS_TYPE_STRING, &old,
912 DBUS_TYPE_STRING, &new,
913 DBUS_TYPE_INVALID) == FALSE)
914 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
916 if (g_str_equal(name, client->service_name) == FALSE)
917 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
920 if (client->disconn_func)
921 client->disconn_func(client->dbus_conn,
922 client->disconn_data);
924 g_free(client->unique_name);
925 client->unique_name = NULL;
926 } else if (*old == '\0') {
927 g_free(client->unique_name);
928 client->unique_name = g_strdup(new);
930 if (client->connect_func)
931 client->connect_func(client->dbus_conn,
932 client->connect_data);
934 get_managed_objects(client);
937 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
940 if (client->unique_name == NULL)
941 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
943 if (g_str_equal(sender, client->unique_name) == TRUE) {
944 const char *path, *interface, *member;
946 path = dbus_message_get_path(message);
947 interface = dbus_message_get_interface(message);
948 member = dbus_message_get_member(message);
950 if (g_str_equal(path, "/") == TRUE) {
951 if (g_str_equal(interface, DBUS_INTERFACE_DBUS
952 ".ObjectManager") == FALSE)
953 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
955 if (g_str_equal(member, "InterfacesAdded") == TRUE) {
956 interfaces_added(client, message);
957 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
960 if (g_str_equal(member, "InterfacesRemoved") == TRUE) {
961 interfaces_removed(client, message);
962 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
965 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
968 if (g_str_has_prefix(path, client->base_path) == FALSE)
969 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
971 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE) {
972 if (g_str_equal(member, "PropertiesChanged") == TRUE)
973 properties_changed(client, path, message);
975 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
978 if (client->signal_func)
979 client->signal_func(client->dbus_conn,
980 message, client->signal_data);
983 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
986 GDBusClient *g_dbus_client_new(DBusConnection *connection,
987 const char *service, const char *path)
992 if (connection == NULL)
995 client = g_try_new0(GDBusClient, 1);
999 if (dbus_connection_add_filter(connection, message_filter,
1000 client, NULL) == FALSE) {
1005 client->dbus_conn = dbus_connection_ref(connection);
1006 client->service_name = g_strdup(service);
1007 client->base_path = g_strdup(path);
1009 get_name_owner(client, client->service_name);
1011 client->match_rules = g_ptr_array_new_full(4, g_free);
1013 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1014 "sender='%s',path='%s',interface='%s',"
1015 "member='NameOwnerChanged',arg0='%s'",
1016 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
1017 DBUS_INTERFACE_DBUS, client->service_name));
1018 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1020 "path='/',interface='%s.ObjectManager',"
1021 "member='InterfacesAdded'",
1022 client->service_name, DBUS_INTERFACE_DBUS));
1023 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1025 "path='/',interface='%s.ObjectManager',"
1026 "member='InterfacesRemoved'",
1027 client->service_name, DBUS_INTERFACE_DBUS));
1028 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1029 "sender='%s',path_namespace='%s'",
1030 client->service_name, client->base_path));
1032 for (i = 0; i < client->match_rules->len; i++) {
1033 modify_match(client->dbus_conn, "AddMatch",
1034 g_ptr_array_index(client->match_rules, i));
1037 return g_dbus_client_ref(client);
1040 GDBusClient *g_dbus_client_ref(GDBusClient *client)
1045 g_atomic_int_inc(&client->ref_count);
1050 void g_dbus_client_unref(GDBusClient *client)
1057 if (g_atomic_int_dec_and_test(&client->ref_count) == FALSE)
1060 if (client->pending_call != NULL) {
1061 dbus_pending_call_cancel(client->pending_call);
1062 dbus_pending_call_unref(client->pending_call);
1065 for (i = 0; i < client->match_rules->len; i++) {
1066 modify_match(client->dbus_conn, "RemoveMatch",
1067 g_ptr_array_index(client->match_rules, i));
1070 g_ptr_array_free(client->match_rules, TRUE);
1072 dbus_connection_remove_filter(client->dbus_conn,
1073 message_filter, client);
1075 g_list_free_full(client->proxy_list, proxy_free);
1077 if (client->disconn_func)
1078 client->disconn_func(client->dbus_conn, client->disconn_data);
1080 dbus_connection_unref(client->dbus_conn);
1082 g_free(client->service_name);
1083 g_free(client->unique_name);
1084 g_free(client->base_path);
1089 gboolean g_dbus_client_set_connect_watch(GDBusClient *client,
1090 GDBusWatchFunction function, void *user_data)
1095 client->connect_func = function;
1096 client->connect_data = user_data;
1101 gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client,
1102 GDBusWatchFunction function, void *user_data)
1107 client->disconn_func = function;
1108 client->disconn_data = user_data;
1113 gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
1114 GDBusMessageFunction function, void *user_data)
1119 client->signal_func = function;
1120 client->signal_data = user_data;
1125 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
1126 GDBusProxyFunction proxy_added,
1127 GDBusProxyFunction proxy_removed,
1128 GDBusPropertyFunction property_changed,
1134 client->proxy_added = proxy_added;
1135 client->proxy_removed = proxy_removed;
1136 client->property_changed = property_changed;
1137 client->user_data = user_data;