cedric pushed a commit to branch master.

http://git.enlightenment.org/core/elementary.git/commit/?id=34d2c8e1250c21e06593efba67eeefc97a216d98

commit 34d2c8e1250c21e06593efba67eeefc97a216d98
Author: Jean Guyomarc'h <jean.guyoma...@gmail.com>
Date:   Mon Jan 4 11:49:11 2016 -0800

    sys_notify: support several notification servers
    
    Summary:
    An Eo class Elm.Sys_Notify acts as a manager of notification
    servers. A manager registers and unregisters notification servers.
    
    Notification servers implement the Elm.Sys_Notify_Interface
    which allows to send and close notifications.
    
    Currently, only the DBus server is implemented (legacy code).
    
    Even though there are many changes in the code, there should
    be no API nor ABI breaks.
    
    Reviewers: naguirre, seoz, cedric
    
    Reviewed By: cedric
    
    Differential Revision: https://phab.enlightenment.org/D3172
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 src/lib/Makefile.am                                |   7 +
 src/lib/elm_sys_notify.c                           | 513 +++++++++------------
 src/lib/elm_sys_notify.eo                          |  90 ++++
 src/lib/elm_sys_notify.h                           |  92 ++--
 .../{elm_sys_notify.c => elm_sys_notify_dbus.c}    | 107 +++--
 src/lib/elm_sys_notify_dbus.eo                     |  14 +
 src/lib/elm_sys_notify_interface.c                 |   9 +
 src/lib/elm_sys_notify_interface.eo                |  66 +++
 8 files changed, 493 insertions(+), 405 deletions(-)

diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 424095e..20f6521 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -348,6 +348,8 @@ elm_systray_eo.h \
 elm_systray_common.h \
 elm_systray_watcher.h \
 elm_sys_notify.h \
+elm_sys_notify.eo.h \
+elm_sys_notify_dbus.eo.h \
 elm_table.h \
 elm_table_eo.h \
 elm_table_legacy.h \
@@ -477,7 +479,9 @@ elm_spinner.c \
 elm_store.c \
 elm_systray.c \
 elm_systray_watcher.c \
+elm_sys_notify_interface.c \
 elm_sys_notify.c \
+elm_sys_notify_dbus.c \
 elm_table.c \
 elm_theme.c \
 elm_thumb.c \
@@ -594,6 +598,9 @@ elm_separator.eo \
 elm_slider.eo \
 elm_slideshow.eo \
 elm_spinner.eo \
+elm_sys_notify_interface.eo \
+elm_sys_notify.eo \
+elm_sys_notify_dbus.eo \
 elm_systray.eo \
 elm_table.eo \
 elm_thumb.eo \
diff --git a/src/lib/elm_sys_notify.c b/src/lib/elm_sys_notify.c
index 23c936f..87536b8 100644
--- a/src/lib/elm_sys_notify.c
+++ b/src/lib/elm_sys_notify.c
@@ -6,372 +6,291 @@
 
 #include "elm_priv.h"
 
-#define OBJ       "/org/freedesktop/Notifications"
-#define BUS       "org.freedesktop.Notifications"
-#define INTERFACE "org.freedesktop.Notifications"
+#include "elm_sys_notify_dbus.eo.h"
+#include "elm_sys_notify_dbus.eo.legacy.h"
+
+#define MY_CLASS ELM_SYS_NOTIFY_CLASS
+
+#define MY_CLASS_NAME        "Elm_Sys_Notify"
+#define MY_CLASS_NAME_LEGACY "elm_sys_notify"
 
 EAPI int ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = 0;
 EAPI int ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED      = 0;
 
-static Eina_Bool _elm_need_sys_notify = EINA_FALSE;
+typedef const Eo_Class *(*Class_Get_Func)(void);
 
-static Eldbus_Connection *_elm_sysnotif_conn  = NULL;
-static Eldbus_Object     *_elm_sysnotif_obj   = NULL;
-static Eldbus_Proxy      *_elm_sysnotif_proxy = NULL;
+static Elm_Sys_Notify *_singleton = NULL;
 
-static Eina_Bool _has_markup = EINA_FALSE;
+/*
+ * Registration of notification servers is done UNIQUELY
+ * in the two structures below.
+ *   1) ALWAYS add a SRV_XXX before __SRV_LAST
+ *   2) copy the #if ... #else ... #endif with the appropriate class
+ *      getter (generated by Eolian) or NULL when unsupported
+ *
+ * The rest of the code relies on the Srv enum and _class_getters
+ * to register/unregister notification servers.
+ */
 
-typedef struct _Elm_Sys_Notify_Send_Data
+typedef enum
 {
-   Elm_Sys_Notify_Send_Cb cb;
-   const void *data;
-} Elm_Sys_Notify_Send_Data;
-
-static void
-_elm_sys_notify_marshal_dict_byte(Eldbus_Message_Iter *array,
-                                  const char *key,
-                                  const char value)
+   SRV_DBUS = 0,
+   __SRV_LAST /* Sentinel */
+} Srv;
+
+static Class_Get_Func _class_getters[__SRV_LAST] =
 {
-   Eldbus_Message_Iter *var, *entry;
+#ifdef ELM_SYS_NOTIFY_DBUS_CLASS
+   [SRV_DBUS] = elm_sys_notify_dbus_class_get
+#else
+   [SRV_DBUS] = NULL
+#endif
+};
 
