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;
67 Eina_List *update_list;
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) {
109 s_info.pending_timer_freezed--;
110 if (s_info.pending_timer && !s_info.pending_timer_freezed) {
111 DbgPrint("Thaw the pending timer\n");
112 ecore_timer_thaw(s_info.pending_timer);
117 * -1 : PD is opened, but not mine
118 * 0 : PD is not opened
119 * 1 : my PD is opened
121 static inline int pd_is_opened(const char *pkgname)
128 EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
129 if (pkgname && !strcmp(pkgname, tmp)) {
136 return i > 0 ? -1 : 0;
139 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
143 item = eina_list_nth(s_info.pd_open_pending_list, 0);
148 if (eina_list_data_find(s_info.update_list, item)) {
149 return ECORE_CALLBACK_RENEW;
152 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
155 * To prevent from checking the is_updated function
157 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
158 /* Item is destroyed */
161 if (s_info.pd_open_pending_list) {
162 return ECORE_CALLBACK_RENEW;
166 s_info.pd_open_pending_timer = NULL;
167 return ECORE_CALLBACK_CANCEL;
170 static Eina_Bool pended_cmd_consumer_cb(void *data)
174 item = eina_list_nth(s_info.pending_list, 0);
179 if (eina_list_data_find(s_info.update_list, item) || pd_is_opened(item->inst->item->pkgname) < 0) {
180 return ECORE_CALLBACK_RENEW;
183 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
186 * To prevent from checking the is_updated function
188 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
189 /* item is destroyed */
192 if (s_info.pending_list) {
193 return ECORE_CALLBACK_RENEW;
197 s_info.pending_timer = NULL;
198 s_info.pending_timer_freezed = 0;
199 return ECORE_CALLBACK_CANCEL;
202 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
204 if (s_info.pending_timer) {
208 s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
209 if (!s_info.pending_timer) {
210 ErrPrint("Failed to add a new pended command consumer\n");
211 return LB_STATUS_ERROR_FAULT;
215 * Do not increase the freezed counter.
216 * Just freeze the timer.
218 if (s_info.pending_timer_freezed) {
219 ecore_timer_freeze(s_info.pending_timer);
225 static inline void deactivate_pending_consumer(void)
227 if (!s_info.pending_timer) {
231 ecore_timer_del(s_info.pending_timer);
232 s_info.pending_timer = NULL;
233 s_info.pending_timer_freezed = 0;
236 static inline void deactivate_pd_open_pending_consumer(void)
238 if (!s_info.pd_open_pending_timer) {
242 ecore_timer_del(s_info.pd_open_pending_timer);
243 s_info.pd_open_pending_timer = NULL;
246 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
248 if (s_info.pd_open_pending_timer) {
252 s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
253 if (!s_info.pd_open_pending_timer) {
254 ErrPrint("Failed to add a new pended command consumer\n");
255 return LB_STATUS_ERROR_FAULT;
261 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
268 EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
269 if (strcmp(pkgname, item->inst->item->pkgname)) {
273 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
274 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
278 if (s_info.pd_open_pending_list) {
279 activate_pd_open_pending_consumer();
282 if (!s_info.pending_list) {
283 deactivate_pending_consumer();
287 static inline void migrate_to_pending_list(const char *pkgname)
294 EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
295 if (strcmp(pkgname, item->inst->item->pkgname)) {
299 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
300 s_info.pending_list = eina_list_append(s_info.pending_list, item);
304 if (s_info.pending_list) {
305 activate_pending_consumer();
308 if (!s_info.pd_open_pending_list) {
309 deactivate_pd_open_pending_consumer();
313 static inline int is_pended_item(struct item *item)
315 struct item *in_item;
316 if (pd_is_opened(item->inst->item->pkgname) == 1) {
317 in_item = eina_list_data_find(s_info.pd_open_pending_list, item);
319 in_item = eina_list_data_find(s_info.pending_list, item);
322 return (in_item == item);
325 static int append_pending_list(struct item *item)
327 if (pd_is_opened(item->inst->item->pkgname) == 1) {
328 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
329 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
330 return LB_STATUS_ERROR_EXIST;
333 if (activate_pd_open_pending_consumer() < 0) {
334 ErrPrint("Failed to activate PD open pending consumer\n");
335 return LB_STATUS_ERROR_FAULT;
338 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
340 if (eina_list_data_find(s_info.pending_list, item) == item) {
341 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
342 return LB_STATUS_ERROR_EXIST;
345 if (activate_pending_consumer() < 0) {
346 return LB_STATUS_ERROR_FAULT;
349 s_info.pending_list = eina_list_append(s_info.pending_list, item);
356 * This function can call the update callback
357 * return 0 if there is no changes
358 * return -1 the item is deleted
360 static inline int timer_thaw(struct item *item)
371 ecore_timer_thaw(item->timer);
372 period = ecore_timer_interval_get(item->timer);
373 pending = ecore_timer_pending_get(item->timer);
374 delay = util_time_delay_for_compensation(period) - pending;
375 ecore_timer_delay(item->timer, delay);
377 if (item->sleep_at == 0.0f) {
381 sleep_time = util_timestamp() - item->sleep_at;
382 item->sleep_at = 0.0f;
384 if (sleep_time > pending) {
385 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
386 /* item is destroyed */
387 return UPDATE_ITEM_DELETED;
389 return UPDATE_INVOKED;
393 return UPDATE_NOT_INVOKED;
396 static void timer_freeze(struct item *item)
402 ecore_timer_freeze(item->timer);
404 if (ecore_timer_interval_get(item->timer) <= 1.0f) {
408 #if defined(_USE_ECORE_TIME_GET)
409 item->sleep_at = ecore_time_get();
412 if (gettimeofday(&tv, NULL) < 0) {
413 ErrPrint("gettimeofday: %s\n", strerror(errno));
418 item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
422 static inline void update_monitor_cnt(struct item *item)
427 now = util_timestamp();
428 interval = now - item->update_interval;
432 * If the content update is processed in too short time,
433 * don't increase the monitor counter, instead of it
434 * set the heavy updating flag.
435 * And handling this heavy updating from the
436 * file update callback.
438 if (interval >= MINIMUM_UPDATE_INTERVAL) {
439 if (eina_list_data_find(s_info.update_list, item)) {
442 * If already in updating mode,
443 * reset the monitor_cnt to 1,
444 * all updated event will be merged into A inotify event
446 DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
447 item->monitor_cnt = 1;
452 item->heavy_updating = 1;
455 item->update_interval = now;
458 static inline Eina_List *find_item(struct instance *inst)
463 EINA_LIST_FOREACH(s_info.item_list, l, item) {
464 if (item->inst == inst) {
472 static inline int output_handler(struct item *item)
477 if (item->monitor_cnt < 0 || item->heavy_updating) {
478 if (!item->heavy_updating) {
479 WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
482 item->heavy_updating = 0; /* Reset flag */
485 item->monitor_cnt = 0;
488 if (item->monitor_cnt == 0) {
490 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
494 ecore_timer_del(item->monitor);
495 item->monitor = NULL;
498 s_info.update_list = eina_list_remove(s_info.update_list, item);
500 if (item->deleteme) {
501 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
502 (void)so_destroy(item->inst);
511 static int desc_updated_cb(const char *filename, void *data, int over)
516 WarnPrint("Event Q overflow\n");
521 DbgPrint("DESC %s is updated\n", filename);
522 if (item->is_pd_show) {
523 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
525 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
530 static int file_updated_cb(const char *filename, void *data, int over)
536 char *content = NULL;
541 WarnPrint("Event Q overflow\n");
546 ret = util_get_filesize(filename);
548 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
549 return EXIT_SUCCESS; /*!< To keep the callback */
552 ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
554 ErrPrint("livebox_get_info returns %d\n", ret);
555 return EXIT_SUCCESS; /*!< To keep the callback */
558 if (IS_LB_SHOWN(item)) {
559 provider_send_updated(item->inst->item->pkgname, item->inst->id,
560 item->inst->w, item->inst->h, item->inst->priority,
563 item->is_lb_updated++;
566 return output_handler(item);
569 static void reset_lb_updated_flag(struct item *item)
571 if (!item->is_lb_updated) {
575 DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
576 item->inst->id, item->is_lb_updated,
577 item->inst->content, item->inst->title);
579 provider_send_updated(item->inst->item->pkgname, item->inst->id,
580 item->inst->w, item->inst->h, item->inst->priority,
581 item->inst->content, item->inst->title);
583 item->is_lb_updated = 0;
586 static inline int clear_from_pd_open_pending_list(struct item *item)
591 EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
596 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
597 if (!s_info.pd_open_pending_list) {
598 deactivate_pd_open_pending_consumer();
600 return LB_STATUS_SUCCESS;
603 return LB_STATUS_ERROR_NOT_EXIST;
606 static inline int clear_from_pending_list(struct item *item)
611 EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
616 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
617 if (!s_info.pending_list) {
618 deactivate_pending_consumer();
620 return LB_STATUS_SUCCESS;
623 return LB_STATUS_ERROR_NOT_EXIST;
626 static Eina_Bool update_timeout_cb(void *data)
632 ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
634 if (!eina_list_data_find(s_info.update_list, item)) {
635 ErrPrint("Updating item is not matched\n");
638 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
639 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
640 s_info.update_list = eina_list_remove(s_info.update_list, item);
643 return ECORE_CALLBACK_CANCEL;
648 * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
649 * So every caller, should manage the deleted item correctly.
651 static Eina_Bool updator_cb(void *data)
658 if (item->monitor) { /*!< If this item is already in update process */
659 return ECORE_CALLBACK_RENEW;
662 if (!IS_LB_SHOWN(item)) {
663 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
664 (void)append_pending_list(item);
665 return ECORE_CALLBACK_RENEW;
668 if (item->is_paused) {
669 item->updated_in_pause++;
670 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
671 return ECORE_CALLBACK_RENEW;
674 item->updated_in_pause = 0;
676 ret = so_is_updated(item->inst);
678 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
679 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
680 lb_destroy(item->inst->item->pkgname, item->inst->id);
683 * Every caller of this, must not access the item from now.
685 return ECORE_CALLBACK_CANCEL;
688 reset_lb_updated_flag(item);
689 return ECORE_CALLBACK_RENEW;
694 * Check the update_list, if you want make serialized update
696 if (/*s_info.update_list || */pd_is_opened(item->inst->item->pkgname) < 0) {
697 DbgPrint("%s is busy\n", item->inst->id);
698 (void)append_pending_list(item);
699 return ECORE_CALLBACK_RENEW;
702 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
703 if (!item->monitor) {
704 ErrPrint("Failed to add update monitor %s(%s):%d\n",
705 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
706 return ECORE_CALLBACK_RENEW;
709 ret = so_update(item->inst);
711 ecore_timer_del(item->monitor);
712 item->monitor = NULL;
713 reset_lb_updated_flag(item);
714 return ECORE_CALLBACK_RENEW;
719 * Counter of the event monitor is only used for asynchronous content updating,
720 * So reset it to 1 from here because the async updating is started now,
721 * even if it is accumulated by other event function before this.
723 item->monitor_cnt = 1;
727 * While waiting the Callback function call,
728 * Add this for finding the crash
730 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
732 if (ret & NEED_TO_SCHEDULE) {
733 (void)append_pending_list(item);
736 if (ret & OUTPUT_UPDATED) {
739 * In this case, there is potential issue
740 * 1. User added update CALLBACK -> Inotify event (Only once)
741 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
742 * 2. Inotify event -> User added update CALLBACK -> Inotify event
743 * > Okay. What we want is this.
745 update_monitor_cnt(item);
750 * This should be updated after "update_monitor_cnt" function call,
751 * because the update_monitor_cnt function will see the s_info.update variable,
753 s_info.update_list = eina_list_append(s_info.update_list, item);
755 return ECORE_CALLBACK_RENEW;
758 static inline void update_monitor_del(const char *id, struct item *item)
763 update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
765 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
768 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
772 snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
773 update_monitor_del_update_cb(tmp, desc_updated_cb);
777 static inline int add_desc_update_monitor(const char *id, struct item *item)
783 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
784 filename = malloc(len);
786 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
787 return LB_STATUS_ERROR_MEMORY;
790 snprintf(filename, len, "%s.desc", util_uri_to_path(id));
791 ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
796 static inline int add_file_update_monitor(const char *id, struct item *item)
798 return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
801 static inline int update_monitor_add(const char *id, struct item *item)
805 * item->inst is not available yet.
807 add_file_update_monitor(id, item);
808 add_desc_update_monitor(id, item);
809 return LB_STATUS_SUCCESS;
812 HAPI int lb_init(void)
814 return LB_STATUS_SUCCESS;
817 HAPI int lb_fini(void)
823 deactivate_pending_consumer();
824 deactivate_pd_open_pending_consumer();
826 EINA_LIST_FREE(s_info.pd_open_pending_list, item);
827 EINA_LIST_FREE(s_info.pending_list, item);
829 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
830 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
831 lb_destroy(item->inst->item->pkgname, item->inst->id);
834 return LB_STATUS_SUCCESS;
839 * Exported API for each liveboxes.
841 const char *livebox_find_pkgname(const char *filename)
846 EINA_LIST_FOREACH(s_info.item_list, l, item) {
847 if (!strcmp(item->inst->id, filename)) {
848 return item->inst->item->pkgname;
855 int livebox_request_update_by_id(const char *filename)
860 if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
861 ErrPrint("Current operation: %d\n", so_current_op());
864 * Some case requires to update the content of other box from livebox_XXX ABI.
865 * In that case this function can be used so we have not to filter it from here.
866 * ex) Setting accessibility.
867 * Press the assistive light, turned on, need to update other instances too.
868 * Then the box will use this function from livebox_clicked function.
872 EINA_LIST_FOREACH(s_info.item_list, l, item) {
873 if (!strcmp(item->inst->id, filename)) {
874 return append_pending_list(item);
878 return LB_STATUS_ERROR_NOT_EXIST;
881 int livebox_trigger_update_monitor(const char *filename, int is_pd)
886 if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
887 ErrPrint("Current operation: %d\n", so_current_op());
888 return LB_STATUS_ERROR_INVALID;
893 len = strlen(filename) + strlen(".desc");
895 fname = malloc(len + 1);
897 ErrPrint("Heap: %s\n", strerror(errno));
898 return LB_STATUS_ERROR_MEMORY;
901 snprintf(fname, len, "%s.desc", filename);
903 fname = strdup(filename);
905 ErrPrint("Heap: %s\n", strerror(errno));
906 return LB_STATUS_ERROR_MEMORY;
910 if (access(fname, R_OK | W_OK) != 0) {
911 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
912 ret = LB_STATUS_ERROR_IO;
914 ret = update_monitor_trigger_update_cb(fname, 0);
921 HAPI int lb_open_pd(const char *pkgname)
926 EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
927 if (!strcmp(pkgname, tmp)) {
932 tmp = strdup(pkgname);
934 ErrPrint("Heap: %s\n", strerror(errno));
935 return LB_STATUS_ERROR_MEMORY;
938 if (!s_info.pd_list) {
939 pending_timer_freeze();
942 s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
945 * Find all instances from the pending list.
946 * Move them to pd_open_pending_timer
948 migrate_to_pd_open_pending_list(pkgname);
949 return LB_STATUS_SUCCESS;
952 HAPI int lb_close_pd(const char *pkgname)
958 EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
959 if (strcmp(tmp, pkgname)) {
963 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
966 if (!s_info.pd_list) {
967 pending_timer_thaw();
971 * Move all items in pd_open_pending_list
974 migrate_to_pending_list(pkgname);
975 return LB_STATUS_SUCCESS;
978 return LB_STATUS_ERROR_NOT_EXIST;
981 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)
983 struct instance *inst;
993 inst = so_find_instance(pkgname, id);
995 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
996 return LB_STATUS_SUCCESS;
999 if (!skip_need_to_create) {
1000 ret = so_create_needed(pkgname, cluster, category, abi);
1001 if (ret != NEED_TO_CREATE) {
1002 return LB_STATUS_ERROR_PERMISSION;
1008 item = calloc(1, sizeof(*item));
1010 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
1011 return LB_STATUS_ERROR_MEMORY;
1014 ret = update_monitor_add(id, item);
1020 create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
1021 if (create_ret < 0) {
1022 update_monitor_del(id, item);
1033 if (period > 0.0f && !s_info.secured) {
1034 item->timer = util_timer_add(period, updator_cb, item);
1036 ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
1037 update_monitor_del(id, item);
1038 (void)so_destroy(inst);
1040 return LB_STATUS_ERROR_FAULT;
1043 if (s_info.paused) {
1047 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
1051 s_info.item_list = eina_list_append(s_info.item_list, item);
1053 if (create_ret & NEED_TO_SCHEDULE) {
1054 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1055 (void)append_pending_list(item);
1058 if (create_ret & OUTPUT_UPDATED) {
1059 update_monitor_cnt(item);
1062 * To send a output info, get the info forcely.
1063 * but the output file monitor will do this again
1065 * This function will set the tmp_content and tmp_title
1066 * even if it has no updates on the content, title,
1067 * it will set them to NULL.
1069 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
1073 tmp = strdup(*out_content);
1075 ErrPrint("Memory: %s\n", strerror(errno));
1084 tmp = strdup(*out_title);
1086 ErrPrint("Memory: %s\n", strerror(errno));
1096 *priority = inst->priority;
1097 return need_to_create;
1100 HAPI int lb_destroy(const char *pkgname, const char *id)
1103 struct instance *inst;
1106 inst = so_find_instance(pkgname, id);
1108 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1109 return LB_STATUS_ERROR_INVALID;
1112 l = find_item(inst);
1114 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1115 return LB_STATUS_ERROR_NOT_EXIST;
1118 item = eina_list_data_get(l);
1119 s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1121 s_info.update_list = eina_list_remove(s_info.update_list, item);
1124 clear_from_pd_open_pending_list(item);
1125 clear_from_pending_list(item);
1126 ecore_timer_del(item->timer);
1129 if (item->monitor) {
1132 update_monitor_del(id, item);
1136 if (!item->monitor) {
1138 (void)so_destroy(inst);
1141 return LB_STATUS_SUCCESS;
1144 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1147 struct instance *inst;
1151 inst = so_find_instance(pkgname, id);
1153 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1154 return LB_STATUS_ERROR_INVALID;
1157 l = find_item(inst);
1159 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1160 return LB_STATUS_ERROR_NOT_EXIST;
1163 item = eina_list_data_get(l);
1165 ret = so_resize(inst, w, h);
1170 if (ret & NEED_TO_SCHEDULE) {
1171 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1172 (void)append_pending_list(item);
1175 if (ret & OUTPUT_UPDATED) {
1176 update_monitor_cnt(item);
1179 return LB_STATUS_SUCCESS;
1182 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1184 struct instance *inst;
1187 inst = so_find_instance(pkgname, id);
1189 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1193 ret = so_pinup(inst, pinup);
1197 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1200 struct instance *inst;
1203 inst = so_find_instance(pkgname, id);
1205 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1206 return LB_STATUS_ERROR_INVALID;
1209 l = find_item(inst);
1211 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1212 return LB_STATUS_ERROR_NOT_EXIST;
1215 item = eina_list_data_get(l);
1217 if (period <= 0.0f) {
1219 ecore_timer_del(item->timer);
1224 util_timer_interval_set(item->timer, period);
1225 } else if (!s_info.secured) {
1226 item->timer = util_timer_add(period, updator_cb, item);
1228 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1229 return LB_STATUS_ERROR_FAULT;
1232 if (s_info.paused) {
1238 return LB_STATUS_SUCCESS;
1241 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1244 struct instance *inst;
1248 inst = so_find_instance(pkgname, id);
1250 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1251 return LB_STATUS_ERROR_INVALID;
1254 l = find_item(inst);
1256 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1257 return LB_STATUS_ERROR_NOT_EXIST;
1260 item = eina_list_data_get(l);
1262 ret = so_clicked(inst, event, timestamp, x, y);
1267 if (ret & NEED_TO_SCHEDULE) {
1268 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1269 (void)append_pending_list(item);
1272 if (ret & OUTPUT_UPDATED) {
1273 update_monitor_cnt(item);
1276 return LB_STATUS_SUCCESS;
1279 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1282 struct instance *inst;
1286 inst = so_find_instance(pkgname, id);
1288 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1289 return LB_STATUS_ERROR_INVALID;
1292 l = find_item(inst);
1294 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1295 return LB_STATUS_ERROR_NOT_EXIST;
1298 item = eina_list_data_get(l);
1300 if (emission && source && !strcmp(source, id)) {
1301 if (item->inst->item->has_livebox_script) {
1302 if (!strcmp(emission, "lb,show")) {
1303 item->is_lb_show = 1;
1305 if (item->is_lb_updated && !is_pended_item(item)) {
1306 reset_lb_updated_flag(item);
1309 source = util_uri_to_path(source);
1310 } else if (!strcmp(emission, "lb,hide")) {
1311 DbgPrint("Livebox(%s) script is hide now\n", id);
1312 item->is_lb_show = 0;
1314 source = util_uri_to_path(source);
1318 if (!strcmp(emission, "pd,show")) {
1319 item->is_pd_show = 1;
1320 source = util_uri_to_path(source);
1321 } else if (!strcmp(emission, "pd,hide")) {
1322 item->is_pd_show = 0;
1323 source = util_uri_to_path(source);
1327 ret = so_script_event(inst, emission, source, event_info);
1332 if (ret & NEED_TO_SCHEDULE) {
1333 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1334 (void)append_pending_list(item);
1337 if (ret & OUTPUT_UPDATED) {
1338 update_monitor_cnt(item);
1341 return LB_STATUS_SUCCESS;
1344 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1347 struct instance *inst;
1350 inst = so_find_instance(pkgname, id);
1352 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1353 return LB_STATUS_ERROR_INVALID;
1356 l = find_item(inst);
1358 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1359 return LB_STATUS_ERROR_NOT_EXIST;
1362 item = eina_list_data_get(l);
1364 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1365 return LB_STATUS_ERROR_FAULT;
1370 * Maybe this is not neccessary for this operation
1372 return so_is_pinned_up(inst);
1375 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1378 struct instance *inst;
1382 inst = so_find_instance(pkgname, id);
1384 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1385 return LB_STATUS_ERROR_INVALID;
1388 l = find_item(inst);
1390 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1391 return LB_STATUS_ERROR_NOT_EXIST;
1394 item = eina_list_data_get(l);
1396 ret = so_change_group(inst, cluster, category);
1401 if (ret & NEED_TO_SCHEDULE) {
1402 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1403 (void)append_pending_list(item);
1406 if (ret & OUTPUT_UPDATED) {
1407 update_monitor_cnt(item);
1410 return LB_STATUS_SUCCESS;
1413 static int lb_sys_event(struct instance *inst, struct item *item, int event)
1417 ret = so_sys_event(inst, event);
1422 if (ret & NEED_TO_SCHEDULE) {
1423 (void)append_pending_list(item);
1426 if (ret & OUTPUT_UPDATED) {
1427 update_monitor_cnt(item);
1430 return LB_STATUS_SUCCESS;
1433 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1436 struct instance *inst;
1439 inst = so_find_instance(pkgname, id);
1441 ErrPrint("instance %s - %s is not created\n");
1442 return LB_STATUS_ERROR_INVALID;
1445 l = find_item(inst);
1447 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1448 return LB_STATUS_ERROR_NOT_EXIST;
1451 item = eina_list_data_get(l);
1452 return lb_sys_event(inst, item, event);
1455 HAPI int lb_update(const char *pkgname, const char *id)
1458 struct instance *inst;
1461 inst = so_find_instance(pkgname, id);
1463 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1464 return LB_STATUS_ERROR_INVALID;
1467 l = find_item(inst);
1469 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1470 return LB_STATUS_ERROR_NOT_EXIST;
1473 item = eina_list_data_get(l);
1474 (void)append_pending_list(item);
1475 return LB_STATUS_SUCCESS;
1478 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1484 DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1485 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1486 if (item->deleteme) {
1490 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
1494 if (category && strcasecmp(item->inst->category, category)) {
1498 if (pkgname && strlen(pkgname)) {
1499 if (!strcmp(item->inst->item->pkgname, pkgname)) {
1500 (void)append_pending_list(item);
1503 (void)append_pending_list(item);
1507 return LB_STATUS_SUCCESS;
1510 HAPI int lb_delete_all_deleteme(void)
1517 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1518 if (!item->deleteme) {
1522 update_monitor_del(item->inst->id, item);
1523 (void)so_destroy(item->inst);
1528 DbgPrint("Delete all deleteme: %d\n", cnt);
1529 return LB_STATUS_SUCCESS;
1532 HAPI int lb_system_event_all(int event)
1538 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1539 if (item->deleteme) {
1543 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1544 lb_sys_event(item->inst, item, event);
1547 return LB_STATUS_SUCCESS;
1550 HAPI void lb_pause_all(void)
1557 pending_timer_freeze();
1559 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1560 if (item->deleteme) {
1561 DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1565 if (item->is_paused) {
1571 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1575 HAPI void lb_resume_all(void)
1583 pending_timer_thaw();
1585 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1586 if (item->deleteme) {
1587 DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1591 if (item->is_paused) {
1595 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1597 if (item->updated_in_pause) {
1598 (void)append_pending_list(item);
1599 item->updated_in_pause = 0;
1604 * After send the resume callback, call this function.
1605 * Because the timer_thaw can call the update function.
1606 * Before resumed event is notified to the livebox,
1607 * Do not call update function
1609 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
1610 /* item is deleted */
1615 HAPI int lb_pause(const char *pkgname, const char *id)
1617 struct instance *inst;
1621 inst = so_find_instance(pkgname, id);
1623 return LB_STATUS_ERROR_INVALID;
1626 l = find_item(inst);
1628 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1629 return LB_STATUS_ERROR_NOT_EXIST;
1632 item = eina_list_data_get(l);
1634 return LB_STATUS_ERROR_FAULT;
1637 if (item->deleteme) {
1638 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1639 return LB_STATUS_ERROR_BUSY;
1642 item->is_paused = 1;
1644 if (s_info.paused) {
1645 return LB_STATUS_SUCCESS;
1650 lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1652 return LB_STATUS_SUCCESS;
1655 HAPI int lb_resume(const char *pkgname, const char *id)
1657 struct instance *inst;
1662 inst = so_find_instance(pkgname, id);
1664 return LB_STATUS_ERROR_INVALID;
1667 l = find_item(inst);
1669 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1670 return LB_STATUS_ERROR_NOT_EXIST;
1673 item = eina_list_data_get(l);
1675 return LB_STATUS_ERROR_FAULT;
1678 if (item->deleteme) {
1679 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1680 return LB_STATUS_ERROR_BUSY;
1683 item->is_paused = 0;
1685 if (s_info.paused) {
1686 return LB_STATUS_SUCCESS;
1689 lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1691 ret = timer_thaw(item);
1692 if (ret == UPDATE_ITEM_DELETED) {
1697 return LB_STATUS_SUCCESS;
1698 } else if (ret == UPDATE_INVOKED) {
1701 * if the update is successfully done, the updated_in_pause will be reset'd.
1702 * or append it to the pending list
1706 if (item->updated_in_pause) {
1707 (void)append_pending_list(item);
1708 item->updated_in_pause = 0;
1711 return LB_STATUS_SUCCESS;
1714 HAPI void lb_turn_secured_on(void)
1719 HAPI int lb_is_all_paused(void)
1721 return s_info.paused;