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