1 #include "edbus_private.h"
2 #include "edbus_private_types.h"
5 /* TODO: mempool of EDBus_Object, Edbus_Object_Context_Event_Cb and
6 * EDBus_Object_Context_Event
9 #define EDBUS_OBJECT_CHECK(obj) \
12 EINA_SAFETY_ON_NULL_RETURN(obj); \
13 if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
15 EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
18 EINA_SAFETY_ON_TRUE_RETURN(obj->refcount <= 0); \
22 #define EDBUS_OBJECT_CHECK_RETVAL(obj, retval) \
25 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, retval); \
26 if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
28 EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
31 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj->refcount <= 0, retval); \
35 #define EDBUS_OBJECT_CHECK_GOTO(obj, label) \
38 EINA_SAFETY_ON_NULL_GOTO(obj, label); \
39 if (!EINA_MAGIC_CHECK(obj, EDBUS_OBJECT_MAGIC)) \
41 EINA_MAGIC_FAIL(obj, EDBUS_OBJECT_MAGIC); \
44 EINA_SAFETY_ON_TRUE_GOTO(obj->refcount <= 0, label); \
49 edbus_object_init(void)
55 edbus_object_shutdown(void)
59 static void _edbus_object_event_callback_call(EDBus_Object *obj, EDBus_Object_Event_Type type, const void *event_info);
60 static void _edbus_object_context_event_cb_del(EDBus_Object_Context_Event *ce, EDBus_Object_Context_Event_Cb *ctx);
61 static void _on_connection_free(void *data, const void *dead_pointer);
62 static void _on_signal_handler_free(void *data, const void *dead_pointer);
65 _edbus_object_call_del(EDBus_Object *obj)
67 EDBus_Object_Context_Event *ce;
69 _edbus_object_event_callback_call(obj, EDBUS_OBJECT_EVENT_DEL, NULL);
71 /* clear all del callbacks so we don't call them twice at
72 * _edbus_object_clear()
74 ce = obj->event_handlers + EDBUS_OBJECT_EVENT_DEL;
77 EDBus_Object_Context_Event_Cb *ctx;
79 ctx = EINA_INLIST_CONTAINER_GET(ce->list,
80 EDBus_Object_Context_Event_Cb);
81 _edbus_object_context_event_cb_del(ce, ctx);
86 _edbus_object_clear(EDBus_Object *obj)
88 EDBus_Signal_Handler *h;
90 Eina_List *iter, *iter_next;
92 DBG("obj=%p, refcount=%d, name=%s, path=%s",
93 obj, obj->refcount, obj->name, obj->path);
96 _edbus_object_call_del(obj);
97 edbus_connection_name_object_del(obj->conn, obj);
99 /* NOTE: obj->proxies is deleted from obj->cbs_free. */
101 EINA_LIST_FOREACH_SAFE(obj->signal_handlers, iter, iter_next, h)
103 DBG("obj=%p delete owned signal handler %p %s",
104 obj, h, edbus_signal_handler_match_get(h));
105 edbus_signal_handler_del(h);
107 EINA_INLIST_FOREACH_SAFE(obj->pendings, in_l, p)
109 DBG("obj=%p delete owned pending call=%p dest=%s path=%s %s.%s()",
111 edbus_pending_destination_get(p),
112 edbus_pending_path_get(p),
113 edbus_pending_interface_get(p),
114 edbus_pending_method_get(p));
115 edbus_pending_cancel(p);
118 edbus_cbs_free_dispatch(&(obj->cbs_free), obj);
123 _edbus_object_free(EDBus_Object *obj)
126 EDBus_Signal_Handler *h;
130 Eina_Iterator *iterator = eina_hash_iterator_data_new(obj->proxies);
132 EINA_ITERATOR_FOREACH(iterator, proxy)
133 ERR("obj=%p alive proxy=%p %s", obj, proxy,
134 edbus_proxy_interface_get(proxy));
135 eina_iterator_free(iterator);
136 eina_hash_free(obj->proxies);
139 EINA_LIST_FREE(obj->signal_handlers, h)
142 edbus_signal_handler_cb_free_del(h, _on_signal_handler_free, obj);
144 ERR("obj=%p alive handler=%p %s", obj, h,
145 edbus_signal_handler_match_get(h));
149 CRITICAL("Object %p released with live pending calls!", obj);
151 for (i = 0; i < EDBUS_OBJECT_EVENT_LAST; i++)
153 EDBus_Object_Context_Event *ce = obj->event_handlers + i;
156 EDBus_Object_Context_Event_Cb *ctx;
158 ctx = EINA_INLIST_CONTAINER_GET(ce->list,
159 EDBus_Object_Context_Event_Cb);
160 _edbus_object_context_event_cb_del(ce, ctx);
162 eina_list_free(ce->to_delete);
165 if (obj->interfaces_added)
166 edbus_signal_handler_del(obj->interfaces_added);
167 if (obj->interfaces_removed)
168 edbus_signal_handler_del(obj->interfaces_removed);
169 if (obj->properties_changed)
170 edbus_signal_handler_del(obj->properties_changed);
171 eina_stringshare_del(obj->name);
172 eina_stringshare_del(obj->path);
173 EINA_MAGIC_SET(obj, EINA_MAGIC_NONE);
179 _on_connection_free(void *data, const void *dead_pointer)
181 EDBus_Object *obj = data;
182 EDBUS_OBJECT_CHECK(obj);
183 _edbus_object_clear(obj);
184 _edbus_object_free(obj);
188 edbus_object_get(EDBus_Connection *conn, const char *bus, const char *path)
192 EINA_SAFETY_ON_NULL_RETURN_VAL(conn, NULL);
193 EINA_SAFETY_ON_NULL_RETURN_VAL(bus, NULL);
194 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
196 obj = edbus_connection_name_object_get(conn, bus, path);
198 return edbus_object_ref(obj);
200 obj = calloc(1, sizeof(EDBus_Object));
201 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
205 obj->path = eina_stringshare_add(path);
206 obj->name = eina_stringshare_add(bus);
207 obj->proxies = eina_hash_string_small_new(NULL);
208 EINA_SAFETY_ON_NULL_GOTO(obj->proxies, cleanup);
209 EINA_MAGIC_SET(obj, EDBUS_OBJECT_MAGIC);
211 edbus_connection_name_object_set(conn, obj);
212 edbus_connection_cb_free_add(obj->conn, _on_connection_free, obj);
214 obj->properties = edbus_proxy_get(obj, EDBUS_FDO_INTERFACE_PROPERTIES);
219 eina_stringshare_del(obj->path);
220 eina_stringshare_del(obj->name);
226 static void _on_signal_handler_free(void *data, const void *dead_pointer);
229 _edbus_object_unref(EDBus_Object *obj)
232 if (obj->refcount > 0) return;
234 edbus_connection_cb_free_del(obj->conn, _on_connection_free, obj);
235 _edbus_object_clear(obj);
236 _edbus_object_free(obj);
240 edbus_object_ref(EDBus_Object *obj)
242 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
243 DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
244 obj, obj->refcount, obj->name, obj->path);
250 edbus_object_unref(EDBus_Object *obj)
252 EDBUS_OBJECT_CHECK(obj);
253 DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
254 obj, obj->refcount, obj->name, obj->path);
255 _edbus_object_unref(obj);
259 edbus_object_cb_free_add(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data)
261 EDBUS_OBJECT_CHECK(obj);
262 EINA_SAFETY_ON_NULL_RETURN(cb);
263 obj->cbs_free = edbus_cbs_free_add(obj->cbs_free, cb, data);
267 edbus_object_cb_free_del(EDBus_Object *obj, EDBus_Free_Cb cb, const void *data)
269 EDBUS_OBJECT_CHECK(obj);
270 EINA_SAFETY_ON_NULL_RETURN(cb);
271 obj->cbs_free = edbus_cbs_free_del(obj->cbs_free, cb, data);
275 _cb_interfaces_added(void *data, const EDBus_Message *msg)
277 EDBus_Object *obj = data;
278 const char *obj_path;
279 EDBus_Message_Iter *array_ifaces, *entry_iface;
281 if (!edbus_message_arguments_get(msg, "oa{sa{sv}}", &obj_path, &array_ifaces))
284 while (edbus_message_iter_get_and_next(array_ifaces, 'e', &entry_iface))
286 const char *iface_name;
287 EDBus_Object_Event_Interface_Added event;
290 edbus_message_iter_basic_get(entry_iface, &iface_name);
291 proxy = edbus_proxy_get(obj, iface_name);
292 EINA_SAFETY_ON_NULL_RETURN(proxy);
293 event.interface = iface_name;
295 _edbus_object_event_callback_call(obj, EDBUS_OBJECT_EVENT_IFACE_ADDED,
301 _cb_interfaces_removed(void *data, const EDBus_Message *msg)
303 EDBus_Object *obj = data;
304 const char *obj_path, *iface;
305 EDBus_Message_Iter *array_ifaces;
307 if (!edbus_message_arguments_get(msg, "oas", &obj_path, &array_ifaces))
310 while (edbus_message_iter_get_and_next(array_ifaces, 's', &iface))
312 EDBus_Object_Event_Interface_Removed event;
313 event.interface = iface;
314 _edbus_object_event_callback_call(obj, EDBUS_OBJECT_EVENT_IFACE_REMOVED,
320 _property_changed_iter(void *data, const void *key, EDBus_Message_Iter *var)
322 EDBus_Proxy *proxy = data;
323 const char *skey = key;
324 Eina_Value *st_value, stack_value;
325 EDBus_Object_Event_Property_Changed event;
327 st_value = _message_iter_struct_to_eina_value(var);
328 eina_value_struct_value_get(st_value, "arg0", &stack_value);
330 event.interface = edbus_proxy_interface_get(proxy);
333 event.value = &stack_value;
334 _edbus_object_event_callback_call(edbus_proxy_object_get(proxy),
335 EDBUS_OBJECT_EVENT_PROPERTY_CHANGED,
337 eina_value_free(st_value);
338 eina_value_flush(&stack_value);
342 _cb_properties_changed(void *data, const EDBus_Message *msg)
344 EDBus_Object *obj = data;
346 EDBus_Message_Iter *array, *invalidate;
348 const char *invalidate_prop;
350 if (!edbus_message_arguments_get(msg, "sa{sv}as", &iface, &array, &invalidate))
352 ERR("Error getting data from properties changed signal.");
356 proxy = edbus_proxy_get(obj, iface);
357 EINA_SAFETY_ON_NULL_RETURN(proxy);
359 if (obj->event_handlers[EDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list)
360 edbus_message_iter_dict_iterate(array, "sv", _property_changed_iter,
363 if (!obj->event_handlers[EDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
366 while (edbus_message_iter_get_and_next(invalidate, 's', &invalidate_prop))
368 EDBus_Object_Event_Property_Removed event;
369 event.interface = iface;
370 event.name = invalidate_prop;
372 _edbus_object_event_callback_call(obj,
373 EDBUS_OBJECT_EVENT_PROPERTY_REMOVED,
379 edbus_object_event_callback_add(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data)
381 EDBus_Object_Context_Event *ce;
382 EDBus_Object_Context_Event_Cb *ctx;
384 EDBUS_OBJECT_CHECK(obj);
385 EINA_SAFETY_ON_NULL_RETURN(cb);
386 EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_OBJECT_EVENT_LAST);
388 ce = obj->event_handlers + type;
390 ctx = calloc(1, sizeof(EDBus_Object_Context_Event_Cb));
391 EINA_SAFETY_ON_NULL_RETURN(ctx);
394 ctx->cb_data = cb_data;
396 ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
400 case EDBUS_OBJECT_EVENT_IFACE_ADDED:
402 if (obj->interfaces_added)
404 obj->interfaces_added =
405 _edbus_signal_handler_add(obj->conn, obj->name, NULL,
406 EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
408 _cb_interfaces_added, obj);
409 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
410 edbus_signal_handler_match_extra_set(obj->interfaces_added, "arg0",
414 case EDBUS_OBJECT_EVENT_IFACE_REMOVED:
416 if (obj->interfaces_removed)
418 obj->interfaces_removed =
419 _edbus_signal_handler_add(obj->conn, obj->name, NULL,
420 EDBUS_FDO_INTERFACE_OBJECT_MANAGER,
422 _cb_interfaces_removed, obj);
423 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
424 edbus_signal_handler_match_extra_set(obj->interfaces_removed,
425 "arg0", obj->path, NULL);
428 case EDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
429 case EDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
431 if (obj->properties_changed)
433 obj->properties_changed =
434 edbus_object_signal_handler_add(obj,
435 EDBUS_FDO_INTERFACE_PROPERTIES,
437 _cb_properties_changed, obj);
438 EINA_SAFETY_ON_NULL_RETURN(obj->properties_changed);
447 _edbus_object_context_event_cb_del(EDBus_Object_Context_Event *ce, EDBus_Object_Context_Event_Cb *ctx)
449 ce->list = eina_inlist_remove(ce->list, EINA_INLIST_GET(ctx));
454 edbus_object_event_callback_del(EDBus_Object *obj, EDBus_Object_Event_Type type, EDBus_Object_Event_Cb cb, const void *cb_data)
456 EDBus_Object_Context_Event *ce;
457 EDBus_Object_Context_Event_Cb *iter, *found = NULL;
459 EDBUS_OBJECT_CHECK(obj);
460 EINA_SAFETY_ON_NULL_RETURN(cb);
461 EINA_SAFETY_ON_TRUE_RETURN(type >= EDBUS_OBJECT_EVENT_LAST);
463 ce = obj->event_handlers + type;
465 EINA_INLIST_FOREACH(ce->list, iter)
467 if (cb != iter->cb) continue;
468 if ((cb_data) && (cb_data != iter->cb_data)) continue;
474 EINA_SAFETY_ON_NULL_RETURN(found);
475 EINA_SAFETY_ON_TRUE_RETURN(found->deleted);
479 found->deleted = EINA_TRUE;
480 ce->to_delete = eina_list_append(ce->to_delete, found);
484 _edbus_object_context_event_cb_del(ce, found);
488 case EDBUS_OBJECT_EVENT_IFACE_ADDED:
490 if (obj->event_handlers[EDBUS_OBJECT_EVENT_IFACE_ADDED].list)
492 edbus_signal_handler_del(obj->interfaces_added);
493 obj->interfaces_added = NULL;
496 case EDBUS_OBJECT_EVENT_IFACE_REMOVED:
498 if (obj->event_handlers[EDBUS_OBJECT_EVENT_IFACE_REMOVED].list)
500 edbus_signal_handler_del(obj->interfaces_removed);
501 obj->interfaces_removed = NULL;
504 case EDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
505 case EDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
507 if (obj->event_handlers[EDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list ||
508 obj->event_handlers[EDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
510 edbus_signal_handler_del(obj->properties_changed);
511 obj->properties_changed = NULL;
520 _edbus_object_event_callback_call(EDBus_Object *obj, EDBus_Object_Event_Type type, const void *event_info)
522 EDBus_Object_Context_Event *ce;
523 EDBus_Object_Context_Event_Cb *iter;
525 ce = obj->event_handlers + type;
528 EINA_INLIST_FOREACH(ce->list, iter)
530 if (iter->deleted) continue;
531 iter->cb((void *)iter->cb_data, obj, (void *)event_info);
534 if (ce->walking > 0) return;
536 EINA_LIST_FREE(ce->to_delete, iter)
537 _edbus_object_context_event_cb_del(ce, iter);
540 EAPI EDBus_Connection *
541 edbus_object_connection_get(const EDBus_Object *obj)
543 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
548 edbus_object_bus_name_get(const EDBus_Object *obj)
550 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
555 edbus_object_path_get(const EDBus_Object *obj)
557 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
562 _on_pending_free(void *data, const void *dead_pointer)
564 EDBus_Object *obj = data;
565 EDBus_Pending *pending = (EDBus_Pending*) dead_pointer;
566 EDBUS_OBJECT_CHECK(obj);
567 obj->pendings = eina_inlist_remove(obj->pendings, EINA_INLIST_GET(pending));
571 edbus_object_send(EDBus_Object *obj, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout)
573 EDBus_Pending *pending;
575 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
576 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
578 pending = _edbus_connection_send(obj->conn, msg, cb, cb_data, timeout);
579 if (!cb) return NULL;
580 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
582 edbus_pending_cb_free_add(pending, _on_pending_free, obj);
583 obj->pendings = eina_inlist_append(obj->pendings, EINA_INLIST_GET(pending));
589 _on_signal_handler_free(void *data, const void *dead_pointer)
591 EDBus_Object *obj = data;
592 EDBUS_OBJECT_CHECK(obj);
593 obj->signal_handlers = eina_list_remove(obj->signal_handlers, dead_pointer);
596 EAPI EDBus_Signal_Handler *
597 edbus_object_signal_handler_add(EDBus_Object *obj, const char *interface, const char *member, EDBus_Signal_Cb cb, const void *cb_data)
599 EDBus_Signal_Handler *handler;
601 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
602 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
604 handler = _edbus_signal_handler_add(obj->conn, obj->name, obj->path,
605 interface, member, cb, cb_data);
606 EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
608 edbus_signal_handler_cb_free_add(handler, _on_signal_handler_free, obj);
609 obj->signal_handlers = eina_list_append(obj->signal_handlers, handler);
615 edbus_object_method_call_new(EDBus_Object *obj, const char *interface, const char *member)
617 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
618 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
619 EINA_SAFETY_ON_NULL_RETURN_VAL(member, NULL);
621 return edbus_message_method_call_new(obj->name, obj->path, interface, member);
625 edbus_object_proxy_add(EDBus_Object *obj, EDBus_Proxy *proxy)
627 return eina_hash_add(obj->proxies, edbus_proxy_interface_get(proxy), proxy);
631 edbus_object_proxy_get(EDBus_Object *obj, const char *interface)
633 return eina_hash_find(obj->proxies, interface);
637 edbus_object_proxy_del(EDBus_Object *obj, EDBus_Proxy *proxy, const char *interface)
639 return eina_hash_del(obj->proxies, interface, proxy);
643 get_peer_proxy(EDBus_Object *obj)
645 return edbus_proxy_get(obj, "org.freedesktop.DBus.Peer");
649 edbus_object_peer_ping(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
651 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
652 return edbus_proxy_call(get_peer_proxy(obj), "Ping", cb,
657 edbus_object_peer_machine_id_get(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
659 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
660 return edbus_proxy_call(get_peer_proxy(obj), "GetMachineId", cb,
665 edbus_object_introspect(EDBus_Object *obj, EDBus_Message_Cb cb, const void *data)
667 EDBus_Proxy *introspectable;
668 EDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
670 introspectable = edbus_proxy_get(obj, EDBUS_FDO_INTERFACE_INTROSPECTABLE);
671 return edbus_proxy_call(introspectable, "Introspect", cb, data, -1, "");