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