-   eldbus_message_iter_arguments_append(array, "{sv}", &entry);
-   eldbus_message_iter_basic_append(entry, 's', key);
 
-   var = eldbus_message_iter_container_new(entry, 'v', "y");
-   eldbus_message_iter_basic_append(var, 'y', value);
-   eldbus_message_iter_container_close(entry, var);
-   eldbus_message_iter_container_close(array, entry);
-}
 
-static void
-_elm_sys_notify_marshal_dict_string(Eldbus_Message_Iter *array,
-                                   const char *key,
-                                   const char *value)
+typedef struct
 {
-   Eldbus_Message_Iter *var, *entry;
+   Eo *servers[__SRV_LAST];
+} Elm_Sys_Notify_Data;
 
-   eldbus_message_iter_arguments_append(array, "{sv}", &entry);
-   eldbus_message_iter_basic_append(entry, 's', key);
+/*============================================================================*
+ *                  Constructor/Destructor - Singleton setup                  *
+ 
*============================================================================*/
 
-   var = eldbus_message_iter_container_new(entry, 'v', "s");
-   eldbus_message_iter_basic_append(var, 's', value);
-   eldbus_message_iter_container_close(entry, var);
-   eldbus_message_iter_container_close(array, entry);
-}
-
-static void
-_get_capabilities_cb(void *data EINA_UNUSED,
-                     const Eldbus_Message *msg,
-                     Eldbus_Pending *pending EINA_UNUSED)
+EOLIAN static Eo_Base *
+_elm_sys_notify_eo_base_constructor(Eo                  *obj,
+                                    Elm_Sys_Notify_Data *sd  EINA_UNUSED)
 {
-   char *val;
-   Eldbus_Message_Iter *arr;
-
-   if (eldbus_message_error_get(msg, NULL, NULL) ||
-       !eldbus_message_arguments_get(msg, "as", &arr)) goto end;
+   if (_singleton != NULL)
+     {
+        ERR("Attempted to create another system notification manager");
+        return NULL;
+     }
 
-   while (eldbus_message_iter_get_and_next(arr, 's', &val))
-     if (!strcmp(val, "body-markup"))
-       {
-          _has_markup = EINA_TRUE;
-          return;
-       }
+   obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+   _singleton = obj;
 
-end:
-   _has_markup = EINA_FALSE;
+   return obj;
 }
 
-void
-_elm_sys_notify_capabilities_get(void)
+EOLIAN static void
+_elm_sys_notify_eo_base_destructor(Eo                  *obj,
+                                   Elm_Sys_Notify_Data *sd  EINA_UNUSED)
 {
-   EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
-
-   if (!eldbus_proxy_call(_elm_sysnotif_proxy, "GetCapabilities",
-                         _get_capabilities_cb, NULL, -1, ""))
-     ERR("Error sending message: "INTERFACE".GetCapabilities.");
+   eo_do_super(obj, MY_CLASS, eo_destructor());
+   _singleton = NULL;
 }
 
-static void
-_close_notification_cb(void *data EINA_UNUSED,
-                       const Eldbus_Message *msg,
-                       Eldbus_Pending *pending EINA_UNUSED)
-{
-   const char *errname, *errmsg;
-
-   if (eldbus_message_error_get(msg, &errname, &errmsg))
-     {
-        if (errmsg && errmsg[0] == '\0')
-          INF("Notification no longer exists.");
-        else
-          ERR("Eldbus Error: %s %s", errname, errmsg);
-     }
-}
 
-EAPI void
-elm_sys_notify_close(unsigned int id)
+/*============================================================================*
+ *                           Notification Interface                           *
+ 
*============================================================================*/
+
+EOLIAN static void
+_elm_sys_notify_elm_sys_notify_interface_send(const Eo *obj EINA_UNUSED,
+                                              Elm_Sys_Notify_Data *sd,
+                                              unsigned int replaces_id,
+                                              const char *icon,
+                                              const char *summary,
+                                              const char *body,
+                                              Elm_Sys_Notify_Urgency urgency,
+                                              int timeout,
+                                              Elm_Sys_Notify_Send_Cb cb,
+                                              const void *cb_data)
 {
-   EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
-   EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
-
-   if (!eldbus_proxy_call(_elm_sysnotif_proxy, "CloseNotification",
-                         _close_notification_cb, NULL, -1, "u", id))
-     ERR("Error sending message: "INTERFACE".CloseNotification.");
+   Srv i;
+
+   /* Propagate to all registered servers */
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
+     if (sd->servers[i])
+       eo_do(sd->servers[i],
+             elm_obj_sys_notify_interface_send(replaces_id,
+                                               icon, summary, body,
+                                               urgency, timeout,
+                                               cb, cb_data));
 }
 
