diff --git a/src/examples/eldbus/dbusmodel.c b/src/examples/eldbus/dbusmodel.c index 034fde63d2..47aecd369e 100644 --- a/src/examples/eldbus/dbusmodel.c +++ b/src/examples/eldbus/dbusmodel.c @@ -9,22 +9,26 @@ #include #include #include +#include -#define DEFAULT_BUS "org.freedesktop.DBus" +#define DEFAULT_BUS_NAME "org.freedesktop.DBus" #define DEFAULT_PATH "/" static int prop_count = 0; +static int retval = EXIT_SUCCESS; +static Eina_Bool quit_on_done = EINA_TRUE; static void -promise_then_prop_c(void* priv_obj, void* data) +future_properties_then(void* data, const Efl_Event *event) { - Eo* obj = priv_obj; + Eo* obj = data; + Efl_Future_Event_Success *future = event->info; Eina_Value * property_value; const Eina_Array *properties_list; Eina_Array_Iterator a_it; char *property, *prop_str; const char *name; - Eina_Iterator* it = data; + Eina_Iterator* it = future->value; name = eldbus_model_proxy_name_get(obj); properties_list = efl_model_properties_get(obj); @@ -43,108 +47,221 @@ promise_then_prop_c(void* priv_obj, void* data) prop_count--; if (prop_count == 0) - ecore_main_loop_quit(); + { + if (quit_on_done) + ecore_main_loop_quit(); + else + printf("monitoring events...\n"); + } } static void -error_cb(void* data EINA_UNUSED, Eina_Error error EINA_UNUSED) +error_cb(void* data EINA_UNUSED, const Efl_Event *event) { - printf(" ERROR\n"); + Efl_Future_Event_Failure *future = event->info; + printf(" ERROR: #%d '%s'\n", future->error, eina_error_msg_get(future->error)); ecore_main_loop_quit(); + retval = EXIT_FAILURE; } static void -promise_then_a(void* priv_obj EINA_UNUSED, void* data) +loop_children(Eina_Accessor *children) { - const Eina_Array *properties_list; - Eina_Array_Iterator a_it; - Eina_Promise **promises; - const char *name; - char *property; Eo* child; int i = 0; - Eina_Accessor* accessor = data; - EINA_ACCESSOR_FOREACH(accessor, i, child) + EINA_ACCESSOR_FOREACH(children, i, child) { - properties_list = efl_model_properties_get(child); - name = eldbus_model_proxy_name_get(child); - + const Eina_Array *properties_list = efl_model_properties_get(child); unsigned p_count = eina_array_count(properties_list); + const char *name = eldbus_model_proxy_name_get(child); if (p_count) { - promises = (Eina_Promise **)calloc(p_count + 1, sizeof(Eina_Promise *)); - promises[p_count] = NULL; - + Efl_Future **futures = calloc(p_count + 1, sizeof(Efl_Future *)); + Eina_Array_Iterator a_it; + const char *property; unsigned j = 0; + EINA_ARRAY_ITER_NEXT(properties_list, j, property, a_it) { - promises[j] = efl_model_property_get(child, property); + futures[j] = efl_model_property_get(child, property); } - eina_promise_then(eina_promise_all(eina_carray_iterator_new((void **)promises)), - &promise_then_prop_c, &error_cb, child); + efl_future_then(efl_future_iterator_all(eina_carray_iterator_new((void **)futures)), + &future_properties_then, &error_cb, NULL, child); prop_count++; + free(futures); + printf(" %2d: %s (loading %u properties asynchronously)\n", i, name, j); } else { - printf(" -> %s\n", name); + printf(" %2d: %s (no properties yet)\n", i, name); } } if (prop_count == 0) - ecore_main_loop_quit(); -} -static void -promise_then(void* obj EINA_UNUSED, void* data) -{ - Eina_Accessor *accessor; - unsigned int* count; - - Eina_Iterator* iterator = data; - - if (!eina_iterator_next(iterator, (void**)&accessor)) { - printf("bye\n"); + if (quit_on_done) + ecore_main_loop_quit(); + else + printf("monitoring events...\n"); + } +} + +static void +future_then(void* obj EINA_UNUSED, const Efl_Event *event) +{ + Efl_Future_Event_Success *future = event->info; + Eina_Accessor *values = future->value; + Eina_Accessor *children; + unsigned int *count; + + if (!eina_accessor_data_get(values, 0, (void**)&children)) + { + fprintf(stderr, "ERROR: missing future fulfillment value #0\n"); + retval = EXIT_FAILURE; ecore_main_loop_quit(); return; } - if(eina_iterator_next(iterator, (void **)&count)) + if (!eina_accessor_data_get(values, 1, (void**)&count)) { - printf("efl_model_loaded count %d\n", (int)*count); fflush(stdout); - printf("efl_model_loaded accessor %p\n", accessor); fflush(stdout); - - promise_then_a(NULL, accessor); + fprintf(stderr, "ERROR: missing future fulfillment value #1\n"); + retval = EXIT_FAILURE; + ecore_main_loop_quit(); + return; } + + printf("efl_model_loaded count %u\n", *count); + loop_children(children); } +static void +_on_properties_changed(void *data EINA_UNUSED, const Efl_Event *event) +{ + Efl_Model_Property_Event *ev = event->info; + Eina_Array_Iterator it; + const char *str; + unsigned int i; + + printf("Properties changed:\n"); + EINA_ARRAY_ITER_NEXT(ev->changed_properties, i, str, it) + printf("\t%s\n", str); + + printf("Properties invalidated:\n"); + EINA_ARRAY_ITER_NEXT(ev->invalidated_properties, i, str, it) + printf("\t%s\n", str); +} + +static void +_on_child_added(void *data EINA_UNUSED, const Efl_Event *event) +{ + Eo *child = event->info; + printf("Children Added: %p\n", child); +} + +static void +_on_child_removed(void *data EINA_UNUSED, const Efl_Event *event) +{ + Eo *child = event->info; + printf("Children Removed: %p\n", child); +} + +EFL_CALLBACKS_ARRAY_DEFINE(event_cbs, + { EFL_MODEL_EVENT_PROPERTIES_CHANGED, _on_properties_changed }, + { EFL_MODEL_EVENT_CHILD_ADDED, _on_child_added }, + { EFL_MODEL_EVENT_CHILD_REMOVED, _on_child_removed }); + +static const Ecore_Getopt options = { + "dbusmodel", /* program name */ + NULL, /* usage line */ + "1", /* version */ + "(C) 2016 Enlightenment Project", /* copyright */ + "BSD 2-Clause", /* license */ + /* long description, may be multiline and contain \n */ + "Example of Eldbus.Model.Object to fetch children and properties.\n", + EINA_FALSE, + { + ECORE_GETOPT_STORE_TRUE('s', "system", "connect to the system bus, not user session."), + ECORE_GETOPT_STORE_FALSE('w', "wait", "after done, wait for events (monitoring)"), + + ECORE_GETOPT_VERSION('V', "version"), + ECORE_GETOPT_COPYRIGHT('C', "copyright"), + ECORE_GETOPT_LICENSE('L', "license"), + ECORE_GETOPT_HELP('h', "help"), + + ECORE_GETOPT_STORE_METAVAR_STR(0, NULL, "The bus name to connect.", "bus_name"), + ECORE_GETOPT_STORE_METAVAR_STR(0, NULL, "The path to explore.", "path"), + + ECORE_GETOPT_SENTINEL + } +}; + int main(int argc, char **argv EINA_UNUSED) { - const char *bus, *path; + Eldbus_Connection_Type conn_type; + Eina_Bool is_system = EINA_FALSE; + char *bus_name = DEFAULT_BUS_NAME; + char *path = DEFAULT_PATH; + Eina_Bool quit_option = EINA_FALSE; + Ecore_Getopt_Value values[] = { + ECORE_GETOPT_VALUE_BOOL(is_system), + ECORE_GETOPT_VALUE_BOOL(quit_on_done), + + /* standard block to provide version, copyright, license and help */ + ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */ + ECORE_GETOPT_VALUE_BOOL(quit_option), /* -C/--copyright quits */ + ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */ + ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */ + + /* positional argument */ + ECORE_GETOPT_VALUE_STR(bus_name), + ECORE_GETOPT_VALUE_STR(path), + + ECORE_GETOPT_VALUE_NONE /* sentinel */ + }; + int args; Eo *root; ecore_init(); eldbus_init(); - bus = DEFAULT_BUS; - path = DEFAULT_PATH; + args = ecore_getopt_parse(&options, values, argc, argv); + if (args < 0) + { + fputs("ERROR: Could not parse command line options.\n", stderr); + retval = EXIT_FAILURE; + goto end; + } - if (argc > 1) bus = argv[1]; - if (argc > 2) path = argv[2]; + if (quit_option) goto end; - root = efl_add_ref(ELDBUS_MODEL_OBJECT_CLASS, NULL, eldbus_model_object_constructor(efl_added, ELDBUS_CONNECTION_TYPE_SESSION, NULL, EINA_FALSE, bus, path)); + args = ecore_getopt_parse_positional(&options, values, argc, argv, args); + if (args < 0) + { + fputs("ERROR: Could not parse positional arguments.\n", stderr); + retval = EXIT_FAILURE; + goto end; + } - Eina_Promise *promises[] = { NULL, NULL, NULL}; - promises[0] = efl_model_children_slice_get(root, 0, 0); - promises[1] = efl_model_children_count_get(root); + conn_type = (is_system ? + ELDBUS_CONNECTION_TYPE_SYSTEM : + ELDBUS_CONNECTION_TYPE_SESSION); - eina_promise_then(eina_promise_all(eina_carray_iterator_new((void **)promises)), - &promise_then, &error_cb, root); + root = efl_add_ref(ELDBUS_MODEL_OBJECT_CLASS, ecore_main_loop_get(), + eldbus_model_object_constructor(efl_added, conn_type, NULL, EINA_FALSE, bus_name, path), + efl_event_callback_array_add(efl_added, event_cbs(), NULL)); + + efl_future_then(efl_future_all(efl_model_children_slice_get(root, 0, 0), + efl_model_children_count_get(root)), + &future_then, &error_cb, NULL, root); ecore_main_loop_begin(); + efl_del(root); - efl_unref(root); + end: eldbus_shutdown(); + ecore_shutdown(); + return retval; }