3bb52afb095f84a205ff09632c74db89f4d31f20
[apps/native/widget/widget.git] / dynamicbox / src / dynamicbox.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <stdlib.h> /* malloc */
20 #include <string.h> /* strdup */
21 #include <libgen.h>
22 #include <unistd.h> /* access */
23 #define __USE_GNU
24 #include <dlfcn.h>
25
26 #include <dlog.h>
27 #include <dynamicbox_errno.h>
28 #include <dynamicbox_service.h>
29 #include <dynamicbox_provider.h>
30 #include <dynamicbox_provider_buffer.h>
31 #include <dynamicbox_conf.h>
32 #include <dynamicbox_buffer.h>
33 #include <Evas.h>
34 #include <Ecore.h>
35
36 #include "debug.h"
37 #include "dlist.h"
38 #include "util.h"
39 #include "dynamicbox.h"
40 #include "internal/dynamicbox.h"
41
42 #define PUBLIC __attribute__((visibility("default")))
43
44 #define FILE_SCHEMA    "file://"
45
46 /**
47  * @note
48  * This value is configurable value.
49  */
50 #define FRAME_WAIT_INTERVAL (1.0f/6.0f)
51
52 struct block {
53     unsigned int idx;
54
55     char *type;
56     char *part;
57     char *data;
58     char *option;
59     char *id;
60     char *file;
61     char *target_id;
62 };
63
64 struct dynamicbox_desc {
65     FILE *fp;
66     int for_pd;
67
68     unsigned int last_idx;
69
70     struct dlist *block_list;
71 };
72
73 struct dynamicbox_buffer_data {
74     int is_gbar;
75     int accelerated;
76
77     /* for Buffer event wrapper */
78     int (*handler)(dynamicbox_buffer_h , dynamicbox_buffer_event_data_t, void *);
79     void *cbdata;
80
81     char *content;
82     char *title;
83     char *icon;
84     char *name;
85
86     Ecore_Timer *frame_wait_timer;
87 };
88
89 /**
90  * @brief These functions are defined in the data-provider-slave
91  */
92 static struct info {
93     const char *(*find_pkgname)(const char *filename);
94     int (*request_update_by_id)(const char *uri);
95     int (*trigger_update_monitor)(const char *id, int is_gbar);
96     int (*update_extra_info)(const char *id, const char *content, const char *title, const char *icon, const char *name);
97
98     enum load_type {
99         LOAD_TYPE_UNKNOWN = -1,
100         LOAD_TYPE_SLAVE   = 0,
101         LOAD_TYPE_APP     = 1
102     } type;
103
104     union _updated {
105         struct _slave {
106             int (*send)(const char *pkgname, const char *id, dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile);
107         } slave;
108
109         struct _app {
110             int (*send)(dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar);
111         } app;
112     } updated;
113 } s_info = {
114     .find_pkgname = NULL,
115     .request_update_by_id = NULL,
116     .trigger_update_monitor = NULL,
117     .update_extra_info = NULL,
118     .type = LOAD_TYPE_UNKNOWN,    /* Not initialized */
119 };
120
121 #define FUNC_PREFIX                               "dynamicbox_"
122 #define FUNC_DYNAMICBOX_SEND_UPDATED              FUNC_PREFIX "send_buffer_updated"
123 #define FUNC_DYNAMICBOX_PROVIDER_APP_UPDATED      FUNC_PREFIX "provider_app_buffer_updated"
124 #define FUNC_DYNAMICBOX_FIND_PKGNAME              FUNC_PREFIX "find_pkgname"
125 #define FUNC_DYNAMICBOX_REQUEST_UPDATE_BY_ID      FUNC_PREFIX "request_update_by_id"
126 #define FUNC_DYNAMICBOX_TRIGGER_UPDATE_MONITOR    FUNC_PREFIX "trigger_update_monitor"
127 #define FUNC_DYNAMICBOX_UPDATE_EXTRA_INFO         FUNC_PREFIX "update_extra_info"
128
129 static inline void load_update_function(void)
130 {
131     /* Must to be checked the slave function first. */
132     s_info.updated.slave.send = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_SEND_UPDATED);
133     if (s_info.updated.slave.send) {
134         s_info.type = LOAD_TYPE_SLAVE;
135         DbgPrint("Slave detected\n");
136     } else {
137         s_info.updated.app.send = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_PROVIDER_APP_UPDATED);
138         if (s_info.updated.app.send) {
139             s_info.type = LOAD_TYPE_APP;
140             DbgPrint("App detected\n");
141         }
142     }
143 }
144
145 static int send_updated(const char *pkgname, const char *id, dynamicbox_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
146 {
147     int ret = DBOX_STATUS_ERROR_INVALID_PARAMETER;
148
149     if (s_info.type == LOAD_TYPE_UNKNOWN) {
150         load_update_function();
151     }
152
153     if (s_info.type == LOAD_TYPE_APP) {
154         ret = s_info.updated.app.send(handle, idx, x, y, w, h, gbar);
155     } else if (s_info.type == LOAD_TYPE_SLAVE) {
156         /**
157          * pkgname, id are used for finding handle of direct connection.
158          */
159         ret = s_info.updated.slave.send(pkgname, id, handle, idx, x, y, w, h, gbar, descfile);
160     } else {
161         dynamicbox_damage_region_t region = {
162             .x = x,
163             .y = y,
164             .w = w,
165             .h = h,
166         };
167         ret = dynamicbox_provider_send_buffer_updated(handle, idx, &region, gbar, descfile);
168     }
169
170     return ret;
171 }
172
173 static char *id_to_uri(const char *id)
174 {
175     char *uri;
176     int uri_len;
177
178     uri_len = strlen(id) + strlen(FILE_SCHEMA) + 1;
179
180     uri = malloc(uri_len);
181     if (!uri) {
182         return NULL;
183     }
184
185     snprintf(uri, uri_len, FILE_SCHEMA "%s", id);
186     return uri;
187 }
188
189 static inline int event_handler_wrapper(dynamicbox_buffer_h buffer, dynamicbox_buffer_event_data_t event_info, void *data)
190 {
191     const char *pkgname;
192     const char *id;
193     struct dynamicbox_buffer_data *cbdata = data;
194     int ret;
195
196     pkgname = dynamicbox_provider_buffer_pkgname(buffer);
197     if (!pkgname) {
198         ErrPrint("pkgname is not valid\n");
199         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
200     }
201
202     id = dynamicbox_provider_buffer_id(buffer);
203     if (!id) {
204         ErrPrint("id is not valid[%s]\n", pkgname);
205         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
206     }
207
208     if (cbdata->handler) {
209         ret = cbdata->handler(buffer, event_info, cbdata->cbdata);
210     } else {
211         ret = DBOX_STATUS_ERROR_FAULT;
212     }
213
214     switch (event_info->type) {
215         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT:
216         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
217         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
218         case DBOX_BUFFER_EVENT_ACCESS_ACTIVATE:
219         case DBOX_BUFFER_EVENT_ACCESS_ACTION_UP:
220         case DBOX_BUFFER_EVENT_ACCESS_ACTION_DOWN:
221         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_UP:
222         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
223         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
224         case DBOX_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
225         case DBOX_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
226         case DBOX_BUFFER_EVENT_ACCESS_MOUSE:
227         case DBOX_BUFFER_EVENT_ACCESS_BACK:
228         case DBOX_BUFFER_EVENT_ACCESS_OVER:
229         case DBOX_BUFFER_EVENT_ACCESS_READ:
230         case DBOX_BUFFER_EVENT_ACCESS_ENABLE:
231         case DBOX_BUFFER_EVENT_ACCESS_DISABLE:
232             DbgPrint("Accessibility event: %d\n", event_info->type);
233             if (ret < 0) {
234                 (void)dynamicbox_provider_send_access_status(pkgname, id, DBOX_ACCESS_STATUS_ERROR);
235             } else {
236                 (void)dynamicbox_provider_send_access_status(pkgname, id, ret);
237             }
238             break;
239         case DBOX_BUFFER_EVENT_KEY_UP:
240         case DBOX_BUFFER_EVENT_KEY_DOWN:
241         case DBOX_BUFFER_EVENT_KEY_FOCUS_IN:
242         case DBOX_BUFFER_EVENT_KEY_FOCUS_OUT:
243             DbgPrint("Key event: %d\n", event_info->type);
244             if (ret < 0) {
245                 (void)dynamicbox_provider_send_key_status(pkgname, id, DBOX_KEY_STATUS_ERROR);
246             } else {
247                 (void)dynamicbox_provider_send_key_status(pkgname, id, ret);
248             }
249             break;
250         default:
251             break;
252     }
253
254     return ret;
255 }
256
257 static inline int default_event_handler(dynamicbox_buffer_h buffer, dynamicbox_buffer_event_data_t event_info, void *data)
258 {
259     /* NOP */
260     return 0;
261 }
262
263 PUBLIC const int DBOX_DONE = 0x00;
264 PUBLIC const int DBOX_OUTPUT_UPDATED = 0x02;
265 PUBLIC const int DBOX_USE_NET = 0x04;
266
267 PUBLIC const int DBOX_NEED_TO_SCHEDULE = 0x01;
268 PUBLIC const int DBOX_NEED_TO_CREATE = 0x01;
269 PUBLIC const int DBOX_NEED_TO_DESTROY = 0x01;
270 PUBLIC const int DBOX_FORCE_TO_SCHEDULE = 0x08;
271
272 PUBLIC const int DBOX_SYS_EVENT_FONT_CHANGED = 0x01;
273 PUBLIC const int DBOX_SYS_EVENT_LANG_CHANGED = 0x02;
274 PUBLIC const int DBOX_SYS_EVENT_TIME_CHANGED = 0x04;
275 PUBLIC const int DBOX_SYS_EVENT_REGION_CHANGED = 0x08;
276 PUBLIC const int DBOX_SYS_EVENT_TTS_CHANGED = 0x10;
277 PUBLIC const int DBOX_SYS_EVENT_PAUSED = 0x0100;
278 PUBLIC const int DBOX_SYS_EVENT_RESUMED = 0x0200;
279 PUBLIC const int DBOX_SYS_EVENT_MMC_STATUS_CHANGED = 0x0400;
280 PUBLIC const int DBOX_SYS_EVENT_DELETED = 0x0800;
281
282 PUBLIC struct dynamicbox_desc *dynamicbox_desc_open(const char *filename, int for_pd)
283 {
284     struct dynamicbox_desc *handle;
285     char *new_fname;
286
287     handle = calloc(1, sizeof(*handle));
288     if (!handle) {
289         ErrPrint("Error: %s\n", strerror(errno));
290         return NULL;
291     }
292
293     if (for_pd) {
294         int len;
295         len = strlen(filename) + strlen(".desc") + 1;
296         new_fname = malloc(len);
297         if (!new_fname) {
298             ErrPrint("Error: %s\n", strerror(errno));
299             free(handle);
300             return NULL;
301         }
302         snprintf(new_fname, len, "%s.desc", filename);
303     } else {
304         new_fname = strdup(filename);
305         if (!new_fname) {
306             ErrPrint("Error: %s\n", strerror(errno));
307             free(handle);
308             return NULL;
309         }
310     }
311
312     DbgPrint("Open a file %s with merge mode %s\n",
313             new_fname,
314             access(new_fname, F_OK) == 0 ? "enabled" : "disabled");
315
316     handle->fp = fopen(new_fname, "at");
317     free(new_fname);
318     if (!handle->fp) {
319         ErrPrint("Failed to open a file: %s\n", strerror(errno));
320         free(handle);
321         return NULL;
322     }
323
324     return handle;
325 }
326
327 PUBLIC int dynamicbox_desc_close(struct dynamicbox_desc *handle)
328 {
329     struct dlist *l;
330     struct dlist *n;
331     struct block *block;
332
333     if (!handle) {
334         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
335     }
336
337     dlist_foreach_safe(handle->block_list, l, n, block) {
338         handle->block_list = dlist_remove(handle->block_list, l);
339
340         fprintf(handle->fp, "{\n");
341         if (block->type) {
342             fprintf(handle->fp, "type=%s\n", block->type);
343         }
344
345         if (block->part) {
346             fprintf(handle->fp, "part=%s\n", block->part);
347         }
348
349         if (block->data) {
350             fprintf(handle->fp, "data=%s\n", block->data);
351         }
352
353         if (block->option) {
354             fprintf(handle->fp, "option=%s\n", block->option);
355         }
356
357         if (block->id) {
358             fprintf(handle->fp, "id=%s\n", block->id);
359         }
360
361         if (block->target_id) {
362             fprintf(handle->fp, "target=%s\n", block->target_id);
363         }
364         fprintf(handle->fp, "}\n");
365
366         free(block->type);
367         free(block->part);
368         free(block->data);
369         free(block->option);
370         free(block->id);
371         free(block->target_id);
372         free(block);
373     }
374
375     if (fclose(handle->fp) != 0) {
376         ErrPrint("fclose: %s\n", strerror(errno));
377     }
378     free(handle);
379     return DBOX_STATUS_ERROR_NONE;
380 }
381
382 PUBLIC int dynamicbox_desc_set_category(struct dynamicbox_desc *handle, const char *id, const char *category)
383 {
384     struct block *block;
385
386     if (!handle || !category) {
387         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
388     }
389
390     block = calloc(1, sizeof(*block));
391     if (!block) {
392         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
393     }
394
395     block->type = strdup(DBOX_DESC_TYPE_INFO);
396     if (!block->type) {
397         free(block);
398         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
399     }
400
401     block->part = strdup("category");
402     if (!block->part) {
403         free(block->type);
404         free(block);
405         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
406     }
407
408     block->data = strdup(category);
409     if (!block->data) {
410         free(block->type);
411         free(block->part);
412         free(block);
413         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
414     }
415
416     if (id) {
417         block->id = strdup(id);
418         if (!block->id) {
419             free(block->data);
420             free(block->type);
421             free(block->part);
422             free(block);
423             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
424         }
425     }
426
427     block->idx = handle->last_idx++;
428     handle->block_list = dlist_append(handle->block_list, block);
429     return block->idx;
430 }
431
432 PUBLIC int dynamicbox_desc_set_size(struct dynamicbox_desc *handle, const char *id, int w, int h)
433 {
434     struct block *block;
435     char buffer[BUFSIZ];
436
437     if (!handle) {
438         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
439     }
440
441     block = calloc(1, sizeof(*block));
442     if (!block) {
443         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
444     }
445
446     block->type = strdup(DBOX_DESC_TYPE_INFO);
447     if (!block->type) {
448         free(block);
449         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
450     }
451
452     block->part = strdup("size");
453     if (!block->part) {
454         free(block->type);
455         free(block);
456         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
457     }
458
459     if (id) {
460         block->id = strdup(id);
461         if (!block->id) {
462             free(block->part);
463             free(block->type);
464             free(block);
465             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
466         }
467     }
468
469     snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
470     block->data = strdup(buffer);
471     if (!block->data) {
472         free(block->id);
473         free(block->part);
474         free(block->type);
475         free(block);
476         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
477     }
478
479     block->idx = handle->last_idx++;
480     handle->block_list = dlist_append(handle->block_list, block);
481     return block->idx;
482 }
483
484 PUBLIC int dynamicbox_desc_set_id(struct dynamicbox_desc *handle, int idx, const char *id)
485 {
486     struct dlist *l;
487     struct block *block;
488
489     dlist_foreach(handle->block_list, l, block) {
490         if (block->idx == idx) {
491             if (strcasecmp(block->type, DBOX_DESC_TYPE_SCRIPT)) {
492                 ErrPrint("Invalid block is used\n");
493                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
494             }
495
496             free(block->target_id);
497             block->target_id = NULL;
498
499             if (!id || !strlen(id)) {
500                 return DBOX_STATUS_ERROR_NONE;
501             }
502
503             block->target_id = strdup(id);
504             if (!block->target_id) {
505                 ErrPrint("Heap: %s\n", strerror(errno));
506                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
507             }
508
509             return DBOX_STATUS_ERROR_NONE;
510         }
511     }
512
513     return DBOX_STATUS_ERROR_NOT_EXIST;
514 }
515
516 /*!
517  * \return idx
518  */
519 PUBLIC int dynamicbox_desc_add_block(struct dynamicbox_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option)
520 {
521     struct block *block;
522
523     if (!handle || !type) {
524         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
525     }
526
527     if (!part) {
528         part = "";
529     }
530
531     if (!data) {
532         data = "";
533     }
534
535     block = calloc(1, sizeof(*block));
536     if (!block) {
537         ErrPrint("Heap: %s\n", strerror(errno));
538         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
539     }
540
541     block->type = strdup(type);
542     if (!block->type) {
543         ErrPrint("Heap: %s\n", strerror(errno));
544         free(block);
545         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
546     }
547
548     block->part = strdup(part);
549     if (!block->part) {
550         ErrPrint("Heap: %s\n", strerror(errno));
551         free(block->type);
552         free(block);
553         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
554     }
555
556     block->data = strdup(data);
557     if (!block->data) {
558         ErrPrint("Heap: %s\n", strerror(errno));
559         free(block->type);
560         free(block->part);
561         free(block);
562         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
563     }
564
565     if (option) {
566         block->option = strdup(option);
567         if (!block->option) {
568             ErrPrint("Heap: %s\n", strerror(errno));
569             free(block->data);
570             free(block->type);
571             free(block->part);
572             free(block);
573             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
574         }
575     }
576
577     if (id) {
578         block->id = strdup(id);
579         if (!block->id) {
580             ErrPrint("Heap: %s\n", strerror(errno));
581             free(block->option);
582             free(block->data);
583             free(block->type);
584             free(block->part);
585             free(block);
586             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
587         }
588     }
589
590     block->idx = handle->last_idx++;
591     handle->block_list = dlist_append(handle->block_list, block);
592     return block->idx;
593 }
594
595 PUBLIC int dynamicbox_desc_del_block(struct dynamicbox_desc *handle, int idx)
596 {
597     struct dlist *l;
598     struct block *block;
599
600     if (!handle || idx < 0) {
601         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
602     }
603
604     dlist_foreach(handle->block_list, l, block) {
605         if (block->idx == idx) {
606             handle->block_list = dlist_remove(handle->block_list, l);
607             free(block->type);
608             free(block->part);
609             free(block->data);
610             free(block->option);
611             free(block->id);
612             free(block->target_id);
613             free(block);
614             return DBOX_STATUS_ERROR_NONE;
615         }
616     }
617
618     return DBOX_STATUS_ERROR_NOT_EXIST;
619 }
620
621 PUBLIC int dynamicbox_acquire_buffer(dynamicbox_buffer_h handle, int idx, int width, int height, int pixel_size)
622 {
623     int ret;
624
625     if (!handle || width <= 0 || height <= 0 || pixel_size <= 0 || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
626         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
627     }
628
629     if (idx >= 0) {
630         int _width = 0;
631         int _height = 0;
632         int _pixel_size = 0;
633         /* To validate the buffer */
634         if (dynamicbox_provider_buffer_get_size(handle, &_width, &_height, &_pixel_size) < 0) {
635             ErrPrint("Failed to get buffer size\n");
636         }
637
638         if (_width != width || _height != height || pixel_size != _pixel_size) {
639             DbgPrint("Extra buffer's geometry is not matched with primary one\n");
640         }
641
642         ret = dynamicbox_provider_buffer_extra_acquire(handle, idx, width, height, pixel_size);
643     } else {
644         ret = dynamicbox_provider_buffer_acquire(handle, width, height, pixel_size);
645     }
646
647     return ret;
648 }
649
650 PUBLIC dynamicbox_buffer_h dynamicbox_create_buffer(const char *filename, int is_gbar, int auto_align, int (*handler)(dynamicbox_buffer_h , dynamicbox_buffer_event_data_t, void *), void *data)
651 {
652     struct dynamicbox_buffer_data *user_data;
653     const char *pkgname;
654     dynamicbox_buffer_h handle;
655     char *uri;
656
657     if (!filename) {
658         ErrPrint("Invalid argument: %p(%dx%d)\n", filename);
659         return NULL;
660     }
661
662     user_data = calloc(1, sizeof(*user_data));
663     if (!user_data) {
664         ErrPrint("Heap: %s\n", strerror(errno));
665         return NULL;
666     }
667
668     user_data->is_gbar = is_gbar;
669     user_data->handler = handler ? handler : default_event_handler;
670     user_data->cbdata = data;
671
672     uri = id_to_uri(filename);
673     if (!uri) {
674         ErrPrint("Heap: %s\n", strerror(errno));
675         free(user_data);
676         return NULL;
677     }
678
679     if (!s_info.find_pkgname) {
680         s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_FIND_PKGNAME);
681         if (!s_info.find_pkgname) {
682             ErrPrint("Failed to find a \"dynamicbox_find_pkgname\"\n");
683             free(user_data);
684             free(uri);
685             return NULL;
686         }
687     }
688
689     pkgname = s_info.find_pkgname(uri);
690     if (!pkgname) {
691         ErrPrint("Invalid Request\n");
692         free(user_data);
693         free(uri);
694         return NULL;
695     }
696
697     handle = dynamicbox_provider_buffer_create((!!is_gbar) ? DBOX_TYPE_GBAR : DBOX_TYPE_DBOX, pkgname, uri, auto_align, event_handler_wrapper, user_data);
698     free(uri);
699     if (!handle) {
700         free(user_data);
701         return NULL;
702     }
703
704     (void)dynamicbox_provider_buffer_set_user_data(handle, user_data);
705     return handle;
706 }
707
708 PUBLIC int dynamicbox_request_update(const char *filename)
709 {
710     char *uri;
711     int ret;
712
713     if (!filename) {
714         ErrPrint("Invalid argument\n");
715         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
716     }
717
718     uri = id_to_uri(filename);
719     if (!uri) {
720         ErrPrint("Heap: %s\n", strerror(errno));
721         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
722     }
723
724     if (!s_info.request_update_by_id) {
725         s_info.request_update_by_id = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_REQUEST_UPDATE_BY_ID);
726         if (!s_info.request_update_by_id) {
727             ErrPrint("\"dynamicbox_request_update_by_id\" is not exists\n");
728             free(uri);
729             return DBOX_STATUS_ERROR_FAULT;
730         }
731     }
732
733     ret = s_info.request_update_by_id(uri);
734     free(uri);
735     return ret;
736 }
737
738 PUBLIC unsigned int dynamicbox_resource_id(dynamicbox_buffer_h handle, int idx)
739 {
740     int ret;
741
742     if (!handle || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
743         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
744     }
745
746     if (idx >= 0) {
747         ret = dynamicbox_provider_buffer_extra_resource_id(handle, idx);
748     } else {
749         ret = dynamicbox_provider_buffer_resource_id(handle);
750     }
751
752     return ret;
753 }
754
755 PUBLIC int dynamicbox_release_buffer(dynamicbox_buffer_h handle, int idx)
756 {
757     int ret;
758
759     if (!handle || idx > DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
760         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
761     }
762
763     if (idx >= 0) {
764         ret = dynamicbox_provider_buffer_extra_release(handle, idx);
765     } else {
766         ret = dynamicbox_provider_buffer_release(handle);
767     }
768
769     DbgPrint("Release buffer: %d (%d)\n", idx, ret);
770     return ret;
771 }
772
773 PUBLIC int dynamicbox_destroy_buffer(dynamicbox_buffer_h handle)
774 {
775     struct dynamicbox_buffer_data *user_data;
776
777     if (!handle) {
778         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
779     }
780
781     user_data = dynamicbox_provider_buffer_user_data(handle);
782     if (user_data) {
783         if (user_data->frame_wait_timer) {
784             ecore_timer_del(user_data->frame_wait_timer);
785             user_data->frame_wait_timer = NULL;
786         }
787         free(user_data->content);
788         free(user_data->title);
789         free(user_data->icon);
790         free(user_data->name);
791         free(user_data);
792         dynamicbox_provider_buffer_set_user_data(handle, NULL);
793     }
794
795     DbgPrint("Destroy buffer\n");
796     return dynamicbox_provider_buffer_destroy(handle);
797 }
798
799 PUBLIC void *dynamicbox_ref_buffer(dynamicbox_buffer_h handle)
800 {
801     struct dynamicbox_buffer_data *user_data;
802     void *data;
803     int w, h, size;
804     int ret;
805
806     if (!handle) {
807         return NULL;
808     }
809
810     user_data = dynamicbox_provider_buffer_user_data(handle);
811     if (!user_data) {
812         return NULL;
813     }
814
815     if (user_data->accelerated) {
816         DbgPrint("H/W accelerated buffer is allocated\n");
817         return NULL;
818     }
819
820     ret = dynamicbox_provider_buffer_get_size(handle, &w, &h, &size);
821
822     data = dynamicbox_provider_buffer_ref(handle);
823     if (data && !ret && w > 0 && h > 0 && size > 0) {
824         memset(data, 0, w * h * size);
825         (void)dynamicbox_provider_buffer_sync(handle);
826     }
827
828     DbgPrint("Ref buffer %ds%d(%d)\n", w, h, size);
829     return data;
830 }
831
832 PUBLIC int dynamicbox_unref_buffer(void *buffer)
833 {
834     if (!buffer) {
835         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
836     }
837
838     DbgPrint("Unref buffer\n");
839     return dynamicbox_provider_buffer_unref(buffer);
840 }
841
842 PUBLIC int dynamicbox_sync_buffer(dynamicbox_buffer_h handle)
843 {
844     struct dynamicbox_buffer_data *user_data;
845     const char *pkgname;
846     const char *id;
847     int w;
848     int h;
849     int pixel_size;
850     int ret;
851
852     if (!handle) {
853         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
854     }
855
856     user_data = dynamicbox_provider_buffer_user_data(handle);
857     if (!user_data) {
858         ErrPrint("Invalid buffer\n");
859         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
860     }
861
862     if (user_data->accelerated) {
863         DbgPrint("H/W Buffer allocated. skip the sync buffer\n");
864         return DBOX_STATUS_ERROR_NONE;
865     }
866
867     pkgname = dynamicbox_provider_buffer_pkgname(handle);
868     if (!pkgname) {
869         ErrPrint("Invalid buffer handler\n");
870         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
871     }
872
873     id = dynamicbox_provider_buffer_id(handle);
874     if (!id) {
875         ErrPrint("Invalid buffer handler\n");
876         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
877     }
878
879     (void)dynamicbox_provider_buffer_sync(handle);
880
881     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
882         ErrPrint("Failed to get size (%s)\n", id);
883     }
884
885     /**
886      * @todo
887      * manipulate the damaged region, so send update event only for the damaged region.
888      * to make more efficient updates
889      */
890     ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
891     if (ret < 0) {
892         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
893     }
894
895     return ret;
896 }
897
898 PUBLIC int dynamicbox_send_updated_by_idx(dynamicbox_buffer_h handle, int idx)
899 {
900     struct dynamicbox_buffer_data *user_data;
901     const char *pkgname;
902     const char *id;
903     int w;
904     int h;
905     int pixel_size;
906     int ret;
907
908     user_data = dynamicbox_provider_buffer_user_data(handle);
909     if (!user_data) {
910         ErrPrint("Invalid buffer\n");
911         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
912     }
913
914     pkgname = dynamicbox_provider_buffer_pkgname(handle);
915     if (!pkgname) {
916         ErrPrint("Invalid buffer handler\n");
917         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
918     }
919
920     id = dynamicbox_provider_buffer_id(handle);
921     if (!id) {
922         ErrPrint("Invalid buffer handler\n");
923         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
924     }
925
926     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
927         ErrPrint("Failed to get size (%s)\n", id);
928     }
929
930     ret = send_updated(pkgname, id, handle, idx, 0, 0, w, h, user_data->is_gbar, NULL);
931     if (ret < 0) {
932         ErrPrint("Failed to send%supdated (%s) %d\n", user_data->is_gbar ? " GBAR " : " ", id, idx);
933     }
934
935     return ret;
936 }
937
938 PUBLIC int dynamicbox_support_hw_buffer(dynamicbox_buffer_h handle)
939 {
940     if (!handle) {
941         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
942     }
943
944     return dynamicbox_provider_buffer_is_support_hw(handle);
945 }
946
947 PUBLIC int dynamicbox_create_hw_buffer(dynamicbox_buffer_h handle)
948 {
949     struct dynamicbox_buffer_data *user_data;
950     int ret;
951
952     if (!handle) {
953         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
954     }
955
956     user_data = dynamicbox_provider_buffer_user_data(handle);
957     if (!user_data) {
958         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
959     }
960
961     if (user_data->accelerated) {
962         return DBOX_STATUS_ERROR_ALREADY;
963     }
964
965     ret = dynamicbox_provider_buffer_create_hw(handle);
966     user_data->accelerated = (ret == 0);
967     return ret;
968 }
969
970 PUBLIC int dynamicbox_destroy_hw_buffer(dynamicbox_buffer_h handle)
971 {
972     struct dynamicbox_buffer_data *user_data;
973
974     if (!handle) {
975         LOGD("handle is NULL\n");
976         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
977     }
978
979     user_data = dynamicbox_provider_buffer_user_data(handle);
980     if (!user_data || !user_data->accelerated) {
981         LOGD("user_data is NULL\n");
982         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
983     }
984
985     user_data->accelerated = 0;
986
987     return dynamicbox_provider_buffer_destroy_hw(handle);
988 }
989
990 PUBLIC void *dynamicbox_buffer_hw_buffer(dynamicbox_buffer_h handle)
991 {
992     struct dynamicbox_buffer_data *user_data;
993
994     if (!handle) {
995         return NULL;
996     }
997
998     user_data = dynamicbox_provider_buffer_user_data(handle);
999     if (!user_data || !user_data->accelerated) {
1000         return NULL;
1001     }
1002
1003     return dynamicbox_provider_buffer_hw_addr(handle);
1004 }
1005
1006 PUBLIC int dynamicbox_buffer_pre_render(dynamicbox_buffer_h handle)
1007 {
1008     struct dynamicbox_buffer_data *user_data;
1009
1010     if (!handle) {
1011         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1012     }
1013
1014     user_data = dynamicbox_provider_buffer_user_data(handle);
1015     if (!user_data) {
1016         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1017     }
1018
1019     if (!user_data->accelerated) {
1020         return DBOX_STATUS_ERROR_NONE;
1021     }
1022
1023     /*!
1024      * \note
1025      * Do preprocessing for accessing the H/W render buffer
1026      */
1027     return dynamicbox_provider_buffer_pre_render(handle);
1028 }
1029
1030 static Eina_Bool frame_wait_cb(void *data)
1031 {
1032     dynamicbox_buffer_h handle = data;
1033     struct dynamicbox_buffer_data *user_data;
1034     const char *pkgname;
1035     const char *id;
1036     int pixel_size;
1037     int ret;
1038     int w;
1039     int h;
1040
1041     user_data = dynamicbox_provider_buffer_user_data(handle);
1042     if (!user_data) {
1043         ErrPrint("Failed to get a user data\n");
1044         return ECORE_CALLBACK_CANCEL;
1045     }
1046
1047     pkgname = dynamicbox_provider_buffer_pkgname(handle);
1048     id = dynamicbox_provider_buffer_id(handle);
1049
1050     if (!pkgname || !id) {
1051         ErrPrint("Failed to get instance information (%s), (%s)\n", pkgname, id);
1052         user_data->frame_wait_timer = NULL;
1053         return ECORE_CALLBACK_CANCEL;
1054     }
1055
1056     if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1057         ErrPrint("Failed to get size (%s)\n", id);
1058         w = 0;
1059         h = 0;
1060         pixel_size = sizeof(int);
1061     }
1062
1063     DbgPrint("Frame skip waiting timer is fired (%s)\n", id);
1064
1065     /**
1066      * @todo
1067      * manipulate the damaged region, so send update event only for the damaged region.
1068      * to make more efficient updates
1069      */
1070     ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1071     if (ret < 0) {
1072         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1073     }
1074
1075     (void)dynamicbox_provider_buffer_clear_frame_skip(handle);
1076
1077     user_data->frame_wait_timer = NULL;
1078     return ECORE_CALLBACK_CANCEL;
1079 }
1080
1081 PUBLIC int dynamicbox_buffer_post_render(dynamicbox_buffer_h handle)
1082 {
1083     int ret;
1084     const char *pkgname;
1085     const char *id;
1086     struct dynamicbox_buffer_data *user_data;
1087     int w;
1088     int h;
1089     int pixel_size;
1090     PERF_INIT();
1091     PERF_BEGIN();
1092
1093     if (!handle) {
1094         PERF_MARK("post_render");
1095         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1096     }
1097
1098     user_data = dynamicbox_provider_buffer_user_data(handle);
1099     if (!user_data) {
1100         PERF_MARK("post_render");
1101         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1102     }
1103
1104     if (!user_data->accelerated) {
1105         PERF_MARK("post_render");
1106         return DBOX_STATUS_ERROR_NONE;
1107     }
1108
1109     pkgname = dynamicbox_provider_buffer_pkgname(handle);
1110     if (!pkgname) {
1111         ErrPrint("Invalid buffer handle\n");
1112         PERF_MARK("post_render");
1113         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1114     }
1115
1116     id = dynamicbox_provider_buffer_id(handle);
1117     if (!id) {
1118         ErrPrint("Invalid buffer handler\n");
1119         PERF_MARK("post_render");
1120         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1121     }
1122
1123     ret = dynamicbox_provider_buffer_post_render(handle);
1124     if (ret < 0) {
1125         ErrPrint("Failed to post render processing\n");
1126         PERF_MARK("post_render");
1127         return ret;
1128     }
1129
1130     if (dynamicbox_provider_buffer_frame_skip(handle) == 0) {
1131         if (dynamicbox_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1132             ErrPrint("Failed to get size (%s)\n", id);
1133         }
1134
1135         /**
1136          * @todo
1137          * manipulate the damaged region, so send update event only for the damaged region.
1138          * to make more efficient updates
1139          */
1140         ret = send_updated(pkgname, id, handle, DBOX_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1141         if (ret < 0) {
1142             ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1143         }
1144
1145         if (user_data->frame_wait_timer) {
1146             ecore_timer_del(user_data->frame_wait_timer);
1147             user_data->frame_wait_timer = NULL;
1148         }
1149     } else {
1150         if (user_data->frame_wait_timer) {
1151             ecore_timer_reset(user_data->frame_wait_timer);
1152         } else {
1153             user_data->frame_wait_timer = ecore_timer_add(FRAME_WAIT_INTERVAL, frame_wait_cb, handle);
1154             if (!user_data->frame_wait_timer) {
1155                 ErrPrint("Failed to add waiting timer for next frame\n");
1156             }
1157         }
1158     }
1159
1160     PERF_MARK("post_render");
1161     return ret;
1162 }
1163
1164 PUBLIC int dynamicbox_buffer_stride(dynamicbox_buffer_h handle)
1165 {
1166     if (!handle) {
1167         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1168     }
1169
1170     return dynamicbox_provider_buffer_stride(handle);
1171 }
1172
1173 PUBLIC int dynamicbox_content_is_updated(const char *filename, int is_gbar)
1174 {
1175     if (!s_info.trigger_update_monitor) {
1176         s_info.trigger_update_monitor = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_TRIGGER_UPDATE_MONITOR);
1177         if (!s_info.trigger_update_monitor) {
1178             ErrPrint("Trigger update monitor function is not exists\n");
1179             return DBOX_STATUS_ERROR_FAULT;
1180         }
1181     }
1182
1183     return s_info.trigger_update_monitor(filename, is_gbar);
1184 }
1185
1186 PUBLIC int dynamicbox_request_close_glance_bar(const char *pkgname, const char *id, int reason)
1187 {
1188     char *uri;
1189     int schema_len = strlen(FILE_SCHEMA);
1190     int ret;
1191
1192     if (!pkgname || !id) {
1193         ErrPrint("Invalid parameters (%s) (%s)\n", pkgname, id);
1194         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1195     }
1196
1197     if (strncmp(id, FILE_SCHEMA, schema_len)) {
1198         uri = id_to_uri(id);
1199         if (!uri) {
1200             ErrPrint("Heap: %s\n", strerror(errno));
1201             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1202         }
1203     } else {
1204         uri = strdup(id);
1205         if (!uri) {
1206             ErrPrint("Heap: %s\n", strerror(errno));
1207             return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1208         }
1209     }
1210
1211     ret = dynamicbox_provider_send_request_close_gbar(pkgname, uri, reason);
1212     free(uri);
1213     return ret;
1214 }
1215
1216 PUBLIC int dynamicbox_freeze_scroller(const char *pkgname, const char *id)
1217 {
1218     char *uri;
1219     int ret;
1220
1221     uri = id_to_uri(id);
1222     if (!uri) {
1223         ErrPrint("Heap: %s\n", strerror(errno));
1224         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1225     }
1226
1227     ret = dynamicbox_provider_send_hold_scroll(pkgname, uri, 1);
1228     free(uri);
1229     return ret;
1230 }
1231
1232 PUBLIC int dynamicbox_thaw_scroller(const char *pkgname, const char *id)
1233 {
1234     char *uri;
1235     int ret;
1236
1237     uri = id_to_uri(id);
1238     if (!uri) {
1239         ErrPrint("Heap: %s\n", strerror(errno));
1240         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1241     }
1242
1243     ret = dynamicbox_provider_send_hold_scroll(pkgname, uri, 0);
1244     free(uri);
1245     return ret;
1246 }
1247
1248 PUBLIC int dynamicbox_set_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1249 {
1250     dynamicbox_buffer_h handle;
1251     const char *pkgname;
1252     char *uri;
1253
1254     uri = id_to_uri(id);
1255     if (!uri) {
1256         ErrPrint("Heap: %s\n", strerror(errno));
1257         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1258     }
1259
1260     if (!s_info.find_pkgname) {
1261         s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_FIND_PKGNAME);
1262         if (!s_info.find_pkgname) {
1263             ErrPrint("Failed to find a \"dynamicbox_find_pkgname\"\n");
1264             free(uri);
1265             return DBOX_STATUS_ERROR_FAULT;
1266         }
1267     }
1268
1269     pkgname = s_info.find_pkgname(uri);
1270     if (!pkgname) {
1271         ErrPrint("Failed to find a package (%s)\n", uri);
1272         free(uri);
1273         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1274     }
1275
1276     handle = dynamicbox_provider_buffer_find_buffer(DBOX_TYPE_DBOX, pkgname, uri);
1277     if (handle) {
1278         struct dynamicbox_buffer_data *user_data;
1279
1280         user_data = dynamicbox_provider_buffer_user_data(handle);
1281         if (!user_data) {
1282             ErrPrint("User data is not available\n");
1283             free(uri);
1284             return DBOX_STATUS_ERROR_FAULT;
1285         }
1286
1287         if (content && strlen(content)) {
1288             char *_content;
1289
1290             _content = strdup(content);
1291             if (_content) {
1292                 if (user_data->content) {
1293                     free(user_data->content);
1294                 }
1295
1296                 user_data->content = _content;
1297             } else {
1298                 ErrPrint("Heap: %s\n", strerror(errno));
1299             }
1300         }
1301
1302         if (title && strlen(title)) {
1303             char *_title;
1304
1305             _title = strdup(title);
1306             if (_title) {
1307                 if (user_data->title) {
1308                     free(user_data->title);
1309                 }
1310
1311                 user_data->title = _title;
1312             } else {
1313                 ErrPrint("Heap: %s\n", strerror(errno));
1314             }
1315         }
1316
1317         if (icon && strlen(icon)) {
1318             char *_icon;
1319
1320             _icon = strdup(icon);
1321             if (_icon) {
1322                 if (user_data->icon) {
1323                     free(user_data->icon);
1324                 }
1325
1326                 user_data->icon = _icon;
1327             } else {
1328                 ErrPrint("Heap: %s\n", strerror(errno));
1329             }
1330         }
1331
1332         if (name && strlen(name)) {
1333             char *_name;
1334
1335             _name = strdup(name);
1336             if (_name) {
1337                 if (user_data->name) {
1338                     free(user_data->name);
1339                 }
1340
1341                 user_data->name = _name;
1342             } else {
1343                 ErrPrint("Heap: %s\n", strerror(errno));
1344             }
1345         }
1346
1347         if (dynamicbox_provider_send_extra_info(pkgname, uri, -1.0f, user_data->content, user_data->title, user_data->icon, user_data->name) < 0) {
1348             ErrPrint("Failed to send extra info (%s)\n", id);
1349         }
1350
1351         free(uri);
1352         return DBOX_STATUS_ERROR_NONE;
1353     }
1354     free(uri);
1355
1356     if (!s_info.update_extra_info) {
1357         s_info.update_extra_info = dlsym(RTLD_DEFAULT, FUNC_DYNAMICBOX_UPDATE_EXTRA_INFO);
1358         if (!s_info.update_extra_info) {
1359             ErrPrint("Failed to find a \"dynamicbox_update_extra_info\"\n");
1360             return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1361         }
1362     }
1363
1364     return s_info.update_extra_info(id, content, title, icon, name);
1365 }
1366
1367 /* End of a file */