-static void
-_notify_cb(void *data,
-           const Eldbus_Message *msg,
-           Eldbus_Pending *pending EINA_UNUSED)
+EOLIAN static void
+_elm_sys_notify_elm_sys_notify_interface_simple_send(const Eo *obj EINA_UNUSED,
+                                                     Elm_Sys_Notify_Data *sd,
+                                                     const char *icon,
+                                                     const char *summary,
+                                                     const char *body)
 {
-   const char *errname, *errmsg;
-   Elm_Sys_Notify_Send_Data *d = data;
-   unsigned int id = 0;
+   Srv i;
 
-   if (eldbus_message_error_get(msg, &errname, &errmsg))
-     ERR("Error: %s %s", errname, errmsg);
-   else if (!eldbus_message_arguments_get(msg, "u", &id))
-     {
-        ERR("Error getting return values of "INTERFACE".Notify.");
-        id = 0;
-     }
-
-   if (d->cb) d->cb((void *)d->data, id);
-   free(d);
+   /* Propagate to all registered servers */
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
+     if (sd->servers[i])
+       eo_do(sd->servers[i],
+             elm_obj_sys_notify_interface_simple_send(icon, summary, body));
 }
 
-EAPI void
-elm_sys_notify_send(unsigned int replaces_id, const char *icon,
-                    const char *summary, const char *body,
-                    Elm_Sys_Notify_Urgency urgency, int timeout,
-                    Elm_Sys_Notify_Send_Cb cb, const void *cb_data)
+EOLIAN static void
+_elm_sys_notify_elm_sys_notify_interface_close(const Eo *obj EINA_UNUSED,
+                                               Elm_Sys_Notify_Data *sd,
+                                               unsigned int id)
 {
-   Eldbus_Message *msg;
-   Eldbus_Message_Iter *iter, *actions, *hints;
-   Elm_Sys_Notify_Send_Data *data;
-   char *body_free = NULL;
-   char *desk_free = NULL;
-   const char *deskentry = elm_app_desktop_entry_get();
-   const char *appname = elm_app_name_get();
-
-   EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
-   EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
-
-   data = malloc(sizeof(Elm_Sys_Notify_Send_Data));
-   EINA_SAFETY_ON_NULL_GOTO(data, error);
-   data->cb = cb;
-   data->data = cb_data;
-
-   if (!icon) icon = "";
-   if (!summary) summary = "";
-   if (!body)
-     body = "";
-   else if (!_has_markup)
-     body = body_free = elm_entry_markup_to_utf8(body);
-
-   msg = eldbus_proxy_method_call_new(_elm_sysnotif_proxy, "Notify");
-
-   iter = eldbus_message_iter_get(msg);
-   eldbus_message_iter_arguments_append(iter, "susssas", appname, replaces_id,
-                                       icon, summary, body, &actions);
-   /* actions */
-   eldbus_message_iter_container_close(iter, actions);
-
-   /* hints */
-   eldbus_message_iter_arguments_append(iter, "a{sv}", &hints);
-   _elm_sys_notify_marshal_dict_byte(hints, "urgency", (char) urgency);
-
-   if (strcmp(deskentry, ""))
-     {
-        deskentry = ecore_file_file_get(deskentry);
-        deskentry = desk_free = ecore_file_strip_ext(deskentry);
-        _elm_sys_notify_marshal_dict_string(hints, "desktop_entry", deskentry);
-     }
-   eldbus_message_iter_container_close(iter, hints);
+   Srv i;
 
-   /* timeout */
-   eldbus_message_iter_arguments_append(iter, "i", timeout);
+   /* Propagate to all registered servers */
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
+     if (sd->servers[i])
+       eo_do(sd->servers[i],
+             elm_obj_sys_notify_interface_close(id));
+}
 
-   eldbus_proxy_send(_elm_sysnotif_proxy, msg, _notify_cb, data, -1);
-   free(desk_free);
-   free(body_free);
-   return;
 
-error:
-   if (cb) cb((void *)cb_data, 0);
-}
+/*============================================================================*
+ *                                   Methods                                  *
+ 
*============================================================================*/
 
-static void
-_on_notification_closed(void *data EINA_UNUSED,
-                        const Eldbus_Message *msg)
+EOLIAN static Eina_Bool
+_elm_sys_notify_servers_set(Eo                     *obj  EINA_UNUSED,
+                            Elm_Sys_Notify_Data    *sd,
+                            Elm_Sys_Notify_Server   servers)
 {
-   const char *errname;
-   const char *errmsg;
-   Elm_Sys_Notify_Notification_Closed *d;
+   Srv i;
+   Class_Get_Func class_get;
 
-   if (eldbus_message_error_get(msg, &errname, &errmsg))
+   /* Update the notification servers */
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
      {
-        ERR("Eldbus Error: %s %s", errname, errmsg);
-        return;
+        if (sd->servers[i])
+          {
+             /* Delete if server type is not provided */
+             if (!(servers & (1 << i)))
+               eo_del(sd->servers[i]);
+          }
+        else
+          {
+             /* If server is required, create when nonexistant */
+             if (servers & (1 << i))
+               {
+                  class_get = _class_getters[i];
+                  if (!class_get)
+                    {
+                       CRI("Unsupported notification server");
+                       return EINA_FALSE;
+                    }
+
+                  sd->servers[i] = eo_add(class_get(), NULL);
+                  if (EINA_UNLIKELY(!(sd->servers[i])))
+                    {
+                       CRI("Failed to create notification server");
+                       return EINA_FALSE;
+                    }
+               }
+          }
      }
 
-   d = malloc(sizeof(*d));
-
-   if (!eldbus_message_arguments_get(msg, "uu", &(d->id), &(d->reason)))
-     {
-        ERR("Error processing signal: "INTERFACE".NotificationClosed.");
-        goto cleanup;
-     }
+   return EINA_TRUE;
+}
 
