From 3edb4ca6975946b7cfd3b261f5c1c7a46d681710 Mon Sep 17 00:00:00 2001 From: Cedric Bail Date: Wed, 25 Oct 2017 18:05:41 -0700 Subject: [PATCH] eldbus: migrate and refactor eldbus.model to new efl.model API. --- src/lib/eldbus/Eldbus.h | 1 + src/lib/eldbus/eldbus_model.c | 16 +- src/lib/eldbus/eldbus_model.eo | 1 + src/lib/eldbus/eldbus_model_arguments.c | 118 +-- src/lib/eldbus/eldbus_model_arguments.eo | 10 +- src/lib/eldbus/eldbus_model_connection.c | 363 ++------ src/lib/eldbus/eldbus_model_connection.eo | 45 +- .../eldbus/eldbus_model_connection_private.h | 18 +- src/lib/eldbus/eldbus_model_method.c | 32 +- src/lib/eldbus/eldbus_model_method.eo | 21 +- src/lib/eldbus/eldbus_model_method_private.h | 4 +- src/lib/eldbus/eldbus_model_object.c | 551 ++++-------- src/lib/eldbus/eldbus_model_object.eo | 64 +- src/lib/eldbus/eldbus_model_object_private.h | 22 +- src/lib/eldbus/eldbus_model_private.h | 31 +- src/lib/eldbus/eldbus_model_proxy.c | 825 ++++++++---------- src/lib/eldbus/eldbus_model_proxy.eo | 32 +- src/lib/eldbus/eldbus_model_proxy_private.h | 23 +- 18 files changed, 815 insertions(+), 1362 deletions(-) diff --git a/src/lib/eldbus/Eldbus.h b/src/lib/eldbus/Eldbus.h index 15f8293062..ac88fd51cf 100644 --- a/src/lib/eldbus/Eldbus.h +++ b/src/lib/eldbus/Eldbus.h @@ -225,6 +225,7 @@ typedef void (*Eldbus_Signal_Cb)(void *data, const Eldbus_Message *msg); #ifdef EFL_BETA_API_SUPPORT +#include "eldbus_model.eo.h" #include "eldbus_model_arguments.eo.h" #include "eldbus_model_connection.eo.h" #include "eldbus_model_method.eo.h" diff --git a/src/lib/eldbus/eldbus_model.c b/src/lib/eldbus/eldbus_model.c index e6d5dcce22..28faa0fb24 100644 --- a/src/lib/eldbus/eldbus_model.c +++ b/src/lib/eldbus/eldbus_model.c @@ -74,6 +74,15 @@ _eldbus_model_efl_object_finalize(Eo *obj, Eldbus_Model_Data *pd) return efl_finalize(efl_super(obj, ELDBUS_MODEL_CLASS)); } +static void +_eldbus_model_efl_object_invalidate(Eo *obj, Eldbus_Model_Data *pd) +{ + if (pd->connection) eldbus_connection_unref(pd->connection); + pd->connection = NULL; + + efl_invalidate(efl_super(obj, MY_CLASS)); +} + static void _eldbus_model_efl_object_destructor(Eo *obj, Eldbus_Model_Data *pd) { @@ -83,9 +92,6 @@ _eldbus_model_efl_object_destructor(Eo *obj, Eldbus_Model_Data *pd) eina_stringshare_del(pd->address); pd->address = NULL; - eldbus_connection_unref(pd->connection); - pd->connection = NULL; - efl_destructor(efl_super(obj, MY_CLASS)); } @@ -115,7 +121,7 @@ _eldbus_model_efl_model_property_set(Eo *obj, { Eina_Error err = EFL_MODEL_ERROR_READ_ONLY; - if (!strcmp(property, UNIQUE_NAME_PROPERTY)) + if (strcmp(property, UNIQUE_NAME_PROPERTY)) err = EFL_MODEL_ERROR_NOT_FOUND; return eina_future_rejected(efl_loop_future_scheduler_get(obj), err); } @@ -153,7 +159,7 @@ _eldbus_model_efl_model_properties_get(const Eo *obj EINA_UNUSED, Eina_Array *r; r = eina_array_new(1); - eina_array_push(r, UNIQUE_NAME_PROPERTY); + eina_array_push(r, eina_stringshare_add(UNIQUE_NAME_PROPERTY)); return r; } diff --git a/src/lib/eldbus/eldbus_model.eo b/src/lib/eldbus/eldbus_model.eo index 81b0ffee4a..e470144622 100644 --- a/src/lib/eldbus/eldbus_model.eo +++ b/src/lib/eldbus/eldbus_model.eo @@ -46,6 +46,7 @@ class Eldbus.Model (Efl.Object, Efl.Model) { } implements { Efl.Object.finalize; + Efl.Object.invalidate; Efl.Object.destructor; Efl.Model.property { get; set; } Efl.Model.properties { get; } diff --git a/src/lib/eldbus/eldbus_model_arguments.c b/src/lib/eldbus/eldbus_model_arguments.c index 834296df91..1d22903668 100644 --- a/src/lib/eldbus/eldbus_model_arguments.c +++ b/src/lib/eldbus/eldbus_model_arguments.c @@ -30,8 +30,6 @@ _eldbus_model_arguments_hash_free(Eina_Value *value) static Efl_Object* _eldbus_model_arguments_efl_object_constructor(Eo *obj, Eldbus_Model_Arguments_Data *pd) { - obj = efl_constructor(efl_super(obj, MY_CLASS)); - pd->obj = obj; pd->properties_array = NULL; pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_arguments_hash_free)); @@ -39,7 +37,19 @@ _eldbus_model_arguments_efl_object_constructor(Eo *obj, Eldbus_Model_Arguments_D pd->proxy = NULL; pd->arguments = NULL; pd->name = NULL; - return obj; + + return efl_constructor(efl_super(obj, MY_CLASS)); +} + +static Efl_Object * +_eldbus_model_arguments_efl_object_finalize(Eo *obj, Eldbus_Model_Arguments_Data *pd) +{ + if (!pd->proxy) return NULL; + if (!eldbus_model_connection_get(obj)) + eldbus_model_connection_set(obj, + eldbus_object_connection_get(eldbus_proxy_object_get(pd->proxy))); + + return efl_finalize(efl_super(obj, MY_CLASS)); } static void @@ -70,9 +80,9 @@ _eldbus_model_arguments_efl_object_destructor(Eo *obj, Eldbus_Model_Arguments_Da efl_destructor(efl_super(obj, MY_CLASS)); } -static Eina_Array const * +static Eina_Array * _eldbus_model_arguments_efl_model_properties_get(const Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd) + Eldbus_Model_Arguments_Data *pd) { EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL); @@ -113,98 +123,58 @@ _eldbus_model_arguments_properties_load(Eldbus_Model_Arguments_Data *pd) } } -static Efl_Future* -_eldbus_model_arguments_efl_model_property_set(Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd, - const char *property, - Eina_Value const* value) +static Eina_Future * +_eldbus_model_arguments_efl_model_property_set(Eo *obj, + Eldbus_Model_Arguments_Data *pd, + const char *property, Eina_Value *value) { Eina_Value *prop_value; - Eina_Value *promise_value; - Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future* future = efl_promise_future_get(promise); + Eina_Error err = 0; + Eina_Bool ret; - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(value, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); DBG("(%p): property=%s", obj, property); + err = EFL_MODEL_ERROR_NOT_FOUND; + if (!property || !value) goto on_error; + _eldbus_model_arguments_properties_load(pd); - Eina_Bool ret = _eldbus_model_arguments_is_input_argument(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_READ_ONLY, future); + err = EFL_MODEL_ERROR_READ_ONLY; + ret = _eldbus_model_arguments_is_input_argument(pd, property); + if (!ret) goto on_error; + err = EFL_MODEL_ERROR_NOT_FOUND; prop_value = eina_hash_find(pd->properties_hash, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(prop_value, promise, EFL_MODEL_ERROR_NOT_FOUND, future); + if (!prop_value) goto on_error; eina_value_flush(prop_value); eina_value_copy(value, prop_value); - promise_value = eina_value_new(eina_value_type_get(value)); - eina_value_copy(value, promise_value); - efl_promise_value_set(promise, promise_value, (Eina_Free_Cb)&eina_value_free); - return future; + return eina_future_resolved(efl_loop_future_scheduler_get(obj), + eina_value_reference_copy(value)); + + on_error: + return eina_future_rejected(efl_loop_future_scheduler_get(obj), err); } -static Efl_Future* -_eldbus_model_arguments_efl_model_property_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd, - const char *property) +static Eina_Value * +_eldbus_model_arguments_efl_model_property_get(const Eo *obj, Eldbus_Model_Arguments_Data *pd, const char *property) { - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - Eina_Value *promise_value; + Eina_Value *value; + Eina_Bool ret; - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); DBG("(%p): property=%s", obj, property); + if (!property) return eina_value_error_new(EFL_MODEL_ERROR_INCORRECT_VALUE); _eldbus_model_arguments_properties_load(pd); - Eina_Value* value = eina_hash_find(pd->properties_hash, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(value, promise, EFL_MODEL_ERROR_NOT_FOUND, future); + value = eina_hash_find(pd->properties_hash, property); + if (!value) return eina_value_error_new(EFL_MODEL_ERROR_NOT_FOUND); - Eina_Bool ret = _eldbus_model_arguments_is_output_argument(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_PERMISSION_DENIED, future); + ret = _eldbus_model_arguments_is_output_argument(pd, property); + if (!ret) return eina_value_error_new(EFL_MODEL_ERROR_PERMISSION_DENIED); - promise_value = eina_value_new(eina_value_type_get(value)); - eina_value_copy(value, promise_value); - efl_promise_value_set(promise, promise_value, (Eina_Free_Cb)&eina_value_free); - return future; -} - -static Eo * -_eldbus_model_arguments_efl_model_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Arguments_Data *pd EINA_UNUSED) -{ - return NULL; -} - -static void -_eldbus_model_arguments_efl_model_child_del(Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd EINA_UNUSED, - Eo *child EINA_UNUSED) -{ -} - -static Efl_Future* -_eldbus_model_arguments_efl_model_children_slice_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd EINA_UNUSED, - unsigned start EINA_UNUSED, - unsigned count EINA_UNUSED) -{ - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - efl_promise_failed_set(promise, EFL_MODEL_ERROR_NOT_SUPPORTED); - return efl_promise_future_get(promise); -} - -static Efl_Future* -_eldbus_model_arguments_efl_model_children_count_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Arguments_Data *pd EINA_UNUSED) -{ - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future* future = efl_promise_future_get(promise); - unsigned *count = malloc(sizeof(unsigned)); - *count = 0; - efl_promise_value_set(promise, count, free); - return future; + return eina_value_dup(value); } static const char * diff --git a/src/lib/eldbus/eldbus_model_arguments.eo b/src/lib/eldbus/eldbus_model_arguments.eo index 4dec2dc395..262d782eee 100644 --- a/src/lib/eldbus/eldbus_model_arguments.eo +++ b/src/lib/eldbus/eldbus_model_arguments.eo @@ -1,6 +1,6 @@ import eldbus_types; -class Eldbus.Model.Arguments (Efl.Object, Efl.Model) { +class Eldbus.Model.Arguments (Eldbus.Model) { [[Eldbus model arguments class]] methods { @@ -24,14 +24,10 @@ class Eldbus.Model.Arguments (Efl.Object, Efl.Model) { } implements { Efl.Object.constructor; + Efl.Object.finalize; Efl.Object.destructor; Efl.Model.properties { get; } - Efl.Model.property_set; - Efl.Model.property_get; - Efl.Model.child_add; - Efl.Model.child_del; - Efl.Model.children_slice_get; - Efl.Model.children_count_get; + Efl.Model.property { set; get; } } constructors { .custom_constructor; diff --git a/src/lib/eldbus/eldbus_model_connection.c b/src/lib/eldbus/eldbus_model_connection.c index 5fe0202e62..ef16f982a0 100644 --- a/src/lib/eldbus/eldbus_model_connection.c +++ b/src/lib/eldbus/eldbus_model_connection.c @@ -9,13 +9,7 @@ #define MY_CLASS ELDBUS_MODEL_CONNECTION_CLASS #define MY_CLASS_NAME "Eldbus_Model_Connection" -#define UNIQUE_NAME_PROPERTY "unique_name" - - static void _eldbus_model_connection_names_list_cb(void *, const Eldbus_Message *, Eldbus_Pending *); -static void _eldbus_model_connection_connect(Eldbus_Model_Connection_Data *); -static void _eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *); -static void _eldbus_model_connection_clear(Eldbus_Model_Connection_Data *); static Efl_Object* _eldbus_model_connection_efl_object_constructor(Eo *obj, Eldbus_Model_Connection_Data *pd) @@ -23,288 +17,101 @@ _eldbus_model_connection_efl_object_constructor(Eo *obj, Eldbus_Model_Connection obj = efl_constructor(efl_super(obj, MY_CLASS)); pd->obj = obj; - pd->is_listed = EINA_FALSE; - pd->connection = NULL; - pd->properties_array = NULL; - pd->children_list = NULL; - pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN; - pd->address = NULL; - pd->private = false; - pd->unique_name = NULL; - pd->pending_list = NULL; return obj; } -static void -_eldbus_model_connection_custom_constructor(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd, - Eldbus_Connection_Type type, - const char* address, - Eina_Bool private) -{ - pd->type = type; - pd->address = eina_stringshare_add(address); - pd->private = private; -} - static void _eldbus_model_connection_efl_object_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd) { - eina_stringshare_del(pd->address); - - _eldbus_model_connection_clear(pd); - - efl_destructor(efl_super(obj, MY_CLASS)); -} - -static Eina_Array const * -_eldbus_model_connection_efl_model_properties_get(const Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, NULL); - - if (pd->properties_array == NULL) - { - Eina_Bool ret; - - pd->properties_array = eina_array_new(1); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, NULL); - - ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY); - EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, NULL); - } - - return pd->properties_array; -} - - -static Efl_Future* -_eldbus_model_connection_efl_model_property_set(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd EINA_UNUSED, - const char *property, - Eina_Value const* value EINA_UNUSED) -{ - Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future* future = efl_promise_future_get(promise); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET((strcmp(property, UNIQUE_NAME_PROPERTY) == 0), promise, - EFL_MODEL_ERROR_NOT_FOUND, future); - efl_promise_failed_set(promise, EFL_MODEL_ERROR_READ_ONLY); - return future; -} - -static Efl_Future* -_eldbus_model_connection_efl_model_property_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd, - const char *property) -{ - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - - DBG("(%p): property=%s", obj, property); - - if (!pd->connection) - _eldbus_model_connection_connect(pd); - - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET((strcmp(property, UNIQUE_NAME_PROPERTY) == 0), promise, - EFL_MODEL_ERROR_NOT_FOUND, future); - - if (pd->unique_name == NULL) - { - const char *unique_name; - - unique_name = eldbus_connection_unique_name_get(pd->connection); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(unique_name, promise, EFL_MODEL_ERROR_NOT_FOUND, future); - pd->unique_name = strdup(unique_name); - } - - Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_STRING); - eina_value_set(v, pd->unique_name); - efl_promise_value_set(promise, v, (Eina_Free_Cb)&eina_value_free); - return future; -} - -static Eo * -_eldbus_model_connection_efl_model_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd EINA_UNUSED) -{ - return NULL; -} - -static void -_eldbus_model_connection_efl_model_child_del(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd EINA_UNUSED, - Eo *child EINA_UNUSED) -{ -} - -static Efl_Promise* -_eldbus_model_connection_efl_model_children_slice_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd, - unsigned int start, - unsigned int count) -{ - Efl_Promise *promise; - Efl_Future *future; - _Eldbus_Children_Slice_Promise* data; - Eldbus_Pending *pending; - - promise = efl_add(EFL_PROMISE_CLASS, obj); - future = efl_promise_future_get(promise); - - if (!pd->connection) - _eldbus_model_connection_connect(pd); - - if (pd->is_listed) - { - Eina_Accessor *ac = efl_model_list_slice(pd->children_list, start, count); - efl_promise_value_set(promise, ac, (Eina_Free_Cb)&eina_accessor_free); - return future; - } - - data = calloc(1, sizeof(struct _Eldbus_Children_Slice_Promise)); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, future); - data->promise = promise; - data->start = start; - data->count = count; - - pd->children_promises = eina_list_prepend(pd->children_promises, data); - - if (pd->pending_list == NULL) - { - pending = eldbus_names_list(pd->connection, &_eldbus_model_connection_names_list_cb, pd); - pd->pending_list = eina_list_append(pd->pending_list, pending); - } - return future; -} - -static Efl_Future* -_eldbus_model_connection_efl_model_children_count_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Connection_Data *pd) -{ - Efl_Promise *promise; - Eldbus_Pending *pending; - - promise = efl_add(EFL_PROMISE_CLASS, obj); - if (!pd->connection) - _eldbus_model_connection_connect(pd); - - if (pd->is_listed) - { - unsigned int *c = calloc(sizeof(unsigned int), 1); - *c = eina_list_count(pd->children_list); - efl_promise_value_set(promise, c, free); - return efl_promise_future_get(promise); - } - - pd->count_promises = eina_list_prepend(pd->count_promises, promise); - if (pd->pending_list == NULL) - { - pending = eldbus_names_list(pd->connection, &_eldbus_model_connection_names_list_cb, pd); - pd->pending_list = eina_list_append(pd->pending_list, pending); - } - return efl_promise_future_get(promise); -} - -static const char * -_eldbus_model_connection_address_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd) -{ - return pd->address; -} - -static Eina_Bool -_eldbus_model_connection_private_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd) -{ - return pd->private; -} - -static Eldbus_Connection_Type -_eldbus_model_connection_type_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Connection_Data *pd) -{ - return pd->type; -} - -static void -_eldbus_model_connection_connect(Eldbus_Model_Connection_Data *pd) -{ - EINA_SAFETY_ON_NULL_RETURN(pd); - - if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type) - { - if (pd->private) - pd->connection = eldbus_address_connection_get(pd->address); - else - pd->connection = eldbus_private_address_connection_get(pd->address); - } - else - { - if (pd->private) - pd->connection = eldbus_private_connection_get(pd->type); - else - pd->connection = eldbus_connection_get(pd->type); - } - - // TODO: Register for disconnection event - - EINA_SAFETY_ON_FALSE_RETURN(pd->connection != NULL); -} - -static void -_eldbus_model_connection_disconnect(Eldbus_Model_Connection_Data *pd) -{ - EINA_SAFETY_ON_NULL_RETURN(pd); - eldbus_connection_unref(pd->connection); - pd->connection = NULL; -} - -static void -_eldbus_model_connection_clear(Eldbus_Model_Connection_Data *pd) -{ - Eldbus_Pending *pending; + Eldbus_Children_Slice_Promise *slice; Eo *child; - EINA_SAFETY_ON_NULL_RETURN(pd); + if (pd->pending) eldbus_pending_cancel(pd->pending); - if (!pd->connection) - return; - - free(pd->unique_name); - pd->unique_name = NULL; - - EINA_LIST_FREE(pd->children_list, child) + EINA_LIST_FREE(pd->childrens, child) efl_del(child); - EINA_LIST_FREE(pd->pending_list, pending) - eldbus_pending_cancel(pending); - - if (pd->properties_array) + EINA_LIST_FREE(pd->requests, slice) { - eina_array_free(pd->properties_array); - pd->properties_array = NULL; + eina_promise_reject(slice->p, EFL_MODEL_ERROR_UNKNOWN); + free(slice); } - _eldbus_model_connection_disconnect(pd); + efl_destructor(efl_super(obj, ELDBUS_MODEL_CONNECTION_CLASS)); +} + +static void +_eldbus_model_children_list(const Eo *obj, Eldbus_Model_Connection_Data *pd) +{ + Eldbus_Model_Data *sd; + + if (pd->pending || pd->is_listed) return ; + + sd = efl_data_scope_get(obj, ELDBUS_MODEL_CLASS); + + pd->pending = eldbus_names_list(sd->connection, + &_eldbus_model_connection_names_list_cb, + pd); +} + +static Eina_Future * +_eldbus_model_connection_efl_model_children_slice_get(Eo *obj, + Eldbus_Model_Connection_Data *pd, + unsigned int start, + unsigned int count) +{ + Eldbus_Children_Slice_Promise* slice; + Eina_Promise *p; + + if (pd->is_listed) + { + Eina_Value v; + + v = efl_model_list_value_get(pd->childrens, start, count); + return eina_future_resolved(efl_loop_future_scheduler_get(obj), v); + } + + p = eina_promise_new(efl_loop_future_scheduler_get(obj), + _eldbus_eina_promise_cancel, NULL); + + slice = calloc(1, sizeof (Eldbus_Children_Slice_Promise)); + slice->p = p; + slice->start = start; + slice->count = count; + + pd->requests = eina_list_prepend(pd->requests, slice); + + _eldbus_model_children_list(obj, pd); + return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));; +} + +static unsigned int +_eldbus_model_connection_efl_model_children_count_get(const Eo *obj, + Eldbus_Model_Connection_Data *pd) +{ + _eldbus_model_children_list(obj, pd); + return eina_list_count(pd->childrens); } static void _eldbus_model_connection_names_list_cb(void *data, const Eldbus_Message *msg, - Eldbus_Pending *pending) + Eldbus_Pending *pending EINA_UNUSED) { - Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*)data; - _Eldbus_Children_Slice_Promise * p; + Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*) data; + Eldbus_Model_Data *sd; + Eldbus_Children_Slice_Promise *slice; const char *error_name, *error_text; Eldbus_Message_Iter *array = NULL; const char *bus; unsigned int count; - Eina_List* i; - pd->pending_list = eina_list_remove(pd->pending_list, pending); + pd->pending = NULL; if (eldbus_message_error_get(msg, &error_name, &error_text)) { ERR("%s: %s", error_name, error_text); - //efl_model_error_notify(pd->obj); return; } @@ -314,39 +121,37 @@ _eldbus_model_connection_names_list_cb(void *data, return; } + sd = efl_data_scope_get(pd->obj, ELDBUS_MODEL_CLASS); + while (eldbus_message_iter_get_and_next(array, 's', &bus)) { + Eo *child; + DBG("(%p): bus = %s", pd->obj, bus); - Eo *child = efl_add(ELDBUS_MODEL_OBJECT_CLASS, pd->obj, eldbus_model_object_connection_constructor(efl_added, pd->connection, bus, "/")); + child = efl_add(ELDBUS_MODEL_OBJECT_CLASS, pd->obj, + eldbus_model_connection_set(efl_added, sd->connection), + eldbus_model_object_bus_set(efl_added, bus), + eldbus_model_object_path_set(efl_added, "/")); - pd->children_list = eina_list_append(pd->children_list, child); + pd->childrens = eina_list_append(pd->childrens, child); } - count = eina_list_count(pd->children_list); - - if (count) - efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &count); - pd->is_listed = EINA_TRUE; - EINA_LIST_FOREACH(pd->children_promises, i, p) - { - Eina_Accessor *ac = efl_model_list_slice(pd->children_list, p->start, p->count); - efl_promise_value_set(p->promise, ac, (Eina_Free_Cb)&eina_accessor_free); - free(p); - } - eina_list_free(pd->children_promises); + count = eina_list_count(pd->childrens); + efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &count); - Efl_Promise *ep; - EINA_LIST_FOREACH(pd->count_promises, i, ep) + EINA_LIST_FREE(pd->requests, slice) { - unsigned *c = calloc(sizeof(unsigned), 1); - *c = eina_list_count(pd->children_list); - efl_promise_value_set(ep, c, free); + Eina_Value v; + + v = efl_model_list_value_get(pd->childrens, + slice->start, slice->count); + eina_promise_resolve(slice->p, v); + + free(slice); } - eina_list_free(pd->count_promises); } - #include "eldbus_model_connection.eo.c" diff --git a/src/lib/eldbus/eldbus_model_connection.eo b/src/lib/eldbus/eldbus_model_connection.eo index b1f9a1daa9..5d13cd965e 100644 --- a/src/lib/eldbus/eldbus_model_connection.eo +++ b/src/lib/eldbus/eldbus_model_connection.eo @@ -1,53 +1,12 @@ import eldbus_types; -class Eldbus.Model.Connection (Efl.Object, Efl.Model) { +class Eldbus.Model.Connection (Eldbus.Model) { [[Eldbus model connection class]] - methods { - custom_constructor { - [[Custom Eldbus_Model_Connection constructor. - - @since 1.16]] - params { - @in type: Eldbus.Connection.Type; [[The connection type]] - @in address: string; [[Remote address of DBus]] - @in private_: bool; [[Non shared dbus connection]] - } - } - @property type { - [[Connection type]] - get { } - values { - type: Eldbus.Connection.Type; [[Connection type]] - } - } - @property address { - [[Remote DBus address]] - get { } - values { - address: string; [[Address]] - } - } - @property private { - [[Indicate if the DBus connection is shared or private]] - get { } - values { - private_: bool; [[Private DBus connection]] - } - } - } implements { Efl.Object.constructor; Efl.Object.destructor; - Efl.Model.properties { get; } - Efl.Model.property_set; - Efl.Model.property_get; - Efl.Model.child_add; - Efl.Model.child_del; Efl.Model.children_slice_get; - Efl.Model.children_count_get; - } - constructors { - .custom_constructor; + Efl.Model.children_count { get; } } } diff --git a/src/lib/eldbus/eldbus_model_connection_private.h b/src/lib/eldbus/eldbus_model_connection_private.h index a1636b94be..829ddd9142 100644 --- a/src/lib/eldbus/eldbus_model_connection_private.h +++ b/src/lib/eldbus/eldbus_model_connection_private.h @@ -13,18 +13,20 @@ typedef struct _Eldbus_Model_Connection_Data Eldbus_Model_Connection_Data; struct _Eldbus_Model_Connection_Data { Eo *obj; - Eina_Bool is_listed : 1; + Eldbus_Connection *connection; - Eina_Array *properties_array; - Eina_List *children_list; - Eina_List *children_promises; - Eina_List *count_promises; + Eldbus_Pending *pending; Eldbus_Connection_Type type; + + Eina_List *childrens; + Eina_List *requests; + Eina_Stringshare *address; - bool private; char *unique_name; - Eina_List *pending_list; + + bool private; + + Eina_Bool is_listed : 1; }; #endif - diff --git a/src/lib/eldbus/eldbus_model_method.c b/src/lib/eldbus/eldbus_model_method.c index caafddda16..8e7e87bf27 100644 --- a/src/lib/eldbus/eldbus_model_method.c +++ b/src/lib/eldbus/eldbus_model_method.c @@ -26,17 +26,33 @@ _eldbus_model_method_efl_object_constructor(Eo *obj, Eldbus_Model_Method_Data *p return obj; } -static void -_eldbus_model_method_method_constructor(Eo *obj EINA_UNUSED, - Eldbus_Model_Method_Data *pd, - Eldbus_Proxy *proxy, - const Eldbus_Introspection_Method *method) +static Efl_Object* +_eldbus_model_method_efl_object_finalize(Eo *obj, Eldbus_Model_Method_Data *pd) { - EINA_SAFETY_ON_NULL_RETURN(proxy); - EINA_SAFETY_ON_NULL_RETURN(method); + if (!pd->proxy || + !pd->method) + return NULL; - eldbus_model_arguments_custom_constructor(efl_super(obj, MY_CLASS), proxy, method->name, method->arguments); + eldbus_model_arguments_custom_constructor(obj, + pd->proxy, + pd->method->name, pd->method->arguments); + return obj; +} + +static void +_eldbus_model_method_proxy_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Method_Data *pd, + Eldbus_Proxy *proxy) +{ + pd->proxy = proxy; +} + +static void +_eldbus_model_method_method_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Method_Data *pd, + const Eldbus_Introspection_Method *method) +{ pd->method = method; } diff --git a/src/lib/eldbus/eldbus_model_method.eo b/src/lib/eldbus/eldbus_model_method.eo index 015ebc72da..ef5ab1001a 100644 --- a/src/lib/eldbus/eldbus_model_method.eo +++ b/src/lib/eldbus/eldbus_model_method.eo @@ -3,13 +3,20 @@ import eldbus_types; class Eldbus.Model.Method (Eldbus.Model.Arguments) { [[Eldbus model method class]] methods { - method_constructor { + @property proxy { [[Custom Eldbus_Model_Method constructor. - @since 1.16]] - params { - @in proxy: ptr(Eldbus.Proxy); [[Eldbus proxy]] - @cref method: Eldbus.Introspection.Method; [[The introspected method]] + @since 1.21]] + set {} + values { + proxy: ptr(Eldbus.Proxy); [[Eldbus proxy]] + } + } + @property method { + [[Object]] + set {} + values { + @cref method: Eldbus.Introspection.Method; [[The introspected interface]] } } call { @@ -24,9 +31,11 @@ class Eldbus.Model.Method (Eldbus.Model.Arguments) { } implements { Efl.Object.constructor; + Efl.Object.finalize; } constructors { - .method_constructor; + .proxy; + .method; } events { successful,call; [[Event dispatched for a successful method call.]] diff --git a/src/lib/eldbus/eldbus_model_method_private.h b/src/lib/eldbus/eldbus_model_method_private.h index 5092b50b53..d3813f6b77 100644 --- a/src/lib/eldbus/eldbus_model_method_private.h +++ b/src/lib/eldbus/eldbus_model_method_private.h @@ -11,8 +11,10 @@ typedef struct _Eldbus_Model_Method_Data Eldbus_Model_Method_Data; struct _Eldbus_Model_Method_Data { Eo *obj; + const Eldbus_Introspection_Method *method; + + Eldbus_Proxy *proxy; }; #endif - diff --git a/src/lib/eldbus/eldbus_model_object.c b/src/lib/eldbus/eldbus_model_object.c index 04af7cf563..5bb9269463 100644 --- a/src/lib/eldbus/eldbus_model_object.c +++ b/src/lib/eldbus/eldbus_model_object.c @@ -11,15 +11,7 @@ #define MY_CLASS ELDBUS_MODEL_OBJECT_CLASS #define MY_CLASS_NAME "Eldbus_Model_Object" -#define UNIQUE_NAME_PROPERTY "unique_name" - -static bool _eldbus_model_object_introspect(Eldbus_Model_Object_Data *, const char *, const char *); static void _eldbus_model_object_introspect_cb(void *, const Eldbus_Message *, Eldbus_Pending *); -static void _eldbus_model_object_connect(Eldbus_Model_Object_Data *); -static void _eldbus_model_object_disconnect(Eldbus_Model_Object_Data *); -static void _eldbus_model_object_clear(Eldbus_Model_Object_Data *); -static void _eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *, const char *, Eina_List *); -static char *_eldbus_model_object_concatenate_path(const char *, const char *); static void _eldbus_model_object_create_children(Eldbus_Model_Object_Data *, Eldbus_Object *, Eina_List *); static Efl_Object* @@ -28,219 +20,135 @@ _eldbus_model_object_efl_object_constructor(Eo *obj, Eldbus_Model_Object_Data *p obj = efl_constructor(efl_super(obj, MY_CLASS)); pd->obj = obj; - pd->is_listed = EINA_FALSE; - pd->connection = NULL; - pd->object_list = NULL; - pd->properties_array = NULL; - pd->children_list = NULL; - pd->type = ELDBUS_CONNECTION_TYPE_UNKNOWN; - pd->address = NULL; - pd->private = false; - pd->bus = NULL; - pd->path = NULL; - pd->unique_name = NULL; - pd->pending_list = NULL; - pd->introspection = NULL; return obj; } static void -_eldbus_model_object_custom_constructor(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd, - Eldbus_Connection_Type type, - const char* address, - Eina_Bool private, - const char* bus, - const char* path) +_eldbus_model_object_bus_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Object_Data *pd, + const char *bus) { - EINA_SAFETY_ON_NULL_RETURN(bus); - EINA_SAFETY_ON_NULL_RETURN(path); - - pd->type = type; - pd->address = eina_stringshare_add(address); - pd->private = private; pd->bus = eina_stringshare_add(bus); - pd->path = eina_stringshare_add(path); } static void -_eldbus_model_object_connection_constructor(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd, - Eldbus_Connection *connection, - const char* bus, - const char* path) +_eldbus_model_object_path_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Object_Data *pd, + const char *path) { - EINA_SAFETY_ON_NULL_RETURN(connection); - EINA_SAFETY_ON_NULL_RETURN(bus); - EINA_SAFETY_ON_NULL_RETURN(path); - - pd->connection = eldbus_connection_ref(connection); - pd->bus = eina_stringshare_add(bus); pd->path = eina_stringshare_add(path); } +static Efl_Object* +_eldbus_model_object_efl_object_finalize(Eo *obj, Eldbus_Model_Object_Data *pd) +{ + if (!pd->bus || !pd->path) + return NULL; + + return efl_finalize(efl_super(obj, MY_CLASS)); +} + +static void +_eldbus_model_object_efl_object_invalidate(Eo *obj, Eldbus_Model_Object_Data *pd) +{ + Eldbus_Pending *pending; + Eldbus_Object *object; + Eo *child; + + EINA_LIST_FREE(pd->childrens, child) + efl_unref(child); + + EINA_LIST_FREE(pd->pendings, pending) + eldbus_pending_cancel(pending); + + EINA_LIST_FREE(pd->objects, object) + eldbus_object_unref(object); + + if (pd->introspection) + { + eldbus_introspection_node_free(pd->introspection); + pd->introspection = NULL; + } + + efl_invalidate(efl_super(obj, MY_CLASS)); +} + static void _eldbus_model_object_efl_object_destructor(Eo *obj, Eldbus_Model_Object_Data *pd) { - eina_stringshare_del(pd->address); eina_stringshare_del(pd->bus); eina_stringshare_del(pd->path); - _eldbus_model_object_clear(pd); - efl_destructor(efl_super(obj, MY_CLASS)); } -static Eina_Array const * -_eldbus_model_object_efl_model_properties_get(const Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->obj, NULL); - - if (pd->properties_array == NULL) - { - Eina_Bool ret; - - pd->properties_array = eina_array_new(1); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, NULL); - - ret = eina_array_push(pd->properties_array, UNIQUE_NAME_PROPERTY); - EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, NULL); - } - - return pd->properties_array; -} - -static Efl_Future* -_eldbus_model_object_efl_model_property_set(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd EINA_UNUSED, - const char *property, - const Eina_Value *value EINA_UNUSED) -{ - Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET((strcmp(property, UNIQUE_NAME_PROPERTY) == 0), promise, - EFL_MODEL_ERROR_NOT_FOUND, efl_promise_future_get(promise)); - efl_promise_failed_set(promise, EFL_MODEL_ERROR_READ_ONLY); - return efl_promise_future_get(promise); -} - -static Efl_Future* -_eldbus_model_object_efl_model_property_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd, - const char *property) -{ - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); - DBG("(%p): property=%s", obj, property); - - if (!pd->connection) - _eldbus_model_object_connect(pd); - - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET((strcmp(property, UNIQUE_NAME_PROPERTY) == 0), promise, - EFL_MODEL_ERROR_NOT_FOUND, future); - - if (pd->unique_name == NULL) - { - const char *unique_name; - - unique_name = eldbus_connection_unique_name_get(pd->connection); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(unique_name, promise, EFL_MODEL_ERROR_NOT_FOUND, future); - pd->unique_name = strdup(unique_name); - } - - Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_STRING); - eina_value_set(v, pd->unique_name); - efl_promise_value_set(promise, v, (Eina_Free_Cb)&eina_value_free); - return future; -} - -static Eo * -_eldbus_model_object_efl_model_child_add(Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd EINA_UNUSED) -{ - return NULL; -} - -static void -_eldbus_model_object_efl_model_child_del(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd EINA_UNUSED, - Eo *child EINA_UNUSED) -{ -} - -static Efl_Future* -_eldbus_model_object_efl_model_children_slice_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd, - unsigned start, - unsigned count) -{ - _Eldbus_Children_Slice_Promise* p; - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - - if (!pd->connection) - _eldbus_model_object_connect(pd); - - if (pd->is_listed) - { - Eina_Accessor* ac = efl_model_list_slice(pd->children_list, start, count); - efl_promise_value_set(promise, ac, (Eina_Free_Cb)&eina_accessor_free); - return future; - } - - p = calloc(1, sizeof(struct _Eldbus_Children_Slice_Promise)); - EINA_SAFETY_ON_NULL_RETURN_VAL(p, future); - p->promise = promise; - p->start = start; - p->count = count; - - pd->children_promises = eina_list_prepend(pd->children_promises, p); - if (pd->pending_list == NULL) - _eldbus_model_object_introspect(pd, pd->bus, pd->path); - return future; -} - -static Efl_Future* -_eldbus_model_object_efl_model_children_count_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Object_Data *pd) -{ - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - if (!pd->connection) - _eldbus_model_object_connect(pd); - - if (pd->is_listed) - { - unsigned int *c = calloc(sizeof(unsigned int), 1); - *c = eina_list_count(pd->children_list); - efl_promise_value_set(promise, c, free); - return efl_promise_future_get(promise); - } - - pd->count_promises = eina_list_prepend(pd->count_promises, promise); - if (pd->pending_list == NULL) - _eldbus_model_object_introspect(pd, pd->bus, pd->path); - return efl_promise_future_get(promise); -} - -static const char * -_eldbus_model_object_address_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd) -{ - return pd->address; -} - static Eina_Bool -_eldbus_model_object_private_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd) +_eldbus_model_object_introspect(const Eo *obj, + Eldbus_Model_Object_Data *pd, + const char *bus, + const char *path) { - return pd->private; + Eldbus_Pending *pending; + Eldbus_Object *object; + + DBG("(%p) Introspecting: bus = %s, path = %s", pd->obj, bus, path); + + object = eldbus_object_get(eldbus_model_connection_get(obj), + bus, path); + if (!object) + { + ERR("(%p): Cannot get object: bus=%s, path=%s", pd->obj, bus, path); + return EINA_FALSE; + } + pd->objects = eina_list_append(pd->objects, object); + + // TODO: Register for interface added/removed event + pending = eldbus_object_introspect(object, &_eldbus_model_object_introspect_cb, pd); + eldbus_pending_data_set(pending, "object", object); + pd->pendings = eina_list_append(pd->pendings, pending); + return EINA_TRUE; } -static Eldbus_Connection_Type -_eldbus_model_object_type_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd) +static Eina_Future * +_eldbus_model_object_efl_model_children_slice_get(Eo *obj EINA_UNUSED, + Eldbus_Model_Object_Data *pd, + unsigned start, + unsigned count) { - return pd->type; + Eldbus_Children_Slice_Promise *slice; + Eina_Promise *p; + + if (pd->is_listed) + { + Eina_Value v; + + v = efl_model_list_value_get(pd->childrens, start, count); + return eina_future_resolved(efl_loop_future_scheduler_get(obj), v); + } + + p = eina_promise_new(efl_loop_future_scheduler_get(obj), + _eldbus_eina_promise_cancel, NULL); + + slice = calloc(1, sizeof(struct _Eldbus_Children_Slice_Promise)); + slice->p = p; + slice->start = start; + slice->count = count; + + pd->requests = eina_list_prepend(pd->requests, slice); + + if (!pd->pendings) + _eldbus_model_object_introspect(obj, pd, pd->bus, pd->path); + return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));; +} + +static unsigned int +_eldbus_model_object_efl_model_children_count_get(const Eo *obj EINA_UNUSED, + Eldbus_Model_Object_Data *pd) +{ + if (!pd->is_listed && !pd->pendings) + _eldbus_model_object_introspect(obj, pd, pd->bus, pd->path); + return eina_list_count(pd->childrens); } static const char * @@ -255,105 +163,71 @@ _eldbus_model_object_path_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Dat return pd->path; } -static void -_eldbus_model_object_connect(Eldbus_Model_Object_Data *pd) +static char * +_eldbus_model_object_concatenate_path(const char *root_path, + const char *relative_path) { - EINA_SAFETY_ON_NULL_RETURN(pd); + Eina_Strbuf *buffer; + const char *format = (strcmp(root_path, "/") != 0) ? "%s/%s" : "%s%s"; + char *absolute_path = NULL; - if (ELDBUS_CONNECTION_TYPE_ADDRESS == pd->type) - { - if (pd->private) - pd->connection = eldbus_address_connection_get(pd->address); - else - pd->connection = eldbus_private_address_connection_get(pd->address); - } - else - { - if (pd->private) - pd->connection = eldbus_private_connection_get(pd->type); - else - pd->connection = eldbus_connection_get(pd->type); - } + buffer = eina_strbuf_new(); + eina_strbuf_append_printf(buffer, format, root_path, relative_path); + absolute_path = eina_strbuf_string_steal(buffer); - // TODO: Register for disconnection event - - EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection); + eina_strbuf_free(buffer); + return absolute_path; } static void -_eldbus_model_object_disconnect(Eldbus_Model_Object_Data *pd) +_eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *pd, + const char *current_path, + Eina_List *nodes) { - EINA_SAFETY_ON_NULL_RETURN(pd); - eldbus_connection_unref(pd->connection); - pd->connection = NULL; + Eldbus_Introspection_Node *node; + Eina_List *it; + + EINA_LIST_FOREACH(nodes, it, node) + { + const char *relative_path; + char *absolute_path; + + relative_path = node->name; + if (!relative_path) continue; + + absolute_path = _eldbus_model_object_concatenate_path(current_path, relative_path); + if (!absolute_path) continue; + + _eldbus_model_object_introspect(pd->obj, pd, pd->bus, absolute_path); + + free(absolute_path); + } } static void -_eldbus_model_object_clear(Eldbus_Model_Object_Data *pd) +_eldbus_model_object_create_children(Eldbus_Model_Object_Data *pd, Eldbus_Object *object, Eina_List *interfaces) { - Eldbus_Pending *pending; - Eldbus_Object *object; - Eo *child; + Eldbus_Introspection_Interface *interface; + const char *current_path; + Eina_List *l; - EINA_SAFETY_ON_NULL_RETURN(pd); - if (!pd->connection) - return; + current_path = eldbus_object_path_get(object); + if (!current_path) return ; - free(pd->unique_name); - pd->unique_name = NULL; - - EINA_LIST_FREE(pd->children_list, child) - efl_unref(child); - - EINA_LIST_FREE(pd->pending_list, pending) - eldbus_pending_cancel(pending); - - if (pd->properties_array) + EINA_LIST_FOREACH(interfaces, l, interface) { - eina_array_free(pd->properties_array); - pd->properties_array = NULL; + Eo *child; + + DBG("(%p) Creating child: bus = %s, path = %s, interface = %s", + pd->obj, pd->bus, current_path, interface->name); + + // TODO: increment reference to keep 'interface' in memory + child = efl_add_ref(ELDBUS_MODEL_PROXY_CLASS, pd->obj, + eldbus_model_proxy_object_set(efl_added, object), + eldbus_model_proxy_interface_set(efl_added, interface)); + + if (child) pd->childrens = eina_list_append(pd->childrens, child); } - - EINA_LIST_FREE(pd->object_list, object) - eldbus_object_unref(object); - - if (pd->introspection) - { - eldbus_introspection_node_free(pd->introspection); - pd->introspection = NULL; - } - - _eldbus_model_object_disconnect(pd); -} - - -static bool -_eldbus_model_object_introspect(Eldbus_Model_Object_Data *pd, - const char *bus, - const char *path) -{ - Eldbus_Object *object; - Eldbus_Pending *pending; - - EINA_SAFETY_ON_NULL_RETURN_VAL(bus, false); - EINA_SAFETY_ON_NULL_RETURN_VAL(path, false); - - DBG("(%p) Introspecting: bus = %s, path = %s", pd->obj, bus, path); - - object = eldbus_object_get(pd->connection, bus, path); - if (!object) - { - ERR("(%p): Cannot get object: bus=%s, path=%s", pd->obj, bus, path); - return false; - } - pd->object_list = eina_list_append(pd->object_list, object); - - // TODO: Register for interface added/removed event - - pending = eldbus_object_introspect(object, &_eldbus_model_object_introspect_cb, pd); - eldbus_pending_data_set(pending, "object", object); - pd->pending_list = eina_list_append(pd->pending_list, pending); - return true; } static void @@ -362,12 +236,15 @@ _eldbus_model_object_introspect_cb(void *data, Eldbus_Pending *pending) { Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data; + Eldbus_Children_Slice_Promise* slice; Eldbus_Object *object; - const char *error_name, *error_text; + const char *error_name; + const char *error_text; const char *xml = NULL; const char *current_path; + unsigned int count; - pd->pending_list = eina_list_remove(pd->pending_list, pending); + pd->pendings = eina_list_remove(pd->pendings, pending); object = eldbus_pending_data_get(pending, "object"); if (eldbus_message_error_get(msg, &error_name, &error_text)) @@ -382,114 +259,36 @@ _eldbus_model_object_introspect_cb(void *data, ERR("Error getting arguments."); return; } - EINA_SAFETY_ON_NULL_RETURN(xml); + + if (!xml) + { + ERR("No XML."); + return ; + } current_path = eldbus_object_path_get(object); - EINA_SAFETY_ON_NULL_RETURN(current_path); + pd->introspection = eldbus_introspection_parse(xml); DBG("(%p): introspect of bus = %s, path = %s =>\n%s", pd->obj, pd->bus, current_path, xml); - pd->introspection = eldbus_introspection_parse(xml); - EINA_SAFETY_ON_NULL_RETURN(pd->introspection); - _eldbus_model_object_introspect_nodes(pd, current_path, pd->introspection->nodes); _eldbus_model_object_create_children(pd, object, pd->introspection->interfaces); - if (eina_list_count(pd->pending_list) == 0) + if (eina_list_count(pd->pendings) != 0) return ; + + count = eina_list_count(pd->childrens); + efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &count); + + pd->is_listed = EINA_TRUE; + + EINA_LIST_FREE(pd->requests, slice) { - Eina_List* i; + Eina_Value v; - pd->is_listed = EINA_TRUE; - _Eldbus_Children_Slice_Promise* p; - EINA_LIST_FOREACH(pd->children_promises, i, p) - { - Eina_Accessor* ac = efl_model_list_slice(pd->children_list, p->start, p->count); - efl_promise_value_set(p->promise, ac, (Eina_Free_Cb)&eina_accessor_free); - free(p); - } - pd->children_promises = eina_list_free(pd->children_promises); + v = efl_model_list_value_get(pd->childrens, slice->start, slice->count); + eina_promise_resolve(slice->p, v); - Efl_Promise *ep; - EINA_LIST_FOREACH(pd->count_promises, i, ep) - { - unsigned *c = calloc(sizeof(unsigned), 1); - *c = eina_list_count(pd->children_list); - efl_promise_value_set(ep, c, free); - } - pd->count_promises = eina_list_free(pd->count_promises); - - } -} - -static void -_eldbus_model_object_introspect_nodes(Eldbus_Model_Object_Data *pd, const char *current_path, Eina_List *nodes) -{ - Eina_List *it; - Eldbus_Introspection_Node *node; - - EINA_SAFETY_ON_NULL_RETURN(pd); - EINA_SAFETY_ON_NULL_RETURN(current_path); - - EINA_LIST_FOREACH(nodes, it, node) - { - const char *relative_path; - char *absolute_path; - - relative_path = node->name; - if (!relative_path) continue; - - absolute_path = _eldbus_model_object_concatenate_path(current_path, relative_path); - if (!absolute_path) continue; - - _eldbus_model_object_introspect(pd, pd->bus, absolute_path); - - free(absolute_path); - } -} - -static char * -_eldbus_model_object_concatenate_path(const char *root_path, const char *relative_path) -{ - Eina_Strbuf *buffer; - char *absolute_path = NULL; - Eina_Bool ret; - - buffer = eina_strbuf_new(); - EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL); - - ret = eina_strbuf_append(buffer, root_path); - if (strcmp(root_path, "/") != 0) - ret = ret && eina_strbuf_append_char(buffer, '/'); - ret = ret && eina_strbuf_append(buffer, relative_path); - EINA_SAFETY_ON_FALSE_GOTO(ret, free_buffer); - - absolute_path = eina_strbuf_string_steal(buffer); - -free_buffer: - eina_strbuf_free(buffer); - return absolute_path; -} - -static void -_eldbus_model_object_create_children(Eldbus_Model_Object_Data *pd, Eldbus_Object *object, Eina_List *interfaces) -{ - Eldbus_Introspection_Interface *interface; - Eina_List *it; - const char *current_path; - - current_path = eldbus_object_path_get(object); - EINA_SAFETY_ON_NULL_RETURN(current_path); - - EINA_LIST_FOREACH(interfaces, it, interface) - { - Eo *child; - - DBG("(%p) Creating child: bus = %s, path = %s, interface = %s", pd->obj, pd->bus, current_path, interface->name); - - // TODO: increment reference to keep 'interface' in memory - child = efl_add_ref(ELDBUS_MODEL_PROXY_CLASS, pd->obj, eldbus_model_proxy_custom_constructor(efl_added, object, interface)); - - pd->children_list = eina_list_append(pd->children_list, child); + free(slice); } } diff --git a/src/lib/eldbus/eldbus_model_object.eo b/src/lib/eldbus/eldbus_model_object.eo index 6123d3aca0..806af546a3 100644 --- a/src/lib/eldbus/eldbus_model_object.eo +++ b/src/lib/eldbus/eldbus_model_object.eo @@ -1,63 +1,22 @@ import eldbus_types; -class Eldbus.Model.Object (Efl.Object, Efl.Model) { +class Eldbus.Model.Object (Eldbus.Model) { [[Eldbus model object class]] data: Eldbus_Model_Object_Data; methods { - custom_constructor { - [[Custom Eldbus_Model_Object constructor. - - @since 1.16]] - params { - @in type: Eldbus.Connection.Type; [[The connection type]] - @in address: string; [[Remote address of DBus]] - @in private_: bool; [[Non shared DBus connection]] - @in bus: string; [[DBus Name or unique-id]] - @in path: string; [[DBus path]] - } - } - connection_constructor { - [[Custom Eldbus_Model_Object connection_constructor. - - @since 1.16]] - params { - @in connection: ptr(Eldbus.Connection); [[Eldbus connection]] - @in bus: string; [[DBus Name or unique-id]] - @in path: string; [[DBus path]] - } - } - @property type { - [[Connection type]] - get { } - values { - type: Eldbus.Connection.Type; [[Connection type]] - } - } - @property address { - [[Remote address of DBus]] - get { } - values { - address: string; [[Address]] - } - } - @property private { - [[Indicate if the DBus connection is shared or private]] - get { } - values { - private_: bool; [[Private DBus connection]] - } - } - @property bus { + @property bus { [[DBus Name or unique-id]] get { } + set { } values { bus: string; [[DBus name]] } } - @property path { + @property path { [[DBus path]] get { } + set { } values { path: string; [[DBus path]] } @@ -65,17 +24,10 @@ class Eldbus.Model.Object (Efl.Object, Efl.Model) { } implements { Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.invalidate; Efl.Object.destructor; - Efl.Model.properties { get; } - Efl.Model.property_set; - Efl.Model.property_get; - Efl.Model.child_add; - Efl.Model.child_del; Efl.Model.children_slice_get; - Efl.Model.children_count_get; - } - constructors { - .custom_constructor; - .connection_constructor; + Efl.Model.children_count { get; } } } diff --git a/src/lib/eldbus/eldbus_model_object_private.h b/src/lib/eldbus/eldbus_model_object_private.h index 4330a2ffb9..6ea2877b37 100644 --- a/src/lib/eldbus/eldbus_model_object_private.h +++ b/src/lib/eldbus/eldbus_model_object_private.h @@ -12,22 +12,18 @@ typedef struct _Eldbus_Model_Object_Data Eldbus_Model_Object_Data; struct _Eldbus_Model_Object_Data { Eo *obj; - Eina_Bool is_listed : 1; - Eldbus_Connection *connection; - Eina_List *object_list; - Eina_Array *properties_array; - Eina_List *children_list; - Eina_List *children_promises; - Eina_List *count_promises; - Eldbus_Connection_Type type; - Eina_Stringshare *address; - bool private; + + Eina_List *objects; + Eina_List *childrens; + Eina_List *requests; + Eina_List *pendings; + Eina_Stringshare *bus; Eina_Stringshare *path; - char *unique_name; - Eina_List *pending_list; + Eldbus_Introspection_Node *introspection; + + Eina_Bool is_listed : 1; }; #endif - diff --git a/src/lib/eldbus/eldbus_model_private.h b/src/lib/eldbus/eldbus_model_private.h index b5f36104e5..5b155a19eb 100644 --- a/src/lib/eldbus/eldbus_model_private.h +++ b/src/lib/eldbus/eldbus_model_private.h @@ -8,19 +8,28 @@ #include #include -typedef struct _Eldbus_Children_Slice_Promise _Eldbus_Children_Slice_Promise; +typedef struct _Eldbus_Children_Slice_Promise Eldbus_Children_Slice_Promise; +typedef struct _Eldbus_Model_Data Eldbus_Model_Data; + struct _Eldbus_Children_Slice_Promise { - unsigned start; - unsigned count; - Efl_Promise* promise; + Eina_Promise *p; + + unsigned int start; + unsigned int count; }; -typedef struct _Eldbus_Property_Promise _Eldbus_Property_Promise; -struct _Eldbus_Property_Promise +struct _Eldbus_Model_Data { - char *property; - Efl_Promise* promise; + Eldbus_Connection *connection; + Eldbus_Connection_Type type; + + Eina_Stringshare *address; + Eina_Stringshare *unique_name; + + Eina_Bool private : 1; + + Eina_Bool is_listed : 1; }; #define UNIQUE_NAME_PROPERTY "unique_name" @@ -28,6 +37,12 @@ struct _Eldbus_Property_Promise /* logging support */ extern int eldbus_model_log_dom; +static inline void +_eldbus_eina_promise_cancel(void *data EINA_UNUSED, + const Eina_Promise *dead_ptr EINA_UNUSED) +{ +} + #define ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(exp, promise, err, v) \ do \ { \ diff --git a/src/lib/eldbus/eldbus_model_proxy.c b/src/lib/eldbus/eldbus_model_proxy.c index 586dfbbb96..229bcc0480 100644 --- a/src/lib/eldbus/eldbus_model_proxy.c +++ b/src/lib/eldbus/eldbus_model_proxy.c @@ -10,61 +10,88 @@ #define MY_CLASS ELDBUS_MODEL_PROXY_CLASS #define MY_CLASS_NAME "Eldbus_Model_Proxy" -static Eina_Bool _eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *); -static void _eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *); static void _eldbus_model_proxy_property_get_all_cb(void *, const Eldbus_Message *, Eldbus_Pending *); static void _eldbus_model_proxy_property_set_cb(void *, const Eldbus_Message *, Eldbus_Pending *); static void _eldbus_model_proxy_property_set_load_cb(void *, const Eldbus_Message *, Eldbus_Pending *); static void _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *); -static void _eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *); static void _eldbus_model_proxy_property_changed_cb(void *, Eldbus_Proxy *, void *); static void _eldbus_model_proxy_property_invalidated_cb(void *, Eldbus_Proxy *, void *); -static bool _eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *, const char *); -static bool _eldbus_model_proxy_has_property(Eldbus_Model_Proxy_Data *, const char *); -static bool _eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *, const char *); static const char *_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *, const char *); static void _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *); static void _eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *); typedef struct _Eldbus_Model_Proxy_Property_Set_Data Eldbus_Model_Proxy_Property_Set_Data; +typedef struct _Eldbus_Property_Promise Eldbus_Property_Promise; struct _Eldbus_Model_Proxy_Property_Set_Data { Eldbus_Model_Proxy_Data *pd; + Eina_Stringshare *property; - Eina_Value value; - Efl_Promise *promise; + Eina_Promise *promise; + Eina_Value *value; +}; + +struct _Eldbus_Property_Promise +{ + Eina_Promise *promise; + Eina_Stringshare *property; }; -static Eldbus_Model_Proxy_Property_Set_Data * _eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *, const char *, const Eina_Value *, Efl_Promise *promise); static void _eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *); -static void -_eldbus_model_proxy_hash_free(Eina_Value *value) +static Eina_Bool +_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd) { - eina_value_free(value); + Eldbus_Introspection_Property *property; + Eina_List *it; + + if (pd->proxy) + return EINA_TRUE; + + pd->proxy = eldbus_proxy_get(pd->object, pd->name); + EINA_SAFETY_ON_NULL_RETURN_VAL(pd->proxy, EINA_FALSE); + + EINA_LIST_FOREACH(pd->interface->properties, it, property) + { + const Eina_Value_Type *type; + Eina_Stringshare *name; + Eina_Value *value; + + type = _dbus_type_to_eina_value_type(property->type[0]); + name = eina_stringshare_add(property->name); + value = eina_value_new(type); + + eina_hash_direct_add(pd->properties, name, value); + } + + return EINA_TRUE; } -static Efl_Object* -_eldbus_model_proxy_efl_object_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd) +static void +_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd) { - obj = efl_constructor(efl_super(obj, MY_CLASS)); + Eldbus_Pending *pending; - pd->obj = obj; - pd->object = NULL; + EINA_LIST_FREE(pd->pendings, pending) + eldbus_pending_cancel(pending); + + if (pd->monitoring) + { + eldbus_proxy_event_callback_del(pd->proxy, + ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, + _eldbus_model_proxy_property_changed_cb, + pd); + eldbus_proxy_event_callback_del(pd->proxy, + ELDBUS_PROXY_EVENT_PROPERTY_REMOVED, + _eldbus_model_proxy_property_invalidated_cb, + pd); + } + pd->monitoring = EINA_FALSE; + + if (pd->proxy) eldbus_proxy_unref(pd->proxy); pd->proxy = NULL; - pd->is_listed = pd->is_loaded = EINA_FALSE; - pd->properties_array = NULL; - pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_proxy_hash_free)); - pd->children_list = NULL; - pd->name = NULL; - pd->pending_list = NULL; - pd->promise_list = NULL; - pd->monitoring = false; - pd->interface = NULL; - - return obj; } static void @@ -75,218 +102,310 @@ _eldbus_model_proxy_object_del(void *data, Eldbus_Object *object EINA_UNUSED, vo pd->object = NULL; } -static void -_eldbus_model_proxy_custom_constructor(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd, - Eldbus_Object *object, - const Eldbus_Introspection_Interface *interface) +static Efl_Object* +_eldbus_model_proxy_efl_object_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd) { - EINA_SAFETY_ON_NULL_RETURN(object); - EINA_SAFETY_ON_NULL_RETURN(interface); + obj = efl_constructor(efl_super(obj, MY_CLASS)); + pd->obj = obj; + pd->properties = eina_hash_stringshared_new(NULL); + + return obj; +} + +static Efl_Object* +_eldbus_model_proxy_efl_object_finalize(Eo *obj, Eldbus_Model_Proxy_Data *pd) +{ + if (!pd->object || + !pd->name || + !pd->interface) + return NULL; + + if (!_eldbus_model_proxy_load(pd)) return NULL; + + if (!eldbus_model_connection_get(obj)) + eldbus_model_connection_set(obj, eldbus_object_connection_get(pd->object)); + + eldbus_object_event_callback_add(pd->object, ELDBUS_OBJECT_EVENT_DEL, _eldbus_model_proxy_object_del, pd); + + return efl_finalize(efl_super(obj, MY_CLASS)); +} + +static void +_eldbus_model_proxy_object_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Proxy_Data *pd, + Eldbus_Object *object) +{ pd->object = eldbus_object_ref(object); - eldbus_object_event_callback_add(object, ELDBUS_OBJECT_EVENT_DEL, _eldbus_model_proxy_object_del, pd); +} + +static void +_eldbus_model_proxy_interface_set(Eo *obj EINA_UNUSED, + Eldbus_Model_Proxy_Data *pd, + const Eldbus_Introspection_Interface *interface) +{ pd->name = eina_stringshare_add(interface->name); pd->interface = interface; } static void -_eldbus_model_proxy_efl_object_destructor(Eo *obj, Eldbus_Model_Proxy_Data *pd) +_eldbus_model_proxy_efl_object_invalidate(Eo *obj, Eldbus_Model_Proxy_Data *pd) { + Eo *child; + + EINA_LIST_FREE(pd->childrens, child) + efl_unref(child); + _eldbus_model_proxy_unload(pd); - eina_hash_free(pd->properties_hash); - - eina_stringshare_del(pd->name); if (pd->object) { eldbus_object_event_callback_del(pd->object, ELDBUS_OBJECT_EVENT_DEL, _eldbus_model_proxy_object_del, pd); eldbus_object_unref(pd->object); } + efl_invalidate(efl_super(obj, MY_CLASS)); +} + +static void +_eldbus_model_proxy_efl_object_destructor(Eo *obj, Eldbus_Model_Proxy_Data *pd) +{ + Eina_Hash_Tuple *tuple; + Eina_Iterator *it; + + it = eina_hash_iterator_tuple_new(pd->properties); + EINA_ITERATOR_FOREACH(it, tuple) + { + Eina_Stringshare *property = tuple->key; + Eina_Value *value = tuple->data; + + eina_stringshare_del(property); + eina_value_free(value); + } + eina_iterator_free(it); + eina_hash_free(pd->properties); + + eina_stringshare_del(pd->name); + efl_destructor(efl_super(obj, MY_CLASS)); } -static Eina_Array const * +static Eina_Array * _eldbus_model_proxy_efl_model_properties_get(const Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd) + Eldbus_Model_Proxy_Data *pd) { - Eina_Bool ret; + Eina_Iterator *it; + Eina_Array *r; + Eina_Stringshare *property; - EINA_SAFETY_ON_NULL_RETURN_VAL(pd, NULL); + r = eina_array_new(4); - ret = _eldbus_model_proxy_load(pd); - if (!ret) return NULL; + it = eina_hash_iterator_key_new(pd->properties); + EINA_ITERATOR_FOREACH(it, property) + eina_array_push(r, property); + eina_iterator_free(it); - return pd->properties_array; + return r; } -static Efl_Future* +#define PROPERTY_EXIST 1 +#define PROPERTY_READ 2 +#define PROPERTY_WRITE 4 + +static unsigned char +eldbus_model_proxy_property_check(Eldbus_Model_Proxy_Data *pd, + const char *property) +{ + Eldbus_Introspection_Property *property_introspection = + eldbus_introspection_property_find(pd->interface->properties, property); + unsigned char r = 0; + + if (property_introspection == NULL) + { + WRN("Property not found: %s", property); + return 0; + } + + r = PROPERTY_EXIST; + // Check read access + if (property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ || + property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE) + r |= PROPERTY_READ; + // Check write access + if (property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE || + property_introspection->access == ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE) + r |= PROPERTY_WRITE; + + return r; +} + +static void +_eldbus_model_proxy_cancel_cb(void *data, + const Eina_Promise *dead_promise EINA_UNUSED) +{ + Eldbus_Model_Proxy_Property_Set_Data *sd = data; + + sd->promise = NULL; +} + +static Eldbus_Pending * +_eldbus_model_proxy_load_all(Eldbus_Model_Proxy_Data *pd, + Eina_Promise *promise, const char *property, + Eldbus_Message_Cb callback, + void *data) +{ + Eldbus_Property_Promise *p; + Eldbus_Pending *pending = NULL; + + p = calloc(1, sizeof(Eldbus_Property_Promise)); + if (!p) + { + if (promise) eina_promise_reject(promise, ENOMEM); + return NULL; + } + + p->promise = promise; + p->property = eina_stringshare_add(property); + pd->promises = eina_list_append(pd->promises, p); + + if (!pd->pendings) + { + pending = eldbus_proxy_property_get_all(pd->proxy, callback, data); + } + return pending; +} + +static Eina_Future * _eldbus_model_proxy_efl_model_property_set(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd, - const char *property, - Eina_Value const* value) + Eldbus_Model_Proxy_Data *pd, + const char *property, + Eina_Value *value) { Eldbus_Model_Proxy_Property_Set_Data *data; const char *signature; Eldbus_Pending *pending; - Eina_Bool ret; - Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future* future = efl_promise_future_get(promise); - - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); + unsigned char access; + Eina_Error err = 0; DBG("(%p): property=%s", obj, property); - ret = _eldbus_model_proxy_load(pd); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_INIT_FAILED, future); - ret = _eldbus_model_proxy_has_property(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_NOT_FOUND, future); - - ret = _eldbus_model_proxy_is_property_writeable(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_READ_ONLY, future); + access = eldbus_model_proxy_property_check(pd, property); + err = EFL_MODEL_ERROR_NOT_FOUND; + if (!access) goto on_error; + err = EFL_MODEL_ERROR_READ_ONLY; + if (!(access & PROPERTY_WRITE)) goto on_error; + err = EFL_MODEL_ERROR_UNKNOWN; signature = _eldbus_model_proxy_property_type_get(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(signature, promise, EFL_MODEL_ERROR_UNKNOWN, future); + if (!signature) goto on_error; - data = _eldbus_model_proxy_property_set_data_new(pd, property, value, promise); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(data, promise, EFL_MODEL_ERROR_UNKNOWN, future); + err = ENOMEM; + data = calloc(1, sizeof (Eldbus_Model_Proxy_Property_Set_Data)); + if (!data) goto on_error; + + data->pd = pd; + data->promise = eina_promise_new(efl_loop_future_scheduler_get(obj), + _eldbus_model_proxy_cancel_cb, data); + data->property = eina_stringshare_add(property); + if (!(data->value = eina_value_dup(value))) goto on_error; if (!pd->is_loaded) { - _Eldbus_Property_Promise *p = calloc(1, sizeof(_Eldbus_Property_Promise)); - EINA_SAFETY_ON_NULL_RETURN_VAL(p, future); - - p->promise = promise; - p->property = strdup(property); - pd->promise_list = eina_list_append(pd->promise_list, p); - - if (!pd->pending_list) - { - pending = eldbus_proxy_property_get_all(pd->proxy, _eldbus_model_proxy_property_set_load_cb, data); - pd->pending_list = eina_list_append(pd->pending_list, pending); - } - return future; + pending = _eldbus_model_proxy_load_all(pd, data->promise, property, + _eldbus_model_proxy_property_set_load_cb, data); } - - pending = eldbus_proxy_property_value_set - (pd->proxy, property, signature, (Eina_Value*)value, _eldbus_model_proxy_property_set_cb, data); - pd->pending_list = eina_list_append(pd->pending_list, pending); - return future; -} - -static Efl_Future* -_eldbus_model_proxy_efl_model_property_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd, - const char *property) -{ - Eina_Bool ret; - Eina_Value *promise_value; - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future); - - ret = _eldbus_model_proxy_load(pd); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_INIT_FAILED, future); - - ret = _eldbus_model_proxy_has_property(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_NOT_FOUND, future); - - if (!pd->is_loaded) + else { - Eldbus_Pending *pending; - _Eldbus_Property_Promise *p = calloc(1, sizeof(_Eldbus_Property_Promise)); - EINA_SAFETY_ON_NULL_RETURN_VAL(p, future); - - p->promise = promise; - p->property = strdup(property); - pd->promise_list = eina_list_append(pd->promise_list, p); - - if (!pd->pending_list) - { - pending = eldbus_proxy_property_get_all(pd->proxy, _eldbus_model_proxy_property_get_all_cb, pd); - pd->pending_list = eina_list_append(pd->pending_list, pending); - } - return future; + pending = eldbus_proxy_property_value_set(pd->proxy, property, signature, (Eina_Value*)value, + _eldbus_model_proxy_property_set_cb, data); } - Eina_Value* value = eina_hash_find(pd->properties_hash, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(value, promise, EFL_MODEL_ERROR_NOT_FOUND, future); + if (pending) pd->pendings = eina_list_append(pd->pendings, pending); + return efl_future_Eina_FutureXXX_then(obj, eina_future_new(data->promise)); - ret = _eldbus_model_proxy_is_property_writeable(pd, property); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_READ_ONLY, future); - - promise_value = eina_value_new(eina_value_type_get(value)); - eina_value_copy(value, promise_value); - efl_promise_value_set(promise, promise_value, (Eina_Free_Cb)&eina_value_free); - return future; + on_error: + return eina_future_rejected(efl_loop_future_scheduler_get(obj), err); } -static Eo * -_eldbus_model_proxy_efl_model_child_add(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd EINA_UNUSED) +static Eina_Value * +_eldbus_model_proxy_efl_model_property_get(const Eo *obj EINA_UNUSED, + Eldbus_Model_Proxy_Data *pd, + const char *property) { - return NULL; + Eldbus_Pending *pending; + unsigned char access; + Eina_Error err = 0; + + access = eldbus_model_proxy_property_check(pd, property); + err = EFL_MODEL_ERROR_NOT_FOUND; + if (!access) goto on_error; + if (!(access & PROPERTY_READ)) goto on_error; + + if (pd->is_loaded) + { + Eina_Stringshare *tmp; + Eina_Value *value; + + err = EFL_MODEL_ERROR_NOT_FOUND; + tmp = eina_stringshare_add(property); + value = eina_hash_find(pd->properties, tmp); + eina_stringshare_del(tmp); + if (!value) goto on_error; + + return eina_value_dup(value); + } + + err = ENOMEM; + + pending = _eldbus_model_proxy_load_all(pd, NULL, property, + _eldbus_model_proxy_property_get_all_cb, pd); + if (pending) pd->pendings = eina_list_append(pd->pendings, pending); + else goto on_error; + + return eina_value_error_new(EAGAIN); + + on_error: + return eina_value_error_new(err); } static void -_eldbus_model_proxy_efl_model_child_del(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd EINA_UNUSED, - Eo *child EINA_UNUSED) +_eldbus_model_proxy_listed(Eldbus_Model_Proxy_Data *pd) { + if (!pd->is_listed) + { + _eldbus_model_proxy_create_methods_children(pd); + _eldbus_model_proxy_create_signals_children(pd); + pd->is_listed = EINA_TRUE; + } } -static Efl_Future* +static Eina_Future* _eldbus_model_proxy_efl_model_children_slice_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd, - unsigned start, - unsigned count) + Eldbus_Model_Proxy_Data *pd, + unsigned start, + unsigned count) { - Eina_Bool ret = _eldbus_model_proxy_load(pd); - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_INIT_FAILED, future); + Eina_Value v; - if (!pd->is_listed) - { - _eldbus_model_proxy_create_methods_children(pd); - _eldbus_model_proxy_create_signals_children(pd); - pd->is_listed = EINA_TRUE; - } + _eldbus_model_proxy_listed(pd); - Eina_Accessor *ac = efl_model_list_slice(pd->children_list, start, count); - efl_promise_value_set(promise, ac, (Eina_Free_Cb)&eina_accessor_free); - return future; + v = efl_model_list_value_get(pd->childrens, start, count); + return eina_future_resolved(efl_loop_future_scheduler_get(obj), v); } -static Efl_Future* -_eldbus_model_proxy_efl_model_children_count_get(Eo *obj EINA_UNUSED, - Eldbus_Model_Proxy_Data *pd) +static unsigned int +_eldbus_model_proxy_efl_model_children_count_get(const Eo *obj EINA_UNUSED, + Eldbus_Model_Proxy_Data *pd) { - Eina_Bool ret = _eldbus_model_proxy_load(pd); - Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); - Efl_Future *future = efl_promise_future_get(promise); - ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_INIT_FAILED, future); - - if (!pd->is_listed) - { - _eldbus_model_proxy_create_methods_children(pd); - _eldbus_model_proxy_create_signals_children(pd); - pd->is_listed = EINA_TRUE; - } - - unsigned int *c = calloc(sizeof(unsigned int), 1); - *c = eina_list_count(pd->children_list); - efl_promise_value_set(promise, c, free); - return future; + _eldbus_model_proxy_listed(pd); + return eina_list_count(pd->childrens); } static void _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd) { - Eina_List *it; Eldbus_Introspection_Method *method; + Eina_List *it; EINA_LIST_FOREACH(pd->interface->methods, it, method) { @@ -311,9 +430,13 @@ _eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd) INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s", pd->obj, bus, path, interface_name, method_name); - child = efl_add(ELDBUS_MODEL_METHOD_CLASS, pd->obj, eldbus_model_method_constructor(efl_added, pd->proxy, method)); + child = efl_add_ref(ELDBUS_MODEL_METHOD_CLASS, pd->obj, + eldbus_model_method_proxy_set(efl_added, pd->proxy), + eldbus_model_method_set(efl_added, method)); - pd->children_list = eina_list_append(pd->children_list, child); + if (child) pd->childrens = eina_list_append(pd->childrens, child); + else ERR("Could not create method child: bus = %s, path = %s method = %s::%s.", + bus, path, interface_name, method_name); } } @@ -346,9 +469,11 @@ _eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd) DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s", pd->obj, bus, path, interface_name, signal_name); - child = efl_add(ELDBUS_MODEL_SIGNAL_CLASS, pd->obj, eldbus_model_signal_constructor(efl_added, pd->proxy, signal)); + child = efl_add_ref(ELDBUS_MODEL_SIGNAL_CLASS, pd->obj, eldbus_model_signal_constructor(efl_added, pd->proxy, signal)); - pd->children_list = eina_list_append(pd->children_list, child); + if (child) pd->childrens = eina_list_append(pd->childrens, child); + else ERR("Could not create signal child: bus = %s, path = %s signal = %s::%s.", + bus, path, interface_name, signal_name); } } @@ -358,90 +483,13 @@ _eldbus_model_proxy_proxy_name_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Proxy return pd->name; } -static Eina_Bool -_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd) -{ - Eldbus_Introspection_Property *property; - Eina_List *it; - - EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_FALSE); - - if (pd->proxy) - return EINA_TRUE; - - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->object, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->name, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->interface, EINA_FALSE); - - pd->proxy = eldbus_proxy_get(pd->object, pd->name); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->proxy, EINA_FALSE); - - const unsigned int properties_count = eina_list_count(pd->interface->properties); - - pd->properties_array = eina_array_new(properties_count); - EINA_SAFETY_ON_NULL_RETURN_VAL(pd->properties_array, EINA_FALSE); - - if (!properties_count) return EINA_TRUE; - - EINA_LIST_FOREACH(pd->interface->properties, it, property) - { - Eina_Stringshare *name; - Eina_Bool ret; - - name = eina_stringshare_add(property->name); - ret = eina_array_push(pd->properties_array, name); - EINA_SAFETY_ON_FALSE_RETURN_VAL(ret, EINA_FALSE); - } - - return EINA_TRUE; -} - -static void -_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd) -{ - Eldbus_Pending *pending; - Eo *child; - - EINA_SAFETY_ON_NULL_RETURN(pd); - - EINA_LIST_FREE(pd->children_list, child) - efl_unref(child); - - EINA_LIST_FREE(pd->pending_list, pending) - { - eldbus_pending_cancel(pending); - } - - if (pd->properties_array) - { - unsigned int i; - Eina_Stringshare *property; - Eina_Array_Iterator it; - - EINA_ARRAY_ITER_NEXT(pd->properties_array, i, property, it) - eina_stringshare_del(property); - eina_array_free(pd->properties_array); - pd->properties_array = NULL; - } - - eina_hash_free_buckets(pd->properties_hash); - - _eldbus_model_proxy_stop_monitor(pd); - - if (pd->proxy) - { - eldbus_proxy_unref(pd->proxy); - pd->proxy = NULL; - } -} - static void _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd) { if (pd->monitoring) return; - pd->monitoring = true; + pd->monitoring = EINA_TRUE; eldbus_proxy_event_callback_add(pd->proxy, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, @@ -454,25 +502,6 @@ _eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd) pd); } -static void -_eldbus_model_proxy_stop_monitor(Eldbus_Model_Proxy_Data *pd) -{ - if (!pd->monitoring) - return; - - pd->monitoring = false; - - eldbus_proxy_event_callback_del(pd->proxy, - ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, - _eldbus_model_proxy_property_changed_cb, - pd); - - eldbus_proxy_event_callback_del(pd->proxy, - ELDBUS_PROXY_EVENT_PROPERTY_REMOVED, - _eldbus_model_proxy_property_invalidated_cb, - pd); -} - static void _eldbus_model_proxy_property_changed_cb(void *data, Eldbus_Proxy *proxy EINA_UNUSED, @@ -483,13 +512,13 @@ _eldbus_model_proxy_property_changed_cb(void *data, Eina_Value *prop_value; Eina_Bool ret; - prop_value = eina_hash_find(pd->properties_hash, event->name); + prop_value = eina_hash_find(pd->properties, event->name); if (!prop_value) return ; ret = eina_value_copy(event->value, prop_value); if (!ret) return ; - efl_model_property_changed_notify(pd->obj, event->name); + efl_model_properties_changed(pd->obj, event->name); } static void @@ -506,11 +535,9 @@ _eldbus_model_proxy_property_invalidated_cb(void *data, static Eina_Array * _eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Model_Proxy_Data *pd) { - Eldbus_Introspection_Property *prop; Eldbus_Message_Iter *values = NULL; Eldbus_Message_Iter *entry; Eina_Array *changed_properties; - Eina_List *it; const char *error_name, *error_text; if (eldbus_message_error_get(msg, &error_name, &error_text)) @@ -525,20 +552,10 @@ _eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Mode return NULL; } - EINA_LIST_FOREACH(pd->interface->properties, it, prop) - { - const Eina_Value_Type *type; - Eina_Value *value; - - type = _dbus_type_to_eina_value_type(prop->type[0]); - value = eina_value_new(type); - - eina_hash_add(pd->properties_hash, prop->name, value); - } - changed_properties = eina_array_new(1); while (eldbus_message_iter_get_and_next(values, 'e', &entry)) { + Eina_Stringshare *tmp; const char *property; Eldbus_Message_Iter *variant; Eina_Value *struct_value; @@ -550,22 +567,24 @@ _eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Mode continue; struct_value = eldbus_message_iter_struct_like_to_eina_value(variant); - EINA_SAFETY_ON_NULL_GOTO(struct_value, on_error); + if (!struct_value) goto on_error; ret = eina_value_struct_value_get(struct_value, "arg0", &arg0); eina_value_free(struct_value); - EINA_SAFETY_ON_FALSE_GOTO(ret, on_error); + if (!ret) goto on_error; - prop_value = eina_hash_find(pd->properties_hash, property); - EINA_SAFETY_ON_NULL_GOTO(prop_value, on_error); + tmp = eina_stringshare_add(property); + prop_value = eina_hash_find(pd->properties, tmp); + eina_stringshare_del(tmp); + if (!prop_value) goto on_error; ret = eina_value_copy(&arg0, prop_value); - EINA_SAFETY_ON_FALSE_GOTO(ret, on_error); + if (!ret) goto on_error; eina_value_flush(&arg0); ret = eina_array_push(changed_properties, property); - EINA_SAFETY_ON_FALSE_GOTO(ret, on_error); + if (!ret) goto on_error; } pd->is_loaded = EINA_TRUE; @@ -576,98 +595,74 @@ _eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Mode return NULL; } +static void +_eldbus_model_proxy_promise_clean(Eldbus_Property_Promise* p, + Eina_Error err) +{ + if (p->promise) eina_promise_reject(p->promise, err); + eina_stringshare_del(p->property); + free(p); +} + static void _eldbus_model_proxy_property_get_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) { - Eina_Value *promise_value; Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data; + Eldbus_Property_Promise* p; + Eina_Array *properties; + Efl_Model_Property_Event evt; - pd->pending_list = eina_list_remove(pd->pending_list, pending); - Eina_Array *changed_properties = _eldbus_model_proxy_property_get_all_load(msg, pd); - if (changed_properties == NULL) + pd->pendings = eina_list_remove(pd->pendings, pending); + + properties = _eldbus_model_proxy_property_get_all_load(msg, pd); + if (!properties) { - Eina_List* i; - _Eldbus_Property_Promise* p; - EINA_LIST_FOREACH(pd->promise_list, i, p) - { - efl_promise_failed_set(p->promise, EFL_MODEL_ERROR_NOT_FOUND); - free(p->property); - } - eina_list_free(pd->promise_list); - return; + EINA_LIST_FREE(pd->promises, p) + _eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_NOT_FOUND); + return ; } - Eina_List* i; - _Eldbus_Property_Promise* p; - EINA_LIST_FOREACH(pd->promise_list, i, p) - { - Eina_Value* value = eina_hash_find(pd->properties_hash, p->property); - if (!value) - { - efl_promise_failed_set(p->promise, EFL_MODEL_ERROR_NOT_FOUND); - free(p->property); - continue; - } - - if (!_eldbus_model_proxy_is_property_readable(pd, p->property)) - { - efl_promise_failed_set(p->promise, EFL_MODEL_ERROR_READ_ONLY); - free(p->property); - continue; - } - - free(p->property); - - promise_value = eina_value_new(eina_value_type_get(value)); - eina_value_copy(value, promise_value); - efl_promise_value_set(p->promise, promise_value, (Eina_Free_Cb)&eina_value_free); - } - eina_list_free(pd->promise_list); - + EINA_LIST_FREE(pd->promises, p) + _eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_READ_ONLY); _eldbus_model_proxy_start_monitor(pd); - if (eina_array_count(changed_properties)) - { - Efl_Model_Property_Event evt = { - .changed_properties = changed_properties - }; - - efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt); - } - - eina_array_free(changed_properties); + evt.changed_properties = properties; + efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt); + eina_array_free(properties); } static void _eldbus_model_proxy_property_set_load_cb(void *data, - const Eldbus_Message *msg, - Eldbus_Pending *pending) + const Eldbus_Message *msg, + Eldbus_Pending *pending) { Eldbus_Model_Proxy_Property_Set_Data *set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data; Eldbus_Model_Proxy_Data *pd = set_data->pd; + Eina_Array *properties; const char *signature; - pd->pending_list = eina_list_remove(pd->pending_list, pending); + pd->pendings = eina_list_remove(pd->pendings, pending); + signature = _eldbus_model_proxy_property_type_get(pd, set_data->property); - Eina_Array *changed_properties = _eldbus_model_proxy_property_get_all_load(msg, pd); - if (signature == NULL || changed_properties == NULL) + properties = _eldbus_model_proxy_property_get_all_load(msg, pd); + if (!signature || !properties) { - efl_promise_failed_set(set_data->promise, EFL_MODEL_ERROR_UNKNOWN); - - eina_array_free(changed_properties); - _eldbus_model_proxy_property_set_data_free(set_data); + eina_promise_reject(set_data->promise, EFL_MODEL_ERROR_UNKNOWN); + eina_array_free(properties); + _eldbus_model_proxy_property_set_data_free(set_data); return; } - eina_array_free(changed_properties); - pending = eldbus_proxy_property_value_set - (pd->proxy, set_data->property, signature, &set_data->value, _eldbus_model_proxy_property_set_cb, set_data); - pd->pending_list = eina_list_append(pd->pending_list, pending); + eina_array_free(properties); + pending = eldbus_proxy_property_value_set(pd->proxy, set_data->property, + signature, set_data->value, + _eldbus_model_proxy_property_set_cb, set_data); + pd->pendings = eina_list_append(pd->pendings, pending); } @@ -676,95 +671,42 @@ _eldbus_model_proxy_property_set_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending) { - Eldbus_Model_Proxy_Property_Set_Data *property_set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data; - Eldbus_Model_Proxy_Data *pd = property_set_data->pd; + Eldbus_Model_Proxy_Property_Set_Data *sd = (Eldbus_Model_Proxy_Property_Set_Data *)data; + Eldbus_Model_Proxy_Data *pd = sd->pd; const char *error_name, *error_text; - Eina_Value *prop_value; - Eina_Value *promise_value; + Eina_Value *value; - pd->pending_list = eina_list_remove(pd->pending_list, pending); + pd->pendings = eina_list_remove(pd->pendings, pending); if (eldbus_message_error_get(msg, &error_name, &error_text)) { ERR("%s: %s", error_name, error_text); - efl_promise_failed_set(property_set_data->promise, EFL_MODEL_ERROR_UNKNOWN); - _eldbus_model_proxy_property_set_data_free(property_set_data); - return; + eina_promise_reject(sd->promise, EFL_MODEL_ERROR_UNKNOWN); + goto end; } - prop_value = eina_hash_find(pd->properties_hash, property_set_data->property); - if (prop_value != NULL) + value = eina_hash_find(pd->properties, sd->property); + if (value) { - if (eina_value_copy(&property_set_data->value, prop_value)) - { - Efl_Model_Property_Event evt = { - .changed_properties = pd->properties_array - }; - - efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt); - efl_model_property_changed_notify(pd->obj, property_set_data->property); - - } - promise_value = eina_value_new(eina_value_type_get(prop_value)); - eina_value_copy(prop_value, promise_value); - efl_promise_value_set(property_set_data->promise, promise_value, (Eina_Free_Cb)&eina_value_free); + efl_model_properties_changed(pd->obj, sd->property); + if (sd->promise) + eina_promise_resolve(sd->promise, + eina_value_reference_copy(value)); } else { - efl_promise_failed_set(property_set_data->promise, EFL_MODEL_ERROR_NOT_FOUND); + if (sd->promise) + eina_promise_reject(sd->promise, + EFL_MODEL_ERROR_NOT_FOUND); } - _eldbus_model_proxy_property_set_data_free(property_set_data); -} - -static bool -_eldbus_model_proxy_has_property(Eldbus_Model_Proxy_Data *pd, const char *property) -{ - Eldbus_Introspection_Property *property_introspection = - eldbus_introspection_property_find(pd->interface->properties, property); - - if (property_introspection == NULL) - { - return false; - } - - return true; -} - -static bool -_eldbus_model_proxy_is_property_writeable(Eldbus_Model_Proxy_Data *pd, const char *property) -{ - Eldbus_Introspection_Property *property_introspection = - eldbus_introspection_property_find(pd->interface->properties, property); - - if (property_introspection == NULL) - { - WRN("Property not found: %s", property); - return false; - } - - return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_WRITE == property_introspection->access - || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access; -} - -static bool -_eldbus_model_proxy_is_property_readable(Eldbus_Model_Proxy_Data *pd, const char *property) -{ - Eldbus_Introspection_Property *property_introspection = - eldbus_introspection_property_find(pd->interface->properties, property); - - if (property_introspection == NULL) - { - WRN("Property not found: %s", property); - return false; - } - - return ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READ == property_introspection->access - || ELDBUS_INTROSPECTION_PROPERTY_ACCESS_READWRITE == property_introspection->access; + end: + _eldbus_model_proxy_property_set_data_free(sd); } static const char * -_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, const char *property) +_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, + const char *property) { Eldbus_Introspection_Property *property_introspection = eldbus_introspection_property_find(pd->interface->properties, property); @@ -778,35 +720,12 @@ _eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd, const char *p return property_introspection->type; } -static Eldbus_Model_Proxy_Property_Set_Data * -_eldbus_model_proxy_property_set_data_new(Eldbus_Model_Proxy_Data *pd, - const char *property, - const Eina_Value *value, - Efl_Promise *promise) -{ - Eldbus_Model_Proxy_Property_Set_Data *data = calloc(1, sizeof(Eldbus_Model_Proxy_Property_Set_Data)); - EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL); - - data->pd = pd; - data->promise = promise; - data->property = eina_stringshare_add(property); - if (!eina_value_copy(value, &data->value)) - goto error; - - return data; - - error: - eina_stringshare_del(data->property); - free(data); - return NULL; -} - static void _eldbus_model_proxy_property_set_data_free(Eldbus_Model_Proxy_Property_Set_Data *data) { EINA_SAFETY_ON_NULL_RETURN(data); eina_stringshare_del(data->property); - eina_value_flush(&data->value); + eina_value_free(data->value); free(data); } diff --git a/src/lib/eldbus/eldbus_model_proxy.eo b/src/lib/eldbus/eldbus_model_proxy.eo index 00521e67c8..0bb8b3ee1c 100644 --- a/src/lib/eldbus/eldbus_model_proxy.eo +++ b/src/lib/eldbus/eldbus_model_proxy.eo @@ -1,19 +1,24 @@ import eldbus_types; -class Eldbus.Model.Proxy (Efl.Object, Efl.Model) { +class Eldbus.Model.Proxy (Eldbus.Model) { [[Eldbus model proxy class]] methods { - custom_constructor { - [[Custom Eldbus_Model_Proxy constructor. - - @since 1.16]] - params { - @in object: ptr(Eldbus.Object); [[Eldbus object]] + @property object { + [[Object]] + set {} + values { + object: ptr(Eldbus.Object); [[Eldbus object]] + } + } + @property interface { + [[Object]] + set {} + values { @cref interface: Eldbus.Introspection.Interface; [[The introspected interface]] } } - @property proxy_name { + @property proxy_name { [[Proxy name]] get {} values { @@ -23,16 +28,15 @@ class Eldbus.Model.Proxy (Efl.Object, Efl.Model) { } implements { Efl.Object.constructor; + Efl.Object.finalize; + Efl.Object.invalidate; Efl.Object.destructor; Efl.Model.properties { get; } - Efl.Model.property_set; - Efl.Model.property_get; - Efl.Model.child_add; - Efl.Model.child_del; + Efl.Model.property { set; get; } Efl.Model.children_slice_get; - Efl.Model.children_count_get; + Efl.Model.children_count { get; } } constructors { - .custom_constructor; + .interface; } } diff --git a/src/lib/eldbus/eldbus_model_proxy_private.h b/src/lib/eldbus/eldbus_model_proxy_private.h index 293a1f5bac..940f778311 100644 --- a/src/lib/eldbus/eldbus_model_proxy_private.h +++ b/src/lib/eldbus/eldbus_model_proxy_private.h @@ -13,20 +13,21 @@ typedef struct _Eldbus_Model_Proxy_Data Eldbus_Model_Proxy_Data; struct _Eldbus_Model_Proxy_Data { Eo *obj; - Eina_Bool is_listed : 1; - Eina_Bool is_loaded : 1; + + const Eldbus_Introspection_Interface *interface; + Eldbus_Object *object; Eldbus_Proxy *proxy; - Eina_Array *properties_array; - Eina_Hash *properties_hash; - Eina_List *children_list; + Eina_Hash *properties; + Eina_List *childrens; + Eina_List *pendings; + Eina_List *promises; + Eina_Stringshare *name; - Eina_List *pending_list; - Eina_List *promise_list; - bool monitoring; - const Eldbus_Introspection_Interface *interface; - Eina_Value tmp_value; + + Eina_Bool monitoring : 1; + Eina_Bool is_listed : 1; + Eina_Bool is_loaded : 1; }; #endif -