eldbus: migrate and refactor eldbus.model to new efl.model API.

This commit is contained in:
Cedric Bail 2017-10-25 18:05:41 -07:00 committed by Cedric BAIL
parent ddcf8d8b97
commit 3edb4ca697
18 changed files with 815 additions and 1362 deletions

View File

@ -225,6 +225,7 @@ typedef void (*Eldbus_Signal_Cb)(void *data, const Eldbus_Message *msg);
#ifdef EFL_BETA_API_SUPPORT #ifdef EFL_BETA_API_SUPPORT
#include "eldbus_model.eo.h"
#include "eldbus_model_arguments.eo.h" #include "eldbus_model_arguments.eo.h"
#include "eldbus_model_connection.eo.h" #include "eldbus_model_connection.eo.h"
#include "eldbus_model_method.eo.h" #include "eldbus_model_method.eo.h"

View File

@ -74,6 +74,15 @@ _eldbus_model_efl_object_finalize(Eo *obj, Eldbus_Model_Data *pd)
return efl_finalize(efl_super(obj, ELDBUS_MODEL_CLASS)); 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 static void
_eldbus_model_efl_object_destructor(Eo *obj, Eldbus_Model_Data *pd) _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); eina_stringshare_del(pd->address);
pd->address = NULL; pd->address = NULL;
eldbus_connection_unref(pd->connection);
pd->connection = NULL;
efl_destructor(efl_super(obj, MY_CLASS)); 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; 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; err = EFL_MODEL_ERROR_NOT_FOUND;
return eina_future_rejected(efl_loop_future_scheduler_get(obj), err); 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; Eina_Array *r;
r = eina_array_new(1); r = eina_array_new(1);
eina_array_push(r, UNIQUE_NAME_PROPERTY); eina_array_push(r, eina_stringshare_add(UNIQUE_NAME_PROPERTY));
return r; return r;
} }

View File