-   if (!ecore_event_add(ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED, d,
-                        NULL, NULL)) goto cleanup;
+EOLIAN static Elm_Sys_Notify_Server
+_elm_sys_notify_servers_get(Eo                  *obj EINA_UNUSED,
+                            Elm_Sys_Notify_Data *sd)
+{
+   Elm_Sys_Notify_Server servers = ELM_SYS_NOTIFY_SERVER_NONE;
+   Srv i;
 
-   return;
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
+     if (sd->servers[i])
+       servers |= (1 << i);
 
-cleanup:
-   free(d);
+   return servers;
 }
 
-static void
-_ev_action_invoked_free(void *data EINA_UNUSED,
-                        void *ev_data)
+EOLIAN static Elm_Sys_Notify *
+_elm_sys_notify_singleton_get(Eo   *obj EINA_UNUSED,
+                              void *sd  EINA_UNUSED)
 {
-   Elm_Sys_Notify_Action_Invoked *d = ev_data;
-
-   free(d->action_key);
-   free(d);
+   if (!_singleton)
+     _singleton = eo_add(MY_CLASS, NULL);
+   return _singleton;
 }
 
-static void
-_on_action_invoked(void *data EINA_UNUSED,
-                   const Eldbus_Message *msg)
+EOLIAN static void
+_elm_sys_notify_class_constructor(Eo_Class *klass EINA_UNUSED)
 {
-   const char *errname;
-   const char *aux;
-
-   Elm_Sys_Notify_Action_Invoked *d;
-
-   if (eldbus_message_error_get(msg, &errname, &aux))
-     {
-        ERR("Eldbus Error: %s %s", errname, aux);
-        return;
-     }
-
-   d = calloc(1, sizeof(*d));
-   if (!d)
-     {
-        ERR("Fail to allocate memory");
-        return;
-     }
-
-   if (!eldbus_message_arguments_get(msg, "us", &(d->id), &aux))
-     {
-        ERR("Error processing signal: "INTERFACE".ActionInvoked.");
-        goto cleanup;
-     }
-
-   d->action_key = strdup(aux);
-
-   if (!ecore_event_add(ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED, d,
-                        _ev_action_invoked_free, NULL)) goto cleanup;
+   ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = ecore_event_type_new();
+   ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED = ecore_event_type_new();
+}
 
-   return;
+/*============================================================================*
+ *                                 Legacy API                                 *
+ 
*============================================================================*/
 
-cleanup:
-   free(d->action_key);
-   free(d);
+void
+_elm_unneed_sys_notify(void)
+{
+   eo_do(_singleton,
+         elm_obj_sys_notify_servers_set(ELM_SYS_NOTIFY_SERVER_NONE));
+   eo_del(_singleton);
 }
 
-static void
-_release(void)
+EAPI Eina_Bool
+elm_need_sys_notify(void)
 {
-   if (_elm_sysnotif_proxy)
+   Elm_Sys_Notify_Server servers = ELM_SYS_NOTIFY_SERVER_NONE;
+   Elm_Sys_Notify *manager;
+   Srv i;
+
+   /* In theory, there can be N notification managers, but
+    * in the implementation there will be only one: the
+    * singleton which is initialized here. */
+   manager = elm_sys_notify_singleton_get();
+   if (EINA_UNLIKELY(!manager))
      {
-        eldbus_proxy_unref(_elm_sysnotif_proxy);
-        _elm_sysnotif_proxy = NULL;
+        CRI("Failed to get notification manager");
+        return EINA_FALSE;
      }
 
-   if (_elm_sysnotif_obj)
+   /* If servers have alread been configured, this is not the right
+    * function to be called! */
+   if (elm_sys_notify_servers_get(manager) != ELM_SYS_NOTIFY_SERVER_NONE)
      {
-        eldbus_object_unref(_elm_sysnotif_obj);
-        _elm_sysnotif_obj = NULL;
+        ERR("Notification servers have already been configured. "
+            "Use elm_sys_notify_servers_set() instead.");
+        return EINA_FALSE;
      }
-}
 
-static void
-_update(void)
-{
-   _release();
-   _elm_sysnotif_obj = eldbus_object_get(_elm_sysnotif_conn, BUS, OBJ);
-   _elm_sysnotif_proxy = eldbus_proxy_get(_elm_sysnotif_obj, INTERFACE);
-   _elm_sys_notify_capabilities_get();
-
-   eldbus_proxy_signal_handler_add(_elm_sysnotif_proxy, "NotificationClosed",
-                                  _on_notification_closed, NULL);
+   /* Register available notification servers */
+   for (i = SRV_DBUS; i < __SRV_LAST; ++i)
+     if (_class_getters[i])
+       servers |= (1 << i);
 
-   eldbus_proxy_signal_handler_add(_elm_sysnotif_proxy, "ActionInvoked",
-                                  _on_action_invoked, NULL);
-}
-
-static void
-_name_owner_get_cb(void *data EINA_UNUSED,
-                   const Eldbus_Message *msg,
-                   Eldbus_Pending *pending EINA_UNUSED)
-{
-   const char *errname, *errmsg;
+   /* If no server are available, don't even bother... */
+   if (servers == ELM_SYS_NOTIFY_SERVER_NONE)
+     return EINA_FALSE;
 
-   if (eldbus_message_error_get(msg, &errname, &errmsg))
-     ERR("Eldbus Error: %s %s", errname, errmsg);
-   else
-     _update();
+   return elm_sys_notify_servers_set(manager, servers);
 }
 
