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