@ -46,6 +46,7 @@ class Eldbus.Model (Efl.Object, Efl.Model) {
} }
implements { implements {
Efl.Object.finalize; Efl.Object.finalize;
Efl.Object.invalidate;
Efl.Object.destructor; Efl.Object.destructor;
Efl.Model.property { get; set; } Efl.Model.property { get; set; }
Efl.Model.properties { get; } Efl.Model.properties { get; }

View File

@ -30,8 +30,6 @@ _eldbus_model_arguments_hash_free(Eina_Value *value)
static Efl_Object* static Efl_Object*
_eldbus_model_arguments_efl_object_constructor(Eo *obj, Eldbus_Model_Arguments_Data *pd) _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->obj = obj;
pd->properties_array = NULL; pd->properties_array = NULL;
pd->properties_hash = eina_hash_string_superfast_new(EINA_FREE_CB(_eldbus_model_arguments_hash_free)); 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->proxy = NULL;
pd->arguments = NULL; pd->arguments = NULL;
pd->name = 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 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)); 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_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); 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* static Eina_Future *
_eldbus_model_arguments_efl_model_property_set(Eo *obj EINA_UNUSED, _eldbus_model_arguments_efl_model_property_set(Eo *obj,
Eldbus_Model_Arguments_Data *pd, Eldbus_Model_Arguments_Data *pd,
const char *property, const char *property, Eina_Value *value)
Eina_Value const* value)
{ {
Eina_Value *prop_value; Eina_Value *prop_value;
Eina_Value *promise_value; Eina_Error err = 0;
Efl_Promise* promise = efl_add(EFL_PROMISE_CLASS, obj); Eina_Bool ret;
Efl_Future* future = efl_promise_future_get(promise);
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); DBG("(%p): property=%s", obj, property);
err = EFL_MODEL_ERROR_NOT_FOUND;
if (!property || !value) goto on_error;
_eldbus_model_arguments_properties_load(pd); _eldbus_model_arguments_properties_load(pd);
Eina_Bool ret = _eldbus_model_arguments_is_input_argument(pd, property); err = EFL_MODEL_ERROR_READ_ONLY;
ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_READ_ONLY, future); 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); 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_flush(prop_value);
eina_value_copy(value, prop_value); eina_value_copy(value, prop_value);
promise_value = eina_value_new(eina_value_type_get(value)); return eina_future_resolved(efl_loop_future_scheduler_get(obj),
eina_value_copy(value, promise_value); eina_value_reference_copy(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 Efl_Future* static Eina_Value *
_eldbus_model_arguments_efl_model_property_get(Eo *obj EINA_UNUSED, _eldbus_model_arguments_efl_model_property_get(const Eo *obj, Eldbus_Model_Arguments_Data *pd, const char *property)
Eldbus_Model_Arguments_Data *pd,
const char *property)
{ {
Efl_Promise *promise = efl_add(EFL_PROMISE_CLASS, obj); Eina_Value *value;
Efl_Future *future = efl_promise_future_get(promise); Eina_Bool ret;
Eina_Value *promise_value;
ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(property, promise, EFL_MODEL_ERROR_INCORRECT_VALUE, future);
DBG("(%p): property=%s", obj, property); DBG("(%p): property=%s", obj, property);
if (!property) return eina_value_error_new(EFL_MODEL_ERROR_INCORRECT_VALUE);
_eldbus_model_arguments_properties_load(pd); _eldbus_model_arguments_properties_load(pd);
Eina_Value* value = eina_hash_find(pd->properties_hash, property); value = eina_hash_find(pd->properties_hash, property);
ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(value, promise, EFL_MODEL_ERROR_NOT_FOUND, future); if (!value) return eina_value_error_new(EFL_MODEL_ERROR_NOT_FOUND);
Eina_Bool ret = _eldbus_model_arguments_is_output_argument(pd, property); ret = _eldbus_model_arguments_is_output_argument(pd, property);
ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(ret, promise, EFL_MODEL_ERROR_PERMISSION_DENIED, future); if (!ret) return eina_value_error_new(EFL_MODEL_ERROR_PERMISSION_DENIED);
promise_value = eina_value_new(eina_value_type_get(value)); return eina_value_dup(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;
} }
static const char * static const char *

View File

@ -1,6 +1,6 @@
import eldbus_types; import eldbus_types;
class Eldbus.Model.Arguments (Efl.Object, Efl.Model) { class Eldbus.Model.Arguments (Eldbus.Model) {
[[Eldbus model arguments class]] [[Eldbus model arguments class]]
methods { methods {
@ -24,14 +24,10 @@ class Eldbus.Model.Arguments (Efl.Object, Efl.Model) {
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.finalize;
Efl.Object.destructor; Efl.Object.destructor;
Efl.Model.properties { get; } Efl.Model.properties { get; }
Efl.Model.property_set; Efl.Model.property { set; get; }
Efl.Model.property_get;
Efl.Model.child_add;
Efl.Model.child_del;
Efl.Model.children_slice_get;
Efl.Model.children_count_get;
} }
constructors { constructors {
.custom_constructor; .custom_constructor;

View File

@ -9,13 +9,7 @@
#define MY_CLASS ELDBUS_MODEL_CONNECTION_CLASS #define MY_CLASS ELDBUS_MODEL_CONNECTION_CLASS
#define MY_CLASS_NAME "Eldbus_Model_Connection" #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_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* static Efl_Object*
_eldbus_model_connection_efl_object_constructor(Eo *obj, Eldbus_Model_Connection_Data *pd) _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)); obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->obj = obj; 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; 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 static void
_eldbus_model_connection_efl_object_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd) _eldbus_model_connection_efl_object_destructor(Eo *obj, Eldbus_Model_Connection_Data *pd)
{ {
eina_stringshare_del(pd->address); Eldbus_Children_Slice_Promise *slice;
_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;
Eo *child; Eo *child;
EINA_SAFETY_ON_NULL_RETURN(pd); if (pd->pending) eldbus_pending_cancel(pd->pending);
if (!pd->connection) EINA_LIST_FREE(pd->childrens, child)
return;
free(pd->unique_name);
pd->unique_name = NULL;
EINA_LIST_FREE(pd->children_list, child)
efl_del(child); efl_del(child);
EINA_LIST_FREE(pd->pending_list, pending) EINA_LIST_FREE(pd->requests, slice)
eldbus_pending_cancel(pending);
if (pd->properties_array)
{ {
eina_array_free(pd->properties_array); eina_promise_reject(slice->p, EFL_MODEL_ERROR_UNKNOWN);
pd->properties_array = NULL; 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 static void
_eldbus_model_connection_names_list_cb(void *data, _eldbus_model_connection_names_list_cb(void *data,
const Eldbus_Message *msg, const Eldbus_Message *msg,
Eldbus_Pending *pending) Eldbus_Pending *pending EINA_UNUSED)
{ {
Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*)data; Eldbus_Model_Connection_Data *pd = (Eldbus_Model_Connection_Data*) data;
_Eldbus_Children_Slice_Promise * p; Eldbus_Model_Data *sd;
Eldbus_Children_Slice_Promise *slice;
const char *error_name, *error_text; const char *error_name, *error_text;
Eldbus_Message_Iter *array = NULL; Eldbus_Message_Iter *array = NULL;
const char *bus; const char *bus;
unsigned int count; 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)) if (eldbus_message_error_get(msg, &error_name, &error_text))
{ {
ERR("%s: %s", error_name, error_text); ERR("%s: %s", error_name, error_text);
//efl_model_error_notify(pd->obj);
return; return;
} }
@ -314,39 +121,37 @@ _eldbus_model_connection_names_list_cb(void *data,
return; return;
} }
sd = efl_data_scope_get(pd->obj, ELDBUS_MODEL_CLASS);
while (eldbus_message_iter_get_and_next(array, 's', &bus)) while (eldbus_message_iter_get_and_next(array, 's', &bus))
{ {
Eo *child;
DBG("(%p): bus = %s", pd->obj, bus); 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; pd->is_listed = EINA_TRUE;
EINA_LIST_FOREACH(pd->children_promises, i, p) count = eina_list_count(pd->childrens);
{ efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, &count);
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);
Efl_Promise *ep; EINA_LIST_FREE(pd->requests, slice)
EINA_LIST_FOREACH(pd->count_promises, i, ep)
{ {
unsigned *c = calloc(sizeof(unsigned), 1); Eina_Value v;
*c = eina_list_count(pd->children_list);
efl_promise_value_set(ep, c, free); 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" #include "eldbus_model_connection.eo.c"

View File

@ -1,53 +1,12 @@
import eldbus_types; import eldbus_types;
class Eldbus.Model.Connection (Efl.Object, Efl.Model) { class Eldbus.Model.Connection (Eldbus.Model) {
[[Eldbus model connection class]] [[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 { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.destructor; 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_slice_get;
Efl.Model.children_count_get; Efl.Model.children_count { get; }
}
constructors {
.custom_constructor;
} }
} }

View File

@ -13,18 +13,20 @@ typedef struct _Eldbus_Model_Connection_Data Eldbus_Model_Connection_Data;
struct _Eldbus_Model_Connection_Data struct _Eldbus_Model_Connection_Data
{ {
Eo *obj; Eo *obj;
Eina_Bool is_listed : 1;
Eldbus_Connection *connection; Eldbus_Connection *connection;
Eina_Array *properties_array; Eldbus_Pending *pending;
Eina_List *children_list;
Eina_List *children_promises;
Eina_List *count_promises;
Eldbus_Connection_Type type; Eldbus_Connection_Type type;
Eina_List *childrens;
Eina_List *requests;
Eina_Stringshare *address; Eina_Stringshare *address;
bool private;
char *unique_name; char *unique_name;
Eina_List *pending_list;
bool private;
Eina_Bool is_listed : 1;
}; };
#endif #endif

View File

@ -26,17 +26,33 @@ _eldbus_model_method_efl_object_constructor(Eo *obj, Eldbus_Model_Method_Data *p
return obj; return obj;
} }
static void static Efl_Object*
_eldbus_model_method_method_constructor(Eo *obj EINA_UNUSED, _eldbus_model_method_efl_object_finalize(Eo *obj, Eldbus_Model_Method_Data *pd)
Eldbus_Model_Method_Data *pd,
Eldbus_Proxy *proxy,
const Eldbus_Introspection_Method *method)
{ {
EINA_SAFETY_ON_NULL_RETURN(proxy); if (!pd->proxy ||
EINA_SAFETY_ON_NULL_RETURN(method); !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; pd->method = method;
} }

View File

@ -3,13 +3,20 @@ import eldbus_types;
class Eldbus.Model.Method (Eldbus.Model.Arguments) { class Eldbus.Model.Method (Eldbus.Model.Arguments) {
[[Eldbus model method class]] [[Eldbus model method class]]
methods { methods {
method_constructor { @property proxy {
[[Custom Eldbus_Model_Method constructor. [[Custom Eldbus_Model_Method constructor.
@since 1.16]] @since 1.21]]
params { set {}
@in proxy: ptr(Eldbus.Proxy); [[Eldbus proxy]] values {
@cref method: Eldbus.Introspection.Method; [[The introspected method]] proxy: ptr(Eldbus.Proxy); [[Eldbus proxy]]
}
}
@property method {
[[Object]]
set {}
values {
@cref method: Eldbus.Introspection.Method; [[The introspected interface]]
} }
} }
call { call {
@ -24,9 +31,11 @@ class Eldbus.Model.Method (Eldbus.Model.Arguments) {
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.finalize;
} }
constructors { constructors {
.method_constructor; .proxy;
.method;
} }
events { events {
successful,call; [[Event dispatched for a successful method call.]] successful,call; [[Event dispatched for a successful method call.]]

View File

@ -11,8 +11,10 @@ typedef struct _Eldbus_Model_Method_Data Eldbus_Model_Method_Data;
struct _Eldbus_Model_Method_Data struct _Eldbus_Model_Method_Data
{ {
Eo *obj; Eo *obj;
const Eldbus_Introspection_Method *method; const Eldbus_Introspection_Method *method;
Eldbus_Proxy *proxy;
}; };
#endif #endif

View File

@ -11,15 +11,7 @@
#define MY_CLASS ELDBUS_MODEL_OBJECT_CLASS #define MY_CLASS ELDBUS_MODEL_OBJECT_CLASS
#define MY_CLASS_NAME "Eldbus_Model_Object" #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_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 void _eldbus_model_object_create_children(Eldbus_Model_Object_Data *, Eldbus_Object *, Eina_List *);
static Efl_Object* 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)); obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->obj = obj; 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; return obj;
} }
static void static void
_eldbus_model_object_custom_constructor(Eo *obj EINA_UNUSED, _eldbus_model_object_bus_set(Eo *obj EINA_UNUSED,
Eldbus_Model_Object_Data *pd, Eldbus_Model_Object_Data *pd,
Eldbus_Connection_Type type, const char *bus)
const char* address,
Eina_Bool private,
const char* bus,
const char* path)
{ {
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->bus = eina_stringshare_add(bus);
pd->path = eina_stringshare_add(path);
} }
static void static void
_eldbus_model_object_connection_constructor(Eo *obj EINA_UNUSED, _eldbus_model_object_path_set(Eo *obj EINA_UNUSED,
Eldbus_Model_Object_Data *pd, Eldbus_Model_Object_Data *pd,
Eldbus_Connection *connection, const char *path)
const char* bus,
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); 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 static void
_eldbus_model_object_efl_object_destructor(Eo *obj, Eldbus_Model_Object_Data *pd) _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->bus);
eina_stringshare_del(pd->path); eina_stringshare_del(pd->path);
_eldbus_model_object_clear(pd);
efl_destructor(efl_super(obj, MY_CLASS)); 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 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 static Eina_Future *
_eldbus_model_object_type_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Data *pd) _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 * static const char *
@ -255,105 +163,71 @@ _eldbus_model_object_path_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Object_Dat
return pd->path; return pd->path;
} }
static void static char *
_eldbus_model_object_connect(Eldbus_Model_Object_Data *pd) _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) buffer = eina_strbuf_new();
{ eina_strbuf_append_printf(buffer, format, root_path, relative_path);
if (pd->private) absolute_path = eina_strbuf_string_steal(buffer);
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_strbuf_free(buffer);
return absolute_path;
EINA_SAFETY_ON_FALSE_RETURN(NULL != pd->connection);
} }
static void 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_Introspection_Node *node;
eldbus_connection_unref(pd->connection); Eina_List *it;
pd->connection = NULL;
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 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_Introspection_Interface *interface;
Eldbus_Object *object; const char *current_path;
Eo *child; Eina_List *l;
EINA_SAFETY_ON_NULL_RETURN(pd); current_path = eldbus_object_path_get(object);
if (!pd->connection) if (!current_path) return ;
return;
free(pd->unique_name); EINA_LIST_FOREACH(interfaces, l, interface)
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_array_free(pd->properties_array); Eo *child;
pd->properties_array = NULL;
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 static void
@ -362,12 +236,15 @@ _eldbus_model_object_introspect_cb(void *data,
Eldbus_Pending *pending) Eldbus_Pending *pending)
{ {
Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data; Eldbus_Model_Object_Data *pd = (Eldbus_Model_Object_Data*)data;
Eldbus_Children_Slice_Promise* slice;
Eldbus_Object *object; Eldbus_Object *object;
const char *error_name, *error_text; const char *error_name;
const char *error_text;
const char *xml = NULL; const char *xml = NULL;
const char *current_path; 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"); object = eldbus_pending_data_get(pending, "object");
if (eldbus_message_error_get(msg, &error_name, &error_text)) 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."); ERR("Error getting arguments.");
return; return;
} }
EINA_SAFETY_ON_NULL_RETURN(xml);
if (!xml)
{
ERR("No XML.");
return ;
}
current_path = eldbus_object_path_get(object); 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); 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_introspect_nodes(pd, current_path, pd->introspection->nodes);
_eldbus_model_object_create_children(pd, object, pd->introspection->interfaces); _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; v = efl_model_list_value_get(pd->childrens, slice->start, slice->count);
_Eldbus_Children_Slice_Promise* p; eina_promise_resolve(slice->p, v);
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);
Efl_Promise *ep; free(slice);
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);
} }
} }