-static void
-_name_owner_changed_cb(void *data EINA_UNUSED,
-                       const char *bus EINA_UNUSED,
-                       const char *old_id EINA_UNUSED,
-                       const char *new_id)
+EAPI void
+elm_sys_notify_send(unsigned int            replaces_id,
+                    const char             *icon,
+                    const char             *summary,
+                    const char             *body,
+                    Elm_Sys_Notify_Urgency  urgency,
+                    int                     timeout,
+                    Elm_Sys_Notify_Send_Cb  cb,
+                    const void             *cb_data)
 {
-   if ((!new_id) || (*new_id == '\0'))
-     _release();
-   else
-     _update();
+   eo_do(_singleton,
+         elm_obj_sys_notify_interface_send(replaces_id,
+                                           icon, summary, body,
+                                           urgency, timeout,
+                                           cb, cb_data));
 }
 
-EAPI Eina_Bool
-elm_need_sys_notify(void)
+EAPI void
+elm_sys_notify_close(unsigned int id)
 {
-   if (_elm_need_sys_notify) return EINA_TRUE;
-
-   if (!elm_need_eldbus()) return EINA_FALSE;
-
-   if (!ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED)
-     ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = ecore_event_type_new();
-
-   if (!ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED)
-     ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED = ecore_event_type_new();
-
-   _elm_sysnotif_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
-
-   eldbus_name_owner_changed_callback_add(_elm_sysnotif_conn, BUS,
-                                         _name_owner_changed_cb, NULL,
-                                         EINA_FALSE);
-
-   eldbus_name_owner_get(_elm_sysnotif_conn, BUS, _name_owner_get_cb, NULL);
-
-   _elm_need_sys_notify = EINA_TRUE;
-
-   return EINA_TRUE;
+   eo_do(_singleton,
+         elm_obj_sys_notify_interface_close(id));
 }
 
-void
-_elm_unneed_sys_notify(void)
-{
-   if (!_elm_need_sys_notify) return;
-
-   _elm_need_sys_notify = EINA_FALSE;
+#include "elm_sys_notify.eo.c"
 
-   _release();
-
-   eldbus_connection_unref(_elm_sysnotif_conn);
-   _elm_sysnotif_conn  = NULL;
-}
diff --git a/src/lib/elm_sys_notify.eo b/src/lib/elm_sys_notify.eo
new file mode 100644
index 0000000..7eb0df2
--- /dev/null
+++ b/src/lib/elm_sys_notify.eo
@@ -0,0 +1,90 @@
+enum Elm.Sys_Notify.Server
+{
+   none = 0, [[No notificationserver (disables notifications)]]
+   dbus = 1 << 0 [[Use DBus as a notification server]]
+}
+
+enum Elm.Sys_Notify.Closed_Reason
+{
+   [[The reason the notification was closed
+
+     @since 1.8
+   ]]
+
+   legacy: elm_sys_notify_closed;
+
+   expired, [[The notification expired]]
+   dismissed, [[The notification was dismissed by the user]]
+   requested, [[The notification was closed by a call to CloseNotification 
method]]
+   undefined [[Undefined/reserved reasons]]
+}
+
+struct Elm.Sys_Notify.Notification_Closed
+{
+   [[Data on event when notification closed is emitted
+
+     @since 1.8
+   ]]
+   id: uint; [[ID of the notification]]
+   reason: Elm.Sys_Notify.Closed_Reason; [[The reason the notification was 
closed]]
+}
+
+struct Elm.Sys_Notify.Action_Invoked
+{
+   [[Data on event when the action invoked is emitted
+
+     @since 1.8
+   ]]
+   id: uint; [[ID of the notification]]
+   action_key: char *; [[The key of the action invoked. These match the
+                                keys sent over in the list of actions]]
+}
+
+class Elm.Sys_Notify (Eo.Base, Elm.Sys_Notify_Interface)
+{
+   legacy_prefix: elm_sys_notify;
+   eo_prefix: elm_obj_sys_notify;
+
+   methods {
+      @property servers {
+         get {
+            [[Get the notification servers that have been registered
+
+              @since 1.16
+            ]]
+         }
+         set {
+            [[Set the notifications server to be used.
+
+              Note: This is an advanced function that should be used only to
+                    fullfill very specific purposes. Use elm_need_sys_notify()
+                    which activates the default available notification
+                    servers.
+            ]]
+            return: bool; [[$true on success, $false on failure]]
+         }
+         values {
+            servers: Elm.Sys_Notify.Server; [[Binary mask of servers to enable.
+            If a server is not present in the binary mask but was previously
+            registered, it will be unregistered.]]
+         }
+      }
+
+      singleton_get @class {
+         [[Returns the singleton instance of the notification manager
+         Elm.Sys_Notify. It is initialized upon the first call of this
+         function]]
+         return: Elm.Sys_Notify *; [[The unique notification manager]]
+      }
+   }
+
+   implements {
+      class.constructor;
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+      Elm.Sys_Notify_Interface.send;
+      Elm.Sys_Notify_Interface.simple_send;
+      Elm.Sys_Notify_Interface.close;
+   }
+}
+
diff --git a/src/lib/elm_sys_notify.h b/src/lib/elm_sys_notify.h
index aeff5a0..4534838 100644
--- a/src/lib/elm_sys_notify.h
+++ b/src/lib/elm_sys_notify.h
@@ -1,67 +1,25 @@
 #ifndef ELM_SYS_NOTIFY_H
 #define ELM_SYS_NOTIFY_H
 
