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
30 #include <dbus/dbus.h>
34 #define METHOD_CALL_TIMEOUT (300 * 1000)
36 #ifndef DBUS_INTERFACE_OBJECT_MANAGER
37 #define DBUS_INTERFACE_OBJECT_MANAGER DBUS_INTERFACE_DBUS ".ObjectManager"
42 DBusConnection *dbus_conn;
49 GPtrArray *match_rules;
50 DBusPendingCall *pending_call;
51 DBusPendingCall *get_objects_call;
52 GDBusWatchFunction connect_func;
54 GDBusWatchFunction disconn_func;
57 GDBusMessageFunction signal_func;
59 GDBusProxyFunction proxy_added;
60 GDBusProxyFunction proxy_removed;
61 #if !defined TIZEN_EXT
62 GDBusClientFunction ready;
65 GDBusPropertyFunction property_changed;
75 GHashTable *prop_list;
77 GDBusPropertyFunction prop_func;
79 GDBusProxyFunction removed_func;
89 static void modify_match_reply(DBusPendingCall *call, void *user_data)
91 DBusMessage *reply = dbus_pending_call_steal_reply(call);
94 dbus_error_init(&error);
96 if (dbus_set_error_from_message(&error, reply) == TRUE)
97 dbus_error_free(&error);
99 dbus_message_unref(reply);
102 static gboolean modify_match(DBusConnection *conn, const char *member,
106 DBusPendingCall *call;
108 msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
109 DBUS_INTERFACE_DBUS, member);
113 dbus_message_append_args(msg, DBUS_TYPE_STRING, &rule,
116 if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
117 dbus_message_unref(msg);
121 dbus_pending_call_set_notify(call, modify_match_reply, NULL, NULL);
122 dbus_pending_call_unref(call);
124 dbus_message_unref(msg);
129 static void iter_append_iter(DBusMessageIter *base, DBusMessageIter *iter)
133 type = dbus_message_iter_get_arg_type(iter);
135 if (dbus_type_is_basic(type)) {
138 dbus_message_iter_get_basic(iter, &value);
139 dbus_message_iter_append_basic(base, type, &value);
140 } else if (dbus_type_is_container(type)) {
141 DBusMessageIter iter_sub, base_sub;
144 dbus_message_iter_recurse(iter, &iter_sub);
147 case DBUS_TYPE_ARRAY:
148 case DBUS_TYPE_VARIANT:
149 sig = dbus_message_iter_get_signature(&iter_sub);
156 dbus_message_iter_open_container(base, type, sig, &base_sub);
161 while (dbus_message_iter_get_arg_type(&iter_sub) !=
163 iter_append_iter(&base_sub, &iter_sub);
164 dbus_message_iter_next(&iter_sub);
167 dbus_message_iter_close_container(base, &base_sub);
171 static void prop_entry_update(struct prop_entry *prop, DBusMessageIter *iter)
174 DBusMessageIter base;
176 msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
180 dbus_message_iter_init_append(msg, &base);
181 iter_append_iter(&base, iter);
183 if (prop->msg != NULL)
184 dbus_message_unref(prop->msg);
186 prop->msg = dbus_message_copy(msg);
187 dbus_message_unref(msg);
190 static struct prop_entry *prop_entry_new(const char *name,
191 DBusMessageIter *iter)
193 struct prop_entry *prop;
195 prop = g_try_new0(struct prop_entry, 1);
199 prop->name = g_strdup(name);
200 prop->type = dbus_message_iter_get_arg_type(iter);
202 prop_entry_update(prop, iter);
207 static void prop_entry_free(gpointer data)
209 struct prop_entry *prop = data;
211 if (prop->msg != NULL)
212 dbus_message_unref(prop->msg);
219 static void add_property(GDBusProxy *proxy, const char *name,
220 DBusMessageIter *iter, gboolean send_changed)
222 GDBusClient *client = proxy->client;
223 DBusMessageIter value;
224 struct prop_entry *prop;
226 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
229 dbus_message_iter_recurse(iter, &value);
231 prop = g_hash_table_lookup(proxy->prop_list, name);
233 prop_entry_update(prop, &value);
237 prop = prop_entry_new(name, &value);
241 g_hash_table_replace(proxy->prop_list, prop->name, prop);
244 if (proxy->prop_func)
245 proxy->prop_func(proxy, name, &value, proxy->prop_data);
247 if (client == NULL || send_changed == FALSE)
250 if (client->property_changed)
251 client->property_changed(proxy, name, &value,
255 static void update_properties(GDBusProxy *proxy, DBusMessageIter *iter,
256 gboolean send_changed)
258 DBusMessageIter dict;
260 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
263 dbus_message_iter_recurse(iter, &dict);
265 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
266 DBusMessageIter entry;
269 dbus_message_iter_recurse(&dict, &entry);
271 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
274 dbus_message_iter_get_basic(&entry, &name);
275 dbus_message_iter_next(&entry);
277 add_property(proxy, name, &entry, send_changed);
279 dbus_message_iter_next(&dict);
283 static void get_all_properties_reply(DBusPendingCall *call, void *user_data)
285 GDBusProxy *proxy = user_data;
286 GDBusClient *client = proxy->client;
287 DBusMessage *reply = dbus_pending_call_steal_reply(call);
288 DBusMessageIter iter;
291 dbus_error_init(&error);
293 if (dbus_set_error_from_message(&error, reply) == TRUE) {
294 dbus_error_free(&error);
298 dbus_message_iter_init(reply, &iter);
300 update_properties(proxy, &iter, FALSE);
303 if (g_list_find(client->proxy_list, proxy) == NULL) {
304 if (client->proxy_added)
305 client->proxy_added(proxy, client->user_data);
307 client->proxy_list = g_list_append(client->proxy_list, proxy);
310 dbus_message_unref(reply);
312 g_dbus_client_unref(client);
315 static void get_all_properties(GDBusProxy *proxy)
317 GDBusClient *client = proxy->client;
318 const char *service_name = client->service_name;
320 DBusPendingCall *call;
322 msg = dbus_message_new_method_call(service_name, proxy->obj_path,
323 DBUS_INTERFACE_PROPERTIES, "GetAll");
327 dbus_message_append_args(msg, DBUS_TYPE_STRING, &proxy->interface,
330 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
331 &call, -1) == FALSE) {
332 dbus_message_unref(msg);
336 g_dbus_client_ref(client);
338 dbus_pending_call_set_notify(call, get_all_properties_reply,
340 dbus_pending_call_unref(call);
342 dbus_message_unref(msg);
345 static GDBusProxy *proxy_lookup(GDBusClient *client, const char *path,
346 const char *interface)
350 for (list = g_list_first(client->proxy_list); list;
351 list = g_list_next(list)) {
352 GDBusProxy *proxy = list->data;
354 if (g_str_equal(proxy->interface, interface) == TRUE &&
355 g_str_equal(proxy->obj_path, path) == TRUE)
362 static gboolean properties_changed(DBusConnection *conn, DBusMessage *msg,
365 GDBusProxy *proxy = user_data;
366 GDBusClient *client = proxy->client;
367 DBusMessageIter iter, entry;
368 const char *interface;
370 if (dbus_message_iter_init(msg, &iter) == FALSE)
373 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
376 dbus_message_iter_get_basic(&iter, &interface);
377 dbus_message_iter_next(&iter);
379 update_properties(proxy, &iter, TRUE);
381 dbus_message_iter_next(&iter);
383 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
386 dbus_message_iter_recurse(&iter, &entry);
388 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
391 dbus_message_iter_get_basic(&entry, &name);
393 g_hash_table_remove(proxy->prop_list, name);
395 if (proxy->prop_func)
396 proxy->prop_func(proxy, name, NULL, proxy->prop_data);
398 if (client->property_changed)
399 client->property_changed(proxy, name, NULL,
402 dbus_message_iter_next(&entry);
408 static GDBusProxy *proxy_new(GDBusClient *client, const char *path,
409 const char *interface)
413 proxy = g_try_new0(GDBusProxy, 1);
417 proxy->client = client;
418 proxy->obj_path = g_strdup(path);
419 proxy->interface = g_strdup(interface);
421 proxy->prop_list = g_hash_table_new_full(g_str_hash, g_str_equal,
422 NULL, prop_entry_free);
423 proxy->watch = g_dbus_add_properties_watch(client->dbus_conn,
424 client->service_name,
430 return g_dbus_proxy_ref(proxy);
433 static void proxy_free(gpointer data)
435 GDBusProxy *proxy = data;
438 GDBusClient *client = proxy->client;
440 if (client->proxy_removed)
441 client->proxy_removed(proxy, client->user_data);
443 g_dbus_remove_watch(client->dbus_conn, proxy->watch);
445 g_hash_table_remove_all(proxy->prop_list);
447 proxy->client = NULL;
450 if (proxy->removed_func)
451 proxy->removed_func(proxy, proxy->removed_data);
453 g_dbus_proxy_unref(proxy);
456 static void proxy_remove(GDBusClient *client, const char *path,
457 const char *interface)
461 for (list = g_list_first(client->proxy_list); list;
462 list = g_list_next(list)) {
463 GDBusProxy *proxy = list->data;
465 if (g_str_equal(proxy->interface, interface) == TRUE &&
466 g_str_equal(proxy->obj_path, path) == TRUE) {
468 g_list_delete_link(client->proxy_list, list);
475 GDBusProxy *g_dbus_proxy_new(GDBusClient *client, const char *path,
476 const char *interface)
483 proxy = proxy_lookup(client, path, interface);
485 return g_dbus_proxy_ref(proxy);
487 proxy = proxy_new(client, path, interface);
491 get_all_properties(proxy);
493 return g_dbus_proxy_ref(proxy);
496 GDBusProxy *g_dbus_proxy_ref(GDBusProxy *proxy)
501 __sync_fetch_and_add(&proxy->ref_count, 1);
506 void g_dbus_proxy_unref(GDBusProxy *proxy)
511 if (__sync_sub_and_fetch(&proxy->ref_count, 1) > 0)
514 g_hash_table_destroy(proxy->prop_list);
516 g_free(proxy->obj_path);
517 g_free(proxy->interface);
522 const char *g_dbus_proxy_get_path(GDBusProxy *proxy)
527 return proxy->obj_path;
530 const char *g_dbus_proxy_get_interface(GDBusProxy *proxy)
535 return proxy->interface;
538 gboolean g_dbus_proxy_get_property(GDBusProxy *proxy, const char *name,
539 DBusMessageIter *iter)
541 struct prop_entry *prop;
543 if (proxy == NULL || name == NULL)
546 prop = g_hash_table_lookup(proxy->prop_list, name);
550 if (prop->msg == NULL)
553 if (dbus_message_iter_init(prop->msg, iter) == FALSE)
559 struct refresh_property_data {
564 static void refresh_property_free(gpointer user_data)
566 struct refresh_property_data *data = user_data;
572 static void refresh_property_reply(DBusPendingCall *call, void *user_data)
574 struct refresh_property_data *data = user_data;
575 DBusMessage *reply = dbus_pending_call_steal_reply(call);
578 dbus_error_init(&error);
580 if (dbus_set_error_from_message(&error, reply) == FALSE) {
581 DBusMessageIter iter;
583 dbus_message_iter_init(reply, &iter);
585 add_property(data->proxy, data->name, &iter, TRUE);
587 dbus_error_free(&error);
589 dbus_message_unref(reply);
592 gboolean g_dbus_proxy_refresh_property(GDBusProxy *proxy, const char *name)
594 struct refresh_property_data *data;
597 DBusMessageIter iter;
598 DBusPendingCall *call;
600 if (proxy == NULL || name == NULL)
603 client = proxy->client;
607 data = g_try_new0(struct refresh_property_data, 1);
612 data->name = g_strdup(name);
614 msg = dbus_message_new_method_call(client->service_name,
615 proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Get");
617 refresh_property_free(data);
621 dbus_message_iter_init_append(msg, &iter);
622 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
624 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
626 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
627 &call, -1) == FALSE) {
628 dbus_message_unref(msg);
629 refresh_property_free(data);
633 dbus_pending_call_set_notify(call, refresh_property_reply,
634 data, refresh_property_free);
635 dbus_pending_call_unref(call);
637 dbus_message_unref(msg);
642 struct set_property_data {
643 GDBusResultFunction function;
645 GDBusDestroyFunction destroy;
648 static void set_property_reply(DBusPendingCall *call, void *user_data)
650 struct set_property_data *data = user_data;
651 DBusMessage *reply = dbus_pending_call_steal_reply(call);
654 dbus_error_init(&error);
656 dbus_set_error_from_message(&error, reply);
659 data->function(&error, data->user_data);
662 data->destroy(data->user_data);
664 dbus_error_free(&error);
666 dbus_message_unref(reply);
669 gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
670 const char *name, int type, const void *value,
671 GDBusResultFunction function, void *user_data,
672 GDBusDestroyFunction destroy)
674 struct set_property_data *data;
677 DBusMessageIter iter, variant;
678 DBusPendingCall *call;
681 if (proxy == NULL || name == NULL || value == NULL)
684 if (dbus_type_is_basic(type) == FALSE)
687 client = proxy->client;
691 data = g_try_new0(struct set_property_data, 1);
695 data->function = function;
696 data->user_data = user_data;
697 data->destroy = destroy;
699 msg = dbus_message_new_method_call(client->service_name,
700 proxy->obj_path, DBUS_INTERFACE_PROPERTIES, "Set");
706 type_as_str[0] = (char) type;
707 type_as_str[1] = '\0';
709 dbus_message_iter_init_append(msg, &iter);
710 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
712 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
714 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
715 type_as_str, &variant);
716 dbus_message_iter_append_basic(&variant, type, value);
717 dbus_message_iter_close_container(&iter, &variant);
719 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
720 &call, -1) == FALSE) {
721 dbus_message_unref(msg);
726 dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
727 dbus_pending_call_unref(call);
729 dbus_message_unref(msg);
734 #if !defined TIZEN_EXT
735 gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
736 const char *name, int type, const void *value,
737 size_t size, GDBusResultFunction function,
738 void *user_data, GDBusDestroyFunction destroy)
740 struct set_property_data *data;
743 DBusMessageIter iter, variant, array;
744 DBusPendingCall *call;
748 if (!proxy || !name || !value)
751 if (!dbus_type_is_basic(type))
754 client = proxy->client;
758 data = g_try_new0(struct set_property_data, 1);
762 data->function = function;
763 data->user_data = user_data;
764 data->destroy = destroy;
766 msg = dbus_message_new_method_call(client->service_name,
768 DBUS_INTERFACE_PROPERTIES,
775 array_sig[0] = DBUS_TYPE_ARRAY;
776 array_sig[1] = (char) type;
779 type_sig[0] = (char) type;
782 dbus_message_iter_init_append(msg, &iter);
783 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
785 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
787 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
788 array_sig, &variant);
790 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
793 if (dbus_type_is_fixed(type))
794 dbus_message_iter_append_fixed_array(&array, type, &value,
796 else if (type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) {
797 const char **str = (const char **) value;
800 for (i = 0; i < size; i++)
801 dbus_message_iter_append_basic(&array, type, &str[i]);
804 dbus_message_iter_close_container(&variant, &array);
805 dbus_message_iter_close_container(&iter, &variant);
807 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
808 &call, -1) == FALSE) {
809 dbus_message_unref(msg);
814 dbus_pending_call_set_notify(call, set_property_reply, data, g_free);
815 dbus_pending_call_unref(call);
817 dbus_message_unref(msg);
823 struct method_call_data {
824 GDBusReturnFunction function;
826 GDBusDestroyFunction destroy;
829 static void method_call_reply(DBusPendingCall *call, void *user_data)
831 struct method_call_data *data = user_data;
832 DBusMessage *reply = dbus_pending_call_steal_reply(call);
835 data->function(reply, data->user_data);
838 data->destroy(data->user_data);
840 dbus_message_unref(reply);
843 gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
844 GDBusSetupFunction setup,
845 GDBusReturnFunction function, void *user_data,
846 GDBusDestroyFunction destroy)
848 struct method_call_data *data;
851 DBusPendingCall *call;
853 if (proxy == NULL || method == NULL)
856 client = proxy->client;
860 msg = dbus_message_new_method_call(client->service_name,
861 proxy->obj_path, proxy->interface, method);
866 DBusMessageIter iter;
868 dbus_message_iter_init_append(msg, &iter);
869 setup(&iter, user_data);
873 return g_dbus_send_message(client->dbus_conn, msg);
875 data = g_try_new0(struct method_call_data, 1);
879 data->function = function;
880 data->user_data = user_data;
881 data->destroy = destroy;
884 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
885 &call, METHOD_CALL_TIMEOUT) == FALSE) {
886 dbus_message_unref(msg);
891 dbus_pending_call_set_notify(call, method_call_reply, data, g_free);
892 dbus_pending_call_unref(call);
894 dbus_message_unref(msg);
899 gboolean g_dbus_proxy_set_property_watch(GDBusProxy *proxy,
900 GDBusPropertyFunction function, void *user_data)
905 proxy->prop_func = function;
906 proxy->prop_data = user_data;
911 gboolean g_dbus_proxy_set_removed_watch(GDBusProxy *proxy,
912 GDBusProxyFunction function, void *user_data)
917 proxy->removed_func = function;
918 proxy->removed_data = user_data;
923 static void refresh_properties(GDBusClient *client)
927 for (list = g_list_first(client->proxy_list); list;
928 list = g_list_next(list)) {
929 GDBusProxy *proxy = list->data;
931 get_all_properties(proxy);
935 static void parse_properties(GDBusClient *client, const char *path,
936 const char *interface, DBusMessageIter *iter)
940 if (g_str_equal(interface, DBUS_INTERFACE_INTROSPECTABLE) == TRUE)
943 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE)
946 proxy = proxy_lookup(client, path, interface);
948 update_properties(proxy, iter, FALSE);
952 proxy = proxy_new(client, path, interface);
956 update_properties(proxy, iter, FALSE);
958 if (client->proxy_added)
959 client->proxy_added(proxy, client->user_data);
961 client->proxy_list = g_list_append(client->proxy_list, proxy);
964 static void parse_interfaces(GDBusClient *client, const char *path,
965 DBusMessageIter *iter)
967 DBusMessageIter dict;
969 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
972 dbus_message_iter_recurse(iter, &dict);
974 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
975 DBusMessageIter entry;
976 const char *interface;
978 dbus_message_iter_recurse(&dict, &entry);
980 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
983 dbus_message_iter_get_basic(&entry, &interface);
984 dbus_message_iter_next(&entry);
986 parse_properties(client, path, interface, &entry);
988 dbus_message_iter_next(&dict);
992 static gboolean interfaces_added(DBusConnection *conn, DBusMessage *msg,
995 GDBusClient *client = user_data;
996 DBusMessageIter iter;
999 if (dbus_message_iter_init(msg, &iter) == FALSE)
1002 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
1005 dbus_message_iter_get_basic(&iter, &path);
1006 dbus_message_iter_next(&iter);
1008 g_dbus_client_ref(client);
1010 parse_interfaces(client, path, &iter);
1012 g_dbus_client_unref(client);
1017 static gboolean interfaces_removed(DBusConnection *conn, DBusMessage *msg,
1020 GDBusClient *client = user_data;
1021 DBusMessageIter iter, entry;
1024 if (dbus_message_iter_init(msg, &iter) == FALSE)
1027 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
1030 dbus_message_iter_get_basic(&iter, &path);
1031 dbus_message_iter_next(&iter);
1033 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1036 dbus_message_iter_recurse(&iter, &entry);
1038 g_dbus_client_ref(client);
1040 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
1041 const char *interface;
1043 dbus_message_iter_get_basic(&entry, &interface);
1044 proxy_remove(client, path, interface);
1045 dbus_message_iter_next(&entry);
1048 g_dbus_client_unref(client);
1053 static void parse_managed_objects(GDBusClient *client, DBusMessage *msg)
1055 DBusMessageIter iter, dict;
1057 if (dbus_message_iter_init(msg, &iter) == FALSE)
1060 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
1063 dbus_message_iter_recurse(&iter, &dict);
1065 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1066 DBusMessageIter entry;
1069 dbus_message_iter_recurse(&dict, &entry);
1071 if (dbus_message_iter_get_arg_type(&entry) !=
1072 DBUS_TYPE_OBJECT_PATH)
1075 dbus_message_iter_get_basic(&entry, &path);
1076 dbus_message_iter_next(&entry);
1078 parse_interfaces(client, path, &entry);
1080 dbus_message_iter_next(&dict);
1084 static void get_managed_objects_reply(DBusPendingCall *call, void *user_data)
1086 GDBusClient *client = user_data;
1087 DBusMessage *reply = dbus_pending_call_steal_reply(call);
1090 g_dbus_client_ref(client);
1092 dbus_error_init(&error);
1094 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1095 dbus_error_free(&error);
1099 parse_managed_objects(client, reply);
1102 #if !defined TIZEN_EXT
1104 client->ready(client, client->ready_data);
1107 dbus_message_unref(reply);
1109 dbus_pending_call_unref(client->get_objects_call);
1110 client->get_objects_call = NULL;
1112 g_dbus_client_unref(client);
1115 static void get_managed_objects(GDBusClient *client)
1119 if (!client->connected)
1122 if ((!client->proxy_added && !client->proxy_removed) ||
1123 !client->root_path) {
1124 refresh_properties(client);
1128 if (client->get_objects_call != NULL)
1131 msg = dbus_message_new_method_call(client->service_name,
1133 DBUS_INTERFACE_OBJECT_MANAGER,
1134 "GetManagedObjects");
1138 dbus_message_append_args(msg, DBUS_TYPE_INVALID);
1140 if (g_dbus_send_message_with_reply(client->dbus_conn, msg,
1141 &client->get_objects_call, -1) == FALSE) {
1142 dbus_message_unref(msg);
1146 dbus_pending_call_set_notify(client->get_objects_call,
1147 get_managed_objects_reply,
1150 dbus_message_unref(msg);
1153 static void service_connect(DBusConnection *conn, void *user_data)
1155 GDBusClient *client = user_data;
1157 g_dbus_client_ref(client);
1159 client->connected = TRUE;
1161 if (client->connect_func)
1162 client->connect_func(conn, client->connect_data);
1164 get_managed_objects(client);
1166 g_dbus_client_unref(client);
1169 static void service_disconnect(DBusConnection *conn, void *user_data)
1171 GDBusClient *client = user_data;
1173 client->connected = FALSE;
1175 g_list_free_full(client->proxy_list, proxy_free);
1176 client->proxy_list = NULL;
1178 if (client->disconn_func)
1179 client->disconn_func(conn, client->disconn_data);
1182 static DBusHandlerResult message_filter(DBusConnection *connection,
1183 DBusMessage *message, void *user_data)
1185 GDBusClient *client = user_data;
1186 const char *sender, *path, *interface;
1188 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
1189 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1191 sender = dbus_message_get_sender(message);
1193 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1195 path = dbus_message_get_path(message);
1196 interface = dbus_message_get_interface(message);
1198 if (g_str_has_prefix(path, client->base_path) == FALSE)
1199 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1201 if (g_str_equal(interface, DBUS_INTERFACE_PROPERTIES) == TRUE)
1202 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1204 if (client->signal_func)
1205 client->signal_func(connection, message, client->signal_data);
1207 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1210 GDBusClient *g_dbus_client_new(DBusConnection *connection,
1211 const char *service, const char *path)
1213 return g_dbus_client_new_full(connection, service, path, "/");
1216 GDBusClient *g_dbus_client_new_full(DBusConnection *connection,
1217 const char *service,
1219 const char *root_path)
1221 GDBusClient *client;
1224 if (!connection || !service)
1227 client = g_try_new0(GDBusClient, 1);
1231 if (dbus_connection_add_filter(connection, message_filter,
1232 client, NULL) == FALSE) {
1237 client->dbus_conn = dbus_connection_ref(connection);
1238 client->service_name = g_strdup(service);
1239 client->base_path = g_strdup(path);
1240 client->root_path = g_strdup(root_path);
1241 client->connected = FALSE;
1243 client->match_rules = g_ptr_array_sized_new(1);
1244 g_ptr_array_set_free_func(client->match_rules, g_free);
1246 client->watch = g_dbus_add_service_watch(connection, service,
1252 return g_dbus_client_ref(client);
1254 client->added_watch = g_dbus_add_signal_watch(connection, service,
1256 DBUS_INTERFACE_OBJECT_MANAGER,
1260 client->removed_watch = g_dbus_add_signal_watch(connection, service,
1262 DBUS_INTERFACE_OBJECT_MANAGER,
1263 "InterfacesRemoved",
1266 g_ptr_array_add(client->match_rules, g_strdup_printf("type='signal',"
1267 "sender='%s',path_namespace='%s'",
1268 client->service_name, client->base_path));
1270 for (i = 0; i < client->match_rules->len; i++) {
1271 modify_match(client->dbus_conn, "AddMatch",
1272 g_ptr_array_index(client->match_rules, i));
1275 return g_dbus_client_ref(client);
1278 GDBusClient *g_dbus_client_ref(GDBusClient *client)
1283 __sync_fetch_and_add(&client->ref_count, 1);
1288 void g_dbus_client_unref(GDBusClient *client)
1295 if (__sync_sub_and_fetch(&client->ref_count, 1) > 0)
1298 if (client->pending_call != NULL) {
1299 dbus_pending_call_cancel(client->pending_call);
1300 dbus_pending_call_unref(client->pending_call);
1303 if (client->get_objects_call != NULL) {
1304 dbus_pending_call_cancel(client->get_objects_call);
1305 dbus_pending_call_unref(client->get_objects_call);
1308 for (i = 0; i < client->match_rules->len; i++) {
1309 modify_match(client->dbus_conn, "RemoveMatch",
1310 g_ptr_array_index(client->match_rules, i));
1313 g_ptr_array_free(client->match_rules, TRUE);
1315 dbus_connection_remove_filter(client->dbus_conn,
1316 message_filter, client);
1318 g_list_free_full(client->proxy_list, proxy_free);
1321 * Don't call disconn_func twice if disconnection
1322 * was previously reported.
1324 if (client->disconn_func && client->connected)
1325 client->disconn_func(client->dbus_conn, client->disconn_data);
1327 g_dbus_remove_watch(client->dbus_conn, client->watch);
1328 g_dbus_remove_watch(client->dbus_conn, client->added_watch);
1329 g_dbus_remove_watch(client->dbus_conn, client->removed_watch);
1331 dbus_connection_unref(client->dbus_conn);
1333 g_free(client->service_name);
1334 g_free(client->base_path);
1335 g_free(client->root_path);
1340 gboolean g_dbus_client_set_connect_watch(GDBusClient *client,
1341 GDBusWatchFunction function, void *user_data)
1346 client->connect_func = function;
1347 client->connect_data = user_data;
1352 gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client,
1353 GDBusWatchFunction function, void *user_data)
1358 client->disconn_func = function;
1359 client->disconn_data = user_data;
1364 gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
1365 GDBusMessageFunction function, void *user_data)
1370 client->signal_func = function;
1371 client->signal_data = user_data;
1376 #if !defined TIZEN_EXT
1377 gboolean g_dbus_client_set_ready_watch(GDBusClient *client,
1378 GDBusClientFunction ready, void *user_data)
1383 client->ready = ready;
1384 client->ready_data = user_data;
1390 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
1391 GDBusProxyFunction proxy_added,
1392 GDBusProxyFunction proxy_removed,
1393 GDBusPropertyFunction property_changed,
1399 client->proxy_added = proxy_added;
1400 client->proxy_removed = proxy_removed;
1401 client->property_changed = property_changed;
1402 client->user_data = user_data;
1404 if (proxy_added || proxy_removed || property_changed)
1405 get_managed_objects(client);