Merge branch 'tizen_2.4' into tizen_2.3
[apps/native/widget/widget.git] / src / widget.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 <widget_errno.h>
28 #include <widget_service.h>
29 #include <widget_service_internal.h>
30 #include <widget_provider.h>
31 #include <widget_provider_buffer.h>
32 #include <widget_conf.h>
33 #include <widget_buffer.h>
34 #include <widget_util.h>
35
36 #include "debug.h"
37 #include "dlist.h"
38 #include "util.h"
39 #include "widget.h"
40 #include "widget_internal.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 widget_desc {
65         FILE *fp;
66         int for_pd;
67
68         unsigned int last_idx;
69
70         struct dlist *block_list;
71 };
72
73 struct widget_buffer_data {
74         int is_gbar;
75         int accelerated;
76
77         /* for Buffer event wrapper */
78         int (*handler)(widget_buffer_h , widget_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, widget_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)(widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar);
111                         int (*add_pre_callback)(widget_pre_callback_e type, widget_pre_callback_t cb, void *data);
112                         int (*del_pre_callback)(widget_pre_callback_e type, widget_pre_callback_t cb, void *data);
113                 } app;
114         } binder;
115 } s_info = {
116         .find_pkgname = NULL,
117         .request_update_by_id = NULL,
118         .trigger_update_monitor = NULL,
119         .update_extra_info = NULL,
120         .type = LOAD_TYPE_UNKNOWN,    /* Not initialized */
121         .binder = {
122                 .slave = {
123                         .send = NULL,
124                 },
125                 .app = {
126                         .send = NULL,
127                         .add_pre_callback = NULL,
128                         .del_pre_callback = NULL,
129                 },
130         },
131 };
132
133 #define FUNC_PREFIX                               "widget_"
134 #define FUNC_WIDGET_SEND_UPDATED              FUNC_PREFIX "send_buffer_updated"
135 #define FUNC_WIDGET_PROVIDER_APP_UPDATED      FUNC_PREFIX "provider_app_buffer_updated"
136 #define FUNC_WIDGET_FIND_PKGNAME              FUNC_PREFIX "find_pkgname"
137 #define FUNC_WIDGET_REQUEST_UPDATE_BY_ID      FUNC_PREFIX "request_update_by_id"
138 #define FUNC_WIDGET_TRIGGER_UPDATE_MONITOR    FUNC_PREFIX "trigger_update_monitor"
139 #define FUNC_WIDGET_UPDATE_EXTRA_INFO         FUNC_PREFIX "update_extra_info"
140 #define FUNC_WIDGET_ADD_PRE_CALLBACK          FUNC_PREFIX "provider_app_add_pre_callback"
141 #define FUNC_WIDGET_DEL_PRE_CALLBACK          FUNC_PREFIX "provider_app_del_pre_callback"
142
143 static inline void load_update_function(void)
144 {
145         /* Must to be checked the slave function first. */
146         s_info.binder.slave.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_SEND_UPDATED);
147         if (s_info.binder.slave.send) {
148                 s_info.type = LOAD_TYPE_SLAVE;
149                 DbgPrint("Slave detected\n");
150         } else {
151                 s_info.binder.app.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_UPDATED);
152                 if (s_info.binder.app.send) {
153                         s_info.type = LOAD_TYPE_APP;
154                         DbgPrint("App detected\n");
155                 }
156         }
157 }
158
159 int widget_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
160 {
161         static int loaded = 0;
162         if (!loaded && !s_info.binder.app.add_pre_callback) {
163                 s_info.binder.app.add_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_ADD_PRE_CALLBACK);
164                 loaded = 1;
165         }
166
167         if (!s_info.binder.app.add_pre_callback) {
168                 return WIDGET_ERROR_NOT_SUPPORTED;
169         }
170
171         return s_info.binder.app.add_pre_callback(type, cb, data);
172 }
173
174 int widget_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
175 {
176         static int loaded = 0;
177         if (!loaded && !s_info.binder.app.del_pre_callback) {
178                 s_info.binder.app.del_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_DEL_PRE_CALLBACK);
179                 loaded = 1;
180         }
181
182         if (!s_info.binder.app.del_pre_callback) {
183                 return WIDGET_ERROR_NOT_SUPPORTED;
184         }
185
186         return s_info.binder.app.del_pre_callback(type, cb, data);
187 }
188
189 static int send_updated(const char *pkgname, const char *id, widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
190 {
191         int ret = WIDGET_ERROR_INVALID_PARAMETER;
192
193         if (s_info.type == LOAD_TYPE_UNKNOWN) {
194                 load_update_function();
195         }
196
197         if (s_info.type == LOAD_TYPE_APP) {
198                 ret = s_info.binder.app.send(handle, idx, x, y, w, h, gbar);
199         } else if (s_info.type == LOAD_TYPE_SLAVE) {
200                 /**
201                  * pkgname, id are used for finding handle of direct connection.
202                  */
203                 ret = s_info.binder.slave.send(pkgname, id, handle, idx, x, y, w, h, gbar, descfile);
204         } else {
205                 widget_damage_region_s region = {
206                         .x = x,
207                         .y = y,
208                         .w = w,
209                         .h = h,
210                 };
211                 ret = widget_provider_send_buffer_updated(handle, idx, &region, gbar, descfile);
212         }
213
214         return ret;
215 }
216
217 static char *id_to_uri(const char *id)
218 {
219         char *uri;
220         int uri_len;
221
222         uri_len = strlen(id) + strlen(FILE_SCHEMA) + 1;
223
224         uri = malloc(uri_len);
225         if (!uri) {
226                 return NULL;
227         }
228
229         snprintf(uri, uri_len, FILE_SCHEMA "%s", id);
230         return uri;
231 }
232
233 static inline int event_handler_wrapper(widget_buffer_h buffer, widget_buffer_event_data_t event_info, void *data)
234 {
235         const char *pkgname;
236         const char *id;
237         struct widget_buffer_data *cbdata = data;
238         int ret;
239
240         pkgname = widget_provider_buffer_pkgname(buffer);
241         if (!pkgname) {
242                 ErrPrint("pkgname is not valid\n");
243                 return WIDGET_ERROR_INVALID_PARAMETER;
244         }
245
246         id = widget_provider_buffer_id(buffer);
247         if (!id) {
248                 ErrPrint("id is not valid[%s]\n", pkgname);
249                 return WIDGET_ERROR_INVALID_PARAMETER;
250         }
251
252         if (cbdata->handler) {
253                 ret = cbdata->handler(buffer, event_info, cbdata->cbdata);
254         } else {
255                 ret = WIDGET_ERROR_FAULT;
256         }
257
258         switch (event_info->type) {
259         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
260         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
261         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
262         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
263         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
264         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_DOWN:
265         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_UP:
266         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
267         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
268         case WIDGET_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
269         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
270         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
271         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
272         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
273         case WIDGET_BUFFER_EVENT_ACCESS_READ:
274         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
275         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
276                 DbgPrint("Accessibility event: %d\n", event_info->type);
277                 if (ret < 0) {
278                         (void)widget_provider_send_access_status(pkgname, id, WIDGET_ACCESS_STATUS_ERROR);
279                 } else {
280                         (void)widget_provider_send_access_status(pkgname, id, ret);
281                 }
282                 break;
283         case WIDGET_BUFFER_EVENT_KEY_UP:
284         case WIDGET_BUFFER_EVENT_KEY_DOWN:
285         case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN:
286         case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT:
287                 DbgPrint("Key event: %d\n", event_info->type);
288                 if (ret < 0) {
289                         (void)widget_provider_send_key_status(pkgname, id, WIDGET_KEY_STATUS_ERROR);
290                 } else {
291                         (void)widget_provider_send_key_status(pkgname, id, ret);
292                 }
293                 break;
294         default:
295                 break;
296         }
297
298         return ret;
299 }
300
301 static inline int default_event_handler(widget_buffer_h buffer, widget_buffer_event_data_t event_info, void *data)
302 {
303         /* NOP */
304         return 0;
305 }
306
307 PUBLIC struct widget_desc *widget_desc_open(const char *filename, int for_pd)
308 {
309         struct widget_desc *handle;
310         char *new_fname;
311
312         handle = calloc(1, sizeof(*handle));
313         if (!handle) {
314                 ErrPrint("Error: %s\n", strerror(errno));
315                 return NULL;
316         }
317
318         if (for_pd) {
319                 int len;
320                 len = strlen(filename) + strlen(".desc") + 1;
321                 new_fname = malloc(len);
322                 if (!new_fname) {
323                         ErrPrint("Error: %s\n", strerror(errno));
324                         free(handle);
325                         return NULL;
326                 }
327                 snprintf(new_fname, len, "%s.desc", filename);
328         } else {
329                 new_fname = strdup(filename);
330                 if (!new_fname) {
331                         ErrPrint("Error: %s\n", strerror(errno));
332                         free(handle);
333                         return NULL;
334                 }
335         }
336
337         DbgPrint("Open a file %s with merge mode %s\n",
338                         new_fname,
339                         access(new_fname, F_OK) == 0 ? "enabled" : "disabled");
340
341         handle->fp = fopen(new_fname, "at");
342         free(new_fname);
343         if (!handle->fp) {
344                 ErrPrint("Failed to open a file: %s\n", strerror(errno));
345                 free(handle);
346                 return NULL;
347         }
348
349         return handle;
350 }
351
352 PUBLIC int widget_desc_close(struct widget_desc *handle)
353 {
354         struct dlist *l;
355         struct dlist *n;
356         struct block *block;
357
358         if (!handle) {
359                 return WIDGET_ERROR_INVALID_PARAMETER;
360         }
361
362         dlist_foreach_safe(handle->block_list, l, n, block) {
363                 handle->block_list = dlist_remove(handle->block_list, l);
364
365                 fprintf(handle->fp, "{\n");
366                 if (block->type) {
367                         fprintf(handle->fp, "type=%s\n", block->type);
368                 }
369
370                 if (block->part) {
371                         fprintf(handle->fp, "part=%s\n", block->part);
372                 }
373
374                 if (block->data) {
375                         fprintf(handle->fp, "data=%s\n", block->data);
376                 }
377
378                 if (block->option) {
379                         fprintf(handle->fp, "option=%s\n", block->option);
380                 }
381
382                 if (block->id) {
383                         fprintf(handle->fp, "id=%s\n", block->id);
384                 }
385
386                 if (block->target_id) {
387                         fprintf(handle->fp, "target=%s\n", block->target_id);
388                 }
389                 fprintf(handle->fp, "}\n");
390
391                 free(block->type);
392                 free(block->part);
393                 free(block->data);
394                 free(block->option);
395                 free(block->id);
396                 free(block->target_id);
397                 free(block);
398         }
399
400         if (fclose(handle->fp) != 0) {
401                 ErrPrint("fclose: %s\n", strerror(errno));
402         }
403         free(handle);
404         return WIDGET_ERROR_NONE;
405 }
406
407 PUBLIC int widget_desc_set_category(struct widget_desc *handle, const char *id, const char *category)
408 {
409         struct block *block;
410
411         if (!handle || !category) {
412                 return WIDGET_ERROR_INVALID_PARAMETER;
413         }
414
415         block = calloc(1, sizeof(*block));
416         if (!block) {
417                 return WIDGET_ERROR_OUT_OF_MEMORY;
418         }
419
420         block->type = strdup(WIDGET_DESC_TYPE_INFO);
421         if (!block->type) {
422                 free(block);
423                 return WIDGET_ERROR_OUT_OF_MEMORY;
424         }
425
426         block->part = strdup("category");
427         if (!block->part) {
428                 free(block->type);
429                 free(block);
430                 return WIDGET_ERROR_OUT_OF_MEMORY;
431         }
432
433         block->data = strdup(category);
434         if (!block->data) {
435                 free(block->type);
436                 free(block->part);
437                 free(block);
438                 return WIDGET_ERROR_OUT_OF_MEMORY;
439         }
440
441         if (id) {
442                 block->id = strdup(id);
443                 if (!block->id) {
444                         free(block->data);
445                         free(block->type);
446                         free(block->part);
447                         free(block);
448                         return WIDGET_ERROR_OUT_OF_MEMORY;
449                 }
450         }
451
452         block->idx = handle->last_idx++;
453         handle->block_list = dlist_append(handle->block_list, block);
454         return block->idx;
455 }
456
457 PUBLIC int widget_desc_set_size(struct widget_desc *handle, const char *id, int w, int h)
458 {
459         struct block *block;
460         char buffer[BUFSIZ];
461
462         if (!handle) {
463                 return WIDGET_ERROR_INVALID_PARAMETER;
464         }
465
466         block = calloc(1, sizeof(*block));
467         if (!block) {
468                 return WIDGET_ERROR_OUT_OF_MEMORY;
469         }
470
471         block->type = strdup(WIDGET_DESC_TYPE_INFO);
472         if (!block->type) {
473                 free(block);
474                 return WIDGET_ERROR_OUT_OF_MEMORY;
475         }
476
477         block->part = strdup("size");
478         if (!block->part) {
479                 free(block->type);
480                 free(block);
481                 return WIDGET_ERROR_OUT_OF_MEMORY;
482         }
483
484         if (id) {
485                 block->id = strdup(id);
486                 if (!block->id) {
487                         free(block->part);
488                         free(block->type);
489                         free(block);
490                         return WIDGET_ERROR_OUT_OF_MEMORY;
491                 }
492         }
493
494         snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
495         block->data = strdup(buffer);
496         if (!block->data) {
497                 free(block->id);
498                 free(block->part);
499                 free(block->type);
500                 free(block);
501                 return WIDGET_ERROR_OUT_OF_MEMORY;
502         }
503
504         block->idx = handle->last_idx++;
505         handle->block_list = dlist_append(handle->block_list, block);
506         return block->idx;
507 }
508
509 PUBLIC int widget_desc_set_id(struct widget_desc *handle, int idx, const char *id)
510 {
511         struct dlist *l;
512         struct block *block;
513
514         dlist_foreach(handle->block_list, l, block) {
515                 if (block->idx == idx) {
516                         if (strcasecmp(block->type, WIDGET_DESC_TYPE_SCRIPT)) {
517                                 ErrPrint("Invalid block is used\n");
518                                 return WIDGET_ERROR_INVALID_PARAMETER;
519                         }
520
521                         free(block->target_id);
522                         block->target_id = NULL;
523
524                         if (!id || !strlen(id)) {
525                                 return WIDGET_ERROR_NONE;
526                         }
527
528                         block->target_id = strdup(id);
529                         if (!block->target_id) {
530                                 ErrPrint("Heap: %s\n", strerror(errno));
531                                 return WIDGET_ERROR_OUT_OF_MEMORY;
532                         }
533
534                         return WIDGET_ERROR_NONE;
535                 }
536         }
537
538         return WIDGET_ERROR_NOT_EXIST;
539 }
540
541 /*!
542  * \return idx
543  */
544 PUBLIC int widget_desc_add_block(struct widget_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option)
545 {
546         struct block *block;
547
548         if (!handle || !type) {
549                 return WIDGET_ERROR_INVALID_PARAMETER;
550         }
551
552         if (!part) {
553                 part = "";
554         }
555
556         if (!data) {
557                 data = "";
558         }
559
560         block = calloc(1, sizeof(*block));
561         if (!block) {
562                 ErrPrint("Heap: %s\n", strerror(errno));
563                 return WIDGET_ERROR_OUT_OF_MEMORY;
564         }
565
566         block->type = strdup(type);
567         if (!block->type) {
568                 ErrPrint("Heap: %s\n", strerror(errno));
569                 free(block);
570                 return WIDGET_ERROR_OUT_OF_MEMORY;
571         }
572
573         block->part = strdup(part);
574         if (!block->part) {
575                 ErrPrint("Heap: %s\n", strerror(errno));
576                 free(block->type);
577                 free(block);
578                 return WIDGET_ERROR_OUT_OF_MEMORY;
579         }
580
581         block->data = strdup(data);
582         if (!block->data) {
583                 ErrPrint("Heap: %s\n", strerror(errno));
584                 free(block->type);
585                 free(block->part);
586                 free(block);
587                 return WIDGET_ERROR_OUT_OF_MEMORY;
588         }
589
590         if (option) {
591                 block->option = strdup(option);
592                 if (!block->option) {
593                         ErrPrint("Heap: %s\n", strerror(errno));
594                         free(block->data);
595                         free(block->type);
596                         free(block->part);
597                         free(block);
598                         return WIDGET_ERROR_OUT_OF_MEMORY;
599                 }
600         }
601
602         if (id) {
603                 block->id = strdup(id);
604                 if (!block->id) {
605                         ErrPrint("Heap: %s\n", strerror(errno));
606                         free(block->option);
607                         free(block->data);
608                         free(block->type);
609                         free(block->part);
610                         free(block);
611                         return WIDGET_ERROR_OUT_OF_MEMORY;
612                 }
613         }
614
615         block->idx = handle->last_idx++;
616         handle->block_list = dlist_append(handle->block_list, block);
617         return block->idx;
618 }
619
620 PUBLIC int widget_desc_del_block(struct widget_desc *handle, int idx)
621 {
622         struct dlist *l;
623         struct block *block;
624
625         if (!handle || idx < 0) {
626                 return WIDGET_ERROR_INVALID_PARAMETER;
627         }
628
629         dlist_foreach(handle->block_list, l, block) {
630                 if (block->idx == idx) {
631                         handle->block_list = dlist_remove(handle->block_list, l);
632                         free(block->type);
633                         free(block->part);
634                         free(block->data);
635                         free(block->option);
636                         free(block->id);
637                         free(block->target_id);
638                         free(block);
639                         return WIDGET_ERROR_NONE;
640                 }
641         }
642
643         return WIDGET_ERROR_NOT_EXIST;
644 }
645
646 PUBLIC int widget_viewer_acquire_buffer(widget_buffer_h handle, int idx, int width, int height, int pixel_size)
647 {
648         int ret;
649
650         if (!handle || width <= 0 || height <= 0 || pixel_size <= 0 || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
651                 return WIDGET_ERROR_INVALID_PARAMETER;
652         }
653
654         if (idx >= 0) {
655                 int _width = 0;
656                 int _height = 0;
657                 int _pixel_size = 0;
658                 /* To validate the buffer */
659                 if (widget_provider_buffer_get_size(handle, &_width, &_height, &_pixel_size) < 0) {
660                         ErrPrint("Failed to get buffer size\n");
661                 }
662
663                 if (_width != width || _height != height || pixel_size != _pixel_size) {
664                         DbgPrint("Extra buffer's geometry is not matched with primary one\n");
665                 }
666
667                 ret = widget_provider_buffer_extra_acquire(handle, idx, width, height, pixel_size);
668         } else {
669                 ret = widget_provider_buffer_acquire(handle, width, height, pixel_size);
670         }
671
672         return ret;
673 }
674
675 PUBLIC widget_buffer_h widget_create_buffer(const char *filename, int is_gbar, int auto_align, int (*handler)(widget_buffer_h , widget_buffer_event_data_t, void *), void *data)
676 {
677         struct widget_buffer_data *user_data;
678         const char *pkgname;
679         widget_buffer_h handle;
680         char *uri;
681
682         if (!filename) {
683                 ErrPrint("Invalid argument: %p(%dx%d)\n", filename);
684                 return NULL;
685         }
686
687         user_data = calloc(1, sizeof(*user_data));
688         if (!user_data) {
689                 ErrPrint("Heap: %s\n", strerror(errno));
690                 return NULL;
691         }
692
693         user_data->is_gbar = is_gbar;
694         user_data->handler = handler ? handler : default_event_handler;
695         user_data->cbdata = data;
696
697         uri = id_to_uri(filename);
698         if (!uri) {
699                 ErrPrint("Heap: %s\n", strerror(errno));
700                 free(user_data);
701                 return NULL;
702         }
703
704         if (!s_info.find_pkgname) {
705                 s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_WIDGET_FIND_PKGNAME);
706                 if (!s_info.find_pkgname) {
707                         ErrPrint("Failed to find a \"widget_find_pkgname\"\n");
708                         free(user_data);
709                         free(uri);
710                         return NULL;
711                 }
712         }
713
714         pkgname = s_info.find_pkgname(uri);
715         if (!pkgname) {
716                 ErrPrint("Invalid Request\n");
717                 free(user_data);
718                 free(uri);
719                 return NULL;
720         }
721
722         handle = widget_provider_buffer_create((!!is_gbar) ? WIDGET_TYPE_GBAR : WIDGET_TYPE_WIDGET, pkgname, uri, auto_align, event_handler_wrapper, user_data);
723         free(uri);
724         if (!handle) {
725                 free(user_data);
726                 return NULL;
727         }
728
729         (void)widget_provider_buffer_set_user_data(handle, user_data);
730         return handle;
731 }
732
733 PUBLIC int widget_request_update(const char *filename)
734 {
735         char *uri;
736         int ret;
737
738         if (!filename) {
739                 ErrPrint("Invalid argument\n");
740                 return WIDGET_ERROR_INVALID_PARAMETER;
741         }
742
743         uri = id_to_uri(filename);
744         if (!uri) {
745                 ErrPrint("Heap: %s\n", strerror(errno));
746                 return WIDGET_ERROR_OUT_OF_MEMORY;
747         }
748
749         if (!s_info.request_update_by_id) {
750                 s_info.request_update_by_id = dlsym(RTLD_DEFAULT, FUNC_WIDGET_REQUEST_UPDATE_BY_ID);
751                 if (!s_info.request_update_by_id) {
752                         ErrPrint("\"widget_request_update_by_id\" is not exists\n");
753                         free(uri);
754                         return WIDGET_ERROR_FAULT;
755                 }
756         }
757
758         ret = s_info.request_update_by_id(uri);
759         free(uri);
760         return ret;
761 }
762
763 PUBLIC unsigned int widget_viewer_get_resource_id(widget_buffer_h handle, int idx)
764 {
765         int ret;
766
767         if (!handle || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
768                 return WIDGET_ERROR_INVALID_PARAMETER;
769         }
770
771         if (idx >= 0) {
772                 ret = widget_provider_buffer_extra_resource_id(handle, idx);
773         } else {
774                 ret = widget_provider_buffer_resource_id(handle);
775         }
776
777         return ret;
778 }
779
780 PUBLIC int widget_viewer_release_buffer(widget_buffer_h handle, int idx)
781 {
782         int ret;
783
784         if (!handle || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
785                 return WIDGET_ERROR_INVALID_PARAMETER;
786         }
787
788         if (idx >= 0) {
789                 ret = widget_provider_buffer_extra_release(handle, idx);
790         } else {
791                 ret = widget_provider_buffer_release(handle);
792         }
793
794         DbgPrint("Release buffer: %d (%d)\n", idx, ret);
795         return ret;
796 }
797
798 PUBLIC int widget_destroy_buffer(widget_buffer_h handle)
799 {
800         struct widget_buffer_data *user_data;
801
802         if (!handle) {
803                 return WIDGET_ERROR_INVALID_PARAMETER;
804         }
805
806         user_data = widget_provider_buffer_user_data(handle);
807         if (user_data) {
808                 if (user_data->frame_wait_timer) {
809                         ecore_timer_del(user_data->frame_wait_timer);
810                         user_data->frame_wait_timer = NULL;
811                 }
812                 free(user_data->content);
813                 free(user_data->title);
814                 free(user_data->icon);
815                 free(user_data->name);
816                 free(user_data);
817                 widget_provider_buffer_set_user_data(handle, NULL);
818         }
819
820         DbgPrint("Destroy buffer\n");
821         return widget_provider_buffer_destroy(handle);
822 }
823
824 PUBLIC void *widget_ref_buffer(widget_buffer_h handle)
825 {
826         struct widget_buffer_data *user_data;
827         void *data;
828         int w, h, size;
829         int ret;
830
831         if (!handle) {
832                 return NULL;
833         }
834
835         user_data = widget_provider_buffer_user_data(handle);
836         if (!user_data) {
837                 return NULL;
838         }
839
840         if (user_data->accelerated) {
841                 DbgPrint("H/W accelerated buffer is allocated\n");
842                 return NULL;
843         }
844
845         ret = widget_provider_buffer_get_size(handle, &w, &h, &size);
846
847         data = widget_provider_buffer_ref(handle);
848         if (data && !ret && w > 0 && h > 0 && size > 0) {
849                 memset(data, 0, w * h * size);
850                 (void)widget_provider_buffer_sync(handle);
851         }
852
853         DbgPrint("Ref buffer %ds%d(%d)\n", w, h, size);
854         return data;
855 }
856
857 PUBLIC int widget_unref_buffer(void *buffer)
858 {
859         if (!buffer) {
860                 return WIDGET_ERROR_INVALID_PARAMETER;
861         }
862
863         DbgPrint("Unref buffer\n");
864         return widget_provider_buffer_unref(buffer);
865 }
866
867 PUBLIC int widget_viewer_sync_buffer(widget_buffer_h handle)
868 {
869         struct widget_buffer_data *user_data;
870         const char *pkgname;
871         const char *id;
872         int w;
873         int h;
874         int pixel_size;
875         int ret;
876
877         if (!handle) {
878                 return WIDGET_ERROR_INVALID_PARAMETER;
879         }
880
881         user_data = widget_provider_buffer_user_data(handle);
882         if (!user_data) {
883                 ErrPrint("Invalid buffer\n");
884                 return WIDGET_ERROR_INVALID_PARAMETER;
885         }
886
887         if (user_data->accelerated) {
888                 DbgPrint("H/W Buffer allocated. skip the sync buffer\n");
889                 return WIDGET_ERROR_NONE;
890         }
891
892         pkgname = widget_provider_buffer_pkgname(handle);
893         if (!pkgname) {
894                 ErrPrint("Invalid buffer handler\n");
895                 return WIDGET_ERROR_INVALID_PARAMETER;
896         }
897
898         id = widget_provider_buffer_id(handle);
899         if (!id) {
900                 ErrPrint("Invalid buffer handler\n");
901                 return WIDGET_ERROR_INVALID_PARAMETER;
902         }
903
904         (void)widget_provider_buffer_sync(handle);
905
906         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
907                 ErrPrint("Failed to get size (%s)\n", id);
908         }
909
910         /**
911          * @todo
912          * manipulate the damaged region, so send update event only for the damaged region.
913          * to make more efficient updates
914          */
915         ret = send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
916         if (ret < 0) {
917                 ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
918         }
919
920         return ret;
921 }
922
923 PUBLIC int widget_send_updated_by_idx(widget_buffer_h handle, int idx)
924 {
925         struct widget_buffer_data *user_data;
926         const char *pkgname;
927         const char *id;
928         int w;
929         int h;
930         int pixel_size;
931         int ret;
932
933         user_data = widget_provider_buffer_user_data(handle);
934         if (!user_data) {
935                 ErrPrint("Invalid buffer\n");
936                 return WIDGET_ERROR_INVALID_PARAMETER;
937         }
938
939         pkgname = widget_provider_buffer_pkgname(handle);
940         if (!pkgname) {
941                 ErrPrint("Invalid buffer handler\n");
942                 return WIDGET_ERROR_INVALID_PARAMETER;
943         }
944
945         id = widget_provider_buffer_id(handle);
946         if (!id) {
947                 ErrPrint("Invalid buffer handler\n");
948                 return WIDGET_ERROR_INVALID_PARAMETER;
949         }
950
951         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
952                 ErrPrint("Failed to get size (%s)\n", id);
953         }
954
955         ret = send_updated(pkgname, id, handle, idx, 0, 0, w, h, user_data->is_gbar, NULL);
956         if (ret < 0) {
957                 ErrPrint("Failed to send%supdated (%s) %d\n", user_data->is_gbar ? " GBAR " : " ", id, idx);
958         }
959
960         return ret;
961 }
962
963 PUBLIC int widget_support_hw_buffer(widget_buffer_h handle)
964 {
965         if (!handle) {
966                 return WIDGET_ERROR_INVALID_PARAMETER;
967         }
968
969         return widget_provider_buffer_is_support_hw(handle);
970 }
971
972 PUBLIC int widget_create_hw_buffer(widget_buffer_h handle)
973 {
974         struct widget_buffer_data *user_data;
975         int ret;
976
977         if (!handle) {
978                 return WIDGET_ERROR_INVALID_PARAMETER;
979         }
980
981         user_data = widget_provider_buffer_user_data(handle);
982         if (!user_data) {
983                 return WIDGET_ERROR_INVALID_PARAMETER;
984         }
985
986         if (user_data->accelerated) {
987                 return WIDGET_ERROR_ALREADY_EXIST;
988         }
989
990         ret = widget_provider_buffer_create_hw(handle);
991         user_data->accelerated = (ret == 0);
992         return ret;
993 }
994
995 PUBLIC int widget_destroy_hw_buffer(widget_buffer_h handle)
996 {
997         struct widget_buffer_data *user_data;
998
999         if (!handle) {
1000                 LOGD("handle is NULL\n");
1001                 return WIDGET_ERROR_INVALID_PARAMETER;
1002         }
1003
1004         user_data = widget_provider_buffer_user_data(handle);
1005         if (!user_data || !user_data->accelerated) {
1006                 LOGD("user_data is NULL\n");
1007                 return WIDGET_ERROR_INVALID_PARAMETER;
1008         }
1009
1010         user_data->accelerated = 0;
1011
1012         return widget_provider_buffer_destroy_hw(handle);
1013 }
1014
1015 PUBLIC void *widget_buffer_hw_buffer(widget_buffer_h handle)
1016 {
1017         struct widget_buffer_data *user_data;
1018
1019         if (!handle) {
1020                 return NULL;
1021         }
1022
1023         user_data = widget_provider_buffer_user_data(handle);
1024         if (!user_data || !user_data->accelerated) {
1025                 return NULL;
1026         }
1027
1028         return widget_provider_buffer_hw_addr(handle);
1029 }
1030
1031 PUBLIC int widget_buffer_pre_render(widget_buffer_h handle)
1032 {
1033         struct widget_buffer_data *user_data;
1034
1035         if (!handle) {
1036                 return WIDGET_ERROR_INVALID_PARAMETER;
1037         }
1038
1039         user_data = widget_provider_buffer_user_data(handle);
1040         if (!user_data) {
1041                 return WIDGET_ERROR_INVALID_PARAMETER;
1042         }
1043
1044         if (!user_data->accelerated) {
1045                 return WIDGET_ERROR_NONE;
1046         }
1047
1048         /*!
1049          * \note
1050          * Do preprocessing for accessing the H/W render buffer
1051          */
1052         return widget_provider_buffer_pre_render(handle);
1053 }
1054
1055 static Eina_Bool frame_wait_cb(void *data)
1056 {
1057         widget_buffer_h handle = data;
1058         struct widget_buffer_data *user_data;
1059         const char *pkgname;
1060         const char *id;
1061         int pixel_size;
1062         int ret;
1063         int w;
1064         int h;
1065
1066         user_data = widget_provider_buffer_user_data(handle);
1067         if (!user_data) {
1068                 ErrPrint("Failed to get a user data\n");
1069                 return ECORE_CALLBACK_CANCEL;
1070         }
1071
1072         pkgname = widget_provider_buffer_pkgname(handle);
1073         id = widget_provider_buffer_id(handle);
1074
1075         if (!pkgname || !id) {
1076                 ErrPrint("Failed to get instance information (%s), (%s)\n", pkgname, id);
1077                 user_data->frame_wait_timer = NULL;
1078                 return ECORE_CALLBACK_CANCEL;
1079         }
1080
1081         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1082                 ErrPrint("Failed to get size (%s)\n", id);
1083                 w = 0;
1084                 h = 0;
1085                 pixel_size = sizeof(int);
1086         }
1087
1088         DbgPrint("Frame skip waiting timer is fired (%s)\n", id);
1089
1090         /**
1091          * @todo
1092          * manipulate the damaged region, so send update event only for the damaged region.
1093          * to make more efficient updates
1094          */
1095         ret = send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1096         if (ret < 0) {
1097                 ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1098         }
1099
1100         (void)widget_provider_buffer_clear_frame_skip(handle);
1101
1102         user_data->frame_wait_timer = NULL;
1103         return ECORE_CALLBACK_CANCEL;
1104 }
1105
1106 PUBLIC int widget_buffer_post_render(widget_buffer_h handle)
1107 {
1108         int ret;
1109         const char *pkgname;
1110         const char *id;
1111         struct widget_buffer_data *user_data;
1112         int w;
1113         int h;
1114         int pixel_size;
1115         PERF_INIT();
1116         PERF_BEGIN();
1117
1118         if (!handle) {
1119                 PERF_MARK("post_render");
1120                 return WIDGET_ERROR_INVALID_PARAMETER;
1121         }
1122
1123         user_data = widget_provider_buffer_user_data(handle);
1124         if (!user_data) {
1125                 PERF_MARK("post_render");
1126                 return WIDGET_ERROR_INVALID_PARAMETER;
1127         }
1128
1129         if (!user_data->accelerated) {
1130                 PERF_MARK("post_render");
1131                 return WIDGET_ERROR_NONE;
1132         }
1133
1134         pkgname = widget_provider_buffer_pkgname(handle);
1135         if (!pkgname) {
1136                 ErrPrint("Invalid buffer handle\n");
1137                 PERF_MARK("post_render");
1138                 return WIDGET_ERROR_INVALID_PARAMETER;
1139         }
1140
1141         id = widget_provider_buffer_id(handle);
1142         if (!id) {
1143                 ErrPrint("Invalid buffer handler\n");
1144                 PERF_MARK("post_render");
1145                 return WIDGET_ERROR_INVALID_PARAMETER;
1146         }
1147
1148         ret = widget_provider_buffer_post_render(handle);
1149         if (ret < 0) {
1150                 ErrPrint("Failed to post render processing\n");
1151                 PERF_MARK("post_render");
1152                 return ret;
1153         }
1154
1155         if (widget_provider_buffer_frame_skip(handle) == 0) {
1156                 if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
1157                         ErrPrint("Failed to get size (%s)\n", id);
1158                 }
1159
1160                 /**
1161                  * @todo
1162                  * manipulate the damaged region, so send update event only for the damaged region.
1163                  * to make more efficient updates
1164                  */
1165                 ret = send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
1166                 if (ret < 0) {
1167                         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
1168                 }
1169
1170                 if (user_data->frame_wait_timer) {
1171                         ecore_timer_del(user_data->frame_wait_timer);
1172                         user_data->frame_wait_timer = NULL;
1173                 }
1174         } else {
1175                 if (user_data->frame_wait_timer) {
1176                         ecore_timer_reset(user_data->frame_wait_timer);
1177                 } else {
1178                         user_data->frame_wait_timer = ecore_timer_add(FRAME_WAIT_INTERVAL, frame_wait_cb, handle);
1179                         if (!user_data->frame_wait_timer) {
1180                                 ErrPrint("Failed to add waiting timer for next frame\n");
1181                         }
1182                 }
1183         }
1184
1185         PERF_MARK("post_render");
1186         return ret;
1187 }
1188
1189 PUBLIC int widget_buffer_stride(widget_buffer_h handle)
1190 {
1191         if (!handle) {
1192                 return WIDGET_ERROR_INVALID_PARAMETER;
1193         }
1194
1195         return widget_provider_buffer_stride(handle);
1196 }
1197
1198 PUBLIC int widget_content_is_updated(const char *filename, int is_gbar)
1199 {
1200         if (!s_info.trigger_update_monitor) {
1201                 s_info.trigger_update_monitor = dlsym(RTLD_DEFAULT, FUNC_WIDGET_TRIGGER_UPDATE_MONITOR);
1202                 if (!s_info.trigger_update_monitor) {
1203                         ErrPrint("Trigger update monitor function is not exists\n");
1204                         return WIDGET_ERROR_FAULT;
1205                 }
1206         }
1207
1208         return s_info.trigger_update_monitor(filename, is_gbar);
1209 }
1210
1211 PUBLIC int widget_request_close_glance_bar(const char *pkgname, const char *id, int reason)
1212 {
1213         char *uri;
1214         int schema_len = strlen(FILE_SCHEMA);
1215         int ret;
1216
1217         if (!pkgname || !id) {
1218                 ErrPrint("Invalid parameters (%s) (%s)\n", pkgname, id);
1219                 return WIDGET_ERROR_INVALID_PARAMETER;
1220         }
1221
1222         if (strncmp(id, FILE_SCHEMA, schema_len)) {
1223                 uri = id_to_uri(id);
1224                 if (!uri) {
1225                         ErrPrint("Heap: %s\n", strerror(errno));
1226                         return WIDGET_ERROR_OUT_OF_MEMORY;
1227                 }
1228         } else {
1229                 uri = strdup(id);
1230                 if (!uri) {
1231                         ErrPrint("Heap: %s\n", strerror(errno));
1232                         return WIDGET_ERROR_OUT_OF_MEMORY;
1233                 }
1234         }
1235
1236         ret = widget_provider_send_request_close_gbar(pkgname, uri, reason);
1237         free(uri);
1238         return ret;
1239 }
1240
1241 PUBLIC int widget_freeze_scroller(const char *pkgname, const char *id)
1242 {
1243         char *uri;
1244         int ret;
1245
1246         if (!pkgname || !id) {
1247                 return WIDGET_ERROR_INVALID_PARAMETER;
1248         }
1249
1250         uri = id_to_uri(id);
1251         if (!uri) {
1252                 ErrPrint("Heap: %s\n", strerror(errno));
1253                 return WIDGET_ERROR_OUT_OF_MEMORY;
1254         }
1255
1256         ret = widget_provider_send_hold_scroll(pkgname, uri, 1);
1257         free(uri);
1258         return ret;
1259 }
1260
1261 PUBLIC int widget_thaw_scroller(const char *pkgname, const char *id)
1262 {
1263         char *uri;
1264         int ret;
1265
1266         if (!pkgname || !id) {
1267                 return WIDGET_ERROR_INVALID_PARAMETER;
1268         }
1269
1270         uri = id_to_uri(id);
1271         if (!uri) {
1272                 ErrPrint("Heap: %s\n", strerror(errno));
1273                 return WIDGET_ERROR_OUT_OF_MEMORY;
1274         }
1275
1276         ret = widget_provider_send_hold_scroll(pkgname, uri, 0);
1277         free(uri);
1278         return ret;
1279 }
1280
1281 PUBLIC int widget_set_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1282 {
1283         widget_buffer_h handle;
1284         const char *pkgname;
1285         char *uri;
1286
1287         uri = id_to_uri(id);
1288         if (!uri) {
1289                 ErrPrint("Heap: %s\n", strerror(errno));
1290                 return WIDGET_ERROR_OUT_OF_MEMORY;
1291         }
1292
1293         if (!s_info.find_pkgname) {
1294                 s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_WIDGET_FIND_PKGNAME);
1295                 if (!s_info.find_pkgname) {
1296                         ErrPrint("Failed to find a \"widget_find_pkgname\"\n");
1297                         free(uri);
1298                         return WIDGET_ERROR_FAULT;
1299                 }
1300         }
1301
1302         pkgname = s_info.find_pkgname(uri);
1303         if (!pkgname) {
1304                 ErrPrint("Failed to find a package (%s)\n", uri);
1305                 free(uri);
1306                 return WIDGET_ERROR_INVALID_PARAMETER;
1307         }
1308
1309         handle = widget_provider_buffer_find_buffer(WIDGET_TYPE_WIDGET, pkgname, uri);
1310         if (handle) {
1311                 struct widget_buffer_data *user_data;
1312
1313                 user_data = widget_provider_buffer_user_data(handle);
1314                 if (!user_data) {
1315                         ErrPrint("User data is not available\n");
1316                         free(uri);
1317                         return WIDGET_ERROR_FAULT;
1318                 }
1319
1320                 if (content && strlen(content)) {
1321                         char *_content;
1322
1323                         _content = strdup(content);
1324                         if (_content) {
1325                                 if (user_data->content) {
1326                                         free(user_data->content);
1327                                 }
1328
1329                                 user_data->content = _content;
1330                         } else {
1331                                 ErrPrint("Heap: %s\n", strerror(errno));
1332                         }
1333                 }
1334
1335                 if (title && strlen(title)) {
1336                         char *_title;
1337
1338                         _title = strdup(title);
1339                         if (_title) {
1340                                 if (user_data->title) {
1341                                         free(user_data->title);
1342                                 }
1343
1344                                 user_data->title = _title;
1345                         } else {
1346                                 ErrPrint("Heap: %s\n", strerror(errno));
1347                         }
1348                 }
1349
1350                 if (icon && strlen(icon)) {
1351                         char *_icon;
1352
1353                         _icon = strdup(icon);
1354                         if (_icon) {
1355                                 if (user_data->icon) {
1356                                         free(user_data->icon);
1357                                 }
1358
1359                                 user_data->icon = _icon;
1360                         } else {
1361                                 ErrPrint("Heap: %s\n", strerror(errno));
1362                         }
1363                 }
1364
1365                 if (name && strlen(name)) {
1366                         char *_name;
1367
1368                         _name = strdup(name);
1369                         if (_name) {
1370                                 if (user_data->name) {
1371                                         free(user_data->name);
1372                                 }
1373
1374                                 user_data->name = _name;
1375                         } else {
1376                                 ErrPrint("Heap: %s\n", strerror(errno));
1377                         }
1378                 }
1379
1380                 if (widget_provider_send_extra_info(pkgname, uri, -1.0f, user_data->content, user_data->title, user_data->icon, user_data->name) < 0) {
1381                         ErrPrint("Failed to send extra info (%s)\n", id);
1382                 }
1383
1384                 free(uri);
1385                 return WIDGET_ERROR_NONE;
1386         }
1387         free(uri);
1388
1389         if (!s_info.update_extra_info) {
1390                 s_info.update_extra_info = dlsym(RTLD_DEFAULT, FUNC_WIDGET_UPDATE_EXTRA_INFO);
1391                 if (!s_info.update_extra_info) {
1392                         ErrPrint("Failed to find a \"widget_update_extra_info\"\n");
1393                         return WIDGET_ERROR_INVALID_PARAMETER;
1394                 }
1395         }
1396
1397         return s_info.update_extra_info(id, content, title, icon, name);
1398 }
1399
1400 /* End of a file */