-/**
- * The reason the notification was closed
- *
- * @since 1.8
- */
-typedef enum _Elm_Sys_Notify_Closed_Reason
-{
-  ELM_SYS_NOTIFY_CLOSED_EXPIRED, /** The notification expired. */
-  ELM_SYS_NOTIFY_CLOSED_DISMISSED, /** The notification was dismissed by the 
user. */
-  ELM_SYS_NOTIFY_CLOSED_REQUESTED, /** The notification was closed by a call 
to CloseNotification method. */
-  ELM_SYS_NOTIFY_CLOSED_UNDEFINED /** Undefined/reserved reasons. */
-} Elm_Sys_Notify_Closed_Reason;
-
-/**
- * Urgency levels of a notification
- *
- * @see elm_sys_notify_send()
- *
- * @since 1.8
- */
-typedef enum _Elm_Sys_Notify_Urgency
-{
-  ELM_SYS_NOTIFY_URGENCY_LOW,
-  ELM_SYS_NOTIFY_URGENCY_NORMAL,
-  ELM_SYS_NOTIFY_URGENCY_CRITICAL
-} Elm_Sys_Notify_Urgency;
-
 typedef void (*Elm_Sys_Notify_Send_Cb)(void *data, unsigned int id);
 
+#include "elm_sys_notify_interface.eo.h"
+#include "elm_sys_notify_interface.eo.legacy.h"
+#include "elm_sys_notify.eo.h"
+#include "elm_sys_notify.eo.legacy.h"
+
 /**
  * Emitted when the signal NotificationClosed is received.
+ * @since 1.8
  */
 EAPI extern int ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED;
 
 /**
  * Emitted when the signal ActionInvoked is received.
- */
-EAPI extern int ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED; /**< A Action has been 
invoked. */
-
-/**
- * Data on event when Notification Closed is emitted.
- *
  * @since 1.8
  */
-typedef struct _Elm_Sys_Notify_Notification_Closed
-{
-   unsigned int id; /**< ID of the notification. */
-   Elm_Sys_Notify_Closed_Reason reason; /**< The Reason the notification was 
closed. */
-} Elm_Sys_Notify_Notification_Closed;
-
+EAPI extern int ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED; /**< A Action has been 
invoked. */
 
-/**
- * Data on event when Action Invoked is emitted.
- *
- * @since 1.8
- */
-typedef struct _Elm_Sys_Notify_Action_Invoked
-{
-   unsigned int id; /**< ID of the notification. */
-   char *action_key; /**< The key of the action invoked. These match the keys 
sent over in the list of actions. */
-} Elm_Sys_Notify_Action_Invoked;
 
 /**
  * @def elm_sys_notify_simple_send
@@ -82,22 +40,9 @@ typedef struct _Elm_Sys_Notify_Action_Invoked
                             -1, NULL, NULL)
 
 /**
- * Causes a notification to be forcefully closed and removed from the user's
- * view. It can be used, for example, in the event that what the notification
- * pertains to is no longer relevant, or to cancel a notification * with no
- * expiration time.
- *
- * @param id Notification id
- *
- * @note If the notification no longer exists,
- * an empty D-BUS Error message is sent back.
- *
- * @since 1.8
- */
-EAPI void      elm_sys_notify_close(unsigned int id);
-
-/**
- * Sends a notification to the notification server.
+ * Sends a notification to the notification servers that have
+ * been registered by elm_need_sys_notify() or
+ * elm_sys_notify_servers_set().
  *
  * @param replaces_id Notification ID that this notification replaces.
  * The value 0 means a new notification.
@@ -120,4 +65,21 @@ EAPI void      elm_sys_notify_send(unsigned int replaces_id,
                                    int timeout,
                                    Elm_Sys_Notify_Send_Cb cb,
                                    const void *cb_data);
+
+/**
+ * Causes a notification to be forcefully closed and removed from the user's
+ * view. It can be used, for example, in the event that what the notification
+ * pertains to is no longer relevant, or to cancel a notification * with no
+ * expiration time.
+ *
+ * @param id Notification id
+ *
+ * @note If the notification no longer exists,
+ * an empty D-BUS Error message is sent back.
+ *
+ * @since 1.8
+ */
+EAPI void      elm_sys_notify_close(unsigned int id);
+
 #endif
+
diff --git a/src/lib/elm_sys_notify.c b/src/lib/elm_sys_notify_dbus.c
similarity index 72%
copy from src/lib/elm_sys_notify.c
copy to src/lib/elm_sys_notify_dbus.c
index 23c936f..bd0fa1e 100644
--- a/src/lib/elm_sys_notify.c
+++ b/src/lib/elm_sys_notify_dbus.c
@@ -6,15 +6,15 @@
 
 #include "elm_priv.h"
 
+#include "elm_sys_notify_dbus.eo.h"
+#include "elm_sys_notify_dbus.eo.legacy.h"
+
+#define MY_CLASS ELM_SYS_NOTIFY_DBUS_CLASS
+
 #define OBJ       "/org/freedesktop/Notifications"
 #define BUS       "org.freedesktop.Notifications"
 #define INTERFACE "org.freedesktop.Notifications"
 
