Update accessibility event code.
authorSung-jae Park <nicesj.park@samsung.com>
Thu, 4 Apr 2013 12:38:15 +0000 (12:38 +0000)
committerSung-jae Park <nicesj.park@samsung.com>
Thu, 4 Apr 2013 15:58:04 +0000 (15:58 +0000)
Add new API for sending accessibility event to provider.

Clear all registered event callbacks if an instance is destroyed by fault.
To give time to release their resources for event callbacks.

Access status event type is added.
Access status would be sent from the provider.

Update VERSION

Change-Id: I760abf4ee5f2dfc62b08744f982cbbd5d2625505

include/livebox.h
include/livebox_internal.h
packaging/liblivebox-viewer.spec
src/client.c
src/livebox.c
src/master_rpc.c

index c5373a9..f262a5e 100644 (file)
@@ -43,18 +43,10 @@ enum content_event_type {
        CONTENT_EVENT_MOUSE_SET         = 0x00000020, /*!< LB mouse set auto event for livebox */
        CONTENT_EVENT_MOUSE_UNSET       = 0x00000040, /*!< LB mouse unset auto event for livebox */
 
-       CONTENT_EVENT_ACCESS_HIGHLIGHT  = 0x00000100, /*!< LB accessibility: Hightlight a object */
-       CONTENT_EVENT_ACCESS_HIGHLIGHT_NEXT     = 0x00000200, /*!< LB accessibility: Set highlight to next object */
-       CONTENT_EVENT_ACCESS_HIGHLIGHT_PREV     = 0x00000400, /*!< LB accessibility: Set highlight to prev object */
-       CONTENT_EVENT_ACCESS_ACTIVATE   = 0x00000800, /*!< LB accessibility activate */
-       CONTENT_EVENT_ACCESS_VALUE_CHANGE       = 0x00001000, /*!< LB accessibility up */
-       CONTENT_EVENT_ACCESS_SCROLL     = 0x00002000, /*!< LB accessibility down */
-
        CONTENT_EVENT_KEY_DOWN          = 0x00100000, /*!< LB key press */
        CONTENT_EVENT_KEY_UP            = 0x00200000, /*!< LB key release */
 
        CONTENT_EVENT_KEY_MASK          = 0x80000000,
-       CONTENT_EVENT_ACCESS_MASK       = 0x40000000,
        CONTENT_EVENT_MOUSE_MASK        = 0x20000000,
        CONTENT_EVENT_PD_MASK           = 0x10000000,
        CONTENT_EVENT_LB_MASK           = 0x00000000,
@@ -75,20 +67,6 @@ enum content_event_type {
        PD_MOUSE_SET                    = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_SET,
        PD_MOUSE_UNSET                  = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_MOUSE_MASK | CONTENT_EVENT_MOUSE_UNSET,
 
-       LB_ACCESS_HIGHLIGHT             = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT,
-       LB_ACCESS_HIGHLIGHT_NEXT        = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT_NEXT,
-       LB_ACCESS_HIGHLIGHT_PREV        = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT_PREV,
-       LB_ACCESS_ACTIVATE              = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_ACTIVATE,
-       LB_ACCESS_VALUE_CHANGE          = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_VALUE_CHANGE,
-       LB_ACCESS_SCROLL                = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_SCROLL,
-
-       PD_ACCESS_HIGHLIGHT             = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT,
-       PD_ACCESS_HIGHLIGHT_NEXT        = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT_NEXT,
-       PD_ACCESS_HIGHLIGHT_PREV        = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_HIGHLIGHT_PREV,
-       PD_ACCESS_ACTIVATE              = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_ACTIVATE,
-       PD_ACCESS_VALUE_CHANGE          = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_VALUE_CHANGE,
-       PD_ACCESS_SCROLL                = CONTENT_EVENT_PD_MASK | CONTENT_EVENT_ACCESS_MASK | CONTENT_EVENT_ACCESS_SCROLL,
-
        LB_KEY_DOWN                     = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_DOWN,
        LB_KEY_UP                       = CONTENT_EVENT_LB_MASK | CONTENT_EVENT_KEY_MASK | CONTENT_EVENT_KEY_UP,
 
@@ -98,6 +76,32 @@ enum content_event_type {
        CONTENT_EVENT_MAX       = 0xFFFFFFFF,
 };
 
+enum access_event_type {
+       ACCESS_EVENT_PD_MASK            = 0x10000000,
+       ACCESS_EVENT_LB_MASK            = 0x00000000,
+
+       ACCESS_EVENT_HIGHLIGHT          = 0x00000100, /*!< LB accessibility: Hightlight a object */
+       ACCESS_EVENT_HIGHLIGHT_NEXT     = 0x00000200, /*!< LB accessibility: Set highlight to next object */
+       ACCESS_EVENT_HIGHLIGHT_PREV     = 0x00000400, /*!< LB accessibility: Set highlight to prev object */
+       ACCESS_EVENT_ACTIVATE           = 0x00000800, /*!< LB accessibility activate */
+       ACCESS_EVENT_VALUE_CHANGE       = 0x00001000, /*!< LB accessibility up */
+       ACCESS_EVENT_SCROLL             = 0x00002000, /*!< LB accessibility down */
+
+       LB_ACCESS_HIGHLIGHT             = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_HIGHLIGHT,
+       LB_ACCESS_HIGHLIGHT_NEXT        = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_HIGHLIGHT_NEXT,
+       LB_ACCESS_HIGHLIGHT_PREV        = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_HIGHLIGHT_PREV,
+       LB_ACCESS_ACTIVATE              = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_ACTIVATE,
+       LB_ACCESS_VALUE_CHANGE          = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_VALUE_CHANGE,
+       LB_ACCESS_SCROLL                = ACCESS_EVENT_LB_MASK | ACCESS_EVENT_SCROLL,
+
+       PD_ACCESS_HIGHLIGHT             = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_HIGHLIGHT,
+       PD_ACCESS_HIGHLIGHT_NEXT        = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_HIGHLIGHT_NEXT,
+       PD_ACCESS_HIGHLIGHT_PREV        = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_HIGHLIGHT_PREV,
+       PD_ACCESS_ACTIVATE              = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_ACTIVATE,
+       PD_ACCESS_VALUE_CHANGE          = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_VALUE_CHANGE,
+       PD_ACCESS_SCROLL                = ACCESS_EVENT_PD_MASK | ACCESS_EVENT_SCROLL,
+};
+
 /* Exported to user app */
 enum livebox_lb_type {
        LB_TYPE_IMAGE = 0x01, /*!< Contents of a livebox is based on the image file */
@@ -487,10 +491,23 @@ extern int livebox_pdfb_bufsz(struct livebox *handler);
  * \param[in] type
  * \param[in] x
  * \param[in] y
+ * \return
  */
 extern int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y);
 
 /*!
+ * \brief Send the access event(for buffer type) to provider(livebox).
+ * \param[in] handler
+ * \param[in] access_event_type
+ * \param[in] x
+ * \param[in] y
+ * \param[in] cb
+ * \param[in] data
+ * \return
+ */
+extern int livebox_access_event(struct livebox *handler, enum access_event_type type, double x, double y, ret_cb_t cb, void *data);
+
+/*!
  * \brief Do pin up or not.
  * \param[in] handler
  * \param[in] flag
index bfb3d16..d5c39ab 100644 (file)
@@ -158,6 +158,9 @@ struct livebox {
 
        ret_cb_t update_mode_cb;
        void *update_mode_cbdata;
+
+       ret_cb_t access_event_cb;
+       void *access_event_cbdata;
 };
 
 /* End of a file */
index e7b3954..a7a4c0b 100644 (file)
@@ -1,6 +1,6 @@
 Name: liblivebox-viewer
 Summary: Library for developing the application.
-Version: 0.11.0
+Version: 0.12.0
 Release: 1
 Group: HomeTF/Livebox
 License: Flora License
index 42fc561..dcb30d3 100644 (file)
@@ -350,6 +350,42 @@ out:
        return NULL;
 }
 
+static struct packet *master_access_status(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       int status;
+
+       ret = packet_get(packet, "ssi", &pkgname, &id, &status);
+       if (ret != 3) {
+               ErrPrint("Invalid argument\n");
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ErrPrint("Instance[%s] is not exists\n", id);
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               DbgPrint("[%s] is not created\n", id);
+               goto out;
+       }
+
+       if (handler->access_event_cb) {
+               handler->access_event_cb(handler, status, handler->access_event_cbdata);
+               handler->access_event_cb = NULL;
+               handler->access_event_cbdata = NULL;
+       } else {
+               ErrPrint("Invalid event[%s]\n", id);
+       }
+out:
+       return NULL;
+}
+
 static struct packet *master_pd_update_end(pid_t pid, int handle, const struct packet *packet)
 {
        struct livebox *handler;
@@ -1121,6 +1157,11 @@ static struct method s_table[] = {
        },
 
        {
+               .cmd = "access_status",
+               .handler = master_access_status,
+       },
+
+       {
                .cmd = NULL,
                .handler = NULL,
        },
index 70c2ce7..a518b09 100644 (file)
@@ -121,6 +121,11 @@ static inline void default_update_mode_cb(struct livebox *handler, int ret, void
        DbgPrint("Default update mode set event handler: %d\n", ret);
 }
 
+static inline void default_access_event_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default access 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;
@@ -144,29 +149,28 @@ static inline void destroy_cb_info(struct cb_info *info)
 static void update_mode_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;
+               goto errout;
        } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = LB_STATUS_ERROR_INVALID;
+               goto errout;
        }
 
