1 #include "eldbus_private.h"
2 #include "eldbus_private_types.h"
3 #include <dbus/dbus.h>
4
5 /* TODO: mempool of Eldbus_Object, Eldbus_Object_Context_Event_Cb and
6 * Eldbus_Object_Context_Event
7 */
8
9 #define ELDBUS_OBJECT_CHECK(obj) \
10 do \
11 { \
12 EINA_SAFETY_ON_NULL_RETURN(obj); \
13 if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC)) \
14 { \
15 EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC); \
16 return; \
17 } \
18 EINA_SAFETY_ON_TRUE_RETURN(obj->refcount <= 0); \
19 } \
20 while (0)
21
22 #define ELDBUS_OBJECT_CHECK_RETVAL(obj, retval) \
23 do \
24 { \
25 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, retval); \
26 if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC)) \
27 { \
28 EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC); \
29 return retval; \
30 } \
31 EINA_SAFETY_ON_TRUE_RETURN_VAL(obj->refcount <= 0, retval); \
32 } \
33 while (0)
34
35 #define ELDBUS_OBJECT_CHECK_GOTO(obj, label) \
36 do \
37 { \
38 EINA_SAFETY_ON_NULL_GOTO(obj, label); \
39 if (!EINA_MAGIC_CHECK(obj, ELDBUS_OBJECT_MAGIC)) \
40 { \
41 EINA_MAGIC_FAIL(obj, ELDBUS_OBJECT_MAGIC); \
42 goto label; \
43 } \
44 EINA_SAFETY_ON_TRUE_GOTO(obj->refcount <= 0, label); \
45 } \
46 while (0)
47
48 Eina_Bool
eldbus_object_init(void)49 eldbus_object_init(void)
50 {
51 return EINA_TRUE;
52 }
53
54 void
eldbus_object_shutdown(void)55 eldbus_object_shutdown(void)
56 {
57 }
58
59 static void _eldbus_object_event_callback_call(Eldbus_Object *obj, Eldbus_Object_Event_Type type, const void *event_info);
60 static void _eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event *ce, Eldbus_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);
63
64 static void
_eldbus_object_call_del(Eldbus_Object * obj)65 _eldbus_object_call_del(Eldbus_Object *obj)
66 {
67 Eldbus_Object_Context_Event *ce;
68
69 _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_DEL, NULL);
70
71 /* clear all del callbacks so we don't call them twice at
72 * _eldbus_object_clear()
73 */
74 ce = obj->event_handlers + ELDBUS_OBJECT_EVENT_DEL;
75 while (ce->list)
76 {
77 Eldbus_Object_Context_Event_Cb *ctx;
78
79 ctx = EINA_INLIST_CONTAINER_GET(ce->list,
80 Eldbus_Object_Context_Event_Cb);
81 _eldbus_object_context_event_cb_del(ce, ctx);
82 }
83 }
84
85 static void
_eldbus_object_clear(Eldbus_Object * obj)86 _eldbus_object_clear(Eldbus_Object *obj)
87 {
88 Eldbus_Signal_Handler *h;
89 Eldbus_Pending *p;
90 Eina_List *iter, *iter_next;
91 Eina_Inlist *in_l;
92 DBG("obj=%p, refcount=%d, name=%s, path=%s",
93 obj, obj->refcount, obj->name, obj->path);
94
95 obj->refcount = 1;
96 _eldbus_object_call_del(obj);
97 eldbus_connection_name_object_del(obj->conn, obj);
98
99 /* NOTE: obj->proxies is deleted from obj->cbs_free. */
100
101 EINA_LIST_FOREACH_SAFE(obj->signal_handlers, iter, iter_next, h)
102 {
103 DBG("obj=%p delete owned signal handler %p %s",
104 obj, h, eldbus_signal_handler_match_get(h));
105 eldbus_signal_handler_del(h);
106 }
107 EINA_INLIST_FOREACH_SAFE(obj->pendings, in_l, p)
108 {
109 DBG("obj=%p delete owned pending call=%p dest=%s path=%s %s.%s()",
110 obj, p,
111 eldbus_pending_destination_get(p),
112 eldbus_pending_path_get(p),
113 eldbus_pending_interface_get(p),
114 eldbus_pending_method_get(p));
115 eldbus_pending_cancel(p);
116 }
117
118 eldbus_cbs_free_dispatch(&(obj->cbs_free), obj);
119 obj->refcount = 0;
120 }
121
122 static void
_eldbus_object_free(Eldbus_Object * obj)123 _eldbus_object_free(Eldbus_Object *obj)
124 {
125 unsigned int i;
126 Eldbus_Signal_Handler *h;
127
128 if (obj->proxies)
129 {
130 Eina_Iterator *iterator = eina_hash_iterator_data_new(obj->proxies);
131 Eldbus_Proxy *proxy;
132 EINA_ITERATOR_FOREACH(iterator, proxy)
133 ERR("obj=%p alive proxy=%p %s", obj, proxy,
134 eldbus_proxy_interface_get(proxy));
135 eina_iterator_free(iterator);
136 eina_hash_free(obj->proxies);
137 }
138
139 EINA_LIST_FREE(obj->signal_handlers, h)
140 {
141 if (h->dangling)
142 eldbus_signal_handler_free_cb_del(h, _on_signal_handler_free, obj);
143 else
144 ERR("obj=%p alive handler=%p %s", obj, h,
145 eldbus_signal_handler_match_get(h));
146 }
147
148 if (obj->pendings)
149 CRI("Object %p released with live pending calls!", obj);
150
151 for (i = 0; i < ELDBUS_OBJECT_EVENT_LAST; i++)
152 {
153 Eldbus_Object_Context_Event *ce = obj->event_handlers + i;
154 while (ce->list)
155 {
156 Eldbus_Object_Context_Event_Cb *ctx;
157
158 ctx = EINA_INLIST_CONTAINER_GET(ce->list,
159 Eldbus_Object_Context_Event_Cb);
160 _eldbus_object_context_event_cb_del(ce, ctx);
161 }
162 eina_list_free(ce->to_delete);
163 }
164
165 if (obj->interfaces_added)
166 eldbus_signal_handler_del(obj->interfaces_added);
167 if (obj->interfaces_removed)
168 eldbus_signal_handler_del(obj->interfaces_removed);
169 if (obj->properties_changed)
170 eldbus_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);
174
175 free(obj);
176 }
177
178 static void
_on_connection_free(void * data,const void * dead_pointer EINA_UNUSED)179 _on_connection_free(void *data, const void *dead_pointer EINA_UNUSED)
180 {
181 Eldbus_Object *obj = data;
182 ELDBUS_OBJECT_CHECK(obj);
183 _eldbus_object_clear(obj);
184 _eldbus_object_free(obj);
185 }
186
187 EAPI Eldbus_Object *
eldbus_object_get(Eldbus_Connection * conn,const char * bus,const char * path)188 eldbus_object_get(Eldbus_Connection *conn, const char *bus, const char *path)
189 {
190 Eldbus_Object *obj;
191
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);
195
196 obj = eldbus_connection_name_object_get(conn, bus, path);
197 if (obj)
198 return eldbus_object_ref(obj);
199
200 obj = calloc(1, sizeof(Eldbus_Object));
201 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
202
203 obj->conn = conn;
204 obj->refcount = 1;
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, ELDBUS_OBJECT_MAGIC);
210
211 eldbus_connection_name_object_set(conn, obj);
212 eldbus_connection_free_cb_add(obj->conn, _on_connection_free, obj);
213
214 obj->properties = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE_PROPERTIES);
215
216 return obj;
217
218 cleanup:
219 eina_stringshare_del(obj->path);
220 eina_stringshare_del(obj->name);
221 free(obj);
222
223 return NULL;
224 }
225
226 static void _on_signal_handler_free(void *data, const void *dead_pointer);
227
228 static void
_eldbus_object_unref(Eldbus_Object * obj)229 _eldbus_object_unref(Eldbus_Object *obj)
230 {
231 obj->refcount--;
232 if (obj->refcount > 0) return;
233
234 eldbus_connection_free_cb_del(obj->conn, _on_connection_free, obj);
235 _eldbus_object_clear(obj);
236 _eldbus_object_free(obj);
237 }
238
239 EAPI Eldbus_Object *
eldbus_object_ref(Eldbus_Object * obj)240 eldbus_object_ref(Eldbus_Object *obj)
241 {
242 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
243 DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
244 obj, obj->refcount, obj->name, obj->path);
245 obj->refcount++;
246 return obj;
247 }
248
249 EAPI void
eldbus_object_unref(Eldbus_Object * obj)250 eldbus_object_unref(Eldbus_Object *obj)
251 {
252 ELDBUS_OBJECT_CHECK(obj);
253 DBG("obj=%p, pre-refcount=%d, name=%s, path=%s",
254 obj, obj->refcount, obj->name, obj->path);
255 _eldbus_object_unref(obj);
256 }
257
258 EAPI void
eldbus_object_free_cb_add(Eldbus_Object * obj,Eldbus_Free_Cb cb,const void * data)259 eldbus_object_free_cb_add(Eldbus_Object *obj, Eldbus_Free_Cb cb, const void *data)
260 {
261 ELDBUS_OBJECT_CHECK(obj);
262 EINA_SAFETY_ON_NULL_RETURN(cb);
263 obj->cbs_free = eldbus_cbs_free_add(obj->cbs_free, cb, data);
264 }
265
266 EAPI void
eldbus_object_free_cb_del(Eldbus_Object * obj,Eldbus_Free_Cb cb,const void * data)267 eldbus_object_free_cb_del(Eldbus_Object *obj, Eldbus_Free_Cb cb, const void *data)
268 {
269 ELDBUS_OBJECT_CHECK(obj);
270 EINA_SAFETY_ON_NULL_RETURN(cb);
271 obj->cbs_free = eldbus_cbs_free_del(obj->cbs_free, cb, data);
272 }
273
274 static void
_cb_interfaces_added(void * data,const Eldbus_Message * msg)275 _cb_interfaces_added(void *data, const Eldbus_Message *msg)
276 {
277 Eldbus_Object *obj = data;
278 const char *obj_path;
279 Eldbus_Message_Iter *array_ifaces, *entry_iface;
280
281 if (!eldbus_message_arguments_get(msg, "oa{sa{sv}}", &obj_path, &array_ifaces))
282 return;
283
284 while (eldbus_message_iter_get_and_next(array_ifaces, 'e', &entry_iface))
285 {
286 const char *iface_name;
287 Eldbus_Object_Event_Interface_Added event;
288
289 eldbus_message_iter_basic_get(entry_iface, &iface_name);
290 event.proxy = eldbus_proxy_get(obj, iface_name);
291 EINA_SAFETY_ON_NULL_RETURN(event.proxy);
292 event.interface = iface_name;
293 _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_IFACE_ADDED,
294 &event);
295 eldbus_proxy_unref(event.proxy);
296 }
297 }
298
299 static void
_cb_interfaces_removed(void * data,const Eldbus_Message * msg)300 _cb_interfaces_removed(void *data, const Eldbus_Message *msg)
301 {
302 Eldbus_Object *obj = data;
303 const char *obj_path, *iface;
304 Eldbus_Message_Iter *array_ifaces;
305
306 if (!eldbus_message_arguments_get(msg, "oas", &obj_path, &array_ifaces))
307 return;
308
309 while (eldbus_message_iter_get_and_next(array_ifaces, 's', &iface))
310 {
311 Eldbus_Object_Event_Interface_Removed event;
312 event.interface = iface;
313 _eldbus_object_event_callback_call(obj, ELDBUS_OBJECT_EVENT_IFACE_REMOVED,
314 &event);
315 }
316 }
317
318 static void
_property_changed_iter(void * data,const void * key,Eldbus_Message_Iter * var)319 _property_changed_iter(void *data, const void *key, Eldbus_Message_Iter *var)
320 {
321 Eldbus_Proxy *proxy = data;
322 const char *skey = key;
323 Eina_Value *st_value, stack_value;
324 Eldbus_Object_Event_Property_Changed event;
325
326 st_value = _message_iter_struct_to_eina_value(var);
327 eina_value_struct_value_get(st_value, "arg0", &stack_value);
328
329 event.interface = eldbus_proxy_interface_get(proxy);
330 event.proxy = proxy;
331 event.name = skey;
332 event.value = &stack_value;
333 _eldbus_object_event_callback_call(eldbus_proxy_object_get(proxy),
334 ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED,
335 &event);
336 eina_value_free(st_value);
337 eina_value_flush(&stack_value);
338 }
339
340 static void
_cb_properties_changed(void * data,const Eldbus_Message * msg)341 _cb_properties_changed(void *data, const Eldbus_Message *msg)
342 {
343 Eldbus_Object *obj = data;
344 Eldbus_Proxy *proxy;
345 Eldbus_Message_Iter *array, *invalidate;
346 const char *iface;
347 const char *invalidate_prop;
348
349 if (!eldbus_message_arguments_get(msg, "sa{sv}as", &iface, &array, &invalidate))
350 {
351 ERR("Error getting data from properties changed signal.");
352 return;
353 }
354
355 proxy = eldbus_proxy_get(obj, iface);
356 EINA_SAFETY_ON_NULL_RETURN(proxy);
357
358 if (obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list)
359 eldbus_message_iter_dict_iterate(array, "sv", _property_changed_iter,
360 proxy);
361
362 if (!obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
363 goto end;
364
365 while (eldbus_message_iter_get_and_next(invalidate, 's', &invalidate_prop))
366 {
367 Eldbus_Object_Event_Property_Removed event;
368 event.interface = iface;
369 event.name = invalidate_prop;
370 event.proxy = proxy;
371 _eldbus_object_event_callback_call(obj,
372 ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED,
373 &event);
374 }
375 end:
376 eldbus_proxy_unref(proxy);
377 }
378
379 EAPI void
eldbus_object_event_callback_add(Eldbus_Object * obj,Eldbus_Object_Event_Type type,Eldbus_Object_Event_Cb cb,const void * cb_data)380 eldbus_object_event_callback_add(Eldbus_Object *obj, Eldbus_Object_Event_Type type, Eldbus_Object_Event_Cb cb, const void *cb_data)
381 {
382 Eldbus_Object_Context_Event *ce;
383 Eldbus_Object_Context_Event_Cb *ctx;
384
385 ELDBUS_OBJECT_CHECK(obj);
386 EINA_SAFETY_ON_NULL_RETURN(cb);
387 EINA_SAFETY_ON_TRUE_RETURN(type >= ELDBUS_OBJECT_EVENT_LAST);
388
389 ce = obj->event_handlers + type;
390
391 ctx = calloc(1, sizeof(Eldbus_Object_Context_Event_Cb));
392 EINA_SAFETY_ON_NULL_RETURN(ctx);
393
394 ctx->cb = cb;
395 ctx->cb_data = cb_data;
396
397 ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
398
399 switch (type)
400 {
401 case ELDBUS_OBJECT_EVENT_IFACE_ADDED:
402 {
403 if (obj->interfaces_added)
404 break;
405 obj->interfaces_added =
406 _eldbus_signal_handler_add(obj->conn, obj->name, NULL,
407 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
408 "InterfacesAdded",
409 _cb_interfaces_added, obj);
410 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_added);
411 eldbus_signal_handler_match_extra_set(obj->interfaces_added, "arg0",
412 obj->path, NULL);
413 break;
414 }
415 case ELDBUS_OBJECT_EVENT_IFACE_REMOVED:
416 {
417 if (obj->interfaces_removed)
418 break;
419 obj->interfaces_removed =
420 _eldbus_signal_handler_add(obj->conn, obj->name, NULL,
421 ELDBUS_FDO_INTERFACE_OBJECT_MANAGER,
422 "InterfacesRemoved",
423 _cb_interfaces_removed, obj);
424 EINA_SAFETY_ON_NULL_RETURN(obj->interfaces_removed);
425 eldbus_signal_handler_match_extra_set(obj->interfaces_removed,
426 "arg0", obj->path, NULL);
427 break;
428 }
429 case ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
430 case ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
431 {
432 if (obj->properties_changed)
433 break;
434 obj->properties_changed =
435 eldbus_object_signal_handler_add(obj,
436 ELDBUS_FDO_INTERFACE_PROPERTIES,
437 "PropertiesChanged",
438 _cb_properties_changed, obj);
439 EINA_SAFETY_ON_NULL_RETURN(obj->properties_changed);
440 break;
441 }
442 default:
443 break;
444 }
445 }
446
447 static void
_eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event * ce,Eldbus_Object_Context_Event_Cb * ctx)448 _eldbus_object_context_event_cb_del(Eldbus_Object_Context_Event *ce, Eldbus_Object_Context_Event_Cb *ctx)
449 {
450 ce->list = eina_inlist_remove(ce->list, EINA_INLIST_GET(ctx));
451 free(ctx);
452 }
453
454 EAPI void
eldbus_object_event_callback_del(Eldbus_Object * obj,Eldbus_Object_Event_Type type,Eldbus_Object_Event_Cb cb,const void * cb_data)455 eldbus_object_event_callback_del(Eldbus_Object *obj, Eldbus_Object_Event_Type type, Eldbus_Object_Event_Cb cb, const void *cb_data)
456 {
457 Eldbus_Object_Context_Event *ce;
458 Eldbus_Object_Context_Event_Cb *iter, *found = NULL;
459
460 ELDBUS_OBJECT_CHECK(obj);
461 EINA_SAFETY_ON_NULL_RETURN(cb);
462 EINA_SAFETY_ON_TRUE_RETURN(type >= ELDBUS_OBJECT_EVENT_LAST);
463
464 ce = obj->event_handlers + type;
465
466 EINA_INLIST_FOREACH(ce->list, iter)
467 {
468 if (cb != iter->cb) continue;
469 if ((cb_data) && (cb_data != iter->cb_data)) continue;
470
471 found = iter;
472 break;
473 }
474
475 EINA_SAFETY_ON_NULL_RETURN(found);
476 EINA_SAFETY_ON_TRUE_RETURN(found->deleted);
477
478 if (ce->walking)
479 {
480 found->deleted = EINA_TRUE;
481 ce->to_delete = eina_list_append(ce->to_delete, found);
482 return;
483 }
484
485 _eldbus_object_context_event_cb_del(ce, found);
486
487 switch (type)
488 {
489 case ELDBUS_OBJECT_EVENT_IFACE_ADDED:
490 {
491 if (obj->event_handlers[ELDBUS_OBJECT_EVENT_IFACE_ADDED].list)
492 break;
493 eldbus_signal_handler_del(obj->interfaces_added);
494 obj->interfaces_added = NULL;
495 break;
496 }
497 case ELDBUS_OBJECT_EVENT_IFACE_REMOVED:
498 {
499 if (obj->event_handlers[ELDBUS_OBJECT_EVENT_IFACE_REMOVED].list)
500 break;
501 eldbus_signal_handler_del(obj->interfaces_removed);
502 obj->interfaces_removed = NULL;
503 break;
504 }
505 case ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED:
506 case ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED:
507 {
508 if (obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED].list ||
509 obj->event_handlers[ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED].list)
510 break;
511 eldbus_signal_handler_del(obj->properties_changed);
512 obj->properties_changed = NULL;
513 break;
514 }
515 default:
516 break;
517 }
518 }
519
520 static void
_eldbus_object_event_callback_call(Eldbus_Object * obj,Eldbus_Object_Event_Type type,const void * event_info)521 _eldbus_object_event_callback_call(Eldbus_Object *obj, Eldbus_Object_Event_Type type, const void *event_info)
522 {
523 Eldbus_Object_Context_Event *ce;
524 Eldbus_Object_Context_Event_Cb *iter;
525
526 ce = obj->event_handlers + type;
527
528 ce->walking++;
529 EINA_INLIST_FOREACH(ce->list, iter)
530 {
531 if (iter->deleted) continue;
532 iter->cb((void *)iter->cb_data, obj, (void *)event_info);
533 }
534 ce->walking--;
535 if (ce->walking > 0) return;
536
537 EINA_LIST_FREE(ce->to_delete, iter)
538 _eldbus_object_context_event_cb_del(ce, iter);
539 }
540
541 EAPI Eldbus_Connection *
eldbus_object_connection_get(const Eldbus_Object * obj)542 eldbus_object_connection_get(const Eldbus_Object *obj)
543 {
544 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
545 return obj->conn;
546 }
547
548 EAPI const char *
eldbus_object_bus_name_get(const Eldbus_Object * obj)549 eldbus_object_bus_name_get(const Eldbus_Object *obj)
550 {
551 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
552 return obj->name;
553 }
554
555 EAPI const char *
eldbus_object_path_get(const Eldbus_Object * obj)556 eldbus_object_path_get(const Eldbus_Object *obj)
557 {
558 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
559 return obj->path;
560 }
561
562 static void
_on_object_message_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending)563 _on_object_message_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
564 {
565 Eldbus_Message_Cb cb = eldbus_pending_data_del(pending, "__user_cb");
566 Eldbus_Object *obj = eldbus_pending_data_del(pending, "__object");
567
568 ELDBUS_OBJECT_CHECK(obj);
569 obj->pendings = eina_inlist_remove(obj->pendings, EINA_INLIST_GET(pending));
570
571 cb(data, msg, pending);
572 }
573
574 EAPI Eldbus_Pending *
eldbus_object_send(Eldbus_Object * obj,Eldbus_Message * msg,Eldbus_Message_Cb cb,const void * cb_data,double timeout)575 eldbus_object_send(Eldbus_Object *obj, Eldbus_Message *msg, Eldbus_Message_Cb cb, const void *cb_data, double timeout)
576 {
577 Eldbus_Pending *pending;
578
579 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
580 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, NULL);
581
582 if (!cb)
583 {
584 _eldbus_connection_send(obj->conn, msg, NULL, NULL, timeout);
585 return NULL;
586 }
587 pending = _eldbus_connection_send(obj->conn, msg, _on_object_message_cb,
588 cb_data, timeout);
589 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, NULL);
590
591 eldbus_pending_data_set(pending, "__user_cb", cb);
592 eldbus_pending_data_set(pending, "__object", obj);
593 obj->pendings = eina_inlist_append(obj->pendings, EINA_INLIST_GET(pending));
594
595 return pending;
596 }
597
598 static void
_on_signal_handler_free(void * data,const void * dead_pointer)599 _on_signal_handler_free(void *data, const void *dead_pointer)
600 {
601 Eldbus_Object *obj = data;
602 ELDBUS_OBJECT_CHECK(obj);
603 obj->signal_handlers = eina_list_remove(obj->signal_handlers, dead_pointer);
604 }
605
606 EAPI Eldbus_Signal_Handler *
eldbus_object_signal_handler_add(Eldbus_Object * obj,const char * interface,const char * member,Eldbus_Signal_Cb cb,const void * cb_data)607 eldbus_object_signal_handler_add(Eldbus_Object *obj, const char *interface, const char *member, Eldbus_Signal_Cb cb, const void *cb_data)
608 {
609 Eldbus_Signal_Handler *handler;
610
611 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
612 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
613
614 handler = _eldbus_signal_handler_add(obj->conn, obj->name, obj->path,
615 interface, member, cb, cb_data);
616 EINA_SAFETY_ON_NULL_RETURN_VAL(handler, NULL);
617
618 eldbus_signal_handler_free_cb_add(handler, _on_signal_handler_free, obj);
619 obj->signal_handlers = eina_list_append(obj->signal_handlers, handler);
620
621 return handler;
622 }
623
624 EAPI Eldbus_Message *
eldbus_object_method_call_new(Eldbus_Object * obj,const char * interface,const char * member)625 eldbus_object_method_call_new(Eldbus_Object *obj, const char *interface, const char *member)
626 {
627 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
628 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
629 EINA_SAFETY_ON_NULL_RETURN_VAL(member, NULL);
630
631 return eldbus_message_method_call_new(obj->name, obj->path, interface, member);
632 }
633
634 Eina_Bool
eldbus_object_proxy_add(Eldbus_Object * obj,Eldbus_Proxy * proxy)635 eldbus_object_proxy_add(Eldbus_Object *obj, Eldbus_Proxy *proxy)
636 {
637 return eina_hash_add(obj->proxies, eldbus_proxy_interface_get(proxy), proxy);
638 }
639
640 Eldbus_Proxy *
eldbus_object_proxy_get(Eldbus_Object * obj,const char * interface)641 eldbus_object_proxy_get(Eldbus_Object *obj, const char *interface)
642 {
643 return eina_hash_find(obj->proxies, interface);
644 }
645
646 Eina_Bool
eldbus_object_proxy_del(Eldbus_Object * obj,Eldbus_Proxy * proxy,const char * interface)647 eldbus_object_proxy_del(Eldbus_Object *obj, Eldbus_Proxy *proxy, const char *interface)
648 {
649 return eina_hash_del(obj->proxies, interface, proxy);
650 }
651
652 EAPI Eldbus_Pending *
eldbus_object_peer_ping(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)653 eldbus_object_peer_ping(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
654 {
655 Eldbus_Message *msg;
656 Eldbus_Pending *p;
657 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
658 msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER, "Ping");
659 p = eldbus_object_send(obj, msg, cb, data, -1);
660 return p;
661 }
662
663 EAPI Eldbus_Pending *
eldbus_object_peer_machine_id_get(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)664 eldbus_object_peer_machine_id_get(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
665 {
666 Eldbus_Message *msg;
667 Eldbus_Pending *p;
668 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
669 msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTEFACE_PEER,
670 "GetMachineId");
671 p = eldbus_object_send(obj, msg, cb, data, -1);
672 return p;
673 }
674
675 EAPI Eldbus_Pending *
eldbus_object_introspect(Eldbus_Object * obj,Eldbus_Message_Cb cb,const void * data)676 eldbus_object_introspect(Eldbus_Object *obj, Eldbus_Message_Cb cb, const void *data)
677 {
678 Eldbus_Message *msg;
679 Eldbus_Pending *p;
680 ELDBUS_OBJECT_CHECK_RETVAL(obj, NULL);
681 msg = eldbus_object_method_call_new(obj, ELDBUS_FDO_INTERFACE_INTROSPECTABLE,
682 "Introspect");
683 p = eldbus_object_send(obj, msg, cb, data, -1);
684 return p;
685 }
686