X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Flivebox.c;h=1d64cf5fddbce2b8a5200d3a5f27449a95aec3e5;hb=05d36f9f96a4e22969b54b4b3641e4ad8dd56c5e;hp=19fc45858e4ac8d22793397711c56f5913d5966d;hpb=b6184dd65a39bfdd19a5f04c952da0ee734ccc9d;p=platform%2Fframework%2Fweb%2Flivebox-viewer.git diff --git a/src/livebox.c b/src/livebox.c index 19fc458..1d64cf5 100644 --- a/src/livebox.c +++ b/src/livebox.c @@ -19,7 +19,12 @@ #include /* malloc */ #include /* strdup */ #include +#include +#include +#include +#include +#include #include #include @@ -36,29 +41,53 @@ #include "util.h" #include "master_rpc.h" #include "client.h" -#include "critical_log.h" +#include "conf.h" #define EAPI __attribute__((visibility("default"))) -#define MINIMUM_EVENT s_info.event_filter #if defined(FLOG) FILE *__file_log_fp; #endif +static int default_launch_handler(struct livebox *handler, const char *appid, void *data); + +enum event_state { + INFO_STATE_CALLBACK_IN_IDLE = 0x00, + INFO_STATE_CALLBACK_IN_PROCESSING = 0x01, +}; + static struct info { struct dlist *livebox_list; + struct dlist *livebox_common_list; + struct dlist *event_list; struct dlist *fault_list; + int init_count; int prevent_overwrite; - double event_filter; + enum event_state event_state; + enum event_state fault_state; + guint job_timer; + struct dlist *job_list; + + struct launch { + int (*handler)(struct livebox *handler, const char *appid, void *data); + void *data; + } launch; } s_info = { .livebox_list = NULL, .event_list = NULL, .fault_list = NULL, .init_count = 0, .prevent_overwrite = 0, - .event_filter = 0.02f, + .event_state = INFO_STATE_CALLBACK_IN_IDLE, + .fault_state = INFO_STATE_CALLBACK_IN_IDLE, + .job_timer = 0, + .job_list = NULL, + .launch = { + .handler = default_launch_handler, + .data = NULL, + }, }; struct cb_info { @@ -67,15 +96,47 @@ struct cb_info { }; struct event_info { + int is_deleted; int (*handler)(struct livebox *handler, enum livebox_event_type event, void *data); void *user_data; }; struct fault_info { + int is_deleted; int (*handler)(enum livebox_fault_type event, const char *pkgname, const char *filename, const char *func, void *data); void *user_data; }; +static void lb_pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data); +static void pd_pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data); + +static int default_launch_handler(struct livebox *handler, const char *appid, void *data) +{ + int ret; + + ret = aul_launch_app(appid, NULL); + if (ret <= 0) { + ErrPrint("Failed to launch an app %s (%d)\n", appid, ret); + } + +/* + service_h service; + + DbgPrint("AUTO_LAUNCH [%s]\n", handler->common->lb.auto_launch); + + ret = service_create(&service); + if (ret == SERVICE_ERROR_NONE) { + service_set_package(service, handler->common->lb.auto_launch); + service_send_launch_request(service, NULL, NULL); + service_destroy(service); + } else { + ErrPrint("Failed to launch an app %s (%d)\n", handler->common->lb.auto_launch, ret); + } +*/ + + return ret > 0 ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_FAULT; +} + static inline void default_create_cb(struct livebox *handler, int ret, void *data) { DbgPrint("Default created event handler: %d\n", ret); @@ -126,13 +187,18 @@ static inline void default_access_event_cb(struct livebox *handler, int ret, voi DbgPrint("Default access event handler: %d\n", ret); } +static inline void default_key_event_cb(struct livebox *handler, int ret, void *data) +{ + DbgPrint("Default key event handler: %d\n", ret); +} + static inline __attribute__((always_inline)) struct cb_info *create_cb_info(ret_cb_t cb, void *data) { struct cb_info *info; info = malloc(sizeof(*info)); if (!info) { - CRITICAL_LOG("Heap: %s\n", strerror(errno)); + ErrPrint("Heap: %s\n", strerror(errno)); return NULL; } @@ -146,6 +212,126 @@ static inline void destroy_cb_info(struct cb_info *info) free(info); } +static int do_fb_lock(int fd) +{ + struct flock flock; + int ret; + + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = getpid(); + + do { + ret = fcntl(fd, F_SETLKW, &flock); + if (ret < 0) { + ret = errno; + ErrPrint("fcntl: %s\n", strerror(errno)); + } + } while (ret == EINTR); + + return ret; +} + +static int do_fb_unlock(int fd) +{ + struct flock flock; + int ret; + + flock.l_type = F_UNLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = getpid(); + + do { + ret = fcntl(fd, F_SETLKW, &flock); + if (ret < 0) { + ret = errno; + ErrPrint("fcntl: %s\n", strerror(errno)); + } + } while (ret == EINTR); + + return ret; +} + +int lb_destroy_lock_file(struct livebox_common *common, int is_pd) +{ + if (is_pd) { + if (!common->pd.lock) { + return LB_STATUS_ERROR_INVALID; + } + + if (close(common->pd.lock_fd) < 0) { + ErrPrint("close: %s\n", strerror(errno)); + } + common->pd.lock_fd = -1; + + if (unlink(common->pd.lock) < 0) { + ErrPrint("unlink: %s\n", strerror(errno)); + } + + free(common->pd.lock); + common->pd.lock = NULL; + } else { + if (!common->lb.lock) { + return LB_STATUS_ERROR_INVALID; + } + + if (close(common->lb.lock_fd) < 0) { + ErrPrint("close: %s\n", strerror(errno)); + } + common->lb.lock_fd = -1; + + if (unlink(common->lb.lock) < 0) { + ErrPrint("unlink: %s\n", strerror(errno)); + } + + free(common->lb.lock); + common->lb.lock = NULL; + } + + return LB_STATUS_SUCCESS; +} + +int lb_create_lock_file(struct livebox_common *common, int is_pd) +{ + int len; + char *file; + + len = strlen(common->id); + file = malloc(len + 20); + if (!file) { + ErrPrint("Heap: %s\n", strerror(errno)); + return LB_STATUS_ERROR_MEMORY; + } + + snprintf(file, len + 20, "%s.%s.lck", util_uri_to_path(common->id), is_pd ? "pd" : "lb"); + + if (is_pd) { + common->pd.lock_fd = open(file, O_RDONLY); + if (common->pd.lock_fd < 0) { + ErrPrint("open: %s\n", strerror(errno)); + free(file); + return LB_STATUS_ERROR_IO; + } + + common->pd.lock = file; + } else { + common->lb.lock_fd = open(file, O_RDONLY); + if (common->lb.lock_fd < 0) { + ErrPrint("open: %s\n", strerror(errno)); + free(file); + return LB_STATUS_ERROR_IO; + } + + common->lb.lock = file; + } + + return LB_STATUS_SUCCESS; +} + static void update_mode_cb(struct livebox *handler, const struct packet *result, void *data) { int ret; @@ -160,29 +346,27 @@ static void update_mode_cb(struct livebox *handler, const struct packet *result, } if (ret < 0) { - DbgPrint("Resize request is failed: %d\n", ret); + ErrPrint("Resize request is failed: %d\n", ret); goto errout; } return; errout: - handler->update_mode_cb(handler, ret, handler->update_mode_cbdata); - handler->update_mode_cb = NULL; - handler->update_mode_cbdata = NULL; - return; + handler->cbs.update_mode.cb(handler, ret, handler->cbs.update_mode.data); + handler->cbs.update_mode.cb = NULL; + handler->cbs.update_mode.data = NULL; + handler->common->request.update_mode = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void resize_cb(struct livebox *handler, const struct packet *result, void *data) { int ret; - struct cb_info *info = data; - ret_cb_t cb; - void *cbdata; - - cb = info->cb; - cbdata = info->data; - destroy_cb_info(info); if (!result) { ret = LB_STATUS_ERROR_FAULT; @@ -203,17 +387,22 @@ static void resize_cb(struct livebox *handler, const struct packet *result, void * after this request. */ if (ret < 0) { - DbgPrint("Resize request is failed: %d\n", ret); + ErrPrint("Resize request is failed: %d\n", ret); goto errout; } - DbgPrint("Resize request is successfully sent\n"); return; errout: - handler->size_changed_cb(handler, ret, handler->size_cbdata); - handler->size_changed_cb = NULL; - handler->size_cbdata = NULL; + handler->cbs.size_changed.cb(handler, ret, handler->cbs.size_changed.data); + handler->cbs.size_changed.cb = NULL; + handler->cbs.size_changed.data = NULL; + handler->common->request.size_changed = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void text_signal_cb(struct livebox *handler, const struct packet *result, void *data) @@ -234,8 +423,9 @@ static void text_signal_cb(struct livebox *handler, const struct packet *result, ret = LB_STATUS_ERROR_INVALID; } - if (cb) + if (cb) { cb(handler, ret, cbdata); + } return; } @@ -252,15 +442,22 @@ static void set_group_ret_cb(struct livebox *handler, const struct packet *resul goto errout; } - if (ret < 0) + if (ret < 0) { goto errout; + } return; errout: - handler->group_changed_cb(handler, ret, handler->group_cbdata); - handler->group_changed_cb = NULL; - handler->group_cbdata = NULL; + handler->cbs.group_changed.cb(handler, ret, handler->cbs.group_changed.data); + handler->cbs.group_changed.cb = NULL; + handler->cbs.group_changed.data = NULL; + handler->common->request.group_changed = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void period_ret_cb(struct livebox *handler, const struct packet *result, void *data) @@ -276,16 +473,22 @@ static void period_ret_cb(struct livebox *handler, const struct packet *result, goto errout; } - if (ret < 0) + if (ret < 0) { goto errout; + } - DbgPrint("Succeed to send period change request, waiting result\n"); return; errout: - handler->period_changed_cb(handler, ret, handler->period_cbdata); - handler->period_changed_cb = NULL; - handler->period_cbdata = NULL; + handler->cbs.period_changed.cb(handler, ret, handler->cbs.period_changed.data); + handler->cbs.period_changed.cb = NULL; + handler->cbs.period_changed.data = NULL; + handler->common->request.period_changed = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void del_ret_cb(struct livebox *handler, const struct packet *result, void *data) @@ -308,9 +511,8 @@ static void del_ret_cb(struct livebox *handler, const struct packet *result, voi } if (ret == 0) { - DbgPrint("Returns %d (waiting deleted event)\n", ret); - handler->deleted_cb = cb; - handler->deleted_cbdata = cbdata; + handler->cbs.deleted.cb = cb; + handler->cbs.deleted.data = cbdata; } else if (cb) { cb(handler, ret, cbdata); } @@ -321,8 +523,8 @@ static void del_ret_cb(struct livebox *handler, const struct packet *result, voi * master will send the "deleted" event. * Then invoke this callback. * - * if (handler->deleted_cb) - * handler->deleted_cb(handler, ret, handler->deleted_cbdata); + * if (handler->cbs.deleted.cb) + * handler->cbs.deleted.cb(handler, ret, handler->cbs.deleted.data); */ } @@ -344,9 +546,8 @@ static void new_ret_cb(struct livebox *handler, const struct packet *result, voi } if (ret >= 0) { - DbgPrint("new request is sent, just waiting the created event\n"); - handler->created_cb = cb; - handler->created_cbdata = cbdata; + handler->cbs.created.cb = cb; + handler->cbs.created.data = cbdata; /*! * \note @@ -363,7 +564,7 @@ static void new_ret_cb(struct livebox *handler, const struct packet *result, voi cb(handler, ret, cbdata); } - lb_unref(handler); + lb_unref(handler, 1); } static void pd_create_cb(struct livebox *handler, const struct packet *result, void *data) @@ -379,16 +580,22 @@ static void pd_create_cb(struct livebox *handler, const struct packet *result, v } if (ret < 0) { - DbgPrint("Failed to create a PD\n"); + ErrPrint("Failed to create a PD[%d]\n", ret); goto errout; } return; errout: - handler->pd_created_cb(handler, ret, handler->pd_created_cbdata); - handler->pd_created_cb = NULL; - handler->pd_created_cbdata = NULL; + handler->cbs.pd_created.cb(handler, ret, handler->cbs.pd_created.data); + handler->cbs.pd_created.cb = NULL; + handler->cbs.pd_created.data = NULL; + handler->common->request.pd_created = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void activated_cb(struct livebox *handler, const struct packet *result, void *data) @@ -409,8 +616,9 @@ static void activated_cb(struct livebox *handler, const struct packet *result, v ret = LB_STATUS_ERROR_INVALID; } - if (cb) + if (cb) { cb(handler, ret, cbdata); + } } static void pd_destroy_cb(struct livebox *handler, const struct packet *result, void *data) @@ -425,21 +633,23 @@ static void pd_destroy_cb(struct livebox *handler, const struct packet *result, destroy_cb_info(info); if (!result) { - DbgPrint("Result is NIL (may connection lost)\n"); + ErrPrint("Result is NIL (may connection lost)\n"); ret = LB_STATUS_ERROR_FAULT; } else if (packet_get(result, "i", &ret) != 1) { - DbgPrint("Invalid parameter\n"); + ErrPrint("Invalid parameter\n"); ret = LB_STATUS_ERROR_INVALID; } - if (ret == 0) { - DbgPrint("PD Destroyed callback prepared\n"); - handler->pd_destroyed_cb = cb; - handler->pd_destroyed_cbdata = cbdata; - } else if (cb) { - DbgPrint("PD is not desroyed (forcely reset, pd flag)\n"); - handler->is_pd_created = 0; - cb(handler, ret, cbdata); + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.pd_destroyed.cb = cb; + handler->cbs.pd_destroyed.data = cbdata; + } else { + handler->common->is_pd_created = 0; + handler->common->request.pd_destroyed = 0; + + if (cb) { + cb(handler, ret, cbdata); + } } } @@ -460,10 +670,9 @@ static void delete_cluster_cb(struct livebox *handler, const struct packet *resu ret = LB_STATUS_ERROR_INVALID; } - DbgPrint("Delete category returns: %d\n", ret); - - if (cb) + if (cb) { cb(handler, ret, cbdata); + } } static void delete_category_cb(struct livebox *handler, const struct packet *result, void *data) @@ -477,19 +686,124 @@ static void delete_category_cb(struct livebox *handler, const struct packet *res cbdata = info->data; destroy_cb_info(info); - if (!result) + if (!result) { ret = LB_STATUS_ERROR_FAULT; - else if (packet_get(result, "i", &ret) != 1) + } else if (packet_get(result, "i", &ret) != 1) { ret = LB_STATUS_ERROR_INVALID; + } - DbgPrint("Delete category returns: %d\n", ret); - - if (cb) + if (cb) { cb(handler, ret, cbdata); + } +} + +static int lb_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *data) +{ + struct packet *packet; + struct cb_info *cbinfo; + const char *id; + int ret; + + id = fb_id(handler->common->lb.fb); + if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) { + return LB_STATUS_ERROR_INVALID; + } + + packet = packet_create("lb_acquire_pixmap", "ss", handler->common->pkgname, handler->common->id); + if (!packet) { + ErrPrint("Failed to build a param\n"); + return LB_STATUS_ERROR_FAULT; + } + + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + packet_destroy(packet); + return LB_STATUS_ERROR_FAULT; + } + + ret = master_rpc_async_request(handler, packet, 0, lb_pixmap_acquired_cb, cbinfo); + if (ret < 0) { + destroy_cb_info(cbinfo); + } + + return ret; +} + +static void lb_pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data) +{ + int pixmap; + int ret = LB_STATUS_ERROR_INVALID; + ret_cb_t cb; + void *cbdata; + struct cb_info *info = data; + + cb = info->cb; + cbdata = info->data; + destroy_cb_info(info); + + if (!result) { + pixmap = 0; /* PIXMAP 0 means error */ + } else if (packet_get(result, "ii", &pixmap, &ret) != 2) { + pixmap = 0; + } + + if (ret == (int)LB_STATUS_ERROR_BUSY) { + ret = lb_acquire_lb_pixmap(handler, cb, cbdata); + DbgPrint("Busy, Try again: %d\n", ret); + /* Try again */ + } else if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + if (cb) { + cb(handler, pixmap, cbdata); + } + + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } else { + if (cb) { + cb(handler, pixmap, cbdata); + } + } +} + +static int lb_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *data) +{ + struct packet *packet; + struct cb_info *cbinfo; + const char *id; + int ret; + + id = fb_id(handler->common->pd.fb); + if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) { + return LB_STATUS_ERROR_INVALID; + } + + packet = packet_create("pd_acquire_pixmap", "ss", handler->common->pkgname, handler->common->id); + if (!packet) { + ErrPrint("Failed to build a param\n"); + return LB_STATUS_ERROR_FAULT; + } + + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + packet_destroy(packet); + return LB_STATUS_ERROR_FAULT; + } + + ret = master_rpc_async_request(handler, packet, 0, pd_pixmap_acquired_cb, cbinfo); + if (ret < 0) { + /*! + * \note + * Packet will be destroyed by master_rpc_async_request + */ + destroy_cb_info(cbinfo); + } + + return ret; } -static void pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data) +static void pd_pixmap_acquired_cb(struct livebox *handler, const struct packet *result, void *data) { + int pixmap; int ret; ret_cb_t cb; void *cbdata; @@ -499,13 +813,30 @@ static void pixmap_acquired_cb(struct livebox *handler, const struct packet *res cbdata = info->data; destroy_cb_info(info); - if (!result) - ret = 0; /* PIXMAP 0 means error */ - else if (packet_get(result, "i", &ret) != 1) - ret = 0; + if (!result) { + pixmap = 0; /* PIXMAP 0 means error */ + ret = LB_STATUS_ERROR_FAULT; + } else if (packet_get(result, "ii", &pixmap, &ret) != 2) { + pixmap = 0; + ret = LB_STATUS_ERROR_INVALID; + } - if (cb) - cb(handler, ret, cbdata); + if (ret == (int)LB_STATUS_ERROR_BUSY) { + ret = lb_acquire_pd_pixmap(handler, cb, cbdata); + DbgPrint("Busy, Try again: %d\n", ret); + /* Try again */ + } else if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + if (cb) { + cb(handler, pixmap, cbdata); + } + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } else { + if (cb) { + DbgPrint("ret: %d, pixmap: %d\n", ret, pixmap); + cb(handler, pixmap, cbdata); + } + } } static void pinup_done_cb(struct livebox *handler, const struct packet *result, void *data) @@ -519,15 +850,53 @@ static void pinup_done_cb(struct livebox *handler, const struct packet *result, goto errout; } - if (ret < 0) + if (ret < 0) { goto errout; + } return; errout: - handler->pinup_cb(handler, ret, handler->pinup_cbdata); - handler->pinup_cb = NULL; - handler->pinup_cbdata = NULL; + handler->cbs.pinup.cb(handler, ret, handler->cbs.pinup.data); + handler->cbs.pinup.cb = NULL; + handler->cbs.pinup.data = NULL; + handler->common->request.pinup = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } +} + +static void key_ret_cb(struct livebox *handler, const struct packet *result, void *data) +{ + int ret; + + if (!result) { + ret = LB_STATUS_ERROR_FAULT; + return; + } + + if (packet_get(result, "i", &ret) != 1) { + ret = LB_STATUS_ERROR_INVALID; + return; + } + + if (ret != LB_STATUS_SUCCESS) { + goto errout; + } + + return; +errout: + handler->cbs.key_event.cb(handler, ret, handler->cbs.key_event.data); + handler->cbs.key_event.cb = NULL; + handler->cbs.key_event.data = NULL; + handler->common->request.key_event = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static void access_ret_cb(struct livebox *handler, const struct packet *result, void *data) @@ -548,14 +917,18 @@ static void access_ret_cb(struct livebox *handler, const struct packet *result, goto errout; } - DbgPrint("Access event is successfully sent. waiting result\n"); return; errout: - handler->access_event_cb(handler, ret, handler->access_event_cbdata); - handler->access_event_cb = NULL; - handler->access_event_cbdata = NULL; - return; + handler->cbs.access_event.cb(handler, ret, handler->cbs.access_event.data); + handler->cbs.access_event.cb = NULL; + handler->cbs.access_event.data = NULL; + handler->common->request.access_event = 0; + + if (ret == (int)LB_STATUS_ERROR_NOT_EXIST && handler->refcnt == 2) { + lb_invoke_event_handler(handler, LB_EVENT_DELETED); + lb_unref(handler, 1); + } } static int send_access_event(struct livebox *handler, const char *event, int x, int y) @@ -565,84 +938,124 @@ static int send_access_event(struct livebox *handler, const char *event, int x, timestamp = util_timestamp(); - packet = packet_create(event, "ssdii", handler->pkgname, handler->id, timestamp, x, y); + packet = packet_create(event, "ssdii", handler->common->pkgname, handler->common->id, timestamp, x, y); if (!packet) { ErrPrint("Failed to build packet\n"); return LB_STATUS_ERROR_FAULT; } - DbgPrint("Send: %dx%d\n", x, y); - return master_rpc_async_request(handler, packet, 0, access_ret_cb, NULL); } +static int send_key_event(struct livebox *handler, const char *event, unsigned int keycode) +{ + struct packet *packet; + double timestamp; + + timestamp = util_timestamp(); + packet = packet_create(event, "ssdi", handler->common->pkgname, handler->common->id, timestamp, keycode); + if (!packet) { + ErrPrint("Failed to build packet\n"); + return LB_STATUS_ERROR_FAULT; + } + + return master_rpc_async_request(handler, packet, 0, key_ret_cb, NULL); +} + static int send_mouse_event(struct livebox *handler, const char *event, int x, int y) { struct packet *packet; double timestamp; timestamp = util_timestamp(); - packet = packet_create_noack(event, "ssdii", handler->pkgname, handler->id, timestamp, x, y); + packet = packet_create_noack(event, "ssdii", handler->common->pkgname, handler->common->id, timestamp, x, y); if (!packet) { ErrPrint("Failed to build param\n"); return LB_STATUS_ERROR_FAULT; } - DbgPrint("Send: %dx%d\n", x, y); - return master_rpc_request_only(handler, packet); } -EAPI int livebox_init(void *disp) +static void initialize_livebox(void *disp, int use_thread) { - const char *env; - - if (s_info.init_count > 0) { - s_info.init_count++; - return LB_STATUS_SUCCESS; - } - env = getenv("PROVIDER_DISABLE_PREVENT_OVERWRITE"); - if (env && !strcasecmp(env, "true")) - s_info.prevent_overwrite = 1; - - env = getenv("PROVIDER_EVENT_FILTER"); - if (env) - sscanf(env, "%lf", &MINIMUM_EVENT); - #if defined(FLOG) char filename[BUFSIZ]; snprintf(filename, sizeof(filename), "/tmp/%d.box.log", getpid()); __file_log_fp = fopen(filename, "w+t"); - if (!__file_log_fp) + if (!__file_log_fp) { __file_log_fp = fdopen(1, "w+t"); + } #endif - critical_log_init("viewer"); livebox_service_init(); fb_init(disp); - client_init(); + client_init(use_thread); s_info.init_count++; +} + +EAPI int livebox_init_with_options(void *disp, int prevent_overwrite, double event_filter, int use_thread) +{ + if (s_info.init_count > 0) { + s_info.init_count++; + return LB_STATUS_SUCCESS; + } + + /*! + * \note + * Some application doesn't want to use the environment value. + * So set them using arguments. + */ + s_info.prevent_overwrite = prevent_overwrite; + conf_set_event_filter(event_filter); + + initialize_livebox(disp, use_thread); + return LB_STATUS_SUCCESS; +} + +EAPI int livebox_init(void *disp) +{ + const char *env; + + if (s_info.init_count > 0) { + s_info.init_count++; + return LB_STATUS_SUCCESS; + } + + env = getenv("PROVIDER_DISABLE_PREVENT_OVERWRITE"); + if (env && !strcasecmp(env, "true")) { + s_info.prevent_overwrite = 1; + } + + env = getenv("PROVIDER_EVENT_FILTER"); + if (env) { + double event_filter; + if (sscanf(env, "%lf", &event_filter) == 1) { + conf_set_event_filter(event_filter); + } + } + + initialize_livebox(disp, 0); return LB_STATUS_SUCCESS; } EAPI int livebox_fini(void) { if (s_info.init_count <= 0) { - DbgPrint("Didn't initialized\n"); + ErrPrint("Doesn't initialized\n"); return LB_STATUS_ERROR_INVALID; } s_info.init_count--; if (s_info.init_count > 0) { - DbgPrint("init count : %d\n", s_info.init_count); + ErrPrint("init count : %d\n", s_info.init_count); return LB_STATUS_SUCCESS; } client_fini(); fb_fini(); livebox_service_fini(); - critical_log_fini(); return LB_STATUS_SUCCESS; } @@ -652,13 +1065,92 @@ static inline char *lb_pkgname(const char *pkgname) lb = livebox_service_pkgname(pkgname); if (!lb) { - if (util_validate_livebox_package(pkgname) == 0) + if (util_validate_livebox_package(pkgname) == 0) { return strdup(pkgname); + } } return lb; } +static struct livebox_common *find_sharable_common_handle(const char *pkgname, const char *content, int w, int h, const char *cluster, const char *category) +{ + struct dlist *l; + struct livebox_common *common; + + if (!conf_shared_content()) { + /*! + * Shared content option is turnned off. + */ + return NULL; + } + + dlist_foreach(s_info.livebox_common_list, l, common) { + if (common->state != CREATE) { + continue; + } + + if (strcmp(common->pkgname, pkgname)) { + continue; + } + + if (strcmp(common->cluster, cluster)) { + DbgPrint("Cluster mismatched\n"); + continue; + } + + if (strcmp(common->category, category)) { + DbgPrint("Category mismatched\n"); + continue; + } + + if (common->content && content) { + if (strcmp(common->content, content)) { + DbgPrint("%s Content ([%s] <> [%s])\n", common->pkgname, common->content, content); + continue; + } + } else { + int c1_len; + int c2_len; + + /*! + * \note + * We assumes "" (ZERO length string) to NULL + */ + c1_len = common->content ? strlen(common->content) : 0; + c2_len = content ? strlen(content) : 0; + if (c1_len != c2_len) { + DbgPrint("%s Content %p <> %p\n", common->pkgname, common->content, content); + continue; + } + } + + if (common->request.size_changed) { + DbgPrint("Changing size\n"); + /*! + * \note + * Do not re-use resizing instance. + * We will not use predicted size. + */ + continue; + } + + if (common->request.created) { + DbgPrint("Creating now but re-use it (%s)\n", common->pkgname); + } + + if (common->lb.width != w || common->lb.height != h) { + DbgPrint("Size mismatched\n"); + continue; + } + + DbgPrint("common handle is found: %p\n", common); + return common; + } + + return NULL; +} + /*! * Just wrapping the livebox_add_with_size function. */ @@ -667,142 +1159,441 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const return livebox_add_with_size(pkgname, content, cluster, category, period, LB_SIZE_TYPE_UNKNOWN, cb, data); } -EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *content, const char *cluster, const char *category, double period, int type, ret_cb_t cb, void *data) +static gboolean job_execute_cb(void *data) { - struct livebox *handler; + struct job_item *item; + struct dlist *l; + + l = dlist_nth(s_info.job_list, 0); + if (!l) { + s_info.job_timer = 0; + return FALSE; + } + + item = dlist_data(l); + s_info.job_list = dlist_remove(s_info.job_list, l); + + if (item) { + item->cb(item->handle, item->ret, item->data); + lb_unref(item->handle, 1); + free(item); + } + + return TRUE; +} + +static int job_add(struct livebox *handle, ret_cb_t job_cb, int ret, void *data) +{ + struct job_item *item; + + if (!job_cb) { + ErrPrint("Invalid argument\n"); + return LB_STATUS_ERROR_INVALID; + } + + item = malloc(sizeof(*item)); + if (!item) { + ErrPrint("Heap: %s\n", strerror(errno)); + return LB_STATUS_ERROR_MEMORY; + } + + item->handle = lb_ref(handle); + item->cb = job_cb; + item->data = data; + item->ret = ret; + + s_info.job_list = dlist_append(s_info.job_list, item); + + if (!s_info.job_timer) { + s_info.job_timer = g_timeout_add(1, job_execute_cb, NULL); + if (!s_info.job_timer) { + ErrPrint("Failed to create a job timer\n"); + } + } + + return LB_STATUS_SUCCESS; +} + +static int create_real_instance(struct livebox *handler, ret_cb_t cb, void *data) +{ + struct cb_info *cbinfo; struct packet *packet; + struct livebox_common *common; int ret; - int width = 0; - int height = 0; - struct cb_info *cbinfo; - if (!pkgname || !cluster || !category) { - ErrPrint("Invalid arguments: pkgname[%p], cluster[%p], category[%p]\n", - pkgname, cluster, category); - return NULL; + common = handler->common; + + packet = packet_create("new", "dssssdii", + common->timestamp, common->pkgname, common->content, + common->cluster, common->category, + common->lb.period, common->lb.width, common->lb.height); + if (!packet) { + ErrPrint("Failed to create a new packet\n"); + return LB_STATUS_ERROR_FAULT; } - if (type != LB_SIZE_TYPE_UNKNOWN) - livebox_service_get_size(type, &width, &height); + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + ErrPrint("Failed to create a cbinfo\n"); + packet_destroy(packet); + return LB_STATUS_ERROR_MEMORY; + } - handler = calloc(1, sizeof(*handler)); - if (!handler) { - ErrPrint("Error: %s\n", strerror(errno)); - return NULL; + /*! + * \note + * master_rpc_async_request will destroy the packet (decrease the refcnt) + * So be aware the packet object after return from master_rpc_async_request. + */ + ret = master_rpc_async_request(handler, packet, 0, new_ret_cb, cbinfo); + if (ret < 0) { + ErrPrint("Failed to send a new packet\n"); + destroy_cb_info(cbinfo); + return LB_STATUS_ERROR_FAULT; } + handler->common->request.created = 1; + return LB_STATUS_SUCCESS; +} - handler->pkgname = lb_pkgname(pkgname); - if (!handler->pkgname) { - free(handler); - return NULL; +static void create_cb(struct livebox *handle, int ret, void *data) +{ + struct cb_info *cbinfo = data; + + if (cbinfo->cb) { + cbinfo->cb(handle, ret, cbinfo->data); } - if (livebox_service_is_enabled(handler->pkgname) == 0) { - DbgPrint("Livebox [%s](%s) is disabled package\n", handler->pkgname, pkgname); - free(handler->pkgname); - free(handler); + destroy_cb_info(cbinfo); + + /*! + * \note + * Forcely generate "updated" event + */ + lb_invoke_event_handler(handle, LB_EVENT_LB_UPDATED); +} + +static int create_fake_instance(struct livebox *handler, ret_cb_t cb, void *data) +{ + struct cb_info *cbinfo; + + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + ErrPrint("Failed to create a cbinfo\n"); + return LB_STATUS_ERROR_MEMORY; + } + + if (job_add(handler, create_cb, LB_STATUS_SUCCESS, cbinfo) != LB_STATUS_SUCCESS) { + destroy_cb_info(cbinfo); + } + + return LB_STATUS_SUCCESS; +} + +struct livebox_common *lb_create_common_handle(struct livebox *handle, const char *pkgname, const char *cluster, const char *category) +{ + struct livebox_common *common; + + common = calloc(1, sizeof(*common)); + if (!common) { + ErrPrint("Heap: %s\n", strerror(errno)); return NULL; } - if (content) { - handler->content = strdup(content); - if (!handler->content) { - ErrPrint("Error: %s\n", strerror(errno)); - free(handler->pkgname); - free(handler); - return NULL; - } - } else { - handler->content = livebox_service_content(handler->pkgname); + common->pkgname = strdup(pkgname); + if (!common->pkgname) { + free(common); + return NULL; } - handler->cluster = strdup(cluster); - if (!handler->cluster) { + common->cluster = strdup(cluster); + if (!common->cluster) { ErrPrint("Error: %s\n", strerror(errno)); - free(handler->content); - free(handler->pkgname); - free(handler); + free(common->pkgname); + free(common); return NULL; } - handler->category = strdup(category); - if (!handler->category) { + common->category = strdup(category); + if (!common->category) { ErrPrint("Error: %s\n", strerror(errno)); - free(handler->cluster); - free(handler->content); - free(handler->pkgname); - free(handler); + free(common->cluster); + free(common->pkgname); + free(common); return NULL; } - if (!cb) - cb = default_create_cb; - /* Data provider will set this */ - handler->lb.type = _LB_TYPE_FILE; - handler->pd.type = _PD_TYPE_SCRIPT; - handler->lb.period = period; + common->lb.type = _LB_TYPE_FILE; + common->pd.type = _PD_TYPE_SCRIPT; /* Used for handling the mouse event on a box */ - handler->lb.mouse_event = livebox_service_mouse_event(handler->pkgname); + common->lb.mouse_event = livebox_service_mouse_event(common->pkgname); /* Cluster infomration is not determined yet */ - handler->nr_of_sizes = 0x01; + common->nr_of_sizes = 0x01; - handler->timestamp = util_timestamp(); - handler->is_user = 1; - handler->visible = LB_SHOW; + common->timestamp = util_timestamp(); + common->is_user = 1; + common->delete_type = LB_DELETE_PERMANENTLY; + common->pd.lock = NULL; + common->pd.lock_fd = -1; + common->lb.lock = NULL; + common->lb.lock_fd = -1; - s_info.livebox_list = dlist_append(s_info.livebox_list, handler); + common->state = CREATE; + common->visible = LB_SHOW; + + s_info.livebox_common_list = dlist_append(s_info.livebox_common_list, common); + return common; +} + +int lb_destroy_common_handle(struct livebox_common *common) +{ + dlist_remove_data(s_info.livebox_common_list, common); - packet = packet_create("new", "dssssdii", handler->timestamp, handler->pkgname, handler->content, cluster, category, period, width, height); + common->state = DESTROYED; + + if (common->filename) { + (void)util_unlink(common->filename); + } + + free(common->cluster); + free(common->category); + free(common->id); + free(common->pkgname); + free(common->filename); + free(common->lb.auto_launch); + free(common->alt.icon); + free(common->alt.name); + + if (common->lb.fb) { + fb_destroy(common->lb.fb); + common->lb.fb = NULL; + } + + if (common->pd.fb) { + fb_destroy(common->pd.fb); + common->pd.fb = NULL; + } + + return 0; +} + +int lb_common_ref(struct livebox_common *common, struct livebox *handle) +{ + common->livebox_list = dlist_append(common->livebox_list, handle); + common->refcnt++; + + return common->refcnt; +} + +int lb_common_unref(struct livebox_common *common, struct livebox *handle) +{ + int refcnt; + dlist_remove_data(common->livebox_list, handle); + refcnt = --common->refcnt; + + return refcnt; +} + +static void refresh_for_paused_updating_cb(struct livebox *handle, int ret, void *data) +{ + if (handle->paused_updating == 0) { + DbgPrint("Paused updates are cleared\n"); + return; + } + + DbgPrint("Pending updates are found\n"); + lb_invoke_event_handler(handle, LB_EVENT_LB_UPDATED); +} + +static int lb_set_visibility(struct livebox *handler, enum livebox_visible_state state) +{ + struct packet *packet; + int need_to_add_job = 0; + int ret; + + if (handler->common->visible != LB_SHOW && state == (int)LB_SHOW) { + need_to_add_job = !!handler->paused_updating; + } else if (handler->common->visible == (int)LB_SHOW && state != LB_SHOW) { + struct dlist *l; + struct livebox *item; + + dlist_foreach(handler->common->livebox_list, l, item) { + if (item->visible == (int)LB_SHOW) { + DbgPrint("%s visibility is not changed\n", handler->common->pkgname); + return LB_STATUS_SUCCESS; + } + } + } else if (handler->common->visible == (int)LB_SHOW && state == (int)LB_SHOW && handler->paused_updating) { + if (job_add(handler, refresh_for_paused_updating_cb, LB_STATUS_SUCCESS, NULL) < 0) { + ErrPrint("Unable to add a new job for refreshing box\n"); + } + + return LB_STATUS_SUCCESS; + } else { + /*! + * \brief + * No need to send this to the master + */ + return LB_STATUS_SUCCESS; + } + + packet = packet_create_noack("change,visibility", "ssi", handler->common->pkgname, handler->common->id, (int)state); if (!packet) { - ErrPrint("Failed to create a new packet\n"); - free(handler->category); - free(handler->cluster); - free(handler->content); - free(handler->pkgname); - free(handler); + ErrPrint("Failed to create a packet\n"); + return LB_STATUS_ERROR_FAULT; + } + + ret = master_rpc_request_only(handler, packet); + if (ret == (int)LB_STATUS_SUCCESS) { + DbgPrint("[%s] visibility is changed 0x[%x]\n", handler->common->pkgname, state); + handler->common->visible = state; + + if (need_to_add_job) { + if (job_add(handler, refresh_for_paused_updating_cb, LB_STATUS_SUCCESS, NULL) < 0) { + ErrPrint("Unable to add a new job for refreshing box\n"); + } + } + } + + return ret; +} + +EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *content, const char *cluster, const char *category, double period, int type, ret_cb_t cb, void *data) +{ + char *lbid; + struct livebox *handler; + int w = 0; + int h = 0; + + if (!pkgname || !cluster || !category) { + ErrPrint("Invalid arguments: pkgname[%p], cluster[%p], category[%p]\n", + pkgname, cluster, category); return NULL; } - cbinfo = create_cb_info(cb, data); - if (!cbinfo) { - ErrPrint("Failed to create a cbinfo\n"); - packet_destroy(packet); - free(handler->category); - free(handler->cluster); - free(handler->content); - free(handler->pkgname); - free(handler); + lbid = lb_pkgname(pkgname); + if (!lbid) { + ErrPrint("Invalid package: %s\n", pkgname); + return NULL; + } + + if (livebox_service_is_enabled(lbid) == 0) { + DbgPrint("Livebox [%s](%s) is disabled package\n", lbid, pkgname); + free(lbid); + return NULL; + } + + if (type != LB_SIZE_TYPE_UNKNOWN) { + (void)livebox_service_get_size(type, &w, &h); + } + + handler = calloc(1, sizeof(*handler)); + if (!handler) { + ErrPrint("Error: %s\n", strerror(errno)); + free(lbid); return NULL; } - ret = master_rpc_async_request(handler, packet, 0, new_ret_cb, cbinfo); - if (ret < 0) { - ErrPrint("Failed to send a new packet\n"); - destroy_cb_info(cbinfo); - free(handler->category); - free(handler->cluster); - free(handler->content); - free(handler->pkgname); - free(handler); - return NULL; + if (!cb) { + cb = default_create_cb; + } + + handler->common = find_sharable_common_handle(lbid, content, w, h, cluster, category); + if (!handler->common) { + handler->common = lb_create_common_handle(handler, lbid, cluster, category); + free(lbid); + if (!handler->common) { + ErrPrint("Failed to find common handle\n"); + free(handler); + return NULL; + } + + if (!content || !strlen(content)) { + char *pc; + /*! + * \note + * I know the content should not be modified. use it temporarly without "const" + */ + pc = livebox_service_content(handler->common->pkgname); + lb_set_content(handler->common, pc); + free(pc); + } else { + lb_set_content(handler->common, content); + } + + lb_set_period(handler->common, period); + lb_set_size(handler->common, w, h); + lb_common_ref(handler->common, handler); + + if (create_real_instance(handler, cb, data) < 0) { + if (lb_common_unref(handler->common, handler) == 0) { + /*! + * Delete common + */ + lb_destroy_common_handle(handler->common); + handler->common = NULL; + } + free(handler); + return NULL; + } + } else { + free(lbid); + + lb_common_ref(handler->common, handler); + + if (handler->common->request.created) { + /*! + * If a box is in creating, wait its result too + */ + handler->cbs.created.cb = cb; + handler->cbs.created.data = data; + } else { + /*! + * or fire the fake created_event + */ + if (create_fake_instance(handler, cb, data) < 0) { + if (lb_common_unref(handler->common, handler) == 0) { + /*! + * Delete common + */ + lb_destroy_common_handle(handler->common); + } + free(handler); + return NULL; + } + } + } + + handler->visible = LB_SHOW; + handler->state = CREATE; + handler = lb_ref(handler); + + if (handler->common->visible != LB_SHOW) { + lb_set_visibility(handler, LB_SHOW); } - DbgPrint("Successfully sent a new request ([%lf] %s)\n", handler->timestamp, handler->pkgname); - handler->state = CREATE; - return lb_ref(handler); + return handler; } EAPI double livebox_period(struct livebox *handler) { - if (!handler || handler->state != CREATE || !handler->id) { + if (!handler || handler->state != CREATE) { ErrPrint("Handler is not valid\n"); return 0.0f; } - return handler->lb.period; + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); + return 0.0f; + } + + if (!handler->common->id) { + ErrPrint("Hnalder is not valid\n"); + return 0.0f; + } + + return handler->common->lb.period; } EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, void *data) @@ -810,49 +1601,146 @@ EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, struct packet *packet; int ret; - if (!handler || handler->state != CREATE || !handler->id) { + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->period_changed_cb) { + if (handler->common->request.period_changed) { ErrPrint("Previous request for changing period is not finished\n"); return LB_STATUS_ERROR_BUSY; } - if (!handler->is_user) { + if (!handler->common->is_user) { ErrPrint("CA Livebox is not able to change the period\n"); return LB_STATUS_ERROR_PERMISSION; } - if (handler->lb.period == period) { + if (handler->common->lb.period == period) { DbgPrint("No changes\n"); return LB_STATUS_ERROR_ALREADY; } - packet = packet_create("set_period", "ssd", handler->pkgname, handler->id, period); + packet = packet_create("set_period", "ssd", handler->common->pkgname, handler->common->id, period); if (!packet) { - ErrPrint("Failed to build a packet %s\n", handler->pkgname); + ErrPrint("Failed to build a packet %s\n", handler->common->pkgname); return LB_STATUS_ERROR_FAULT; } - if (!cb) + if (!cb) { cb = default_period_changed_cb; - - handler->period_changed_cb = cb; - handler->period_cbdata = data; + } ret = master_rpc_async_request(handler, packet, 0, period_ret_cb, NULL); - if (ret < 0) { - handler->period_changed_cb = NULL; - handler->period_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.period_changed.cb = cb; + handler->cbs.period_changed.data = data; + handler->common->request.period_changed = 1; } return ret; } -EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data) +static void lb_update_visibility(struct livebox_common *old_common) +{ + struct dlist *l; + struct livebox *item; + + item = NULL; + dlist_foreach(old_common->livebox_list, l, item) { + if (item->visible == (int)LB_SHOW) { + break; + } + + item = NULL; + } + + if (!item) { + l = dlist_nth(old_common->livebox_list, 0); + item = dlist_data(l); + + if (item) { + lb_set_visibility(item, LB_HIDE_WITH_PAUSE); + } else { + ErrPrint("Unable to get the valid handle from common handler\n"); + } + } else { + lb_set_visibility(item, LB_SHOW); + } +} + +/*! + * \note + * The second parameter should be the "return value", + * But in this case, we will use it for "type of deleting instance". + */ +static void job_del_cb(struct livebox *handle, int type, void *data) +{ + struct cb_info *cbinfo = data; + ret_cb_t cb; + + if (handle->visible == (int)LB_SHOW) { + lb_update_visibility(handle->common); + } + + cb = cbinfo->cb; + data = cbinfo->data; + destroy_cb_info(cbinfo); + + if (handle->common->state != CREATE) { + DbgPrint("[%s] %d\n", handle->common->pkgname, handle->refcnt); + if (cb) { + cb(handle, LB_STATUS_SUCCESS, data); + } + + return; + } + + if (handle->common->refcnt == 1) { + handle->common->delete_type = type; + handle->common->state = DELETE; + + if (!handle->common->id) { + /*! + * \note + * The id is not determined yet. + * It means a user didn't receive created event yet. + * Then just stop to delete procedure from here. + * Because the "created" event handle will release this. + * By the way, if the user adds any callback for getting return status of this, + * call it at here. + */ + if (cb) { + cb(handle, LB_STATUS_SUCCESS, data); + } + } + + DbgPrint("Send delete request\n"); + lb_send_delete(handle, type, cb, data); + } else { + if (cb) { + cb(handle, LB_STATUS_SUCCESS, data); + } + + DbgPrint("Before unref: %d\n", handle->common->refcnt); + lb_unref(handle, 1); + } +} + +EAPI int livebox_del_NEW(struct livebox *handler, int type, ret_cb_t cb, void *data) { + struct cb_info *cbinfo; + if (!handler) { ErrPrint("Handler is NIL\n"); return LB_STATUS_ERROR_INVALID; @@ -865,42 +1753,43 @@ EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data) handler->state = DELETE; - if (!handler->id) { - /*! - * \note - * The id is not determined yet. - * It means a user didn't receive created event yet. - * Then just stop to delete procedure from here. - * Because the "created" event handler will release this. - * By the way, if the user adds any callback for getting return status of this, - * call it at here. - */ - if (cb) - cb(handler, 0, data); - return LB_STATUS_SUCCESS; + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + ErrPrint("Failed to create a cbinfo\n"); + return LB_STATUS_ERROR_MEMORY; } - if (!cb) - cb = default_delete_cb; + if (job_add(handler, job_del_cb, type, cbinfo) != LB_STATUS_SUCCESS) { + ErrPrint("Failed to add a new job\n"); + destroy_cb_info(cbinfo); + return LB_STATUS_ERROR_FAULT; + } + + return LB_STATUS_SUCCESS; +} - return lb_send_delete(handler, cb, data); +EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data) +{ + return livebox_del_NEW(handler, LB_DELETE_PERMANENTLY, cb, data); } EAPI int livebox_set_fault_handler(int (*cb)(enum livebox_fault_type, const char *, const char *, const char *, void *), void *data) { struct fault_info *info; - if (!cb) + if (!cb) { return LB_STATUS_ERROR_INVALID; + } info = malloc(sizeof(*info)); if (!info) { - CRITICAL_LOG("Heap: %s\n", strerror(errno)); + ErrPrint("Heap: %s\n", strerror(errno)); return LB_STATUS_ERROR_MEMORY; } info->handler = cb; info->user_data = data; + info->is_deleted = 0; s_info.fault_list = dlist_append(s_info.fault_list, info); return LB_STATUS_SUCCESS; @@ -914,9 +1803,15 @@ EAPI void *livebox_unset_fault_handler(int (*cb)(enum livebox_fault_type, const dlist_foreach(s_info.fault_list, l, info) { if (info->handler == cb) { void *data; - s_info.fault_list = dlist_remove(s_info.fault_list, l); + data = info->user_data; - free(info); + + if (s_info.fault_state == INFO_STATE_CALLBACK_IN_PROCESSING) { + info->is_deleted = 1; + } else { + s_info.fault_list = dlist_remove(s_info.fault_list, l); + free(info); + } return data; } @@ -936,12 +1831,13 @@ EAPI int livebox_set_event_handler(int (*cb)(struct livebox *, enum livebox_even info = malloc(sizeof(*info)); if (!info) { - CRITICAL_LOG("Heap: %s\n", strerror(errno)); + ErrPrint("Heap: %s\n", strerror(errno)); return LB_STATUS_ERROR_MEMORY; } info->handler = cb; info->user_data = data; + info->is_deleted = 0; s_info.event_list = dlist_append(s_info.event_list, info); return LB_STATUS_SUCCESS; @@ -956,9 +1852,14 @@ EAPI void *livebox_unset_event_handler(int (*cb)(struct livebox *, enum livebox_ if (info->handler == cb) { void *data; - s_info.event_list = dlist_remove(s_info.event_list, l); data = info->user_data; - free(info); + + if (s_info.event_state == INFO_STATE_CALLBACK_IN_PROCESSING) { + info->is_deleted = 1; + } else { + s_info.event_list = dlist_remove(s_info.event_list, l); + free(info); + } return data; } @@ -972,39 +1873,48 @@ EAPI int livebox_set_update_mode(struct livebox *handler, int active_update, ret struct packet *packet; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is Invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is Invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Handler is Invalid\n"); return LB_STATUS_ERROR_INVALID; + } - if (handler->update_mode_cb) { + if (handler->common->request.update_mode) { ErrPrint("Previous update_mode cb is not finished yet\n"); return LB_STATUS_ERROR_BUSY; } - if (handler->is_active_update == active_update) + if (handler->common->is_active_update == active_update) { return LB_STATUS_ERROR_ALREADY; + } - if (!handler->is_user) + if (!handler->common->is_user) { return LB_STATUS_ERROR_PERMISSION; + } - packet = packet_create("update_mode", "ssi", handler->pkgname, handler->id, active_update); - if (!packet) + packet = packet_create("update_mode", "ssi", handler->common->pkgname, handler->common->id, active_update); + if (!packet) { return LB_STATUS_ERROR_FAULT; + } - if (!cb) + if (!cb) { cb = default_update_mode_cb; - - handler->update_mode_cb = cb; - handler->update_mode_cbdata = data; + } ret = master_rpc_async_request(handler, packet, 0, update_mode_cb, NULL); - if (ret < 0) { - handler->update_mode_cb = NULL; - handler->update_mode_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.update_mode.cb = cb; + handler->cbs.update_mode.data = data; + handler->common->request.update_mode = 1; } return ret; @@ -1012,70 +1922,210 @@ EAPI int livebox_set_update_mode(struct livebox *handler, int active_update, ret EAPI int livebox_is_active_update(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is Invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is Invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { return LB_STATUS_ERROR_INVALID; + } + + return handler->common->is_active_update; +} + +static void resize_job_cb(struct livebox *handler, int ret, void *data) +{ + struct cb_info *info = data; - return handler->is_active_update; + if (info->cb) { + info->cb(handler, ret, info->data); + } + + free(info); + + /*! + * \note + * Forcely update the box + */ + lb_invoke_event_handler(handler, LB_EVENT_LB_UPDATED); } EAPI int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *data) { - struct packet *packet; + struct livebox_common *common; int w; int h; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + /*! + * \TODO + * If this handle is host instance or link instance, + * Create a new instance or find another linkable instance. + */ + + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->size_changed_cb) { + /*! + * \note + * resize operation should be separated by each handler. + * If a handler is resizing, the other handler can request resize too. + * So we should not use the common->request.size_changed flag. + */ + if (handler->cbs.size_changed.cb) { ErrPrint("Previous resize request is not finished yet\n"); return LB_STATUS_ERROR_BUSY; } - if (!handler->is_user) { - ErrPrint("CA Livebox is not able to be resized\n"); - return LB_STATUS_ERROR_PERMISSION; - } - if (livebox_service_get_size(type, &w, &h) != 0) { ErrPrint("Invalid size type\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->lb.width == w && handler->lb.height == h) { + if (handler->common->lb.width == w && handler->common->lb.height == h) { DbgPrint("No changes\n"); - return LB_STATUS_ERROR_ALREADY;; + return LB_STATUS_ERROR_ALREADY; } - packet = packet_create("resize", "ssii", handler->pkgname, handler->id, w, h); - if (!packet) { - ErrPrint("Failed to build param\n"); - return LB_STATUS_ERROR_FAULT; + if (!handler->common->is_user) { + ErrPrint("CA Livebox is not able to be resized\n"); + return LB_STATUS_ERROR_PERMISSION; } - if (!cb) - cb = default_lb_size_changed_cb; + if (handler->common->refcnt <= 1) { + struct packet *packet; - handler->size_changed_cb = cb; - handler->size_cbdata = data; + /* Only 1 instance */ + packet = packet_create("resize", "ssii", handler->common->pkgname, handler->common->id, w, h); + if (!packet) { + ErrPrint("Failed to build param\n"); + return LB_STATUS_ERROR_FAULT; + } - ret = master_rpc_async_request(handler, packet, 0, resize_cb, NULL); - if (ret < 0) { - handler->size_changed_cb = NULL; - handler->size_cbdata = NULL; + if (!cb) { + cb = default_lb_size_changed_cb; + } + + ret = master_rpc_async_request(handler, packet, 0, resize_cb, NULL); + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.size_changed.cb = cb; + handler->cbs.size_changed.data = data; + handler->common->request.size_changed = 1; + } + } else { + common = find_sharable_common_handle(handler->common->pkgname, handler->common->content, w, h, handler->common->cluster, handler->common->category); + if (!common) { + struct livebox_common *old_common; + /*! + * \note + * If the common handler is in resizing, + * if user tries to resize a hander, then simply create new one even if the requested size is same with this. + + if (handler->common->request.size_changed) { + } + + */ + + old_common = handler->common; + + common = lb_create_common_handle(handler, old_common->pkgname, old_common->cluster, old_common->category); + if (!common) { + ErrPrint("Failed to create common handle\n"); + return LB_STATUS_ERROR_FAULT; + } + + lb_set_size(common, w, h); + lb_set_content(common, old_common->content); + lb_set_period(common, old_common->lb.period); + + /*! + * \note + * Disconnecting from old one. + */ + if (lb_common_unref(old_common, handler) == 0) { + /*! + * \note + * Impossible + */ + ErrPrint("Common has no associated handler\n"); + } + + lb_common_ref(common, handler); + + /*! + * Connect to a new one + */ + handler->common = common; + + /*! + * \TODO + * Need to care, if it fails to create a common handle, + * the resize operation will be failed. + * in that case, we should reuse the old common handle + */ + ret = create_real_instance(handler, cb, data); + if (ret < 0) { + lb_common_unref(common, handler); + lb_destroy_common_handle(common); + + lb_common_ref(old_common, handler); + handler->common = old_common; + } else { + /*! + * In this case, we should update visibility of old_common's liveboxes + */ + if (handler->visible == (int)LB_SHOW) { + lb_update_visibility(old_common); + } + } + } else { + struct cb_info *cbinfo; + + cbinfo = create_cb_info(cb, data); + if (!cbinfo) { + ErrPrint("Failed to create a cbinfo\n"); + ret = LB_STATUS_ERROR_MEMORY; + } else { + ret = job_add(handler, resize_job_cb, LB_STATUS_SUCCESS, cbinfo); + if (ret == (int)LB_STATUS_SUCCESS) { + struct livebox_common *old_common; + + old_common = handler->common; + + if (lb_common_unref(handler->common, handler) == 0) { + ErrPrint("Old common has no associated handler\n"); + } + + lb_common_ref(common, handler); + handler->common = common; + + if (handler->visible == (int)LB_SHOW) { + lb_update_visibility(old_common); /* To update visibility: Show --> Paused */ + lb_update_visibility(common); /* To update visibility: Paused --> Show */ + } + } else { + destroy_cb_info(cbinfo); + } + } + } } return ret; @@ -1087,47 +2137,57 @@ EAPI int livebox_click(struct livebox *handler, double x, double y) double timestamp; int ret; - timestamp = util_timestamp(); - DbgPrint("CLICKED: %lf\n", timestamp); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->lb.auto_launch) { - DbgPrint("Auto-launch enabled: %s\n", handler->lb.auto_launch); - if (aul_launch_app(handler->lb.auto_launch, NULL) < 0) - ErrPrint("Failed to launch app %s\n", handler->lb.auto_launch); + if (handler->common->lb.auto_launch) { + if (s_info.launch.handler) { + ret = s_info.launch.handler(handler, handler->common->lb.auto_launch, s_info.launch.data); + if (ret < 0) { + ErrPrint("launch handler app %s (%d)\n", handler->common->lb.auto_launch, ret); + } + } } - packet = packet_create_noack("clicked", "sssddd", handler->pkgname, handler->id, "clicked", timestamp, x, y); + timestamp = util_timestamp(); + DbgPrint("CLICKED: %lf\n", timestamp); + + packet = packet_create_noack("clicked", "sssddd", handler->common->pkgname, handler->common->id, "clicked", timestamp, x, y); if (!packet) { ErrPrint("Failed to build param\n"); return LB_STATUS_ERROR_FAULT; } ret = master_rpc_request_only(handler, packet); - DbgPrint("Click request: %d\n", ret); - if (!handler->lb.mouse_event && (handler->lb.type == _LB_TYPE_BUFFER || handler->lb.type == _LB_TYPE_SCRIPT)) { + if (!handler->common->lb.mouse_event && (handler->common->lb.type == _LB_TYPE_BUFFER || handler->common->lb.type == _LB_TYPE_SCRIPT)) { int ret; /* Shadow variable */ - ret = send_mouse_event(handler, "lb_mouse_down", x * handler->lb.width, y * handler->lb.height); - if (ret < 0) - DbgPrint("Failed to send Down: %d\n", ret); + ret = send_mouse_event(handler, "lb_mouse_down", x * handler->common->lb.width, y * handler->common->lb.height); + if (ret < 0) { + ErrPrint("Failed to send Down: %d\n", ret); + } - ret = send_mouse_event(handler, "lb_mouse_move", x * handler->lb.width, y * handler->lb.height); - if (ret < 0) - DbgPrint("Failed to send Move: %d\n", ret); + ret = send_mouse_event(handler, "lb_mouse_move", x * handler->common->lb.width, y * handler->common->lb.height); + if (ret < 0) { + ErrPrint("Failed to send Move: %d\n", ret); + } - ret = send_mouse_event(handler, "lb_mouse_up", x * handler->lb.width, y * handler->lb.height); - if (ret < 0) - DbgPrint("Failed to send Up: %d\n", ret); + ret = send_mouse_event(handler, "lb_mouse_up", x * handler->common->lb.width, y * handler->common->lb.height); + if (ret < 0) { + ErrPrint("Failed to send Up: %d\n", ret); + } } return ret; @@ -1135,32 +2195,42 @@ EAPI int livebox_click(struct livebox *handler, double x, double y) EAPI int livebox_has_pd(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - return !!handler->pd.data.fb; + return !!handler->common->pd.fb; } EAPI int livebox_pd_is_created(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) { + if (!handler->common->pd.fb || !handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - return handler->is_pd_created; + return handler->common->is_pd_created; } EAPI int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *data) @@ -1168,47 +2238,85 @@ EAPI int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *data) return livebox_create_pd_with_position(handler, -1.0, -1.0, cb, data); } +static void turn_off_pd_destroyed_flag_cb(struct livebox *handler, int ret, void *data) +{ + if (handler->common->request.pd_destroyed) { + ret_cb_t cb; + void *data; + + DbgPrint("pd_destroyed request is canceled\n"); + handler->common->request.pd_destroyed = 0; + cb = handler->cbs.pd_destroyed.cb; + data = handler->cbs.pd_destroyed.data; + handler->cbs.pd_destroyed.cb = NULL; + handler->cbs.pd_destroyed.data = NULL; + + if (cb) { + cb(handler, ret, data); + } + } +} + EAPI int livebox_create_pd_with_position(struct livebox *handler, double x, double y, ret_cb_t cb, void *data) { struct packet *packet; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) { + if (!handler->common->pd.fb || !handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->is_pd_created == 1) { - DbgPrint("PD already created\n"); + /*! + * \note + * Only one handler can have a PD + */ + if (handler->common->is_pd_created) { + DbgPrint("PD is already created\n"); return LB_STATUS_SUCCESS; } - if (handler->pd_created_cb) { + if (handler->common->request.pd_created) { ErrPrint("Previous request is not completed yet\n"); return LB_STATUS_ERROR_BUSY; } - packet = packet_create("create_pd", "ssdd", handler->pkgname, handler->id, x, y); + /*! + * \note + * Turn off the pd_destroyed request flag + */ + if (handler->common->request.pd_destroyed) { + if (job_add(handler, turn_off_pd_destroyed_flag_cb, LB_STATUS_ERROR_CANCEL, NULL) < 0) { + ErrPrint("Failed to add pd_destroyed job\n"); + } + } + + packet = packet_create("create_pd", "ssdd", handler->common->pkgname, handler->common->id, x, y); if (!packet) { ErrPrint("Failed to build param\n"); return LB_STATUS_ERROR_FAULT; } - if (!cb) + if (!cb) { cb = default_pd_created_cb; + } - handler->pd_created_cb = cb; - handler->pd_created_cbdata = data; - + DbgPrint("PERF_DBOX\n"); ret = master_rpc_async_request(handler, packet, 0, pd_create_cb, NULL); - if (ret < 0) { - handler->pd_created_cb = NULL; - handler->pd_created_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.pd_created.cb = cb; + handler->cbs.pd_created.data = data; + handler->common->request.pd_created = 1; } return ret; @@ -1218,22 +2326,27 @@ EAPI int livebox_move_pd(struct livebox *handler, double x, double y) { struct packet *packet; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) { + if (!handler->common->pd.fb || !handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->is_pd_created) { - DbgPrint("PD is not created\n"); + if (!handler->common->is_pd_created) { + ErrPrint("PD is not created\n"); return LB_STATUS_ERROR_INVALID; } - packet = packet_create_noack("pd_move", "ssdd", handler->pkgname, handler->id, x, y); + packet = packet_create_noack("pd_move", "ssdd", handler->common->pkgname, handler->common->id, x, y); if (!packet) { ErrPrint("Failed to build param\n"); return LB_STATUS_ERROR_FAULT; @@ -1248,8 +2361,9 @@ EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data) struct cb_info *cbinfo; int ret; - if (!pkgname) + if (!pkgname) { return LB_STATUS_ERROR_INVALID; + } packet = packet_create("activate_package", "s", pkgname); if (!packet) { @@ -1265,41 +2379,90 @@ EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data) } ret = master_rpc_async_request(NULL, packet, 0, activated_cb, cbinfo); - if (ret < 0) + if (ret < 0) { destroy_cb_info(cbinfo); + } return ret; } +static void turn_off_pd_created_flag_cb(struct livebox *handler, int ret, void *data) +{ + if (handler->common->request.pd_created) { + ret_cb_t cb; + void *data; + + DbgPrint("pd_created request is canceled\n"); + handler->common->request.pd_created = 0; + cb = handler->cbs.pd_created.cb; + data = handler->cbs.pd_created.data; + handler->cbs.pd_created.cb = NULL; + handler->cbs.pd_created.data = NULL; + + if (cb) { + cb(handler, ret, data); + } + } +} + EAPI int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data) { struct packet *packet; struct cb_info *cbinfo; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->pd.data.fb || handler->state != CREATE || !handler->id) { + if (!handler->common->pd.fb || !handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (!handler->is_pd_created) { + /*! + * \FIXME + * Replace the callback check code. + * Use the flag instead of callback. + * the flag should be in the ADT "common" + */ + if (!handler->common->is_pd_created && !handler->common->request.pd_created) { ErrPrint("PD is not created\n"); return LB_STATUS_ERROR_INVALID; } - packet = packet_create("destroy_pd", "ss", handler->pkgname, handler->id); + if (handler->common->request.pd_destroyed) { + ErrPrint("PD destroy request is already sent\n"); + return LB_STATUS_ERROR_ALREADY; + } + + /*! + * \note + * Disable the pd_created request flag + */ + if (handler->common->request.pd_created) { + if (job_add(handler, turn_off_pd_created_flag_cb, LB_STATUS_ERROR_CANCEL, NULL) < 0) { + ErrPrint("Failed to add a new job\n"); + } + } + + DbgPrint("[%s]\n", handler->common->pkgname); + + packet = packet_create("destroy_pd", "ss", handler->common->pkgname, handler->common->id); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_FAULT; } - if (!cb) + if (!cb) { cb = default_pd_destroyed_cb; + } cbinfo = create_cb_info(cb, data); if (!cbinfo) { @@ -1308,8 +2471,11 @@ EAPI int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data) } ret = master_rpc_async_request(handler, packet, 0, pd_destroy_cb, cbinfo); - if (ret < 0) + if (ret < 0) { destroy_cb_info(cbinfo); + } else { + handler->common->request.pd_destroyed = 1; + } return ret; } @@ -1322,35 +2488,40 @@ EAPI int livebox_access_event(struct livebox *handler, enum access_event_type ty char *ptr = cmd; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->access_event_cb) { + if (handler->common->request.access_event) { ErrPrint("Previous access event is not yet done\n"); return LB_STATUS_ERROR_BUSY; } if (type & ACCESS_EVENT_PD_MASK) { - if (!handler->is_pd_created) { + if (!handler->common->is_pd_created) { ErrPrint("PD is not created\n"); return LB_STATUS_ERROR_INVALID; } *ptr++ = 'p'; *ptr++ = 'd'; - w = handler->pd.width; - h = handler->pd.height; + w = handler->common->pd.width; + h = handler->common->pd.height; } else if (type & ACCESS_EVENT_LB_MASK) { *ptr++ = 'l'; *ptr++ = 'b'; - w = handler->lb.width; - h = handler->lb.height; + w = handler->common->lb.width; + h = handler->common->lb.height; } else { ErrPrint("Invalid event type\n"); return LB_STATUS_ERROR_INVALID; @@ -1391,16 +2562,15 @@ EAPI int livebox_access_event(struct livebox *handler, enum access_event_type ty return LB_STATUS_ERROR_INVALID; } - if (!cb) + if (!cb) { cb = default_access_event_cb; - - handler->access_event_cb = cb; - handler->access_event_cbdata = data; + } ret = send_access_event(handler, cmd, x * w, y * h); - if (ret < 0) { - handler->access_event_cb = NULL; - handler->access_event_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.access_event.cb = cb; + handler->cbs.access_event.data = data; + handler->common->request.access_event = 1; } return ret; @@ -1408,78 +2578,90 @@ EAPI int livebox_access_event(struct livebox *handler, enum access_event_type ty EAPI int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y) { + return livebox_mouse_event(handler, type, x, y); +} + +EAPI int livebox_mouse_event(struct livebox *handler, enum content_event_type type, double x, double y) +{ int w = 1; int h = 1; char cmd[32] = { '\0', }; char *ptr = cmd; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } + if (!(type & CONTENT_EVENT_MOUSE_MASK)) { + ErrPrint("Invalid content event is used\n"); + return LB_STATUS_ERROR_INVALID; + } + if (type & CONTENT_EVENT_PD_MASK) { int flag = 1; - if (!handler->is_pd_created) { + if (!handler->common->is_pd_created) { ErrPrint("PD is not created\n"); return LB_STATUS_ERROR_INVALID; } - if (type & CONTENT_EVENT_MOUSE_MASK) { - if (!handler->pd.data.fb) { - ErrPrint("Handler is not valid\n"); - return LB_STATUS_ERROR_INVALID; - } + if (!handler->common->pd.fb) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } - if (type & CONTENT_EVENT_MOUSE_MOVE) { - if (fabs(x - handler->pd.x) < MINIMUM_EVENT && fabs(y - handler->pd.y) < MINIMUM_EVENT) - return LB_STATUS_ERROR_BUSY; - } else if (type & CONTENT_EVENT_MOUSE_SET) { - flag = 0; + if (type & CONTENT_EVENT_MOUSE_MOVE) { + if (fabs(x - handler->common->pd.x) < conf_event_filter() && fabs(y - handler->common->pd.y) < conf_event_filter()) { + return LB_STATUS_ERROR_BUSY; } + } else if (type & CONTENT_EVENT_MOUSE_SET) { + flag = 0; } if (flag) { - w = handler->pd.width; - h = handler->pd.height; - handler->pd.x = x; - handler->pd.y = y; + w = handler->common->pd.width; + h = handler->common->pd.height; + handler->common->pd.x = x; + handler->common->pd.y = y; } *ptr++ = 'p'; *ptr++ = 'd'; } else if (type & CONTENT_EVENT_LB_MASK) { int flag = 1; - if (type & CONTENT_EVENT_MOUSE_MASK) { - if (!handler->lb.mouse_event) { - ErrPrint("Box is not support the mouse event\n"); - return LB_STATUS_ERROR_INVALID; - } + if (!handler->common->lb.mouse_event) { + return LB_STATUS_ERROR_INVALID; + } - if (!handler->lb.data.fb) { - ErrPrint("Handler is not valid\n"); - return LB_STATUS_ERROR_INVALID; - } + if (!handler->common->lb.fb) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } - if (type & CONTENT_EVENT_MOUSE_MOVE) { - if (fabs(x - handler->lb.x) < MINIMUM_EVENT && fabs(y - handler->lb.y) < MINIMUM_EVENT) - return LB_STATUS_ERROR_BUSY; - } else if (type & CONTENT_EVENT_MOUSE_SET) { - flag = 0; + if (type & CONTENT_EVENT_MOUSE_MOVE) { + if (fabs(x - handler->common->lb.x) < conf_event_filter() && fabs(y - handler->common->lb.y) < conf_event_filter()) { + return LB_STATUS_ERROR_BUSY; } + } else if (type & CONTENT_EVENT_MOUSE_SET) { + flag = 0; } if (flag) { - w = handler->lb.width; - h = handler->lb.height; - handler->lb.x = x; - handler->lb.y = y; + w = handler->common->lb.width; + h = handler->common->lb.height; + handler->common->lb.x = x; + handler->common->lb.y = y; } *ptr++ = 'l'; *ptr++ = 'b'; @@ -1513,37 +2695,162 @@ EAPI int livebox_content_event(struct livebox *handler, enum content_event_type case CONTENT_EVENT_MOUSE_UNSET | CONTENT_EVENT_MOUSE_MASK: strcpy(ptr, "_mouse_unset"); break; - case CONTENT_EVENT_KEY_DOWN | CONTENT_EVENT_KEY_MASK: - strcpy(ptr, "_key_down"); + default: + ErrPrint("Invalid event type\n"); + return LB_STATUS_ERROR_INVALID; + } + + return send_mouse_event(handler, cmd, x * w, y * h); +} + +EAPI int livebox_key_event(struct livebox *handler, enum content_event_type type, unsigned int keycode, ret_cb_t cb, void *data) +{ + char cmd[32] = { '\0', }; + char *ptr = cmd; + int ret; + + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!(type & CONTENT_EVENT_KEY_MASK)) { + ErrPrint("Invalid key event is used\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (handler->common->request.key_event) { + ErrPrint("Previous key event is not completed yet\n"); + return LB_STATUS_ERROR_BUSY; + } + + if (type & CONTENT_EVENT_PD_MASK) { + if (!handler->common->is_pd_created) { + ErrPrint("PD is not created\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->pd.fb) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (type & CONTENT_EVENT_KEY_DOWN) { + /*! + * \TODO + * filtering the reproduced events if it is too fast + */ + } else if (type & CONTENT_EVENT_KEY_SET) { + /*! + * \TODO + * What can I do for this case? + */ + } + + *ptr++ = 'p'; + *ptr++ = 'd'; + } else if (type & CONTENT_EVENT_LB_MASK) { + if (!handler->common->lb.mouse_event) { + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->lb.fb) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (type & CONTENT_EVENT_KEY_DOWN) { + /*! + * \TODO + * filtering the reproduced events if it is too fast + */ + } else if (type & CONTENT_EVENT_KEY_SET) { + /*! + * What can I do for this case? + */ + } + + *ptr++ = 'l'; + *ptr++ = 'b'; + } else { + ErrPrint("Invalid event type\n"); + return LB_STATUS_ERROR_INVALID; + } + + /*! + * Must be short than 29 bytes. + */ + switch ((type & ~(CONTENT_EVENT_PD_MASK | CONTENT_EVENT_LB_MASK))) { + case CONTENT_EVENT_KEY_FOCUS_IN | CONTENT_EVENT_KEY_MASK: + strcpy(ptr, "_key_focus_in"); + break; + case CONTENT_EVENT_KEY_FOCUS_OUT | CONTENT_EVENT_KEY_MASK: + strcpy(ptr, "_key_focus_out"); break; case CONTENT_EVENT_KEY_UP | CONTENT_EVENT_KEY_MASK: strcpy(ptr, "_key_up"); break; + case CONTENT_EVENT_KEY_DOWN | CONTENT_EVENT_KEY_MASK: + strcpy(ptr, "_key_down"); + break; + case CONTENT_EVENT_KEY_SET | CONTENT_EVENT_KEY_MASK: + strcpy(ptr, "_key_set"); + break; + case CONTENT_EVENT_KEY_UNSET | CONTENT_EVENT_KEY_MASK: + strcpy(ptr, "_key_unset"); + break; default: ErrPrint("Invalid event type\n"); return LB_STATUS_ERROR_INVALID; } - return send_mouse_event(handler, cmd, x * w, y * h); + if (!cb) { + cb = default_key_event_cb; + } + + ret = send_key_event(handler, cmd, keycode); + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.key_event.cb = cb; + handler->cbs.key_event.data = data; + handler->common->request.key_event = 1; + } + + return ret; } EAPI const char *livebox_filename(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return NULL; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return NULL; } - if (handler->filename) - return handler->filename; + if (handler->common->filename) { + return handler->common->filename; + } /* Oooops */ - return util_uri_to_path(handler->id); + return util_uri_to_path(handler->common->id); } EAPI int livebox_get_pdsize(struct livebox *handler, int *w, int *h) @@ -1551,28 +2858,34 @@ EAPI int livebox_get_pdsize(struct livebox *handler, int *w, int *h) int _w; int _h; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (!w) + if (!w) { w = &_w; - if (!h) + } + if (!h) { h = &_h; + } - if (!handler->is_pd_created) { - DbgPrint("Buffer is not created yet [%dx%d]\n", *w, *h); - *w = handler->pd.default_width; - *h = handler->pd.default_height; + if (!handler->common->is_pd_created) { + *w = handler->common->pd.default_width; + *h = handler->common->pd.default_height; } else { - *w = handler->pd.width; - *h = handler->pd.height; + *w = handler->common->pd.width; + *h = handler->common->pd.height; } return LB_STATUS_SUCCESS; @@ -1583,24 +2896,28 @@ EAPI int livebox_size(struct livebox *handler) int w; int h; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - w = handler->lb.width; - h = handler->lb.height; + w = handler->common->lb.width; + h = handler->common->lb.height; - switch (handler->lb.type) { + switch (handler->common->lb.type) { case _LB_TYPE_BUFFER: case _LB_TYPE_SCRIPT: - if (!fb_is_created(handler->lb.data.fb)) { - DbgPrint("Buffer is not created yet - reset size\n"); + if (!fb_is_created(handler->common->lb.fb)) { w = 0; h = 0; } @@ -1622,61 +2939,80 @@ EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const c return LB_STATUS_ERROR_INVALID; } - if (!cluster || !category || handler->state != CREATE || !handler->id) { + if (!cluster || !category || handler->state != CREATE) { + ErrPrint("Invalid argument\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid argument\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { ErrPrint("Invalid argument\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->group_changed_cb) { + if (handler->common->request.group_changed) { ErrPrint("Previous group changing request is not finished yet\n"); return LB_STATUS_ERROR_BUSY; } - if (!handler->is_user) { + if (!handler->common->is_user) { ErrPrint("CA Livebox is not able to change the group\n"); return LB_STATUS_ERROR_PERMISSION; } - if (!strcmp(handler->cluster, cluster) && !strcmp(handler->category, category)) { + if (!strcmp(handler->common->cluster, cluster) && !strcmp(handler->common->category, category)) { DbgPrint("No changes\n"); return LB_STATUS_ERROR_ALREADY; } - packet = packet_create("change_group", "ssss", handler->pkgname, handler->id, cluster, category); + packet = packet_create("change_group", "ssss", handler->common->pkgname, handler->common->id, cluster, category); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_FAULT; } - if (!cb) + if (!cb) { cb = default_group_changed_cb; - - handler->group_changed_cb = cb; - handler->group_cbdata = data; + } ret = master_rpc_async_request(handler, packet, 0, set_group_ret_cb, NULL); - if (ret < 0) { - handler->group_changed_cb = NULL; - handler->group_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.group_changed.cb = cb; + handler->cbs.group_changed.data = data; + handler->common->request.group_changed = 1; } return ret; } -EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category) +EAPI int livebox_get_group(struct livebox *handler, const char **cluster, const char **category) { if (!handler) { ErrPrint("Handler is NIL\n"); return LB_STATUS_ERROR_INVALID; } - if (!cluster || !category || handler->state != CREATE || !handler->id) { + if (!cluster || !category || handler->state != CREATE) { + ErrPrint("Invalid argument\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid argument\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { ErrPrint("Invalid argument\n"); return LB_STATUS_ERROR_INVALID; } - *cluster = handler->cluster; - *category = handler->category; + *cluster = handler->common->cluster; + *category = handler->common->category; return LB_STATUS_SUCCESS; } @@ -1690,15 +3026,26 @@ EAPI int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *siz return LB_STATUS_ERROR_INVALID; } - if (!cnt || handler->state != CREATE || !handler->id) { + if (!cnt || handler->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } for (j = i = 0; i < NR_OF_SIZE_LIST; i++) { - if (handler->lb.size_list & (0x01 << i)) { - if (j == *cnt) + if (handler->common->lb.size_list & (0x01 << i)) { + if (j == *cnt) { break; + } size_list[j++] = (0x01 << i); } @@ -1720,22 +3067,32 @@ EAPI const char *livebox_pkgname(struct livebox *handler) return NULL; } - return handler->pkgname; + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return NULL; + } + + return handler->common->pkgname; } EAPI double livebox_priority(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); - return 0.0f; + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return -1.0f; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return -1.0f; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid (%p)\n", handler); return -1.0f; } - return handler->lb.priority; + return handler->common->lb.priority; } EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data) @@ -1757,8 +3114,9 @@ EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data) } ret = master_rpc_async_request(NULL, packet, 0, delete_cluster_cb, cbinfo); - if (ret < 0) + if (ret < 0) { destroy_cb_info(cbinfo); + } return ret; } @@ -1782,34 +3140,41 @@ EAPI int livebox_delete_category(const char *cluster, const char *category, ret_ } ret = master_rpc_async_request(NULL, packet, 0, delete_category_cb, cbinfo); - if (ret < 0) + if (ret < 0) { destroy_cb_info(cbinfo); + } return ret; } EAPI enum livebox_lb_type livebox_lb_type(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_TYPE_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_TYPE_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_TYPE_INVALID; } - switch (handler->lb.type) { + switch (handler->common->lb.type) { case _LB_TYPE_FILE: return LB_TYPE_IMAGE; case _LB_TYPE_BUFFER: case _LB_TYPE_SCRIPT: { const char *id; - id = fb_id(handler->lb.data.fb); - if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) + id = fb_id(handler->common->lb.fb); + if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) { return LB_TYPE_PIXMAP; + } } return LB_TYPE_BUFFER; case _LB_TYPE_TEXT: @@ -1823,26 +3188,32 @@ EAPI enum livebox_lb_type livebox_lb_type(struct livebox *handler) EAPI enum livebox_pd_type livebox_pd_type(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return PD_TYPE_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return PD_TYPE_INVALID; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Handler is not valid\n"); return PD_TYPE_INVALID; } - switch (handler->pd.type) { + switch (handler->common->pd.type) { case _PD_TYPE_TEXT: return PD_TYPE_TEXT; case _PD_TYPE_BUFFER: case _PD_TYPE_SCRIPT: { const char *id; - id = fb_id(handler->pd.data.fb); - if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) + id = fb_id(handler->common->pd.fb); + if (id && !strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) { return PD_TYPE_PIXMAP; + } } return PD_TYPE_BUFFER; default: @@ -1864,7 +3235,7 @@ EAPI int livebox_set_pd_text_handler(struct livebox *handler, struct livebox_scr return LB_STATUS_ERROR_INVALID; } - memcpy(&handler->pd.data.ops, ops, sizeof(*ops)); + memcpy(&handler->cbs.pd_ops, ops, sizeof(*ops)); return LB_STATUS_SUCCESS; } @@ -1880,75 +3251,93 @@ EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script return LB_STATUS_ERROR_INVALID; } - memcpy(&handler->lb.data.ops, ops, sizeof(*ops)); + memcpy(&handler->cbs.lb_ops, ops, sizeof(*ops)); return LB_STATUS_SUCCESS; } EAPI int livebox_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *data) { - struct packet *packet; - struct cb_info *cbinfo; - const char *id; - int ret; - - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Invalid handle\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) { - ErrPrint("Handler is not valid type\n"); + if (!handler->common->id) { + ErrPrint("Invalid handle\n"); return LB_STATUS_ERROR_INVALID; } - id = fb_id(handler->lb.data.fb); - if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) + if (handler->common->lb.type != _LB_TYPE_SCRIPT && handler->common->lb.type != _LB_TYPE_BUFFER) { + ErrPrint("Handler is not valid type\n"); return LB_STATUS_ERROR_INVALID; - - packet = packet_create("lb_acquire_pixmap", "ss", handler->pkgname, handler->id); - if (!packet) { - ErrPrint("Failed to build a param\n"); - return LB_STATUS_ERROR_FAULT; - } - - cbinfo = create_cb_info(cb, data); - if (!cbinfo) { - packet_destroy(packet); - return LB_STATUS_ERROR_FAULT; } - ret = master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, cbinfo); - if (ret < 0) - destroy_cb_info(cbinfo); - - return ret; + return lb_acquire_lb_pixmap(handler, cb, data); } +/*! + * \note + * Do not check the state of handler and common-handler. + * If this function is used in the deleted callback, + * the handler and common-handler's state would be DELETE + * if this function check the state of handles, + * user cannot release the pixmap. + */ EAPI int livebox_release_lb_pixmap(struct livebox *handler, int pixmap) { struct packet *packet; + const char *pkgname; + const char *id; + + if (pixmap == 0 /* || handler->state != CREATE */ ) { + ErrPrint("Handler is invalid [%d]\n", pixmap); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler) { + /*! + * \note + * Even though the handler is NULL, we should send the release request to the master. + * Because the pixmap resource can be released after the handler is destroyed. + * Pixmap resource is used by client. and it cannot be guaranteed to release pixmap. + * In some cases, the pixmap can be released after the handler is deleted. + * + * Its implementation is up to the viewer app. + * But we cannot force it to use only with valid handler. + */ + DbgPrint("Using NULL handler\n"); + pkgname = NULL; + id = NULL; + /*! + * \note + * Master will try to find the buffer handler using given pixmap. if the pkgname and id is not valid. + */ + } else { + if (!handler->common /* || handler->common->state != CREATE */) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } - if (!handler) { - ErrPrint("Handler is NIL\n"); - return LB_STATUS_ERROR_INVALID; - } + if (!handler->common->id) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Invalid handle\n"); - return LB_STATUS_ERROR_INVALID; - } + if (handler->common->lb.type != _LB_TYPE_SCRIPT && handler->common->lb.type != _LB_TYPE_BUFFER) { + ErrPrint("Handler is not valid type\n"); + return LB_STATUS_ERROR_INVALID; + } - if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) { - ErrPrint("Handler is not valid type\n"); - return LB_STATUS_ERROR_INVALID; + pkgname = handler->common->pkgname; + id = handler->common->id; } - packet = packet_create_noack("lb_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap); + packet = packet_create_noack("lb_release_pixmap", "ssi", pkgname, id, pixmap); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_INVALID; @@ -1959,47 +3348,27 @@ EAPI int livebox_release_lb_pixmap(struct livebox *handler, int pixmap) EAPI int livebox_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *data) { - struct packet *packet; - struct cb_info *cbinfo; - const char *id; - int ret; - - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Invalid handle\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) { - ErrPrint("Handler is not valid type\n"); + if (!handler->common->id) { + ErrPrint("Invalid handle\n"); return LB_STATUS_ERROR_INVALID; } - id = fb_id(handler->pd.data.fb); - if (!id || strncasecmp(id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP))) + if (handler->common->pd.type != _PD_TYPE_SCRIPT && handler->common->pd.type != _PD_TYPE_BUFFER) { + ErrPrint("Handler is not valid type\n"); return LB_STATUS_ERROR_INVALID; - - packet = packet_create("pd_acquire_pixmap", "ss", handler->pkgname, handler->id); - if (!packet) { - ErrPrint("Failed to build a param\n"); - return LB_STATUS_ERROR_FAULT; - } - - cbinfo = create_cb_info(cb, data); - if (!cbinfo) { - packet_destroy(packet); - return LB_STATUS_ERROR_FAULT; } - ret = master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, cbinfo); - if (ret < 0) - destroy_cb_info(cbinfo); - - return ret; + return lb_acquire_pd_pixmap(handler, cb, data); } EAPI int livebox_pd_pixmap(const struct livebox *handler) @@ -2007,23 +3376,28 @@ EAPI int livebox_pd_pixmap(const struct livebox *handler) const char *id; int pixmap = 0; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return 0; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return 0; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Invalid handler\n"); return 0; } - if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) { + if (handler->common->pd.type != _PD_TYPE_SCRIPT && handler->common->pd.type != _PD_TYPE_BUFFER) { ErrPrint("Invalid handler\n"); return 0; } - id = fb_id(handler->pd.data.fb); - if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) { + id = fb_id(handler->common->pd.fb); + if (id && sscanf(id, SCHEMA_PIXMAP "%u", (unsigned int *)&pixmap) != 1) { ErrPrint("PIXMAP Id is not valid\n"); return 0; } @@ -2036,23 +3410,28 @@ EAPI int livebox_lb_pixmap(const struct livebox *handler) const char *id; int pixmap = 0; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return 0; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return 0; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Invalid handler\n"); return 0; } - if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) { + if (handler->common->lb.type != _LB_TYPE_SCRIPT && handler->common->lb.type != _LB_TYPE_BUFFER) { ErrPrint("Invalid handler\n"); return 0; } - id = fb_id(handler->lb.data.fb); - if (id && sscanf(id, SCHEMA_PIXMAP "%d", &pixmap) != 1) { + id = fb_id(handler->common->lb.fb); + if (id && sscanf(id, SCHEMA_PIXMAP "%u", (unsigned int *)&pixmap) != 1) { ErrPrint("PIXMAP Id is not valid\n"); return 0; } @@ -2060,26 +3439,64 @@ EAPI int livebox_lb_pixmap(const struct livebox *handler) return pixmap; } +/*! + * \note + * Do not check the state of handler and common-handler. + * If this function is used in the deleted callback, + * the handler and common-handler's state would be DELETE + * if this function check the state of handles, + * user cannot release the pixmap. + */ EAPI int livebox_release_pd_pixmap(struct livebox *handler, int pixmap) { struct packet *packet; + const char *pkgname; + const char *id; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (pixmap == 0 /* || handler->state != CREATE */) { + ErrPrint("Pixmap is invalid [%d]\n", pixmap); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Invalid handle\n"); - return LB_STATUS_ERROR_INVALID; - } + if (!handler) { + /*! + * \note + * Even though the handler is NULL, we should send the release request to the master. + * Because the pixmap resource can be released after the handler is destroyed. + * Pixmap resource is used by client. and it cannot be guaranteed to release pixmap. + * In some cases, the pixmap can be released after the handler is deleted. + * + * Its implementation is up to the viewer app. + * But we cannot force it to use only with valid handler. + */ + DbgPrint("Using NULL handler\n"); + pkgname = NULL; + id = NULL; + /*! + * \note + * Master will try to find the buffer handler using given pixmap. if the pkgname and id is not valid. + */ + } else { + if (!handler->common /* || handler-common->state != CREATE */) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } - if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) { - ErrPrint("Handler is not valid type\n"); - return LB_STATUS_ERROR_INVALID; + if (!handler->common->id) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (handler->common->pd.type != _PD_TYPE_SCRIPT && handler->common->pd.type != _PD_TYPE_BUFFER) { + ErrPrint("Handler is not valid type\n"); + return LB_STATUS_ERROR_INVALID; + } + + pkgname = handler->common->pkgname; + id = handler->common->id; } - packet = packet_create_noack("pd_release_pixmap", "ssi", handler->pkgname, handler->id, pixmap); + packet = packet_create_noack("pd_release_pixmap", "ssi", pkgname, id, pixmap); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_FAULT; @@ -2090,22 +3507,27 @@ EAPI int livebox_release_pd_pixmap(struct livebox *handler, int pixmap) EAPI void *livebox_acquire_fb(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return NULL; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Invalid handle\n"); return NULL; } - if (handler->lb.type != _LB_TYPE_SCRIPT && handler->lb.type != _LB_TYPE_BUFFER) { + if (handler->common->lb.type != _LB_TYPE_SCRIPT && handler->common->lb.type != _LB_TYPE_BUFFER) { ErrPrint("Handler is not valid type\n"); return NULL; } - return fb_acquire_buffer(handler->lb.data.fb); + return fb_acquire_buffer(handler->common->lb.fb); } EAPI int livebox_release_fb(void *buffer) @@ -2120,22 +3542,27 @@ EAPI int livebox_fb_refcnt(void *buffer) EAPI void *livebox_acquire_pdfb(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return NULL; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; } - if (handler->state != CREATE || !handler->id) { + if (!handler->common->id) { ErrPrint("Invalid handler\n"); return NULL; } - if (handler->pd.type != _PD_TYPE_SCRIPT && handler->pd.type != _PD_TYPE_BUFFER) { + if (handler->common->pd.type != _PD_TYPE_SCRIPT && handler->common->pd.type != _PD_TYPE_BUFFER) { ErrPrint("Handler is not valid type\n"); return NULL; } - return fb_acquire_buffer(handler->pd.data.fb); + return fb_acquire_buffer(handler->common->pd.fb); } EAPI int livebox_release_pdfb(void *buffer) @@ -2150,47 +3577,62 @@ EAPI int livebox_pdfb_refcnt(void *buffer) EAPI int livebox_pdfb_bufsz(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Handler is not valid\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); return LB_STATUS_ERROR_INVALID; } - return fb_size(handler->pd.data.fb); + return fb_size(handler->common->pd.fb); } EAPI int livebox_lbfb_bufsz(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Handler is not valid\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); return LB_STATUS_ERROR_INVALID; } - return fb_size(handler->lb.data.fb); + return fb_size(handler->common->lb.fb); } EAPI int livebox_is_user(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE) { + if (!handler->common || handler->common->state != CREATE) { ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - return handler->is_user; + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); + return LB_STATUS_ERROR_INVALID; + } + + return handler->common->is_user; } EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void *data) @@ -2198,42 +3640,46 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void struct packet *packet; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) { - ErrPrint("Handler is not valid\n"); + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->pinup_cb) { + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (handler->common->request.pinup) { ErrPrint("Previous pinup request is not finished\n"); return LB_STATUS_ERROR_BUSY; } - if (handler->is_pinned_up == flag) { + if (handler->common->is_pinned_up == flag) { DbgPrint("No changes\n"); return LB_STATUS_ERROR_ALREADY; } - packet = packet_create("pinup_changed", "ssi", handler->pkgname, handler->id, flag); + packet = packet_create("pinup_changed", "ssi", handler->common->pkgname, handler->common->id, flag); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_FAULT; } - if (!cb) + if (!cb) { cb = default_pinup_cb; - - handler->pinup_cb = cb; - handler->pinup_cbdata = data; + } ret = master_rpc_async_request(handler, packet, 0, pinup_done_cb, NULL); - if (ret < 0) { - handler->pinup_cb = NULL; - handler->pinup_cbdata = NULL; + if (ret == (int)LB_STATUS_SUCCESS) { + handler->cbs.pinup.cb = cb; + handler->cbs.pinup.data = data; + handler->common->request.pinup = 1; } return ret; @@ -2241,28 +3687,42 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void EAPI int livebox_is_pinned_up(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); return LB_STATUS_ERROR_INVALID; + } - return handler->is_pinned_up; + return handler->common->is_pinned_up; } EAPI int livebox_has_pinup(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Invalid handler\n"); return LB_STATUS_ERROR_INVALID; + } - return handler->lb.pinup_supported; + return handler->common->lb.pinup_supported; } EAPI int livebox_set_data(struct livebox *handler, void *data) @@ -2272,8 +3732,10 @@ EAPI int livebox_set_data(struct livebox *handler, void *data) return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE) + if (handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; + } handler->data = data; return LB_STATUS_SUCCESS; @@ -2286,8 +3748,10 @@ EAPI void *livebox_get_data(struct livebox *handler) return NULL; } - if (handler->state != CREATE) + if (handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; + } return handler->data; } @@ -2307,28 +3771,32 @@ EAPI int livebox_is_exists(const char *pkgname) EAPI const char *livebox_content(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; } - if (handler->state != CREATE) + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); return NULL; + } - return handler->content; + return handler->common->content; } EAPI const char *livebox_category_title(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); return NULL; } - if (handler->state != CREATE) + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); return NULL; + } - return handler->title; + return handler->common->title; } EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission, const char *source, double sx, double sy, double ex, double ey, ret_cb_t cb, void *data) @@ -2337,24 +3805,31 @@ EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission, struct cb_info *cbinfo; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is invalid\n"); return LB_STATUS_ERROR_INVALID; } - if ((handler->lb.type != _LB_TYPE_TEXT && handler->pd.type != _PD_TYPE_TEXT) || handler->state != CREATE || !handler->id) { + if ((handler->common->lb.type != _LB_TYPE_TEXT && handler->common->pd.type != _PD_TYPE_TEXT) || !handler->common->id) { ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (!emission) + if (!emission) { emission = ""; + } - if (!source) + if (!source) { source = ""; + } packet = packet_create("text_signal", "ssssdddd", - handler->pkgname, handler->id, emission, source, sx, sy, ex, ey); + handler->common->pkgname, handler->common->id, emission, source, sx, sy, ex, ey); if (!packet) { ErrPrint("Failed to build a param\n"); return LB_STATUS_ERROR_FAULT; @@ -2367,10 +3842,11 @@ EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission, } ret = master_rpc_async_request(handler, packet, 0, text_signal_cb, cbinfo); - if (ret < 0) + if (ret < 0) { destroy_cb_info(cbinfo); + } - return LB_STATUS_ERROR_FAULT; + return ret; } EAPI int livebox_subscribe_group(const char *cluster, const char *category) @@ -2378,7 +3854,7 @@ EAPI int livebox_subscribe_group(const char *cluster, const char *category) struct packet *packet; /*! - * \TODO + * \todo * Validate the group info using DB * If the group info is not valid, do not send this request */ @@ -2397,7 +3873,7 @@ EAPI int livebox_unsubscribe_group(const char *cluster, const char *category) struct packet *packet; /*! - * \TODO + * \todo * Validate the group info using DB * If the group info is not valid, do not send this request * AND Check the subscribed or not too @@ -2412,19 +3888,26 @@ EAPI int livebox_unsubscribe_group(const char *cluster, const char *category) return master_rpc_request_only(NULL, packet); } -EAPI int livebox_refresh(struct livebox *handler) +EAPI int livebox_refresh(struct livebox *handler, int force) { struct packet *packet; - if (!handler) { - ErrPrint("Hnalder is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; + } - packet = packet_create_noack("update", "ss", handler->pkgname, handler->id); + packet = packet_create_noack("update", "ssi", handler->common->pkgname, handler->common->id, force); if (!packet) { ErrPrint("Failed to create a packet\n"); return LB_STATUS_ERROR_FAULT; @@ -2433,7 +3916,7 @@ EAPI int livebox_refresh(struct livebox *handler) return master_rpc_request_only(handler, packet); } -EAPI int livebox_refresh_group(const char *cluster, const char *category) +EAPI int livebox_refresh_group(const char *cluster, const char *category, int force) { struct packet *packet; @@ -2442,7 +3925,7 @@ EAPI int livebox_refresh_group(const char *cluster, const char *category) return LB_STATUS_ERROR_INVALID; } - packet = packet_create_noack("refresh_group", "ss", cluster, category); + packet = packet_create_noack("refresh_group", "ssi", cluster, category, force); if (!packet) { ErrPrint("Failed to create a packet\n"); return LB_STATUS_ERROR_FAULT; @@ -2453,57 +3936,71 @@ EAPI int livebox_refresh_group(const char *cluster, const char *category) EAPI int livebox_set_visibility(struct livebox *handler, enum livebox_visible_state state) { - struct packet *packet; + int old_state; int ret; - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Handler is not valid\n"); return LB_STATUS_ERROR_INVALID; + } - if (!handler->is_user) { + if (!handler->common->is_user) { /* System cluster livebox cannot be changed its visible states */ - if (state == LB_HIDE_WITH_PAUSE) { + if (state == (int)LB_HIDE_WITH_PAUSE) { ErrPrint("CA Livebox is not able to change the visibility\n"); return LB_STATUS_ERROR_PERMISSION; } } - DbgPrint("Change the visibility %d <> %d, %s\n", handler->visible, state, handler->id); + DbgPrint("[%s] Change visiblity to 0x%x\n", handler->common->pkgname, state); - if (handler->visible == state) + if (handler->visible == state) { + DbgPrint("%s has no changes\n", handler->common->pkgname); return LB_STATUS_ERROR_ALREADY; - - packet = packet_create_noack("change,visibility", "ssi", handler->pkgname, handler->id, (int)state); - if (!packet) { - ErrPrint("Failed to create a packet\n"); - return LB_STATUS_ERROR_FAULT; } - ret = master_rpc_request_only(handler, packet); - if (ret == 0) - handler->visible = state; + old_state = handler->visible; + handler->visible = state; + + ret = lb_set_visibility(handler, state); + if (ret < 0) { + handler->visible = old_state; + } return ret; } EAPI enum livebox_visible_state livebox_visibility(struct livebox *handler) { - if (!handler) { - ErrPrint("Handler is NIL\n"); + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is invalid\n"); + return LB_VISIBLE_ERROR; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); return LB_VISIBLE_ERROR; } - if (handler->state != CREATE || !handler->id) + if (!handler->common->id) { + ErrPrint("Handler is not valid\n"); return LB_VISIBLE_ERROR; + } return handler->visible; } -int lb_set_group(struct livebox *handler, const char *cluster, const char *category) +int lb_set_group(struct livebox_common *common, const char *cluster, const char *category) { void *pc = NULL; void *ps = NULL; @@ -2511,7 +4008,7 @@ int lb_set_group(struct livebox *handler, const char *cluster, const char *categ if (cluster) { pc = strdup(cluster); if (!pc) { - CRITICAL_LOG("Heap: %s (cluster: %s)\n", strerror(errno), cluster); + ErrPrint("Heap: %s (cluster: %s)\n", strerror(errno), cluster); return LB_STATUS_ERROR_MEMORY; } } @@ -2519,45 +4016,47 @@ int lb_set_group(struct livebox *handler, const char *cluster, const char *categ if (category) { ps = strdup(category); if (!ps) { - CRITICAL_LOG("Heap: %s (category: %s)\n", strerror(errno), category); + ErrPrint("Heap: %s (category: %s)\n", strerror(errno), category); free(pc); return LB_STATUS_ERROR_MEMORY; } } - if (handler->cluster) - free(handler->cluster); + if (common->cluster) { + free(common->cluster); + } - if (handler->category) - free(handler->category); + if (common->category) { + free(common->category); + } - handler->cluster = pc; - handler->category = ps; + common->cluster = pc; + common->category = ps; return LB_STATUS_SUCCESS; } -void lb_set_size(struct livebox *handler, int w, int h) +void lb_set_size(struct livebox_common *common, int w, int h) { - handler->lb.width = w; - handler->lb.height = h; + common->lb.width = w; + common->lb.height = h; } -void lb_set_update_mode(struct livebox *handle, int active_mode) +void lb_set_update_mode(struct livebox_common *common, int active_mode) { - handle->is_active_update = active_mode; + common->is_active_update = active_mode; } -void lb_set_pdsize(struct livebox *handler, int w, int h) +void lb_set_pdsize(struct livebox_common *common, int w, int h) { - handler->pd.width = w; - handler->pd.height = h; + common->pd.width = w; + common->pd.height = h; } -void lb_set_default_pdsize(struct livebox *handler, int w, int h) +void lb_set_default_pdsize(struct livebox_common *common, int w, int h) { - handler->pd.default_width = w; - handler->pd.default_height = h; + common->pd.default_width = w; + common->pd.default_height = h; } void lb_invoke_fault_handler(enum livebox_fault_type event, const char *pkgname, const char *file, const char *func) @@ -2566,10 +4065,20 @@ void lb_invoke_fault_handler(enum livebox_fault_type event, const char *pkgname, struct dlist *n; struct fault_info *info; + s_info.fault_state = INFO_STATE_CALLBACK_IN_PROCESSING; + dlist_foreach_safe(s_info.fault_list, l, n, info) { - if (info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE) + if (!info->is_deleted && info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE) { + info->is_deleted = 1; + } + + if (info->is_deleted) { s_info.fault_list = dlist_remove(s_info.fault_list, l); + free(info); + } } + + s_info.fault_state &= ~INFO_STATE_CALLBACK_IN_PROCESSING; } void lb_invoke_event_handler(struct livebox *handler, enum livebox_event_type event) @@ -2578,84 +4087,66 @@ void lb_invoke_event_handler(struct livebox *handler, enum livebox_event_type ev struct dlist *n; struct event_info *info; - dlist_foreach_safe(s_info.event_list, l, n, info) { - if (info->handler(handler, event, info->user_data) == EXIT_FAILURE) - s_info.event_list = dlist_remove(s_info.event_list, l); + if (event == (int)LB_EVENT_LB_UPDATED && handler->common->refcnt > 1) { + if (handler->visible != LB_SHOW) { + DbgPrint("Update requested(pending) - %s\n", handler->common->pkgname); + handler->paused_updating++; + return; + } else { + handler->paused_updating = 0; + } } -} -struct livebox *lb_find_livebox(const char *pkgname, const char *id) -{ - struct dlist *l; - struct livebox *handler; + s_info.event_state = INFO_STATE_CALLBACK_IN_PROCESSING; - dlist_foreach(s_info.livebox_list, l, handler) { - if (!handler->id) - continue; + dlist_foreach_safe(s_info.event_list, l, n, info) { + if (!info->is_deleted && info->handler(handler, event, info->user_data) == EXIT_FAILURE) { + DbgPrint("Event handler returns EXIT_FAILURE\n"); + info->is_deleted = 1; + } - if (!strcmp(handler->pkgname, pkgname) && !strcmp(handler->id, id)) - return handler; + if (info->is_deleted) { + s_info.event_list = dlist_remove(s_info.event_list, l); + free(info); + } } - return NULL; + s_info.event_state &= ~INFO_STATE_CALLBACK_IN_PROCESSING; } -struct livebox *lb_find_livebox_by_timestamp(double timestamp) +struct livebox_common *lb_find_common_handle(const char *pkgname, const char *id) { struct dlist *l; - struct livebox *handler; - - dlist_foreach(s_info.livebox_list, l, handler) { - if (handler->timestamp == timestamp) - return handler; - } - - return NULL; -} - -static inline char *get_file_kept_in_safe(const char *id) -{ - const char *path; - char *new_path; - int len; - int base_idx; - - path = util_uri_to_path(id); - if (!path) { - ErrPrint("Invalid URI(%s)\n", id); - return NULL; - } + struct livebox_common *common; - /*! - * \TODO: REMOVE ME - */ - if (s_info.prevent_overwrite) { - new_path = strdup(path); - if (!new_path) - ErrPrint("Heap: %s\n", strerror(errno)); + dlist_foreach(s_info.livebox_common_list, l, common) { + if (!common->id) { + continue; + } - return new_path; + if (!strcmp(common->pkgname, pkgname) && !strcmp(common->id, id)) { + return common; + } } + return NULL; +} - len = strlen(path); - base_idx = len - 1; - - while (base_idx > 0 && path[base_idx] != '/') base_idx--; - base_idx += (path[base_idx] == '/'); +struct livebox_common *lb_find_common_handle_by_timestamp(double timestamp) +{ + struct dlist *l; + struct livebox_common *common; - new_path = malloc(len + 10); - if (!new_path) { - ErrPrint("Heap: %s\n", strerror(errno)); - return NULL; + dlist_foreach(s_info.livebox_common_list, l, common) { + if (common->timestamp == timestamp) { + return common; + } } - strncpy(new_path, path, base_idx); - snprintf(new_path + base_idx, len + 10 - base_idx, "reader/%s", path + base_idx); - return new_path; + return NULL; } -struct livebox *lb_new_livebox(const char *pkgname, const char *id, double timestamp) +struct livebox *lb_new_livebox(const char *pkgname, const char *id, double timestamp, const char *cluster, const char *category) { struct livebox *handler; @@ -2665,37 +4156,21 @@ struct livebox *lb_new_livebox(const char *pkgname, const char *id, double times return NULL; } - handler->pkgname = strdup(pkgname); - if (!handler->pkgname) { - ErrPrint("%s\n", strerror(errno)); - free(handler); - return NULL; - } - - handler->id = strdup(id); - if (!handler->id) { - ErrPrint("%s\n", strerror(errno)); - free(handler->pkgname); + handler->common = lb_create_common_handle(handler, pkgname, cluster, category); + if (!handler->common) { + ErrPrint("Heap: %s\n", strerror(errno)); free(handler); return NULL; } - handler->filename = get_file_kept_in_safe(id); - if (!handler->filename) { - handler->filename = strdup(util_uri_to_path(id)); - if (!handler->filename) - ErrPrint("Error: %s\n", strerror(errno)); - } - - handler->timestamp = timestamp; - handler->lb.type = _LB_TYPE_FILE; - handler->pd.type = _PD_TYPE_SCRIPT; - handler->state = CREATE; + lb_common_ref(handler->common, handler); + lb_set_id(handler->common, id); + handler->common->timestamp = timestamp; + handler->common->state = CREATE; handler->visible = LB_SHOW; - s_info.livebox_list = dlist_append(s_info.livebox_list, handler); - lb_ref(handler); - return handler; + + return lb_ref(handler); } int lb_delete_all(void) @@ -2706,354 +4181,412 @@ int lb_delete_all(void) dlist_foreach_safe(s_info.livebox_list, l, n, handler) { lb_invoke_event_handler(handler, LB_EVENT_DELETED); - lb_unref(handler); + lb_unref(handler, 1); } return LB_STATUS_SUCCESS; } -int lb_set_content(struct livebox *handler, const char *content) +int lb_set_content(struct livebox_common *common, const char *content) { - if (handler->content) { - DbgPrint("Release content: %s\n", content); - free(handler->content); - handler->content = NULL; - } + char *pc = NULL; if (content) { - DbgPrint("Update Content: [%s]\n", content); - handler->content = strdup(content); - if (!handler->content) { - CRITICAL_LOG("Heap: %s (content: %s)\n", strerror(errno), content); + pc = strdup(content); + if (!pc) { + ErrPrint("heap: %s [%s]\n", strerror(errno), content); return LB_STATUS_ERROR_MEMORY; } } + free(common->content); + common->content = pc; return LB_STATUS_SUCCESS; } -int lb_set_title(struct livebox *handler, const char *title) +int lb_set_title(struct livebox_common *common, const char *title) { - if (handler->title) { - free(handler->title); - handler->title = NULL; - } + char *pt = NULL; if (title) { - handler->title = strdup(title); - if (!handler->title) { - CRITICAL_LOG("Heap: %s (title: %s)\n", strerror(errno), title); + pt = strdup(title); + if (!pt) { + ErrPrint("heap: %s [%s]\n", strerror(errno), title); return LB_STATUS_ERROR_MEMORY; } } + free(common->title); + common->title = pt; return LB_STATUS_SUCCESS; } -void lb_set_size_list(struct livebox *handler, int size_list) +void lb_set_size_list(struct livebox_common *common, int size_list) { - handler->lb.size_list = size_list; + common->lb.size_list = size_list; } -void lb_set_auto_launch(struct livebox *handler, const char *auto_launch) +void lb_set_auto_launch(struct livebox_common *common, const char *auto_launch) { - if (!strlen(auto_launch)) + char *pa = NULL; + + if (!auto_launch || !strlen(auto_launch)) { return; + } - handler->lb.auto_launch = strdup(auto_launch); - if (!handler->lb.auto_launch) - ErrPrint("Heap: %s\n", strerror(errno)); + pa = strdup(auto_launch); + if (!pa) { + ErrPrint("heap: %s, [%s]\n", strerror(errno), auto_launch); + return; + } + + free(common->lb.auto_launch); + common->lb.auto_launch = pa; } -void lb_set_priority(struct livebox *handler, double priority) +void lb_set_priority(struct livebox_common *common, double priority) { - handler->lb.priority = priority; + common->lb.priority = priority; } -void lb_set_id(struct livebox *handler, const char *id) +void lb_set_id(struct livebox_common *common, const char *id) { - if (handler->id) - free(handler->id); + char *pi = NULL; - handler->id = strdup(id); - if (!handler->id) - ErrPrint("Error: %s\n", strerror(errno)); + if (id) { + pi = strdup(id); + if (!pi) { + ErrPrint("heap: %s [%s]\n", strerror(errno), pi); + return; + } + } + + free(common->id); + common->id = pi; +} + +void lb_set_filename(struct livebox_common *common, const char *filename) +{ + if (common->filename) { + if (common->lb.type == _LB_TYPE_FILE || common->lb.type == _LB_TYPE_TEXT) { + if (common->filename[0] && unlink(common->filename) < 0) { + ErrPrint("unlink: %s (%s)\n", strerror(errno), common->filename); + } + } + + free(common->filename); + } + + common->filename = strdup(filename); + if (!common->filename) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} - if (handler->filename) - free(handler->filename); +void lb_set_alt_info(struct livebox_common *common, const char *icon, const char *name) +{ + char *_icon = NULL; + char *_name = NULL; + + if (icon && strlen(icon)) { + _icon = strdup(icon); + if (!_icon) { + ErrPrint("Heap: %s\n", strerror(errno)); + } + } - handler->filename = get_file_kept_in_safe(id); - if (!handler->filename) { - handler->filename = strdup(util_uri_to_path(id)); - if (!handler->filename) - ErrPrint("Error: %s\n", strerror(errno)); + if (name && strlen(name)) { + _name = strdup(name); + if (!_name) { + ErrPrint("Heap: %s\n", strerror(errno)); + } } + + free(common->alt.icon); + common->alt.icon = _icon; + + free(common->alt.name); + common->alt.name = _name; } -int lb_set_lb_fb(struct livebox *handler, const char *filename) +int lb_set_lb_fb(struct livebox_common *common, const char *filename) { struct fb_info *fb; - if (!handler) + if (!common) { return LB_STATUS_ERROR_INVALID; + } - fb = handler->lb.data.fb; - if (fb && !strcmp(fb_id(fb), filename)) /*!< BUFFER is not changed, */ + fb = common->lb.fb; + if (fb && !strcmp(fb_id(fb), filename)) { /*!< BUFFER is not changed, */ return LB_STATUS_SUCCESS; + } - handler->lb.data.fb = NULL; + common->lb.fb = NULL; if (!filename || filename[0] == '\0') { - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_SUCCESS; } - handler->lb.data.fb = fb_create(filename, handler->lb.width, handler->lb.height); - if (!handler->lb.data.fb) { + common->lb.fb = fb_create(filename, common->lb.width, common->lb.height); + if (!common->lb.fb) { ErrPrint("Faield to create a FB\n"); - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_ERROR_FAULT; } - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_SUCCESS; } -int lb_set_pd_fb(struct livebox *handler, const char *filename) +int lb_set_pd_fb(struct livebox_common *common, const char *filename) { struct fb_info *fb; - if (!handler) + if (!common || common->state != CREATE) { return LB_STATUS_ERROR_INVALID; + } - fb = handler->pd.data.fb; + fb = common->pd.fb; if (fb && !strcmp(fb_id(fb), filename)) { /* BUFFER is not changed, just update the content */ return LB_STATUS_ERROR_EXIST; } - handler->pd.data.fb = NULL; + common->pd.fb = NULL; if (!filename || filename[0] == '\0') { - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_SUCCESS; } - handler->pd.data.fb = fb_create(filename, handler->pd.width, handler->pd.height); - if (!handler->pd.data.fb) { + common->pd.fb = fb_create(filename, common->pd.width, common->pd.height); + if (!common->pd.fb) { ErrPrint("Failed to create a FB\n"); - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_ERROR_FAULT; } - if (fb) + if (fb) { fb_destroy(fb); + } return LB_STATUS_SUCCESS; } -struct fb_info *lb_get_lb_fb(struct livebox *handler) +struct fb_info *lb_get_lb_fb(struct livebox_common *common) { - return handler->lb.data.fb; + return common->lb.fb; } -struct fb_info *lb_get_pd_fb(struct livebox *handler) +struct fb_info *lb_get_pd_fb(struct livebox_common *common) { - return handler->pd.data.fb; + return common->pd.fb; } -void lb_set_user(struct livebox *handler, int user) +void lb_set_user(struct livebox_common *common, int user) { - handler->is_user = user; + common->is_user = user; } -void lb_set_pinup(struct livebox *handler, int pinup_supported) +void lb_set_pinup(struct livebox_common *common, int pinup_supported) { - handler->lb.pinup_supported = pinup_supported; + common->lb.pinup_supported = pinup_supported; } -void lb_set_text_lb(struct livebox *handler) +void lb_set_text_lb(struct livebox_common *common) { - handler->lb.type = _LB_TYPE_TEXT; + common->lb.type = _LB_TYPE_TEXT; } -void lb_set_text_pd(struct livebox *handler) +void lb_set_text_pd(struct livebox_common *common) { - handler->pd.type = _PD_TYPE_TEXT; + common->pd.type = _PD_TYPE_TEXT; } -int lb_text_lb(struct livebox *handler) +int lb_text_lb(struct livebox_common *common) { - return handler->lb.type == _LB_TYPE_TEXT; + return common->lb.type == _LB_TYPE_TEXT; } -int lb_text_pd(struct livebox *handler) +int lb_text_pd(struct livebox_common *common) { - return handler->pd.type == _PD_TYPE_TEXT; + return common->pd.type == _PD_TYPE_TEXT; } -void lb_set_period(struct livebox *handler, double period) +void lb_set_period(struct livebox_common *common, double period) { - handler->lb.period = period; + common->lb.period = period; } struct livebox *lb_ref(struct livebox *handler) { - if (!handler) + if (!handler) { return NULL; + } handler->refcnt++; return handler; } -struct livebox *lb_unref(struct livebox *handler) +struct livebox *lb_unref(struct livebox *handler, int destroy_common) { - if (!handler) + if (!handler) { return NULL; + } handler->refcnt--; - if (handler->refcnt > 0) + if (handler->refcnt > 0) { return handler; + } - if (handler->created_cb) { - DbgPrint("Clear created event callback\n"); - handler->created_cb(handler, LB_STATUS_ERROR_FAULT, handler->created_cbdata); - handler->created_cb = NULL; - handler->created_cbdata = NULL; + if (handler->cbs.created.cb) { + handler->cbs.created.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.created.data); + handler->cbs.created.cb = NULL; + handler->cbs.created.data = NULL; } - if (handler->deleted_cb) { - DbgPrint("Clear deleted event callback\n"); - handler->deleted_cb(handler, LB_STATUS_ERROR_FAULT, handler->deleted_cbdata); - handler->deleted_cb = NULL; - handler->deleted_cbdata = NULL; + if (handler->cbs.deleted.cb) { + handler->cbs.deleted.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.deleted.data); + handler->cbs.deleted.cb = NULL; + handler->cbs.deleted.data = NULL; } - if (handler->pinup_cb) { - DbgPrint("Clear pinup event callback\n"); - handler->pinup_cb(handler, LB_STATUS_ERROR_FAULT, handler->pinup_cbdata); - handler->pinup_cb = NULL; - handler->pinup_cbdata = NULL; + if (handler->cbs.pinup.cb) { + handler->cbs.pinup.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.pinup.data); + handler->cbs.pinup.cb = NULL; + handler->cbs.pinup.data = NULL; } - if (handler->group_changed_cb) { - DbgPrint("Clear group changed event callback\n"); - handler->group_changed_cb(handler, LB_STATUS_ERROR_FAULT, handler->group_cbdata); - handler->group_changed_cb = NULL; - handler->group_cbdata = NULL; + if (handler->cbs.group_changed.cb) { + handler->cbs.group_changed.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.group_changed.data); + handler->cbs.group_changed.cb = NULL; + handler->cbs.group_changed.data = NULL; } - if (handler->period_changed_cb) { - DbgPrint("Clear period changed event callback\n"); - handler->period_changed_cb(handler, LB_STATUS_ERROR_FAULT, handler->period_cbdata); - handler->period_changed_cb = NULL; - handler->period_cbdata = NULL; + if (handler->cbs.period_changed.cb) { + handler->cbs.period_changed.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.period_changed.data); + handler->cbs.period_changed.cb = NULL; + handler->cbs.period_changed.data = NULL; } - if (handler->size_changed_cb) { - DbgPrint("Clear size changed event callback\n"); - handler->size_changed_cb(handler, LB_STATUS_ERROR_FAULT, handler->size_cbdata); - handler->size_changed_cb = NULL; - handler->size_cbdata = NULL; + if (handler->cbs.size_changed.cb) { + handler->cbs.size_changed.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.size_changed.data); + handler->cbs.size_changed.cb = NULL; + handler->cbs.size_changed.data = NULL; } - if (handler->pd_created_cb) { - DbgPrint("Clear pd created event callback\n"); - handler->pd_created_cb(handler, LB_STATUS_ERROR_FAULT, handler->pd_created_cbdata); - handler->pd_created_cb = NULL; - handler->pd_created_cbdata = NULL; + if (handler->cbs.pd_created.cb) { + handler->cbs.pd_created.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.pd_created.data); + handler->cbs.pd_created.cb = NULL; + handler->cbs.pd_created.data = NULL; } - if (handler->pd_destroyed_cb) { - DbgPrint("Clear pd destroyed event callback\n"); - handler->pd_destroyed_cb(handler, LB_STATUS_ERROR_FAULT, handler->pd_destroyed_cbdata); - handler->pd_destroyed_cb = NULL; - handler->pd_destroyed_cbdata = NULL; + if (handler->cbs.pd_destroyed.cb) { + handler->cbs.pd_destroyed.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.pd_destroyed.data); + handler->cbs.pd_destroyed.cb = NULL; + handler->cbs.pd_destroyed.data = NULL; } - if (handler->update_mode_cb) { - DbgPrint("Clear update mode callback\n"); - handler->update_mode_cb(handler, LB_STATUS_ERROR_FAULT, handler->update_mode_cbdata); - handler->update_mode_cb = NULL; - handler->update_mode_cbdata = NULL; + if (handler->cbs.update_mode.cb) { + handler->cbs.update_mode.cb(handler, LB_STATUS_ERROR_FAULT, handler->cbs.update_mode.data); + handler->cbs.update_mode.cb = NULL; + handler->cbs.update_mode.data = NULL; } - if (handler->access_event_cb) { - DbgPrint("Clear access status callback\n"); - handler->access_event_cb(handler, LB_STATUS_ERROR_FAULT, handler->access_event_cbdata); - handler->access_event_cb = NULL; - handler->access_event_cbdata = NULL; + if (handler->cbs.access_event.cb) { + handler->cbs.access_event.cb(handler, LB_ACCESS_STATUS_ERROR, handler->cbs.access_event.data); + handler->cbs.access_event.cb = NULL; + handler->cbs.access_event.data = NULL; } - if (handler->filename) - util_unlink(handler->filename); + if (handler->cbs.key_event.cb) { + handler->cbs.key_event.cb(handler, LB_KEY_STATUS_ERROR, handler->cbs.key_event.data); + handler->cbs.key_event.cb = NULL; + handler->cbs.key_event.data = NULL; + } dlist_remove_data(s_info.livebox_list, handler); handler->state = DESTROYED; - free(handler->cluster); - free(handler->category); - free(handler->id); - free(handler->pkgname); - free(handler->filename); - free(handler->lb.auto_launch); - - if (handler->lb.data.fb) { - fb_destroy(handler->lb.data.fb); - handler->lb.data.fb = NULL; - } - - if (handler->pd.data.fb) { - fb_destroy(handler->pd.data.fb); - handler->pd.data.fb = NULL; + if (lb_common_unref(handler->common, handler) == 0) { + if (destroy_common) { + /*! + * \note + * Lock file should be deleted after all callbacks are processed. + */ + lb_destroy_lock_file(handler->common, 0); + lb_destroy_common_handle(handler->common); + } } - free(handler); + DbgPrint("Handler is released\n"); return NULL; } -int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data) +int lb_send_delete(struct livebox *handler, int type, ret_cb_t cb, void *data) { struct packet *packet; struct cb_info *cbinfo; int ret; - if (!cb && !!data) { - ErrPrint("Invalid argument\n"); - return LB_STATUS_ERROR_INVALID; - } - - if (handler->deleted_cb) { + if (handler->common->request.deleted) { ErrPrint("Already in-progress\n"); + if (cb) { + cb(handler, LB_STATUS_SUCCESS, data); + } return LB_STATUS_ERROR_BUSY; } - packet = packet_create("delete", "ss", handler->pkgname, handler->id); + if (!cb) { + cb = default_delete_cb; + } + + packet = packet_create("delete", "ssid", handler->common->pkgname, handler->common->id, type, handler->common->timestamp); if (!packet) { ErrPrint("Failed to build a param\n"); - if (cb) + if (cb) { cb(handler, LB_STATUS_ERROR_FAULT, data); + } return LB_STATUS_ERROR_FAULT; } - if (!cb) - cb = default_delete_cb; - cbinfo = create_cb_info(cb, data); if (!cbinfo) { packet_destroy(packet); + ErrPrint("Failed to create cbinfo\n"); + if (cb) { + cb(handler, LB_STATUS_ERROR_FAULT, data); + } + return LB_STATUS_ERROR_FAULT; } ret = master_rpc_async_request(handler, packet, 0, del_ret_cb, cbinfo); - if (ret < 0) + if (ret < 0) { + /*! + * Packet is destroyed by master_rpc_async_request. + */ destroy_cb_info(cbinfo); + if (cb) { + cb(handler, LB_STATUS_ERROR_FAULT, data); + } + } else { + handler->common->request.deleted = 1; + } + return ret; } @@ -3083,4 +4616,253 @@ EAPI int livebox_client_resumed(void) return master_rpc_request_only(NULL, packet); } +EAPI int livebox_sync_lb_fb(struct livebox *handler) +{ + if (!handler || handler->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + return LB_STATUS_ERROR_INVALID; + } + + return lb_sync_lb_fb(handler->common); +} + +int lb_sync_lb_fb(struct livebox_common *common) +{ + int ret; + + if (fb_type(lb_get_lb_fb(common)) == BUFFER_TYPE_FILE && common->lb.lock_fd >= 0) { + (void)do_fb_lock(common->lb.lock_fd); + ret = fb_sync(lb_get_lb_fb(common)); + (void)do_fb_unlock(common->lb.lock_fd); + } else { + ret = fb_sync(lb_get_lb_fb(common)); + } + + return ret; +} + +int lb_sync_pd_fb(struct livebox_common *common) +{ + int ret; + + if (fb_type(lb_get_pd_fb(common)) == BUFFER_TYPE_FILE && common->pd.lock_fd >= 0) { + (void)do_fb_lock(common->pd.lock_fd); + ret = fb_sync(lb_get_pd_fb(common)); + (void)do_fb_unlock(common->pd.lock_fd); + } else { + ret = fb_sync(lb_get_pd_fb(common)); + } + + return ret; +} + +EAPI int livebox_sync_pd_fb(struct livebox *handler) +{ + if (!handler || handler->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + return lb_sync_pd_fb(handler->common); +} + +EAPI const char *livebox_alt_icon(struct livebox *handler) +{ + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is not valid[%p]\n", handler); + return NULL; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return NULL; + } + + return handler->common->alt.icon; +} + +EAPI const char *livebox_alt_name(struct livebox *handler) +{ + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is not valid[%p]\n", handler); + return NULL; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return NULL; + } + + return handler->common->alt.name; +} + +EAPI int livebox_acquire_fb_lock(struct livebox *handler, int is_pd) +{ + int ret = LB_STATUS_SUCCESS; + int fd; + + if (!handler || handler->state != CREATE) { + ErrPrint("Handler is not valid[%p]\n", handler); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Handler is not valid\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Handler is not valid[%p]\n", handler); + return LB_STATUS_ERROR_INVALID; + } + + if (is_pd) { + if (!handler->common->pd.lock || handler->common->pd.lock_fd < 0) { + DbgPrint("Lock: %s (%d)\n", handler->common->pd.lock, handler->common->pd.lock_fd); + return LB_STATUS_ERROR_INVALID; + } + + if (fb_type(lb_get_pd_fb(handler->common)) == BUFFER_TYPE_FILE) { + return LB_STATUS_SUCCESS; + } + + fd = handler->common->pd.lock_fd; + } else { + if (!handler->common->lb.lock || handler->common->lb.lock_fd < 0) { + DbgPrint("Lock: %s (%d)\n", handler->common->lb.lock, handler->common->lb.lock_fd); + return LB_STATUS_ERROR_INVALID; + } + + if (fb_type(lb_get_lb_fb(handler->common)) == BUFFER_TYPE_FILE) { + return LB_STATUS_SUCCESS; + } + + fd = handler->common->lb.lock_fd; + } + + ret = do_fb_lock(fd); + + return ret == 0 ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_FAULT; +} + +EAPI int livebox_release_fb_lock(struct livebox *handler, int is_pd) +{ + int ret = LB_STATUS_SUCCESS; + int fd; + + if (!handler || handler->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common || handler->common->state != CREATE) { + ErrPrint("Invalid handle\n"); + return LB_STATUS_ERROR_INVALID; + } + + if (!handler->common->id) { + ErrPrint("Handler is not valid[%p]\n", handler); + return LB_STATUS_ERROR_INVALID; + } + + if (is_pd) { + if (!handler->common->pd.lock || handler->common->pd.lock_fd < 0) { + DbgPrint("Unlock: %s (%d)\n", handler->common->pd.lock, handler->common->pd.lock_fd); + return LB_STATUS_ERROR_INVALID; + } + + if (fb_type(lb_get_pd_fb(handler->common)) == BUFFER_TYPE_FILE) { + return LB_STATUS_SUCCESS; + } + + fd = handler->common->pd.lock_fd; + } else { + if (!handler->common->lb.lock || handler->common->lb.lock_fd < 0) { + DbgPrint("Unlock: %s (%d)\n", handler->common->lb.lock, handler->common->lb.lock_fd); + return LB_STATUS_ERROR_INVALID; + } + + if (fb_type(lb_get_lb_fb(handler->common)) == BUFFER_TYPE_FILE) { + return LB_STATUS_SUCCESS; + } + + fd = handler->common->lb.lock_fd; + } + + ret = do_fb_unlock(fd); + + return ret == 0 ? LB_STATUS_SUCCESS : LB_STATUS_ERROR_FAULT; +} + +EAPI int livebox_set_option(enum livebox_option_type option, int state) +{ + int ret = LB_STATUS_SUCCESS; + + switch (option) { + case LB_OPTION_MANUAL_SYNC: + conf_set_manual_sync(state); + break; + case LB_OPTION_FRAME_DROP_FOR_RESIZE: + conf_set_frame_drop_for_resizing(state); + break; + case LB_OPTION_SHARED_CONTENT: + conf_set_shared_content(state); + break; + default: + ret = LB_STATUS_ERROR_INVALID; + break; + } + + return ret; +} + +EAPI int livebox_option(enum livebox_option_type option) +{ + int ret; + + switch (option) { + case LB_OPTION_MANUAL_SYNC: + ret = conf_manual_sync(); + break; + case LB_OPTION_FRAME_DROP_FOR_RESIZE: + ret = conf_frame_drop_for_resizing(); + break; + case LB_OPTION_SHARED_CONTENT: + ret = conf_shared_content(); + break; + default: + ret = LB_STATUS_ERROR_INVALID; + break; + } + + return ret; +} + +EAPI int livebox_set_auto_launch_handler(int (*launch_handler)(struct livebox *handler, const char *appid, void *data), void *data) +{ + s_info.launch.handler = launch_handler; + s_info.launch.data = data; + + return LB_STATUS_SUCCESS; +} + /* End of a file */