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:
José Roberto de Souza 2012-10-26 18:19:32 +00:00 committed by Lucas De Marchi
parent 45a5f7e5d5
commit c30124d90a
6 changed files with 297 additions and 23 deletions

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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))

View File

@ -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;
}
}
}