2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.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.
22 #include <Ecore_Evas.h>
28 #include <com-core_packet.h>
29 #include <livebox-service.h>
30 #include <livebox-errno.h>
35 #include "slave_life.h"
36 #include "slave_rpc.h"
37 #include "client_life.h"
39 #include "client_rpc.h"
41 #include "script_handler.h"
42 #include "buffer_handler.h"
49 enum buffer_type env_buf_type;
51 .env_buf_type = BUFFER_TYPE_FILE,
54 struct set_pinup_cbdata {
55 struct inst_info *inst;
59 struct resize_cbdata {
60 struct inst_info *inst;
65 struct change_group_cbdata {
66 struct inst_info *inst;
71 struct period_cbdata {
72 struct inst_info *inst;
77 int (*event_cb)(struct inst_info *inst, void *data);
82 struct pkg_info *info;
84 enum instance_state state; /*!< Represents current state */
85 enum instance_state requested_state; /*!< Only ACTIVATED | DESTROYED is acceptable */
98 enum livebox_visible_state visible;
106 struct script_info *script;
107 struct buffer_info *buffer;
110 const char *auto_launch;
122 struct script_info *script;
123 struct buffer_info *buffer;
126 struct client_node *owner;
127 int is_opened_for_reactivate;
128 int need_to_send_close_event;
129 char *pended_update_desc;
130 int pended_update_cnt;
133 struct client_node *client; /*!< Owner - creator */
134 Eina_List *client_list; /*!< Viewer list */
137 Ecore_Timer *update_timer; /*!< Only used for secured livebox */
139 Eina_List *delete_event_list;
142 #define CLIENT_SEND_EVENT(instance, packet) ((instance)->client ? client_rpc_async_request((instance)->client, (packet)) : client_broadcast((instance), (packet)))
144 static Eina_Bool update_timer_cb(void *data);
146 static inline void timer_thaw(struct inst_info *inst)
153 ecore_timer_thaw(inst->update_timer);
154 period = ecore_timer_interval_get(inst->update_timer);
155 pending = ecore_timer_pending_get(inst->update_timer);
156 delay = util_time_delay_for_compensation(period) - pending;
157 ecore_timer_delay(inst->update_timer, delay);
158 DbgPrint("Compensated: %lf\n", delay);
160 if (inst->sleep_at == 0.0f)
163 sleep_time = util_timestamp() - inst->sleep_at;
164 if (sleep_time > pending) {
165 DbgPrint("Update time elapsed\n");
166 (void)update_timer_cb(inst);
169 inst->sleep_at = 0.0f;
172 static inline void timer_freeze(struct inst_info *inst)
175 ecore_timer_freeze(inst->update_timer);
177 if (ecore_timer_interval_get(inst->update_timer) <= 1.0f)
180 gettimeofday(&tv, NULL);
181 inst->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
185 static int viewer_deactivated_cb(struct client_node *client, void *data)
187 struct inst_info *inst = data;
189 DbgPrint("%d is deleted from the list of viewer of %s(%s)\n", client_pid(client), package_name(instance_package(inst)), instance_id(inst));
190 if (!eina_list_data_find(inst->client_list, client)) {
191 DbgPrint("Not found\n");
192 return LB_STATUS_ERROR_NOT_EXIST;
195 inst->client_list = eina_list_remove(inst->client_list, client);
196 if (!inst->client_list && !inst->client) {
197 DbgPrint("Has no clients\n");
198 instance_destroy(inst);
201 instance_unref(inst);
202 return -1; /*!< Remove this callback from the cb list */
205 static inline int pause_livebox(struct inst_info *inst)
207 struct packet *packet;
209 packet = packet_create_noack("lb_pause", "ss", package_name(inst->info), inst->id);
211 ErrPrint("Failed to create a new packet\n");
212 return LB_STATUS_ERROR_FAULT;
215 return slave_rpc_request_only(package_slave(inst->info), package_name(inst->info), packet, 0);
218 /*! \TODO Wake up the freeze'd timer */
219 static inline int resume_livebox(struct inst_info *inst)
221 struct packet *packet;
223 packet = packet_create_noack("lb_resume", "ss", package_name(inst->info), inst->id);
225 ErrPrint("Failed to create a new packet\n");
226 return LB_STATUS_ERROR_FAULT;
229 return slave_rpc_request_only(package_slave(inst->info), package_name(inst->info), packet, 0);
232 static inline int instance_recover_visible_state(struct inst_info *inst)
236 switch (inst->visible) {
239 instance_thaw_updator(inst);
243 case LB_HIDE_WITH_PAUSE:
244 ret = pause_livebox(inst);
246 instance_freeze_updator(inst);
249 ret = LB_STATUS_ERROR_INVALID;
253 DbgPrint("Visible state is recovered to %d\n", ret);
257 static inline void instance_send_resized_event(struct inst_info *inst, int is_pd, int w, int h, int status)
259 struct packet *packet;
264 ErrPrint("Instance info is not ready to use\n");
268 pkgname = package_name(inst->info);
271 DbgPrint("Size is changed to %dx%d (%s) %s\n", w, h, id, is_pd ? "pd" : "lb");
273 packet = packet_create_noack("size_changed", "ssiiii", pkgname, id, is_pd, w, h, status);
275 CLIENT_SEND_EVENT(inst, packet);
277 ErrPrint("Failed to send size changed event\n");
280 HAPI int instance_unicast_created_event(struct inst_info *inst, struct client_node *client)
282 struct packet *packet;
283 enum lb_type lb_type;
284 enum pd_type pd_type;
289 client = inst->client;
291 return LB_STATUS_SUCCESS;
294 lb_type = package_lb_type(inst->info);
295 pd_type = package_pd_type(inst->info);
297 if (lb_type == LB_TYPE_SCRIPT)
298 lb_file = fb_id(script_handler_fb(inst->lb.canvas.script));
299 else if (lb_type == LB_TYPE_BUFFER)
300 lb_file = buffer_handler_id(inst->lb.canvas.buffer);
304 if (pd_type == PD_TYPE_SCRIPT)
305 pd_file = fb_id(script_handler_fb(inst->pd.canvas.script));
306 else if (pd_type == PD_TYPE_BUFFER)
307 pd_file = buffer_handler_id(inst->pd.canvas.buffer);
311 packet = packet_create_noack("created", "dsssiiiisssssdiiiiidsi",
313 package_name(inst->info), inst->id, inst->content,
314 inst->lb.width, inst->lb.height,
315 inst->pd.width, inst->pd.height,
316 inst->cluster, inst->category,
318 inst->lb.auto_launch,
320 package_size_list(inst->info),
322 package_pinup(inst->info),
324 inst->lb.period, inst->title,
327 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
328 return LB_STATUS_ERROR_FAULT;
331 return client_rpc_async_request(client, packet);
334 static int update_client_list(struct client_node *client, void *data)
336 struct inst_info *inst = data;
338 if (!instance_has_client(inst, client))
339 instance_add_client(inst, client);
341 return LB_STATUS_SUCCESS;
344 static int instance_broadcast_created_event(struct inst_info *inst)
346 struct packet *packet;
347 enum lb_type lb_type;
348 enum pd_type pd_type;
352 lb_type = package_lb_type(inst->info);
353 pd_type = package_pd_type(inst->info);
355 if (lb_type == LB_TYPE_SCRIPT)
356 lb_file = fb_id(script_handler_fb(inst->lb.canvas.script));
357 else if (lb_type == LB_TYPE_BUFFER)
358 lb_file = buffer_handler_id(inst->lb.canvas.buffer);
362 if (pd_type == PD_TYPE_SCRIPT)
363 pd_file = fb_id(script_handler_fb(inst->pd.canvas.script));
364 else if (pd_type == PD_TYPE_BUFFER)
365 pd_file = buffer_handler_id(inst->pd.canvas.buffer);
370 client_browse_list(inst->cluster, inst->category, update_client_list, inst);
372 packet = packet_create_noack("created", "dsssiiiisssssdiiiiidsi",
374 package_name(inst->info), inst->id, inst->content,
375 inst->lb.width, inst->lb.height,
376 inst->pd.width, inst->pd.height,
377 inst->cluster, inst->category,
379 inst->lb.auto_launch,
381 package_size_list(inst->info),
383 package_pinup(inst->info),
385 inst->lb.period, inst->title,
388 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
389 return LB_STATUS_ERROR_FAULT;
392 return CLIENT_SEND_EVENT(inst, packet);
395 HAPI int instance_unicast_deleted_event(struct inst_info *inst, struct client_node *client)
397 struct packet *packet;
400 client = inst->client;
402 return LB_STATUS_ERROR_INVALID;
405 packet = packet_create_noack("deleted", "ssd", package_name(inst->info), inst->id, inst->timestamp);
407 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
408 return LB_STATUS_ERROR_FAULT;
411 return client_rpc_async_request(client, packet);
414 static int instance_broadcast_deleted_event(struct inst_info *inst)
416 struct packet *packet;
417 struct client_node *client;
422 packet = packet_create_noack("deleted", "ssd", package_name(inst->info), inst->id, inst->timestamp);
424 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
425 return LB_STATUS_ERROR_FAULT;
428 ret = CLIENT_SEND_EVENT(inst, packet);
430 EINA_LIST_FOREACH_SAFE(inst->client_list, l, n, client) {
431 instance_del_client(inst, client);
437 static int client_deactivated_cb(struct client_node *client, void *data)
439 struct inst_info *inst = data;
440 instance_destroy(inst);
441 return LB_STATUS_SUCCESS;
444 static int send_pd_destroyed_to_client(struct inst_info *inst, int status)
446 struct packet *packet;
448 packet = packet_create_noack("pd_destroyed", "ssi", package_name(inst->info), inst->id, status);
450 ErrPrint("Failed to create a packet\n");
451 return LB_STATUS_ERROR_FAULT;
454 return CLIENT_SEND_EVENT(inst, packet);
457 static inline void invoke_delete_callbacks(struct inst_info *inst)
461 struct event_item *item;
463 EINA_LIST_FOREACH_SAFE(inst->delete_event_list, l, n, item) {
464 if (item->event_cb(inst, item->data) < 0) {
465 if (eina_list_data_find(inst->delete_event_list, item)) {
466 inst->delete_event_list = eina_list_remove(inst->delete_event_list, item);
473 HAPI int instance_event_callback_add(struct inst_info *inst, enum instance_event type, int (*event_cb)(struct inst_info *inst, void *data), void *data)
475 struct event_item *item;
478 return LB_STATUS_ERROR_INVALID;
481 case INSTANCE_EVENT_DESTROY:
482 item = malloc(sizeof(*item));
484 ErrPrint("Heap: %s\n", strerror(errno));
485 return LB_STATUS_ERROR_MEMORY;
488 item->event_cb = event_cb;
491 inst->delete_event_list = eina_list_append(inst->delete_event_list, item);
494 return LB_STATUS_ERROR_INVALID;
497 return LB_STATUS_SUCCESS;
500 HAPI int instance_event_callback_del(struct inst_info *inst, enum instance_event type, int (*event_cb)(struct inst_info *inst, void *data))
504 struct event_item *item;
507 case INSTANCE_EVENT_DESTROY:
508 EINA_LIST_FOREACH_SAFE(inst->delete_event_list, l, n, item) {
509 if (item->event_cb == event_cb) {
510 inst->delete_event_list = eina_list_remove(inst->delete_event_list, item);
512 return LB_STATUS_SUCCESS;
520 return LB_STATUS_ERROR_NOT_EXIST;
523 static inline void destroy_instance(struct inst_info *inst)
525 struct pkg_info *pkg;
526 enum lb_type lb_type;
527 enum pd_type pd_type;
528 struct slave_node *slave;
529 struct event_item *item;
531 invoke_delete_callbacks(inst);
535 lb_type = package_lb_type(pkg);
536 pd_type = package_pd_type(pkg);
537 slave = package_slave(inst->info);
539 DbgPrint("Instance is destroyed (%p), slave(%p)\n", inst, slave);
541 if (inst->pd.need_to_send_close_event)
542 send_pd_destroyed_to_client(inst, 0);
544 if (lb_type == LB_TYPE_SCRIPT) {
545 script_handler_unload(inst->lb.canvas.script, 0);
546 script_handler_destroy(inst->lb.canvas.script);
547 } else if (lb_type == LB_TYPE_BUFFER) {
548 buffer_handler_unload(inst->lb.canvas.buffer);
549 buffer_handler_destroy(inst->lb.canvas.buffer);
552 if (pd_type == PD_TYPE_SCRIPT) {
553 script_handler_unload(inst->pd.canvas.script, 1);
554 script_handler_destroy(inst->pd.canvas.script);
555 } else if (pd_type == PD_TYPE_BUFFER) {
556 buffer_handler_unload(inst->pd.canvas.buffer);
557 buffer_handler_destroy(inst->pd.canvas.buffer);
561 client_event_callback_del(inst->client, CLIENT_EVENT_DEACTIVATE, client_deactivated_cb, inst);
562 client_unref(inst->client);
565 if (inst->update_timer)
566 ecore_timer_del(inst->update_timer);
571 * inst->lb.auto_launch
573 * will be released by the package object
574 * it is readonly value for instances
576 EINA_LIST_FREE(inst->delete_event_list, item) {
579 DbgFree(inst->category);
580 DbgFree(inst->cluster);
581 DbgFree(inst->content);
582 DbgFree(inst->title);
583 util_unlink(util_uri_to_path(inst->id));
585 package_del_instance(inst->info, inst);
588 slave = slave_unload_instance(slave);
591 static Eina_Bool update_timer_cb(void *data)
593 struct inst_info *inst = (struct inst_info *)data;
595 DbgPrint("Update instance %s (%s) %s/%s\n", package_name(inst->info), inst->id, inst->cluster, inst->category);
596 slave_rpc_request_update(package_name(inst->info), inst->id, inst->cluster, inst->category);
597 return ECORE_CALLBACK_RENEW;
600 static inline int fork_package(struct inst_info *inst, const char *pkgname)
602 struct pkg_info *info;
605 info = package_find(pkgname);
607 ErrPrint("%s is not found\n", pkgname);
608 return LB_STATUS_ERROR_NOT_EXIST;
611 len = strlen(SCHEMA_FILE "%s%s_%d_%lf.png") + strlen(IMAGE_PATH) + strlen(package_name(info)) + 50;
612 inst->id = malloc(len);
614 ErrPrint("Heap: %s\n", strerror(errno));
615 return LB_STATUS_ERROR_MEMORY;
618 snprintf(inst->id, len, SCHEMA_FILE "%s%s_%d_%lf.png", IMAGE_PATH, package_name(info), client_pid(inst->client), inst->timestamp);
619 inst->lb.auto_launch = package_auto_launch(info);
621 instance_set_pd_info(inst, package_pd_width(info), package_pd_height(info));
623 inst->lb.timeout = package_timeout(info);
624 inst->lb.period = package_period(info);
628 if (package_secured(info)) {
629 DbgPrint("Register the update timer for secured livebox [%s]\n", package_name(info));
630 inst->update_timer = util_timer_add(inst->lb.period, update_timer_cb, inst);
631 if (!inst->update_timer)
632 ErrPrint("Failed to add an update timer for instance %s\n", inst->id);
634 timer_freeze(inst); /* Freeze the update timer as default */
637 return LB_STATUS_SUCCESS;
640 HAPI struct inst_info *instance_create(struct client_node *client, double timestamp, const char *pkgname, const char *content, const char *cluster, const char *category, double period, int width, int height)
642 struct inst_info *inst;
644 inst = calloc(1, sizeof(*inst));
646 ErrPrint("Heap: %s\n", strerror(errno));
650 inst->timestamp = timestamp;
651 inst->lb.width = width;
652 inst->lb.height = height;
654 inst->content = strdup(content);
655 if (!inst->content) {
656 ErrPrint("Heap: %s\n", strerror(errno));
661 inst->cluster = strdup(cluster);
662 if (!inst->cluster) {
663 ErrPrint("Heap: %s\n", strerror(errno));
664 DbgFree(inst->content);
669 inst->category = strdup(category);
670 if (!inst->category) {
671 ErrPrint("Heap: %s\n", strerror(errno));
672 DbgFree(inst->cluster);
673 DbgFree(inst->content);
678 inst->title = strdup(DEFAULT_TITLE); /*!< Use the DEFAULT Title "" */
680 ErrPrint("Heap: %s\n", strerror(errno));
681 DbgFree(inst->category);
682 DbgFree(inst->cluster);
683 DbgFree(inst->content);
689 inst->client = client_ref(client);
690 client_event_callback_add(inst->client, CLIENT_EVENT_DEACTIVATE, client_deactivated_cb, inst);
693 if (fork_package(inst, pkgname) < 0) {
694 client_event_callback_del(inst->client, CLIENT_EVENT_DEACTIVATE, client_deactivated_cb, inst);
695 client_unref(inst->client);
696 DbgFree(inst->title);
697 DbgFree(inst->category);
698 DbgFree(inst->cluster);
699 DbgFree(inst->content);
704 inst->state = INST_INIT;
705 inst->requested_state = INST_INIT;
708 if (package_add_instance(inst->info, inst) < 0) {
709 instance_state_reset(inst);
710 instance_destroy(inst);
714 slave_load_instance(package_slave(inst->info));
716 if (instance_activate(inst) < 0) {
717 instance_state_reset(inst);
718 instance_destroy(inst);
725 HAPI struct inst_info *instance_ref(struct inst_info *inst)
734 HAPI struct inst_info *instance_unref(struct inst_info *inst)
739 if (inst->refcnt == 0) {
740 ErrPrint("Instance refcnt is not valid\n");
745 if (inst->refcnt == 0) {
746 destroy_instance(inst);
753 static void deactivate_cb(struct slave_node *slave, const struct packet *packet, void *data)
755 struct inst_info *inst = data;
756 struct pkg_info *info;
761 * In this callback, we cannot trust the "client" information.
762 * It could be cleared before reach to here.
766 DbgPrint("Consuming a request of a dead process\n");
769 * The instance_reload will care this.
770 * And it will be called from the slave activate callback.
772 inst->changing_state = 0;
773 instance_unref(inst);
777 if (packet_get(packet, "i", &ret) != 1) {
778 ErrPrint("Invalid argument\n");
779 inst->changing_state = 0;
780 instance_unref(inst);
784 if (inst->state == INST_DESTROYED) {
788 * Do nothing at here anymore.
790 inst->changing_state = 0;
791 instance_unref(inst);
799 * Successfully unloaded
801 switch (inst->requested_state) {
803 DbgPrint("REQ: ACTIVATED\n");
804 instance_state_reset(inst);
805 instance_reactivate(inst);
809 instance_broadcast_deleted_event(inst);
810 instance_state_reset(inst);
811 instance_destroy(inst);
812 DbgPrint("== %s\n", package_name(info));
814 /*!< Unable to reach here */
819 case LB_STATUS_ERROR_INVALID:
822 * Slave has no instance of this package.
824 case LB_STATUS_ERROR_NOT_EXIST:
827 * This instance's previous state is only can be the INST_ACTIVATED.
828 * So we should care the slave_unload_instance from here.
829 * And we should send notification to clients, about this is deleted.
833 * Slave has no instance of this.
834 * In this case, ignore the requested_state
835 * Because, this instance is already met a problem.
840 * Failed to unload this instance.
841 * This is not possible, slave will always return LB_STATUS_ERROR_NOT_EXIST, LB_STATUS_ERROR_INVALID, or 0.
842 * but care this exceptional case.
844 DbgPrint("[%s] instance destroying ret(%d)\n", package_name(inst->info), ret);
846 instance_broadcast_deleted_event(inst);
847 instance_state_reset(inst);
848 instance_destroy(inst);
852 inst->changing_state = 0;
853 instance_unref(inst);
856 static void reactivate_cb(struct slave_node *slave, const struct packet *packet, void *data)
858 struct inst_info *inst = data;
859 struct pkg_info *info;
860 enum lb_type lb_type;
861 enum pd_type pd_type;
868 DbgPrint("Consuming a request of a dead process\n");
871 * instance_reload function will care this.
872 * and it will be called from the slave_activate callback
877 if (packet_get(packet, "issi", &ret, &content, &title, &is_pinned_up) != 4) {
878 ErrPrint("Invalid parameter\n");
882 if (strlen(content)) {
885 tmp = strdup(content);
887 ErrPrint("Heap: %s\n", strerror(errno));
891 DbgFree(inst->content);
894 DbgPrint("Update content info %s\n", tmp);
902 ErrPrint("Heap: %s\n", strerror(errno));
906 DbgFree(inst->title);
909 DbgPrint("Update title info %s\n", tmp);
912 if (inst->state == INST_DESTROYED) {
916 * Do nothing at here anymore.
922 case 0: /*!< normally created */
923 inst->state = INST_ACTIVATED;
924 switch (inst->requested_state) {
926 instance_destroy(inst);
929 inst->is_pinned_up = is_pinned_up;
931 lb_type = package_lb_type(info);
932 pd_type = package_pd_type(info);
936 * Optimization point.
937 * In case of the BUFFER type,
938 * the slave will request the buffer to render its contents.
939 * so the buffer will be automatcially recreated when it gots the
940 * buffer request packet.
941 * so load a buffer from here is not neccessary.
942 * I should to revise it and concrete the concept.
943 * Just leave it only for now.
946 if (lb_type == LB_TYPE_SCRIPT && inst->lb.canvas.script) {
947 script_handler_load(inst->lb.canvas.script, 0);
948 } else if (lb_type == LB_TYPE_BUFFER && inst->lb.canvas.buffer) {
949 buffer_handler_load(inst->lb.canvas.buffer);
952 if (pd_type == PD_TYPE_SCRIPT && inst->pd.canvas.script && inst->pd.is_opened_for_reactivate) {
956 * We should to send a request to open a PD to slave.
957 * if we didn't send it, the slave will not recognize the state of a PD.
958 * We have to keep the view of PD seamless even if the livebox is reactivated.
959 * To do that, send open request from here.
961 ret = instance_slave_open_pd(inst, NULL);
962 instance_slave_get_pd_pos(inst, &x, &y);
966 * In this case, master already loads the PD script.
967 * So just send the pd,show event to the slave again.
969 ret = instance_signal_emit(inst,
970 "pd,show", util_uri_to_path(instance_id(inst)),
971 0.0, 0.0, 0.0, 0.0, x, y, 0);
972 } else if (pd_type == PD_TYPE_BUFFER && inst->pd.canvas.buffer && inst->pd.is_opened_for_reactivate) {
975 buffer_handler_load(inst->pd.canvas.buffer);
976 instance_slave_get_pd_pos(inst, &x, &y);
980 * We should to send a request to open a PD to slave.
981 * if we didn't send it, the slave will not recognize the state of a PD.
982 * We have to keep the view of PD seamless even if the livebox is reactivated.
983 * To do that, send open request from here.
985 ret = instance_slave_open_pd(inst, NULL);
989 * In this case, just send the pd,show event for keeping the compatibility
991 ret = instance_signal_emit(inst,
992 "pd,show", util_uri_to_path(instance_id(inst)),
993 0.0, 0.0, 0.0, 0.0, x, y, 0);
998 * After create an instance again,
999 * Send resize request to the livebox.
1000 * instance_resize(inst, inst->lb.width, inst->lb.height);
1002 * renew request will resize the livebox while creating it again
1007 * This function will check the visiblity of a livebox and
1008 * make decision whether it thaw the update timer or not.
1010 instance_recover_visible_state(inst);
1017 DbgPrint("[%s] instance destroying ret(%d)\n", package_name(info), ret);
1018 instance_broadcast_deleted_event(inst);
1019 instance_state_reset(inst);
1020 instance_destroy(inst);
1025 inst->changing_state = 0;
1026 instance_unref(inst);
1029 static void activate_cb(struct slave_node *slave, const struct packet *packet, void *data)
1031 struct inst_info *inst = data;
1041 DbgPrint("Consuming a request of a dead process\n");
1044 * instance_reload will care this
1045 * it will be called from the slave_activate callback
1050 if (packet_get(packet, "iiidssi", &ret, &w, &h, &priority, &content, &title, &is_pinned_up) != 7) {
1051 ErrPrint("Invalid parameter\n");
1055 if (inst->state == INST_DESTROYED) {
1058 * Already destroyed.
1059 * Do nothing at here anymore.
1065 case 1: /*!< need to create */
1066 if (util_free_space(IMAGE_PATH) > MINIMUM_SPACE) {
1067 struct inst_info *new_inst;
1068 new_inst = instance_create(inst->client, util_timestamp(), package_name(inst->info),
1069 inst->content, inst->cluster, inst->category,
1070 inst->lb.period, 0, 0);
1072 ErrPrint("Failed to create a new instance\n");
1074 ErrPrint("Not enough space\n");
1076 case 0: /*!< normally created */
1079 * Anyway this instance is loaded to the slave,
1080 * just increase the loaded instance counter
1081 * And then reset jobs.
1083 instance_set_lb_info(inst, w, h, priority, content, title);
1085 inst->state = INST_ACTIVATED;
1087 switch (inst->requested_state) {
1088 case INST_DESTROYED:
1089 instance_unicast_deleted_event(inst, NULL);
1090 instance_state_reset(inst);
1091 instance_destroy(inst);
1093 case INST_ACTIVATED:
1097 * LB should be created at the create time
1099 inst->is_pinned_up = is_pinned_up;
1100 if (package_lb_type(inst->info) == LB_TYPE_SCRIPT) {
1101 if (inst->lb.width == 0 && inst->lb.height == 0)
1102 livebox_service_get_size(LB_SIZE_TYPE_1x1, &inst->lb.width, &inst->lb.height);
1104 inst->lb.canvas.script = script_handler_create(inst,
1105 package_lb_path(inst->info),
1106 package_lb_group(inst->info),
1107 inst->lb.width, inst->lb.height);
1109 if (!inst->lb.canvas.script)
1110 ErrPrint("Failed to create LB\n");
1112 script_handler_load(inst->lb.canvas.script, 0);
1113 } else if (package_lb_type(inst->info) == LB_TYPE_BUFFER) {
1114 instance_create_lb_buffer(inst);
1117 if (package_pd_type(inst->info) == PD_TYPE_SCRIPT) {
1118 if (inst->pd.width == 0 && inst->pd.height == 0)
1119 instance_set_pd_info(inst, package_pd_width(inst->info), package_pd_height(inst->info));
1121 inst->pd.canvas.script = script_handler_create(inst,
1122 package_pd_path(inst->info),
1123 package_pd_group(inst->info),
1124 inst->pd.width, inst->pd.height);
1126 if (!inst->pd.canvas.script)
1127 ErrPrint("Failed to create PD\n");
1128 } else if (package_pd_type(inst->info) == PD_TYPE_BUFFER) {
1129 instance_create_pd_buffer(inst);
1132 instance_broadcast_created_event(inst);
1134 instance_thaw_updator(inst);
1139 DbgPrint("[%s] instance destroying ret(%d)\n", package_name(inst->info), ret);
1140 instance_unicast_deleted_event(inst, NULL);
1141 instance_state_reset(inst);
1142 instance_destroy(inst);
1147 inst->changing_state = 0;
1148 instance_unref(inst);
1151 HAPI int instance_create_pd_buffer(struct inst_info *inst)
1153 if (inst->pd.width == 0 && inst->pd.height == 0)
1154 instance_set_pd_info(inst, package_pd_width(inst->info), package_pd_height(inst->info));
1156 if (!inst->pd.canvas.buffer) {
1157 inst->pd.canvas.buffer = buffer_handler_create(inst, s_info.env_buf_type, inst->pd.width, inst->pd.height, sizeof(int));
1158 if (!inst->pd.canvas.buffer)
1159 ErrPrint("Failed to create PD Buffer\n");
1162 return !!inst->pd.canvas.buffer;
1165 HAPI int instance_create_lb_buffer(struct inst_info *inst)
1167 if (inst->lb.width == 0 && inst->lb.height == 0)
1168 livebox_service_get_size(LB_SIZE_TYPE_1x1, &inst->lb.width, &inst->lb.height);
1170 if (!inst->lb.canvas.buffer) {
1173 * Slave doesn't call the acquire_buffer.
1174 * In this case, create the buffer from here.
1176 inst->lb.canvas.buffer = buffer_handler_create(inst, s_info.env_buf_type, inst->lb.width, inst->lb.height, sizeof(int));
1177 if (!inst->lb.canvas.buffer)
1178 ErrPrint("Failed to create LB\n");
1181 return !!inst->lb.canvas.buffer;
1184 HAPI int instance_destroy(struct inst_info *inst)
1186 struct packet *packet;
1189 ErrPrint("Invalid instance handle\n");
1190 return LB_STATUS_ERROR_INVALID;
1193 switch (inst->state) {
1194 case INST_REQUEST_TO_ACTIVATE:
1195 case INST_REQUEST_TO_DESTROY:
1196 case INST_REQUEST_TO_REACTIVATE:
1197 inst->requested_state = INST_DESTROYED;
1198 return LB_STATUS_SUCCESS;
1200 inst->state = INST_DESTROYED;
1201 inst->requested_state = INST_DESTROYED;
1202 instance_unref(inst);
1203 return LB_STATUS_SUCCESS;
1204 case INST_DESTROYED:
1205 inst->requested_state = INST_DESTROYED;
1206 return LB_STATUS_SUCCESS;
1211 packet = packet_create("delete", "ss", package_name(inst->info), inst->id);
1213 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1214 return LB_STATUS_ERROR_FAULT;
1217 inst->requested_state = INST_DESTROYED;
1218 inst->state = INST_REQUEST_TO_DESTROY;
1219 inst->changing_state = 1;
1220 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, deactivate_cb, instance_ref(inst), 0);
1223 /* Client Deactivated Callback */
1224 static int pd_buffer_close_cb(struct client_node *client, void *inst)
1228 ret = instance_slave_close_pd(inst, client);
1229 DbgPrint("Forcely close the PD ret: %d\n", ret);
1230 return -1; /* Delete this callback */
1233 /* Client Deactivated Callback */
1234 static int pd_script_close_cb(struct client_node *client, void *inst)
1238 ret = script_handler_unload(instance_pd_script(inst), 1);
1239 DbgPrint("Unload script: %d\n", ret);
1241 ret = instance_slave_close_pd(inst, client);
1242 DbgPrint("Forcely close the PD ret: %d\n", ret);
1244 return -1; /* Delete this callback */
1247 static inline void release_resource_for_closing_pd(struct pkg_info *info, struct inst_info *inst, struct client_node *client)
1250 client = inst->pd.owner;
1257 * Clean up the resources
1259 if (package_pd_type(info) == PD_TYPE_BUFFER) {
1260 if (client_event_callback_del(client, CLIENT_EVENT_DEACTIVATE, pd_buffer_close_cb, inst) == 0) {
1263 * Only if this function succeed to remove the pd_buffer_close_cb,
1264 * Decrease the reference count of this instance
1267 instance_unref(inst);
1268 } else if (package_pd_type(info) == PD_TYPE_SCRIPT) {
1269 if (client_event_callback_del(client, CLIENT_EVENT_DEACTIVATE, pd_script_close_cb, inst) == 0) {
1272 * Only if this function succeed to remove the script_close_cb,
1273 * Decrease the reference count of this instance
1276 instance_unref(inst);
1278 ErrPrint("Unknown PD type\n");
1283 HAPI int instance_state_reset(struct inst_info *inst)
1285 enum lb_type lb_type;
1286 enum pd_type pd_type;
1289 ErrPrint("Invalid instance handle\n");
1290 return LB_STATUS_ERROR_INVALID;
1293 if (inst->state == INST_DESTROYED)
1294 return LB_STATUS_SUCCESS;
1296 lb_type = package_lb_type(inst->info);
1297 pd_type = package_pd_type(inst->info);
1299 if (lb_type == LB_TYPE_SCRIPT && inst->lb.canvas.script)
1300 script_handler_unload(inst->lb.canvas.script, 0);
1301 else if (lb_type == LB_TYPE_BUFFER && inst->lb.canvas.buffer)
1302 buffer_handler_unload(inst->lb.canvas.buffer);
1304 if (pd_type == PD_TYPE_SCRIPT && inst->pd.canvas.script) {
1305 inst->pd.is_opened_for_reactivate = script_handler_is_loaded(inst->pd.canvas.script);
1306 release_resource_for_closing_pd(instance_package(inst), inst, NULL);
1307 script_handler_unload(inst->pd.canvas.script, 1);
1308 } else if (pd_type == PD_TYPE_BUFFER && inst->pd.canvas.buffer) {
1309 inst->pd.is_opened_for_reactivate = buffer_handler_is_loaded(inst->pd.canvas.buffer);
1310 release_resource_for_closing_pd(instance_package(inst), inst, NULL);
1311 buffer_handler_unload(inst->pd.canvas.buffer);
1314 inst->state = INST_INIT;
1315 inst->requested_state = INST_INIT;
1316 return LB_STATUS_SUCCESS;
1319 HAPI int instance_reactivate(struct inst_info *inst)
1321 struct packet *packet;
1325 ErrPrint("Invalid instance handle\n");
1326 return LB_STATUS_ERROR_INVALID;
1329 if (package_is_fault(inst->info)) {
1330 DbgPrint("Fault package [%s]\n", package_name(inst->info));
1331 return LB_STATUS_ERROR_FAULT;
1334 switch (inst->state) {
1335 case INST_REQUEST_TO_DESTROY:
1336 case INST_REQUEST_TO_ACTIVATE:
1337 case INST_REQUEST_TO_REACTIVATE:
1338 inst->requested_state = INST_ACTIVATED;
1339 return LB_STATUS_SUCCESS;
1340 case INST_DESTROYED:
1341 case INST_ACTIVATED:
1342 return LB_STATUS_SUCCESS;
1348 packet = packet_create("renew", "sssiidssiis",
1349 package_name(inst->info),
1353 !!package_lb_path(inst->info),
1357 inst->lb.width, inst->lb.height,
1358 package_abi(inst->info));
1360 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1361 return LB_STATUS_ERROR_FAULT;
1364 ret = slave_activate(package_slave(inst->info));
1365 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY) {
1368 * If the master failed to launch the slave,
1369 * Do not send any requests to the slave.
1371 ErrPrint("Failed to launch the slave\n");
1372 packet_destroy(packet);
1376 inst->requested_state = INST_ACTIVATED;
1377 inst->state = INST_REQUEST_TO_REACTIVATE;
1378 inst->changing_state = 1;
1380 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, reactivate_cb, instance_ref(inst), 1);
1383 HAPI int instance_activate(struct inst_info *inst)
1385 struct packet *packet;
1389 ErrPrint("Invalid instance handle\n");
1390 return LB_STATUS_ERROR_INVALID;
1393 if (package_is_fault(inst->info)) {
1394 DbgPrint("Fault package [%s]\n", package_name(inst->info));
1395 return LB_STATUS_ERROR_FAULT;
1398 switch (inst->state) {
1399 case INST_REQUEST_TO_REACTIVATE:
1400 case INST_REQUEST_TO_ACTIVATE:
1401 case INST_REQUEST_TO_DESTROY:
1402 inst->requested_state = INST_ACTIVATED;
1403 return LB_STATUS_SUCCESS;
1404 case INST_ACTIVATED:
1405 case INST_DESTROYED:
1406 return LB_STATUS_SUCCESS;
1412 packet = packet_create("new", "sssiidssisii",
1413 package_name(inst->info),
1417 !!package_lb_path(inst->info),
1422 package_abi(inst->info),
1426 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1427 return LB_STATUS_ERROR_FAULT;
1430 ret = slave_activate(package_slave(inst->info));
1431 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY) {
1434 * If the master failed to launch the slave,
1435 * Do not send any requests to the slave.
1437 ErrPrint("Failed to launch the slave\n");
1438 packet_destroy(packet);
1442 inst->state = INST_REQUEST_TO_ACTIVATE;
1443 inst->requested_state = INST_ACTIVATED;
1444 inst->changing_state = 1;
1448 * Try to activate a slave if it is not activated
1450 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, activate_cb, instance_ref(inst), 1);
1453 HAPI void instance_lb_updated(const char *pkgname, const char *id)
1455 struct inst_info *inst;
1457 inst = package_find_instance_by_id(pkgname, id);
1461 instance_lb_updated_by_instance(inst);
1464 HAPI void instance_lb_updated_by_instance(struct inst_info *inst)
1466 struct packet *packet;
1468 enum lb_type lb_type;
1470 const char *content;
1472 if (inst->client && inst->visible != LB_SHOW) {
1473 if (inst->visible == LB_HIDE) {
1474 DbgPrint("Ignore update event %s(HIDE)\n", inst->id);
1477 DbgPrint("Livebox(%s) is PAUSED. But content is updated.\n", inst->id);
1480 lb_type = package_lb_type(inst->info);
1481 if (lb_type == LB_TYPE_SCRIPT)
1482 id = fb_id(script_handler_fb(inst->lb.canvas.script));
1483 else if (lb_type == LB_TYPE_BUFFER)
1484 id = buffer_handler_id(inst->lb.canvas.buffer);
1489 content = inst->content;
1494 title = inst->title;
1498 packet = packet_create_noack("lb_updated", "sssiidss",
1499 package_name(inst->info), inst->id, id,
1500 inst->lb.width, inst->lb.height, inst->lb.priority, content, title);
1502 ErrPrint("Failed to create param (%s - %s)\n", package_name(inst->info), inst->id);
1506 (void)CLIENT_SEND_EVENT(inst, packet);
1509 HAPI void instance_pd_updated_by_instance(struct inst_info *inst, const char *descfile)
1511 struct packet *packet;
1514 if (inst->client && inst->visible != LB_SHOW) {
1515 DbgPrint("Livebox is hidden. ignore update event\n");
1519 if (!inst->pd.need_to_send_close_event) {
1520 DbgPrint("PD is not created yet. Ignore update event - %s\n", descfile);
1522 if (inst->pd.pended_update_desc) {
1523 DbgFree(inst->pd.pended_update_desc);
1524 inst->pd.pended_update_desc = NULL;
1528 inst->pd.pended_update_desc = strdup(descfile);
1529 if (!inst->pd.pended_update_desc)
1530 ErrPrint("Heap: %s\n", strerror(errno));
1533 inst->pd.pended_update_cnt++;
1538 descfile = inst->id;
1540 switch (package_pd_type(inst->info)) {
1541 case PD_TYPE_SCRIPT:
1542 id = fb_id(script_handler_fb(inst->pd.canvas.script));
1544 case PD_TYPE_BUFFER:
1545 id = buffer_handler_id(inst->pd.canvas.buffer);
1553 packet = packet_create_noack("pd_updated", "ssssii",
1554 package_name(inst->info), inst->id, descfile, id,
1555 inst->pd.width, inst->pd.height);
1557 ErrPrint("Failed to create param (%s - %s)\n", package_name(inst->info), inst->id);
1561 (void)CLIENT_SEND_EVENT(inst, packet);
1564 HAPI void instance_pd_updated(const char *pkgname, const char *id, const char *descfile)
1566 struct inst_info *inst;
1568 inst = package_find_instance_by_id(pkgname, id);
1572 instance_pd_updated_by_instance(inst, descfile);
1575 HAPI void instance_set_lb_info(struct inst_info *inst, int w, int h, double priority, const char *content, const char *title)
1577 char *_content = NULL;
1578 char *_title = NULL;
1580 if (content && strlen(content)) {
1581 _content = strdup(content);
1583 ErrPrint("Heap: %s\n", strerror(errno));
1586 if (title && strlen(title)) {
1587 _title = strdup(title);
1589 ErrPrint("Heap: %s\n", strerror(errno));
1593 DbgFree(inst->content);
1594 inst->content= _content;
1598 DbgFree(inst->title);
1599 inst->title = _title;
1602 if (priority >= 0.0f && priority <= 1.0f)
1603 inst->lb.priority = priority;
1605 if (inst->lb.width != w || inst->lb.height != h)
1606 instance_send_resized_event(inst, IS_LB, w, h, LB_STATUS_SUCCESS);
1609 inst->lb.height = h;
1612 HAPI void instance_set_pd_info(struct inst_info *inst, int w, int h)
1614 if (inst->pd.width != w || inst->pd.height != h)
1615 instance_send_resized_event(inst, IS_PD, w, h, LB_STATUS_SUCCESS);
1618 inst->pd.height = h;
1621 static void pinup_cb(struct slave_node *slave, const struct packet *packet, void *data)
1623 struct set_pinup_cbdata *cbdata = data;
1624 const char *content;
1625 struct packet *result;
1631 * Send pinup failed event to client.
1633 ret = LB_STATUS_ERROR_INVALID;
1637 if (packet_get(packet, "is", &ret, &content) != 2) {
1640 * Send pinup failed event to client
1642 ret = LB_STATUS_ERROR_INVALID;
1649 new_content = strdup(content);
1651 ErrPrint("Heap: %s\n", strerror(errno));
1654 * send pinup failed event to client
1656 ret = LB_STATUS_ERROR_MEMORY;
1660 cbdata->inst->is_pinned_up = cbdata->pinup;
1661 DbgFree(cbdata->inst->content);
1663 cbdata->inst->content = new_content;
1669 * Send PINUP Result to client.
1670 * Client should wait this event.
1672 result = packet_create_noack("pinup", "iisss", ret, cbdata->inst->is_pinned_up,
1673 package_name(cbdata->inst->info), cbdata->inst->id, cbdata->inst->content);
1675 (void)CLIENT_SEND_EVENT(cbdata->inst, result);
1677 ErrPrint("Failed to build a packet for %s\n", package_name(cbdata->inst->info));
1679 instance_unref(cbdata->inst);
1683 HAPI int instance_set_pinup(struct inst_info *inst, int pinup)
1685 struct set_pinup_cbdata *cbdata;
1686 struct packet *packet;
1689 ErrPrint("Invalid instance handle\n");
1690 return LB_STATUS_ERROR_INVALID;
1693 if (package_is_fault(inst->info)) {
1694 DbgPrint("Fault package [%s]\n", package_name(inst->info));
1695 return LB_STATUS_ERROR_FAULT;
1698 if (!package_pinup(inst->info))
1699 return LB_STATUS_ERROR_INVALID;
1701 if (pinup == inst->is_pinned_up)
1702 return LB_STATUS_ERROR_INVALID;
1704 cbdata = malloc(sizeof(*cbdata));
1706 return LB_STATUS_ERROR_MEMORY;
1708 cbdata->inst = instance_ref(inst);
1709 cbdata->pinup = pinup;
1711 packet = packet_create("pinup", "ssi", package_name(inst->info), inst->id, pinup);
1713 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1714 instance_unref(cbdata->inst);
1716 return LB_STATUS_ERROR_FAULT;
1719 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, pinup_cb, cbdata, 0);
1722 HAPI int instance_freeze_updator(struct inst_info *inst)
1724 if (!inst->update_timer)
1725 return LB_STATUS_ERROR_INVALID;
1727 DbgPrint("Freeze the update timer (%s)\n", inst->id);
1729 return LB_STATUS_SUCCESS;
1732 HAPI int instance_thaw_updator(struct inst_info *inst)
1734 if (!inst->update_timer)
1735 return LB_STATUS_ERROR_INVALID;
1737 if (client_is_all_paused() || setting_is_lcd_off()) {
1738 DbgPrint("Skip thaw (%s)\n", inst->id);
1739 return LB_STATUS_ERROR_INVALID;
1742 if (inst->visible == LB_HIDE_WITH_PAUSE) {
1743 DbgPrint("Live box is invisible (%s)\n", inst->id);
1744 return LB_STATUS_ERROR_INVALID;
1747 DbgPrint("Thaw the update timer (%s)\n", inst->id);
1749 return LB_STATUS_SUCCESS;
1752 HAPI enum livebox_visible_state instance_visible_state(struct inst_info *inst)
1754 return inst->visible;
1757 HAPI int instance_set_visible_state(struct inst_info *inst, enum livebox_visible_state state)
1759 if (inst->visible == state) {
1760 DbgPrint("Visibility has no changed\n");
1761 return LB_STATUS_SUCCESS;
1767 if (inst->visible == LB_HIDE_WITH_PAUSE) {
1768 if (resume_livebox(inst) == 0)
1769 inst->visible = state;
1771 instance_thaw_updator(inst);
1773 inst->visible = state;
1777 case LB_HIDE_WITH_PAUSE:
1778 if (pause_livebox(inst) == 0)
1779 inst->visible = LB_HIDE_WITH_PAUSE;
1781 instance_freeze_updator(inst);
1785 return LB_STATUS_ERROR_INVALID;
1788 return LB_STATUS_SUCCESS;
1791 static void resize_cb(struct slave_node *slave, const struct packet *packet, void *data)
1793 struct resize_cbdata *cbdata = data;
1797 ErrPrint("Invalid packet\n");
1798 instance_send_resized_event(cbdata->inst, IS_LB, cbdata->inst->lb.width, cbdata->inst->lb.height, LB_STATUS_ERROR_FAULT);
1799 instance_unref(cbdata->inst);
1804 if (packet_get(packet, "i", &ret) != 1) {
1805 ErrPrint("Invalid parameter\n");
1806 instance_send_resized_event(cbdata->inst, IS_LB, cbdata->inst->lb.width, cbdata->inst->lb.height, LB_STATUS_ERROR_INVALID);
1807 instance_unref(cbdata->inst);
1812 if (ret == LB_STATUS_SUCCESS) {
1815 * else waiting the first update with new size
1817 if (cbdata->inst->lb.width == cbdata->w && cbdata->inst->lb.height == cbdata->h) {
1820 * Right after the viewer adds a new box,
1821 * Box has no size information, then it will try to use the default size,
1822 * After a box returns created event.
1824 * A box will start to generate default size content.
1825 * But the viewer doesn't know it,.
1827 * So the viewer will try to change the size of a box.
1829 * At that time, the provider gots the size changed event from the box.
1830 * So it sent the size changed event to the viewer.
1831 * But the viewer ignores it. if it doesn't care the size changed event.
1832 * (even if it cares the size changed event, there is a timing issue)
1834 * And the provider receives resize request,
1835 * right before send the size changed event.
1836 * but there is no changes about the size.
1838 * Now the view will waits size changed event forever.
1839 * To resolve this timing issue.
1841 * Check the size of a box from here.
1842 * And if the size is already updated, send the ALREADY event to the viewer
1843 * to get the size changed event callback correctly.
1845 instance_send_resized_event(cbdata->inst, IS_LB, cbdata->inst->lb.width, cbdata->inst->lb.height, LB_STATUS_ERROR_ALREADY);
1846 DbgPrint("Livebox is already resized\n");
1849 DbgPrint("Livebox rejects the new size: %dx%d (%d)\n", cbdata->w, cbdata->h, ret);
1850 instance_send_resized_event(cbdata->inst, IS_LB, cbdata->inst->lb.width, cbdata->inst->lb.height, ret);
1853 instance_unref(cbdata->inst);
1857 HAPI int instance_resize(struct inst_info *inst, int w, int h)
1859 struct resize_cbdata *cbdata;
1860 struct packet *packet;
1864 ErrPrint("Invalid instance handle\n");
1865 return LB_STATUS_ERROR_INVALID;
1868 if (package_is_fault(inst->info)) {
1869 ErrPrint("Fault package: %s\n", package_name(inst->info));
1870 return LB_STATUS_ERROR_FAULT;
1873 cbdata = malloc(sizeof(*cbdata));
1875 ErrPrint("Heap: %s\n", strerror(errno));
1876 return LB_STATUS_ERROR_MEMORY;
1879 cbdata->inst = instance_ref(inst);
1883 /* NOTE: param is resued from here */
1884 packet = packet_create("resize", "ssii", package_name(inst->info), inst->id, w, h);
1886 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1887 instance_unref(cbdata->inst);
1889 return LB_STATUS_ERROR_FAULT;
1892 ret = slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, resize_cb, cbdata, 0);
1896 static void set_period_cb(struct slave_node *slave, const struct packet *packet, void *data)
1899 struct period_cbdata *cbdata = data;
1900 struct packet *result;
1903 ret = LB_STATUS_ERROR_FAULT;
1907 if (packet_get(packet, "i", &ret) != 1) {
1908 ret = LB_STATUS_ERROR_INVALID;
1913 cbdata->inst->lb.period = cbdata->period;
1915 ErrPrint("Failed to set period %d\n", ret);
1918 result = packet_create_noack("period_changed", "idss", ret, cbdata->inst->lb.period, package_name(cbdata->inst->info), cbdata->inst->id);
1920 (void)CLIENT_SEND_EVENT(cbdata->inst, result);
1922 ErrPrint("Failed to build a packet for %s\n", package_name(cbdata->inst->info));
1924 instance_unref(cbdata->inst);
1929 static Eina_Bool timer_updator_cb(void *data)
1931 struct period_cbdata *cbdata = data;
1932 struct inst_info *inst;
1934 struct packet *result;
1936 period = cbdata->period;
1937 inst = cbdata->inst;
1940 DbgPrint("Update period is changed to %lf from %lf\n", period, inst->lb.period);
1942 inst->lb.period = period;
1943 if (inst->update_timer) {
1944 if (inst->lb.period == 0.0f) {
1945 ecore_timer_del(inst->update_timer);
1946 inst->update_timer = NULL;
1948 util_timer_interval_set(inst->update_timer, inst->lb.period);
1950 } else if (inst->lb.period > 0.0f) {
1951 inst->update_timer = util_timer_add(inst->lb.period, update_timer_cb, inst);
1952 if (!inst->update_timer)
1953 ErrPrint("Failed to add an update timer for instance %s\n", inst->id);
1955 timer_freeze(inst); /* Freeze the update timer as default */
1958 result = packet_create_noack("period_changed", "idss", 0, inst->lb.period, package_name(inst->info), inst->id);
1960 (void)CLIENT_SEND_EVENT(inst, result);
1962 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
1964 instance_unref(inst);
1965 return ECORE_CALLBACK_CANCEL;
1968 HAPI int instance_set_period(struct inst_info *inst, double period)
1970 struct packet *packet;
1971 struct period_cbdata *cbdata;
1974 ErrPrint("Invalid instance handle\n");
1975 return LB_STATUS_ERROR_INVALID;
1978 if (package_is_fault(inst->info)) {
1979 DbgPrint("Fault package [%s]\n", package_name(inst->info));
1980 return LB_STATUS_ERROR_FAULT;
1983 if (period < 0.0f) { /* Use the default period */
1984 period = package_period(inst->info);
1985 } else if (period > 0.0f && period < MINIMUM_PERIOD) {
1986 period = MINIMUM_PERIOD; /* defined at conf.h */
1989 cbdata = malloc(sizeof(*cbdata));
1991 ErrPrint("Heap: %s\n", strerror(errno));
1992 return LB_STATUS_ERROR_MEMORY;
1995 cbdata->period = period;
1996 cbdata->inst = instance_ref(inst);
1998 if (package_secured(inst->info)) {
2001 * Secured livebox doesn't need to send its update period to the slave.
2002 * Slave has no local timer for updating liveboxes
2004 * So update its timer at here.
2006 if (!ecore_timer_add(DELAY_TIME, timer_updator_cb, cbdata))
2007 timer_updator_cb(cbdata);
2008 return LB_STATUS_SUCCESS;
2011 packet = packet_create("set_period", "ssd", package_name(inst->info), inst->id, period);
2013 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
2014 instance_unref(cbdata->inst);
2016 return LB_STATUS_ERROR_FAULT;
2019 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, set_period_cb, cbdata, 0);
2022 HAPI int instance_clicked(struct inst_info *inst, const char *event, double timestamp, double x, double y)
2024 struct packet *packet;
2027 ErrPrint("Invalid instance handle\n");
2028 return LB_STATUS_ERROR_INVALID;
2031 if (package_is_fault(inst->info)) {
2032 DbgPrint("Fault package [%s]\n", package_name(inst->info));
2033 return LB_STATUS_ERROR_FAULT;
2036 /* NOTE: param is resued from here */
2037 packet = packet_create_noack("clicked", "sssddd", package_name(inst->info), inst->id, event, timestamp, x, y);
2039 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
2040 return LB_STATUS_ERROR_FAULT;
2043 return slave_rpc_request_only(package_slave(inst->info), package_name(inst->info), packet, 0);
2046 HAPI int instance_signal_emit(struct inst_info *inst, const char *signal, const char *part, double sx, double sy, double ex, double ey, double x, double y, int down)
2048 const char *pkgname;
2050 struct slave_node *slave;
2051 struct packet *packet;
2054 pkgname = package_name(instance_package(inst));
2055 id = instance_id(inst);
2056 if (!pkgname || !id) {
2057 ErrPrint("Invalid instance\n");
2058 return LB_STATUS_ERROR_INVALID;
2061 slave = package_slave(instance_package(inst));
2063 ErrPrint("Slave is not valid\n");
2064 return LB_STATUS_ERROR_INVALID;
2067 packet = packet_create_noack("script", "ssssddddddi",
2073 ErrPrint("Failed to create param\n");
2074 return LB_STATUS_ERROR_FAULT;
2077 DbgPrint("Signal emit: %s(%s), %s(%s), %lf, %lf, %lf, %lf, %lfx%lf, %d\n", pkgname, id, signal, part, sx, sy, ex, ey, x, y, down);
2078 ret = slave_rpc_request_only(slave, pkgname, packet, 0);
2082 HAPI int instance_text_signal_emit(struct inst_info *inst, const char *emission, const char *source, double sx, double sy, double ex, double ey)
2084 struct packet *packet;
2087 ErrPrint("Invalid instance handle\n");
2088 return LB_STATUS_ERROR_INVALID;
2091 if (package_is_fault(inst->info)) {
2092 DbgPrint("Fault package [%s]\n", package_name(inst->info));
2093 return LB_STATUS_ERROR_FAULT;
2096 packet = packet_create_noack("text_signal", "ssssdddd", package_name(inst->info), inst->id, emission, source, sx, sy, ex, ey);
2098 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
2099 return LB_STATUS_ERROR_FAULT;
2102 return slave_rpc_request_only(package_slave(inst->info), package_name(inst->info), packet, 0);
2105 static void change_group_cb(struct slave_node *slave, const struct packet *packet, void *data)
2107 struct change_group_cbdata *cbdata = data;
2108 struct packet *result;
2112 DbgFree(cbdata->cluster);
2113 DbgFree(cbdata->category);
2114 ret = LB_STATUS_ERROR_FAULT;
2118 if (packet_get(packet, "i", &ret) != 1) {
2119 ErrPrint("Invalid packet\n");
2120 DbgFree(cbdata->cluster);
2121 DbgFree(cbdata->category);
2122 ret = LB_STATUS_ERROR_INVALID;
2127 DbgFree(cbdata->inst->cluster);
2128 cbdata->inst->cluster = cbdata->cluster;
2130 DbgFree(cbdata->inst->category);
2131 cbdata->inst->category = cbdata->category;
2133 DbgFree(cbdata->cluster);
2134 DbgFree(cbdata->category);
2138 result = packet_create_noack("group_changed", "ssiss",
2139 package_name(cbdata->inst->info), cbdata->inst->id, ret,
2140 cbdata->inst->cluster, cbdata->inst->category);
2142 ErrPrint("Failed to build a packet %s\n", package_name(cbdata->inst->info));
2144 (void)CLIENT_SEND_EVENT(cbdata->inst, result);
2146 instance_unref(cbdata->inst);
2150 HAPI int instance_change_group(struct inst_info *inst, const char *cluster, const char *category)
2152 struct packet *packet;
2153 struct change_group_cbdata *cbdata;
2156 ErrPrint("Invalid instance handle\n");
2157 return LB_STATUS_ERROR_INVALID;
2160 if (package_is_fault(inst->info)) {
2161 DbgPrint("Fault package [%s]\n", package_name(inst->info));
2162 return LB_STATUS_ERROR_FAULT;
2165 cbdata = malloc(sizeof(*cbdata));
2167 ErrPrint("Heap: %s\n", strerror(errno));
2168 return LB_STATUS_ERROR_MEMORY;
2171 cbdata->cluster = strdup(cluster);
2172 if (!cbdata->cluster) {
2173 ErrPrint("Heap: %s\n", strerror(errno));
2175 return LB_STATUS_ERROR_MEMORY;
2178 cbdata->category = strdup(category);
2179 if (!cbdata->category) {
2180 ErrPrint("Heap: %s\n", strerror(errno));
2181 DbgFree(cbdata->cluster);
2183 return LB_STATUS_ERROR_MEMORY;
2186 cbdata->inst = instance_ref(inst);
2188 packet = packet_create("change_group","ssss", package_name(inst->info), inst->id, cluster, category);
2190 ErrPrint("Failed to build a packet for %s\n", package_name(inst->info));
2191 instance_unref(cbdata->inst);
2192 DbgFree(cbdata->category);
2193 DbgFree(cbdata->cluster);
2195 return LB_STATUS_ERROR_FAULT;
2198 return slave_rpc_async_request(package_slave(inst->info), package_name(inst->info), packet, change_group_cb, cbdata, 0);
2201 HAPI const char * const instance_auto_launch(const struct inst_info *inst)
2203 return inst->lb.auto_launch;
2206 HAPI const int const instance_priority(const struct inst_info *inst)
2208 return inst->lb.priority;
2211 HAPI const struct client_node *const instance_client(const struct inst_info *inst)
2213 return inst->client;
2216 HAPI const int const instance_timeout(const struct inst_info *inst)
2218 return inst->lb.timeout;
2221 HAPI const double const instance_period(const struct inst_info *inst)
2223 return inst->lb.period;
2226 HAPI const int const instance_lb_width(const struct inst_info *inst)
2228 return inst->lb.width;
2231 HAPI const int const instance_lb_height(const struct inst_info *inst)
2233 return inst->lb.height;
2236 HAPI const int const instance_pd_width(const struct inst_info *inst)
2238 return inst->pd.width;
2241 HAPI const int const instance_pd_height(const struct inst_info *inst)
2243 return inst->pd.height;
2246 HAPI struct pkg_info *const instance_package(const struct inst_info *inst)
2251 HAPI struct script_info *const instance_lb_script(const struct inst_info *inst)
2253 return (package_lb_type(inst->info) == LB_TYPE_SCRIPT) ? inst->lb.canvas.script : NULL;
2256 HAPI struct script_info *const instance_pd_script(const struct inst_info *inst)
2258 return (package_pd_type(inst->info) == PD_TYPE_SCRIPT) ? inst->pd.canvas.script : NULL;
2261 HAPI struct buffer_info *const instance_lb_buffer(const struct inst_info *inst)
2263 return (package_lb_type(inst->info) == LB_TYPE_BUFFER) ? inst->lb.canvas.buffer : NULL;
2266 HAPI struct buffer_info *const instance_pd_buffer(const struct inst_info *inst)
2268 return (package_pd_type(inst->info) == PD_TYPE_BUFFER) ? inst->pd.canvas.buffer : NULL;
2271 HAPI const char *const instance_id(const struct inst_info *inst)
2276 HAPI const char *const instance_content(const struct inst_info *inst)
2278 return inst->content;
2281 HAPI const char *const instance_category(const struct inst_info *inst)
2283 return inst->category;
2286 HAPI const char *const instance_cluster(const struct inst_info *inst)
2288 return inst->cluster;
2291 HAPI const char * const instance_title(const struct inst_info *inst)
2296 HAPI const double const instance_timestamp(const struct inst_info *inst)
2298 return inst->timestamp;
2301 HAPI const enum instance_state const instance_state(const struct inst_info *inst)
2306 HAPI int instance_destroyed(struct inst_info *inst)
2308 switch (inst->state) {
2310 case INST_REQUEST_TO_ACTIVATE:
2313 * No other clients know the existence of this instance,
2314 * only who added this knows it.
2315 * So send deleted event to only it.
2317 DbgPrint("Send deleted event - unicast - %p\n", inst->client);
2318 instance_unicast_deleted_event(inst, NULL);
2319 instance_state_reset(inst);
2320 instance_destroy(inst);
2322 case INST_REQUEST_TO_REACTIVATE:
2323 case INST_REQUEST_TO_DESTROY:
2324 case INST_ACTIVATED:
2325 DbgPrint("Send deleted event - multicast\n");
2326 instance_broadcast_deleted_event(inst);
2327 instance_state_reset(inst);
2328 instance_destroy(inst);
2329 case INST_DESTROYED:
2332 return LB_STATUS_ERROR_INVALID;
2335 return LB_STATUS_SUCCESS;
2339 * Invoked when a slave is activated
2341 HAPI int instance_recover_state(struct inst_info *inst)
2345 if (inst->changing_state) {
2346 DbgPrint("Doesn't need to recover the state\n");
2347 return LB_STATUS_SUCCESS;
2350 switch (inst->state) {
2351 case INST_ACTIVATED:
2352 case INST_REQUEST_TO_REACTIVATE:
2353 case INST_REQUEST_TO_DESTROY:
2354 switch (inst->requested_state) {
2355 case INST_ACTIVATED:
2356 DbgPrint("Req. to RE-ACTIVATED (%s)\n", package_name(inst->info));
2357 instance_state_reset(inst);
2358 instance_reactivate(inst);
2361 case INST_DESTROYED:
2362 DbgPrint("Req. to DESTROYED (%s)\n", package_name(inst->info));
2363 instance_state_reset(inst);
2364 instance_destroy(inst);
2371 case INST_REQUEST_TO_ACTIVATE:
2372 switch (inst->requested_state) {
2373 case INST_ACTIVATED:
2375 DbgPrint("Req. to ACTIVATED (%s)\n", package_name(inst->info));
2376 instance_state_reset(inst);
2377 if (instance_activate(inst) < 0) {
2378 DbgPrint("Failed to reactivate the instance\n");
2379 instance_broadcast_deleted_event(inst);
2380 instance_state_reset(inst);
2381 instance_destroy(inst);
2386 case INST_DESTROYED:
2387 DbgPrint("Req. to DESTROYED (%s)\n", package_name(inst->info));
2388 instance_state_reset(inst);
2389 instance_destroy(inst);
2396 case INST_DESTROYED:
2405 * Invoked when a slave is deactivated
2407 HAPI int instance_need_slave(struct inst_info *inst)
2411 if (inst->client && client_is_faulted(inst->client)) {
2414 * In this case, the client is faulted(disconnected)
2415 * when the client is deactivated, its liveboxes should be removed too.
2416 * So if the current inst is created by the faulted client,
2417 * remove it and don't try to recover its states
2420 DbgPrint("CLIENT FAULT: Req. to DESTROYED (%s)\n", package_name(inst->info));
2421 switch (inst->state) {
2423 case INST_ACTIVATED:
2424 case INST_REQUEST_TO_REACTIVATE:
2425 case INST_REQUEST_TO_DESTROY:
2426 case INST_REQUEST_TO_ACTIVATE:
2427 instance_state_reset(inst);
2428 instance_destroy(inst);
2430 case INST_DESTROYED:
2434 return LB_STATUS_SUCCESS;
2437 switch (inst->state) {
2438 case INST_ACTIVATED:
2439 case INST_REQUEST_TO_REACTIVATE:
2440 case INST_REQUEST_TO_DESTROY:
2441 switch (inst->requested_state) {
2443 case INST_ACTIVATED:
2444 DbgPrint("Req. to ACTIVATED (%s)\n", package_name(inst->info));
2447 case INST_DESTROYED:
2448 DbgPrint("Req. to DESTROYED (%s)\n", package_name(inst->info));
2449 instance_state_reset(inst);
2450 instance_destroy(inst);
2457 case INST_REQUEST_TO_ACTIVATE:
2458 switch (inst->requested_state) {
2460 case INST_ACTIVATED:
2461 DbgPrint("Req. to ACTIVATED (%s)\n", package_name(inst->info));
2464 case INST_DESTROYED:
2465 DbgPrint("Req. to DESTROYED (%s)\n", package_name(inst->info));
2466 instance_state_reset(inst);
2467 instance_destroy(inst);
2473 case INST_DESTROYED:
2481 HAPI void instance_slave_set_pd_pos(struct inst_info *inst, double x, double y)
2487 HAPI void instance_slave_get_pd_pos(struct inst_info *inst, double *x, double *y)
2495 HAPI int instance_slave_open_pd(struct inst_info *inst, struct client_node *client)
2497 const char *pkgname;
2499 struct packet *packet;
2500 struct slave_node *slave;
2501 const struct pkg_info *info;
2505 client = inst->pd.owner;
2507 ErrPrint("Client is not valid\n");
2508 return LB_STATUS_ERROR_INVALID;
2510 } else if (inst->pd.owner) {
2511 if (inst->pd.owner != client) {
2512 ErrPrint("Client is already owned\n");
2513 return LB_STATUS_ERROR_ALREADY;
2517 slave = package_slave(instance_package(inst));
2519 return LB_STATUS_ERROR_FAULT;
2521 info = instance_package(inst);
2523 return LB_STATUS_ERROR_INVALID;
2525 pkgname = package_name(info);
2526 id = instance_id(inst);
2528 if (!pkgname || !id)
2529 return LB_STATUS_ERROR_INVALID;
2531 packet = packet_create_noack("pd_show", "ssiidd", pkgname, id, instance_pd_width(inst), instance_pd_height(inst), inst->pd.x, inst->pd.y);
2533 ErrPrint("Failed to create a packet\n");
2534 return LB_STATUS_ERROR_FAULT;
2537 slave_freeze_ttl(slave);
2539 ret = slave_rpc_request_only(slave, pkgname, packet, 0);
2543 * If a client is disconnected, the slave has to close the PD
2544 * So the pd_buffer_close_cb/pd_script_close_cb will catch the disconnection event
2545 * then it will send the close request to the slave
2547 if (package_pd_type(info) == PD_TYPE_BUFFER) {
2549 if (client_event_callback_add(client, CLIENT_EVENT_DEACTIVATE, pd_buffer_close_cb, inst) < 0)
2550 instance_unref(inst);
2551 } else if (package_pd_type(info) == PD_TYPE_SCRIPT) {
2553 if (client_event_callback_add(client, CLIENT_EVENT_DEACTIVATE, pd_script_close_cb, inst) < 0)
2554 instance_unref(inst);
2557 inst->pd.owner = client;
2558 DbgPrint("pd,show event is sent\n");
2562 HAPI int instance_slave_close_pd(struct inst_info *inst, struct client_node *client)
2564 const char *pkgname;
2566 struct packet *packet;
2567 struct slave_node *slave;
2568 struct pkg_info *info;
2571 if (inst->pd.owner != client) {
2572 ErrPrint("PD owner is not matched\n");
2573 return LB_STATUS_ERROR_INVALID;
2576 slave = package_slave(instance_package(inst));
2578 return LB_STATUS_ERROR_FAULT;
2580 info = instance_package(inst);
2582 return LB_STATUS_ERROR_INVALID;
2584 pkgname = package_name(info);
2585 id = instance_id(inst);
2587 if (!pkgname || !id)
2588 return LB_STATUS_ERROR_INVALID;
2590 packet = packet_create_noack("pd_hide", "ss", pkgname, id);
2592 ErrPrint("Failed to create a packet\n");
2593 return LB_STATUS_ERROR_FAULT;
2596 slave_thaw_ttl(slave);
2598 ret = slave_rpc_request_only(slave, pkgname, packet, 0);
2599 release_resource_for_closing_pd(info, inst, client);
2600 inst->pd.owner = NULL;
2604 HAPI int instance_client_pd_created(struct inst_info *inst, int status)
2606 struct packet *packet;
2610 if (inst->pd.need_to_send_close_event) {
2611 DbgPrint("PD is already created\n");
2612 return LB_STATUS_ERROR_INVALID;
2615 switch (package_pd_type(inst->info)) {
2616 case PD_TYPE_SCRIPT:
2617 buf_id = fb_id(script_handler_fb(inst->pd.canvas.script));
2619 case PD_TYPE_BUFFER:
2620 buf_id = buffer_handler_id(inst->pd.canvas.buffer);
2628 inst->pd.need_to_send_close_event = (status == 0);
2630 packet = packet_create_noack("pd_created", "sssiii",
2631 package_name(inst->info), inst->id, buf_id,
2632 inst->pd.width, inst->pd.height, status);
2634 ErrPrint("Failed to create a packet\n");
2635 return LB_STATUS_ERROR_FAULT;
2638 ret = CLIENT_SEND_EVENT(inst, packet);
2640 if (inst->pd.need_to_send_close_event && inst->pd.pended_update_cnt) {
2641 DbgPrint("Apply pended desc(%d) - %s\n", inst->pd.pended_update_cnt, inst->pd.pended_update_desc);
2642 instance_pd_updated_by_instance(inst, inst->pd.pended_update_desc);
2643 inst->pd.pended_update_cnt = 0;
2644 DbgFree(inst->pd.pended_update_desc);
2645 inst->pd.pended_update_desc = NULL;
2651 HAPI int instance_client_pd_destroyed(struct inst_info *inst, int status)
2653 if (!inst->pd.need_to_send_close_event) {
2654 DbgPrint("PD is not created\n");
2655 return LB_STATUS_ERROR_INVALID;
2658 inst->pd.need_to_send_close_event = 0;
2660 return send_pd_destroyed_to_client(inst, status);
2663 HAPI int instance_add_client(struct inst_info *inst, struct client_node *client)
2665 if (inst->client == client) {
2666 ErrPrint("Owner cannot be the viewer\n");
2667 return LB_STATUS_ERROR_INVALID;
2670 DbgPrint("%d is added to the list of viewer of %s(%s)\n", client_pid(client), package_name(instance_package(inst)), instance_id(inst));
2671 if (client_event_callback_add(client, CLIENT_EVENT_DEACTIVATE, viewer_deactivated_cb, inst) < 0) {
2672 ErrPrint("Failed to add a deactivate callback\n");
2673 return LB_STATUS_ERROR_FAULT;
2677 inst->client_list = eina_list_append(inst->client_list, client);
2678 return LB_STATUS_SUCCESS;
2681 HAPI int instance_del_client(struct inst_info *inst, struct client_node *client)
2683 if (inst->client == client) {
2684 ErrPrint("Owner is not in the viewer list\n");
2685 return LB_STATUS_ERROR_INVALID;
2688 client_event_callback_del(client, CLIENT_EVENT_DEACTIVATE, viewer_deactivated_cb, inst);
2689 viewer_deactivated_cb(client, inst);
2690 return LB_STATUS_SUCCESS;
2693 HAPI int instance_has_client(struct inst_info *inst, struct client_node *client)
2695 return !!eina_list_data_find(inst->client_list, client);
2698 HAPI void *instance_client_list(struct inst_info *inst)
2700 return inst->client_list;
2703 HAPI void instance_init(void)
2705 if (!strcasecmp(PROVIDER_METHOD, "shm"))
2706 s_info.env_buf_type = BUFFER_TYPE_SHM;
2707 else if (!strcasecmp(PROVIDER_METHOD, "pixmap"))
2708 s_info.env_buf_type = BUFFER_TYPE_PIXMAP;
2711 HAPI void instance_fini(void)