7
#include "eldbus_model_proxy_private.h"
8
#include "eldbus_model_private.h"
10
#define MY_CLASS ELDBUS_MODEL_PROXY_CLASS
11
#define MY_CLASS_NAME "Eldbus_Model_Proxy"
13
static void _eldbus_model_proxy_property_get_all_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
14
static void _eldbus_model_proxy_property_set_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
15
static void _eldbus_model_proxy_property_set_load_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
16
static void _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *);
17
static void _eldbus_model_proxy_property_changed_cb(void *, Eldbus_Proxy *, void *);
18
static void _eldbus_model_proxy_property_invalidated_cb(void *, Eldbus_Proxy *, void *);
19
static const char *_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *, const char *);
20
static void _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *);
21
static void _eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *);
24
typedef struct _Eldbus_Model_Proxy_Property_Set_Data Eldbus_Model_Proxy_Property_Set_Data;
25
typedef struct _Eldbus_Property_Promise Eldbus_Property_Promise;
27
struct _Eldbus_Model_Proxy_Property_Set_Data
29
Eldbus_Model_Proxy_Data *pd;
31
Eina_Stringshare *property;
32
Eina_Promise *promise;
36
struct _Eldbus_Property_Promise
38
Eina_Promise *promise;
39
Eina_Stringshare *property;
43
_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd)
45
Eldbus_Introspection_Property *property;
51
pd->proxy = eldbus_proxy_get(pd->object, pd->name);
52
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->proxy, EINA_FALSE);
54
EINA_LIST_FOREACH(pd->interface->properties, it, property)
56
const Eina_Value_Type *type;
57
Eina_Stringshare *name;
60
type = _dbus_type_to_eina_value_type(property->type[0]);
61
name = eina_stringshare_add(property->name);
62
value = eina_value_new(type);
64
eina_hash_direct_add(pd->properties, name, value);
71
_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd)
73
Eldbus_Pending *pending;
75
EINA_LIST_FREE(pd->pendings, pending)
76
eldbus_pending_cancel(pending);
80
eldbus_proxy_event_callback_del(pd->proxy,
81
ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
82
_eldbus_model_proxy_property_changed_cb,
84
eldbus_proxy_event_callback_del(pd->proxy,
85
ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
86
_eldbus_model_proxy_property_invalidated_cb,
89
pd->monitoring = EINA_FALSE;
91
if (pd->proxy) eldbus_proxy_unref(pd->proxy);
96
_eldbus_model_proxy_object_del(void *data, Eldbus_Object *object EINA_UNUSED, void *event_info EINA_UNUSED)
98
Eldbus_Model_Proxy_Data *pd = data;
104
_eldbus_model_proxy_efl_object_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
106
obj = efl_constructor(efl_super(obj, MY_CLASS));
109
pd->properties = eina_hash_stringshared_new(NULL);
115
_eldbus_model_proxy_efl_object_finalize(Eo *obj, Eldbus_Model_Proxy_Data *pd)
122
if (!_eldbus_model_proxy_load(pd)) return NULL;
124
if (!eldbus_model_connection_get(obj))
125
eldbus_model_connection_set(obj, eldbus_object_connection_get(pd->object));
127
eldbus_object_event_callback_add(pd->object, ELDBUS_OBJECT_EVENT_DEL, _eldbus_model_proxy_object_del, pd);
129
return efl_finalize(efl_super(obj, MY_CLASS));
133
_eldbus_model_proxy_object_set(Eo *obj EINA_UNUSED,
134
Eldbus_Model_Proxy_Data *pd,
135
Eldbus_Object *object)
137
pd->object = eldbus_object_ref(object);
141
_eldbus_model_proxy_interface_set(Eo *obj EINA_UNUSED,
142
Eldbus_Model_Proxy_Data *pd,
143
const Eldbus_Introspection_Interface *interface)
145
pd->name = eina_stringshare_add(interface->name);
146
pd->interface = interface;
150
_eldbus_model_proxy_efl_object_invalidate(Eo *obj, Eldbus_Model_Proxy_Data *pd)
154
EINA_LIST_FREE(pd->childrens, child)
157
_eldbus_model_proxy_unload(pd);
161
eldbus_object_event_callback_del(pd->object, ELDBUS_OBJECT_EVENT_DEL, _eldbus_model_proxy_object_del, pd);
162
eldbus_object_unref(pd->object);
165
efl_invalidate(efl_super(obj, MY_CLASS));
169
_eldbus_model_proxy_efl_object_destructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
171
Eina_Hash_Tuple *tuple;
174
it = eina_hash_iterator_tuple_new(pd->properties);
175
EINA_ITERATOR_FOREACH(it, tuple)
177
Eina_Stringshare *property = tuple->key;
178
Eina_Value *value = tuple->data;
180
eina_stringshare_del(property);
181
eina_value_free(value);
183
eina_iterator_free(it);
184
eina_hash_free(pd->properties);
186
eina_stringshare_del(pd->name);
188
efl_destructor(efl_super(obj, MY_CLASS));
191
static Eina_Iterator *
192
_eldbus_model_proxy_efl_model_properties_get(const Eo *obj EINA_UNUSED,
193
Eldbus_Model_Proxy_Data *pd)
195
return eina_hash_iterator_key_new(pd->properties);
198
#define PROPERTY_EXIST 1
199
#define PROPERTY_READ 2
200
#define PROPERTY_WRITE 4
203
eldbus_model_proxy_property_check(Eldbus_Model_Proxy_Data *pd,
204
const char *property)
206
Eldbus_Introspection_Property *property_introspection =
207
eldbus_introspection_property_find(pd->interface->properties, property);
210
if (property_introspection == NULL)
212
WRN("Property not found: %s", property);
218
if (property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ ||
219
property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE)
222
if (property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE ||
223
property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE)
230
_eldbus_model_proxy_cancel_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
232
const Eina_Future *dead_future EINA_UNUSED)
234
Eldbus_Model_Proxy_Property_Set_Data *sd = data;
237
eina_stringshare_del(sd->property);
238
eina_value_free(sd->value);
242
static Eldbus_Pending *
243
_eldbus_model_proxy_load_all(Eldbus_Model_Proxy_Data *pd,
244
Eina_Promise *promise, const char *property,
245
Eldbus_Message_Cb callback,
248
Eldbus_Property_Promise *p;
249
Eldbus_Pending *pending = NULL;
251
p = calloc(1, sizeof(Eldbus_Property_Promise));
254
if (promise) eina_promise_reject(promise, ENOMEM);
258
p->promise = promise;
259
p->property = eina_stringshare_add(property);
260
pd->promises = eina_list_append(pd->promises, p);
264
pending = eldbus_proxy_property_get_all(pd->proxy, callback, data);
270
_eldbus_model_proxy_efl_model_property_set(Eo *obj EINA_UNUSED,
271
Eldbus_Model_Proxy_Data *pd,
272
const char *property,
275
Eldbus_Model_Proxy_Property_Set_Data *data = NULL;
276
const char *signature;
277
Eldbus_Pending *pending;
278
unsigned char access;
281
DBG("(%p): property=%s", obj, property);
283
access = eldbus_model_proxy_property_check(pd, property);
284
err = EFL_MODEL_ERROR_NOT_FOUND;
285
if (!access) goto on_error;
286
err = EFL_MODEL_ERROR_READ_ONLY;
287
if (!(access & PROPERTY_WRITE)) goto on_error;
289
err = EFL_MODEL_ERROR_UNKNOWN;
290
signature = _eldbus_model_proxy_property_type_get(pd, property);
291
if (!signature) goto on_error;
294
data = calloc(1, sizeof (Eldbus_Model_Proxy_Property_Set_Data));
295
if (!data) goto on_error;
298
data->promise = efl_loop_promise_new(obj);
299
data->property = eina_stringshare_add(property);
300
if (!(data->value = eina_value_dup(value))) goto on_error;
304
pending = _eldbus_model_proxy_load_all(pd, data->promise, property,
305
_eldbus_model_proxy_property_set_load_cb, data);
309
pending = eldbus_proxy_property_value_set(pd->proxy, property, signature, (Eina_Value*)value,
310
_eldbus_model_proxy_property_set_cb, data);
313
if (pending) pd->pendings = eina_list_append(pd->pendings, pending);
314
return efl_future_then(obj, eina_future_new(data->promise),
315
.data = data, .free = _eldbus_model_proxy_cancel_cb);
319
return efl_loop_future_rejected(obj, err);
323
_eldbus_model_proxy_efl_model_property_get(const Eo *obj EINA_UNUSED,
324
Eldbus_Model_Proxy_Data *pd,
325
const char *property)
327
Eldbus_Pending *pending;
328
unsigned char access;
331
access = eldbus_model_proxy_property_check(pd, property);
332
err = EFL_MODEL_ERROR_NOT_FOUND;
333
if (!access) goto on_error;
334
if (!(access & PROPERTY_READ)) goto on_error;
338
Eina_Stringshare *tmp;
341
err = EFL_MODEL_ERROR_NOT_FOUND;
342
tmp = eina_stringshare_add(property);
343
value = eina_hash_find(pd->properties, tmp);
344
eina_stringshare_del(tmp);
345
if (!value) goto on_error;
347
return eina_value_dup(value);
352
pending = _eldbus_model_proxy_load_all(pd, NULL, property,
353
_eldbus_model_proxy_property_get_all_cb, pd);
354
if (pending) pd->pendings = eina_list_append(pd->pendings, pending);
357
return eina_value_error_new(EAGAIN);
360
return eina_value_error_new(err);
364
_eldbus_model_proxy_listed(Eldbus_Model_Proxy_Data *pd)
368
_eldbus_model_proxy_create_methods_children(pd);
369
_eldbus_model_proxy_create_signals_children(pd);
371
efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, NULL);
372
pd->is_listed = EINA_TRUE;
377
_eldbus_model_proxy_efl_model_children_slice_get(Eo *obj EINA_UNUSED,
378
Eldbus_Model_Proxy_Data *pd,
384
_eldbus_model_proxy_listed(pd);
386
v = efl_model_list_value_get(pd->childrens, start, count);
387
return efl_loop_future_resolved(obj, v);
391
_eldbus_model_proxy_efl_model_children_count_get(const Eo *obj EINA_UNUSED,
392
Eldbus_Model_Proxy_Data *pd)
394
_eldbus_model_proxy_listed(pd);
395
return eina_list_count(pd->childrens);
399
_eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd)
401
Eldbus_Introspection_Method *method;
404
EINA_LIST_FOREACH(pd->interface->methods, it, method)
408
const char *interface_name;
409
const char *method_name;
412
bus = eldbus_object_bus_name_get(pd->object);
415
path = eldbus_object_path_get(pd->object);
418
interface_name = pd->interface->name;
419
if (!interface_name) continue;
421
method_name = method->name;
422
if (!method_name) continue;
424
INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s",
425
pd->obj, bus, path, interface_name, method_name);
427
child = efl_add_ref(ELDBUS_MODEL_METHOD_CLASS, pd->obj,
428
eldbus_model_method_proxy_set(efl_added, pd->proxy),
429
eldbus_model_method_set(efl_added, method));
431
if (child) pd->childrens = eina_list_append(pd->childrens, child);
432
else ERR("Could not create method child: bus = %s, path = %s method = %s::%s.",
433
bus, path, interface_name, method_name);
438
_eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd)
441
Eldbus_Introspection_Signal *signal;
443
EINA_LIST_FOREACH(pd->interface->signals, it, signal)
447
const char *interface_name;
448
const char *signal_name;
451
bus = eldbus_object_bus_name_get(pd->object);
454
path = eldbus_object_path_get(pd->object);
457
interface_name = pd->interface->name;
458
if (!interface_name) continue;
460
signal_name = signal->name;
461
if (!signal_name) continue;
463
DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s",
464
pd->obj, bus, path, interface_name, signal_name);
466
child = efl_add_ref(ELDBUS_MODEL_SIGNAL_CLASS, pd->obj, eldbus_model_signal_constructor(efl_added, pd->proxy, signal));
468
if (child) pd->childrens = eina_list_append(pd->childrens, child);
469
else ERR("Could not create signal child: bus = %s, path = %s signal = %s::%s.",
470
bus, path, interface_name, signal_name);
475
_eldbus_model_proxy_proxy_name_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
481
_eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd)
486
pd->monitoring = EINA_TRUE;
488
eldbus_proxy_event_callback_add(pd->proxy,
489
ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
490
_eldbus_model_proxy_property_changed_cb,
493
eldbus_proxy_event_callback_add(pd->proxy,
494
ELDBUS_PROXY_EVENT_PROPERTY_REMOVED,
495
_eldbus_model_proxy_property_invalidated_cb,
500
_eldbus_model_proxy_property_changed_cb(void *data,
501
Eldbus_Proxy *proxy EINA_UNUSED,
504
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
505
Eldbus_Object_Event_Property_Changed *event = (Eldbus_Object_Event_Property_Changed*)event_info;
506
Eina_Value *prop_value;
509
prop_value = eina_hash_find(pd->properties, event->name);
510
if (!prop_value) return ;
512
ret = eina_value_copy(event->value, prop_value);
515
efl_model_properties_changed(pd->obj, event->name);
519
_eldbus_model_proxy_property_invalidated_cb(void *data,
520
Eldbus_Proxy *proxy EINA_UNUSED,
523
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
524
Eldbus_Proxy_Event_Property_Changed *event = (Eldbus_Proxy_Event_Property_Changed*)event_info;
526
efl_model_property_invalidated_notify(pd->obj, event->name);
530
_eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Model_Proxy_Data *pd)
532
Eldbus_Message_Iter *values = NULL;
533
Eldbus_Message_Iter *entry;
534
Eina_Array *changed_properties;
535
Eina_Stringshare *tmp = NULL;
536
const char *error_name, *error_text;
538
if (eldbus_message_error_get(msg, &error_name, &error_text))
540
ERR("%s: %s", error_name, error_text);
544
if (!eldbus_message_arguments_get(msg, "a{sv}", &values))
546
ERR("%s", "Error getting arguments.");
550
changed_properties = eina_array_new(1);
551
while (eldbus_message_iter_get_and_next(values, 'e', &entry))
553
const char *property;
554
Eldbus_Message_Iter *variant;
555
Eina_Value *struct_value;
556
Eina_Value *prop_value;
560
if (!eldbus_message_iter_arguments_get(entry, "sv", &property, &variant))
563
struct_value = eldbus_message_iter_struct_like_to_eina_value(variant);
564
if (!struct_value) goto on_error;
566
ret = eina_value_struct_value_get(struct_value, "arg0", &arg0);
567
eina_value_free(struct_value);
568
if (!ret) goto on_error;
570
tmp = eina_stringshare_add(property);
571
prop_value = eina_hash_find(pd->properties, tmp);
572
if (!prop_value) goto on_error;
574
ret = eina_value_copy(&arg0, prop_value);
575
if (!ret) goto on_error;
577
eina_value_flush(&arg0);
579
ret = eina_array_push(changed_properties, tmp);
580
if (!ret) goto on_error;
586
pd->is_loaded = EINA_TRUE;
587
return changed_properties;
590
eina_stringshare_del(tmp);
591
while ((tmp = eina_array_pop(changed_properties)))
592
eina_stringshare_del(tmp);
593
eina_array_free(changed_properties);
598
_eldbus_model_proxy_promise_clean(Eldbus_Property_Promise* p,
601
if (p->promise) eina_promise_reject(p->promise, err);
602
eina_stringshare_del(p->property);
607
_eldbus_model_proxy_property_get_all_cb(void *data,
608
const Eldbus_Message *msg,
609
Eldbus_Pending *pending)
611
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
612
Eldbus_Property_Promise* p;
613
Eina_Stringshare *sp;
614
Eina_Array *properties;
615
Efl_Model_Property_Event evt;
617
pd->pendings = eina_list_remove(pd->pendings, pending);
619
properties = _eldbus_model_proxy_property_get_all_load(msg, pd);
622
EINA_LIST_FREE(pd->promises, p)
623
_eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_NOT_FOUND);
627
EINA_LIST_FREE(pd->promises, p)
628
_eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_READ_ONLY);
630
_eldbus_model_proxy_start_monitor(pd);
632
evt.changed_properties = properties;
633
efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt);
634
while ((sp = eina_array_pop(properties)))
635
eina_stringshare_del(sp);
636
eina_array_free(properties);
641
_eldbus_model_proxy_property_set_load_cb(void *data,
642
const Eldbus_Message *msg,
643
Eldbus_Pending *pending)
645
Eldbus_Model_Proxy_Property_Set_Data *set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data;
646
Eldbus_Model_Proxy_Data *pd = set_data->pd;
647
Eina_Array *properties;
648
Eina_Stringshare *sp;
649
const char *signature;
651
pd->pendings = eina_list_remove(pd->pendings, pending);
653
signature = _eldbus_model_proxy_property_type_get(pd, set_data->property);
655
properties = _eldbus_model_proxy_property_get_all_load(msg, pd);
656
if (!signature || !properties)
658
eina_promise_reject(set_data->promise, EFL_MODEL_ERROR_UNKNOWN);
662
pending = eldbus_proxy_property_value_set(pd->proxy, set_data->property,
663
signature, set_data->value,
664
_eldbus_model_proxy_property_set_cb, set_data);
665
pd->pendings = eina_list_append(pd->pendings, pending);
668
if (!properties) return;
669
while ((sp = eina_array_pop(properties)))
670
eina_stringshare_del(sp);
671
eina_array_free(properties);
676
_eldbus_model_proxy_property_set_cb(void *data,
677
const Eldbus_Message *msg,
678
Eldbus_Pending *pending)
680
Eldbus_Model_Proxy_Property_Set_Data *sd = (Eldbus_Model_Proxy_Property_Set_Data *)data;
681
Eldbus_Model_Proxy_Data *pd = sd->pd;
682
const char *error_name, *error_text;
685
pd->pendings = eina_list_remove(pd->pendings, pending);
687
if (eldbus_message_error_get(msg, &error_name, &error_text))
689
ERR("%s: %s", error_name, error_text);
690
eina_promise_reject(sd->promise, EFL_MODEL_ERROR_UNKNOWN);
694
value = eina_hash_find(pd->properties, sd->property);
697
efl_model_properties_changed(pd->obj, sd->property);
699
eina_promise_resolve(sd->promise,
700
eina_value_reference_copy(value));
705
eina_promise_reject(sd->promise,
706
EFL_MODEL_ERROR_NOT_FOUND);
711
_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd,
712
const char *property)
714
Eldbus_Introspection_Property *property_introspection =
715
eldbus_introspection_property_find(pd->interface->properties, property);
717
if (property_introspection == NULL)
719
WRN("Property not found: %s", property);
723
return property_introspection->type;
726
#include "eldbus_model_proxy.eo.c"