Sync to I29fc45cc5bd693eb796d4ea256c0b23afe39b192
[platform/framework/web/livebox-viewer.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 <math.h>
22
23 #include <aul.h>
24 #include <dlog.h>
25
26 #include <com-core_packet.h>
27 #include <packet.h>
28 #include <livebox-service.h>
29 #include <livebox-errno.h>
30
31 #include "debug.h"
32 #include "fb.h"
33 #include "livebox.h"
34 #include "livebox_internal.h"
35 #include "dlist.h"
36 #include "util.h"
37 #include "master_rpc.h"
38 #include "client.h"
39 #include "critical_log.h"
40
41 #define EAPI __attribute__((visibility("default")))
42 #define MINIMUM_EVENT   s_info.event_filter
43
44 #if defined(FLOG)
45 FILE *__file_log_fp;
46 #endif
47
48 static struct info {
49         struct dlist *livebox_list;
50         struct dlist *event_list;
51         struct dlist *fault_list;
52         int init_count;
53         int prevent_overwrite;
54         double event_filter;
55 } s_info = {
56         .livebox_list = NULL,
57         .event_list = NULL,
58         .fault_list = NULL,
59         .init_count = 0,
60         .prevent_overwrite = 0,
61         .event_filter = 0.02f,
62 };
63
64 struct cb_info {
65         ret_cb_t cb;
66         void *data;
67 };
68
69 struct event_info {
70         int (*handler)(struct livebox *handler, enum livebox_event_type event, void *data);
71         void *user_data;
72 };
73
74 struct fault_info {
75         int (*handler)(enum livebox_fault_type event, const char *pkgname, const char *filename, const char *func, void *data);
76         void *user_data;
77 };
78
79 static inline void default_create_cb(struct livebox *handler, int ret, void *data)
80 {
81         DbgPrint("Default created event handler: %d\n", ret);
82 }
83
84 static inline void default_delete_cb(struct livebox *handler, int ret, void *data)
85 {
86         DbgPrint("Default deleted event handler: %d\n", ret);
87 }
88
89 static inline void default_pinup_cb(struct livebox *handler, int ret, void *data)
90 {
91         DbgPrint("Default pinup event handler: %d\n", ret);
92 }
93
94 static inline void default_group_changed_cb(struct livebox *handler, int ret, void *data)
95 {
96         DbgPrint("Default group changed event handler: %d\n", ret);
97 }
98
99 static inline void default_period_changed_cb(struct livebox *handler, int ret, void *data)
100 {
101         DbgPrint("Default period changed event handler: %d\n", ret);
102 }
103
104 static inline void default_pd_created_cb(struct livebox *handler, int ret, void *data)
105 {
106         DbgPrint("Default PD created event handler: %d\n", ret);
107 }
108
109 static inline void default_pd_destroyed_cb(struct livebox *handler, int ret, void *data)
110 {
111         DbgPrint("Default PD destroyed event handler: %d\n", ret);
112 }
113
114 static inline void default_lb_size_changed_cb(struct livebox *handler, int ret, void *data)
115 {
116         DbgPrint("Default LB size changed event handler: %d\n", ret);
117 }
118
119 static inline __attribute__((always_inline)) struct cb_info *create_cb_info(ret_cb_t cb, void *data)
120 {
121         struct cb_info *info;
122
123         info = malloc(sizeof(*info));
124         if (!info) {
125                 CRITICAL_LOG("Heap: %s\n", strerror(errno));
126                 return NULL;
127         }
128
129         info->cb = cb;
130         info->data = data;
131         return info;
132 }
133
134 static inline void destroy_cb_info(struct cb_info *info)
135 {
136         free(info);
137 }
138
139 static void resize_cb(struct livebox *handler, const struct packet *result, void *data)
140 {
141         int ret;
142         struct cb_info *info = data;
143         ret_cb_t cb;
144         void *cbdata;
145
146         cb = info->cb;
147         cbdata = info->data;
148         destroy_cb_info(info);
149
150         if (!result) {
151                 ret = LB_STATUS_ERROR_FAULT;
152         } else if (packet_get(result, "i", &ret) != 1) {
153                 ErrPrint("Invalid argument\n");
154                 ret = LB_STATUS_ERROR_INVALID;
155         }
156
157         /*!
158          * \note
159          * In case of resize request,
160          * The livebox handler will not have resized value right after this callback,
161          * It can only get the new size when it makes updates.
162          *
163          * So the user can only get the resized value(result) from the first update event
164          * after this request.
165          */
166         if (ret == 0) {
167                 DbgPrint("Resize request is done, prepare the size changed event\n");
168                 handler->size_changed_cb = cb;
169                 handler->size_cbdata = cbdata;
170         } else {
171                 DbgPrint("Resize request is failed: %d\n", ret);
172                 cb(handler, ret, cbdata);
173         }
174 }
175
176 static void text_signal_cb(struct livebox *handler, const struct packet *result, void *data)
177 {
178         int ret;
179         void *cbdata;
180         struct cb_info *info = data;
181         ret_cb_t cb;
182
183         cbdata = info->data;
184         cb = info->cb;
185         destroy_cb_info(info);
186
187         if (!result) {
188                 ret = LB_STATUS_ERROR_FAULT;
189         } else if (packet_get(result, "i", &ret) != 1) {
190                 ErrPrint("Invalid argument\n");
191                 ret = LB_STATUS_ERROR_INVALID;
192         }
193
194         if (cb)
195                 cb(handler, ret, cbdata);
196         return;
197 }
198
199 static void set_group_ret_cb(struct livebox *handler, const struct packet *result, void *data)
200 {
201         int ret;
202         void *cbdata;
203         ret_cb_t cb;
204         struct cb_info *info = data;
205
206         cbdata = info->data;
207         cb = info->cb;
208         destroy_cb_info(info);
209
210         if (!result) {
211                 ret = LB_STATUS_ERROR_FAULT;
212         } else if (packet_get(result, "i", &ret) != 1) {
213                 ErrPrint("Invalid argument\n");
214                 ret = LB_STATUS_ERROR_INVALID;
215         }
216
217         if (ret == 0) { /*!< Group information is successfully changed */
218                 handler->group_changed_cb = cb;
219                 handler->group_cbdata = cbdata;
220         } else if (cb) {
221                 cb(handler, ret, cbdata);
222         }
223
224         return;
225 }
226
227 static void period_ret_cb(struct livebox *handler, const struct packet *result, void *data)
228 {
229         struct cb_info *info = data;
230         int ret;
231         ret_cb_t cb;
232         void *cbdata;
233
234         cb = info->cb;
235         cbdata = info->data;
236         destroy_cb_info(info);
237
238         if (!result) {
239                 ret = LB_STATUS_ERROR_FAULT;
240         } else if (packet_get(result, "i", &ret) != 1) {
241                 ErrPrint("Invalid argument\n");
242                 ret = LB_STATUS_ERROR_INVALID;
243         }
244
245         if (ret == 0) {
246                 handler->period_changed_cb = cb;
247                 handler->period_cbdata = cbdata;
248         } else if (cb) {
249                 cb(handler, ret, cbdata);
250         }
251 }
252
253 static void del_ret_cb(struct livebox *handler, const struct packet *result, void *data)
254 {
255         struct cb_info *info = data;
256         int ret;
257         ret_cb_t cb;
258         void *cbdata;
259
260         cb = info->cb;
261         cbdata = info->data;
262         destroy_cb_info(info);
263
264         if (!result) {
265                 ErrPrint("Connection lost?\n");
266                 ret = LB_STATUS_ERROR_FAULT;
267         } else if (packet_get(result, "i", &ret) != 1) {
268                 ErrPrint("Invalid argument\n");
269                 ret = LB_STATUS_ERROR_INVALID;
270         }
271
272         if (ret == 0) {
273                 DbgPrint("Returns %d (waiting deleted event)\n", ret);
274                 handler->deleted_cb = cb;
275                 handler->deleted_cbdata = cbdata;
276         } else if (cb) {
277                 cb(handler, ret, cbdata);
278         }
279
280         /*!
281          * \note
282          * Do not call the deleted callback from here.
283          * master will send the "deleted" event.
284          * Then invoke this callback.
285          *
286          * if (handler->deleted_cb)
287          *      handler->deleted_cb(handler, ret, handler->deleted_cbdata);
288          */
289 }
290
291 static void new_ret_cb(struct livebox *handler, const struct packet *result, void *data)
292 {
293         int ret;
294         struct cb_info *info = data;
295         ret_cb_t cb;
296         void *cbdata;
297
298         cb = info->cb;
299         cbdata = info->data;
300         destroy_cb_info(info);
301
302         if (!result) {
303                 ret = LB_STATUS_ERROR_FAULT;
304         } else if (packet_get(result, "i", &ret) != 1) {
305                 ret = LB_STATUS_ERROR_INVALID;
306         }
307
308         if (ret >= 0) {
309                 DbgPrint("new request is sent, just waiting the created event\n");
310                 handler->created_cb = cb;
311                 handler->created_cbdata = cbdata;
312
313                 /*!
314                  * \note
315                  * Don't go anymore ;)
316                  */
317                 return;
318         } else if (cb) {
319                 /*!
320                  * \note
321                  * It means the current instance is not created,
322                  * so user has to know about this.
323                  * notice it to user using "deleted" event.
324                  */
325                 cb(handler, ret, cbdata);
326         }
327
328         lb_unref(handler);
329 }
330
331 static void pd_create_cb(struct livebox *handler, const struct packet *result, void *data)
332 {
333         struct cb_info *info = data;
334         void *cbdata;
335         ret_cb_t cb;
336         int ret;
337
338         cb = info->cb;
339         cbdata = info->data;
340         destroy_cb_info(data);
341
342         if (!result) {
343                 ret = LB_STATUS_ERROR_FAULT;
344         } else if (packet_get(result, "i", &ret) != 1) {
345                 ret = LB_STATUS_ERROR_INVALID;
346         }
347
348         if (ret == 0) {
349                 DbgPrint("PD Created event handler prepared\n");
350                 handler->pd_created_cb = cb;
351                 handler->pd_created_cbdata = cbdata;
352         } else if (cb) {
353                 DbgPrint("Failed to create a PD\n");
354                 cb(handler, ret, cbdata);
355         }
356 }
357
358 static void activated_cb(struct livebox *handler, const struct packet *result, void *data)
359 {
360         int ret;
361         struct cb_info *info = data;
362         void *cbdata;
363         ret_cb_t cb;
364         const char *pkgname = "";
365
366         cbdata = info->data;
367         cb = info->cb;
368         destroy_cb_info(info);
369
370         if (!result) {
371                 ret = LB_STATUS_ERROR_FAULT;
372         } else if (packet_get(result, "is", &ret, &pkgname) != 2) {
373                 ret = LB_STATUS_ERROR_INVALID;
374         }
375
376         if (cb)
377                 cb(handler, ret, cbdata);
378 }
379
380 static void pd_destroy_cb(struct livebox *handler, const struct packet *result, void *data)
381 {
382         int ret;
383         ret_cb_t cb;
384         void *cbdata;
385         struct cb_info *info = data;
386
387         cbdata = info->data;
388         cb = info->cb;
389         destroy_cb_info(info);
390
391         if (!result) {
392                 DbgPrint("Result is NIL (may connection lost)\n");
393                 ret = LB_STATUS_ERROR_FAULT;
394         } else if (packet_get(result, "i", &ret) != 1) {
395                 DbgPrint("Invalid parameter\n");
396                 ret = LB_STATUS_ERROR_INVALID;
397         }
398
399         if (ret == 0) {
400                 DbgPrint("PD Destroyed callback prepared\n");
401                 handler->pd_destroyed_cb = cb;
402                 handler->pd_destroyed_cbdata = cbdata;
403         } else if (cb) {
404                 DbgPrint("PD is not desroyed (forcely reset, pd flag)\n");
405                 handler->is_pd_created = 0;
406                 cb(handler, ret, cbdata);
407         }
408 }
409
410 static void delete_cluster_cb(struct livebox *handler, const struct packet *result, void *data)
411 {
412         struct cb_info *info = data;
413         int ret;
414         ret_cb_t cb;
415         void *cbdata;
416
417         cb = info->cb;
418         cbdata = info->data;
419         destroy_cb_info(info);
420
421         if (!result) {
422                 ret = LB_STATUS_ERROR_FAULT;
423         } else if (packet_get(result, "i", &ret) != 1) {
424                 ret = LB_STATUS_ERROR_INVALID;
425         }
426
427         DbgPrint("Delete category returns: %d\n", ret);
428
429         if (cb)
430                 cb(handler, ret, cbdata);
431 }
432
433 static void delete_category_cb(struct livebox *handler, const struct packet *result, void *data)
434 {
435         struct cb_info *info = data;
436         int ret;
437         ret_cb_t cb;
438         void *cbdata;
439
440         cb = info->cb;
441         cbdata = info->data;
442         destroy_cb_info(info);
443
444         if (!result)
445                 ret = LB_STATUS_ERROR_FAULT;
446         else if (packet_get(result, "i", &ret) != 1)
447                 ret = LB_STATUS_ERROR_INVALID;
448
449         DbgPrint("Delete category returns: %d\n", ret);
450
451         if (cb)
452                 cb(handler, ret, cbdata);
453 }
454
455 static void pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data)
456 {
457         int ret;
458         ret_cb_t cb;
459         void *cbdata;
460         struct cb_info *info = data;
461
462         cb = info->cb;
463         cbdata = info->data;
464         destroy_cb_info(info);
465
466         if (!result)
467                 ret = 0; /* PIXMAP 0 means error */
468         else if (packet_get(result, "i", &ret) != 1)
469                 ret = 0;
470
471         if (cb)
472                 cb(handler, ret, cbdata);
473 }
474
475 static void pinup_done_cb(struct livebox *handler, const struct packet *result, void *data)
476 {
477         int ret;
478         ret_cb_t cb;
479         void *cbdata;
480         struct cb_info *info = data;
481
482         cb = info->cb;
483         cbdata = info->data;
484         destroy_cb_info(info);
485
486         if (!result)
487                 ret = LB_STATUS_ERROR_FAULT;
488         else if (packet_get(result, "i", &ret) != 1)
489                 ret = LB_STATUS_ERROR_INVALID;
490
491         if (ret == 0) {
492                 handler->pinup_cb = cb;
493                 handler->pinup_cbdata = cbdata;
494         } else if (cb) {
495                 cb(handler, ret, cbdata);
496         }
497 }
498
499 static int send_mouse_event(struct livebox *handler, const char *event, int x, int y)
500 {
501         struct packet *packet;
502         double timestamp;
503
504         timestamp = util_timestamp();
505         packet = packet_create_noack(event, "ssdii", handler->pkgname, handler->id, timestamp, x, y);
506         if (!packet) {
507                 ErrPrint("Failed to build param\n");
508                 return LB_STATUS_ERROR_FAULT;
509         }
510
511         DbgPrint("Send: %dx%d\n", x, y);
512
513         return master_rpc_request_only(handler, packet);
514 }
515
516 EAPI int livebox_init(void *disp)
517 {
518         const char *env;
519
520         if (s_info.init_count > 0) {
521                 s_info.init_count++;
522                 return LB_STATUS_SUCCESS;
523         }
524         env = getenv("PROVIDER_DISABLE_PREVENT_OVERWRITE");
525         if (env && !strcasecmp(env, "true"))
526                 s_info.prevent_overwrite = 1;
527
528         env = getenv("PROVIDER_EVENT_FILTER");
529         if (env)
530                 sscanf(env, "%lf", &MINIMUM_EVENT);
531
532 #if defined(FLOG)
533         char filename[BUFSIZ];
534         snprintf(filename, sizeof(filename), "/tmp/%d.box.log", getpid());
535         __file_log_fp = fopen(filename, "w+t");
536         if (!__file_log_fp)
537                 __file_log_fp = fdopen(1, "w+t");
538 #endif
539         critical_log_init("viewer");
540         livebox_service_init();
541         fb_init(disp);
542
543         client_init();
544
545         s_info.init_count++;
546         return LB_STATUS_SUCCESS;
547 }
548
549 EAPI int livebox_fini(void)
550 {
551         if (s_info.init_count <= 0) {
552                 DbgPrint("Didn't initialized\n");
553                 return LB_STATUS_ERROR_INVALID;
554         }
555
556         s_info.init_count--;
557         if (s_info.init_count > 0) {
558                 DbgPrint("init count : %d\n", s_info.init_count);
559                 return LB_STATUS_SUCCESS;
560         }
561
562         client_fini();
563         fb_fini();
564         livebox_service_fini();
565         critical_log_fini();
566         return LB_STATUS_SUCCESS;
567 }
568
569 static inline char *lb_pkgname(const char *pkgname)
570 {
571         char *lb;
572
573         lb = livebox_service_pkgname(pkgname);
574         if (!lb) {
575                 if (util_validate_livebox_package(pkgname) == 0)
576                         return strdup(pkgname);
577         }
578
579         return lb;
580 }
581
582 /*!
583  * Just wrapping the livebox_add_with_size function.
584  */
585 EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const char *cluster, const char *category, double period, ret_cb_t cb, void *data)
586 {
587         return livebox_add_with_size(pkgname, content, cluster, category, period, LB_SIZE_TYPE_UNKNOWN, cb, data);
588 }
589
590 EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *content, const char *cluster, const char *category, double period, int type, ret_cb_t cb, void *data)
591 {
592         struct livebox *handler;
593         struct packet *packet;
594         int ret;
595         int width = 0;
596         int height = 0;
597
598         if (!pkgname || !cluster || !category) {
599                 ErrPrint("Invalid arguments: pkgname[%p], cluster[%p], category[%p]\n",
600                                                                 pkgname, cluster, category);
601                 return NULL;
602         }
603
604         if (type != LB_SIZE_TYPE_UNKNOWN)
605                 livebox_service_get_size(type, &width, &height);
606
607         handler = calloc(1, sizeof(*handler));
608         if (!handler) {
609                 ErrPrint("Error: %s\n", strerror(errno));
610                 return NULL;
611         }
612
613         handler->pkgname = lb_pkgname(pkgname);
614         if (!handler->pkgname) {
615                 free(handler);
616                 return NULL;
617         }
618
619         if (livebox_service_is_enabled(handler->pkgname) == 0) {
620                 DbgPrint("Livebox [%s](%s) is disabled package\n", handler->pkgname, pkgname);
621                 free(handler->pkgname);
622                 free(handler);
623                 return NULL;
624         }
625
626         if (content) {
627                 handler->content = strdup(content);
628                 if (!handler->content) {
629                         ErrPrint("Error: %s\n", strerror(errno));
630                         free(handler->pkgname);
631                         free(handler);
632                         return NULL;
633                 }
634         } else {
635                 handler->content = livebox_service_content(handler->pkgname);
636         }
637
638         handler->cluster = strdup(cluster);
639         if (!handler->cluster) {
640                 ErrPrint("Error: %s\n", strerror(errno));
641                 free(handler->content);
642                 free(handler->pkgname);
643                 free(handler);
644                 return NULL;
645         }
646
647         handler->category = strdup(category);
648         if (!handler->category) {
649                 ErrPrint("Error: %s\n", strerror(errno));
650                 free(handler->cluster);
651                 free(handler->content);
652                 free(handler->pkgname);
653                 free(handler);
654                 return NULL;
655         }
656
657         if (!cb)
658                 cb = default_create_cb;
659
660         /* Data provider will set this */
661         handler->lb.type = _LB_TYPE_FILE;
662         handler->pd.type = _PD_TYPE_SCRIPT;
663         handler->lb.period = period;
664
665         /* Used for handling the mouse event on a box */
666         handler->lb.mouse_event = livebox_service_mouse_event(handler->pkgname);
667
668         /* Cluster infomration is not determined yet */
669         handler->nr_of_sizes = 0x01;
670
671         handler->timestamp = util_timestamp();
672         handler->is_user = 1;
673         handler->visible = LB_SHOW;
674
675         s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
676
677         packet = packet_create("new", "dssssdii", handler->timestamp, handler->pkgname, handler->content, cluster, category, period, width, height);
678         if (!packet) {
679                 ErrPrint("Failed to create a new packet\n");
680                 free(handler->category);
681                 free(handler->cluster);
682                 free(handler->content);
683                 free(handler->pkgname);
684                 free(handler);
685                 return NULL;
686         }
687
688         ret = master_rpc_async_request(handler, packet, 0, new_ret_cb, create_cb_info(cb, data));
689         if (ret < 0) {
690                 ErrPrint("Failed to send a new packet\n");
691                 free(handler->category);
692                 free(handler->cluster);
693                 free(handler->content);
694                 free(handler->pkgname);
695                 free(handler);
696                 return NULL;
697         }
698
699         DbgPrint("Successfully sent a new request ([%lf] %s)\n", handler->timestamp, handler->pkgname);
700         handler->state = CREATE;
701         return lb_ref(handler);
702 }
703
704 EAPI double livebox_period(struct livebox *handler)
705 {
706         if (!handler || handler->state != CREATE || !handler->id) {
707                 ErrPrint("Handler is not valid\n");
708                 return 0.0f;
709         }
710
711         return handler->lb.period;
712 }
713
714 EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, void *data)
715 {
716         struct packet *packet;
717
718         if (!handler || handler->state != CREATE || !handler->id) {
719                 ErrPrint("Handler is not valid\n");
720                 return LB_STATUS_ERROR_INVALID;
721         }
722
723         if (handler->period_changed_cb) {
724                 ErrPrint("Previous request for changing period is not finished\n");
725                 return LB_STATUS_ERROR_BUSY;
726         }
727
728         if (!handler->is_user) {
729                 ErrPrint("CA Livebox is not able to change the period\n");
730                 return LB_STATUS_ERROR_PERMISSION;
731         }
732
733         if (handler->lb.period == period) {
734                 DbgPrint("No changes\n");
735                 return LB_STATUS_ERROR_ALREADY;
736         }
737
738         packet = packet_create("set_period", "ssd", handler->pkgname, handler->id, period);
739         if (!packet) {
740                 ErrPrint("Failed to build a packet %s\n", handler->pkgname);
741                 return LB_STATUS_ERROR_FAULT;
742         }
743
744         if (!cb)
745                 cb = default_period_changed_cb;
746
747         return master_rpc_async_request(handler, packet, 0, period_ret_cb, create_cb_info(cb, data));
748 }
749
750 EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data)
751 {
752         if (!handler) {
753                 ErrPrint("Handler is NIL\n");
754                 return LB_STATUS_ERROR_INVALID;
755         }
756
757         if (handler->state != CREATE) {
758                 ErrPrint("Handler is already deleted\n");
759                 return LB_STATUS_ERROR_INVALID;
760         }
761
762         handler->state = DELETE;
763
764         if (!handler->id) {
765                 /*!
766                  * \note
767                  * The id is not determined yet.
768                  * It means a user didn't receive created event yet.
769                  * Then just stop to delete procedure from here.
770                  * Because the "created" event handler will release this.
771                  * By the way, if the user adds any callback for getting return status of this,
772                  * call it at here.
773                  */
774                 if (cb)
775                         cb(handler, 0, data);
776                 return LB_STATUS_SUCCESS;
777         }
778
779         if (!cb)
780                 cb = default_delete_cb;
781
782         return lb_send_delete(handler, cb, data);
783 }
784
785 EAPI int livebox_set_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *), void *data)
786 {
787         struct fault_info *info;
788
789         if (!cb)
790                 return LB_STATUS_ERROR_INVALID;
791
792         info = malloc(sizeof(*info));
793         if (!info) {
794                 CRITICAL_LOG("Heap: %s\n", strerror(errno));
795                 return LB_STATUS_ERROR_MEMORY;
796         }
797
798         info->handler = cb;
799         info->user_data = data;
800
801         s_info.fault_list = dlist_append(s_info.fault_list, info);
802         return LB_STATUS_SUCCESS;
803 }
804
805 EAPI void *livebox_unset_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *))
806 {
807         struct fault_info *info;
808         struct dlist *l;
809
810         dlist_foreach(s_info.fault_list, l, info) {
811                 if (info->handler == cb) {
812                         void *data;
813                         s_info.fault_list = dlist_remove(s_info.fault_list, l);
814                         data = info->user_data;
815                         free(info);
816
817                         return data;
818                 }
819         }
820
821         return NULL;
822 }
823
824 EAPI int livebox_set_event_handler(int (*cb)(struct livebox *, enum livebox_event_type, void *), void *data)
825 {
826         struct event_info *info;
827
828         if (!cb) {
829                 ErrPrint("Invalid argument cb is nil\n");
830                 return LB_STATUS_ERROR_INVALID;
831         }
832
833         info = malloc(sizeof(*info));
834         if (!info) {
835                 CRITICAL_LOG("Heap: %s\n", strerror(errno));
836                 return LB_STATUS_ERROR_MEMORY;
837         }
838
839         info->handler = cb;
840         info->user_data = data;
841
842         s_info.event_list = dlist_append(s_info.event_list, info);
843         return LB_STATUS_SUCCESS;
844 }
845
846 EAPI void *livebox_unset_event_handler(int (*cb)(struct livebox *, enum livebox_event_type, void *))
847 {
848         struct event_info *info;
849         struct dlist *l;
850
851         dlist_foreach(s_info.event_list, l, info) {
852                 if (info->handler == cb) {
853                         void *data;
854
855                         s_info.event_list = dlist_remove(s_info.event_list, l);
856                         data = info->user_data;
857                         free(info);
858
859                         return data;
860                 }
861         }
862
863         return NULL;
864 }
865
866 EAPI int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *data)
867 {
868         struct packet *packet;
869         int w;
870         int h;
871
872         if (!handler) {
873                 ErrPrint("Handler is NIL\n");
874                 return LB_STATUS_ERROR_INVALID;
875         }
876
877         if (handler->state != CREATE || !handler->id) {
878                 ErrPrint("Handler is not valid\n");
879                 return LB_STATUS_ERROR_INVALID;
880         }
881
882         if (handler->size_changed_cb) {
883                 ErrPrint("Previous resize request is not finished yet\n");
884                 return LB_STATUS_ERROR_BUSY;
885         }
886
887         if (!handler->is_user) {
888                 ErrPrint("CA Livebox is not able to be resized\n");
889                 return LB_STATUS_ERROR_PERMISSION;
890         }
891
892         if (livebox_service_get_size(type, &w, &h) != 0) {
893                 ErrPrint("Invalid size type\n");
894                 return LB_STATUS_ERROR_INVALID;
895         }
896
897         if (handler->lb.width == w && handler->lb.height == h) {
898                 DbgPrint("No changes\n");
899                 return LB_STATUS_ERROR_ALREADY;;
900         }
901
902         packet = packet_create("resize", "ssii", handler->pkgname, handler->id, w, h);
903         if (!packet) {
904                 ErrPrint("Failed to build param\n");
905                 return LB_STATUS_ERROR_FAULT;
906         }
907
908         if (!cb)
909                 cb = default_lb_size_changed_cb;
910
911         return master_rpc_async_request(handler, packet, 0, resize_cb, create_cb_info(cb, data));
912 }
913
914 EAPI int livebox_click(struct livebox *handler, double x, double y)
915 {
916         struct packet *packet;
917         double timestamp;
918         int ret;
919
920         if (!handler) {
921                 ErrPrint("Handler is NIL\n");
922                 return LB_STATUS_ERROR_INVALID;
923         }
924
925         if (handler->state != CREATE || !handler->id) {
926                 ErrPrint("Handler is not valid\n");
927                 return LB_STATUS_ERROR_INVALID;
928         }
929
930         if (handler->lb.auto_launch)
931                 if (aul_open_app(handler->lb.auto_launch) < 0)
932                         ErrPrint("Failed to launch app %s\n", handler->lb.auto_launch);
933
934         timestamp = util_timestamp();
935         packet = packet_create_noack("clicked", "sssddd", handler->pkgname, handler->id, "clicked", timestamp, x, y);
936         if (!packet) {
937                 ErrPrint("Failed to build param\n");
938                 return LB_STATUS_ERROR_FAULT;
939         }
940
941         ret = master_rpc_request_only(handler, packet);
942         DbgPrint("Click request: %d\n", ret);
943
944         if (!handler->lb.mouse_event && (handler->lb.type == _LB_TYPE_BUFFER || handler->lb.type == _LB_TYPE_SCRIPT)) {
945                 int ret; /* Shadow variable */
946                 ret = send_mouse_event(handler, "lb_mouse_down", x * handler->lb.width, y * handler->lb.height);
947                 if (ret < 0)
948                         DbgPrint("Failed to send Down: %d\n", ret);
949
950                 ret = send_mouse_event(handler, "lb_mouse_move", x * handler->lb.width, y * handler->lb.height);
951                 if (ret < 0)
952                         DbgPrint("Failed to send Move: %d\n", ret);
953
954                 ret = send_mouse_event(handler, "lb_mouse_up", x * handler->lb.width, y * handler->lb.height);
955                 if (ret < 0)
956                         DbgPrint("Failed to send Up: %d\n", ret);
957         }
958
959         return ret;
960 }
961
962 EAPI int livebox_has_pd(struct livebox *handler)
963 {
964         if (!handler) {
965                 ErrPrint("Handler is NIL\n");
966                 return LB_STATUS_ERROR_INVALID;
967         }
968
969         if (handler->state != CREATE || !handler->id) {
970                 ErrPrint("Handler is not valid\n");
971                 return LB_STATUS_ERROR_INVALID;
972         }
973
974         return !!handler->pd.data.fb;
975 }
976
977 EAPI int livebox_pd_is_created(struct livebox *handler)
978 {
979         if (!handler) {
980                 ErrPrint("Handler is NIL\n");
981                 return LB_STATUS_ERROR_INVALID;
982         }
983
984         if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
985                 ErrPrint("Handler is not valid\n");
986                 return LB_STATUS_ERROR_INVALID;
987         }
988
989         return handler->is_pd_created;
990 }
991
992 EAPI int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *data)
993 {
994         return livebox_create_pd_with_position(handler, -1.0, -1.0, cb, data);
995 }
996
997 EAPI int livebox_create_pd_with_position(struct livebox *handler, double x, double y, ret_cb_t cb, void *data)
998 {
999         struct packet *packet;
1000
1001         if (!handler) {
1002                 ErrPrint("Handler is NIL\n");
1003                 return LB_STATUS_ERROR_INVALID;
1004         }
1005
1006         if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
1007                 ErrPrint("Handler is not valid\n");
1008                 return LB_STATUS_ERROR_INVALID;
1009         }
1010
1011         if (handler->is_pd_created == 1) {
1012                 DbgPrint("PD already created\n");
1013                 return LB_STATUS_SUCCESS;
1014         }
1015
1016         packet = packet_create("create_pd", "ssdd", handler->pkgname, handler->id, x, y);
1017         if (!packet) {
1018                 ErrPrint("Failed to build param\n");
1019                 return LB_STATUS_ERROR_FAULT;
1020         }
1021
1022         if (!cb)
1023                 handler->pd_created_cb = default_pd_created_cb;
1024
1025         return master_rpc_async_request(handler, packet, 0, pd_create_cb, create_cb_info(cb, data));
1026 }
1027
1028 EAPI int livebox_move_pd(struct livebox *handler, double x, double y)
1029 {
1030         struct packet *packet;
1031
1032         if (!handler) {
1033                 ErrPrint("Handler is NIL\n");
1034                 return LB_STATUS_ERROR_INVALID;
1035         }
1036
1037         if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
1038                 ErrPrint("Handler is not valid\n");
1039                 return LB_STATUS_ERROR_INVALID;
1040         }
1041
1042         if (!handler->is_pd_created) {
1043                 DbgPrint("PD is not created\n");
1044                 return LB_STATUS_ERROR_INVALID;
1045         }
1046
1047         packet = packet_create_noack("pd_move", "ssdd", handler->pkgname, handler->id, x, y);
1048         if (!packet) {
1049                 ErrPrint("Failed to build param\n");
1050                 return LB_STATUS_ERROR_FAULT;
1051         }
1052
1053         return master_rpc_request_only(handler, packet);
1054 }
1055
1056 EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data)
1057 {
1058         struct packet *packet;
1059
1060         if (!pkgname)
1061                 return LB_STATUS_ERROR_INVALID;
1062
1063         packet = packet_create("activate_package", "s", pkgname);
1064         if (!packet) {
1065                 ErrPrint("Failed to build a param\n");
1066                 return LB_STATUS_ERROR_FAULT;
1067         }
1068
1069         return master_rpc_async_request(NULL, packet, 0, activated_cb, create_cb_info(cb, data));
1070 }
1071
1072 EAPI int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data)
1073 {
1074         struct packet *packet;
1075
1076         if (!handler) {
1077                 ErrPrint("Handler is NIL\n");
1078                 return LB_STATUS_ERROR_INVALID;
1079         }
1080
1081         if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) {
1082                 ErrPrint("Handler is not valid\n");
1083                 return LB_STATUS_ERROR_INVALID;
1084         }
1085
1086         if (!handler->is_pd_created) {
1087                 ErrPrint("PD is not created\n");
1088                 return LB_STATUS_ERROR_INVALID;
1089         }
1090
1091         packet = packet_create("destroy_pd", "ss", handler->pkgname, handler->id);
1092         if (!packet) {
1093                 ErrPrint("Failed to build a param\n");
1094                 return LB_STATUS_ERROR_FAULT;
1095         }
1096
1097         if (!cb)
1098                 cb = default_pd_destroyed_cb;
1099
1100         return master_rpc_async_request(handler, packet, 0, pd_destroy_cb, create_cb_info(cb, data));
1101 }
1102
1103 EAPI int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y)
1104 {
1105         int w = 1;
1106         int h = 1;
1107         char cmd[32] = { '\0', };
1108         char *ptr = cmd;
1109
1110         if (!handler) {
1111                 ErrPrint("Handler is NIL\n");
1112                 return LB_STATUS_ERROR_INVALID;
1113         }
1114
1115         if (handler->state != CREATE || !handler->id) {
1116                 ErrPrint("Handler is not valid\n");
1117                 return LB_STATUS_ERROR_INVALID;
1118         }
1119
1120         if (type & CONTENT_EVENT_PD_MASK) {
1121                 int flag = 1;
1122
1123                 if (!handler->is_pd_created) {
1124                         ErrPrint("PD is not created\n");
1125                         return LB_STATUS_ERROR_INVALID;
1126                 }
1127
1128                 if (type & CONTENT_EVENT_MOUSE_MASK) {
1129                         if (!handler->pd.data.fb) {
1130                                 ErrPrint("Handler is not valid\n");
1131                                 return LB_STATUS_ERROR_INVALID;
1132                         }
1133
1134                         if (type & CONTENT_EVENT_MOUSE_MOVE) {
1135                                 if (fabs(x - handler->pd.x) < MINIMUM_EVENT && fabs(y - handler->pd.y) < MINIMUM_EVENT)
1136                                         return LB_STATUS_ERROR_BUSY;
1137                         } else if (type & CONTENT_EVENT_MOUSE_SET) {
1138                                 flag = 0;
1139                         }
1140                 }
1141
1142                 if (flag) {
1143                         w = handler->pd.width;
1144                         h = handler->pd.height;
1145                         handler->pd.x = x;
1146                         handler->pd.y = y;
1147                 }
1148                 *ptr++ = 'p';
1149                 *ptr++ = 'd';
1150         } else {
1151                 int flag = 1;
1152
1153                 if (type & CONTENT_EVENT_MOUSE_MASK) {
1154                         if (!handler->lb.mouse_event) {
1155                                 ErrPrint("Box is not support the mouse event\n");
1156                                 return LB_STATUS_ERROR_INVALID;
1157                         }
1158
1159                         if (!handler->lb.data.fb) {
1160                                 ErrPrint("Handler is not valid\n");
1161                                 return LB_STATUS_ERROR_INVALID;
1162                         }
1163
1164                         if (type & CONTENT_EVENT_MOUSE_MOVE) {
1165                                 if (fabs(x - handler->lb.x) < MINIMUM_EVENT && fabs(y - handler->lb.y) < MINIMUM_EVENT)
1166                                         return LB_STATUS_ERROR_BUSY;
1167                         } else if (type & CONTENT_EVENT_MOUSE_SET) {
1168                                 flag = 0;
1169                         }
1170                 }
1171
1172                 if (flag) {
1173                         w = handler->lb.width;
1174                         h = handler->lb.height;
1175                         handler->lb.x = x;
1176                         handler->lb.y = y;
1177                 }
1178                 *ptr++ = 'l';
1179                 *ptr++ = 'b';
1180         }
1181
1182         /*!
1183          * Must be short than 29 bytes.
1184          */
1185         switch ((type & ~CONTENT_EVENT_PD_MASK)) {
1186         case CONTENT_EVENT_ACCESS_HIGHLIGHT | CONTENT_EVENT_ACCESS_MASK:
1187                 strcpy(ptr, "_access_hl");
1188                 break;
1189         case CONTENT_EVENT_ACCESS_HIGHLIGHT_PREV | CONTENT_EVENT_ACCESS_MASK:
1190                 strcpy(ptr, "_access_hl_prev");
1191                 break;
1192         case CONTENT_EVENT_ACCESS_HIGHLIGHT_NEXT | CONTENT_EVENT_ACCESS_MASK:
1193                 strcpy(ptr, "_access_hl_next");
1194                 break;
1195         case CONTENT_EVENT_ACCESS_ACTIVATE | CONTENT_EVENT_ACCESS_MASK:
1196                 strcpy(ptr, "_access_activate");
1197                 break;
1198         case CONTENT_EVENT_ACCESS_VALUE_CHANGE | CONTENT_EVENT_ACCESS_MASK:
1199                 strcpy(ptr, "_access_value_change");
1200                 break;
1201         case CONTENT_EVENT_ACCESS_SCROLL | CONTENT_EVENT_ACCESS_MASK:
1202                 strcpy(ptr, "_access_scroll");
1203                 break;
1204         case CONTENT_EVENT_MOUSE_ENTER | CONTENT_EVENT_MOUSE_MASK:
1205                 strcpy(ptr, "_mouse_enter");
1206                 break;
1207         case CONTENT_EVENT_MOUSE_LEAVE | CONTENT_EVENT_MOUSE_MASK:
1208                 strcpy(ptr, "_mouse_leave");
1209                 break;
1210         case CONTENT_EVENT_MOUSE_UP | CONTENT_EVENT_MOUSE_MASK:
1211                 strcpy(ptr, "_mouse_up");
1212                 break;
1213         case CONTENT_EVENT_MOUSE_DOWN | CONTENT_EVENT_MOUSE_MASK:
1214                 strcpy(ptr, "_mouse_down");
1215                 break;
1216         case CONTENT_EVENT_MOUSE_MOVE | CONTENT_EVENT_MOUSE_MASK:
1217                 strcpy(ptr, "_mouse_move");
1218                 break;
1219         case CONTENT_EVENT_MOUSE_SET | CONTENT_EVENT_MOUSE_MASK:
1220                 strcpy(ptr, "_mouse_set");
1221                 break;
1222         case CONTENT_EVENT_MOUSE_UNSET | CONTENT_EVENT_MOUSE_MASK:
1223                 strcpy(ptr, "_mouse_unset");
1224                 break;
1225         case CONTENT_EVENT_KEY_DOWN | CONTENT_EVENT_KEY_MASK:
1226                 strcpy(ptr, "_key_down");
1227                 break;
1228         case CONTENT_EVENT_KEY_UP | CONTENT_EVENT_KEY_MASK:
1229                 strcpy(ptr, "_key_up");
1230                 break;
1231         default:
1232                 ErrPrint("Invalid event type\n");
1233                 return LB_STATUS_ERROR_INVALID;
1234         }
1235
1236         return send_mouse_event(handler, cmd, x * w, y * h);
1237 }
1238
1239 EAPI const char *livebox_filename(struct livebox *handler)
1240 {
1241         if (!handler) {
1242                 ErrPrint("Handler is NIL\n");
1243                 return NULL;
1244         }
1245
1246         if (handler->state != CREATE || !handler->id) {
1247                 ErrPrint("Handler is not valid\n");
1248                 return NULL;
1249         }
1250
1251         if (handler->filename)
1252                 return handler->filename;
1253
1254         /* Oooops */
1255         return util_uri_to_path(handler->id);
1256 }
1257
1258 EAPI int livebox_get_pdsize(struct livebox *handler, int *w, int *h)
1259 {
1260         int _w;
1261         int _h;
1262
1263         if (!handler) {
1264                 ErrPrint("Handler is NIL\n");
1265                 return LB_STATUS_ERROR_INVALID;
1266         }
1267
1268         if (handler->state != CREATE || !handler->id) {
1269                 ErrPrint("Handler is not valid\n");
1270                 return LB_STATUS_ERROR_INVALID;
1271         }
1272
1273         if (!w)
1274                 w = &_w;
1275         if (!h)
1276                 h = &_h;
1277
1278         if (!handler->is_pd_created) {
1279                 DbgPrint("Buffer is not created yet [%dx%d]\n", *w, *h);
1280                 *w = handler->pd.default_width;
1281                 *h = handler->pd.default_height;
1282         } else {
1283                 *w = handler->pd.width;
1284                 *h = handler->pd.height;
1285         }
1286
1287         return LB_STATUS_SUCCESS;
1288 }
1289
1290 EAPI int livebox_size(struct livebox *handler)
1291 {
1292         int w;
1293         int h;
1294
1295         if (!handler) {
1296                 ErrPrint("Handler is NIL\n");
1297                 return LB_STATUS_ERROR_INVALID;
1298         }
1299
1300         if (handler->state != CREATE || !handler->id) {
1301                 ErrPrint("Handler is not valid\n");
1302                 return LB_STATUS_ERROR_INVALID;
1303         }
1304
1305         w = handler->lb.width;
1306         h = handler->lb.height;
1307
1308         switch (handler->lb.type) {
1309         case _LB_TYPE_BUFFER:
1310         case _LB_TYPE_SCRIPT:
1311                 if (!fb_is_created(handler->lb.data.fb)) {
1312                         DbgPrint("Buffer is not created yet - reset size\n");
1313                         w = 0;
1314                         h = 0;
1315                 }
1316                 break;
1317         default:
1318                 break;
1319         }
1320
1321         return livebox_service_size_type(w, h);
1322 }
1323
1324 EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const char *category, ret_cb_t cb, void *data)
1325 {
1326         struct packet *packet;
1327
1328         if (!handler) {
1329                 ErrPrint("Handler is NIL\n");
1330                 return LB_STATUS_ERROR_INVALID;
1331         }
1332
1333         if (!cluster || !category || handler->state != CREATE || !handler->id) {
1334                 ErrPrint("Invalid argument\n");
1335                 return LB_STATUS_ERROR_INVALID;
1336         }
1337
1338         if (handler->group_changed_cb) {
1339                 ErrPrint("Previous group changing request is not finished yet\n");
1340                 return LB_STATUS_ERROR_BUSY;
1341         }
1342
1343         if (!handler->is_user) {
1344                 ErrPrint("CA Livebox is not able to change the group\n");
1345                 return LB_STATUS_ERROR_PERMISSION;
1346         }
1347
1348         if (!strcmp(handler->cluster, cluster) && !strcmp(handler->category, category)) {
1349                 DbgPrint("No changes\n");
1350                 return LB_STATUS_ERROR_ALREADY;
1351         }
1352
1353         packet = packet_create("change_group", "ssss", handler->pkgname, handler->id, cluster, category);
1354         if (!packet) {
1355                 ErrPrint("Failed to build a param\n");
1356                 return LB_STATUS_ERROR_FAULT;
1357         }
1358
1359         if (!cb)
1360                 cb = default_group_changed_cb;
1361
1362         return master_rpc_async_request(handler, packet, 0, set_group_ret_cb, create_cb_info(cb, data));
1363 }
1364
1365 EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category)
1366 {
1367         if (!handler) {
1368                 ErrPrint("Handler is NIL\n");
1369                 return LB_STATUS_ERROR_INVALID;
1370         }
1371
1372         if (!cluster || !category || handler->state != CREATE || !handler->id) {
1373                 ErrPrint("Invalid argument\n");
1374                 return LB_STATUS_ERROR_INVALID;
1375         }
1376
1377         *cluster = handler->cluster;
1378         *category = handler->category;
1379         return LB_STATUS_SUCCESS;
1380 }
1381
1382 EAPI int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *size_list)
1383 {
1384         register int i;
1385         register int j;
1386
1387         if (!handler || !size_list) {
1388                 ErrPrint("Invalid argument, handler(%p), size_list(%p)\n", handler, size_list);
1389                 return LB_STATUS_ERROR_INVALID;
1390         }
1391
1392         if (!cnt || handler->state != CREATE || !handler->id) {
1393                 ErrPrint("Handler is not valid\n");
1394                 return LB_STATUS_ERROR_INVALID;
1395         }
1396
1397         for (j = i = 0; i < NR_OF_SIZE_LIST; i++) {
1398                 if (handler->lb.size_list & (0x01 << i)) {
1399                         if (j == *cnt)
1400                                 break;
1401
1402                         size_list[j++] = (0x01 << i);
1403                 }
1404         }
1405
1406         *cnt = j;
1407         return LB_STATUS_SUCCESS;
1408 }
1409
1410 EAPI const char *livebox_pkgname(struct livebox *handler)
1411 {
1412         if (!handler) {
1413                 ErrPrint("Handler is NIL\n");
1414                 return NULL;
1415         }
1416
1417         if (handler->state != CREATE) {
1418                 ErrPrint("Handler is not valid\n");
1419                 return NULL;
1420         }
1421
1422         return handler->pkgname;
1423 }
1424
1425 EAPI double livebox_priority(struct livebox *handler)
1426 {
1427         if (!handler) {
1428                 ErrPrint("Handler is NIL\n");
1429                 return 0.0f;
1430         }
1431
1432         if (handler->state != CREATE || !handler->id) {
1433                 ErrPrint("Handler is not valid (%p)\n", handler);
1434                 return -1.0f;
1435         }
1436
1437         return handler->lb.priority;
1438 }
1439
1440 EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data)
1441 {
1442         struct packet *packet;
1443
1444         packet = packet_create("delete_cluster", "s", cluster);
1445         if (!packet) {
1446                 ErrPrint("Failed to build a param\n");
1447                 return LB_STATUS_ERROR_FAULT;
1448         }
1449
1450         return master_rpc_async_request(NULL, packet, 0, delete_cluster_cb, create_cb_info(cb, data));
1451 }
1452
1453 EAPI int livebox_delete_category(const char *cluster, const char *category, ret_cb_t cb, void *data)
1454 {
1455         struct packet *packet;
1456
1457         packet = packet_create("delete_category", "ss", cluster, category);
1458         if (!packet) {
1459                 ErrPrint("Failed to build a param\n");
1460                 return LB_STATUS_ERROR_FAULT;
1461         }
1462
1463         return master_rpc_async_request(NULL, packet, 0, delete_category_cb, create_cb_info(cb, data));
1464 }
1465
1466 EAPI enum livebox_lb_type livebox_lb_type(struct livebox *handler)
1467 {
1468         if (!handler) {
1469                 ErrPrint("Handler is NIL\n");
1470                 return LB_TYPE_INVALID;
1471         }
1472
1473         if (handler->state != CREATE || !handler->id) {
1474                 ErrPrint("Handler is not valid\n");
1475                 return LB_TYPE_INVALID;
1476         }
1477
1478         switch (handler->lb.type) {
1479         case _LB_TYPE_FILE:
1480                 return LB_TYPE_IMAGE;
1481         case _LB_TYPE_BUFFER:
1482         case _LB_TYPE_SCRIPT:
1483                 {
1484                         const char *id;
1485                         id = fb_id(handler->lb.data.fb);
1486                         if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
1487                                 return LB_TYPE_PIXMAP;
1488                 }
1489                 return LB_TYPE_BUFFER;
1490         case _LB_TYPE_TEXT:
1491                 return LB_TYPE_TEXT;
1492         default:
1493                 break;
1494         }
1495
1496         return LB_TYPE_INVALID;
1497 }
1498
1499 EAPI enum livebox_pd_type livebox_pd_type(struct livebox *handler)
1500 {
1501         if (!handler) {
1502                 ErrPrint("Handler is NIL\n");
1503                 return PD_TYPE_INVALID;
1504         }
1505
1506         if (handler->state != CREATE || !handler->id) {
1507                 ErrPrint("Handler is not valid\n");
1508                 return PD_TYPE_INVALID;
1509         }
1510
1511         switch (handler->pd.type) {
1512         case _PD_TYPE_TEXT:
1513                 return PD_TYPE_TEXT;
1514         case _PD_TYPE_BUFFER:
1515         case _PD_TYPE_SCRIPT:
1516                 {
1517                         const char *id;
1518                         id = fb_id(handler->pd.data.fb);
1519                         if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
1520                                 return PD_TYPE_PIXMAP;
1521                 }
1522                 return PD_TYPE_BUFFER;
1523         default:
1524                 break;
1525         }
1526
1527         return PD_TYPE_INVALID;
1528 }
1529
1530 EAPI int livebox_set_pd_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
1531 {
1532         if (!handler) {
1533                 ErrPrint("Handler is NIL\n");
1534                 return LB_STATUS_ERROR_INVALID;
1535         }
1536
1537         if (handler->state != CREATE) {
1538                 ErrPrint("Handler is not valid\n");
1539                 return LB_STATUS_ERROR_INVALID;
1540         }
1541
1542         memcpy(&handler->pd.data.ops, ops, sizeof(*ops));
1543         return LB_STATUS_SUCCESS;
1544 }
1545
1546 EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
1547 {
1548         if (!handler) {
1549                 ErrPrint("Handler is NIL\n");
1550                 return LB_STATUS_ERROR_INVALID;
1551         }
1552
1553         if (handler->state != CREATE) {
1554                 ErrPrint("Handler is not valid\n");
1555                 return LB_STATUS_ERROR_INVALID;
1556         }
1557
1558         memcpy(&handler->lb.data.ops, ops, sizeof(*ops));
1559         return LB_STATUS_SUCCESS;
1560 }
1561
1562 EAPI int livebox_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *data)
1563 {
1564         struct packet *packet;
1565         const char *id;
1566
1567         if (!handler) {
1568                 ErrPrint("Handler is NIL\n");
1569                 return LB_STATUS_ERROR_INVALID;
1570         }
1571
1572         if (handler->state != CREATE || !handler->id) {
1573                 ErrPrint("Invalid handle\n");
1574                 return LB_STATUS_ERROR_INVALID;
1575         }
1576
1577         if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
1578                 ErrPrint("Handler is not valid type\n");
1579                 return LB_STATUS_ERROR_INVALID;
1580         }
1581
1582         id = fb_id(handler->lb.data.fb);
1583         if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
1584                 return LB_STATUS_ERROR_INVALID;
1585
1586         packet = packet_create("lb_acquire_pixmap", "ss", handler->pkgname, handler->id);
1587         if (!packet) {
1588                 ErrPrint("Failed to build a param\n");
1589                 return LB_STATUS_ERROR_FAULT;
1590         }
1591
1592         return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
1593 }
1594
1595 EAPI int livebox_release_lb_pixmap(struct livebox *handler, int pixmap)
1596 {
1597         struct packet *packet;
1598
1599         if (!handler) {
1600                 ErrPrint("Handler is NIL\n");
1601                 return LB_STATUS_ERROR_INVALID;
1602         }
1603
1604         if (handler->state != CREATE || !handler->id) {
1605                 ErrPrint("Invalid handle\n");
1606                 return LB_STATUS_ERROR_INVALID;
1607         }
1608
1609         if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
1610                 ErrPrint("Handler is not valid type\n");
1611                 return LB_STATUS_ERROR_INVALID;
1612         }
1613
1614         packet = packet_create_noack("lb_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap);
1615         if (!packet) {
1616                 ErrPrint("Failed to build a param\n");
1617                 return LB_STATUS_ERROR_INVALID;
1618         }
1619
1620         return master_rpc_request_only(handler, packet);
1621 }
1622
1623 EAPI int livebox_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *data)
1624 {
1625         struct packet *packet;
1626         const char *id;
1627
1628         if (!handler) {
1629                 ErrPrint("Handler is NIL\n");
1630                 return LB_STATUS_ERROR_INVALID;
1631         }
1632
1633         if (handler->state != CREATE || !handler->id) {
1634                 ErrPrint("Invalid handle\n");
1635                 return LB_STATUS_ERROR_INVALID;
1636         }
1637
1638         if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
1639                 ErrPrint("Handler is not valid type\n");
1640                 return LB_STATUS_ERROR_INVALID;
1641         }
1642
1643         id = fb_id(handler->pd.data.fb);
1644         if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)))
1645                 return LB_STATUS_ERROR_INVALID;
1646
1647         packet = packet_create("pd_acquire_pixmap", "ss", handler->pkgname, handler->id);
1648         if (!packet) {
1649                 ErrPrint("Failed to build a param\n");
1650                 return LB_STATUS_ERROR_FAULT;
1651         }
1652
1653         return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
1654 }
1655
1656 EAPI int livebox_pd_pixmap(const struct livebox *handler)
1657 {
1658         const char *id;
1659         int pixmap = 0;
1660
1661         if (!handler) {
1662                 ErrPrint("Handler is NIL\n");
1663                 return 0;
1664         }
1665
1666         if (handler->state != CREATE || !handler->id) {
1667                 ErrPrint("Invalid handler\n");
1668                 return 0;
1669         }
1670
1671         if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
1672                 ErrPrint("Invalid handler\n");
1673                 return 0;
1674         }
1675
1676         id = fb_id(handler->pd.data.fb);
1677         if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) {
1678                 ErrPrint("PIXMAP Id is not valid\n");
1679                 return 0;
1680         }
1681
1682         return pixmap;
1683 }
1684
1685 EAPI int livebox_lb_pixmap(const struct livebox *handler)
1686 {
1687         const char *id;
1688         int pixmap = 0;
1689
1690         if (!handler) {
1691                 ErrPrint("Handler is NIL\n");
1692                 return 0;
1693         }
1694
1695         if (handler->state != CREATE || !handler->id) {
1696                 ErrPrint("Invalid handler\n");
1697                 return 0;
1698         }
1699
1700         if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
1701                 ErrPrint("Invalid handler\n");
1702                 return 0;
1703         }
1704
1705         id = fb_id(handler->lb.data.fb);
1706         if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) {
1707                 ErrPrint("PIXMAP Id is not valid\n");
1708                 return 0;
1709         }
1710
1711         return pixmap;
1712 }
1713
1714 EAPI int livebox_release_pd_pixmap(struct livebox *handler, int pixmap)
1715 {
1716         struct packet *packet;
1717
1718         if (!handler) {
1719                 ErrPrint("Handler is NIL\n");
1720                 return LB_STATUS_ERROR_INVALID;
1721         }
1722
1723         if (handler->state != CREATE || !handler->id) {
1724                 ErrPrint("Invalid handle\n");
1725                 return LB_STATUS_ERROR_INVALID;
1726         }
1727
1728         if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
1729                 ErrPrint("Handler is not valid type\n");
1730                 return LB_STATUS_ERROR_INVALID;
1731         }
1732
1733         packet = packet_create_noack("pd_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap);
1734         if (!packet) {
1735                 ErrPrint("Failed to build a param\n");
1736                 return LB_STATUS_ERROR_FAULT;
1737         }
1738
1739         return master_rpc_request_only(handler, packet);
1740 }
1741
1742 EAPI void *livebox_acquire_fb(struct livebox *handler)
1743 {
1744         if (!handler) {
1745                 ErrPrint("Handler is NIL\n");
1746                 return NULL;
1747         }
1748
1749         if (handler->state != CREATE || !handler->id) {
1750                 ErrPrint("Invalid handle\n");
1751                 return NULL;
1752         }
1753
1754         if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) {
1755                 ErrPrint("Handler is not valid type\n");
1756                 return NULL;
1757         }
1758
1759         return fb_acquire_buffer(handler->lb.data.fb);
1760 }
1761
1762 EAPI int livebox_release_fb(void *buffer)
1763 {
1764         return fb_release_buffer(buffer);
1765 }
1766
1767 EAPI int livebox_fb_refcnt(void *buffer)
1768 {
1769         return fb_refcnt(buffer);
1770 }
1771
1772 EAPI void *livebox_acquire_pdfb(struct livebox *handler)
1773 {
1774         if (!handler) {
1775                 ErrPrint("Handler is NIL\n");
1776                 return NULL;
1777         }
1778
1779         if (handler->state != CREATE || !handler->id) {
1780                 ErrPrint("Invalid handler\n");
1781                 return NULL;
1782         }
1783
1784         if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) {
1785                 ErrPrint("Handler is not valid type\n");
1786                 return NULL;
1787         }
1788
1789         return fb_acquire_buffer(handler->pd.data.fb);
1790 }
1791
1792 EAPI int livebox_release_pdfb(void *buffer)
1793 {
1794         return fb_release_buffer(buffer);
1795 }
1796
1797 EAPI int livebox_pdfb_refcnt(void *buffer)
1798 {
1799         return fb_refcnt(buffer);
1800 }
1801
1802 EAPI int livebox_pdfb_bufsz(struct livebox *handler)
1803 {
1804         if (!handler) {
1805                 ErrPrint("Handler is NIL\n");
1806                 return LB_STATUS_ERROR_INVALID;
1807         }
1808
1809         if (handler->state != CREATE || !handler->id) {
1810                 ErrPrint("Handler is not valid\n");
1811                 return LB_STATUS_ERROR_INVALID;
1812         }
1813
1814         return fb_size(handler->pd.data.fb);
1815 }
1816
1817 EAPI int livebox_lbfb_bufsz(struct livebox *handler)
1818 {
1819         if (!handler) {
1820                 ErrPrint("Handler is NIL\n");
1821                 return LB_STATUS_ERROR_INVALID;
1822         }
1823
1824         if (handler->state != CREATE || !handler->id) {
1825                 ErrPrint("Handler is not valid\n");
1826                 return LB_STATUS_ERROR_INVALID;
1827         }
1828
1829         return fb_size(handler->lb.data.fb);
1830 }
1831
1832 EAPI int livebox_is_user(struct livebox *handler)
1833 {
1834         if (!handler) {
1835                 ErrPrint("Handler is NIL\n");
1836                 return LB_STATUS_ERROR_INVALID;
1837         }
1838
1839         if (handler->state != CREATE) {
1840                 ErrPrint("Handler is invalid\n");
1841                 return LB_STATUS_ERROR_INVALID;
1842         }
1843
1844         return handler->is_user;
1845 }
1846
1847 EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void *data)
1848 {
1849         struct packet *packet;
1850
1851         if (!handler) {
1852                 ErrPrint("Handler is NIL\n");
1853                 return LB_STATUS_ERROR_INVALID;
1854         }
1855
1856         if (handler->state != CREATE || !handler->id) {
1857                 ErrPrint("Handler is not valid\n");
1858                 return LB_STATUS_ERROR_INVALID;
1859         }
1860
1861         if (handler->pinup_cb) {
1862                 ErrPrint("Previous pinup request is not finished\n");
1863                 return LB_STATUS_ERROR_BUSY;
1864         }
1865
1866         if (handler->is_pinned_up == flag) {
1867                 DbgPrint("No changes\n");
1868                 return LB_STATUS_ERROR_ALREADY;
1869         }
1870
1871         packet = packet_create("pinup_changed", "ssi", handler->pkgname, handler->id, flag);
1872         if (!packet) {
1873                 ErrPrint("Failed to build a param\n");
1874                 return LB_STATUS_ERROR_FAULT;
1875         }
1876
1877         if (!cb)
1878                 cb = default_pinup_cb;
1879
1880         return master_rpc_async_request(handler, packet, 0, pinup_done_cb, create_cb_info(cb, data));
1881 }
1882
1883 EAPI int livebox_is_pinned_up(struct livebox *handler)
1884 {
1885         if (!handler) {
1886                 ErrPrint("Handler is NIL\n");
1887                 return LB_STATUS_ERROR_INVALID;
1888         }
1889
1890         if (handler->state != CREATE || !handler->id)
1891                 return LB_STATUS_ERROR_INVALID;
1892
1893         return handler->is_pinned_up;
1894 }
1895
1896 EAPI int livebox_has_pinup(struct livebox *handler)
1897 {
1898         if (!handler) {
1899                 ErrPrint("Handler is NIL\n");
1900                 return LB_STATUS_ERROR_INVALID;
1901         }
1902
1903         if (handler->state != CREATE || !handler->id)
1904                 return LB_STATUS_ERROR_INVALID;
1905
1906         return handler->lb.pinup_supported;
1907 }
1908
1909 EAPI int livebox_set_data(struct livebox *handler, void *data)
1910 {
1911         if (!handler) {
1912                 ErrPrint("Handler is NIL\n");
1913                 return LB_STATUS_ERROR_INVALID;
1914         }
1915
1916         if (handler->state != CREATE)
1917                 return LB_STATUS_ERROR_INVALID;
1918
1919         handler->data = data;
1920         return LB_STATUS_SUCCESS;
1921 }
1922
1923 EAPI void *livebox_get_data(struct livebox *handler)
1924 {
1925         if (!handler) {
1926                 ErrPrint("Handler is NIL\n");
1927                 return NULL;
1928         }
1929
1930         if (handler->state != CREATE)
1931                 return NULL;
1932
1933         return handler->data;
1934 }
1935
1936 EAPI int livebox_is_exists(const char *pkgname)
1937 {
1938         char *lb;
1939
1940         lb = lb_pkgname(pkgname);
1941         if (lb) {
1942                 free(lb);
1943                 return 1;
1944         }
1945
1946         return 0;
1947 }
1948
1949 EAPI const char *livebox_content(struct livebox *handler)
1950 {
1951         if (!handler) {
1952                 ErrPrint("Handler is NIL\n");
1953                 return NULL;
1954         }
1955
1956         if (handler->state != CREATE)
1957                 return NULL;
1958
1959         return handler->content;
1960 }
1961
1962 EAPI const char *livebox_category_title(struct livebox *handler)
1963 {
1964         if (!handler) {
1965                 ErrPrint("Handler is NIL\n");
1966                 return NULL;
1967         }
1968
1969         if (handler->state != CREATE)
1970                 return NULL;
1971
1972         return handler->title;
1973 }
1974
1975 EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission, const char *source, double sx, double sy, double ex, double ey, ret_cb_t cb, void *data)
1976 {
1977         struct packet *packet;
1978
1979         if (!handler) {
1980                 ErrPrint("Handler is NIL\n");
1981                 return LB_STATUS_ERROR_INVALID;
1982         }
1983
1984         if ((handler->lb.type != _LB_TYPE_TEXT && handler->pd.type != _PD_TYPE_TEXT) || handler->state != CREATE || !handler->id) {
1985                 ErrPrint("Handler is not valid\n");
1986                 return LB_STATUS_ERROR_INVALID;
1987         }
1988
1989         if (!emission)
1990                 emission = "";
1991
1992         if (!source)
1993                 source = "";
1994
1995         packet = packet_create("text_signal", "ssssdddd",
1996                                 handler->pkgname, handler->id, emission, source, sx, sy, ex, ey);
1997         if (!packet) {
1998                 ErrPrint("Failed to build a param\n");
1999                 return LB_STATUS_ERROR_FAULT;
2000         }
2001
2002         return master_rpc_async_request(handler, packet, 0, text_signal_cb, create_cb_info(cb, data));
2003 }
2004
2005 EAPI int livebox_subscribe_group(const char *cluster, const char *category)
2006 {
2007         struct packet *packet;
2008
2009         /*!
2010          * \TODO
2011          * Validate the group info using DB
2012          * If the group info is not valid, do not send this request
2013          */
2014
2015         packet = packet_create_noack("subscribe", "ss", cluster ? cluster : "", category ? category : "");
2016         if (!packet) {
2017                 ErrPrint("Failed to create a packet\n");
2018                 return LB_STATUS_ERROR_FAULT;
2019         }
2020
2021         return master_rpc_request_only(NULL, packet);
2022 }
2023
2024 EAPI int livebox_unsubscribe_group(const char *cluster, const char *category)
2025 {
2026         struct packet *packet;
2027
2028         /*!
2029          * \TODO
2030          * Validate the group info using DB
2031          * If the group info is not valid, do not send this request
2032          * AND Check the subscribed or not too
2033          */
2034
2035         packet = packet_create_noack("unsubscribe", "ss", cluster ? cluster : "", category ? category : "");
2036         if (!packet) {
2037                 ErrPrint("Failed to create a packet\n");
2038                 return LB_STATUS_ERROR_FAULT;
2039         }
2040
2041         return master_rpc_request_only(NULL, packet);
2042 }
2043
2044 EAPI int livebox_refresh(struct livebox *handler)
2045 {
2046         struct packet *packet;
2047
2048         if (!handler) {
2049                 ErrPrint("Hnalder is NIL\n");
2050                 return LB_STATUS_ERROR_INVALID;
2051         }
2052
2053         if (handler->state != CREATE || !handler->id)
2054                 return LB_STATUS_ERROR_INVALID;
2055
2056         packet = packet_create_noack("update", "ss", handler->pkgname, handler->id);
2057         if (!packet) {
2058                 ErrPrint("Failed to create a packet\n");
2059                 return LB_STATUS_ERROR_FAULT;
2060         }
2061
2062         return master_rpc_request_only(handler, packet);
2063 }
2064
2065 EAPI int livebox_refresh_group(const char *cluster, const char *category)
2066 {
2067         struct packet *packet;
2068
2069         if (!cluster || !category) {
2070                 ErrPrint("Invalid argument\n");
2071                 return LB_STATUS_ERROR_INVALID;
2072         }
2073
2074         packet = packet_create_noack("refresh_group", "ss", cluster, category);
2075         if (!packet) {
2076                 ErrPrint("Failed to create a packet\n");
2077                 return LB_STATUS_ERROR_FAULT;
2078         }
2079
2080         return master_rpc_request_only(NULL, packet);
2081 }
2082
2083 EAPI int livebox_set_visibility(struct livebox *handler, enum livebox_visible_state state)
2084 {
2085         struct packet *packet;
2086         int ret;
2087
2088         if (!handler) {
2089                 ErrPrint("Handler is NIL\n");
2090                 return LB_STATUS_ERROR_INVALID;
2091         }
2092
2093         if (handler->state != CREATE || !handler->id)
2094                 return LB_STATUS_ERROR_INVALID;
2095
2096         if (!handler->is_user) {
2097                 /* System cluster livebox cannot be changed its visible states */
2098                 if (state == LB_HIDE_WITH_PAUSE) {
2099                         ErrPrint("CA Livebox is not able to change the visibility\n");
2100                         return LB_STATUS_ERROR_PERMISSION;
2101                 }
2102         }
2103
2104         DbgPrint("Change the visibility %d <> %d, %s\n", handler->visible, state, handler->id);
2105
2106         if (handler->visible == state)
2107                 return LB_STATUS_ERROR_ALREADY;
2108
2109         packet = packet_create_noack("change,visibility", "ssi", handler->pkgname, handler->id, (int)state);
2110         if (!packet) {
2111                 ErrPrint("Failed to create a packet\n");
2112                 return LB_STATUS_ERROR_FAULT;
2113         }
2114
2115         ret = master_rpc_request_only(handler, packet);
2116         if (ret == 0)
2117                 handler->visible = state;
2118
2119         return ret;
2120 }
2121
2122 EAPI enum livebox_visible_state livebox_visibility(struct livebox *handler)
2123 {
2124         if (!handler) {
2125                 ErrPrint("Handler is NIL\n");
2126                 return LB_VISIBLE_ERROR;
2127         }
2128
2129         if (handler->state != CREATE || !handler->id)
2130                 return LB_VISIBLE_ERROR;
2131
2132         return handler->visible;
2133 }
2134
2135 int lb_set_group(struct livebox *handler, const char *cluster, const char *category)
2136 {
2137         void *pc = NULL;
2138         void *ps = NULL;
2139
2140         if (cluster) {
2141                 pc = strdup(cluster);
2142                 if (!pc) {
2143                         CRITICAL_LOG("Heap: %s (cluster: %s)\n", strerror(errno), cluster);
2144                         return LB_STATUS_ERROR_MEMORY;
2145                 }
2146         }
2147
2148         if (category) {
2149                 ps = strdup(category);
2150                 if (!ps) {
2151                         CRITICAL_LOG("Heap: %s (category: %s)\n", strerror(errno), category);
2152                         free(pc);
2153                         return LB_STATUS_ERROR_MEMORY;
2154                 }
2155         }
2156
2157         if (handler->cluster)
2158                 free(handler->cluster);
2159
2160         if (handler->category)
2161                 free(handler->category);
2162
2163         handler->cluster = pc;
2164         handler->category = ps;
2165
2166         return LB_STATUS_SUCCESS;
2167 }
2168
2169 void lb_set_size(struct livebox *handler, int w, int h)
2170 {
2171         handler->lb.width = w;
2172         handler->lb.height = h;
2173 }
2174
2175 void lb_set_pdsize(struct livebox *handler, int w, int h)
2176 {
2177         handler->pd.width = w;
2178         handler->pd.height = h;
2179 }
2180
2181 void lb_set_default_pdsize(struct livebox *handler, int w, int h)
2182 {
2183         handler->pd.default_width = w;
2184         handler->pd.default_height = h;
2185 }
2186
2187 void lb_invoke_fault_handler(enum livebox_fault_type event, const char *pkgname, const char *file, const char *func)
2188 {
2189         struct dlist *l;
2190         struct dlist *n;
2191         struct fault_info *info;
2192
2193         dlist_foreach_safe(s_info.fault_list, l, n, info) {
2194                 if (info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE)
2195                         s_info.fault_list = dlist_remove(s_info.fault_list, l);
2196         }
2197 }
2198
2199 void lb_invoke_event_handler(struct livebox *handler, enum livebox_event_type event)
2200 {
2201         struct dlist *l;
2202         struct dlist *n;
2203         struct event_info *info;
2204
2205         dlist_foreach_safe(s_info.event_list, l, n, info) {
2206                 if (info->handler(handler, event, info->user_data) == EXIT_FAILURE)
2207                         s_info.event_list = dlist_remove(s_info.event_list, l);
2208         }
2209 }
2210
2211 struct livebox *lb_find_livebox(const char *pkgname, const char *id)
2212 {
2213         struct dlist *l;
2214         struct livebox *handler;
2215
2216         dlist_foreach(s_info.livebox_list, l, handler) {
2217                 if (!handler->id)
2218                         continue;
2219
2220                 if (!strcmp(handler->pkgname, pkgname) && !strcmp(handler->id, id))
2221                         return handler;
2222         }
2223
2224         return NULL;
2225 }
2226
2227 struct livebox *lb_find_livebox_by_timestamp(double timestamp)
2228 {
2229         struct dlist *l;
2230         struct livebox *handler;
2231
2232         dlist_foreach(s_info.livebox_list, l, handler) {
2233                 if (handler->timestamp == timestamp)
2234                         return handler;
2235         }
2236
2237         return NULL;
2238 }
2239
2240 static inline char *get_file_kept_in_safe(const char *id)
2241 {
2242         const char *path;
2243         char *new_path;
2244         int len;
2245         int base_idx;
2246
2247         path = util_uri_to_path(id);
2248         if (!path) {
2249                 ErrPrint("Invalid URI(%s)\n", id);
2250                 return NULL;
2251         }
2252
2253         /*!
2254          * \TODO: REMOVE ME
2255          */
2256         if (s_info.prevent_overwrite) {
2257                 new_path = strdup(path);
2258                 if (!new_path)
2259                         ErrPrint("Heap: %s\n", strerror(errno));
2260
2261                 return new_path;
2262         }
2263
2264
2265         len = strlen(path);
2266         base_idx = len - 1;
2267
2268         while (base_idx > 0 && path[base_idx] != '/') base_idx--;
2269         base_idx += (path[base_idx] == '/');
2270
2271         new_path = malloc(len + 10);
2272         if (!new_path) {
2273                 ErrPrint("Heap: %s\n", strerror(errno));
2274                 return NULL;
2275         }
2276
2277         strncpy(new_path, path, base_idx);
2278         snprintf(new_path + base_idx, len + 10 - base_idx, "reader/%s", path + base_idx);
2279         return new_path;
2280 }
2281
2282 struct livebox *lb_new_livebox(const char *pkgname, const char *id, double timestamp)
2283 {
2284         struct livebox *handler;
2285
2286         handler = calloc(1, sizeof(*handler));
2287         if (!handler) {
2288                 ErrPrint("Failed to create a new livebox\n");
2289                 return NULL;
2290         }
2291
2292         handler->pkgname = strdup(pkgname);
2293         if (!handler->pkgname) {
2294                 ErrPrint("%s\n", strerror(errno));
2295                 free(handler);
2296                 return NULL;
2297         }
2298
2299         handler->id = strdup(id);
2300         if (!handler->id) {
2301                 ErrPrint("%s\n", strerror(errno));
2302                 free(handler->pkgname);
2303                 free(handler);
2304                 return NULL;
2305         }
2306
2307         handler->filename = get_file_kept_in_safe(id);
2308         if (!handler->filename) {
2309                 handler->filename = strdup(util_uri_to_path(id));
2310                 if (!handler->filename)
2311                         ErrPrint("Error: %s\n", strerror(errno));
2312         }
2313
2314         handler->timestamp = timestamp;
2315         handler->lb.type = _LB_TYPE_FILE;
2316         handler->pd.type = _PD_TYPE_SCRIPT;
2317         handler->state = CREATE;
2318         handler->visible = LB_SHOW;
2319
2320         s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
2321         lb_ref(handler);
2322         return handler;
2323 }
2324
2325 int lb_delete_all(void)
2326 {
2327         struct dlist *l;
2328         struct dlist *n;
2329         struct livebox *handler;
2330
2331         dlist_foreach_safe(s_info.livebox_list, l, n, handler) {
2332                 lb_invoke_event_handler(handler, LB_EVENT_DELETED);
2333                 lb_unref(handler);
2334         }
2335
2336         return LB_STATUS_SUCCESS;
2337 }
2338
2339 int lb_set_content(struct livebox *handler, const char *content)
2340 {
2341         if (handler->content) {
2342                 free(handler->content);
2343                 handler->content = NULL;
2344         }
2345
2346         if (content) {
2347                 handler->content = strdup(content);
2348                 if (!handler->content) {
2349                         CRITICAL_LOG("Heap: %s (content: %s)\n", strerror(errno), content);
2350                         return LB_STATUS_ERROR_MEMORY;
2351                 }
2352         }
2353
2354         return LB_STATUS_SUCCESS;
2355 }
2356
2357 int lb_set_title(struct livebox *handler, const char *title)
2358 {
2359         if (handler->title) {
2360                 free(handler->title);
2361                 handler->title = NULL;
2362         }
2363
2364         if (title) {
2365                 handler->title = strdup(title);
2366                 if (!handler->title) {
2367                         CRITICAL_LOG("Heap: %s (title: %s)\n", strerror(errno), title);
2368                         return LB_STATUS_ERROR_MEMORY;
2369                 }
2370         }
2371
2372         return LB_STATUS_SUCCESS;
2373 }
2374
2375 void lb_set_size_list(struct livebox *handler, int size_list)
2376 {
2377         handler->lb.size_list = size_list;
2378 }
2379
2380 void lb_set_auto_launch(struct livebox *handler, const char *auto_launch)
2381 {
2382         if (!strlen(auto_launch))
2383                 return;
2384
2385         handler->lb.auto_launch = strdup(auto_launch);
2386         if (!handler->lb.auto_launch)
2387                 ErrPrint("Heap: %s\n", strerror(errno));
2388 }
2389
2390 void lb_set_priority(struct livebox *handler, double priority)
2391 {
2392         handler->lb.priority = priority;
2393 }
2394
2395 void lb_set_id(struct livebox *handler, const char *id)
2396 {
2397         if (handler->id)
2398                 free(handler->id);
2399
2400         handler->id = strdup(id);
2401         if (!handler->id)
2402                 ErrPrint("Error: %s\n", strerror(errno));
2403
2404         if (handler->filename)
2405                 free(handler->filename);
2406
2407         handler->filename = get_file_kept_in_safe(id);
2408         if (!handler->filename) {
2409                 handler->filename = strdup(util_uri_to_path(id));
2410                 if (!handler->filename)
2411                         ErrPrint("Error: %s\n", strerror(errno));
2412         }
2413 }
2414
2415 int lb_set_lb_fb(struct livebox *handler, const char *filename)
2416 {
2417         struct fb_info *fb;
2418
2419         if (!handler)
2420                 return LB_STATUS_ERROR_INVALID;
2421
2422         fb = handler->lb.data.fb;
2423         if (fb && !strcmp(fb_id(fb), filename)) /*!< BUFFER is not changed, */
2424                 return LB_STATUS_SUCCESS;
2425
2426         handler->lb.data.fb = NULL;
2427
2428         if (!filename || filename[0] == '\0') {
2429                 if (fb)
2430                         fb_destroy(fb);
2431                 return LB_STATUS_SUCCESS;
2432         }
2433
2434         handler->lb.data.fb = fb_create(filename, handler->lb.width, handler->lb.height);
2435         if (!handler->lb.data.fb) {
2436                 ErrPrint("Faield to create a FB\n");
2437                 if (fb)
2438                         fb_destroy(fb);
2439                 return LB_STATUS_ERROR_FAULT;
2440         }
2441
2442         if (fb)
2443                 fb_destroy(fb);
2444
2445         return LB_STATUS_SUCCESS;
2446 }
2447
2448 int lb_set_pd_fb(struct livebox *handler, const char *filename)
2449 {
2450         struct fb_info *fb;
2451
2452         if (!handler)
2453                 return LB_STATUS_ERROR_INVALID;
2454
2455         fb = handler->pd.data.fb;
2456         if (fb && !strcmp(fb_id(fb), filename)) {
2457                 /* BUFFER is not changed, just update the content */
2458                 return LB_STATUS_ERROR_EXIST;
2459         }
2460         handler->pd.data.fb = NULL;
2461
2462         if (!filename || filename[0] == '\0') {
2463                 if (fb)
2464                         fb_destroy(fb);
2465                 return LB_STATUS_SUCCESS;
2466         }
2467
2468         handler->pd.data.fb = fb_create(filename, handler->pd.width, handler->pd.height);
2469         if (!handler->pd.data.fb) {
2470                 ErrPrint("Failed to create a FB\n");
2471                 if (fb)
2472                         fb_destroy(fb);
2473                 return LB_STATUS_ERROR_FAULT;
2474         }
2475
2476         if (fb)
2477                 fb_destroy(fb);
2478         return LB_STATUS_SUCCESS;
2479 }
2480
2481 struct fb_info *lb_get_lb_fb(struct livebox *handler)
2482 {
2483         return handler->lb.data.fb;
2484 }
2485
2486 struct fb_info *lb_get_pd_fb(struct livebox *handler)
2487 {
2488         return handler->pd.data.fb;
2489 }
2490
2491 void lb_set_user(struct livebox *handler, int user)
2492 {
2493         handler->is_user = user;
2494 }
2495
2496 void lb_set_pinup(struct livebox *handler, int pinup_supported)
2497 {
2498         handler->lb.pinup_supported = pinup_supported;
2499 }
2500
2501 void lb_set_text_lb(struct livebox *handler)
2502 {
2503         handler->lb.type = _LB_TYPE_TEXT;
2504 }
2505
2506 void lb_set_text_pd(struct livebox *handler)
2507 {
2508         handler->pd.type = _PD_TYPE_TEXT;
2509 }
2510
2511 int lb_text_lb(struct livebox *handler)
2512 {
2513         return handler->lb.type == _LB_TYPE_TEXT;
2514 }
2515
2516 int lb_text_pd(struct livebox *handler)
2517 {
2518         return handler->pd.type == _PD_TYPE_TEXT;
2519 }
2520
2521 void lb_set_period(struct livebox *handler, double period)
2522 {
2523         handler->lb.period = period;
2524 }
2525
2526 struct livebox *lb_ref(struct livebox *handler)
2527 {
2528         if (!handler)
2529                 return NULL;
2530
2531         handler->refcnt++;
2532         return handler;
2533 }
2534
2535 struct livebox *lb_unref(struct livebox *handler)
2536 {
2537         if (!handler)
2538                 return NULL;
2539
2540         handler->refcnt--;
2541         if (handler->refcnt > 0)
2542                 return handler;
2543
2544         if (handler->filename)
2545                 util_unlink(handler->filename);
2546
2547         dlist_remove_data(s_info.livebox_list, handler);
2548
2549         handler->state = DESTROYED;
2550         free(handler->cluster);
2551         free(handler->category);
2552         free(handler->id);
2553         free(handler->pkgname);
2554         free(handler->filename);
2555         free(handler->lb.auto_launch);
2556
2557         if (handler->lb.data.fb) {
2558                 fb_destroy(handler->lb.data.fb);
2559                 handler->lb.data.fb = NULL;
2560         }
2561
2562         if (handler->pd.data.fb) {
2563                 fb_destroy(handler->pd.data.fb);
2564                 handler->pd.data.fb = NULL;
2565         }
2566
2567         free(handler);
2568         return NULL;
2569 }
2570
2571 int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data)
2572 {
2573         struct packet *packet;
2574
2575         if (!cb && !!data) {
2576                 ErrPrint("Invalid argument\n");
2577                 return LB_STATUS_ERROR_INVALID;
2578         }
2579
2580         if (handler->deleted_cb) {
2581                 ErrPrint("Already in-progress\n");
2582                 return LB_STATUS_ERROR_BUSY;
2583         }
2584
2585         packet = packet_create("delete", "ss", handler->pkgname, handler->id);
2586         if (!packet) {
2587                 ErrPrint("Failed to build a param\n");
2588                 if (cb)
2589                         cb(handler, LB_STATUS_ERROR_FAULT, data);
2590
2591                 return LB_STATUS_ERROR_FAULT;
2592         }
2593
2594         if (!cb)
2595                 cb = default_delete_cb;
2596
2597         return master_rpc_async_request(handler, packet, 0, del_ret_cb, create_cb_info(cb, data));
2598 }
2599
2600 EAPI int livebox_client_paused(void)
2601 {
2602         struct packet *packet;
2603
2604         packet = packet_create_noack("client_paused", "d", util_timestamp());
2605         if (!packet) {
2606                 ErrPrint("Failed to create a pause packet\n");
2607                 return LB_STATUS_ERROR_FAULT;
2608         }
2609
2610         return master_rpc_request_only(NULL, packet);
2611 }
2612
2613 EAPI int livebox_client_resumed(void)
2614 {
2615         struct packet *packet;
2616
2617         packet = packet_create_noack("client_resumed", "d", util_timestamp());
2618         if (!packet) {
2619                 ErrPrint("Failed to create a resume packet\n");
2620                 return LB_STATUS_ERROR_FAULT;
2621         }
2622
2623         return master_rpc_request_only(NULL, packet);
2624 }
2625
2626 /* End of a file */