forked from enlightenment/efl
edbus: Implementation of EDBUS_PROXY_EVENTS and edbus_proxy_properties_monitor
Patch by: José Roberto de Souza <zehortigoza@profusion.mobi> SVN revision: 78544
This commit is contained in:
parent
45a5f7e5d5
commit
c30124d90a
|
@ -179,6 +179,31 @@ on_receive_array(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_property_changed(void *data, EDBus_Proxy *proxy, void *event_info)
|
||||
{
|
||||
EDBus_Proxy_Event_Property_Changed *event = event_info;
|
||||
const char *name;
|
||||
const Eina_Value *value;
|
||||
printf("property changed\n");
|
||||
|
||||
name = event->name;
|
||||
value = event->value;
|
||||
|
||||
if (!strcmp(name, "text"))
|
||||
{
|
||||
const char *txt;
|
||||
eina_value_get(value, &txt);
|
||||
printf("[%s] = %s\n", name, txt);
|
||||
}
|
||||
else if (!strcmp(name, "int32"))
|
||||
{
|
||||
int num;
|
||||
eina_value_get(value, &num);
|
||||
printf("[%s] = %d\n", name, num);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
@ -271,11 +296,13 @@ main(void)
|
|||
-1 , "i", plus_one);
|
||||
|
||||
pending = edbus_proxy_property_get(test2_proxy, "Resp2", get_property_resp2, test2_proxy);
|
||||
edbus_proxy_event_callback_add(test2_proxy, EDBUS_PROXY_EVENT_PROPERTY_CHANGED, _property_changed, NULL);
|
||||
|
||||
ecore_timer_add(5, _timer1_cb, NULL);
|
||||
ecore_timer_add(20, _timer1_cb, NULL);
|
||||
|
||||
ecore_main_loop_begin();
|
||||
|
||||
edbus_proxy_event_callback_del(test2_proxy, EDBUS_PROXY_EVENT_PROPERTY_CHANGED, _property_changed, NULL);
|
||||
edbus_connection_unref(conn);
|
||||
|
||||
edbus_shutdown();
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#define PATH "/com/profusion/Test"
|
||||
#define IFACE "com.profusion.Test"
|
||||
|
||||
char *resp2;
|
||||
static char *resp2;
|
||||
static Ecore_Timer *timer;
|
||||
|
||||
static EDBus_Message *
|
||||
_receive_array(const EDBus_Service_Interface *iface, const EDBus_Message *msg)
|
||||
|
@ -331,11 +332,57 @@ static const EDBus_Method properties_methods[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static const EDBus_Signal properties_signals[] = {
|
||||
{ "PropertiesChanged",
|
||||
EDBUS_ARGS({"s", "interface"}, {"a{sv}", "data"}, {"as", "invalidate"}), 0
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static Eina_Bool _emmit_changed(void *data)
|
||||
{
|
||||
EDBus_Service_Interface *iface = data;
|
||||
EDBus_Message *sig = edbus_service_signal_new(iface, 0);
|
||||
EDBus_Message_Iter *main_iter, *array, *entry, *var, *invalidate;
|
||||
|
||||
main_iter = edbus_message_iter_get(sig);
|
||||
if (!edbus_message_iter_arguments_set(main_iter, "sa{sv}", IFACE, &array))
|
||||
{
|
||||
printf("Error setting arguments of signal");
|
||||
goto end;
|
||||
}
|
||||
|
||||
edbus_message_iter_arguments_set(array, "{sv}", &entry);
|
||||
edbus_message_iter_arguments_set(entry, "s", "text");
|
||||
var = edbus_message_iter_container_new(entry, 'v', "s");
|
||||
edbus_message_iter_arguments_set(var, "s", "lalala text");
|
||||
edbus_message_iter_container_close(entry, var);
|
||||
edbus_message_iter_container_close(array, entry);
|
||||
|
||||
edbus_message_iter_arguments_set(array, "{sv}", &entry);
|
||||
edbus_message_iter_arguments_set(entry, "s", "int32");
|
||||
var = edbus_message_iter_container_new(entry, 'v', "i");
|
||||
edbus_message_iter_arguments_set(var, "i", 35);
|
||||
edbus_message_iter_container_close(entry, var);
|
||||
edbus_message_iter_container_close(array, entry);
|
||||
|
||||
edbus_message_iter_container_close(main_iter, array);
|
||||
|
||||
edbus_message_iter_arguments_set(main_iter, "as", &invalidate);
|
||||
edbus_message_iter_container_close(main_iter, invalidate);
|
||||
|
||||
edbus_service_signal_send(iface, sig);
|
||||
end:
|
||||
edbus_message_unref(sig);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_request(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
|
||||
{
|
||||
EDBus_Connection *conn = data;
|
||||
unsigned int flag;
|
||||
EDBus_Service_Interface *piface;
|
||||
|
||||
resp2 = malloc(sizeof(char) * 5);
|
||||
strcpy(resp2, "test");
|
||||
|
@ -359,7 +406,9 @@ on_name_request(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
|
|||
}
|
||||
|
||||
edbus_service_interface_register(conn, PATH, IFACE, methods, NULL);
|
||||
edbus_service_interface_register(conn, PATH, EDBUS_FDO_INTERFACE_PROPERTIES, properties_methods, NULL);
|
||||
piface = edbus_service_interface_register(conn, PATH, EDBUS_FDO_INTERFACE_PROPERTIES,
|
||||
properties_methods, properties_signals);
|
||||
timer = ecore_timer_add(3, _emmit_changed, piface);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -377,6 +426,7 @@ main(void)
|
|||
ecore_main_loop_begin();
|
||||
|
||||
free(resp2);
|
||||
ecore_timer_del(timer);
|
||||
edbus_connection_unref(conn);
|
||||
|
||||
edbus_shutdown();
|
||||
|
|
|
@ -86,26 +86,13 @@ EAPI EDBus_Pending *edbus_object_introspect(EDBus_Object *obj, EDBus_Mess
|
|||
|
||||
/**
|
||||
* @defgroup EDBus_FDO_Properties org.freedesktop.DBus.Properties
|
||||
*
|
||||
* Whenever edbus_proxy_properties_monitor() is called on a
|
||||
* proxy to an object it will automatically listen for properties
|
||||
* changed on that interface, emitting events with
|
||||
* edbus_object_event_type being
|
||||
* #EDBUS_OBJECT_EVENT_PROPERTY_CHANGED and
|
||||
* #EDBUS_OBJECT_EVENT_PROPERTY_REMOVED, as well as
|
||||
* #EDBUS_PROXY_EVENT_PROPERTY_CHANGED and
|
||||
* #EDBUS_PROXY_EVENT_PROPERTY_REMOVED.
|
||||
*
|
||||
* One may manually query the properties
|
||||
* edbus_proxy_property_get() and edbus_proxy_property_get_all()
|
||||
* or listen for changes with
|
||||
* edbus_proxy_properties_changed_callback_add().
|
||||
*
|
||||
* To set property call edbus_proxy_property_set().
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
EAPI void edbus_proxy_properties_monitor(EDBus_Proxy *proxy);
|
||||
|
||||
/**
|
||||
* Enable or disable local cache of properties.
|
||||
*/
|
||||
EAPI void edbus_proxy_properties_monitor(EDBus_Proxy *proxy, Eina_Bool enable);
|
||||
|
||||
EAPI EDBus_Pending *edbus_proxy_property_get(EDBus_Proxy *proxy, const char *name, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 3);
|
||||
EAPI EDBus_Pending *edbus_proxy_property_set(EDBus_Proxy *proxy, const char *name, char type, const void *value, EDBus_Message_Cb cb, const void *data) EINA_ARG_NONNULL(1, 2, 4);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
static void _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Message_Iter *iter);
|
||||
static void _eina_value_struct_free(Eina_Value *value, Eina_Array *array);
|
||||
static Eina_Value *_message_iter_struct_to_eina_value(EDBus_Message_Iter *iter);
|
||||
|
||||
static const Eina_Value_Type *
|
||||
_dbus_type_to_eina_value_type(char type)
|
||||
|
@ -217,7 +216,7 @@ _message_iter_basic_array_to_eina_value(char type, Eina_Value *value, EDBus_Mess
|
|||
|
||||
#define ARG "arg%d"
|
||||
|
||||
static Eina_Value *
|
||||
Eina_Value *
|
||||
_message_iter_struct_to_eina_value(EDBus_Message_Iter *iter)
|
||||
{
|
||||
int type;
|
||||
|
|
|
@ -73,6 +73,7 @@ void edbus_connection_name_owner_monitor(EDBus_Connection *con
|
|||
EDBus_Pending *_edbus_connection_send(EDBus_Connection *conn, EDBus_Message *msg, EDBus_Message_Cb cb, const void *cb_data, double timeout);
|
||||
|
||||
EDBus_Message_Iter *edbus_message_iter_sub_iter_get(EDBus_Message_Iter *iter);
|
||||
Eina_Value *_message_iter_struct_to_eina_value(EDBus_Message_Iter *iter);
|
||||
|
||||
#ifdef HAVE_VA_LIST_AS_ARRAY
|
||||
#define MAKE_PTR_FROM_VA_LIST(arg) ((va_list *)(arg))
|
||||
|
|
|
@ -30,6 +30,9 @@ struct _EDBus_Proxy
|
|||
Eina_List *handlers;
|
||||
Eina_Inlist *cbs_free;
|
||||
EDBus_Proxy_Context_Event event_handlers[EDBUS_PROXY_EVENT_LAST];
|
||||
Eina_Hash *props;
|
||||
EDBus_Signal_Handler *properties_changed;
|
||||
Eina_Bool monitor_enabled:1;
|
||||
};
|
||||
|
||||
#define EDBUS_PROXY_CHECK(proxy) \
|
||||
|
@ -85,6 +88,7 @@ edbus_proxy_shutdown(void)
|
|||
static void _edbus_proxy_event_callback_call(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, const void *event_info);
|
||||
static void _edbus_proxy_context_event_cb_del(EDBus_Proxy_Context_Event *ce, EDBus_Proxy_Context_Event_Cb *ctx);
|
||||
static void _on_signal_handler_free(void *data, const void *dead_pointer);
|
||||
static EDBus_Proxy *get_properties_proxy(EDBus_Proxy *proxy);
|
||||
|
||||
static void
|
||||
_edbus_proxy_call_del(EDBus_Proxy *proxy)
|
||||
|
@ -139,6 +143,10 @@ _edbus_proxy_clear(EDBus_Proxy *proxy)
|
|||
}
|
||||
|
||||
edbus_cbs_free_dispatch(&(proxy->cbs_free), proxy);
|
||||
if (proxy->props)
|
||||
eina_hash_free(proxy->props);
|
||||
if (proxy->properties_changed)
|
||||
edbus_signal_handler_del(proxy->properties_changed);
|
||||
proxy->refcount = 0;
|
||||
}
|
||||
|
||||
|
@ -267,6 +275,87 @@ edbus_proxy_cb_free_del(EDBus_Proxy *proxy, EDBus_Free_Cb cb, const void *data)
|
|||
proxy->cbs_free = edbus_cbs_free_del(proxy->cbs_free, cb, data);
|
||||
}
|
||||
|
||||
static void
|
||||
_property_changed_iter(void *data, const void *key, EDBus_Message_Iter *var)
|
||||
{
|
||||
EDBus_Proxy *proxy = data;
|
||||
const char *skey = key;
|
||||
Eina_Value *st_value, stack_value, *value;
|
||||
EDBus_Proxy_Event_Property_Changed event;
|
||||
|
||||
st_value = _message_iter_struct_to_eina_value(var);
|
||||
eina_value_struct_value_get(st_value, "arg0", &stack_value);
|
||||
|
||||
value = eina_hash_find(proxy->props, skey);
|
||||
if (value)
|
||||
{
|
||||
eina_value_flush(value);
|
||||
eina_value_copy(&stack_value, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = calloc(1, sizeof(Eina_Value));
|
||||
eina_value_copy(&stack_value, value);
|
||||
eina_hash_add(proxy->props, skey, value);
|
||||
}
|
||||
|
||||
event.name = skey;
|
||||
event.value = value;
|
||||
_edbus_proxy_event_callback_call(proxy, EDBUS_PROXY_EVENT_PROPERTY_CHANGED,
|
||||
&event);
|
||||
|
||||
edbus_message_to_eina_value_free(st_value);
|
||||
//TODO if value have any STRUCT at this point it will not be accessible
|
||||
eina_value_flush(&stack_value);
|
||||
}
|
||||
|
||||
static void
|
||||
_properties_changed(void *data, const EDBus_Message *msg)
|
||||
{
|
||||
EDBus_Proxy *proxy = data;
|
||||
EDBus_Message_Iter *array, *invalidate;
|
||||
const char *iface;
|
||||
const char *invalidate_prop;
|
||||
|
||||
if (!edbus_message_arguments_get(msg, "sa{sv}as", &iface, &array, &invalidate))
|
||||
{
|
||||
ERR("Error getting data from properties changed signal.");
|
||||
return;
|
||||
}
|
||||
if (proxy->props)
|
||||
edbus_message_iter_dict_iterate(array, "sv", _property_changed_iter,
|
||||
proxy);
|
||||
|
||||
while (edbus_message_iter_get_and_next(invalidate, 's', &invalidate_prop))
|
||||
{
|
||||
EDBus_Proxy_Event_Property_Removed event;
|
||||
event.interface = proxy->interface;
|
||||
event.name = invalidate_prop;
|
||||
event.proxy = proxy;
|
||||
if (proxy->props)
|
||||
eina_hash_del(proxy->props, event.name, NULL);
|
||||
_edbus_proxy_event_callback_call(proxy, EDBUS_PROXY_EVENT_PROPERTY_REMOVED,
|
||||
&event);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_props_cache_free(void *data)
|
||||
{
|
||||
Eina_Value *value = data;
|
||||
eina_value_free(value);
|
||||
}
|
||||
|
||||
static void
|
||||
_properties_changed_add(EDBus_Proxy *proxy)
|
||||
{
|
||||
proxy->properties_changed =
|
||||
edbus_proxy_signal_handler_add(get_properties_proxy(proxy),
|
||||
"PropertiesChanged", _properties_changed, proxy);
|
||||
edbus_signal_handler_match_extra_set(proxy->properties_changed, "arg0",
|
||||
proxy->interface, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
edbus_proxy_event_callback_add(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type, EDBus_Proxy_Event_Cb cb, const void *cb_data)
|
||||
{
|
||||
|
@ -285,6 +374,19 @@ edbus_proxy_event_callback_add(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type,
|
|||
ctx->cb_data = cb_data;
|
||||
|
||||
ce->list = eina_inlist_append(ce->list, EINA_INLIST_GET(ctx));
|
||||
|
||||
if (type == EDBUS_PROXY_EVENT_PROPERTY_CHANGED)
|
||||
{
|
||||
if (proxy->properties_changed) return;
|
||||
if (!proxy->props)
|
||||
proxy->props = eina_hash_string_superfast_new(_props_cache_free);
|
||||
_properties_changed_add(proxy);
|
||||
}
|
||||
else if (type == EDBUS_PROXY_EVENT_PROPERTY_REMOVED)
|
||||
{
|
||||
if (proxy->properties_changed) return;
|
||||
_properties_changed_add(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -326,6 +428,36 @@ edbus_proxy_event_callback_del(EDBus_Proxy *proxy, EDBus_Proxy_Event_Type type,
|
|||
}
|
||||
|
||||
_edbus_proxy_context_event_cb_del(ce, found);
|
||||
|
||||
if (type == EDBUS_PROXY_EVENT_PROPERTY_CHANGED)
|
||||
{
|
||||
EDBus_Proxy_Context_Event *ce_prop_remove;
|
||||
ce_prop_remove = proxy->event_handlers +
|
||||
EDBUS_PROXY_EVENT_PROPERTY_REMOVED;
|
||||
if (!ce->list && !proxy->monitor_enabled)
|
||||
{
|
||||
eina_hash_free(proxy->props);
|
||||
proxy->props = NULL;
|
||||
}
|
||||
|
||||
if (!ce_prop_remove->list && !ce->list && !proxy->monitor_enabled)
|
||||
{
|
||||
edbus_signal_handler_unref(proxy->properties_changed);
|
||||
proxy->properties_changed = NULL;
|
||||
}
|
||||
}
|
||||
else if (type == EDBUS_PROXY_EVENT_PROPERTY_REMOVED)
|
||||
{
|
||||
EDBus_Proxy_Context_Event *ce_prop_changed;
|
||||
ce_prop_changed = proxy->event_handlers +
|
||||
EDBUS_PROXY_EVENT_PROPERTY_CHANGED;
|
||||
|
||||
if (!ce_prop_changed->list && !ce->list && !proxy->monitor_enabled)
|
||||
{
|
||||
edbus_signal_handler_unref(proxy->properties_changed);
|
||||
proxy->properties_changed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -543,3 +675,81 @@ edbus_proxy_property_get_all(EDBus_Proxy *proxy, EDBus_Message_Cb cb, const void
|
|||
return edbus_proxy_call(get_properties_proxy(proxy), "GetAll", cb, data, -1,
|
||||
"s", proxy->interface);
|
||||
}
|
||||
|
||||
static void
|
||||
_property_iter(void *data, const void *key, EDBus_Message_Iter *var)
|
||||
{
|
||||
EDBus_Proxy *proxy = data;
|
||||
const char *skey = key;
|
||||
Eina_Value *st_value, stack_value, *value;
|
||||
|
||||
st_value = _message_iter_struct_to_eina_value(var);
|
||||
eina_value_struct_value_get(st_value, "arg0", &stack_value);
|
||||
|
||||
value = eina_hash_find(proxy->props, skey);
|
||||
if (value)
|
||||
{
|
||||
eina_value_flush(value);
|
||||
eina_value_copy(&stack_value, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = calloc(1, sizeof(Eina_Value));
|
||||
eina_value_copy(&stack_value, value);
|
||||
eina_hash_add(proxy->props, skey, value);
|
||||
}
|
||||
|
||||
edbus_message_to_eina_value_free(st_value);
|
||||
eina_value_flush(&stack_value);
|
||||
}
|
||||
|
||||
static void
|
||||
_props_get_all(void *data, const EDBus_Message *msg, EDBus_Pending *pending)
|
||||
{
|
||||
EDBus_Proxy *proxy = data;
|
||||
EDBus_Message_Iter *dict;
|
||||
|
||||
if (!edbus_message_arguments_get(msg, "a{sv}", &dict))
|
||||
{
|
||||
ERR("Error getting data from properties getAll.");
|
||||
return;
|
||||
}
|
||||
edbus_message_iter_dict_iterate(dict, "sv", _property_iter, proxy);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
edbus_proxy_properties_monitor(EDBus_Proxy *proxy, Eina_Bool enable)
|
||||
{
|
||||
EDBUS_PROXY_CHECK(proxy);
|
||||
if (proxy->monitor_enabled == enable)
|
||||
return;
|
||||
|
||||
proxy->monitor_enabled = enable;
|
||||
if (enable)
|
||||
{
|
||||
if (!proxy->props)
|
||||
proxy->props = eina_hash_string_superfast_new(_props_cache_free);
|
||||
edbus_proxy_property_get_all(proxy, _props_get_all, proxy);
|
||||
|
||||
if (proxy->properties_changed)
|
||||
return;
|
||||
_properties_changed_add(proxy);
|
||||
}
|
||||
else
|
||||
{
|
||||
EDBus_Proxy_Context_Event *ce_prop_changed, *ce_prop_removed;
|
||||
ce_prop_changed = proxy->event_handlers + EDBUS_PROXY_EVENT_PROPERTY_CHANGED;
|
||||
ce_prop_removed = proxy->event_handlers + EDBUS_PROXY_EVENT_PROPERTY_REMOVED;
|
||||
|
||||
if (!ce_prop_changed->list)
|
||||
{
|
||||
eina_hash_free(proxy->props);
|
||||
proxy->props = NULL;
|
||||
}
|
||||
if (!ce_prop_changed->list && !ce_prop_removed->list)
|
||||
{
|
||||
edbus_signal_handler_unref(proxy->properties_changed);
|
||||
proxy->properties_changed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue