2015-01-09 08:20:14 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2016-02-17 03:49:28 -08:00
|
|
|
#include <Eina.h>
|
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
#include "eldbus_model_proxy_private.h"
|
|
|
|
#include "eldbus_model_private.h"
|
|
|
|
|
|
|
|
#define MY_CLASS ELDBUS_MODEL_PROXY_CLASS
|
|
|
|
#define MY_CLASS_NAME "Eldbus_Model_Proxy"
|
|
|
|
|
|
|
|
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 *);
|
2016-04-29 15:39:37 -07:00
|
|
|
static void _eldbus_model_proxy_property_set_load_cb(void *, const Eldbus_Message *, Eldbus_Pending *);
|
2015-01-09 08:20:14 -08:00
|
|
|
static void _eldbus_model_proxy_start_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 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 *);
|
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
typedef struct _Eldbus_Model_Proxy_Property_Set_Data Eldbus_Model_Proxy_Property_Set_Data;
|
2017-10-25 18:05:41 -07:00
|
|
|
typedef struct _Eldbus_Property_Promise Eldbus_Property_Promise;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
struct _Eldbus_Model_Proxy_Property_Set_Data
|
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Data *pd;
|
2017-10-25 18:05:41 -07:00
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
Eina_Stringshare *property;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_Promise *promise;
|
|
|
|
Eina_Value *value;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Eldbus_Property_Promise
|
|
|
|
{
|
|
|
|
Eina_Promise *promise;
|
|
|
|
Eina_Stringshare *property;
|
2015-01-09 08:20:14 -08:00
|
|
|
};
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eldbus_model_proxy_load(Eldbus_Model_Proxy_Data *pd)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
static void
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_unload(Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Pending *pending;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_object_del(void *data, Eldbus_Object *object EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Data *pd = data;
|
|
|
|
|
|
|
|
pd->object = NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2016-08-10 07:23:04 -07:00
|
|
|
static Efl_Object*
|
|
|
|
_eldbus_model_proxy_efl_object_constructor(Eo *obj, Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
pd->obj = obj;
|
2017-10-25 18:05:41 -07:00
|
|
|
pd->properties = eina_hash_stringshared_new(NULL);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static Efl_Object*
|
|
|
|
_eldbus_model_proxy_efl_object_finalize(Eo *obj, Eldbus_Model_Proxy_Data *pd)
|
2018-03-14 12:17:59 -07:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!pd->object ||
|
|
|
|
!pd->name ||
|
|
|
|
!pd->interface)
|
|
|
|
return NULL;
|
2018-03-14 12:17:59 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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));
|
2018-03-14 12:17:59 -07:00
|
|
|
}
|
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
static void
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_object_set(Eo *obj EINA_UNUSED,
|
|
|
|
Eldbus_Model_Proxy_Data *pd,
|
|
|
|
Eldbus_Object *object)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
|
|
|
pd->object = eldbus_object_ref(object);
|
2017-10-25 18:05:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_interface_set(Eo *obj EINA_UNUSED,
|
|
|
|
Eldbus_Model_Proxy_Data *pd,
|
|
|
|
const Eldbus_Introspection_Interface *interface)
|
|
|
|
{
|
2015-01-09 08:20:14 -08:00
|
|
|
pd->name = eina_stringshare_add(interface->name);
|
|
|
|
pd->interface = interface;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_efl_object_invalidate(Eo *obj, Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
Eo *child;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
EINA_LIST_FREE(pd->childrens, child)
|
|
|
|
efl_unref(child);
|
|
|
|
|
|
|
|
_eldbus_model_proxy_unload(pd);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2018-03-14 12:17:59 -07:00
|
|
|
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);
|
|
|
|
}
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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);
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2018-11-23 08:25:19 -08:00
|
|
|
static Eina_Iterator *
|
2018-04-17 11:09:44 -07:00
|
|
|
_eldbus_model_proxy_efl_model_properties_get(const Eo *obj EINA_UNUSED,
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2018-11-23 08:25:19 -08:00
|
|
|
return eina_hash_iterator_key_new(pd->properties);
|
2017-10-25 18:05:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#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;
|
|
|
|
}
|
2016-07-21 09:50:19 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static void
|
2019-01-04 17:42:26 -08:00
|
|
|
_eldbus_model_proxy_cancel_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,
|
|
|
|
void *data,
|
|
|
|
const Eina_Future *dead_future EINA_UNUSED)
|
2017-10-25 18:05:41 -07:00
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Property_Set_Data *sd = data;
|
|
|
|
|
|
|
|
sd->promise = NULL;
|
2019-11-15 09:39:38 -08:00
|
|
|
eina_stringshare_del(sd->property);
|
|
|
|
eina_value_free(sd->value);
|
|
|
|
free(sd);
|
2017-10-25 18:05:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static Eina_Future *
|
2016-05-10 03:36:13 -07:00
|
|
|
_eldbus_model_proxy_efl_model_property_set(Eo *obj EINA_UNUSED,
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Model_Proxy_Data *pd,
|
|
|
|
const char *property,
|
|
|
|
Eina_Value *value)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2019-03-19 05:57:59 -07:00
|
|
|
Eldbus_Model_Proxy_Property_Set_Data *data = NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
const char *signature;
|
|
|
|
Eldbus_Pending *pending;
|
2017-10-25 18:05:41 -07:00
|
|
|
unsigned char access;
|
|
|
|
Eina_Error err = 0;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
DBG("(%p): property=%s", obj, property);
|
2016-04-29 15:39:37 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
err = EFL_MODEL_ERROR_UNKNOWN;
|
2015-01-09 08:20:14 -08:00
|
|
|
signature = _eldbus_model_proxy_property_type_get(pd, property);
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!signature) goto on_error;
|
2016-04-29 15:39:37 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
err = ENOMEM;
|
|
|
|
data = calloc(1, sizeof (Eldbus_Model_Proxy_Property_Set_Data));
|
|
|
|
if (!data) goto on_error;
|
|
|
|
|
|
|
|
data->pd = pd;
|
2019-01-04 17:42:26 -08:00
|
|
|
data->promise = efl_loop_promise_new(obj);
|
2017-10-25 18:05:41 -07:00
|
|
|
data->property = eina_stringshare_add(property);
|
|
|
|
if (!(data->value = eina_value_dup(value))) goto on_error;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
if (!pd->is_loaded)
|
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
pending = _eldbus_model_proxy_load_all(pd, data->promise, property,
|
|
|
|
_eldbus_model_proxy_property_set_load_cb, data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pending = eldbus_proxy_property_value_set(pd->proxy, property, signature, (Eina_Value*)value,
|
|
|
|
_eldbus_model_proxy_property_set_cb, data);
|
2016-04-29 15:39:37 -07:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
if (pending) pd->pendings = eina_list_append(pd->pendings, pending);
|
2019-01-04 17:42:26 -08:00
|
|
|
return efl_future_then(obj, eina_future_new(data->promise),
|
|
|
|
.data = data, .free = _eldbus_model_proxy_cancel_cb);
|
2017-10-25 18:05:41 -07:00
|
|
|
|
|
|
|
on_error:
|
2019-03-19 05:57:59 -07:00
|
|
|
free(data);
|
2018-11-22 17:14:51 -08:00
|
|
|
return efl_loop_future_rejected(obj, err);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static Eina_Value *
|
|
|
|
_eldbus_model_proxy_efl_model_property_get(const Eo *obj EINA_UNUSED,
|
|
|
|
Eldbus_Model_Proxy_Data *pd,
|
|
|
|
const char *property)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Pending *pending;
|
|
|
|
unsigned char access;
|
|
|
|
Eina_Error err = 0;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
if (pd->is_loaded)
|
|
|
|
{
|
|
|
|
Eina_Stringshare *tmp;
|
|
|
|
Eina_Value *value;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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;
|
2016-04-29 15:39:37 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
return eina_value_dup(value);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
err = ENOMEM;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
return eina_value_error_new(EAGAIN);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
on_error:
|
|
|
|
return eina_value_error_new(err);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2016-04-20 13:07:53 -07:00
|
|
|
static void
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_listed(Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2016-04-20 13:07:53 -07:00
|
|
|
if (!pd->is_listed)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2016-04-20 13:07:53 -07:00
|
|
|
_eldbus_model_proxy_create_methods_children(pd);
|
|
|
|
_eldbus_model_proxy_create_signals_children(pd);
|
2018-04-12 14:41:54 -07:00
|
|
|
|
|
|
|
efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_CHILDREN_COUNT_CHANGED, NULL);
|
2016-04-20 13:07:53 -07:00
|
|
|
pd->is_listed = EINA_TRUE;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
static Eina_Future*
|
|
|
|
_eldbus_model_proxy_efl_model_children_slice_get(Eo *obj EINA_UNUSED,
|
|
|
|
Eldbus_Model_Proxy_Data *pd,
|
|
|
|
unsigned start,
|
|
|
|
unsigned count)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_Value v;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_listed(pd);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
v = efl_model_list_value_get(pd->childrens, start, count);
|
2018-11-22 17:14:51 -08:00
|
|
|
return efl_loop_future_resolved(obj, v);
|
2017-10-25 18:05:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
_eldbus_model_proxy_efl_model_children_count_get(const Eo *obj EINA_UNUSED,
|
|
|
|
Eldbus_Model_Proxy_Data *pd)
|
|
|
|
{
|
|
|
|
_eldbus_model_proxy_listed(pd);
|
|
|
|
return eina_list_count(pd->childrens);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_create_methods_children(Eldbus_Model_Proxy_Data *pd)
|
|
|
|
{
|
|
|
|
Eldbus_Introspection_Method *method;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_List *it;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
EINA_LIST_FOREACH(pd->interface->methods, it, method)
|
|
|
|
{
|
|
|
|
const char *bus;
|
|
|
|
const char *path;
|
|
|
|
const char *interface_name;
|
|
|
|
const char *method_name;
|
|
|
|
Eo *child;
|
|
|
|
|
|
|
|
bus = eldbus_object_bus_name_get(pd->object);
|
|
|
|
if (!bus) continue;
|
|
|
|
|
|
|
|
path = eldbus_object_path_get(pd->object);
|
|
|
|
if (!path) continue;
|
|
|
|
|
|
|
|
interface_name = pd->interface->name;
|
|
|
|
if (!interface_name) continue;
|
|
|
|
|
|
|
|
method_name = method->name;
|
|
|
|
if (!method_name) continue;
|
|
|
|
|
2016-04-20 13:07:53 -07:00
|
|
|
INF("(%p) Creating method child: bus = %s, path = %s, method = %s::%s",
|
|
|
|
pd->obj, bus, path, interface_name, method_name);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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));
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_create_signals_children(Eldbus_Model_Proxy_Data *pd)
|
|
|
|
{
|
|
|
|
Eina_List *it;
|
|
|
|
Eldbus_Introspection_Signal *signal;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(pd->interface->signals, it, signal)
|
|
|
|
{
|
|
|
|
const char *bus;
|
|
|
|
const char *path;
|
|
|
|
const char *interface_name;
|
|
|
|
const char *signal_name;
|
|
|
|
Eo *child;
|
|
|
|
|
|
|
|
bus = eldbus_object_bus_name_get(pd->object);
|
|
|
|
if (!bus) continue;
|
|
|
|
|
|
|
|
path = eldbus_object_path_get(pd->object);
|
|
|
|
if (!path) continue;
|
|
|
|
|
|
|
|
interface_name = pd->interface->name;
|
|
|
|
if (!interface_name) continue;
|
|
|
|
|
|
|
|
signal_name = signal->name;
|
|
|
|
if (!signal_name) continue;
|
|
|
|
|
2016-04-20 13:07:53 -07:00
|
|
|
DBG("(%p) Creating signal child: bus = %s, path = %s, signal = %s::%s",
|
|
|
|
pd->obj, bus, path, interface_name, signal_name);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
child = efl_add_ref(ELDBUS_MODEL_SIGNAL_CLASS, pd->obj, eldbus_model_signal_constructor(efl_added, pd->proxy, signal));
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2018-04-17 11:09:44 -07:00
|
|
|
_eldbus_model_proxy_proxy_name_get(const Eo *obj EINA_UNUSED, Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
|
|
|
return pd->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_start_monitor(Eldbus_Model_Proxy_Data *pd)
|
|
|
|
{
|
|
|
|
if (pd->monitoring)
|
|
|
|
return;
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
pd->monitoring = EINA_TRUE;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
eldbus_proxy_event_callback_add(pd->proxy,
|
|
|
|
ELDBUS_PROXY_EVENT_PROPERTY_CHANGED,
|
|
|
|
_eldbus_model_proxy_property_changed_cb,
|
|
|
|
pd);
|
|
|
|
|
|
|
|
eldbus_proxy_event_callback_add(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,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
|
|
|
|
Eldbus_Object_Event_Property_Changed *event = (Eldbus_Object_Event_Property_Changed*)event_info;
|
|
|
|
Eina_Value *prop_value;
|
|
|
|
Eina_Bool ret;
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
prop_value = eina_hash_find(pd->properties, event->name);
|
2015-01-09 08:20:14 -08:00
|
|
|
if (!prop_value) return ;
|
|
|
|
|
|
|
|
ret = eina_value_copy(event->value, prop_value);
|
|
|
|
if (!ret) return ;
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
efl_model_properties_changed(pd->obj, event->name);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_property_invalidated_cb(void *data,
|
|
|
|
Eldbus_Proxy *proxy EINA_UNUSED,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
|
|
|
|
Eldbus_Proxy_Event_Property_Changed *event = (Eldbus_Proxy_Event_Property_Changed*)event_info;
|
|
|
|
|
|
|
|
efl_model_property_invalidated_notify(pd->obj, event->name);
|
|
|
|
}
|
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
static Eina_Array *
|
|
|
|
_eldbus_model_proxy_property_get_all_load(const Eldbus_Message *msg, Eldbus_Model_Proxy_Data *pd)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
|
|
|
Eldbus_Message_Iter *values = NULL;
|
|
|
|
Eldbus_Message_Iter *entry;
|
2016-04-29 15:39:37 -07:00
|
|
|
Eina_Array *changed_properties;
|
2019-02-13 10:46:31 -08:00
|
|
|
Eina_Stringshare *tmp = NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
const char *error_name, *error_text;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(msg, &error_name, &error_text))
|
|
|
|
{
|
|
|
|
ERR("%s: %s", error_name, error_text);
|
2016-04-29 15:39:37 -07:00
|
|
|
return NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(msg, "a{sv}", &values))
|
|
|
|
{
|
|
|
|
ERR("%s", "Error getting arguments.");
|
2016-04-29 15:39:37 -07:00
|
|
|
return NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
changed_properties = eina_array_new(1);
|
|
|
|
while (eldbus_message_iter_get_and_next(values, 'e', &entry))
|
|
|
|
{
|
|
|
|
const char *property;
|
|
|
|
Eldbus_Message_Iter *variant;
|
|
|
|
Eina_Value *struct_value;
|
|
|
|
Eina_Value *prop_value;
|
|
|
|
Eina_Value arg0;
|
|
|
|
Eina_Bool ret;
|
|
|
|
|
|
|
|
if (!eldbus_message_iter_arguments_get(entry, "sv", &property, &variant))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
struct_value = eldbus_message_iter_struct_like_to_eina_value(variant);
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!struct_value) goto on_error;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
ret = eina_value_struct_value_get(struct_value, "arg0", &arg0);
|
|
|
|
eina_value_free(struct_value);
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!ret) goto on_error;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
tmp = eina_stringshare_add(property);
|
|
|
|
prop_value = eina_hash_find(pd->properties, tmp);
|
|
|
|
if (!prop_value) goto on_error;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
ret = eina_value_copy(&arg0, prop_value);
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!ret) goto on_error;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
eina_value_flush(&arg0);
|
|
|
|
|
2019-02-13 10:46:31 -08:00
|
|
|
ret = eina_array_push(changed_properties, tmp);
|
2017-10-25 18:05:41 -07:00
|
|
|
if (!ret) goto on_error;
|
2019-02-13 10:46:31 -08:00
|
|
|
|
|
|
|
// Reset tmp to NULL to avoid double free.
|
|
|
|
tmp = NULL;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2016-04-20 13:07:53 -07:00
|
|
|
pd->is_loaded = EINA_TRUE;
|
2016-04-29 15:39:37 -07:00
|
|
|
return changed_properties;
|
|
|
|
|
|
|
|
on_error:
|
2019-02-13 10:46:31 -08:00
|
|
|
eina_stringshare_del(tmp);
|
|
|
|
while ((tmp = eina_array_pop(changed_properties)))
|
|
|
|
eina_stringshare_del(tmp);
|
2016-04-29 15:39:37 -07:00
|
|
|
eina_array_free(changed_properties);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_property_get_all_cb(void *data,
|
|
|
|
const Eldbus_Message *msg,
|
|
|
|
Eldbus_Pending *pending)
|
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Data *pd = (Eldbus_Model_Proxy_Data*)data;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Property_Promise* p;
|
2019-02-13 10:46:31 -08:00
|
|
|
Eina_Stringshare *sp;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_Array *properties;
|
|
|
|
Efl_Model_Property_Event evt;
|
2016-04-29 15:39:37 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
pd->pendings = eina_list_remove(pd->pendings, pending);
|
2016-04-20 13:07:53 -07:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
properties = _eldbus_model_proxy_property_get_all_load(msg, pd);
|
|
|
|
if (!properties)
|
2016-04-20 13:07:53 -07:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
EINA_LIST_FREE(pd->promises, p)
|
|
|
|
_eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_NOT_FOUND);
|
|
|
|
return ;
|
2016-04-20 13:07:53 -07:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
EINA_LIST_FREE(pd->promises, p)
|
|
|
|
_eldbus_model_proxy_promise_clean(p, EFL_MODEL_ERROR_READ_ONLY);
|
2016-04-20 13:07:53 -07:00
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
_eldbus_model_proxy_start_monitor(pd);
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
evt.changed_properties = properties;
|
|
|
|
efl_event_callback_call(pd->obj, EFL_MODEL_EVENT_PROPERTIES_CHANGED, &evt);
|
2019-02-13 10:46:31 -08:00
|
|
|
while ((sp = eina_array_pop(properties)))
|
|
|
|
eina_stringshare_del(sp);
|
2017-10-25 18:05:41 -07:00
|
|
|
eina_array_free(properties);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_property_set_load_cb(void *data,
|
2017-10-25 18:05:41 -07:00
|
|
|
const Eldbus_Message *msg,
|
|
|
|
Eldbus_Pending *pending)
|
2016-04-29 15:39:37 -07:00
|
|
|
{
|
|
|
|
Eldbus_Model_Proxy_Property_Set_Data *set_data = (Eldbus_Model_Proxy_Property_Set_Data *)data;
|
|
|
|
Eldbus_Model_Proxy_Data *pd = set_data->pd;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_Array *properties;
|
2019-02-13 10:46:31 -08:00
|
|
|
Eina_Stringshare *sp;
|
2016-04-29 15:39:37 -07:00
|
|
|
const char *signature;
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
pd->pendings = eina_list_remove(pd->pendings, pending);
|
|
|
|
|
2016-04-29 15:39:37 -07:00
|
|
|
signature = _eldbus_model_proxy_property_type_get(pd, set_data->property);
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
properties = _eldbus_model_proxy_property_get_all_load(msg, pd);
|
|
|
|
if (!signature || !properties)
|
2016-04-29 15:39:37 -07:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
eina_promise_reject(set_data->promise, EFL_MODEL_ERROR_UNKNOWN);
|
2019-02-13 10:46:31 -08:00
|
|
|
goto end;
|
2016-04-29 15:39:37 -07:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
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);
|
2019-03-15 09:14:18 -07:00
|
|
|
|
|
|
|
end:
|
|
|
|
if (!properties) return;
|
2019-02-13 10:46:31 -08:00
|
|
|
while ((sp = eina_array_pop(properties)))
|
|
|
|
eina_stringshare_del(sp);
|
|
|
|
eina_array_free(properties);
|
2016-04-29 15:39:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-09 08:20:14 -08:00
|
|
|
static void
|
|
|
|
_eldbus_model_proxy_property_set_cb(void *data,
|
|
|
|
const Eldbus_Message *msg,
|
|
|
|
Eldbus_Pending *pending)
|
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
Eldbus_Model_Proxy_Property_Set_Data *sd = (Eldbus_Model_Proxy_Property_Set_Data *)data;
|
|
|
|
Eldbus_Model_Proxy_Data *pd = sd->pd;
|
2015-01-09 08:20:14 -08:00
|
|
|
const char *error_name, *error_text;
|
2017-10-25 18:05:41 -07:00
|
|
|
Eina_Value *value;
|
2015-01-09 08:20:14 -08:00
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
pd->pendings = eina_list_remove(pd->pendings, pending);
|
2015-01-09 08:20:14 -08:00
|
|
|
|
|
|
|
if (eldbus_message_error_get(msg, &error_name, &error_text))
|
|
|
|
{
|
2016-04-29 15:39:37 -07:00
|
|
|
ERR("%s: %s", error_name, error_text);
|
2017-10-25 18:05:41 -07:00
|
|
|
eina_promise_reject(sd->promise, EFL_MODEL_ERROR_UNKNOWN);
|
2019-11-15 09:39:38 -08:00
|
|
|
return;
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
|
2017-10-25 18:05:41 -07:00
|
|
|
value = eina_hash_find(pd->properties, sd->property);
|
|
|
|
if (value)
|
2016-04-29 15:39:37 -07:00
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
efl_model_properties_changed(pd->obj, sd->property);
|
|
|
|
if (sd->promise)
|
|
|
|
eina_promise_resolve(sd->promise,
|
|
|
|
eina_value_reference_copy(value));
|
2016-04-29 15:39:37 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-25 18:05:41 -07:00
|
|
|
if (sd->promise)
|
|
|
|
eina_promise_reject(sd->promise,
|
|
|
|
EFL_MODEL_ERROR_NOT_FOUND);
|
2015-01-09 08:20:14 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2017-10-25 18:05:41 -07:00
|
|
|
_eldbus_model_proxy_property_type_get(Eldbus_Model_Proxy_Data *pd,
|
|
|
|
const char *property)
|
2015-01-09 08:20:14 -08:00
|
|
|
{
|
|
|
|
Eldbus_Introspection_Property *property_introspection =
|
|
|
|
eldbus_introspection_property_find(pd->interface->properties, property);
|
|
|
|
|
|
|
|
if (property_introspection == NULL)
|
|
|
|
{
|
|
|
|
WRN("Property not found: %s", property);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return property_introspection->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "eldbus_model_proxy.eo.c"
|