-       if (ret == 0) {
-               DbgPrint("Update mode set is done, prepare the update mode set event\n");
-               handler->update_mode_cb = cb;
-               handler->update_mode_cbdata = cbdata;
-       } else {
+       if (ret < 0) {
                DbgPrint("Resize request is failed: %d\n", ret);
-               cb(handler, ret, cbdata);
+               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;
 }
 
 static void resize_cb(struct livebox *handler, const struct packet *result, void *data)
@@ -182,9 +186,11 @@ static void resize_cb(struct livebox *handler, const struct packet *result, void
 
        if (!result) {
                ret = LB_STATUS_ERROR_FAULT;
+               goto errout;
        } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = LB_STATUS_ERROR_INVALID;
+               goto errout;
        }
 
        /*!
@@ -196,14 +202,18 @@ static void resize_cb(struct livebox *handler, const struct packet *result, void
         * So the user can only get the resized value(result) from the first update event
         * after this request.
         */
-       if (ret == 0) {
-               DbgPrint("Resize request is done, prepare the size changed event\n");
-               handler->size_changed_cb = cb;
-               handler->size_cbdata = cbdata;
-       } else {
+       if (ret < 0) {
                DbgPrint("Resize request is failed: %d\n", ret);
-               cb(handler, ret, cbdata);
+               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;
 }
 
 static void text_signal_cb(struct livebox *handler, const struct packet *result, void *data)
@@ -232,55 +242,50 @@ static void text_signal_cb(struct livebox *handler, const struct packet *result,
 static void set_group_ret_cb(struct livebox *handler, const struct packet *result, void *data)
 {
        int ret;
-       void *cbdata;
-       ret_cb_t cb;
-       struct cb_info *info = data;
-
-       cbdata = info->data;
-       cb = info->cb;
-       destroy_cb_info(info);
 
        if (!result) {
                ret = LB_STATUS_ERROR_FAULT;
+               goto errout;
        } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = LB_STATUS_ERROR_INVALID;
+               goto errout;
        }
 
-       if (ret == 0) { /*!< Group information is successfully changed */
-               handler->group_changed_cb = cb;
-               handler->group_cbdata = cbdata;
-       } else if (cb) {
-               cb(handler, ret, cbdata);
-       }
+       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;
 }
 
 static void period_ret_cb(struct livebox *handler, const struct packet *result, void *data)
 {
-       struct cb_info *info = data;
        int ret;
-       ret_cb_t cb;
-       void *cbdata;
-
-       cb = info->cb;
-       cbdata = info->data;
-       destroy_cb_info(info);
 
        if (!result) {
                ret = LB_STATUS_ERROR_FAULT;
+               goto errout;
        } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = LB_STATUS_ERROR_INVALID;
+               goto errout;
        }
 
-       if (ret == 0) {
-               handler->period_changed_cb = cb;
-               handler->period_cbdata = cbdata;
-       } else if (cb) {
-               cb(handler, ret, cbdata);
-       }
+       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;
 }
 
 static void del_ret_cb(struct livebox *handler, const struct packet *result, void *data)
@@ -363,29 +368,27 @@ static void new_ret_cb(struct livebox *handler, const struct packet *result, voi
 
 static void pd_create_cb(struct livebox *handler, const struct packet *result, void *data)
 {
-       struct cb_info *info = data;
-       void *cbdata;
-       ret_cb_t cb;
        int ret;
 
-       cb = info->cb;
-       cbdata = info->data;
-       destroy_cb_info(data);
-
        if (!result) {
                ret = LB_STATUS_ERROR_FAULT;
+               goto errout;
        } else if (packet_get(result, "i", &ret) != 1) {
                ret = LB_STATUS_ERROR_INVALID;
+               goto errout;
        }
 
-       if (ret == 0) {
-               DbgPrint("PD Created event handler prepared\n");
-               handler->pd_created_cb = cb;
-               handler->pd_created_cbdata = cbdata;
-       } else if (cb) {
+       if (ret < 0) {
                DbgPrint("Failed to create a PD\n");
-               cb(handler, ret, cbdata);
+               goto errout;
        }
+
+       return;
+
+errout:
+       handler->pd_created_cb(handler, ret, handler->pd_created_cbdata);
+       handler->pd_created_cb = NULL;
+       handler->pd_created_cbdata = NULL;
 }
 
 static void activated_cb(struct livebox *handler, const struct packet *result, void *data)
@@ -508,25 +511,69 @@ static void pixmap_acquired_cb(struct livebox *handler, const struct packet *res
 static void pinup_done_cb(struct livebox *handler, const struct packet *result, void *data)
 {
        int ret;
-       ret_cb_t cb;
-       void *cbdata;
-       struct cb_info *info = data;
 
-       cb = info->cb;
-       cbdata = info->data;
-       destroy_cb_info(info);
+       if (!result) {
+               ret = LB_STATUS_ERROR_FAULT;
+               goto errout;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               goto errout;
+       }
 
-       if (!result)
+       if (ret < 0)
+               goto errout;
+
+       return;
+
+errout:
+       handler->pinup_cb(handler, ret, handler->pinup_cbdata);
+       handler->pinup_cb = NULL;
+       handler->pinup_cbdata = NULL;
+}
+
+static void access_ret_cb(struct livebox *handler, const struct packet *result, void *data)
+{
+       int ret;
+
+       if (!result) {
                ret = LB_STATUS_ERROR_FAULT;
-       else if (packet_get(result, "i", &ret) != 1)
+               return;
+       }
+
+       if (packet_get(result, "i", &ret) != 1) {
                ret = LB_STATUS_ERROR_INVALID;
+               return;
+       }
 
-       if (ret == 0) {
-               handler->pinup_cb = cb;
-               handler->pinup_cbdata = cbdata;
-       } else if (cb) {
-               cb(handler, ret, cbdata);
+       if (ret != LB_STATUS_SUCCESS) {
+               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;
+}
+
+static int send_access_event(struct livebox *handler, const char *event, int x, int y)
+{
+       struct packet *packet;
+       double timestamp;
+
+       timestamp = util_timestamp();
+
+       packet = packet_create(event, "ssdii", handler->pkgname, handler->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_mouse_event(struct livebox *handler, const char *event, int x, int y)
@@ -627,6 +674,7 @@ EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *cont
        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",
@@ -718,9 +766,22 @@ EAPI struct livebox *livebox_add_with_size(const char *pkgname, const char *cont
                return NULL;
        }
 
-       ret = master_rpc_async_request(handler, packet, 0, new_ret_cb, create_cb_info(cb, data));
+       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);
+               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);
@@ -747,6 +808,7 @@ EAPI double livebox_period(struct livebox *handler)
 EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       int ret;
 
        if (!handler || handler->state != CREATE || !handler->id) {
                ErrPrint("Handler is not valid\n");
@@ -777,7 +839,16 @@ EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb,
        if (!cb)
                cb = default_period_changed_cb;
 
-       return master_rpc_async_request(handler, packet, 0, period_ret_cb, create_cb_info(cb, data));
+       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;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data)
@@ -899,6 +970,7 @@ EAPI void *livebox_unset_event_handler(int (*cb)(struct livebox *, enum livebox_
 EAPI int livebox_set_update_mode(struct livebox *handler, int active_update, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       int ret;
 
        if (!handler) {
                ErrPrint("Handler is NIL\n");
@@ -926,7 +998,16 @@ EAPI int livebox_set_update_mode(struct livebox *handler, int active_update, ret
        if (!cb)
                cb = default_update_mode_cb;
 
-       return master_rpc_async_request(handler, packet, 0, update_mode_cb, create_cb_info(cb, data));
+       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;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_is_active_update(struct livebox *handler)
@@ -947,6 +1028,7 @@ EAPI int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *da
        struct packet *packet;
        int w;
        int h;
+       int ret;
 
        if (!handler) {
                ErrPrint("Handler is NIL\n");
@@ -987,7 +1069,16 @@ EAPI int livebox_resize(struct livebox *handler, int type, ret_cb_t cb, void *da
        if (!cb)
                cb = default_lb_size_changed_cb;
 
-       return master_rpc_async_request(handler, packet, 0, resize_cb, create_cb_info(cb, data));
+       handler->size_changed_cb = cb;
+       handler->size_cbdata = data;
+
+       ret = master_rpc_async_request(handler, packet, 0, resize_cb, NULL);
+       if (ret < 0) {
+               handler->size_changed_cb = NULL;
+               handler->size_cbdata = NULL;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_click(struct livebox *handler, double x, double y)
@@ -1076,6 +1167,7 @@ EAPI int livebox_create_pd(struct livebox *handler, ret_cb_t cb, void *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");
@@ -1092,6 +1184,11 @@ EAPI int livebox_create_pd_with_position(struct livebox *handler, double x, doub
                return LB_STATUS_SUCCESS;
        }
 
+       if (handler->pd_created_cb) {
+               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);
        if (!packet) {
                ErrPrint("Failed to build param\n");
@@ -1099,9 +1196,18 @@ EAPI int livebox_create_pd_with_position(struct livebox *handler, double x, doub
        }
 
        if (!cb)
-               handler->pd_created_cb = default_pd_created_cb;
+               cb = default_pd_created_cb;
+
+       handler->pd_created_cb = cb;
+       handler->pd_created_cbdata = data;
+
+       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;
+       }
 
-       return master_rpc_async_request(handler, packet, 0, pd_create_cb, create_cb_info(cb, data));
+       return ret;
 }
 
 EAPI int livebox_move_pd(struct livebox *handler, double x, double y)
@@ -1135,6 +1241,8 @@ EAPI int livebox_move_pd(struct livebox *handler, double x, double y)
 EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       struct cb_info *cbinfo;
+       int ret;
 
        if (!pkgname)
                return LB_STATUS_ERROR_INVALID;
@@ -1145,12 +1253,25 @@ EAPI int livebox_activate(const char *pkgname, ret_cb_t cb, void *data)
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(NULL, packet, 0, activated_cb, create_cb_info(cb, data));
+       cbinfo = create_cb_info(cb, data);
+       if (!cbinfo) {
+               ErrPrint("Unable to create cbinfo\n");
+               packet_destroy(packet);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       ret = master_rpc_async_request(NULL, packet, 0, activated_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return ret;
 }
 
 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");
@@ -1176,7 +1297,97 @@ EAPI int livebox_destroy_pd(struct livebox *handler, ret_cb_t cb, void *data)
        if (!cb)
                cb = default_pd_destroyed_cb;
 
-       return master_rpc_async_request(handler, packet, 0, pd_destroy_cb, create_cb_info(cb, data));
+       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_destroy_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return ret;
+}
+
+EAPI int livebox_access_event(struct livebox *handler, enum access_event_type type, double x, double y, ret_cb_t cb, void *data)
+{
+       int w = 1;
+       int h = 1;
+       char cmd[32] = { '\0', };
+       char *ptr = cmd;
+       int ret;
+
+       if (!handler) {
+               ErrPrint("Handler is NIL\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       if (handler->state != CREATE || !handler->id) {
+               ErrPrint("Handler is not valid\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       if (handler->access_event_cb) {
+               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) {
+                       ErrPrint("PD is not created\n");
+                       return LB_STATUS_ERROR_INVALID;
+               }
+               *ptr++ = 'p';
+               *ptr++ = 'd';
+               w = handler->pd.width;
+               h = handler->pd.height;
+       } else if (type & ACCESS_EVENT_LB_MASK) {
+               *ptr++ = 'l';
+               *ptr++ = 'b';
+               w = handler->lb.width;
+               h = handler->lb.height;
+       } else {
+               ErrPrint("Invalid event type\n");
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       switch (type & ~ACCESS_EVENT_PD_MASK) {
+       case ACCESS_EVENT_HIGHLIGHT:
+               strcpy(ptr, "_access_hl");
+               break;
+       case ACCESS_EVENT_HIGHLIGHT_NEXT:
+               strcpy(ptr, "_access_hl_next");
+               break;
+       case ACCESS_EVENT_HIGHLIGHT_PREV:
+               strcpy(ptr, "_access_hl_prev");
+               break;
+       case ACCESS_EVENT_ACTIVATE:
+               strcpy(ptr, "_access_activate");
+               break;
+       case ACCESS_EVENT_VALUE_CHANGE:
+               strcpy(ptr, "_access_value_change");
+               break;
+       case ACCESS_EVENT_SCROLL:
+               strcpy(ptr, "_access_scroll");
+               break;
+       default:
+               return LB_STATUS_ERROR_INVALID;
+       }
+
+       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;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_content_event(struct livebox *handler, enum content_event_type type, double x, double y)
@@ -1262,24 +1473,6 @@ EAPI int livebox_content_event(struct livebox *handler, enum content_event_type
         * Must be short than 29 bytes.
         */
        switch ((type & ~CONTENT_EVENT_PD_MASK)) {
-       case CONTENT_EVENT_ACCESS_HIGHLIGHT | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_hl");
-               break;
-       case CONTENT_EVENT_ACCESS_HIGHLIGHT_PREV | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_hl_prev");
-               break;
-       case CONTENT_EVENT_ACCESS_HIGHLIGHT_NEXT | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_hl_next");
-               break;
-       case CONTENT_EVENT_ACCESS_ACTIVATE | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_activate");
-               break;
-       case CONTENT_EVENT_ACCESS_VALUE_CHANGE | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_value_change");
-               break;
-       case CONTENT_EVENT_ACCESS_SCROLL | CONTENT_EVENT_ACCESS_MASK:
-               strcpy(ptr, "_access_scroll");
-               break;
        case CONTENT_EVENT_MOUSE_ENTER | CONTENT_EVENT_MOUSE_MASK:
                strcpy(ptr, "_mouse_enter");
                break;
@@ -1403,6 +1596,7 @@ EAPI int livebox_size(struct livebox *handler)
 EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const char *category, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       int ret;
 
        if (!handler) {
                ErrPrint("Handler is NIL\n");
@@ -1438,7 +1632,16 @@ EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const c
        if (!cb)
                cb = default_group_changed_cb;
 
-       return master_rpc_async_request(handler, packet, 0, set_group_ret_cb, create_cb_info(cb, data));
+       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;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category)
@@ -1519,6 +1722,8 @@ EAPI double livebox_priority(struct livebox *handler)
 EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       struct cb_info *cbinfo;
+       int ret;
 
        packet = packet_create("delete_cluster", "s", cluster);
        if (!packet) {
@@ -1526,12 +1731,24 @@ EAPI int livebox_delete_cluster(const char *cluster, ret_cb_t cb, void *data)
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(NULL, packet, 0, delete_cluster_cb, create_cb_info(cb, data));
+       cbinfo = create_cb_info(cb, data);
+       if (!cbinfo) {
+               packet_destroy(packet);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       ret = master_rpc_async_request(NULL, packet, 0, delete_cluster_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return ret;
 }
 
 EAPI int livebox_delete_category(const char *cluster, const char *category, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       struct cb_info *cbinfo;
+       int ret;
 
        packet = packet_create("delete_category", "ss", cluster, category);
        if (!packet) {
@@ -1539,7 +1756,17 @@ EAPI int livebox_delete_category(const char *cluster, const char *category, ret_
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(NULL, packet, 0, delete_category_cb, create_cb_info(cb, data));
+       cbinfo = create_cb_info(cb, data);
+       if (!cbinfo) {
+               packet_destroy(packet);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       ret = master_rpc_async_request(NULL, packet, 0, delete_category_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return ret;
 }
 
 EAPI enum livebox_lb_type livebox_lb_type(struct livebox *handler)
@@ -1641,7 +1868,9 @@ EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script
 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");
@@ -1668,7 +1897,17 @@ EAPI int livebox_acquire_lb_pixmap(struct livebox *handler, ret_cb_t cb, void *d
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
+       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;
 }
 
 EAPI int livebox_release_lb_pixmap(struct livebox *handler, int pixmap)
@@ -1702,7 +1941,9 @@ 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");
@@ -1729,7 +1970,17 @@ EAPI int livebox_acquire_pd_pixmap(struct livebox *handler, ret_cb_t cb, void *d
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(handler, packet, 0, pixmap_acquired_cb, create_cb_info(cb, data));
+       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;
 }
 
 EAPI int livebox_pd_pixmap(const struct livebox *handler)
@@ -1926,6 +2177,7 @@ EAPI int livebox_is_user(struct livebox *handler)
 EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       int ret;
 
        if (!handler) {
                ErrPrint("Handler is NIL\n");
@@ -1956,7 +2208,16 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void
        if (!cb)
                cb = default_pinup_cb;
 
-       return master_rpc_async_request(handler, packet, 0, pinup_done_cb, create_cb_info(cb, data));
+       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;
+       }
+
+       return ret;
 }
 
 EAPI int livebox_is_pinned_up(struct livebox *handler)
@@ -2054,6 +2315,8 @@ EAPI const char *livebox_category_title(struct livebox *handler)
 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)
 {
        struct packet *packet;
+       struct cb_info *cbinfo;
+       int ret;
 
        if (!handler) {
                ErrPrint("Handler is NIL\n");
@@ -2078,7 +2341,17 @@ EAPI int livebox_emit_text_signal(struct livebox *handler, const char *emission,
                return LB_STATUS_ERROR_FAULT;
        }
 
-       return master_rpc_async_request(handler, packet, 0, text_signal_cb, create_cb_info(cb, data));
+       cbinfo = create_cb_info(cb, data);
+       if (!cbinfo) {
+               packet_destroy(packet);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       ret = master_rpc_async_request(handler, packet, 0, text_signal_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return LB_STATUS_ERROR_FAULT;
 }
 
 EAPI int livebox_subscribe_group(const char *cluster, const char *category)
@@ -2625,6 +2898,76 @@ struct livebox *lb_unref(struct livebox *handler)
        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->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->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->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->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->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->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->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->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->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->filename)
                util_unlink(handler->filename);
 
@@ -2655,6 +2998,8 @@ struct livebox *lb_unref(struct livebox *handler)
 int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data)
 {
        struct packet *packet;
+       struct cb_info *cbinfo;
+       int ret;
 
        if (!cb && !!data) {
                ErrPrint("Invalid argument\n");
@@ -2678,7 +3023,17 @@ int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data)
        if (!cb)
                cb = default_delete_cb;
 
-       return master_rpc_async_request(handler, packet, 0, del_ret_cb, create_cb_info(cb, data));
+       cbinfo = create_cb_info(cb, data);
+       if (!cbinfo) {
+               packet_destroy(packet);
+               return LB_STATUS_ERROR_FAULT;
+       }
+
+       ret = master_rpc_async_request(handler, packet, 0, del_ret_cb, cbinfo);
+       if (ret < 0)
+               destroy_cb_info(cbinfo);
+
+       return ret;
 }
 
 EAPI int livebox_client_paused(void)
index 6e80932..0cb0e21 100644 (file)
@@ -200,9 +200,6 @@ int master_rpc_async_request(struct livebox *handler, struct packet *packet, int
        command = create_command(handler, packet);
        if (!command) {
                ErrPrint("Failed to create a command\n");
-               if (ret_cb)
-                       ret_cb(handler, NULL, data);
-
                packet_unref(packet);
                return LB_STATUS_ERROR_FAULT;
        }