summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Stanislawski <lukasz.stanislawski@gmail.com>2017-12-14 21:01:21 +0100
committerLukasz Stanislawski <lukasz.stanislawski@gmail.com>2017-12-17 18:16:14 +0100
commitb7a4c27e3655076889a5d142e7bdeb83435225fd (patch)
tree0cd1edde2f9280ff896d1fc585e7eafd6cc6a77e
parent453361cac12d587cedb9854a0747b75a598e160e (diff)
downloadefl-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.am2
-rw-r--r--src/examples/elementary/Makefile.am7
-rw-r--r--src/examples/elementary/bus_watcher.c52
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/elm_bus_watcher.c172
-rw-r--r--src/lib/elementary/elm_bus_watcher.eo70
-rw-r--r--src/lib/elementary/elm_bus_watcher.h8
-rw-r--r--src/lib/elementary/elm_bus_watcher_private.x71
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