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