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