Add TIME_CHANGED event
[apps/livebox/livebox.git] / src / livebox.c
1 /*
2  * Copyright 2012  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
28 #include "debug.h"
29 #include "livebox.h"
30 #include "dlist.h"
31 #include "util.h"
32
33 #define EAPI __attribute__((visibility("default")))
34
35 #define FILE_SCHEMA     "file://"
36
37 /*!
38  * \brief This function is defined by the data-provider-slave
39  */
40 extern const char *livebox_find_pkgname(const char *filename);
41 extern int livebox_request_update_by_id(const char *uri);
42
43 struct block {
44         unsigned int idx;
45
46         char *type;
47         char *part;
48         char *data;
49         char *group;
50         char *id;
51         char *file;
52         char *target_id;
53 };
54
55 struct livebox_desc {
56         FILE *fp;
57         int for_pd;
58
59         unsigned int last_idx;
60
61         struct dlist *block_list;
62 };
63
64 EAPI const int DONE = 0x00;
65 EAPI const int NEED_TO_SCHEDULE = 0x01;
66 EAPI const int OUTPUT_UPDATED = 0x02;
67 EAPI const int NEED_TO_CREATE = 0x01;
68 EAPI const int NEED_TO_DESTROY = 0x01;
69 EAPI const int LB_SYS_EVENT_FONT_CHANGED = 0x01;
70 EAPI const int LB_SYS_EVENT_LANG_CHANGED = 0x02;
71 EAPI const int LB_SYS_EVENT_TIME_CHANGED = 0x04;
72 EAPI const int LB_SYS_EVENT_PAUSED = 0x0100;
73 EAPI const int LB_SYS_EVENT_RESUMED = 0x0200;
74
75 EAPI struct livebox_desc *livebox_desc_open(const char *filename, int for_pd)
76 {
77         struct livebox_desc *handle;
78         char *new_fname;
79
80         handle = calloc(1, sizeof(*handle));
81         if (!handle) {
82                 ErrPrint("Error: %s\n", strerror(errno));
83                 return NULL;
84         }
85
86         if (for_pd) {
87                 int len;
88                 len = strlen(filename) + strlen(".desc") + 1;
89                 new_fname = malloc(len);
90                 if (!new_fname) {
91                         ErrPrint("Error: %s\n", strerror(errno));
92                         free(handle);
93                         return NULL;
94                 }
95                 snprintf(new_fname, len, "%s.desc", filename);
96         } else {
97                 new_fname = strdup(filename);
98                 if (!new_fname) {
99                         ErrPrint("Error: %s\n", strerror(errno));
100                         free(handle);
101                         return NULL;
102                 }
103         }
104
105         DbgPrint("Open a new file: %s\n", new_fname);
106         handle->fp = fopen(new_fname, "w+t");
107         free(new_fname);
108         if (!handle->fp) {
109                 ErrPrint("Failed to open a file: %s\n", strerror(errno));
110                 free(handle);
111                 return NULL;
112         }
113
114         return handle;
115 }
116
117 EAPI int livebox_desc_close(struct livebox_desc *handle)
118 {
119         struct dlist *l;
120         struct dlist *n;
121         struct block *block;
122
123         if (!handle)
124                 return -EINVAL;
125
126         DbgPrint("Close and flush\n");
127         dlist_foreach_safe(handle->block_list, l, n, block) {
128                 handle->block_list = dlist_remove(handle->block_list, l);
129
130                 DbgPrint("{\n");
131                 fprintf(handle->fp, "{\n");
132                 if (block->type) {
133                         fprintf(handle->fp, "type=%s\n", block->type);
134                         DbgPrint("type=%s\n", block->type);
135                 }
136
137                 if (block->part) {
138                         fprintf(handle->fp, "part=%s\n", block->part);
139                         DbgPrint("part=%s\n", block->part);
140                 }
141
142                 if (block->data) {
143                         fprintf(handle->fp, "data=%s\n", block->data);
144                         DbgPrint("data=%s\n", block->data);
145                 }
146
147                 if (block->group) {
148                         fprintf(handle->fp, "group=%s\n", block->group);
149                         DbgPrint("group=%s\n", block->group);
150                 }
151
152                 if (block->id) {
153                         fprintf(handle->fp, "id=%s\n", block->id);
154                         DbgPrint("id=%s\n", block->id);
155                 }
156
157                 if (block->target_id) {
158                         fprintf(handle->fp, "target=%s\n", block->target_id);
159                         DbgPrint("target=%s\n", block->target_id);
160                 }
161
162                 fprintf(handle->fp, "}\n");
163                 DbgPrint("}\n");
164
165                 free(block->type);
166                 free(block->part);
167                 free(block->data);
168                 free(block->group);
169                 free(block->id);
170                 free(block->target_id);
171                 free(block);
172         }
173
174         fclose(handle->fp);
175         free(handle);
176         return 0;
177 }
178
179 EAPI int livebox_desc_set_category(struct livebox_desc *handle, const char *id, const char *category)
180 {
181         struct block *block;
182
183         if (!handle || !category)
184                 return -EINVAL;
185
186         block = calloc(1, sizeof(*block));
187         if (!block)
188                 return -ENOMEM;
189
190         block->type = strdup(LB_DESC_TYPE_INFO);
191         if (!block->type) {
192                 free(block);
193                 return -ENOMEM;
194         }
195
196         block->part = strdup("category");
197         if (!block->part) {
198                 free(block->type);
199                 free(block);
200                 return -ENOMEM;
201         }
202
203         block->data = strdup(category);
204         if (!block->data) {
205                 free(block->type);
206                 free(block->part);
207                 free(block);
208                 return -ENOMEM;
209         }
210
211         if (id) {
212                 block->id = strdup(id);
213                 if (!block->id) {
214                         free(block->data);
215                         free(block->type);
216                         free(block->part);
217                         free(block);
218                         return -ENOMEM;
219                 }
220         }
221
222         block->idx = handle->last_idx++;
223         handle->block_list = dlist_append(handle->block_list, block);
224         return block->idx;
225 }
226
227 EAPI int livebox_desc_set_size(struct livebox_desc *handle, const char *id, int w, int h)
228 {
229         struct block *block;
230         char buffer[BUFSIZ];
231
232         if (!handle)
233                 return -EINVAL;
234
235         block = calloc(1, sizeof(*block));
236         if (!block)
237                 return -ENOMEM;
238
239         block->type = strdup(LB_DESC_TYPE_INFO);
240         if (!block->type) {
241                 free(block);
242                 return -ENOMEM;
243         }
244
245         block->part = strdup("size");
246         if (!block->part) {
247                 free(block->type);
248                 free(block);
249                 return -ENOMEM;
250         }
251
252         if (id) {
253                 block->id = strdup(id);
254                 if (!block->id) {
255                         free(block->part);
256                         free(block->type);
257                         free(block);
258                         return -ENOMEM;
259                 }
260         }
261
262         snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
263         block->data = strdup(buffer);
264         if (!block->data) {
265                 free(block->part);
266                 free(block->type);
267                 free(block);
268                 return -ENOMEM;
269         }
270
271         block->idx = handle->last_idx++;
272         handle->block_list = dlist_append(handle->block_list, block);
273         return block->idx;
274 }
275
276 EAPI char *livebox_util_nl2br(const char *str)
277 {
278         int len;
279         register int i;
280         char *ret;
281         char *ptr;
282
283         if (!str)
284                 return NULL;
285
286         len = strlen(str);
287         if (!len)
288                 return NULL;
289
290         ret = malloc(len);
291         if (!ret)
292                 return NULL;
293
294         ptr = ret;
295         i = 0;
296         while (*str) {
297                 switch (*str) {
298                 case '\n':
299                         if (len - i < 5) {
300                                 char *tmp;
301                                 len += len;
302
303                                 tmp = realloc(ret, len);
304                                 if (!tmp) {
305                                         free(ret);
306                                         return NULL;
307                                 }
308
309                                 ret = tmp;
310                                 ptr = tmp + i;
311                         }
312
313                         strcpy(ptr, "<br>");
314                         ptr += 4;
315                         i += 4;
316                         break;
317                 default:
318                         *ptr++ = *str;
319                         i++;
320                         break;
321                 }
322
323                 str++;
324         }
325         *ptr = '\0';
326
327         return ret;
328 }
329
330 EAPI int livebox_desc_set_id(struct livebox_desc *handle, int idx, const char *id)
331 {
332         struct dlist *l;
333         struct block *block;
334
335         dlist_foreach(handle->block_list, l, block) {
336                 if (block->idx == idx) {
337                         if (strcasecmp(block->type, LB_DESC_TYPE_SCRIPT)) {
338                                 ErrPrint("Invalid block is used\n");
339                                 return -EINVAL;
340                         }
341
342                         free(block->target_id);
343                         block->target_id = NULL;
344
345                         if (!id || !strlen(id))
346                                 return 0;
347
348                         block->target_id = strdup(id);
349                         if (!block->target_id) {
350                                 ErrPrint("Heap: %s\n", strerror(errno));
351                                 return -ENOMEM;
352                         }
353
354                         return 0;
355                 }
356         }
357
358         return -ENOENT;
359 }
360
361 /*!
362  * \return idx
363  */
364 EAPI int livebox_desc_add_block(struct livebox_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *group)
365 {
366         struct block *block;
367
368         if (!handle || !type)
369                 return -EINVAL;
370
371         if (!part)
372                 part = "";
373
374         if (!data)
375                 data = "";
376
377         block = calloc(1, sizeof(*block));
378         if (!block)
379                 return -ENOMEM;
380
381         block->type = strdup(type);
382         if (!block->type) {
383                 free(block);
384                 return -ENOMEM;
385         }
386
387         block->part = strdup(part);
388         if (!block->part) {
389                 free(block->type);
390                 free(block);
391                 return -ENOMEM;
392         }
393
394         block->data = strdup(data);
395         if (!block->data) {
396                 free(block->type);
397                 free(block->part);
398                 free(block);
399                 return -ENOMEM;
400         }
401
402         if (group) {
403                 block->group = strdup(group);
404                 if (!block->group) {
405                         free(block->data);
406                         free(block->type);
407                         free(block->part);
408                         free(block);
409                         return -ENOMEM;
410                 }
411         }
412
413         if (id) {
414                 block->id = strdup(id);
415                 if (!block->id) {
416                         free(block->group);
417                         free(block->data);
418                         free(block->type);
419                         free(block->part);
420                         free(block);
421                         return -ENOMEM;
422                 }
423         }
424
425         block->idx = handle->last_idx++;
426         handle->block_list = dlist_append(handle->block_list, block);
427         return block->idx;
428 }
429
430 EAPI int livebox_desc_del_block(struct livebox_desc *handle, int idx)
431 {
432         struct dlist *l;
433         struct block *block;
434
435         dlist_foreach(handle->block_list, l, block) {
436                 if (block->idx == idx) {
437                         handle->block_list = dlist_remove(handle->block_list, l);
438                         free(block->type);
439                         free(block->part);
440                         free(block->data);
441                         free(block->group);
442                         free(block->id);
443                         free(block->target_id);
444                         free(block);
445                         return 0;
446                 }
447         }
448
449         return -ENOENT;
450 }
451
452 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)
453 {
454         const char *pkgname;
455         struct livebox_buffer *handle;
456         char *uri;
457         int uri_len;
458
459         if (!filename || !width || !height) {
460                 ErrPrint("Invalid argument: %p(%dx%d)\n", filename, width, height);
461                 return NULL;
462         }
463
464         uri_len = strlen(filename) + strlen(FILE_SCHEMA) + 1;
465         uri = malloc(uri_len);
466         if (!uri) {
467                 ErrPrint("Heap: %s\n", strerror(errno));
468                 return NULL;
469         }
470
471         snprintf(uri, uri_len, FILE_SCHEMA "%s", filename);
472         pkgname = livebox_find_pkgname(uri);
473         if (!pkgname) {
474                 ErrPrint("Invalid Request\n");
475                 free(uri);
476                 return NULL;
477         }
478
479         handle = provider_buffer_acquire((!!is_pd) ? TYPE_PD : TYPE_LB, pkgname, uri, width, height, sizeof(int), handler, data);
480         DbgPrint("Acquire buffer for PD(%s), %s, %p\n", pkgname, uri, handle);
481         free(uri);
482         return handle;
483 }
484
485 EAPI int livebox_request_update(const char *filename)
486 {
487         int uri_len;
488         char *uri;
489         int ret;
490
491         if (!filename) {
492                 ErrPrint("Invalid argument\n");
493                 return -EINVAL;
494         }
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                 return -ENOMEM;
501         }
502
503         snprintf(uri, uri_len, FILE_SCHEMA "%s", filename);
504         ret = livebox_request_update_by_id(uri);
505         free(uri);
506         return ret;
507 }
508
509 EAPI unsigned long livebox_pixmap_id(struct livebox_buffer *handle)
510 {
511         return provider_buffer_pixmap_id(handle);
512 }
513
514 EAPI int livebox_release_buffer(struct livebox_buffer *handle)
515 {
516         if (!handle)
517                 return -EINVAL;
518
519         DbgPrint("Release buffer\n");
520         return provider_buffer_release(handle);
521 }
522
523 EAPI void *livebox_ref_buffer(struct livebox_buffer *handle)
524 {
525         if (!handle)
526                 return -EINVAL;
527
528         DbgPrint("Ref buffer\n");
529         return provider_buffer_ref(handle);
530 }
531
532 EAPI int livebox_unref_buffer(void *buffer)
533 {
534         if (!buffer)
535                 return -EINVAL;
536
537         DbgPrint("Unref buffer\n");
538         return provider_buffer_unref(buffer);
539 }
540
541 EAPI int livebox_sync_buffer(struct livebox_buffer *handle)
542 {
543         const char *pkgname;
544         const char *id;
545
546         if (!handle)
547                 return -EINVAL;
548
549         pkgname = provider_buffer_pkgname(handle);
550         id = provider_buffer_id(handle);
551         if (!pkgname || !id) {
552                 ErrPrint("Invalid buffer handler\n");
553                 return -EINVAL;
554         }
555
556         DbgPrint("Sync buffer\n");
557         provider_buffer_sync(handle);
558         provider_send_desc_updated(pkgname, id, NULL);
559         return 0;
560 }
561
562 /* End of a file */