Add new internal API
[platform/framework/web/data-provider-slave.git] / src / lb.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h> /* exit */
19 #include <errno.h>
20 #include <unistd.h> /* access */
21
22 #include <Ecore.h>
23 #include <Eina.h>
24
25 #include <dlog.h>
26 #include <provider.h>
27 #include <livebox.h>
28 #include <livebox-errno.h>
29
30 #include "critical_log.h"
31 #include "debug.h"
32 #include "conf.h"
33 #include "so_handler.h"
34 #include "lb.h"
35 #include "update_monitor.h"
36 #include "fault.h"
37 #include "util.h"
38
39 #define IS_LB_SHOWN(itm) (!(itm)->inst->item->has_livebox_script || ((itm)->inst->item->has_livebox_script && (itm)->is_lb_show))
40
41 int errno;
42
43 struct item {
44         Ecore_Timer *timer;
45         struct instance *inst;
46         int monitor_cnt;
47         Ecore_Timer *monitor;
48         int deleteme;
49         double update_interval;
50         int heavy_updating; /* Only for debugging message */
51         int is_paused; /* 1 is paused, 0 is resumed */
52         double sleep_at;
53
54         int is_lb_show;
55         int is_pd_show;
56         int is_lb_updated;
57 };
58
59 static struct info {
60         Eina_List *item_list;
61         struct item *update;
62         Eina_List *pending_list;
63         Ecore_Timer *pending_timer;
64         Eina_List *pd_open_pending_list;
65         Ecore_Timer *pd_open_pending_timer;
66         int paused;
67         Eina_List *pd_list;
68         int secured;
69         int pending_timer_freezed;
70 } s_info  = {
71         .item_list = NULL,
72         .update = NULL,
73         .pending_list = NULL,
74         .pending_timer = NULL,
75         .pd_open_pending_list = NULL,
76         .pd_open_pending_timer = NULL,
77         .paused = 0,
78         .pd_list = NULL,
79         .secured = 0,
80         .pending_timer_freezed = 0,
81 };
82
83 static Eina_Bool updator_cb(void *data);
84
85 static void pending_timer_freeze(void)
86 {
87         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
88         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
89                 DbgPrint("Freeze the pending timer\n");
90                 ecore_timer_freeze(s_info.pending_timer);
91         }
92
93         s_info.pending_timer_freezed++;
94 }
95
96 static void pending_timer_thaw(void)
97 {
98         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
99         if (!s_info.pending_timer_freezed)
100                 return;
101
102         s_info.pending_timer_freezed--;
103         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
104                 DbgPrint("Thaw the pending timer\n");
105                 ecore_timer_thaw(s_info.pending_timer);
106         }
107 }
108
109 /*
110  * -1 : PD is opened, but not mine
111  *  0 : PD is not opened
112  *  1 : my PD is opened
113  */
114 static inline int pd_is_opened(const char *pkgname)
115 {
116         int i;
117         Eina_List *l;
118         char *tmp;
119
120         i = 0;
121         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
122                 if (pkgname && !strcmp(pkgname, tmp))
123                         return 1;
124
125                 i++;
126         }
127
128         return i > 0 ? -1 : 0;
129 }
130
131 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
132 {
133         struct item *item;
134
135         item = eina_list_nth(s_info.pd_open_pending_list, 0);
136         if (!item)
137                 goto cleanout;
138
139         if (s_info.update)
140                 return ECORE_CALLBACK_RENEW;
141
142         s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
143         /*!
144          * \note
145          * To prevent from checking the is_updated function
146          */
147         (void)updator_cb(item);
148         if (s_info.pd_open_pending_list)
149                 return ECORE_CALLBACK_RENEW;
150
151 cleanout:
152         s_info.pd_open_pending_timer = NULL;
153         return ECORE_CALLBACK_CANCEL;
154 }
155
156 static Eina_Bool pended_cmd_consumer_cb(void *data)
157 {
158         struct item *item;
159
160         item = eina_list_nth(s_info.pending_list, 0);
161         if (!item)
162                 goto cleanout;
163
164         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0)
165                 return ECORE_CALLBACK_RENEW;
166
167         s_info.pending_list = eina_list_remove(s_info.pending_list, item);
168         /*!
169          * \note
170          * To prevent from checking the is_updated function
171          */
172         (void)updator_cb(item);
173         if (s_info.pending_list)
174                 return ECORE_CALLBACK_RENEW;
175
176 cleanout:
177         s_info.pending_timer = NULL;
178         s_info.pending_timer_freezed = 0;
179         return ECORE_CALLBACK_CANCEL;
180 }
181
182 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
183 {
184         if (s_info.pending_timer)
185                 return 0;
186
187         s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
188         if (!s_info.pending_timer) {
189                 ErrPrint("Failed to add a new pended command consumer\n");
190                 return LB_STATUS_ERROR_FAULT;
191         }
192
193         /*!
194          * Do not increase the freezed counter.
195          * Just freeze the timer.
196          */
197         if (s_info.pending_timer_freezed)
198                 ecore_timer_freeze(s_info.pending_timer);
199
200         return 0;
201 }
202
203 static inline void deactivate_pending_consumer(void)
204 {
205         if (!s_info.pending_timer)
206                 return;
207
208         ecore_timer_del(s_info.pending_timer);
209         s_info.pending_timer = NULL;
210         s_info.pending_timer_freezed = 0;
211 }
212
213 static inline void deactivate_pd_open_pending_consumer(void)
214 {
215         if (!s_info.pd_open_pending_timer)
216                 return;
217
218         ecore_timer_del(s_info.pd_open_pending_timer);
219         s_info.pd_open_pending_timer = NULL;
220 }
221
222 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
223 {
224         if (s_info.pd_open_pending_timer)
225                 return 0;
226
227         s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
228         if (!s_info.pd_open_pending_timer) {
229                 ErrPrint("Failed to add a new pended command consumer\n");
230                 return LB_STATUS_ERROR_FAULT;
231         }
232
233         return 0;
234 }
235
236 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
237 {
238         Eina_List *l;
239         Eina_List *n;
240         struct item *item;
241         int cnt = 0;
242
243         EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
244                 if (strcmp(pkgname, item->inst->item->pkgname))
245                         continue;
246
247                 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
248                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
249                 cnt++;
250         }
251
252         if (s_info.pd_open_pending_list)
253                 activate_pd_open_pending_consumer();
254
255         if (!s_info.pending_list)
256                 deactivate_pending_consumer();
257 }
258
259 static inline void migrate_to_pending_list(const char *pkgname)
260 {
261         Eina_List *l;
262         Eina_List *n;
263         struct item *item;
264         int cnt = 0;
265
266         EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
267                 if (strcmp(pkgname, item->inst->item->pkgname))
268                         continue;
269
270                 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
271                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
272                 cnt++;
273         }
274
275         if (s_info.pending_list)
276                 activate_pending_consumer();
277
278         if (!s_info.pd_open_pending_list)
279                 deactivate_pd_open_pending_consumer();
280 }
281
282 static inline int append_pending_list(struct item *item)
283 {
284         if (pd_is_opened(item->inst->item->pkgname) == 1) {
285                 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
286                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
287                         return LB_STATUS_ERROR_EXIST;
288                 }
289
290                 if (activate_pd_open_pending_consumer() < 0) {
291                         ErrPrint("Failed to activate PD open pending consumer\n");
292                         return LB_STATUS_ERROR_FAULT;
293                 }
294
295                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
296         } else {
297                 if (eina_list_data_find(s_info.pending_list, item) == item) {
298                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
299                         return LB_STATUS_ERROR_EXIST;
300                 }
301
302                 if (activate_pending_consumer() < 0)
303                         return LB_STATUS_ERROR_FAULT;
304
305                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
306         }
307         return 0;
308 }
309
310 static inline void timer_thaw(struct item *item)
311 {
312         double pending;
313         double period;
314         double delay;
315         double sleep_time;
316
317         if (!item->timer)
318                 return;
319
320         ecore_timer_thaw(item->timer);
321         period = ecore_timer_interval_get(item->timer);
322         pending = ecore_timer_pending_get(item->timer);
323         delay = util_time_delay_for_compensation(period) - pending;
324         ecore_timer_delay(item->timer, delay);
325
326         if (item->sleep_at == 0.0f)
327                 return;
328
329         sleep_time = util_timestamp() - item->sleep_at;
330         if (sleep_time > pending)
331                 (void)updator_cb(item);
332
333         item->sleep_at = 0.0f;
334 }
335
336 static inline void timer_freeze(struct item *item)
337 {
338         struct timeval tv;
339
340         if (!item->timer)
341                 return;
342
343         ecore_timer_freeze(item->timer);
344
345         if (ecore_timer_interval_get(item->timer) <= 1.0f)
346                 return;
347
348         if (gettimeofday(&tv, NULL) < 0) {
349                 ErrPrint("gettimeofday: %s\n", strerror(errno));
350                 tv.tv_sec = 0;
351                 tv.tv_usec = 0;
352         }
353
354         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
355 }
356
357 static inline void update_monitor_cnt(struct item *item)
358 {
359         double now;
360         double interval;
361
362         now = util_timestamp();
363         interval = now - item->update_interval;
364
365         /*!
366          * \note
367          * If the content update is processed in too short time,
368          * don't increase the monitor counter, instead of it
369          * set the heavy updating flag.
370          * And handling this heavy updating from the
371          * file update callback.
372          */
373         if (interval >= MINIMUM_UPDATE_INTERVAL) {
374                 if (s_info.update == item) {
375                         /*!
376                          * \note
377                          * If already in updating mode,
378                          * reset the monitor_cnt to 1,
379                          * all updated event will be merged into A inotify event
380                          */
381                         DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
382                         item->monitor_cnt = 1;
383                 } else {
384                         item->monitor_cnt++;
385                 }
386         } else {
387                 item->heavy_updating = 1;
388         }
389
390         item->update_interval = now;
391 }
392
393 static inline Eina_List *find_item(struct instance *inst)
394 {
395         Eina_List *l;
396         struct item *item;
397         
398         EINA_LIST_FOREACH(s_info.item_list, l, item) {
399                 if (item->inst == inst)
400                         return l;
401         }
402
403         return NULL;
404 }
405
406 static inline int output_handler(struct item *item)
407 {
408         int invalid = 0;
409
410         item->monitor_cnt--;
411         if (item->monitor_cnt < 0 || item->heavy_updating) {
412                 if (!item->heavy_updating) {
413                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
414                         invalid = 1;
415                 } else {
416                         item->heavy_updating = 0;       /* Reset flag */
417                 }
418
419                 item->monitor_cnt = 0;
420         }
421
422         if (item->monitor_cnt == 0) {
423                 if (!invalid)
424                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
425
426                 if (item->monitor) {
427                         ecore_timer_del(item->monitor);
428                         item->monitor = NULL;
429                 }
430
431                 if (s_info.update == item)
432                         s_info.update = NULL;
433
434                 if (item->deleteme) {
435                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
436                         (void)so_destroy(item->inst);
437                         free(item);
438                         return EXIT_FAILURE;
439                 }
440         }
441
442         return EXIT_SUCCESS;
443 }
444
445 static int desc_updated_cb(const char *filename, void *data, int over)
446 {
447         struct item *item;
448
449         if (over)
450                 WarnPrint("Event Q overflow\n");
451
452         item = data;
453
454         DbgPrint("DESC %s is updated\n", filename);
455         if (item->is_pd_show) {
456                 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
457         } else {
458                 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
459         }
460         return EXIT_SUCCESS;
461 }
462
463 static int file_updated_cb(const char *filename, void *data, int over)
464 {
465         struct item *item;
466         int w;
467         int h;
468         double priority;
469         char *content = NULL;
470         char *title = NULL;
471         int ret;
472
473         if (over)
474                 WarnPrint("Event Q overflow\n");
475
476         item = data;
477
478         ret = util_get_filesize(filename);
479         if (ret <= 0) {
480                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
481                 return EXIT_SUCCESS; /*!< To keep the callback */
482         }
483
484         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
485         if (ret < 0) {
486                 ErrPrint("livebox_get_info returns %d\n", ret);
487                 return EXIT_SUCCESS; /*!< To keep the callback */
488         }
489
490         if (IS_LB_SHOWN(item)) {
491                 provider_send_updated(item->inst->item->pkgname, item->inst->id,
492                                         item->inst->w, item->inst->h, item->inst->priority, content, title);
493         } else {
494                 item->is_lb_updated++;
495         }
496
497         return output_handler(item);
498 }
499
500 static inline int clear_from_pd_open_pending_list(struct item *item)
501 {
502         Eina_List *l;
503         struct item *tmp;
504
505         EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
506                 if (tmp != item)
507                         continue;
508
509                 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
510                 if (!s_info.pd_open_pending_list)
511                         deactivate_pd_open_pending_consumer();
512                 return LB_STATUS_SUCCESS;
513         }
514
515         return LB_STATUS_ERROR_NOT_EXIST;
516 }
517
518 static inline int clear_from_pending_list(struct item *item)
519 {
520         Eina_List *l;
521         struct item *tmp;
522
523         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
524                 if (tmp != item)
525                         continue;
526
527                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
528                 if (!s_info.pending_list)
529                         deactivate_pending_consumer();
530                 return LB_STATUS_SUCCESS;
531         }
532
533         return LB_STATUS_ERROR_NOT_EXIST;
534 }
535
536 static Eina_Bool update_timeout_cb(void *data)
537 {
538         struct item *item;
539
540         item = data;
541
542         ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
543
544         if (s_info.update != item)
545                 ErrPrint("Updating item is not matched\n");
546
547         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
548         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
549         s_info.update = NULL;
550
551         exit(ETIME);
552         return ECORE_CALLBACK_CANCEL;
553 }
554
555 static Eina_Bool updator_cb(void *data)
556 {
557         struct item *item;
558         int ret;
559
560         item = data;
561
562         if (item->monitor) {/*!< If this item is already in update process */
563                 return ECORE_CALLBACK_RENEW;
564         }
565
566         if (!IS_LB_SHOWN(item)) {
567                 DbgPrint("%s is not shown yet. delaying updates\n", item->inst->item->pkgname);
568                 (void)append_pending_list(item);
569                 return ECORE_CALLBACK_RENEW;
570         }
571
572         ret = so_is_updated(item->inst);
573         if (ret <= 0) {
574                 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
575                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
576                         lb_destroy(item->inst->item->pkgname, item->inst->id);
577
578                         ecore_timer_del(item->timer);
579                         item->timer = NULL;
580                         return ECORE_CALLBACK_CANCEL;
581                 }
582
583                 return ECORE_CALLBACK_RENEW;
584         }
585
586         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
587                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
588                 (void)append_pending_list(item);
589                 return ECORE_CALLBACK_RENEW;
590         }
591
592         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
593         if (!item->monitor) {
594                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
595                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
596                 return ECORE_CALLBACK_RENEW;
597         }
598
599         ret = so_update(item->inst);
600         if (ret < 0) {
601                 ecore_timer_del(item->monitor);
602                 item->monitor = NULL;
603                 return ECORE_CALLBACK_RENEW;
604         }
605
606         /*!
607          * \note
608          * Counter of the event monitor is only used for asynchronous content updating,
609          * So reset it to 1 from here because the async updating is started now,
610          * even if it is accumulated by other event function before this.
611          */
612         item->monitor_cnt = 1;
613
614         /*!
615          * \note
616          * While waiting the Callback function call,
617          * Add this for finding the crash
618          */
619         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
620
621         if (ret & NEED_TO_SCHEDULE)
622                 (void)append_pending_list(item);
623
624         if (ret & OUTPUT_UPDATED) {
625                 /*!
626                  * \NOTE 
627                  * In this case, there is potential issue
628                  * 1. User added update CALLBACK -> Inotify event (Only once)
629                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
630                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
631                  *    > Okay. What we want is this.
632                  */
633                 update_monitor_cnt(item);
634         }
635
636         /*
637          * \NOTE
638          * This should be updated after "update_monitor_cnt" function call,
639          * because the update_monitor_cnt function will see the s_info.update variable,
640          */
641         s_info.update = item;
642
643         return ECORE_CALLBACK_RENEW;
644 }
645
646 static inline void update_monitor_del(const char *id, struct item *item)
647 {
648         char *tmp;
649         int len;
650
651         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
652
653         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
654         tmp = malloc(len);
655         if (!tmp) {
656                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
657                 return;
658         }
659
660         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
661         update_monitor_del_update_cb(tmp, desc_updated_cb);
662         free(tmp);
663 }
664
665 static inline int add_desc_update_monitor(const char *id, struct item *item)
666 {
667         char *filename;
668         int len;
669
670         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
671         filename = malloc(len);
672         if (!filename) {
673                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
674                 return LB_STATUS_ERROR_MEMORY;
675         }
676
677         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
678         return update_monitor_add_update_cb(filename, desc_updated_cb, item);
679 }
680
681 static inline int add_file_update_monitor(const char *id, struct item *item)
682 {
683         char *filename;
684
685         filename = strdup(util_uri_to_path(id));
686         if (!filename) {
687                 ErrPrint("Heap: %s (%s)\n", strerror(errno), id);
688                 return LB_STATUS_ERROR_MEMORY;
689         }
690
691         return update_monitor_add_update_cb(filename, file_updated_cb, item);
692 }
693
694 static inline int update_monitor_add(const char *id, struct item *item)
695 {
696         /*!
697          * \NOTE
698          * item->inst is not available yet.
699          */
700         add_file_update_monitor(id, item);
701         add_desc_update_monitor(id, item);
702         return LB_STATUS_SUCCESS;
703 }
704
705 HAPI int lb_init(void)
706 {
707         return LB_STATUS_SUCCESS;
708 }
709
710 HAPI int lb_fini(void)
711 {
712         Eina_List *l;
713         Eina_List *n;
714         struct item *item;
715
716         deactivate_pending_consumer();
717         deactivate_pd_open_pending_consumer();
718
719         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
720         EINA_LIST_FREE(s_info.pending_list, item);
721
722         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
723                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
724                 lb_destroy(item->inst->item->pkgname, item->inst->id);
725         }
726
727         return LB_STATUS_SUCCESS;
728 }
729
730 /*!
731  * \note
732  * Exported API for each liveboxes.
733  */
734 const char *livebox_find_pkgname(const char *filename)
735 {
736         Eina_List *l;
737         struct item *item;
738
739         EINA_LIST_FOREACH(s_info.item_list, l, item) {
740                 if (!strcmp(item->inst->id, filename))
741                         return item->inst->item->pkgname;
742         }
743
744         return NULL;
745 }
746
747 int livebox_request_update_by_id(const char *filename)
748 {
749         Eina_List *l;
750         struct item *item;
751
752         EINA_LIST_FOREACH(s_info.item_list, l, item) {
753                 if (!strcmp(item->inst->id, filename)) {
754                         return append_pending_list(item);
755                 }
756         }
757
758         return LB_STATUS_ERROR_NOT_EXIST;
759 }
760
761 int livebox_trigger_update_monitor(const char *filename, int is_pd)
762 {
763         char *fname;
764         int ret;
765
766         if (is_pd) {
767                 int len;
768                 len = strlen(filename) + strlen(".desc");
769
770                 fname = malloc(len + 1);
771                 if (!fname) {
772                         ErrPrint("Heap: %s\n", strerror(errno));
773                         return LB_STATUS_ERROR_MEMORY;
774                 }
775
776                 snprintf(fname, len, "%s.desc", filename);
777         } else {
778                 fname = strdup(filename);
779                 if (!fname) {
780                         ErrPrint("Heap: %s\n", strerror(errno));
781                         return LB_STATUS_ERROR_MEMORY;
782                 }
783         }
784
785         if (access(fname, R_OK | W_OK) != 0) {
786                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
787                 ret = LB_STATUS_ERROR_IO;
788         } else {
789                 ret = update_monitor_trigger_update_cb(fname, 0);
790         }
791
792         free(fname);
793         return ret;
794 }
795
796 HAPI int lb_open_pd(const char *pkgname)
797 {
798         Eina_List *l;
799         char *tmp;
800
801         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
802                 if (!strcmp(pkgname, tmp))
803                         return 0;
804         }
805
806         tmp = strdup(pkgname);
807         if (!tmp) {
808                 ErrPrint("Heap: %s\n", strerror(errno));
809                 return LB_STATUS_ERROR_MEMORY;
810         }
811
812         if (!s_info.pd_list)
813                 pending_timer_freeze();
814
815         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
816
817         /*!
818          * Find all instances from the pending list.
819          * Move them to pd_open_pending_timer
820          */
821         migrate_to_pd_open_pending_list(pkgname);
822         return LB_STATUS_SUCCESS;
823 }
824
825 HAPI int lb_close_pd(const char *pkgname)
826 {
827         Eina_List *l;
828         Eina_List *n;
829         char *tmp;
830
831         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
832                 if (strcmp(tmp, pkgname))
833                         continue;
834
835                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
836                 free(tmp);
837
838                 if (!s_info.pd_list)
839                         pending_timer_thaw();
840
841                 /*!
842                  * Move all items in pd_open_pending_list
843                  * to pending_list.
844                  */
845                 migrate_to_pending_list(pkgname);
846                 return LB_STATUS_SUCCESS;
847         }
848
849         return LB_STATUS_ERROR_NOT_EXIST;
850 }
851
852 HAPI int lb_create(const char *pkgname, const char *id, const char *content_info, int timeout, int has_livebox_script, double period, const char *cluster, const char *category, int *w, int *h, double *priority, int skip_need_to_create, const char *abi, char **out_content, char **out_title)
853 {
854         struct instance *inst;
855         struct item *item;
856         int ret;
857         int create_ret;
858         int need_to_create;
859
860         need_to_create = 0;
861         *out_content = NULL;
862         *out_title = NULL;
863
864         inst = so_find_instance(pkgname, id);
865         if (inst) {
866                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
867                 return LB_STATUS_SUCCESS;
868         }
869
870         if (!skip_need_to_create) {
871                 ret = so_create_needed(pkgname, cluster, category, abi);
872                 if (ret != NEED_TO_CREATE)
873                         return LB_STATUS_ERROR_PERMISSION;
874
875                 need_to_create = 1;
876         }
877
878         item = calloc(1, sizeof(*item));
879         if (!item) {
880                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
881                 return LB_STATUS_ERROR_MEMORY;
882         }
883
884         ret = update_monitor_add(id, item);
885         if (ret < 0) {
886                 free(item);
887                 return ret;
888         }
889
890         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
891         if (create_ret < 0) {
892                 update_monitor_del(id,  item);
893                 free(item);
894
895                 *w = 0;
896                 *h = 0;
897                 *priority = 0.0f;
898                 return create_ret;
899         }
900
901         item->inst = inst;
902
903         if (period > 0.0f && !s_info.secured) {
904                 item->timer = util_timer_add(period, updator_cb, item);
905                 if (!item->timer) {
906                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
907                         update_monitor_del(id, item);
908                         (void)so_destroy(inst);
909                         free(item);
910                         return LB_STATUS_ERROR_FAULT;
911                 }
912
913                 if (s_info.paused)
914                         timer_freeze(item);
915         } else {
916                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
917                 item->timer = NULL;
918         }
919
920         s_info.item_list = eina_list_append(s_info.item_list, item);
921
922         if (create_ret & NEED_TO_SCHEDULE) {
923                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
924                 (void)append_pending_list(item);
925         }
926
927         if (create_ret & OUTPUT_UPDATED) {
928                 update_monitor_cnt(item);
929                 /*!
930                  * \note
931                  * To send a output info, get the info forcely.
932                  * but the output file monitor will do this again
933                  *
934                  * This function will set the tmp_content and tmp_title
935                  * even if it has no updates on the content, title,
936                  * it will set them to NULL.
937                  */
938                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
939                         if (*out_content) {
940                                 char *tmp;
941
942                                 tmp = strdup(*out_content);
943                                 if (!tmp)
944                                         ErrPrint("Memory: %s\n", strerror(errno));
945
946                                 *out_content = tmp;
947                         }
948
949                         if (*out_title) {
950                                 char *tmp;
951
952                                 tmp = strdup(*out_title);
953                                 if (!tmp)
954                                         ErrPrint("Memory: %s\n", strerror(errno));
955
956                                 *out_title = tmp;
957                         }
958                 }
959         }
960
961         *w = inst->w;
962         *h = inst->h;
963         *priority = inst->priority;
964         return need_to_create;
965 }
966
967 HAPI int lb_destroy(const char *pkgname, const char *id)
968 {
969         Eina_List *l;
970         struct instance *inst;
971         struct item *item;
972
973         inst = so_find_instance(pkgname, id);
974         if (!inst) {
975                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
976                 return LB_STATUS_ERROR_INVALID;
977         }
978
979         l = find_item(inst);
980         if (!l) {
981                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
982                 return LB_STATUS_ERROR_NOT_EXIST;
983         }
984
985         item = eina_list_data_get(l);
986         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
987
988         if (s_info.update == item)
989                 s_info.update = NULL;
990
991         if (item->timer) {
992                 clear_from_pd_open_pending_list(item);
993                 clear_from_pending_list(item);
994                 ecore_timer_del(item->timer);
995                 item->timer = NULL;
996
997                 if (item->monitor)
998                         item->deleteme = 1;
999                 else
1000                         update_monitor_del(id, item);
1001         }
1002
1003         if (!item->monitor) {
1004                 free(item);
1005                 (void)so_destroy(inst);
1006         }
1007
1008         return LB_STATUS_SUCCESS;
1009 }
1010
1011 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1012 {
1013         Eina_List *l;
1014         struct instance *inst;
1015         struct item *item;
1016         int ret;
1017
1018         inst = so_find_instance(pkgname, id);
1019         if (!inst) {
1020                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1021                 return LB_STATUS_ERROR_INVALID;
1022         }
1023
1024         l = find_item(inst);
1025         if (!l) {
1026                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1027                 return LB_STATUS_ERROR_NOT_EXIST;
1028         }
1029
1030         item = eina_list_data_get(l);
1031
1032         ret = so_resize(inst, w, h);
1033         if (ret < 0)
1034                 return ret;
1035
1036         if (ret & NEED_TO_SCHEDULE) {
1037                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1038                 (void)append_pending_list(item);
1039         }
1040
1041         if (ret & OUTPUT_UPDATED)
1042                 update_monitor_cnt(item);
1043
1044         return LB_STATUS_SUCCESS;
1045 }
1046
1047 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1048 {
1049         struct instance *inst;
1050         char *ret;
1051
1052         inst = so_find_instance(pkgname, id);
1053         if (!inst) {
1054                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1055                 return NULL;
1056         }
1057
1058         ret = so_pinup(inst, pinup);
1059         return ret;
1060 }
1061
1062 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1063 {
1064         Eina_List *l;
1065         struct instance *inst;
1066         struct item *item;
1067
1068         inst = so_find_instance(pkgname, id);
1069         if (!inst) {
1070                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1071                 return LB_STATUS_ERROR_INVALID;
1072         }
1073
1074         l = find_item(inst);
1075         if (!l) {
1076                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1077                 return LB_STATUS_ERROR_NOT_EXIST;
1078         }
1079
1080         item = eina_list_data_get(l);
1081
1082         if (period <= 0.0f) {
1083                 if (item->timer) {
1084                         ecore_timer_del(item->timer);
1085                         item->timer = NULL;
1086                 }
1087         } else {
1088                 if (item->timer) {
1089                         util_timer_interval_set(item->timer, period);
1090                 } else if (!s_info.secured) {
1091                         item->timer = util_timer_add(period, updator_cb, item);
1092                         if (!item->timer) {
1093                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1094                                 return LB_STATUS_ERROR_FAULT;
1095                         }
1096
1097                         if (s_info.paused)
1098                                 timer_freeze(item);
1099                 }
1100         }
1101
1102         return LB_STATUS_SUCCESS;
1103 }
1104
1105 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1106 {
1107         Eina_List *l;
1108         struct instance *inst;
1109         struct item *item;
1110         int ret;
1111
1112         inst = so_find_instance(pkgname, id);
1113         if (!inst) {
1114                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1115                 return LB_STATUS_ERROR_INVALID;
1116         }
1117
1118         l = find_item(inst);
1119         if (!l) {
1120                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1121                 return LB_STATUS_ERROR_NOT_EXIST;
1122         }
1123
1124         item = eina_list_data_get(l);
1125
1126         ret = so_clicked(inst, event, timestamp, x, y);
1127         if (ret < 0)
1128                 return ret;
1129
1130         if (ret & NEED_TO_SCHEDULE) {
1131                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1132                 (void)append_pending_list(item);
1133         }
1134
1135         if (ret & OUTPUT_UPDATED)
1136                 update_monitor_cnt(item);
1137
1138         return LB_STATUS_SUCCESS;
1139 }
1140
1141 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1142 {
1143         Eina_List *l;
1144         struct instance *inst;
1145         struct item *item;
1146         int ret;
1147
1148         inst = so_find_instance(pkgname, id);
1149         if (!inst) {
1150                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1151                 return LB_STATUS_ERROR_INVALID;
1152         }
1153
1154         l = find_item(inst);
1155         if (!l) {
1156                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1157                 return LB_STATUS_ERROR_NOT_EXIST;
1158         }
1159
1160         item = eina_list_data_get(l);
1161
1162         if (emission && source && !strcmp(source, id)) {
1163                 if (item->inst->item->has_livebox_script) {
1164                         if (!strcmp(emission, "lb,show")) {
1165                                 item->is_lb_show = 1;
1166
1167                                 DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n", id, item->is_lb_updated, item->inst->content, item->inst->title);
1168                                 if (item->is_lb_updated) {
1169                                         provider_send_updated(item->inst->item->pkgname, item->inst->id,
1170                                                                 item->inst->w, item->inst->h, item->inst->priority, item->inst->content, item->inst->title);
1171                                         item->is_lb_updated = 0;
1172                                 }
1173
1174                                 source = util_uri_to_path(source);
1175                         } else if (!strcmp(emission, "lb,hide")) {
1176                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1177                                 item->is_lb_show = 0;
1178
1179                                 source = util_uri_to_path(source);
1180                         }
1181                 }
1182
1183                 if (!strcmp(emission, "pd,show")) {
1184                         item->is_pd_show = 1;
1185                         source = util_uri_to_path(source);
1186                 } else if (!strcmp(emission, "pd,hide")) {
1187                         item->is_pd_show = 0;
1188                         source = util_uri_to_path(source);
1189                 }
1190         }
1191
1192         ret = so_script_event(inst, emission, source, event_info);
1193         if (ret < 0)
1194                 return ret;
1195
1196         if (ret & NEED_TO_SCHEDULE) {
1197                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1198                 (void)append_pending_list(item);
1199         }
1200
1201         if (ret & OUTPUT_UPDATED)
1202                 update_monitor_cnt(item);
1203
1204         return LB_STATUS_SUCCESS;
1205 }
1206
1207 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1208 {
1209         Eina_List *l;
1210         struct instance *inst;
1211         struct item *item;
1212
1213         inst = so_find_instance(pkgname, id);
1214         if (!inst) {
1215                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1216                 return LB_STATUS_ERROR_INVALID;
1217         }
1218
1219         l = find_item(inst);
1220         if (!l) {
1221                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1222                 return LB_STATUS_ERROR_NOT_EXIST;
1223         }
1224
1225         item = eina_list_data_get(l);
1226         if (!item) {
1227                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1228                 return LB_STATUS_ERROR_FAULT;
1229         }
1230         /*!
1231          * NOTE:
1232          * item is not used.
1233          * Maybe this is not neccessary for this operation
1234          */
1235         return so_is_pinned_up(inst);
1236 }
1237
1238 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1239 {
1240         Eina_List *l;
1241         struct instance *inst;
1242         struct item *item;
1243         int ret;
1244
1245         inst = so_find_instance(pkgname, id);
1246         if (!inst) {
1247                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1248                 return LB_STATUS_ERROR_INVALID;
1249         }
1250
1251         l = find_item(inst);
1252         if (!l) {
1253                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1254                 return LB_STATUS_ERROR_NOT_EXIST;
1255         }
1256
1257         item = eina_list_data_get(l);
1258
1259         ret = so_change_group(inst, cluster, category);
1260         if (ret < 0)
1261                 return ret;
1262
1263         if (ret & NEED_TO_SCHEDULE) {
1264                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1265                 (void)append_pending_list(item);
1266         }
1267
1268         if (ret & OUTPUT_UPDATED)
1269                 update_monitor_cnt(item);
1270
1271         return LB_STATUS_SUCCESS;
1272 }
1273
1274 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1275 {
1276         int ret;
1277
1278         ret = so_sys_event(inst, event);
1279         if (ret < 0)
1280                 return ret;
1281
1282         if (ret & NEED_TO_SCHEDULE)
1283                 (void)append_pending_list(item);
1284
1285         if (ret & OUTPUT_UPDATED)
1286                 update_monitor_cnt(item);
1287
1288         return LB_STATUS_SUCCESS;
1289 }
1290
1291 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1292 {
1293         Eina_List *l;
1294         struct instance *inst;
1295         struct item *item;
1296
1297         inst = so_find_instance(pkgname, id);
1298         if (!inst) {
1299                 ErrPrint("instance %s - %s is not created\n");
1300                 return LB_STATUS_ERROR_INVALID;
1301         }
1302
1303         l = find_item(inst);
1304         if (!l) {
1305                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1306                 return LB_STATUS_ERROR_NOT_EXIST;
1307         }
1308
1309         item = eina_list_data_get(l);
1310         return lb_sys_event(inst, item, event);
1311 }
1312
1313 HAPI int lb_update(const char *pkgname, const char *id)
1314 {
1315         Eina_List *l;
1316         struct instance *inst;
1317         struct item *item;
1318
1319         inst = so_find_instance(pkgname, id);
1320         if (!inst) {
1321                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1322                 return LB_STATUS_ERROR_INVALID;
1323         }
1324
1325         l = find_item(inst);
1326         if (!l) {
1327                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1328                 return LB_STATUS_ERROR_NOT_EXIST;
1329         }
1330
1331         item = eina_list_data_get(l);
1332         (void)append_pending_list(item);
1333         return LB_STATUS_SUCCESS;
1334 }
1335
1336 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1337 {
1338         Eina_List *l;
1339         Eina_List *n;
1340         struct item *item;
1341
1342         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1343         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1344                 if (item->deleteme)
1345                         continue;
1346
1347                 if (cluster && strcasecmp(item->inst->cluster, cluster))
1348                         continue;
1349
1350                 if (category && strcasecmp(item->inst->category, category))
1351                         continue;
1352
1353                 if (pkgname && strlen(pkgname)) {
1354                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1355                                 (void)append_pending_list(item);
1356                         }
1357                 } else {
1358                         (void)append_pending_list(item);
1359                 }
1360         }
1361
1362         return LB_STATUS_SUCCESS;
1363 }
1364
1365 HAPI int lb_delete_all_deleteme(void)
1366 {
1367         Eina_List *l;
1368         Eina_List *n;
1369         struct item *item;
1370         int cnt = 0;
1371
1372         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1373                 if (!item->deleteme)
1374                         continue;
1375
1376                 s_info.item_list = eina_list_remove(s_info.item_list, item);
1377
1378                 update_monitor_del(item->inst->id, item);
1379                 (void)so_destroy(item->inst);
1380                 free(item);
1381                 cnt++;
1382         }
1383
1384         DbgPrint("Delete all deleteme: %d\n", cnt);
1385         return LB_STATUS_SUCCESS;
1386 }
1387
1388 HAPI int lb_system_event_all(int event)
1389 {
1390         Eina_List *l;
1391         Eina_List *n;
1392         struct item *item;
1393
1394         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1395                 if (item->deleteme)
1396                         continue;
1397
1398                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1399                 lb_sys_event(item->inst, item, event);
1400         }
1401
1402         return LB_STATUS_SUCCESS;
1403 }
1404
1405 HAPI void lb_pause_all(void)
1406 {
1407         Eina_List *l;
1408         struct item *item;
1409
1410         s_info.paused = 1;
1411
1412         pending_timer_freeze();
1413
1414         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1415                 if (item->deleteme) {
1416                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1417                         continue;
1418                 }
1419
1420                 if (item->is_paused)
1421                         continue;
1422
1423                 timer_freeze(item);
1424
1425                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1426         }
1427 }
1428
1429 HAPI void lb_resume_all(void)
1430 {
1431         Eina_List *l;
1432         struct item *item;
1433
1434         s_info.paused = 0;
1435
1436         pending_timer_thaw();
1437
1438         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1439                 if (item->deleteme) {
1440                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1441                         continue;
1442                 }
1443
1444                 if (item->is_paused)
1445                         continue;
1446
1447                 timer_thaw(item);
1448
1449                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1450         }
1451 }
1452
1453 HAPI int lb_pause(const char *pkgname, const char *id)
1454 {
1455         struct instance *inst;
1456         Eina_List *l;
1457         struct item *item;
1458
1459         inst = so_find_instance(pkgname, id);
1460         if (!inst)
1461                 return LB_STATUS_ERROR_INVALID;
1462
1463         l = find_item(inst);
1464         if (!l) {
1465                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1466                 return LB_STATUS_ERROR_NOT_EXIST;
1467         }
1468
1469         item = eina_list_data_get(l);
1470         if (!item)
1471                 return LB_STATUS_ERROR_FAULT;
1472
1473         if (item->deleteme) {
1474                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1475                 return LB_STATUS_ERROR_BUSY;
1476         }
1477
1478         item->is_paused = 1;
1479
1480         if (s_info.paused)
1481                 return LB_STATUS_SUCCESS;
1482
1483         timer_freeze(item);
1484
1485         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1486
1487         return LB_STATUS_SUCCESS;
1488 }
1489
1490 HAPI int lb_resume(const char *pkgname, const char *id)
1491 {
1492         struct instance *inst;
1493         Eina_List *l;
1494         struct item *item;
1495
1496         inst = so_find_instance(pkgname, id);
1497         if (!inst)
1498                 return LB_STATUS_ERROR_INVALID;
1499
1500         l = find_item(inst);
1501         if (!l) {
1502                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1503                 return LB_STATUS_ERROR_NOT_EXIST;
1504         }
1505
1506         item = eina_list_data_get(l);
1507         if (!item)
1508                 return LB_STATUS_ERROR_FAULT;
1509
1510         if (item->deleteme) {
1511                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1512                 return LB_STATUS_ERROR_BUSY;
1513         }
1514
1515         item->is_paused = 0;
1516
1517         if (s_info.paused)
1518                 return LB_STATUS_SUCCESS;
1519
1520         timer_thaw(item);
1521
1522         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1523         return LB_STATUS_SUCCESS;
1524 }
1525
1526 HAPI void lb_turn_secured_on(void)
1527 {
1528         s_info.secured = 1;
1529 }
1530
1531 HAPI int lb_is_all_paused(void)
1532 {
1533         return s_info.paused;
1534 }
1535
1536 /* End of a file */