-EAPI int ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = 0;
-EAPI int ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED      = 0;
-
-static Eina_Bool _elm_need_sys_notify = EINA_FALSE;
-
 static Eldbus_Connection *_elm_sysnotif_conn  = NULL;
 static Eldbus_Object     *_elm_sysnotif_obj   = NULL;
 static Eldbus_Proxy      *_elm_sysnotif_proxy = NULL;
@@ -107,14 +107,15 @@ _close_notification_cb(void *data EINA_UNUSED,
      }
 }
 
-EAPI void
-elm_sys_notify_close(unsigned int id)
+EOLIAN static void
+_elm_sys_notify_dbus_elm_sys_notify_interface_close(const Eo     *obj 
EINA_UNUSED,
+                                                    void         *sd  
EINA_UNUSED,
+                                                    unsigned int  id)
 {
-   EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
    EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
 
    if (!eldbus_proxy_call(_elm_sysnotif_proxy, "CloseNotification",
-                         _close_notification_cb, NULL, -1, "u", id))
+                          _close_notification_cb, NULL, -1, "u", id))
      ERR("Error sending message: "INTERFACE".CloseNotification.");
 }
 
@@ -139,11 +140,17 @@ _notify_cb(void *data,
    free(d);
 }
 
-EAPI void
-elm_sys_notify_send(unsigned int replaces_id, const char *icon,
-                    const char *summary, const char *body,
-                    Elm_Sys_Notify_Urgency urgency, int timeout,
-                    Elm_Sys_Notify_Send_Cb cb, const void *cb_data)
+EOLIAN static void
+_elm_sys_notify_dbus_elm_sys_notify_interface_send(const Eo *obj EINA_UNUSED,
+                                                   void *sd EINA_UNUSED,
+                                                   unsigned int replaces_id,
+                                                   const char *icon,
+                                                   const char *summary,
+                                                   const char *body,
+                                                   Elm_Sys_Notify_Urgency 
urgency,
+                                                   int timeout,
+                                                   Elm_Sys_Notify_Send_Cb cb,
+                                                   const void *cb_data)
 {
    Eldbus_Message *msg;
    Eldbus_Message_Iter *iter, *actions, *hints;
@@ -153,7 +160,6 @@ elm_sys_notify_send(unsigned int replaces_id, const char 
*icon,
    const char *deskentry = elm_app_desktop_entry_get();
    const char *appname = elm_app_name_get();
 
-   EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
    EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
 
    data = malloc(sizeof(Elm_Sys_Notify_Send_Data));
@@ -172,7 +178,7 @@ elm_sys_notify_send(unsigned int replaces_id, const char 
*icon,
 
    iter = eldbus_message_iter_get(msg);
    eldbus_message_iter_arguments_append(iter, "susssas", appname, replaces_id,
-                                       icon, summary, body, &actions);
+                                        icon, summary, body, &actions);
    /* actions */
    eldbus_message_iter_container_close(iter, actions);
 
@@ -200,6 +206,19 @@ error:
    if (cb) cb((void *)cb_data, 0);
 }
 
+EOLIAN static void
+_elm_sys_notify_dbus_elm_sys_notify_interface_simple_send(const Eo   *obj,
+                                                          void       *sd,
+                                                          const char *icon,
+                                                          const char *summary,
+                                                          const char *body)
+{
+   _elm_sys_notify_dbus_elm_sys_notify_interface_send(obj, sd,
+                                                      0, icon, summary, body,
+                                                      
ELM_SYS_NOTIFY_URGENCY_NORMAL,
+                                                      -1, NULL, NULL);
+}
+
 static void
 _on_notification_closed(void *data EINA_UNUSED,
                         const Eldbus_Message *msg)
@@ -306,10 +325,10 @@ _update(void)
    _elm_sys_notify_capabilities_get();
 
    eldbus_proxy_signal_handler_add(_elm_sysnotif_proxy, "NotificationClosed",
-                                  _on_notification_closed, NULL);
+                                   _on_notification_closed, NULL);
 
    eldbus_proxy_signal_handler_add(_elm_sysnotif_proxy, "ActionInvoked",
-                                  _on_action_invoked, NULL);
+                                   _on_action_invoked, NULL);
 }
 
 static void
@@ -337,41 +356,43 @@ _name_owner_changed_cb(void *data EINA_UNUSED,
      _update();
 }
 
