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 void add_property(GDBusProxy *proxy, const char *name,
202 DBusMessageIter *iter)
204 DBusMessageIter value;
205 struct prop_entry *prop;
207 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
210 dbus_message_iter_recurse(iter, &value);
212 prop = g_hash_table_lookup(proxy->prop_list, name);
214 GDBusClient *client = proxy->client;
216 prop_entry_update(prop, &value);
221 if (client->property_changed)
222 client->property_changed(proxy, name, &value,
227 prop = prop_entry_new(name, &value);
231 g_hash_table_replace(proxy->prop_list, prop->name, prop);
234 static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter)
236 DBusMessageIter dict;
238 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
241 dbus_message_iter_recurse(iter, &dict);
243 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
244 DBusMessageIter entry;
247 dbus_message_iter_recurse(&dict, &entry);
249 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
252 dbus_message_iter_get_basic(&entry, &name);
253 dbus_message_iter_next(&entry);
255 add_property(proxy, name, &entry);
257 dbus_message_iter_next(&dict);
261 static void get_all_properties_reply(DBusPendingCall *call, void *user_data)
263 GDBusProxy *proxy = user_data;
264 DBusMessage *reply = dbus_pending_call_steal_reply(call);
265 DBusMessageIter iter;
268 dbus_error_init(&error);
270 if (dbus_set_error_from_message(&error, reply) == TRUE) {
271 dbus_error_free(&error);
275 dbus_message_iter_init(reply, &iter);
277 update_properties(proxy, &iter);
280 if (proxy->client != NULL) {
281 GDBusClient *client = proxy->client;
283 if (client->proxy_added)
284 client->proxy_added(proxy, client->user_data);
286 client->proxy_list = g_list_append(client->proxy_list, proxy);
288 g_dbus_proxy_unref(proxy);
290 dbus_message_unref(reply);
293 static void get_all_properties(GDBusProxy *proxy)
295 GDBusClient *client = proxy->client;
296 const char *service_name = client->service_name;
298 DBusPendingCall *call;
300 msg = dbus_message_new_method_call(service_name, proxy->obj_path,
301 DBUS_INTERFACE_PROPERTIES, "GetAll");
305 dbus_message_append_args(msg, DBUS_TYPE_STRING, &proxy->interface,
308 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
309 &call, -1) == FALSE) {
310 dbus_message_unref(msg);
314 g_dbus_proxy_ref(proxy);
316 dbus_pending_call_set_notify(call, get_all_properties_reply,
318 dbus_pending_call_unref(call);
320 dbus_message_unref(msg);
323 static GDBusProxy *proxy_lookup(GDBusClient *client, const char *path,
324 const char *interface)
328 for (list = g_list_first(client->proxy_list); list;
329 list = g_list_next(list)) {
330 GDBusProxy *proxy = list->data;
332 if (g_str_equal(proxy->interface, interface) == TRUE &&
333 g_str_equal(proxy->obj_path, path) == TRUE)
340 static GDBusProxy *proxy_new(GDBusClient *client, const char *path,
341 const char *interface)
345 proxy = g_try_new0(GDBusProxy, 1);
349 proxy->client = client;
350 proxy->obj_path = g_strdup(path);
351 proxy->interface = g_strdup(interface);
353 proxy->prop_list = g_hash_table_new_full(g_str_hash, g_str_equal,
354 NULL, prop_entry_free);
356 proxy->match_rule = g_strdup_printf("type='signal',"
357 "sender='%s',path='%s',interface='%s',"
358 "member='PropertiesChanged',arg0='%s'",
359 client->service_name, proxy->obj_path,
360 DBUS_INTERFACE_PROPERTIES, proxy->interface);
362 modify_match(client->dbus_conn, "AddMatch", proxy->match_rule);
364 return g_dbus_proxy_ref(proxy);
367 static void proxy_free(gpointer data)
369 GDBusProxy *proxy = data;
372 GDBusClient *client = proxy->client;
374 if (client->proxy_removed)
375 client->proxy_removed(proxy, client->user_data);
377 modify_match(client->dbus_conn, "RemoveMatch",
380 g_free(proxy->match_rule);
381 proxy->match_rule = NULL;
383 g_hash_table_remove_all(proxy->prop_list);
385 proxy->client = NULL;
388 g_dbus_proxy_unref(proxy);
391 static void proxy_remove(GDBusClient *client, const char *path,
392 const char *interface)
396 for (list = g_list_first(client->proxy_list); list;
397 list = g_list_next(list)) {
398 GDBusProxy *proxy = list->data;
400 if (g_str_equal(proxy->interface, interface) == TRUE &&
401 g_str_equal(proxy->obj_path, path) == TRUE) {
403 g_list_delete_link(client->proxy_list, list);
410 GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path,
411 const char *interface)
418 proxy = proxy_lookup(client, path, interface);
420 return g_dbus_proxy_ref(proxy);
422 proxy = proxy_new(client, path, interface);
426 get_all_properties(proxy);
431 GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy)
436 g_atomic_int_inc(&proxy->ref_count);
441 void g_dbus_proxy_unref(GDBusProxy *proxy)
446 if (g_atomic_int_dec_and_test(&proxy->ref_count) == FALSE)
449 g_hash_table_destroy(proxy->prop_list);
451 g_free(proxy->obj_path);
452 g_free(proxy->interface);
457 const char *g_dbus_proxy_get_path(GDBusProxy *proxy)
462 return proxy->obj_path;
465 const char *g_dbus_proxy_get_interface(GDBusProxy *proxy)
470 return proxy->interface;
473 gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name,
474 DBusMessageIter *iter)
476 struct prop_entry *prop;
478 if (proxy == NULL || name == NULL)
481 prop = g_hash_table_lookup(proxy->prop_list, name);
485 if (prop->msg == NULL)
488 if (dbus_message_iter_init(prop->msg, iter) == FALSE)
494 struct set_property_data {
495 GDBusResultFunction function;
497 GDBusDestroyFunction destroy;
500 static void set_property_reply(DBusPendingCall *call, void *user_data)
502 struct set_property_data *data = user_data;
503 DBusMessage *reply = dbus_pending_call_steal_reply(call);
506 dbus_error_init(&error);
508 dbus_set_error_from_message(&error, reply);
511 data->function(&error, data->user_data);
514 data->destroy(data->user_data);
516 dbus_error_free(&error);
518 dbus_message_unref(reply);
521 gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
522 const char *name, int type, const void *value,
523 GDBusResultFunction function, void *user_data,
524 GDBusDestroyFunction destroy)
526 struct set_property_data *data;
529 DBusMessageIter iter, variant;
530 DBusPendingCall *call;
533 if (proxy == NULL || name == NULL || value == NULL)
536 if (dbus_type_is_basic(type) == FALSE)
539 client = proxy->client;
543 data = g_try_new0(struct set_property_data, 1);
547 data->function = function;
548 data->user_data = user_data;
549 data->destroy = destroy;
551 msg = dbus_message_new_method_call(client->service_name,
552 proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Set");
558 type_as_str[0] = (char) type;
559 type_as_str[1] = '\0';
561 dbus_message_iter_init_append(msg, &iter);
562 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
564 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
566 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
567 type_as_str, &variant);
568 dbus_message_iter_append_basic(&variant, type, value);
569 dbus_message_iter_close_container(&iter, &variant);
571 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
572 &call, -1) == FALSE) {
573 dbus_message_unref(msg);
578 dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
579 dbus_pending_call_unref(call);
581 dbus_message_unref(msg);
586 struct method_call_data {
587 GDBusReturnFunction function;
589 GDBusDestroyFunction destroy;
592 static void method_call_reply(DBusPendingCall *call, void *user_data)
594 struct method_call_data *data = user_data;
595 DBusMessage *reply = dbus_pending_call_steal_reply(call);
598 data->function(reply, data->user_data);
601 data->destroy(data->user_data);
603 dbus_message_unref(reply);
606 gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
607 GDBusSetupFunction setup,
608 GDBusReturnFunction function, void *user_data,
609 GDBusDestroyFunction destroy)
611 struct method_call_data *data;
614 DBusPendingCall *call;
616 if (proxy == NULL || method == NULL)
619 client = proxy->client;
623 data = g_try_new0(struct method_call_data, 1);
627 data->function = function;
628 data->user_data = user_data;
629 data->destroy = destroy;
631 msg = dbus_message_new_method_call(client->service_name,
632 proxy->obj_path, proxy->interface, method);
639 DBusMessageIter iter;
641 dbus_message_iter_init_append(msg, &iter);
642 setup(&iter, data->user_data);
645 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
646 &call, METHOD_CALL_TIMEOUT) == FALSE) {
647 dbus_message_unref(msg);
652 dbus_pending_call_set_notify(call, method_call_reply, data, g_free);
653 dbus_pending_call_unref(call);
655 dbus_message_unref(msg);
660 static void properties_changed(GDBusClient *client, const char *path,
663 GDBusProxy *proxy = NULL;
664 DBusMessageIter iter, entry;
665 const char *interface;
668 if (dbus_message_iter_init(msg, &iter) == FALSE)
671 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
674 dbus_message_iter_get_basic(&iter, &interface);
675 dbus_message_iter_next(&iter);
677 for (list = g_list_first(client->proxy_list); list;
678 list = g_list_next(list)) {
679 GDBusProxy *data = list->data;
681 if (g_str_equal(data->interface, interface) == TRUE &&
682 g_str_equal(data->obj_path, path) == TRUE) {
691 update_properties(proxy, &iter);
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) {
703 dbus_message_iter_get_basic(&entry, &name);
705 g_hash_table_remove(proxy->prop_list, name);
707 if (client->property_changed)
708 client->property_changed(proxy, name, NULL,
711 dbus_message_iter_next(&entry);
715 static void parse_properties(GDBusClient *client, const char *path,
716 const char *interface, DBusMessageIter *iter)
720 if (g_str_equal(interface, DBUS_INTERFACE_INTROSPECTABLE) == TRUE)
723 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE)
726 proxy = proxy_lookup(client, path, interface);
728 update_properties(proxy, iter);
732 proxy = proxy_new(client, path, interface);
736 update_properties(proxy, iter);
738 if (client->proxy_added)
739 client->proxy_added(proxy, client->user_data);
741 client->proxy_list = g_list_append(client->proxy_list, proxy);
744 static void parse_interfaces(GDBusClient *client, const char *path,
745 DBusMessageIter *iter)
747 DBusMessageIter dict;
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;
756 const char *interface;
758 dbus_message_iter_recurse(&dict, &entry);
760 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
763 dbus_message_iter_get_basic(&entry, &interface);
764 dbus_message_iter_next(&entry);
766 parse_properties(client, path, interface, &entry);
768 dbus_message_iter_next(&dict);
772 static void interfaces_added(GDBusClient *client, DBusMessage *msg)
774 DBusMessageIter iter;
777 if (dbus_message_iter_init(msg, &iter) == FALSE)
780 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
783 dbus_message_iter_get_basic(&iter, &path);
784 dbus_message_iter_next(&iter);
786 g_dbus_client_ref(client);
788 parse_interfaces(client, path, &iter);
790 g_dbus_client_unref(client);
793 static void interfaces_removed(GDBusClient *client, DBusMessage *msg)
795 DBusMessageIter iter, entry;
798 if (dbus_message_iter_init(msg, &iter) == FALSE)
801 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
804 dbus_message_iter_get_basic(&iter, &path);
805 dbus_message_iter_next(&iter);
807 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
810 dbus_message_iter_recurse(&iter, &entry);
812 g_dbus_client_ref(client);
814 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
815 const char *interface;
817 dbus_message_iter_get_basic(&entry, &interface);
818 proxy_remove(client, path, interface);
819 dbus_message_iter_next(&entry);
822 g_dbus_client_unref(client);
825 static void parse_managed_objects(GDBusClient *client, DBusMessage *msg)
827 DBusMessageIter iter, dict;
829 if (dbus_message_iter_init(msg, &iter) == FALSE)
832 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
835 dbus_message_iter_recurse(&iter, &dict);
837 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
838 DBusMessageIter entry;
841 dbus_message_iter_recurse(&dict, &entry);
843 if (dbus_message_iter_get_arg_type(&entry) !=
844 DBUS_TYPE_OBJECT_PATH)
847 dbus_message_iter_get_basic(&entry, &path);
848 dbus_message_iter_next(&entry);
850 parse_interfaces(client, path, &entry);
852 dbus_message_iter_next(&dict);
856 static void get_managed_objects_reply(DBusPendingCall *call, void *user_data)
858 GDBusClient *client = user_data;
859 DBusMessage *reply = dbus_pending_call_steal_reply(call);
862 dbus_error_init(&error);
864 if (dbus_set_error_from_message(&error, reply) == TRUE) {
865 dbus_error_free(&error);
869 parse_managed_objects(client, reply);
872 dbus_message_unref(reply);
874 dbus_pending_call_unref(client->pending_call);
875 client->pending_call = NULL;
877 g_dbus_client_unref(client);
880 static void get_managed_objects(GDBusClient *client)
884 msg = dbus_message_new_method_call("org.bluez", "/",
885 DBUS_INTERFACE_DBUS ".ObjectManager",
886 "GetManagedObjects");
890 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
892 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
893 &client->pending_call, -1) == FALSE) {
894 dbus_message_unref(msg);
898 g_dbus_client_ref(client);
900 dbus_pending_call_set_notify(client->pending_call,
901 get_managed_objects_reply, client, NULL);
903 dbus_message_unref(msg);
906 static void get_name_owner_reply(DBusPendingCall *call, void *user_data)
908 GDBusClient *client = user_data;
909 DBusMessage *reply = dbus_pending_call_steal_reply(call);
913 dbus_error_init(&error);
915 if (dbus_set_error_from_message(&error, reply) == TRUE) {
916 dbus_error_free(&error);
920 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &name,
921 DBUS_TYPE_INVALID) == FALSE)
924 g_free(client->unique_name);
925 client->unique_name = g_strdup(name);
927 g_dbus_client_ref(client);
929 if (client->connect_func)
930 client->connect_func(client->dbus_conn, client->connect_data);
933 dbus_message_unref(reply);
935 dbus_pending_call_unref(client->pending_call);
936 client->pending_call = NULL;
938 get_managed_objects(client);
940 g_dbus_client_unref(client);
943 static void get_name_owner(GDBusClient *client, const char *name)
947 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
948 DBUS_INTERFACE_DBUS, "GetNameOwner");
952 dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
955 if (dbus_connection_send_with_reply(client->dbus_conn, msg,
956 &client->pending_call, -1) == FALSE) {
957 dbus_message_unref(msg);
961 dbus_pending_call_set_notify(client->pending_call,
962 get_name_owner_reply, client, NULL);
964 dbus_message_unref(msg);
967 static DBusHandlerResult message_filter(DBusConnection *connection,
968 DBusMessage *message, void *user_data)
970 GDBusClient *client = user_data;
973 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
974 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
976 sender = dbus_message_get_sender(message);
978 if (g_str_equal(sender, DBUS_SERVICE_DBUS) == TRUE) {
979 const char *interface, *member;
980 const char *name, *old, *new;
982 interface = dbus_message_get_interface(message);
984 if (g_str_equal(interface, DBUS_INTERFACE_DBUS) == FALSE)
985 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
987 member = dbus_message_get_member(message);
989 if (g_str_equal(member, "NameOwnerChanged") == FALSE)
990 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
992 if (dbus_message_get_args(message, NULL,
993 DBUS_TYPE_STRING, &name,
994 DBUS_TYPE_STRING, &old,
995 DBUS_TYPE_STRING, &new,
996 DBUS_TYPE_INVALID) == FALSE)
997 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
999 if (g_str_equal(name, client->service_name) == FALSE)
1000 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1003 if (client->disconn_func)
1004 client->disconn_func(client->dbus_conn,
1005 client->disconn_data);
1007 g_free(client->unique_name);
1008 client->unique_name = NULL;
1009 } else if (*old == '\0') {
1010 g_free(client->unique_name);
1011 client->unique_name = g_strdup(new);
1013 if (client->connect_func)
1014 client->connect_func(client->dbus_conn,
1015 client->connect_data);
1017 get_managed_objects(client);
1020 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1023 if (client->unique_name == NULL)
1024 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1026 if (g_str_equal(sender, client->unique_name) == TRUE) {
1027 const char *path, *interface, *member;
1029 path = dbus_message_get_path(message);
1030 interface = dbus_message_get_interface(message);
1031 member = dbus_message_get_member(message);
1033 if (g_str_equal(path, "/") == TRUE) {
1034 if (g_str_equal(interface, DBUS_INTERFACE_DBUS
1035 ".ObjectManager") == FALSE)
1036 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1038 if (g_str_equal(member, "InterfacesAdded") == TRUE) {
1039 interfaces_added(client, message);
1040 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1043 if (g_str_equal(member, "InterfacesRemoved") == TRUE) {
1044 interfaces_removed(client, message);
1045 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1048 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1051 if (g_str_has_prefix(path, client->base_path) == FALSE)
1052 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1054 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE) {
1055 if (g_str_equal(member, "PropertiesChanged") == TRUE)
1056 properties_changed(client, path, message);
1058 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1061 if (client->signal_func)
1062 client->signal_func(client->dbus_conn,
1063 message, client->signal_data);
1066 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1069 GDBusClient *g_dbus_client_new(DBusConnection *connection,
1070 const char *service, const char *path)
1072 GDBusClient *client;
1075 if (connection == NULL)
1078 client = g_try_new0(GDBusClient, 1);
1082 if (dbus_connection_add_filter(connection, message_filter,
1083 client, NULL) == FALSE) {
1088 client->dbus_conn = dbus_connection_ref(connection);
1089 client->service_name = g_strdup(service);
1090 client->base_path = g_strdup(path);
1092 get_name_owner(client, client->service_name);
1094 client->match_rules = g_ptr_array_sized_new(4);
1095 g_ptr_array_set_free_func(client->match_rules, g_free);
1097 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1098 "sender='%s',path='%s',interface='%s',"
1099 "member='NameOwnerChanged',arg0='%s'",
1100 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
1101 DBUS_INTERFACE_DBUS, client->service_name));
1102 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1104 "path='/',interface='%s.ObjectManager',"
1105 "member='InterfacesAdded'",
1106 client->service_name, DBUS_INTERFACE_DBUS));
1107 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1109 "path='/',interface='%s.ObjectManager',"
1110 "member='InterfacesRemoved'",
1111 client->service_name, DBUS_INTERFACE_DBUS));
1112 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1113 "sender='%s',path_namespace='%s'",
1114 client->service_name, client->base_path));
1116 for (i = 0; i < client->match_rules->len; i++) {
1117 modify_match(client->dbus_conn, "AddMatch",
1118 g_ptr_array_index(client->match_rules, i));
1121 return g_dbus_client_ref(client);
1124 GDBusClient *g_dbus_client_ref(GDBusClient *client)
1129 g_atomic_int_inc(&client->ref_count);
1134 void g_dbus_client_unref(GDBusClient *client)
1141 if (g_atomic_int_dec_and_test(&client->ref_count) == FALSE)
1144 if (client->pending_call != NULL) {
1145 dbus_pending_call_cancel(client->pending_call);
1146 dbus_pending_call_unref(client->pending_call);
1149 for (i = 0; i < client->match_rules->len; i++) {
1150 modify_match(client->dbus_conn, "RemoveMatch",
1151 g_ptr_array_index(client->match_rules, i));
1154 g_ptr_array_free(client->match_rules, TRUE);
1156 dbus_connection_remove_filter(client->dbus_conn,
1157 message_filter, client);
1159 g_list_free_full(client->proxy_list, proxy_free);
1161 if (client->disconn_func)
1162 client->disconn_func(client->dbus_conn, client->disconn_data);
1164 dbus_connection_unref(client->dbus_conn);
1166 g_free(client->service_name);
1167 g_free(client->unique_name);
1168 g_free(client->base_path);
1173 gboolean g_dbus_client_set_connect_watch(GDBusClient *client,
1174 GDBusWatchFunction function, void *user_data)
1179 client->connect_func = function;
1180 client->connect_data = user_data;
1185 gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client,
1186 GDBusWatchFunction function, void *user_data)
1191 client->disconn_func = function;
1192 client->disconn_data = user_data;
1197 gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
1198 GDBusMessageFunction function, void *user_data)
1203 client->signal_func = function;
1204 client->signal_data = user_data;
1209 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
1210 GDBusProxyFunction proxy_added,
1211 GDBusProxyFunction proxy_removed,
1212 GDBusPropertyFunction property_changed,
1218 client->proxy_added = proxy_added;
1219 client->proxy_removed = proxy_removed;
1220 client->property_changed = property_changed;
1221 client->user_data = user_data;