diff options
author | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-14 21:01:21 +0100 |
---|---|---|
committer | Lukasz Stanislawski <lukasz.stanislawski@gmail.com> | 2017-12-17 18:16:14 +0100 |
commit | b7a4c27e3655076889a5d142e7bdeb83435225fd (patch) | |
tree | 0cd1edde2f9280ff896d1fc585e7eafd6cc6a77e | |
parent | 453361cac12d587cedb9854a0747b75a598e160e (diff) | |
download | efl-b7a4c27e3655076889a5d142e7bdeb83435225fd.tar.gz |
elm: implement elm_bus_watcher class
Summary:
Bus watcher will be used for monitoring dbus services.
Change-Id: Id28e43ba43caa9c3290d462d807acde710fce7d6
Subscribers: cedric, jpeg
Differential Revision: https://phab.enlightenment.org/D5560
-rw-r--r-- | src/Makefile_Elementary.am | 2 | ||||
-rw-r--r-- | src/examples/elementary/Makefile.am | 7 | ||||
-rw-r--r-- | src/examples/elementary/bus_watcher.c | 52 | ||||
-rw-r--r-- | src/lib/elementary/Elementary.h | 1 | ||||
-rw-r--r-- | src/lib/elementary/elm_bus_watcher.c | 172 | ||||
-rw-r--r-- | src/lib/elementary/elm_bus_watcher.eo | 70 | ||||
-rw-r--r-- | src/lib/elementary/elm_bus_watcher.h | 8 | ||||
-rw-r--r-- | src/lib/elementary/elm_bus_watcher_private.x | 71 |
8 files changed, 381 insertions, 2 deletions
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index 6e4b3bee82..cb283e350d 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -93,6 +93,7 @@ elm_public_eolian_files = \ lib/elementary/efl_access_window.eo \ lib/elementary/efl_config_global.eo \ lib/elementary/elm_code_widget.eo \ + lib/elementary/elm_bus_watcher.eo \ $(NULL) # More public files -- FIXME @@ -747,6 +748,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/efl_ui_list_precise_layouter.c \ lib/elementary/efl_ui_list_segarray.c \ lib/elementary/efl_ui_layout_factory.c \ + lib/elementary/elm_bus_watcher.c \ $(NULL) diff --git a/src/examples/elementary/Makefile.am b/src/examples/elementary/Makefile.am index 320d333125..89bbc39d90 100644 --- a/src/examples/elementary/Makefile.am +++ b/src/examples/elementary/Makefile.am @@ -67,7 +67,8 @@ $(top_builddir)/src/lib/embryo/libembryo.la \ $(top_builddir)/src/lib/edje/libedje.la \ $(top_builddir)/src/lib/elementary/libelementary.la \ $(top_builddir)/src/lib/ethumb_client/libethumb_client.la \ -$(top_builddir)/src/lib/elocation/libelocation.la +$(top_builddir)/src/lib/elocation/libelocation.la \ +$(top_builddir)/src/lib/eldbus/libeldbus.la SRCS = \ actionslider_example_01.c \ @@ -184,6 +185,7 @@ efl_thread_win32_4.c \ efl_ui_list_example_1.c \ efl_ui_list_example_2.c \ efl_ui_list_example_3.c +bus_watcher.c SRCS += \ bg_cxx_example_01.cc \ @@ -376,7 +378,8 @@ efl_thread_5 \ efl_thread_6 \ efl_ui_list_example_1 \ efl_ui_list_example_2 \ -efl_ui_list_example_3 +efl_ui_list_example_3 \ +bus_watcher #benchmark3d #sphere-hunter diff --git a/src/examples/elementary/bus_watcher.c b/src/examples/elementary/bus_watcher.c new file mode 100644 index 0000000000..3897b49193 --- /dev/null +++ b/src/examples/elementary/bus_watcher.c @@ -0,0 +1,52 @@ +#define EFL_EO_API_SUPPORT +#define EFL_BETA_API_SUPPORT + +#include <Elementary.h> +#include <stdio.h> + +static void _cb(void *data EINA_UNUSED, const Efl_Event *event) +{ + Elm_Bus_Watcher_Service_Change_Info *info = event->info; + printf("Registered %s by %s\n", info->service_name, info->new_id); +} + +static void _cb2(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) +{ + Elm_Bus_Watcher_Service_Change_Info *info = event->info; + printf("Unregistered %s by %s\n", info->service_name, info->old_id); +} + +static void parse_args(Elm_Bus_Watcher *watcher, int argc, char **argv) +{ + int i; + if (argc < 2) + { + fprintf(stderr, "Invalid usage:\n%s <dbus-service-name>\n", argv[0]); + exit(1); + } + for (i = 1; i < argc; ++i) + { + elm_bus_watcher_service_add(watcher, argv[i]); + elm_bus_watcher_service_add(watcher, argv[i]); + } +} + +EAPI_MAIN int +elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + Elm_Bus_Watcher *watcher = efl_add(ELM_BUS_WATCHER_CLASS, NULL); + Eldbus_Connection *conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); + + parse_args(watcher, argc, argv); + + elm_bus_watcher_connection_set(watcher, conn); + efl_event_callback_add(watcher, ELM_BUS_WATCHER_EVENT_REGISTERED, _cb, watcher); + efl_event_callback_add(watcher, ELM_BUS_WATCHER_EVENT_UNREGISTERED, _cb2, watcher); + eldbus_connection_unref(conn); + + elm_run(); + efl_unref(watcher); + + return 0; +} +ELM_MAIN() diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index e404d6b3ab..d90c812e8c 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -322,6 +322,7 @@ EAPI extern Elm_Version *elm_version; # include <efl_ui_list_relayout.eo.h> # include <efl_ui_list.eo.h> # include <efl_ui_list_pan.eo.h> +# include <elm_bus_watcher.eo.h> #endif /* include deprecated calls last of all */ diff --git a/src/lib/elementary/elm_bus_watcher.c b/src/lib/elementary/elm_bus_watcher.c new file mode 100644 index 0000000000..cb6282f7f9 --- /dev/null +++ b/src/lib/elementary/elm_bus_watcher.c @@ -0,0 +1,172 @@ +#ifdef HAVE_CONFIG_H + #include "elementary_config.h" +#endif + +#define ELM_BUS_WATCHER_PROTECTED + +#include <Elementary.h> +#include "elm_widget.h" +#include "elm_priv.h" + +#include "elm_bus_watcher.eo.h" +#include "elm_bus_watcher_private.x" + +static Eina_Bool _bus_watcher_service_unregister_callback(const void *container, void *data, void *gdata); +static Eina_Bool _bus_watcher_service_register_callback(const void *container, void *data, void *gdata); + +typedef struct _Elm_Bus_Watcher_Data +{ + Eina_Array *service_names; + Eldbus_Connection *connection; +} Elm_Bus_Watcher_Data; + +EOLIAN static Eo* +_elm_bus_watcher_efl_object_constructor(Eo *obj, Elm_Bus_Watcher_Data *pd) +{ + obj = efl_constructor(efl_super(obj, ELM_BUS_WATCHER_CLASS)); + pd->service_names = eina_array_new(2); // make step small since in most cases watchers will have 1-2 names. + return obj; +} + +EOLIAN static void +_elm_bus_watcher_efl_object_destructor(Eo *obj, Elm_Bus_Watcher_Data *pd) +{ + elm_bus_watcher_connection_set(obj, NULL); + _eina_array_strings_clear(pd->service_names); + eina_array_free(pd->service_names); + + efl_destructor(efl_super(obj, ELM_BUS_WATCHER_CLASS)); +} + +static void +_elm_atspi_bus_watcher_name_owner_changed_callback(void *data, const char *bus, const char *old_id, const char *new_id) +{ + Elm_Bus_Watcher *watcher = data; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + Elm_Bus_Watcher_Owner_Change_Info info = { .service_name = bus, .old_id = old_id, .new_id = new_id }; + + if (!_eina_array_string_contains(pd->service_names, bus)) return; + + /** + Dbus deamon in case when service gets unregisted sends NameChanged signal with "newid" + parameter set to empty string "". In case of service registration "oldid" is empty string. + */ + if (!new_id || !strcmp(new_id, "")) + { + elm_bus_watcher_on_unregistered(watcher, bus); + efl_event_callback_call(watcher, ELM_BUS_WATCHER_EVENT_UNREGISTERED, (void*)bus); + } + else if (!old_id || !strcmp(old_id, "")) + { + elm_bus_watcher_on_registered(watcher, bus); + efl_event_callback_call(watcher, ELM_BUS_WATCHER_EVENT_REGISTERED, (void*)bus); + } + else + { + elm_bus_watcher_on_owner_changed(watcher, bus, old_id, new_id); + efl_event_callback_call(watcher, ELM_BUS_WATCHER_EVENT_OWNER_CHANGED, &info); + } +} + +static void +_elm_bus_watcher_dbus_setup(Eo *obj, Eldbus_Connection *conn, const char *service_name) +{ + eldbus_name_owner_changed_callback_add(conn, service_name, _elm_atspi_bus_watcher_name_owner_changed_callback, obj, EINA_TRUE); +} + +static void +_elm_bus_watcher_dbus_teardown(Eo *obj, Eldbus_Connection *conn, const char *service_name) +{ + eldbus_name_owner_changed_callback_del(conn, service_name, _elm_atspi_bus_watcher_name_owner_changed_callback, obj); +} + +EOLIAN static void +_elm_bus_watcher_service_add(Eo *obj, Elm_Bus_Watcher_Data *pd, const char *service) +{ + if (!service || _eina_array_string_contains(pd->service_names, service)) + return; + + _eina_array_string_push(pd->service_names, service); + if (pd->connection) _elm_bus_watcher_dbus_setup(obj, pd->connection, service); +} + +EOLIAN static void +_elm_bus_watcher_service_remove(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd, const char *service) +{ + if (!_eina_array_string_contains(pd->service_names, service)) + return; + + _eina_array_string_remove(pd->service_names, service); + if (pd->connection) _elm_bus_watcher_dbus_teardown(obj, pd->connection, service); +} + +static Eina_Bool +_bus_watcher_service_register_callback(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Elm_Bus_Watcher *watcher = gdata; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + const char *service_name = data; + + _elm_bus_watcher_dbus_setup(watcher, pd->connection, service_name); + return EINA_TRUE; +} + +static Eina_Bool +_bus_watcher_service_unregister_callback(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Elm_Bus_Watcher *watcher = gdata; + Elm_Bus_Watcher_Data *pd = efl_data_scope_get(watcher, ELM_BUS_WATCHER_CLASS); + const char *service_name = data; + + _elm_bus_watcher_dbus_teardown(watcher, pd->connection, service_name); + return EINA_TRUE; +} + +EOLIAN static void +_elm_bus_watcher_connection_set(Eo *obj, Elm_Bus_Watcher_Data *pd, Eldbus_Connection *conn) +{ + if (pd->connection) + { + eina_array_foreach(pd->service_names, _bus_watcher_service_unregister_callback, obj); + eldbus_connection_unref(pd->connection); + pd->connection = NULL; + } + if (conn) + { + pd->connection = eldbus_connection_ref(conn); + eina_array_foreach(pd->service_names, _bus_watcher_service_register_callback, obj); + } +} + +EOLIAN static Eldbus_Connection* +_elm_bus_watcher_connection_get(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd) +{ + return pd->connection; +} + +EOLIAN static Eina_Iterator* +_elm_bus_watcher_services_get(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd) +{ + return eina_array_iterator_new(pd->service_names); +} + +EOLIAN static void +_elm_bus_watcher_on_registered(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd EINA_UNUSED, + const char *service EINA_UNUSED) +{ +} + +EOLIAN static void +_elm_bus_watcher_on_unregistered(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd EINA_UNUSED, + const char *service EINA_UNUSED) +{ +} + +EOLIAN static void +_elm_bus_watcher_on_owner_changed(Eo *obj EINA_UNUSED, Elm_Bus_Watcher_Data *pd EINA_UNUSED, + const char *service EINA_UNUSED, const char *old_id EINA_UNUSED, + const char *new_id EINA_UNUSED) +{ +} + +#include "elm_bus_watcher.eo.c" diff --git a/src/lib/elementary/elm_bus_watcher.eo b/src/lib/elementary/elm_bus_watcher.eo new file mode 100644 index 0000000000..f37663af5c --- /dev/null +++ b/src/lib/elementary/elm_bus_watcher.eo @@ -0,0 +1,70 @@ +import eldbus_types; + +struct Elm.Bus.Watcher.Owner.Change.Info +{ + service_name: string; + old_id: string; + new_id: string; +} + +class Elm.Bus.Watcher (Efl.Object) +{ + methods { + service_add { + params { + @in bus: string; + } + } + service_remove { + params { + @in bus: string; + } + } + @property services { + get { + } + values { + services: iterator<string>; + } + } + @property connection { + get { + } + set { + } + values { + conn: ptr(Eldbus.Connection); + } + } + on_registered @protected { + params { + @in bus_name: string; + } + } + on_unregistered @protected { + params { + @in bus_name: string; + } + } + on_owner_changed @protected { + params { + @in bus_name: string; + @in old_id: string; + @in new_id: string; + } + } + } + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } + constructors { + .connection; + } + events { + registered: string; + unregistered: string; + owner,changed : Elm.Bus.Watcher.Owner.Change.Info; + } +} + diff --git a/src/lib/elementary/elm_bus_watcher.h b/src/lib/elementary/elm_bus_watcher.h new file mode 100644 index 0000000000..329543cfb2 --- /dev/null +++ b/src/lib/elementary/elm_bus_watcher.h @@ -0,0 +1,8 @@ +#ifndef ELM_BUS_WATCHER_H +#define ELM_BUS_WATCHER_H + +#ifdef EFL_EO_API_SUPPORT +#include "elm_bus_watcher.eo.h" +#endif + +#endif diff --git a/src/lib/elementary/elm_bus_watcher_private.x b/src/lib/elementary/elm_bus_watcher_private.x new file mode 100644 index 0000000000..a3f297e805 --- /dev/null +++ b/src/lib/elementary/elm_bus_watcher_private.x @@ -0,0 +1,71 @@ +#include <Eina.h> + +/** + @brief Helpers for manipulating eina_array of stringshared strings. +*/ + +typedef struct _Eina_Array_Foreach_Closure_Data +{ + const char *searched_string; + Eina_Bool *return_value; +} Eina_Array_Foreach_Closure_Data; + +static void +_eina_array_string_push(Eina_Array *array, const char *string) +{ + EINA_SAFETY_ON_NULL_RETURN(string); + eina_array_push(array, eina_stringshare_add(string)); +} + +static Eina_Bool +_eina_stringshare_foreach(const void *container EINA_UNUSED, void *data, void *gdata) +{ + Eina_Array_Foreach_Closure_Data *closure = gdata; + const char *str = data; + + if (str && closure->searched_string && !strcmp(str, closure->searched_string)) + *closure->return_value = EINA_TRUE; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_array_string_contains(Eina_Array *array, const char *string) +{ + Eina_Bool found = EINA_FALSE; + Eina_Array_Foreach_Closure_Data closure = { .searched_string = string, .return_value = &found }; + return eina_array_foreach(array, _eina_stringshare_foreach, &closure) && found; +} + +static Eina_Bool +_eina_stringshare_remove(void *data, void *gdata) +{ + const char *string = data; + const char *string_to_remove = gdata; + + if (string && string_to_remove && !strcmp(string, string_to_remove)) + return EINA_FALSE; + + return EINA_TRUE; +} + +static Eina_Bool +_eina_array_string_remove(Eina_Array *array, const char *string) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE); + return eina_array_remove(array, _eina_stringshare_remove, (void*)string); +} + +static Eina_Bool +_eina_stringshare_del_stringshare(const void *container EINA_UNUSED, void *data, void *gdata EINA_UNUSED) +{ + const char *string = data; + eina_stringshare_del(string); + return EINA_TRUE; +} + +static void +_eina_array_strings_clear(Eina_Array *array) +{ + eina_array_foreach(array, _eina_stringshare_del_stringshare, NULL); +}
\ No newline at end of file |