-EAPI Eina_Bool
-elm_need_sys_notify(void)
+EOLIAN static Eo_Base *
+_elm_sys_notify_dbus_eo_base_constructor(Eo   *obj,
+                                         void *sd  EINA_UNUSED)
 {
-   if (_elm_need_sys_notify) return EINA_TRUE;
-
-   if (!elm_need_eldbus()) return EINA_FALSE;
-
-   if (!ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED)
-     ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = ecore_event_type_new();
-
-   if (!ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED)
-     ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED = ecore_event_type_new();
+   /* Don't create the same object twice (singleton) */
+   if (!_elm_sysnotif_conn)
+     {
+        if (!elm_need_eldbus()) return NULL;
 
-   _elm_sysnotif_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+        _elm_sysnotif_conn = 
eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
+        if (!_elm_sysnotif_conn) return NULL;
 
-   eldbus_name_owner_changed_callback_add(_elm_sysnotif_conn, BUS,
-                                         _name_owner_changed_cb, NULL,
-                                         EINA_FALSE);
+        eldbus_name_owner_changed_callback_add(_elm_sysnotif_conn, BUS,
+                                               _name_owner_changed_cb, NULL,
+                                               EINA_FALSE);
 
-   eldbus_name_owner_get(_elm_sysnotif_conn, BUS, _name_owner_get_cb, NULL);
+        eldbus_name_owner_get(_elm_sysnotif_conn, BUS, _name_owner_get_cb, 
NULL);
 
-   _elm_need_sys_notify = EINA_TRUE;
+        obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
+        return obj;
+     }
 
-   return EINA_TRUE;
+   ERR("Elm.Sys_Notify.Dbus is a singleton. It has already been created");
+   return NULL;
 }
 
-void
-_elm_unneed_sys_notify(void)
+EOLIAN static void
+_elm_sys_notify_dbus_eo_base_destructor(Eo   *obj,
+                                        void *sd  EINA_UNUSED)
 {
-   if (!_elm_need_sys_notify) return;
-
-   _elm_need_sys_notify = EINA_FALSE;
-
    _release();
 
    eldbus_connection_unref(_elm_sysnotif_conn);
-   _elm_sysnotif_conn  = NULL;
+   _elm_sysnotif_conn = NULL;
+   eo_do_super(obj, MY_CLASS, eo_destructor());
 }
+
+
+#include "elm_sys_notify_dbus.eo.c"
+
diff --git a/src/lib/elm_sys_notify_dbus.eo b/src/lib/elm_sys_notify_dbus.eo
new file mode 100644
index 0000000..df8eb9c
--- /dev/null
+++ b/src/lib/elm_sys_notify_dbus.eo
@@ -0,0 +1,14 @@
+class Elm.Sys_Notify.Dbus (Eo.Base, Elm.Sys_Notify_Interface)
+{
+   eo_prefix: elm_obj_sys_notify_dbus;
+   data: null;
+
+   implements {
+      Eo.Base.constructor;
+      Eo.Base.destructor;
+      Elm.Sys_Notify_Interface.send;
+      Elm.Sys_Notify_Interface.simple_send;
+      Elm.Sys_Notify_Interface.close;
+   }
+}
+
diff --git a/src/lib/elm_sys_notify_interface.c 
b/src/lib/elm_sys_notify_interface.c
new file mode 100644
index 0000000..c630afe
--- /dev/null
+++ b/src/lib/elm_sys_notify_interface.c
@@ -0,0 +1,9 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+
+#include "elm_priv.h"
+#include "elm_sys_notify_interface.eo.c"
+
diff --git a/src/lib/elm_sys_notify_interface.eo 
b/src/lib/elm_sys_notify_interface.eo
new file mode 100644
index 0000000..627586b
--- /dev/null
+++ b/src/lib/elm_sys_notify_interface.eo
@@ -0,0 +1,66 @@
+enum Elm.Sys_Notify.Urgency
+{
+   [[Urgency levels of a notification
+
+     @since 1.8
+   ]]
+   low, [[Low urgency]]
+   normal, [[Normal urgency]]
+   critical [[Critical urgency]]
+}
+
+interface Elm.Sys_Notify_Interface
+{
+   eo_prefix: elm_obj_sys_notify_interface;
+   legacy_prefix: elm_sys_notify_interface;
+
+   methods {
+      send @const {
+         [[Causes a notification to be forcefully closed and removed from the
+           user's view. It can be used, for example, in the event that what the
+           notification pertains to is no longer relevant, or to cancel a
+           notification with no expiration time.
+
+           @since 1.8
+         ]]
+         params {
+            @in replaces_id: uint; [[Notification ID that this notification 
replaces.
+                                     The value 0 means a new notification.]]
+            @in icon: const(char) *; [[The optional program icon of the 
calling application]]
+            @in summary: const(char) *; [[The summary text briefly describing 
the notification]]
+            @in body: const(char) * @optional; [[The optional detailed body 
text. Can be empty]]
+            @in urgency: Elm.Sys_Notify.Urgency; [[The urgency level]]
+            @in timeout: int; [[Timeout display in milliseconds]]
+            @in cb: Elm_Sys_Notify_Send_Cb; [[Callback used to retrieve the 
notification id
+                                              returned by the Notification 
Server]]
+            @in cb_data: const(void) * @optional; [[Optional context data]]
+         }
+      }
+      simple_send @const {
+         [[Create a new notification just with Icon, Body and Summary.
+           It is a helper that wraps the send method
+
+           @since 1.16
+         ]]
+
+         params {
+            @in icon: const(char) *; [[The optional program icon of the 
calling application]]
+            @in summary: const(char) *; [[The summary text briefly describing 
the notification]]
+            @in body: const(char) *; [[The optional detailed body text. Can be 
empty]]
+         }
+      }
+      close @const {
+         [[Causes a notification to be forcefully closed and removed from the
+           user's view. It can be used, for example, in the event that what the
+           notification  pertains to is no longer relevant, or to cancel a
+           notification with no expiration time.
+
+           @since 1.8
+         ]]
+         params {
+            @in id: uint; [[Notification ID]]
+         }
+      }
+   }
+}
+

-- 


Reply via email to