2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
18 #include <stdlib.h> /* exit */
20 #include <unistd.h> /* access */
28 #include <livebox-errno.h>
30 #include "critical_log.h"
33 #include "so_handler.h"
35 #include "update_monitor.h"
39 #define IS_LB_SHOWN(itm) (!(itm)->inst->item->has_livebox_script || ((itm)->inst->item->has_livebox_script && (itm)->is_lb_show))
43 #define UPDATE_ITEM_DELETED (-1)
44 #define UPDATE_INVOKED (-2)
45 #define UPDATE_NOT_INVOKED (0)
49 struct instance *inst;
53 double update_interval;
54 int heavy_updating; /* Only for debugging message */
55 int is_paused; /* 1 is paused, 0 is resumed */
58 unsigned int updated_in_pause;
68 Eina_List *pending_list;
69 Ecore_Timer *pending_timer;
70 Eina_List *pd_open_pending_list;
71 Ecore_Timer *pd_open_pending_timer;
75 int pending_timer_freezed;
80 .pending_timer = NULL,
81 .pd_open_pending_list = NULL,
82 .pd_open_pending_timer = NULL,
86 .pending_timer_freezed = 0,
89 static Eina_Bool updator_cb(void *data);
91 static void pending_timer_freeze(void)
93 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
94 if (s_info.pending_timer && !s_info.pending_timer_freezed) {
95 DbgPrint("Freeze the pending timer\n");
96 ecore_timer_freeze(s_info.pending_timer);
99 s_info.pending_timer_freezed++;
102 static void pending_timer_thaw(void)
104 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
105 if (!s_info.pending_timer_freezed)
108 s_info.pending_timer_freezed--;
109 if (s_info.pending_timer && !s_info.pending_timer_freezed) {
110 DbgPrint("Thaw the pending timer\n");
111 ecore_timer_thaw(s_info.pending_timer);
116 * -1 : PD is opened, but not mine
117 * 0 : PD is not opened
118 * 1 : my PD is opened
120 static inline int pd_is_opened(const char *pkgname)
127 EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
128 if (pkgname && !strcmp(pkgname, tmp))
134 return i > 0 ? -1 : 0;
137 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
141 item = eina_list_nth(s_info.pd_open_pending_list, 0);
146 return ECORE_CALLBACK_RENEW;
148 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
151 * To prevent from checking the is_updated function
153 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
154 /* Item is destroyed */
157 if (s_info.pd_open_pending_list)
158 return ECORE_CALLBACK_RENEW;
161 s_info.pd_open_pending_timer = NULL;
162 return ECORE_CALLBACK_CANCEL;
165 static Eina_Bool pended_cmd_consumer_cb(void *data)
169 item = eina_list_nth(s_info.pending_list, 0);
173 if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0)
174 return ECORE_CALLBACK_RENEW;
176 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
179 * To prevent from checking the is_updated function
181 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
182 /* item is destroyed */
185 if (s_info.pending_list)
186 return ECORE_CALLBACK_RENEW;
189 s_info.pending_timer = NULL;
190 s_info.pending_timer_freezed = 0;
191 return ECORE_CALLBACK_CANCEL;
194 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
196 if (s_info.pending_timer)
199 s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
200 if (!s_info.pending_timer) {
201 ErrPrint("Failed to add a new pended command consumer\n");
202 return LB_STATUS_ERROR_FAULT;
206 * Do not increase the freezed counter.
207 * Just freeze the timer.
209 if (s_info.pending_timer_freezed)
210 ecore_timer_freeze(s_info.pending_timer);
215 static inline void deactivate_pending_consumer(void)
217 if (!s_info.pending_timer)
220 ecore_timer_del(s_info.pending_timer);
221 s_info.pending_timer = NULL;
222 s_info.pending_timer_freezed = 0;
225 static inline void deactivate_pd_open_pending_consumer(void)
227 if (!s_info.pd_open_pending_timer)
230 ecore_timer_del(s_info.pd_open_pending_timer);
231 s_info.pd_open_pending_timer = NULL;
234 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
236 if (s_info.pd_open_pending_timer)
239 s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
240 if (!s_info.pd_open_pending_timer) {
241 ErrPrint("Failed to add a new pended command consumer\n");
242 return LB_STATUS_ERROR_FAULT;
248 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
255 EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
256 if (strcmp(pkgname, item->inst->item->pkgname))
259 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
260 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
264 if (s_info.pd_open_pending_list)
265 activate_pd_open_pending_consumer();
267 if (!s_info.pending_list)
268 deactivate_pending_consumer();
271 static inline void migrate_to_pending_list(const char *pkgname)
278 EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
279 if (strcmp(pkgname, item->inst->item->pkgname))
282 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
283 s_info.pending_list = eina_list_append(s_info.pending_list, item);
287 if (s_info.pending_list)
288 activate_pending_consumer();
290 if (!s_info.pd_open_pending_list)
291 deactivate_pd_open_pending_consumer();
294 static inline int is_pended_item(struct item *item)
296 struct item *in_item;
297 if (pd_is_opened(item->inst->item->pkgname) == 1) {
298 in_item = eina_list_data_find(s_info.pd_open_pending_list, item);
300 in_item = eina_list_data_find(s_info.pending_list, item);
303 return (in_item == item);
306 static int append_pending_list(struct item *item)
308 if (pd_is_opened(item->inst->item->pkgname) == 1) {
309 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
310 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
311 return LB_STATUS_ERROR_EXIST;
314 if (activate_pd_open_pending_consumer() < 0) {
315 ErrPrint("Failed to activate PD open pending consumer\n");
316 return LB_STATUS_ERROR_FAULT;
319 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
321 if (eina_list_data_find(s_info.pending_list, item) == item) {
322 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
323 return LB_STATUS_ERROR_EXIST;
326 if (activate_pending_consumer() < 0)
327 return LB_STATUS_ERROR_FAULT;
329 s_info.pending_list = eina_list_append(s_info.pending_list, item);
336 * This function can call the update callback
337 * return 0 if there is no changes
338 * return -1 the item is deleted
340 static inline int timer_thaw(struct item *item)
350 ecore_timer_thaw(item->timer);
351 period = ecore_timer_interval_get(item->timer);
352 pending = ecore_timer_pending_get(item->timer);
353 delay = util_time_delay_for_compensation(period) - pending;
354 ecore_timer_delay(item->timer, delay);
356 if (item->sleep_at == 0.0f)
359 sleep_time = util_timestamp() - item->sleep_at;
360 item->sleep_at = 0.0f;
362 if (sleep_time > pending) {
363 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
364 /* item is destroyed */
365 return UPDATE_ITEM_DELETED;
367 return UPDATE_INVOKED;
371 return UPDATE_NOT_INVOKED;
374 static inline void timer_freeze(struct item *item)
381 ecore_timer_freeze(item->timer);
383 if (ecore_timer_interval_get(item->timer) <= 1.0f)
386 if (gettimeofday(&tv, NULL) < 0) {
387 ErrPrint("gettimeofday: %s\n", strerror(errno));
392 item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
395 static inline void update_monitor_cnt(struct item *item)
400 now = util_timestamp();
401 interval = now - item->update_interval;
405 * If the content update is processed in too short time,
406 * don't increase the monitor counter, instead of it
407 * set the heavy updating flag.
408 * And handling this heavy updating from the
409 * file update callback.
411 if (interval >= MINIMUM_UPDATE_INTERVAL) {
412 if (s_info.update == item) {
415 * If already in updating mode,
416 * reset the monitor_cnt to 1,
417 * all updated event will be merged into A inotify event
419 DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
420 item->monitor_cnt = 1;
425 item->heavy_updating = 1;
428 item->update_interval = now;
431 static inline Eina_List *find_item(struct instance *inst)
436 EINA_LIST_FOREACH(s_info.item_list, l, item) {
437 if (item->inst == inst)
444 static inline int output_handler(struct item *item)
449 if (item->monitor_cnt < 0 || item->heavy_updating) {
450 if (!item->heavy_updating) {
451 WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
454 item->heavy_updating = 0; /* Reset flag */
457 item->monitor_cnt = 0;
460 if (item->monitor_cnt == 0) {
462 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
465 ecore_timer_del(item->monitor);
466 item->monitor = NULL;
469 if (s_info.update == item)
470 s_info.update = NULL;
472 if (item->deleteme) {
473 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
474 (void)so_destroy(item->inst);
483 static int desc_updated_cb(const char *filename, void *data, int over)
488 WarnPrint("Event Q overflow\n");
492 DbgPrint("DESC %s is updated\n", filename);
493 if (item->is_pd_show) {
494 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
496 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
501 static int file_updated_cb(const char *filename, void *data, int over)
507 char *content = NULL;
512 WarnPrint("Event Q overflow\n");
516 ret = util_get_filesize(filename);
518 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
519 return EXIT_SUCCESS; /*!< To keep the callback */
522 ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
524 ErrPrint("livebox_get_info returns %d\n", ret);
525 return EXIT_SUCCESS; /*!< To keep the callback */
528 if (IS_LB_SHOWN(item)) {
529 provider_send_updated(item->inst->item->pkgname, item->inst->id,
530 item->inst->w, item->inst->h, item->inst->priority,
533 item->is_lb_updated++;
536 return output_handler(item);
539 static void reset_lb_updated_flag(struct item *item)
541 if (!item->is_lb_updated)
544 DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
545 item->inst->id, item->is_lb_updated,
546 item->inst->content, item->inst->title);
548 provider_send_updated(item->inst->item->pkgname, item->inst->id,
549 item->inst->w, item->inst->h, item->inst->priority,
550 item->inst->content, item->inst->title);
552 item->is_lb_updated = 0;
555 static inline int clear_from_pd_open_pending_list(struct item *item)
560 EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
564 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
565 if (!s_info.pd_open_pending_list)
566 deactivate_pd_open_pending_consumer();
567 return LB_STATUS_SUCCESS;
570 return LB_STATUS_ERROR_NOT_EXIST;
573 static inline int clear_from_pending_list(struct item *item)
578 EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
582 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
583 if (!s_info.pending_list)
584 deactivate_pending_consumer();
585 return LB_STATUS_SUCCESS;
588 return LB_STATUS_ERROR_NOT_EXIST;
591 static Eina_Bool update_timeout_cb(void *data)
597 ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
599 if (s_info.update != item)
600 ErrPrint("Updating item is not matched\n");
602 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
603 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
604 s_info.update = NULL;
607 return ECORE_CALLBACK_CANCEL;
612 * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
613 * So every caller, should manage the deleted item correctly.
615 static Eina_Bool updator_cb(void *data)
622 if (item->monitor) {/*!< If this item is already in update process */
623 return ECORE_CALLBACK_RENEW;
626 if (!IS_LB_SHOWN(item)) {
627 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
628 (void)append_pending_list(item);
629 return ECORE_CALLBACK_RENEW;
632 if (item->is_paused) {
633 item->updated_in_pause++;
634 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
635 return ECORE_CALLBACK_RENEW;
638 item->updated_in_pause = 0;
640 ret = so_is_updated(item->inst);
642 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
643 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
644 lb_destroy(item->inst->item->pkgname, item->inst->id);
647 * Every caller of this, must not access the item from now.
649 return ECORE_CALLBACK_CANCEL;
652 reset_lb_updated_flag(item);
653 return ECORE_CALLBACK_RENEW;
656 if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
657 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
658 (void)append_pending_list(item);
659 return ECORE_CALLBACK_RENEW;
662 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
663 if (!item->monitor) {
664 ErrPrint("Failed to add update monitor %s(%s):%d\n",
665 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
666 return ECORE_CALLBACK_RENEW;
669 ret = so_update(item->inst);
671 ecore_timer_del(item->monitor);
672 item->monitor = NULL;
673 reset_lb_updated_flag(item);
674 return ECORE_CALLBACK_RENEW;
679 * Counter of the event monitor is only used for asynchronous content updating,
680 * So reset it to 1 from here because the async updating is started now,
681 * even if it is accumulated by other event function before this.
683 item->monitor_cnt = 1;
687 * While waiting the Callback function call,
688 * Add this for finding the crash
690 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
692 if (ret & NEED_TO_SCHEDULE)
693 (void)append_pending_list(item);
695 if (ret & OUTPUT_UPDATED) {
698 * In this case, there is potential issue
699 * 1. User added update CALLBACK -> Inotify event (Only once)
700 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
701 * 2. Inotify event -> User added update CALLBACK -> Inotify event
702 * > Okay. What we want is this.
704 update_monitor_cnt(item);
709 * This should be updated after "update_monitor_cnt" function call,
710 * because the update_monitor_cnt function will see the s_info.update variable,
712 s_info.update = item;
714 return ECORE_CALLBACK_RENEW;
717 static inline void update_monitor_del(const char *id, struct item *item)
722 update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
724 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
727 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
731 snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
732 update_monitor_del_update_cb(tmp, desc_updated_cb);
736 static inline int add_desc_update_monitor(const char *id, struct item *item)
742 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
743 filename = malloc(len);
745 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
746 return LB_STATUS_ERROR_MEMORY;
749 snprintf(filename, len, "%s.desc", util_uri_to_path(id));
750 ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
755 static inline int add_file_update_monitor(const char *id, struct item *item)
757 return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
760 static inline int update_monitor_add(const char *id, struct item *item)
764 * item->inst is not available yet.
766 add_file_update_monitor(id, item);
767 add_desc_update_monitor(id, item);
768 return LB_STATUS_SUCCESS;
771 HAPI int lb_init(void)
773 return LB_STATUS_SUCCESS;
776 HAPI int lb_fini(void)
782 deactivate_pending_consumer();
783 deactivate_pd_open_pending_consumer();
785 EINA_LIST_FREE(s_info.pd_open_pending_list, item);
786 EINA_LIST_FREE(s_info.pending_list, item);
788 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
789 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
790 lb_destroy(item->inst->item->pkgname, item->inst->id);
793 return LB_STATUS_SUCCESS;
798 * Exported API for each liveboxes.
800 const char *livebox_find_pkgname(const char *filename)
805 EINA_LIST_FOREACH(s_info.item_list, l, item) {
806 if (!strcmp(item->inst->id, filename))
807 return item->inst->item->pkgname;
813 int livebox_request_update_by_id(const char *filename)
818 if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
819 ErrPrint("Current operation: %d\n", so_current_op());
820 return LB_STATUS_ERROR_INVALID;
823 EINA_LIST_FOREACH(s_info.item_list, l, item) {
824 if (!strcmp(item->inst->id, filename)) {
825 return append_pending_list(item);
829 return LB_STATUS_ERROR_NOT_EXIST;
832 int livebox_trigger_update_monitor(const char *filename, int is_pd)
837 if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
838 ErrPrint("Current operation: %d\n", so_current_op());
839 return LB_STATUS_ERROR_INVALID;
844 len = strlen(filename) + strlen(".desc");
846 fname = malloc(len + 1);
848 ErrPrint("Heap: %s\n", strerror(errno));
849 return LB_STATUS_ERROR_MEMORY;
852 snprintf(fname, len, "%s.desc", filename);
854 fname = strdup(filename);
856 ErrPrint("Heap: %s\n", strerror(errno));
857 return LB_STATUS_ERROR_MEMORY;
861 if (access(fname, R_OK | W_OK) != 0) {
862 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
863 ret = LB_STATUS_ERROR_IO;
865 ret = update_monitor_trigger_update_cb(fname, 0);
872 HAPI int lb_open_pd(const char *pkgname)
877 EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
878 if (!strcmp(pkgname, tmp))
882 tmp = strdup(pkgname);
884 ErrPrint("Heap: %s\n", strerror(errno));
885 return LB_STATUS_ERROR_MEMORY;
889 pending_timer_freeze();
891 s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
894 * Find all instances from the pending list.
895 * Move them to pd_open_pending_timer
897 migrate_to_pd_open_pending_list(pkgname);
898 return LB_STATUS_SUCCESS;
901 HAPI int lb_close_pd(const char *pkgname)
907 EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
908 if (strcmp(tmp, pkgname))
911 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
915 pending_timer_thaw();
918 * Move all items in pd_open_pending_list
921 migrate_to_pending_list(pkgname);
922 return LB_STATUS_SUCCESS;
925 return LB_STATUS_ERROR_NOT_EXIST;
928 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)
930 struct instance *inst;
940 inst = so_find_instance(pkgname, id);
942 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
943 return LB_STATUS_SUCCESS;
946 if (!skip_need_to_create) {
947 ret = so_create_needed(pkgname, cluster, category, abi);
948 if (ret != NEED_TO_CREATE)
949 return LB_STATUS_ERROR_PERMISSION;
954 item = calloc(1, sizeof(*item));
956 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
957 return LB_STATUS_ERROR_MEMORY;
960 ret = update_monitor_add(id, item);
966 create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
967 if (create_ret < 0) {
968 update_monitor_del(id, item);
979 if (period > 0.0f && !s_info.secured) {
980 item->timer = util_timer_add(period, updator_cb, item);
982 ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
983 update_monitor_del(id, item);
984 (void)so_destroy(inst);
986 return LB_STATUS_ERROR_FAULT;
992 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
996 s_info.item_list = eina_list_append(s_info.item_list, item);
998 if (create_ret & NEED_TO_SCHEDULE) {
999 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1000 (void)append_pending_list(item);
1003 if (create_ret & OUTPUT_UPDATED) {
1004 update_monitor_cnt(item);
1007 * To send a output info, get the info forcely.
1008 * but the output file monitor will do this again
1010 * This function will set the tmp_content and tmp_title
1011 * even if it has no updates on the content, title,
1012 * it will set them to NULL.
1014 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
1018 tmp = strdup(*out_content);
1020 ErrPrint("Memory: %s\n", strerror(errno));
1028 tmp = strdup(*out_title);
1030 ErrPrint("Memory: %s\n", strerror(errno));
1039 *priority = inst->priority;
1040 return need_to_create;
1043 HAPI int lb_destroy(const char *pkgname, const char *id)
1046 struct instance *inst;
1049 inst = so_find_instance(pkgname, id);
1051 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1052 return LB_STATUS_ERROR_INVALID;
1055 l = find_item(inst);
1057 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1058 return LB_STATUS_ERROR_NOT_EXIST;
1061 item = eina_list_data_get(l);
1062 s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1064 if (s_info.update == item)
1065 s_info.update = NULL;
1068 clear_from_pd_open_pending_list(item);
1069 clear_from_pending_list(item);
1070 ecore_timer_del(item->timer);
1076 update_monitor_del(id, item);
1079 if (!item->monitor) {
1081 (void)so_destroy(inst);
1084 return LB_STATUS_SUCCESS;
1087 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1090 struct instance *inst;
1094 inst = so_find_instance(pkgname, id);
1096 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1097 return LB_STATUS_ERROR_INVALID;
1100 l = find_item(inst);
1102 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1103 return LB_STATUS_ERROR_NOT_EXIST;
1106 item = eina_list_data_get(l);
1108 ret = so_resize(inst, w, h);
1112 if (ret & NEED_TO_SCHEDULE) {
1113 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1114 (void)append_pending_list(item);
1117 if (ret & OUTPUT_UPDATED)
1118 update_monitor_cnt(item);
1120 return LB_STATUS_SUCCESS;
1123 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1125 struct instance *inst;
1128 inst = so_find_instance(pkgname, id);
1130 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1134 ret = so_pinup(inst, pinup);
1138 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1141 struct instance *inst;
1144 inst = so_find_instance(pkgname, id);
1146 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1147 return LB_STATUS_ERROR_INVALID;
1150 l = find_item(inst);
1152 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1153 return LB_STATUS_ERROR_NOT_EXIST;
1156 item = eina_list_data_get(l);
1158 if (period <= 0.0f) {
1160 ecore_timer_del(item->timer);
1165 util_timer_interval_set(item->timer, period);
1166 } else if (!s_info.secured) {
1167 item->timer = util_timer_add(period, updator_cb, item);
1169 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1170 return LB_STATUS_ERROR_FAULT;
1178 return LB_STATUS_SUCCESS;
1181 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1184 struct instance *inst;
1188 inst = so_find_instance(pkgname, id);
1190 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1191 return LB_STATUS_ERROR_INVALID;
1194 l = find_item(inst);
1196 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1197 return LB_STATUS_ERROR_NOT_EXIST;
1200 item = eina_list_data_get(l);
1202 ret = so_clicked(inst, event, timestamp, x, y);
1206 if (ret & NEED_TO_SCHEDULE) {
1207 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1208 (void)append_pending_list(item);
1211 if (ret & OUTPUT_UPDATED)
1212 update_monitor_cnt(item);
1214 return LB_STATUS_SUCCESS;
1217 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1220 struct instance *inst;
1224 inst = so_find_instance(pkgname, id);
1226 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1227 return LB_STATUS_ERROR_INVALID;
1230 l = find_item(inst);
1232 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1233 return LB_STATUS_ERROR_NOT_EXIST;
1236 item = eina_list_data_get(l);
1238 if (emission && source && !strcmp(source, id)) {
1239 if (item->inst->item->has_livebox_script) {
1240 if (!strcmp(emission, "lb,show")) {
1241 item->is_lb_show = 1;
1243 if (item->is_lb_updated && !is_pended_item(item))
1244 reset_lb_updated_flag(item);
1246 source = util_uri_to_path(source);
1247 } else if (!strcmp(emission, "lb,hide")) {
1248 DbgPrint("Livebox(%s) script is hide now\n", id);
1249 item->is_lb_show = 0;
1251 source = util_uri_to_path(source);
1255 if (!strcmp(emission, "pd,show")) {
1256 item->is_pd_show = 1;
1257 source = util_uri_to_path(source);
1258 } else if (!strcmp(emission, "pd,hide")) {
1259 item->is_pd_show = 0;
1260 source = util_uri_to_path(source);
1264 ret = so_script_event(inst, emission, source, event_info);
1268 if (ret & NEED_TO_SCHEDULE) {
1269 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1270 (void)append_pending_list(item);
1273 if (ret & OUTPUT_UPDATED)
1274 update_monitor_cnt(item);
1276 return LB_STATUS_SUCCESS;
1279 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1282 struct instance *inst;
1285 inst = so_find_instance(pkgname, id);
1287 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1288 return LB_STATUS_ERROR_INVALID;
1291 l = find_item(inst);
1293 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1294 return LB_STATUS_ERROR_NOT_EXIST;
1297 item = eina_list_data_get(l);
1299 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1300 return LB_STATUS_ERROR_FAULT;
1305 * Maybe this is not neccessary for this operation
1307 return so_is_pinned_up(inst);
1310 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1313 struct instance *inst;
1317 inst = so_find_instance(pkgname, id);
1319 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1320 return LB_STATUS_ERROR_INVALID;
1323 l = find_item(inst);
1325 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1326 return LB_STATUS_ERROR_NOT_EXIST;
1329 item = eina_list_data_get(l);
1331 ret = so_change_group(inst, cluster, category);
1335 if (ret & NEED_TO_SCHEDULE) {
1336 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1337 (void)append_pending_list(item);
1340 if (ret & OUTPUT_UPDATED)
1341 update_monitor_cnt(item);
1343 return LB_STATUS_SUCCESS;
1346 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1350 ret = so_sys_event(inst, event);
1354 if (ret & NEED_TO_SCHEDULE)
1355 (void)append_pending_list(item);
1357 if (ret & OUTPUT_UPDATED)
1358 update_monitor_cnt(item);
1360 return LB_STATUS_SUCCESS;
1363 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1366 struct instance *inst;
1369 inst = so_find_instance(pkgname, id);
1371 ErrPrint("instance %s - %s is not created\n");
1372 return LB_STATUS_ERROR_INVALID;
1375 l = find_item(inst);
1377 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1378 return LB_STATUS_ERROR_NOT_EXIST;
1381 item = eina_list_data_get(l);
1382 return lb_sys_event(inst, item, event);
1385 HAPI int lb_update(const char *pkgname, const char *id)
1388 struct instance *inst;
1391 inst = so_find_instance(pkgname, id);
1393 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1394 return LB_STATUS_ERROR_INVALID;
1397 l = find_item(inst);
1399 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1400 return LB_STATUS_ERROR_NOT_EXIST;
1403 item = eina_list_data_get(l);
1404 (void)append_pending_list(item);
1405 return LB_STATUS_SUCCESS;
1408 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1414 DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1415 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1419 if (cluster && strcasecmp(item->inst->cluster, cluster))
1422 if (category && strcasecmp(item->inst->category, category))
1425 if (pkgname && strlen(pkgname)) {
1426 if (!strcmp(item->inst->item->pkgname, pkgname)) {
1427 (void)append_pending_list(item);
1430 (void)append_pending_list(item);
1434 return LB_STATUS_SUCCESS;
1437 HAPI int lb_delete_all_deleteme(void)
1444 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1445 if (!item->deleteme)
1448 update_monitor_del(item->inst->id, item);
1449 (void)so_destroy(item->inst);
1454 DbgPrint("Delete all deleteme: %d\n", cnt);
1455 return LB_STATUS_SUCCESS;
1458 HAPI int lb_system_event_all(int event)
1464 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1468 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1469 lb_sys_event(item->inst, item, event);
1472 return LB_STATUS_SUCCESS;
1475 HAPI void lb_pause_all(void)
1482 pending_timer_freeze();
1484 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1485 if (item->deleteme) {
1486 DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1490 if (item->is_paused)
1495 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1499 HAPI void lb_resume_all(void)
1507 pending_timer_thaw();
1509 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1510 if (item->deleteme) {
1511 DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1515 if (item->is_paused)
1518 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1520 if (item->updated_in_pause) {
1521 (void)append_pending_list(item);
1522 item->updated_in_pause = 0;
1527 * After send the resume callback, call this function.
1528 * Because the timer_thaw can call the update function.
1529 * Before resumed event is notified to the livebox,
1530 * Do not call update function
1532 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
1533 /* item is deleted */
1538 HAPI int lb_pause(const char *pkgname, const char *id)
1540 struct instance *inst;
1544 inst = so_find_instance(pkgname, id);
1546 return LB_STATUS_ERROR_INVALID;
1548 l = find_item(inst);
1550 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1551 return LB_STATUS_ERROR_NOT_EXIST;
1554 item = eina_list_data_get(l);
1556 return LB_STATUS_ERROR_FAULT;
1558 if (item->deleteme) {
1559 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1560 return LB_STATUS_ERROR_BUSY;
1563 item->is_paused = 1;
1566 return LB_STATUS_SUCCESS;
1570 lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1572 return LB_STATUS_SUCCESS;
1575 HAPI int lb_resume(const char *pkgname, const char *id)
1577 struct instance *inst;
1582 inst = so_find_instance(pkgname, id);
1584 return LB_STATUS_ERROR_INVALID;
1586 l = find_item(inst);
1588 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1589 return LB_STATUS_ERROR_NOT_EXIST;
1592 item = eina_list_data_get(l);
1594 return LB_STATUS_ERROR_FAULT;
1596 if (item->deleteme) {
1597 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1598 return LB_STATUS_ERROR_BUSY;
1601 item->is_paused = 0;
1604 return LB_STATUS_SUCCESS;
1606 lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1608 ret = timer_thaw(item);
1609 if (ret == UPDATE_ITEM_DELETED) {
1614 return LB_STATUS_SUCCESS;
1615 } else if (ret == UPDATE_INVOKED) {
1618 * if the update is successfully done, the updated_in_pause will be reset'd.
1619 * or append it to the pending list
1623 if (item->updated_in_pause) {
1624 (void)append_pending_list(item);
1625 item->updated_in_pause = 0;
1628 return LB_STATUS_SUCCESS;
1631 HAPI void lb_turn_secured_on(void)
1636 HAPI int lb_is_all_paused(void)
1638 return s_info.paused;