Add new API for notifying updated contents.
[platform/framework/web/livebox.git] / src / livebox.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
24 #include <dlog.h>
25 #include <livebox-service.h>
26 #include <provider.h>
27 #include <provider_buffer.h>
28 #include <livebox-errno.h>
29
30 #include "debug.h"
31 #include "livebox.h"
32 #include "dlist.h"
33 #include "util.h"
34
35 #define PUBLIC __attribute__((visibility("default")))
36
37 #define FILE_SCHEMA     "file://"
38
39 /*!
40  * \brief This function is defined by the data-provider-slave
41  */
42 extern const char *livebox_find_pkgname(const char *filename);
43 extern int livebox_request_update_by_id(const char *uri);
44 extern int livebox_trigger_update_monitor(const char *id, int is_pd);
45
46 struct block {
47         unsigned int idx;
48
49         char *type;
50         char *part;
51         char *data;
52         char *option;
53         char *id;
54         char *file;
55         char *target_id;
56 };
57
58 struct livebox_desc {
59         FILE *fp;
60         int for_pd;
61
62         unsigned int last_idx;
63
64         struct dlist *block_list;
65 };
66
67 struct livebox_buffer_data {
68         int is_pd;
69         int accelerated;
70
71         /* for Buffer event wrapper */
72         int (*handler)(struct livebox_buffer *, enum buffer_event, double, double, double, void *);
73         void *cbdata;
74 };
75
76 PUBLIC const int DONE = 0x00;
77 PUBLIC const int OUTPUT_UPDATED = 0x02;
78 PUBLIC const int USE_NET = 0x04;
79
80 PUBLIC const int NEED_TO_SCHEDULE = 0x01;
81 PUBLIC const int NEED_TO_CREATE = 0x01;
82 PUBLIC const int NEED_TO_DESTROY = 0x01;
83 PUBLIC const int NEED_TO_UPDATE = 0x01;
84
85 PUBLIC const int LB_SYS_EVENT_FONT_CHANGED = 0x01;
86 PUBLIC const int LB_SYS_EVENT_LANG_CHANGED = 0x02;
87 PUBLIC const int LB_SYS_EVENT_TIME_CHANGED = 0x04;
88 PUBLIC const int LB_SYS_EVENT_REGION_CHANGED = 0x08;
89 PUBLIC const int LB_SYS_EVENT_PAUSED = 0x0100;
90 PUBLIC const int LB_SYS_EVENT_RESUMED = 0x0200;
91 PUBLIC const int LB_SYS_EVENT_MMC_STATUS_CHANGED = 0x0400;
92
93 PUBLIC struct livebox_desc *livebox_desc_open(const char *filename, int for_pd)
94 {
95         struct livebox_desc *handle;
96         char *new_fname;
97
98         handle = calloc(1, sizeof(*handle));
99         if (!handle) {
100                 ErrPrint("Error: %s\n", strerror(errno));
101                 return NULL;
102         }
103
104         if (for_pd) {
105                 int len;
106                 len = strlen(filename) + strlen(".desc") + 1;
107                 new_fname = malloc(len);
108                 if (!new_fname) {
109                         ErrPrint("Error: %s\n", strerror(errno));
110                         free(handle);
111                         return NULL;
112                 }
113                 snprintf(new_fname, len, "%s.desc", filename);
114         } else {
115                 new_fname = strdup(filename);
116                 if (!new_fname) {
117                         ErrPrint("Error: %s\n", strerror(errno));
118                         free(handle);
119                         return NULL;
120                 }
121         }
122
123         DbgPrint("Open a file %s with merge mode %s\n",
124                                 new_fname,
125                                 access(new_fname, F_OK) == 0 ? "enabled" : "disabled");
126
127         handle->fp = fopen(new_fname, "at");
128         free(new_fname);
129         if (!handle->fp) {
130                 ErrPrint("Failed to open a file: %s\n", strerror(errno));
131                 free(handle);
132                 return NULL;
133         }
134
135         return handle;
136 }
137
138 PUBLIC int livebox_desc_close(struct livebox_desc *handle)
139 {
140         struct dlist *l;
141         struct dlist *n;
142         struct block *block;
143
144         if (!handle)
145                 return LB_STATUS_ERROR_INVALID;
146
147         dlist_foreach_safe(handle->block_list, l, n, block) {
148                 handle->block_list = dlist_remove(handle->block_list, l);
149
150                 fprintf(handle->fp, "{\n");
151                 if (block->type)
152                         fprintf(handle->fp, "type=%s\n", block->type);
153
154                 if (block->part)
155                         fprintf(handle->fp, "part=%s\n", block->part);
156
157                 if (block->data)
158                         fprintf(handle->fp, "data=%s\n", block->data);
159
160                 if (block->option)
161                         fprintf(handle->fp, "option=%s\n", block->option);
162
163                 if (block->id)
164                         fprintf(handle->fp, "id=%s\n", block->id);
165
166                 if (block->target_id)
167                         fprintf(handle->fp, "target=%s\n", block->target_id);
168                 fprintf(handle->fp, "}\n");
169
170                 free(block->type);
171                 free(block->part);
172                 free(block->data);
173                 free(block->option);
174                 free(block->id);
175                 free(block->target_id);
176                 free(block);
177         }
178
179         fclose(handle->fp);
180         free(handle);
181         return LB_STATUS_SUCCESS;
182 }
183
184 PUBLIC int livebox_desc_set_category(struct livebox_desc *handle, const char *id, const char *category)
185 {
186         struct block *block;
187
188         if (!handle || !category)
189                 return LB_STATUS_ERROR_INVALID;
190
191         block = calloc(1, sizeof(*block));
192         if (!block)
193                 return LB_STATUS_ERROR_MEMORY;
194
195         block->type = strdup(LB_DESC_TYPE_INFO);
196         if (!block->type) {
197                 free(block);
198                 return LB_STATUS_ERROR_MEMORY;
199         }
200
201         block->part = strdup("category");
202         if (!block->part) {
203                 free(block->type);
204                 free(block);
205                 return LB_STATUS_ERROR_MEMORY;
206         }
207
208         block->data = strdup(category);
209         if (!block->data) {
210                 free(block->type);
211                 free(block->part);
212                 free(block);
213                 return LB_STATUS_ERROR_MEMORY;
214         }
215
216         if (id) {
217                 block->id = strdup(id);
218                 if (!block->id) {
219                         free(block->data);
220                         free(block->type);
221                         free(block->part);
222                         free(block);
223                         return LB_STATUS_ERROR_MEMORY;
224                 }
225         }
226
227         block->idx = handle->last_idx++;
228         handle->block_list = dlist_append(handle->block_list, block);
229         return block->idx;
230 }
231
232 PUBLIC int livebox_desc_set_size(struct livebox_desc *handle, const char *id, int w, int h)
233 {
234         struct block *block;
235         char buffer[BUFSIZ];
236
237         if (!handle)
238                 return LB_STATUS_ERROR_INVALID;
239
240         block = calloc(1, sizeof(*block));
241         if (!block)
242                 return LB_STATUS_ERROR_MEMORY;
243
244         block->type = strdup(LB_DESC_TYPE_INFO);
245         if (!block->type) {
246                 free(block);
247                 return LB_STATUS_ERROR_MEMORY;
248         }
249
250         block->part = strdup("size");
251         if (!block->part) {
252                 free(block->type);
253                 free(block);
254                 return LB_STATUS_ERROR_MEMORY;
255         }
256
257         if (id) {
258                 block->id = strdup(id);
259                 if (!block->id) {
260                         free(block->part);
261                         free(block->type);
262                         free(block);
263                         return LB_STATUS_ERROR_MEMORY;
264                 }
265         }
266
267         snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
268         block->data = strdup(buffer);
269         if (!block->data) {
270                 free(block->part);
271                 free(block->type);
272                 free(block);
273                 return LB_STATUS_ERROR_MEMORY;
274         }
275
276         block->idx = handle->last_idx++;
277         handle->block_list = dlist_append(handle->block_list, block);
278         return block->idx;
279 }
280
281 PUBLIC char *livebox_util_nl2br(const char *str)
282 {
283         int len;
284         register int i;
285         char *ret;
286         char *ptr;
287
288         if (!str)
289                 return NULL;
290
291         len = strlen(str);
292         if (!len)
293                 return NULL;
294
295         ret = malloc(len + 1);
296         if (!ret)
297                 return NULL;
298
299         ptr = ret;
300         i = 0;
301         while (*str) {
302                 switch (*str) {
303                 case '\n':
304                         if (len - i < 5) {
305                                 char *tmp;
306                                 len += len;
307
308                                 tmp = realloc(ret, len + 1);
309                                 if (!tmp) {
310                                         free(ret);
311                                         return NULL;
312                                 }
313
314                                 ret = tmp;
315                                 ptr = tmp + i;
316                         }
317
318                         strcpy(ptr, "<br>");
319                         ptr += 4;
320                         i += 4;
321                         break;
322                 default:
323                         *ptr++ = *str;
324                         i++;
325                         break;
326                 }
327
328                 str++;
329         }
330         *ptr = '\0';
331
332         return ret;
333 }
334
335 PUBLIC int livebox_desc_set_id(struct livebox_desc *handle, int idx, const char *id)
336 {
337         struct dlist *l;
338         struct block *block;
339
340         dlist_foreach(handle->block_list, l, block) {
341                 if (block->idx == idx) {
342                         if (strcasecmp(block->type, LB_DESC_TYPE_SCRIPT)) {
343                                 ErrPrint("Invalid block is used\n");
344                                 return LB_STATUS_ERROR_INVALID;
345                         }
346
347                         free(block->target_id);
348                         block->target_id = NULL;
349
350                         if (!id || !strlen(id))
351                                 return LB_STATUS_SUCCESS;
352
353                         block->target_id = strdup(id);
354                         if (!block->target_id) {
355                                 ErrPrint("Heap: %s\n", strerror(errno));
356                                 return LB_STATUS_ERROR_MEMORY;
357                         }
358
359                         return LB_STATUS_SUCCESS;
360                 }
361         }
362
363         return LB_STATUS_ERROR_NOT_EXIST;
364 }
365
366 /*!
367  * \return idx
368  */
369 PUBLIC int livebox_desc_add_block(struct livebox_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option)
370 {
371         struct block *block;
372
373         if (!handle || !type)
374                 return LB_STATUS_ERROR_INVALID;
375
376         if (!part)
377                 part = "";
378
379         if (!data)
380                 data = "";
381
382         block = calloc(1, sizeof(*block));
383         if (!block) {
384                 ErrPrint("Heap: %s\n", strerror(errno));
385                 return LB_STATUS_ERROR_MEMORY;
386         }
387
388         block->type = strdup(type);
389         if (!block->type) {
390                 ErrPrint("Heap: %s\n", strerror(errno));
391                 free(block);
392                 return LB_STATUS_ERROR_MEMORY;
393         }
394
395         block->part = strdup(part);
396         if (!block->part) {
397                 ErrPrint("Heap: %s\n", strerror(errno));
398                 free(block->type);
399                 free(block);
400                 return LB_STATUS_ERROR_MEMORY;
401         }
402
403         block->data = strdup(data);
404         if (!block->data) {
405                 ErrPrint("Heap: %s\n", strerror(errno));
406                 free(block->type);
407                 free(block->part);
408                 free(block);
409                 return LB_STATUS_ERROR_MEMORY;
410         }
411
412         if (option) {
413                 block->option = strdup(option);
414                 if (!block->option) {
415                         ErrPrint("Heap: %s\n", strerror(errno));
416                         free(block->data);
417                         free(block->type);
418                         free(block->part);
419                         free(block);
420                         return LB_STATUS_ERROR_MEMORY;
421                 }
422         }
423
424         if (id) {
425                 block->id = strdup(id);
426                 if (!block->id) {
427                         ErrPrint("Heap: %s\n", strerror(errno));
428                         free(block->option);
429                         free(block->data);
430                         free(block->type);
431                         free(block->part);
432                         free(block);
433                         return LB_STATUS_ERROR_MEMORY;
434                 }
435         }
436
437         block->idx = handle->last_idx++;
438         handle->block_list = dlist_append(handle->block_list, block);
439         return block->idx;
440 }
441
442 PUBLIC int livebox_desc_del_block(struct livebox_desc *handle, int idx)
443 {
444         struct dlist *l;
445         struct block *block;
446
447         dlist_foreach(handle->block_list, l, block) {
448                 if (block->idx == idx) {
449                         handle->block_list = dlist_remove(handle->block_list, l);
450                         free(block->type);
451                         free(block->part);
452                         free(block->data);
453                         free(block->option);
454                         free(block->id);
455                         free(block->target_id);
456                         free(block);
457                         return LB_STATUS_SUCCESS;
458                 }
459         }
460
461         return LB_STATUS_ERROR_NOT_EXIST;
462 }
463
464 /*!
465  * \note
466  * The last "data" argument is same with "user_data" which is managed by "provider_set_user_data).
467  */
468 static inline int event_handler_wrapper(struct livebox_buffer *buffer, enum buffer_event event, double timestamp, double x, double y, void *data)
469 {
470         const char *pkgname;
471         const char *id;
472         struct livebox_buffer_data *cbdata = data;
473         int ret;
474
475         pkgname = provider_buffer_pkgname(buffer);
476         id = provider_buffer_pkgname(buffer);
477
478         ret = cbdata->handler(buffer, event, timestamp, x, y, cbdata->cbdata);
479
480         switch (event) {
481         case BUFFER_EVENT_HIGHLIGHT:
482         case BUFFER_EVENT_HIGHLIGHT_NEXT:
483         case BUFFER_EVENT_HIGHLIGHT_PREV:
484         case BUFFER_EVENT_ACTIVATE:
485         case BUFFER_EVENT_ACTION_UP:
486         case BUFFER_EVENT_ACTION_DOWN:
487         case BUFFER_EVENT_SCROLL_UP:
488         case BUFFER_EVENT_SCROLL_MOVE:
489         case BUFFER_EVENT_SCROLL_DOWN:
490         case BUFFER_EVENT_UNHIGHLIGHT:
491                 if (ret < 0)
492                         (void)provider_send_access_status(pkgname, id, LB_ACCESS_STATUS_ERROR);
493                 else
494                         (void)provider_send_access_status(pkgname, id, ret);
495                 break;
496         default:
497                 break;
498         }
499
500         return ret;
501 }
502
503 static inline int default_event_handler(struct livebox_buffer *buffer, enum buffer_event event, double timestamp, double x, double y, void *data)
504 {
505         /* NOP */
506         return 0;
507 }
508
509 PUBLIC struct livebox_buffer *livebox_acquire_buffer(const char *filename, int is_pd, int width, int height, int (*handler)(struct livebox_buffer *, enum buffer_event, double, double, double, void *), void *data)
510 {
511         struct livebox_buffer_data *user_data;
512         const char *pkgname;
513         struct livebox_buffer *handle;
514         char *uri;
515         int uri_len;
516         struct event_cbdata *cbdata;
517
518         if (!filename || !width || !height) {
519                 ErrPrint("Invalid argument: %p(%dx%d)\n", filename, width, height);
520                 return NULL;
521         }
522
523         user_data = calloc(1, sizeof(*user_data));
524         if (!user_data) {
525                 ErrPrint("Heap: %s\n", strerror(errno));
526                 return NULL;
527         }
528
529         user_data->is_pd = is_pd;
530         user_data->handler = handler ? handler : default_event_handler;
531         user_data->cbdata = data;
532
533         uri_len = strlen(filename) + strlen(FILE_SCHEMA) + 1;
534         uri = malloc(uri_len);
535         if (!uri) {
536                 ErrPrint("Heap: %s\n", strerror(errno));
537                 free(user_data);
538                 return NULL;
539         }
540
541         snprintf(uri, uri_len, FILE_SCHEMA "%s", filename);
542         pkgname = livebox_find_pkgname(uri);
543         if (!pkgname) {
544                 ErrPrint("Invalid Request\n");
545                 free(user_data);
546                 free(uri);
547                 return NULL;
548         }
549
550         handle = provider_buffer_acquire((!!is_pd) ? TYPE_PD : TYPE_LB, pkgname, uri, width, height, sizeof(int), event_handler_wrapper, user_data);
551         DbgPrint("Acquire buffer for PD(%s), %s, %p\n", pkgname, uri, handle);
552         free(uri);
553         if (!handle) {
554                 free(user_data);
555                 return NULL;
556         }
557
558         (void)provider_buffer_set_user_data(handle, user_data);
559         return handle;
560 }
561
562 PUBLIC int livebox_request_update(const char *filename)
563 {
564         int uri_len;
565         char *uri;
566         int ret;
567
568         if (!filename) {
569                 ErrPrint("Invalid argument\n");
570                 return LB_STATUS_ERROR_INVALID;
571         }
572
573         uri_len = strlen(filename) + strlen(FILE_SCHEMA) + 1;
574         uri = malloc(uri_len);
575         if (!uri) {
576                 ErrPrint("Heap: %s\n", strerror(errno));
577                 return LB_STATUS_ERROR_MEMORY;
578         }
579
580         snprintf(uri, uri_len, FILE_SCHEMA "%s", filename);
581         ret = livebox_request_update_by_id(uri);
582         free(uri);
583         return ret;
584 }
585
586 PUBLIC unsigned long livebox_pixmap_id(struct livebox_buffer *handle)
587 {
588         return provider_buffer_pixmap_id(handle);
589 }
590
591 PUBLIC int livebox_release_buffer(struct livebox_buffer *handle)
592 {
593         struct livebox_buffer_data *user_data;
594
595         if (!handle)
596                 return LB_STATUS_ERROR_INVALID;
597
598         user_data = provider_buffer_user_data(handle);
599         if (user_data) {
600                 free(user_data);
601                 provider_buffer_set_user_data(handle, NULL);
602         }
603
604         DbgPrint("Release buffer\n");
605         return provider_buffer_release(handle);
606 }
607
608 PUBLIC void *livebox_ref_buffer(struct livebox_buffer *handle)
609 {
610         struct livebox_buffer_data *user_data;
611         void *data;
612         int w, h, size;
613         int ret;
614
615         if (!handle)
616                 return NULL;
617
618         user_data = provider_buffer_user_data(handle);
619         if (!user_data)
620                 return NULL;
621
622         if (user_data->accelerated) {
623                 DbgPrint("H/W accelerated buffer is allocated\n");
624                 return NULL;
625         }
626
627         ret = provider_buffer_get_size(handle, &w, &h, &size);
628
629         data = provider_buffer_ref(handle);
630         if (data && !ret && w > 0 && h > 0 && size > 0) {
631                 memset(data, 0, w * h * size);
632                 provider_buffer_sync(handle);
633         }
634
635         DbgPrint("Ref buffer %ds%d(%d)\n", w, h, size);
636         return data;
637 }
638
639 PUBLIC int livebox_unref_buffer(void *buffer)
640 {
641         if (!buffer)
642                 return LB_STATUS_ERROR_INVALID;
643
644         DbgPrint("Unref buffer\n");
645         return provider_buffer_unref(buffer);
646 }
647
648 PUBLIC int livebox_sync_buffer(struct livebox_buffer *handle)
649 {
650         struct livebox_buffer_data *user_data;
651         const char *pkgname;
652         const char *id;
653
654         if (!handle)
655                 return LB_STATUS_ERROR_INVALID;
656
657         user_data = provider_buffer_user_data(handle);
658         if (!user_data) {
659                 ErrPrint("Invalid buffer\n");
660                 return LB_STATUS_ERROR_INVALID;
661         }
662
663         if (user_data->accelerated) {
664                 DbgPrint("H/W Buffer allocated. skip the sync buffer\n");
665                 return LB_STATUS_SUCCESS;
666         }
667
668         pkgname = provider_buffer_pkgname(handle);
669         if (!pkgname) {
670                 ErrPrint("Invalid buffer handler\n");
671                 return LB_STATUS_ERROR_INVALID;
672         }
673
674         id = provider_buffer_id(handle);
675         if (!id) {
676                 ErrPrint("Invalid buffer handler\n");
677                 return LB_STATUS_ERROR_INVALID;
678         }
679
680         provider_buffer_sync(handle);
681
682         if (user_data->is_pd) {
683                 if (provider_send_desc_updated(pkgname, id, NULL) < 0)
684                         ErrPrint("Failed to send PD updated (%s)\n", id);
685         } else {
686                 int w;
687                 int h;
688                 int pixel_size;
689
690                 if (provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0)
691                         ErrPrint("Failed to get size (%s)\n", id);
692
693                 if (provider_send_updated(pkgname, id, w, h, -1.0f, NULL, NULL) < 0)
694                         ErrPrint("Failed to send updated (%s)\n", id);
695         }
696
697         return LB_STATUS_SUCCESS;
698 }
699
700 PUBLIC int livebox_support_hw_buffer(struct livebox_buffer *handle)
701 {
702         if (!handle)
703                 return LB_STATUS_ERROR_INVALID;
704
705         return provider_buffer_pixmap_is_support_hw(handle);
706 }
707
708 PUBLIC int livebox_create_hw_buffer(struct livebox_buffer *handle)
709 {
710         struct livebox_buffer_data *user_data;
711         int ret;
712
713         if (!handle)
714                 return LB_STATUS_ERROR_INVALID;
715
716         user_data = provider_buffer_user_data(handle);
717         if (!user_data)
718                 return LB_STATUS_ERROR_INVALID;
719
720         if (user_data->accelerated)
721                 return -EALREADY;
722
723         ret = provider_buffer_pixmap_create_hw(handle);
724         user_data->accelerated = (ret == 0);
725         return ret;
726 }
727
728 PUBLIC int livebox_destroy_hw_buffer(struct livebox_buffer *handle)
729 {
730         struct livebox_buffer_data *user_data;
731         if (!handle)
732                 return LB_STATUS_ERROR_INVALID;
733
734         user_data = provider_buffer_user_data(handle);
735         if (!user_data || !user_data->accelerated)
736                 return LB_STATUS_ERROR_INVALID;
737
738         user_data->accelerated = 0;
739
740         return provider_buffer_pixmap_destroy_hw(handle);
741 }
742
743 PUBLIC void *livebox_buffer_hw_buffer(struct livebox_buffer *handle)
744 {
745         struct livebox_buffer_data *user_data;
746
747         if (!handle)
748                 return NULL;
749
750         user_data = provider_buffer_user_data(handle);
751         if (!user_data || !user_data->accelerated)
752                 return NULL;
753
754         return provider_buffer_pixmap_hw_addr(handle);
755 }
756
757 PUBLIC int livebox_buffer_pre_render(struct livebox_buffer *handle)
758 {
759         struct livebox_buffer_data *user_data;
760
761         if (!handle)
762                 return LB_STATUS_ERROR_INVALID;
763
764         user_data = provider_buffer_user_data(handle);
765         if (!user_data)
766                 return LB_STATUS_ERROR_INVALID;
767
768         if (!user_data->accelerated)
769                 return LB_STATUS_SUCCESS;
770
771         /*!
772          * \note
773          * Do preprocessing for accessing the H/W render buffer
774          */
775         return provider_buffer_pre_render(handle);
776 }
777
778 PUBLIC int livebox_buffer_post_render(struct livebox_buffer *handle)
779 {
780         int ret;
781         const char *pkgname;
782         const char *id;
783         struct livebox_buffer_data *user_data;
784
785         if (!handle)
786                 return LB_STATUS_ERROR_INVALID;
787
788         user_data = provider_buffer_user_data(handle);
789         if (!user_data)
790                 return LB_STATUS_ERROR_INVALID;
791
792         if (!user_data->accelerated)
793                 return LB_STATUS_SUCCESS;
794
795         pkgname = provider_buffer_pkgname(handle);
796         if (!pkgname) {
797                 ErrPrint("Invalid buffer handle\n");
798                 return LB_STATUS_ERROR_INVALID;
799         }
800
801         id = provider_buffer_id(handle);
802         if (!id) {
803                 ErrPrint("Invalid buffer handler\n");
804                 return LB_STATUS_ERROR_INVALID;
805         }
806
807         ret = provider_buffer_post_render(handle);
808         if (ret < 0) {
809                 ErrPrint("Failed to post render processing\n");
810                 return ret;
811         }
812
813         if (user_data->is_pd == 1) {
814                 if (provider_send_desc_updated(pkgname, id, NULL) < 0)
815                         ErrPrint("Failed to send PD updated (%s)\n", id);
816         } else {
817                 int w;
818                 int h;
819                 int pixel_size;
820
821                 if (provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0)
822                         ErrPrint("Failed to get size (%s)\n", id);
823
824                 if (provider_send_updated(pkgname, id, w, h, -1.0f, NULL, NULL) < 0)
825                         ErrPrint("Failed to send updated (%s)\n", id);
826         }
827
828         return LB_STATUS_SUCCESS;
829 }
830
831 PUBLIC int livebox_content_is_updated(const char *filename, int is_pd)
832 {
833         return livebox_trigger_update_monitor(filename, is_pd);
834 }
835
836 /* End of a file */