View File

@ -1,63 +1,22 @@
import eldbus_types; import eldbus_types;
class Eldbus.Model.Object (Efl.Object, Efl.Model) { class Eldbus.Model.Object (Eldbus.Model) {
[[Eldbus model object class]] [[Eldbus model object class]]
data: Eldbus_Model_Object_Data; data: Eldbus_Model_Object_Data;
methods { methods {
custom_constructor { @property bus {
[[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 {
[[DBus Name or unique-id]] [[DBus Name or unique-id]]
get { } get { }
set { }
values { values {
bus: string; [[DBus name]] bus: string; [[DBus name]]
} }
} }
@property path { @property path {
[[DBus path]] [[DBus path]]
get { } get { }
set { }
values { values {
path: string; [[DBus path]] path: string; [[DBus path]]
} }
@ -65,17 +24,10 @@ class Eldbus.Model.Object (Efl.Object, Efl.Model) {
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.finalize;
Efl.Object.invalidate;
Efl.Object.destructor; 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_slice_get;
Efl.Model.children_count_get; Efl.Model.children_count { get; }
}
constructors {
.custom_constructor;
.connection_constructor;
} }
} }

View File

@ -12,22 +12,18 @@ typedef struct _Eldbus_Model_Object_Data Eldbus_Model_Object_Data;
struct _Eldbus_Model_Object_Data struct _Eldbus_Model_Object_Data
{ {
Eo *obj; Eo *obj;
Eina_Bool is_listed : 1;
Eldbus_Connection *connection; Eina_List *objects;
Eina_List *object_list; Eina_List *childrens;
Eina_Array *properties_array; Eina_List *requests;
Eina_List *children_list; Eina_List *pendings;
Eina_List *children_promises;
Eina_List *count_promises;
Eldbus_Connection_Type type;
Eina_Stringshare *address;
bool private;
Eina_Stringshare *bus; Eina_Stringshare *bus;
Eina_Stringshare *path; Eina_Stringshare *path;
char *unique_name;
Eina_List *pending_list;
Eldbus_Introspection_Node *introspection; Eldbus_Introspection_Node *introspection;
Eina_Bool is_listed : 1;
}; };
#endif #endif

View File

@ -8,19 +8,28 @@
#include <Eo.h> #include <Eo.h>
#include <Efl.h> #include <Efl.h>
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 struct _Eldbus_Children_Slice_Promise
{ {
unsigned start; Eina_Promise *p;
unsigned count;
Efl_Promise* promise; unsigned int start;
unsigned int count;
}; };
typedef struct _Eldbus_Property_Promise _Eldbus_Property_Promise; struct _Eldbus_Model_Data
struct _Eldbus_Property_Promise
{ {
char *property; Eldbus_Connection *connection;
Efl_Promise* promise; 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" #define UNIQUE_NAME_PROPERTY "unique_name"
@ -28,6 +37,12 @@ struct _Eldbus_Property_Promise
/* logging support */ /* logging support */
extern int eldbus_model_log_dom; 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) \ #define ELDBUS_MODEL_ON_ERROR_EXIT_PROMISE_SET(exp, promise, err, v) \
do \ do \
{ \ { \

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,24 @@
import eldbus_types; import eldbus_types;
class Eldbus.Model.Proxy (Efl.Object, Efl.Model) { class Eldbus.Model.Proxy (Eldbus.Model) {
[[Eldbus model proxy class]] [[Eldbus model proxy class]]
methods { methods {
custom_constructor { @property object {
[[Custom Eldbus_Model_Proxy constructor. [[Object]]
set {}
@since 1.16]] values {
params { object: ptr(Eldbus.Object); [[Eldbus object]]
@in object: ptr(Eldbus.Object); [[Eldbus object]] }
}
@property interface {
[[Object]]
set {}
values {
@cref interface: Eldbus.Introspection.Interface; [[The introspected interface]] @cref interface: Eldbus.Introspection.Interface; [[The introspected interface]]
} }
} }
@property proxy_name { @property proxy_name {
[[Proxy name]] [[Proxy name]]
get {} get {}
values { values {
@ -23,16 +28,15 @@ class Eldbus.Model.Proxy (Efl.Object, Efl.Model) {
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.finalize;
Efl.Object.invalidate;
Efl.Object.destructor; Efl.Object.destructor;
Efl.Model.properties { get; } Efl.Model.properties { get; }
Efl.Model.property_set; Efl.Model.property { set; get; }
Efl.Model.property_get;
Efl.Model.child_add;
Efl.Model.child_del;
Efl.Model.children_slice_get; Efl.Model.children_slice_get;
Efl.Model.children_count_get; Efl.Model.children_count { get; }
} }
constructors { constructors {
.custom_constructor; .interface;
} }
} }

View File

@ -13,20 +13,21 @@ typedef struct _Eldbus_Model_Proxy_Data Eldbus_Model_Proxy_Data;
struct _Eldbus_Model_Proxy_Data struct _Eldbus_Model_Proxy_Data
{ {
Eo *obj; Eo *obj;
Eina_Bool is_listed : 1;
Eina_Bool is_loaded : 1; const Eldbus_Introspection_Interface *interface;
Eldbus_Object *object; Eldbus_Object *object;
Eldbus_Proxy *proxy; Eldbus_Proxy *proxy;
Eina_Array *properties_array; Eina_Hash *properties;
Eina_Hash *properties_hash; Eina_List *childrens;
Eina_List *children_list; Eina_List *pendings;
Eina_List *promises;
Eina_Stringshare *name; Eina_Stringshare *name;
Eina_List *pending_list;
Eina_List *promise_list; Eina_Bool monitoring : 1;
bool monitoring; Eina_Bool is_listed : 1;
const Eldbus_Introspection_Interface *interface; Eina_Bool is_loaded : 1;
Eina_Value tmp_value;
}; };
#endif #endif