Package upload
[framework/uifw/edbus.git] / src / lib / notification / notification.c
1 #include "E_Notify.h"
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <inttypes.h>
6 #include "e_notify_private.h"
7
8 /* private functions */
9 static Eina_List             *e_notification_action_list_new(void);
10 static E_Notification_Action *e_notification_action_new(const char *id,
11                                                         const char *name);
12
13 int _e_dbus_notify_log_dom = -1;
14
15 static void
16 loginit(void)
17 {
18    if (_e_dbus_notify_log_dom == -1)
19      _e_dbus_notify_log_dom = eina_log_domain_register("e_dbus_notify", E_DBUS_COLOR_DEFAULT);
20 }
21
22 /* (con|de)structor */
23
24 EAPI E_Notification *
25 e_notification_full_new(const char *app_name, unsigned int replaces_id, const char *app_icon, const char *summary, const char *body, int expire_timeout)
26 {
27    E_Notification *n;
28
29    loginit();
30    n = e_notification_new();
31    if (!n) return NULL;
32
33    n->app_name = eina_stringshare_add(app_name);
34    n->replaces_id = replaces_id;
35    n->app_icon = eina_stringshare_add(app_icon);
36    n->summary = eina_stringshare_add(summary);
37    n->body = eina_stringshare_add(body);
38    n->expire_timeout = expire_timeout;
39    n->hints.x = n->hints.y = -1;
40
41    return n;
42 }
43
44 EAPI E_Notification *
45 e_notification_new(void)
46 {
47    E_Notification *n;
48    
49    loginit();
50    n = calloc(1, sizeof(E_Notification));
51    if (!n) return NULL;
52    n->refcount = 1;
53
54    return n;
55 }
56
57 EAPI void
58 e_notification_ref(E_Notification *n)
59 {
60    loginit();
61    n->refcount++;
62 }
63
64 EAPI void
65 e_notification_unref(E_Notification *n)
66 {
67    loginit();
68    if (--n->refcount == 0) e_notification_free(n);
69 }
70
71 EAPI void
72 e_notification_free(E_Notification *n)
73 {
74    loginit();
75    if (!n) return;
76
77    eina_stringshare_del(n->app_name);
78    eina_stringshare_del(n->app_icon);
79    eina_stringshare_del(n->summary);
80    eina_stringshare_del(n->body);
81
82    eina_list_free(n->actions);
83
84    eina_stringshare_del(n->hints.category);
85    eina_stringshare_del(n->hints.desktop);
86    eina_stringshare_del(n->hints.sound_file);
87    if (n->hints.image_data) e_notification_image_free(n->hints.image_data);
88    if (n->hints.icon_data) e_notification_image_free(n->hints.icon_data);
89    free(n);
90 }
91
92 /* mutators */
93 EAPI void
94 e_notification_id_set(E_Notification *note, unsigned int id)
95 {
96    loginit();
97    note->id = id;
98 }
99
100 EAPI void
101 e_notification_app_name_set(E_Notification *note, const char *app_name)
102 {
103    loginit();
104    eina_stringshare_replace(&note->app_name, app_name);
105 }
106
107 EAPI void
108 e_notification_app_icon_set(E_Notification *note, const char *app_icon)
109 {
110    loginit();
111    eina_stringshare_replace(&note->app_icon, app_icon);
112 }
113
114 EAPI void
115 e_notification_summary_set(E_Notification *note, const char *summary)
116 {
117    loginit();
118    eina_stringshare_replace(&note->summary, summary);
119 }
120
121 EAPI void
122 e_notification_body_set(E_Notification *note, const char *body)
123 {
124    loginit();
125    eina_stringshare_replace(&note->body, body);
126 }
127
128 EAPI void
129 e_notification_action_add(E_Notification *n, const char *action_id, const char *action_name)
130 {
131    E_Notification_Action *a;
132
133    loginit();
134    if (!n->actions)
135      n->actions = e_notification_action_list_new();
136
137    a = e_notification_action_new(action_id, action_name);
138    n->actions = eina_list_append(n->actions, a);
139 }
140
141 EAPI void
142 e_notification_replaces_id_set(E_Notification *note, int replaces_id)
143 {
144    loginit();
145    note->replaces_id = replaces_id;
146 }
147
148 EAPI void
149 e_notification_timeout_set(E_Notification *note, int timeout)
150 {
151    loginit();
152    note->expire_timeout = timeout;
153 }
154
155 EAPI void
156 e_notification_closed_set(E_Notification *note, unsigned char closed)
157 {
158    loginit();
159    note->closed = closed;
160 }
161
162 /* accessors */
163 EAPI unsigned int
164 e_notification_id_get(E_Notification *note)
165 {
166    loginit();
167    return note->id;
168 }
169
170 EAPI const char *
171 e_notification_app_name_get(E_Notification *note)
172 {
173    loginit();
174    return note->app_name;
175 }
176
177 EAPI const char *
178 e_notification_app_icon_get(E_Notification *note)
179 {
180    loginit();
181    return note->app_icon;
182 }
183
184 EAPI const char *
185 e_notification_summary_get(E_Notification *note)
186 {
187    loginit();
188    return note->summary;
189 }
190
191 EAPI const char *
192 e_notification_body_get(E_Notification *note)
193 {
194    loginit();
195    return note->body;
196 }
197
198 EAPI Eina_List *
199 e_notification_actions_get(E_Notification *note)
200 {
201    loginit();
202    return note->actions;
203 }
204
205 EAPI int
206 e_notification_replaces_id_get(E_Notification *note)
207 {
208    loginit();
209    return note->replaces_id;
210 }
211
212 EAPI int
213 e_notification_timeout_get(E_Notification *note)
214 {
215    loginit();
216    return note->expire_timeout;
217 }
218
219 EAPI unsigned char
220 e_notification_closed_get(E_Notification *note)
221 {
222    loginit();
223    return note->closed;
224 }
225
226 /***** actions *****/
227
228 static Eina_List *
229 e_notification_action_list_new(void)
230 {
231    Eina_List *alist;
232
233    loginit();
234    alist = NULL;
235    return alist;
236 }
237
238 static E_Notification_Action *
239 e_notification_action_new(const char *id, const char *name)
240 {
241    E_Notification_Action *act;
242    
243    loginit();
244    act = malloc(sizeof(E_Notification_Action));
245    act->id = eina_stringshare_add(id);
246    act->name = eina_stringshare_add(name);
247    return act;
248 }
249
250 EAPI const char *
251 e_notification_action_id_get(E_Notification_Action *a)
252 {
253    loginit();
254    EINA_SAFETY_ON_NULL_RETURN_VAL(a, NULL);
255    return a->id;
256 }
257
258 EAPI const char *
259 e_notification_action_name_get(E_Notification_Action *a)
260 {
261    loginit();
262    EINA_SAFETY_ON_NULL_RETURN_VAL(a, NULL);
263    return a->name;
264 }
265
266 /********* hints *******/
267 EAPI void
268 e_notification_hint_transient_set(E_Notification *n, Eina_Bool transient)
269 {
270    loginit();
271    if (transient)
272      n->hint_flags |= E_NOTIFICATION_HINT_TRANSIENT;
273    else
274      n->hint_flags ^= E_NOTIFICATION_HINT_TRANSIENT;
275 }
276
277 EAPI void
278 e_notification_hint_resident_set(E_Notification *n, Eina_Bool resident)
279 {
280    loginit();
281    if (resident)
282      n->hint_flags |= E_NOTIFICATION_HINT_RESIDENT;
283    else
284      n->hint_flags ^= E_NOTIFICATION_HINT_RESIDENT;
285 }
286
287 EAPI void
288 e_notification_hint_action_icons_set(E_Notification *n, Eina_Bool action_icons)
289 {
290    loginit();
291    if (action_icons)
292      n->hint_flags |= E_NOTIFICATION_HINT_ACTION_ICONS;
293    else
294      n->hint_flags ^= E_NOTIFICATION_HINT_ACTION_ICONS;
295 }
296
297 EAPI void
298 e_notification_hint_urgency_set(E_Notification *n, char urgency)
299 {
300    loginit();
301    n->hints.urgency = urgency;
302    n->hint_flags |= E_NOTIFICATION_HINT_URGENCY;
303 }
304
305 EAPI void
306 e_notification_hint_image_path_set(E_Notification *n, const char *path)
307 {
308    loginit();
309    eina_stringshare_replace(&n->hints.image_path, path);
310 }
311
312 EAPI void
313 e_notification_hint_category_set(E_Notification *n, const char *category)
314 {
315    loginit();
316    eina_stringshare_replace(&n->hints.category, category);
317    n->hint_flags |= E_NOTIFICATION_HINT_CATEGORY;
318 }
319
320 EAPI void
321 e_notification_hint_desktop_set(E_Notification *n, const char *desktop)
322 {
323    loginit();
324    eina_stringshare_replace(&n->hints.desktop, desktop);
325    n->hint_flags |= E_NOTIFICATION_HINT_DESKTOP;
326 }
327
328 EAPI void
329 e_notification_hint_sound_file_set(E_Notification *n, const char *sound_file)
330 {
331    loginit();
332    eina_stringshare_replace(&n->hints.sound_file, sound_file);
333    n->hint_flags |= E_NOTIFICATION_HINT_SOUND_FILE;
334 }
335
336 EAPI void
337 e_notification_hint_suppress_sound_set(E_Notification *n, char suppress_sound)
338 {
339    loginit();
340    n->hints.suppress_sound = suppress_sound;
341    n->hint_flags |= E_NOTIFICATION_HINT_SUPPRESS_SOUND;
342 }
343
344 EAPI void
345 e_notification_hint_xy_set(E_Notification *n, int x, int y)
346 {
347    loginit();
348    n->hints.x = x;
349    n->hints.y = y;
350    n->hint_flags |= E_NOTIFICATION_HINT_XY;
351 }
352
353 EAPI void
354 e_notification_hint_image_data_set(E_Notification *n, E_Notification_Image *image)
355 {
356    loginit();
357    n->hints.image_data = image;
358 }
359
360 EAPI char
361 e_notification_hint_urgency_get(E_Notification *n)
362 {
363    loginit();
364    return n->hint_flags & E_NOTIFICATION_HINT_URGENCY ? n->hints.urgency : 1;
365 }
366
367 EAPI const char *
368 e_notification_hint_category_get(E_Notification *n)
369 {
370    loginit();
371    return n->hints.category;
372 }
373
374 EAPI const char *
375 e_notification_hint_desktop_get(E_Notification *n)
376 {
377    loginit();
378    return n->hints.desktop;
379 }
380
381 EAPI const char *
382 e_notification_hint_image_path_get(E_Notification *n)
383 {
384    loginit();
385    return n->hints.image_path;
386 }
387
388 EAPI const char *
389 e_notification_hint_sound_file_get(E_Notification *n)
390 {
391    loginit();
392    return n->hints.sound_file;
393 }
394
395 EAPI char
396 e_notification_hint_suppress_sound_get(E_Notification *n)
397 {
398    loginit();
399    return n->hints.suppress_sound;
400 }
401
402 EAPI int
403 e_notification_hint_xy_get(E_Notification *n, int *x, int *y)
404 {
405    loginit();
406    if (x) *x = n->hints.x;
407    if (y) *y = n->hints.y;
408
409    return n->hint_flags & E_NOTIFICATION_HINT_XY ? 1 : 0;
410 }
411
412 EAPI E_Notification_Image *
413 e_notification_hint_image_data_get(E_Notification *n)
414 {
415    loginit();
416    return n->hints.image_data;
417 }
418
419 EAPI E_Notification_Image *
420 e_notification_hint_icon_data_get(E_Notification *n)
421 {
422    loginit();
423    return n->hints.icon_data;
424 }
425
426 EAPI E_Notification_Image *
427 e_notification_image_new(void)
428 {
429    E_Notification_Image *img;
430
431    loginit();
432    img = calloc(1, sizeof(E_Notification_Image));
433    img->bits_per_sample = 8;
434    return img;
435 }
436
437 EAPI Eina_Bool
438 e_notification_image_init(E_Notification_Image *img, Evas_Object *obj)
439 {
440    int x, y, w = 0, h = 0;
441    unsigned char *d, *imgdata;
442    int rowstride;
443    int *s;
444    
445    loginit();
446    EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
447    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
448
449    evas_object_image_size_get(obj, &w, &h);
450    if ((w <= 0) || (h <= 0)) return EINA_FALSE;
451    imgdata = evas_object_image_data_get(obj, EINA_FALSE);
452    if (!imgdata) return EINA_FALSE;
453    
454    img->data = malloc(4 * w * h);
455    if (!img->data)
456      {
457         evas_object_image_data_set(obj, imgdata);
458         return EINA_FALSE;
459      }
460    img->channels = 4;
461    img->rowstride = 4 * w;
462    img->width = w;
463    img->height = h;
464    img->bits_per_sample = 8;
465    img->has_alpha = EINA_TRUE;
466    
467    rowstride = evas_object_image_stride_get(obj);
468    for (y = 0; y < img->height; y++)
469      {
470         s = (int *)(imgdata + (y * rowstride));
471         d = img->data + (y * img->rowstride);
472         
473         for (x = 0; x < img->width; x++, s++)
474           {
475              *d++ = (*s >> 16) & 0xff;
476              *d++ = (*s >> 8) & 0xff;
477              *d++ = (*s) & 0xff;
478              *d++ = (*s >> 24) & 0xff;
479           }
480      }
481    
482    evas_object_image_data_set(obj, imgdata);
483    return EINA_TRUE;
484 }
485
486 EAPI void
487 e_notification_image_free(E_Notification_Image *img)
488 {
489    loginit();
490    if (!img) return;
491    free(img->data);
492    free(img);
493 }
494
495 static Eina_Bool
496 _e_notification_image_evas_object_fill(E_Notification_Image *img, Evas_Object *obj)
497 {
498    unsigned char *imgdata;
499    
500    EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
501    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
502
503    evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_ARGB8888);
504    evas_object_image_alpha_set(obj, img->has_alpha);
505    evas_object_image_size_set(obj, img->width, img->height);
506    
507    imgdata = evas_object_image_data_get(obj, EINA_TRUE);
508    if (!imgdata) return EINA_FALSE;
509    
510    if (img->bits_per_sample == 8)
511      {
512         /* Although not specified.
513          * The data are very likely to come from a GdkPixbuf
514          * which align each row on a 4-bytes boundary when using RGB.
515          * And is RGBA otherwise. */
516         int x, y, *d;
517         unsigned char *s;
518         int rowstride;
519         
520         rowstride = evas_object_image_stride_get(obj);
521         for (y = 0; y < img->height; y++)
522           {
523              s = img->data + (y * img->rowstride);
524              d = (int *)(imgdata + (y * rowstride));
525
526              for (x = 0; x < img->width; x++, s += img->channels, d++)
527                {
528                   if (img->has_alpha)
529                     *d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | (s[2]);
530                   else
531                     *d = (0xff << 24) | (s[0] << 16) | (s[1] << 8) | (s[2]);
532                }
533           }
534      }
535    evas_object_image_data_update_add(obj, 0, 0, img->width, img->height);
536    evas_object_image_data_set(obj, imgdata);
537    
538    return EINA_TRUE;
539 }
540
541 EAPI Evas_Object *
542 e_notification_image_evas_object_add(Evas *evas, E_Notification_Image *img)
543 {
544    Evas_Object *o = NULL;
545
546    loginit();
547    if ((!evas) || (!img)) return NULL;
548    o = evas_object_image_filled_add(evas);
549    evas_object_resize(o, img->width, img->height);
550    if (!_e_notification_image_evas_object_fill(img, o))
551      {
552         evas_object_del(o);
553         return NULL;
554      }
555    return o;
556 }
557