1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include <Elementary.h>
6 
7 #include "elm_priv.h"
8 
9 #include "elm_sys_notify_interface_eo.h"
10 #include "elm_sys_notify_eo.h"
11 #include "elm_sys_notify_dbus_eo.h"
12 #include "elm_sys_notify_dbus_eo.legacy.h"
13 
14 #define MY_CLASS ELM_SYS_NOTIFY_CLASS
15 
16 #define MY_CLASS_NAME        "Elm_Sys_Notify"
17 #define MY_CLASS_NAME_LEGACY "elm_sys_notify"
18 
19 EAPI int ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = 0;
20 EAPI int ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED      = 0;
21 
22 typedef const Efl_Class *(*Class_Get_Func)(void);
23 
24 static Elm_Sys_Notify *_singleton = NULL;
25 
26 /*
27  * Registration of notification servers is done UNIQUELY
28  * in the two structures below.
29  *   1) ALWAYS add a SRV_XXX before __SRV_LAST
30  *   2) copy the #if ... #else ... #endif with the appropriate class
31  *      getter (generated by Eolian) or NULL when unsupported
32  *
33  * The rest of the code relies on the Srv enum and _class_getters
34  * to register/unregister notification servers.
35  */
36 
37 typedef enum
38 {
39    SRV_DBUS = 0,
40    __SRV_LAST /* Sentinel */
41 } Srv;
42 
43 static Class_Get_Func _class_getters[__SRV_LAST] =
44 {
45 #ifdef ELM_SYS_NOTIFY_DBUS_CLASS
46    [SRV_DBUS] = elm_sys_notify_dbus_class_get
47 #else
48    [SRV_DBUS] = NULL
49 #endif
50 };
51 
52 
53 
54 typedef struct
55 {
56    Eo *servers[__SRV_LAST];
57 } Elm_Sys_Notify_Data;
58 
59 /*============================================================================*
60  *                  Constructor/Destructor - Singleton setup                  *
61  *============================================================================*/
62 
63 EOLIAN static Efl_Object *
_elm_sys_notify_efl_object_constructor(Eo * obj,Elm_Sys_Notify_Data * sd EINA_UNUSED)64 _elm_sys_notify_efl_object_constructor(Eo                  *obj,
65                                     Elm_Sys_Notify_Data *sd  EINA_UNUSED)
66 {
67    if (_singleton != NULL)
68      {
69         ERR("Attempted to create another system notification manager");
70         return NULL;
71      }
72 
73    obj = efl_constructor(efl_super(obj, MY_CLASS));
74    _singleton = obj;
75 
76    return obj;
77 }
78 
79 EOLIAN static void
_elm_sys_notify_efl_object_destructor(Eo * obj,Elm_Sys_Notify_Data * sd EINA_UNUSED)80 _elm_sys_notify_efl_object_destructor(Eo                  *obj,
81                                    Elm_Sys_Notify_Data *sd  EINA_UNUSED)
82 {
83    efl_destructor(efl_super(obj, MY_CLASS));
84    _singleton = NULL;
85 }
86 
87 
88 /*============================================================================*
89  *                           Notification Interface                           *
90  *============================================================================*/
91 
92 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)93 _elm_sys_notify_elm_sys_notify_interface_send(const Eo *obj EINA_UNUSED,
94                                               Elm_Sys_Notify_Data *sd,
95                                               unsigned int replaces_id,
96                                               const char *icon,
97                                               const char *summary,
98                                               const char *body,
99                                               Elm_Sys_Notify_Urgency urgency,
100                                               int timeout,
101                                               Elm_Sys_Notify_Send_Cb cb,
102                                               const void *cb_data)
103 {
104    Srv i;
105 
106    /* Propagate to all registered servers */
107    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
108      if (sd->servers[i])
109        elm_obj_sys_notify_interface_send(sd->servers[i], replaces_id, icon, summary, body, urgency, timeout, cb, cb_data);
110 }
111 
112 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)113 _elm_sys_notify_elm_sys_notify_interface_simple_send(const Eo *obj EINA_UNUSED,
114                                                      Elm_Sys_Notify_Data *sd,
115                                                      const char *icon,
116                                                      const char *summary,
117                                                      const char *body)
118 {
119    Srv i;
120 
121    /* Propagate to all registered servers */
122    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
123      if (sd->servers[i])
124        elm_obj_sys_notify_interface_simple_send(sd->servers[i], icon, summary, body);
125 }
126 
127 EOLIAN static void
_elm_sys_notify_elm_sys_notify_interface_close(const Eo * obj EINA_UNUSED,Elm_Sys_Notify_Data * sd,unsigned int id)128 _elm_sys_notify_elm_sys_notify_interface_close(const Eo *obj EINA_UNUSED,
129                                                Elm_Sys_Notify_Data *sd,
130                                                unsigned int id)
131 {
132    Srv i;
133 
134    /* Propagate to all registered servers */
135    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
136      if (sd->servers[i])
137        elm_obj_sys_notify_interface_close(sd->servers[i], id);
138 }
139 
140 
141 /*============================================================================*
142  *                                   Methods                                  *
143  *============================================================================*/
144 
145 EOLIAN static Eina_Bool
_elm_sys_notify_servers_set(Eo * obj EINA_UNUSED,Elm_Sys_Notify_Data * sd,Elm_Sys_Notify_Server servers)146 _elm_sys_notify_servers_set(Eo                     *obj  EINA_UNUSED,
147                             Elm_Sys_Notify_Data    *sd,
148                             Elm_Sys_Notify_Server   servers)
149 {
150    Srv i;
151    Class_Get_Func class_get;
152 
153    /* Update the notification servers */
154    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
155      {
156         if (sd->servers[i])
157           {
158              /* Delete if server type is not provided */
159              if (!(servers & (1 << i)))
160                efl_del(sd->servers[i]);
161           }
162         else
163           {
164              /* If server is required, create when nonexistant */
165              if (servers & (1 << i))
166                {
167                   class_get = _class_getters[i];
168                   if (!class_get)
169                     {
170                        CRI("Unsupported notification server");
171                        return EINA_FALSE;
172                     }
173 
174                   sd->servers[i] = efl_add(class_get(), NULL);
175                   if (EINA_UNLIKELY(!(sd->servers[i])))
176                     {
177                        CRI("Failed to create notification server");
178                        return EINA_FALSE;
179                     }
180                }
181           }
182      }
183 
184    return EINA_TRUE;
185 }
186 
187 EOLIAN static Elm_Sys_Notify_Server
_elm_sys_notify_servers_get(const Eo * obj EINA_UNUSED,Elm_Sys_Notify_Data * sd)188 _elm_sys_notify_servers_get(const Eo            *obj EINA_UNUSED,
189                             Elm_Sys_Notify_Data *sd)
190 {
191    Elm_Sys_Notify_Server servers = ELM_SYS_NOTIFY_SERVER_NONE;
192    Srv i;
193 
194    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
195      if (sd->servers[i])
196        servers |= (1 << i);
197 
198    return servers;
199 }
200 
201 EOLIAN static Elm_Sys_Notify *
_elm_sys_notify_singleton_get(void)202 _elm_sys_notify_singleton_get(void)
203 {
204    if (!_singleton)
205      _singleton = efl_add(MY_CLASS, efl_main_loop_get());
206    return _singleton;
207 }
208 
209 EOLIAN static void
_elm_sys_notify_class_constructor(Efl_Class * klass EINA_UNUSED)210 _elm_sys_notify_class_constructor(Efl_Class *klass EINA_UNUSED)
211 {
212    ELM_EVENT_SYS_NOTIFY_NOTIFICATION_CLOSED = ecore_event_type_new();
213    ELM_EVENT_SYS_NOTIFY_ACTION_INVOKED = ecore_event_type_new();
214 }
215 
216 /*============================================================================*
217  *                                 Legacy API                                 *
218  *============================================================================*/
219 
220 void
_elm_unneed_sys_notify(void)221 _elm_unneed_sys_notify(void)
222 {
223    Elm_Sys_Notify *manager = elm_obj_sys_notify_singleton_get();
224    if (manager)
225      {
226         elm_obj_sys_notify_servers_set(manager, ELM_SYS_NOTIFY_SERVER_NONE);
227         efl_del(manager);
228      }
229 }
230 
231 EAPI Eina_Bool
elm_need_sys_notify(void)232 elm_need_sys_notify(void)
233 {
234    Elm_Sys_Notify_Server servers = ELM_SYS_NOTIFY_SERVER_NONE;
235    Elm_Sys_Notify *manager;
236    Srv i;
237 
238    /* In theory, there can be N notification managers, but
239     * in the implementation there will be only one: the
240     * singleton which is initialized here. */
241    manager = elm_obj_sys_notify_singleton_get();
242    if (EINA_UNLIKELY(!manager))
243      {
244         CRI("Failed to get notification manager");
245         return EINA_FALSE;
246      }
247 
248    /* If servers have alread been configured, this is not the right
249     * function to be called! */
250    if (elm_sys_notify_servers_get(manager) != ELM_SYS_NOTIFY_SERVER_NONE)
251      {
252         ERR("Notification servers have already been configured. "
253             "Use elm_sys_notify_servers_set() instead.");
254         return EINA_FALSE;
255      }
256 
257    /* Register available notification servers */
258    for (i = SRV_DBUS; i < __SRV_LAST; ++i)
259      if (_class_getters[i])
260        servers |= (1 << i);
261 
262    /* If no server are available, don't even bother... */
263    if (servers == ELM_SYS_NOTIFY_SERVER_NONE)
264      return EINA_FALSE;
265 
266    return elm_sys_notify_servers_set(manager, servers);
267 }
268 
269 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)270 elm_sys_notify_send(unsigned int            replaces_id,
271                     const char             *icon,
272                     const char             *summary,
273                     const char             *body,
274                     Elm_Sys_Notify_Urgency  urgency,
275                     int                     timeout,
276                     Elm_Sys_Notify_Send_Cb  cb,
277                     const void             *cb_data)
278 {
279    elm_obj_sys_notify_interface_send(_singleton, replaces_id, icon, summary, body, urgency, timeout, cb, cb_data);
280 }
281 
282 EAPI void
elm_sys_notify_close(unsigned int id)283 elm_sys_notify_close(unsigned int id)
284 {
285    elm_obj_sys_notify_interface_close(_singleton, id);
286 }
287 
288 #include "elm_sys_notify_eo.c"
289 
290