summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSung-jae Park <nicesj.park@samsung.com>2013-05-15 11:13:11 +0900
committerSung-jae Park <nicesj.park@samsung.com>2013-05-15 11:13:11 +0900
commit73841e54e490d5b718922726fd1fa2c7f753dacc (patch)
tree37ae6f6f58c70527800d7fe40c0573608ae8297b
parent67ab9f9a537d7e55e7824d602e0191a26a8e5b4a (diff)
downloadshortcut-tizen_2.1.tar.gz
shortcut-tizen_2.1.tar.bz2
shortcut-tizen_2.1.zip
Patch 2 Update the icon service reuqest codes. APIs are changed. Patch 1 Update shortcut service library. Icon service API is implemented. Default layout & group should be "" (zero length string) The icon provider will choose the default layout and group when it get zero length string. Change-Id: I2d47a1dbdeb8281c20f3a352fd3bcaf4ffe10a4e
-rw-r--r--lib/CMakeLists.txt2
-rw-r--r--lib/include/dlist.h43
-rw-r--r--lib/include/shortcut.h85
-rw-r--r--lib/include/shortcut_internal.h37
-rw-r--r--lib/src/dlist.c180
-rw-r--r--lib/src/icon.c738
-rw-r--r--lib/src/main.c17
-rw-r--r--packaging/libshortcut.spec4
-rw-r--r--test/icon.c91
9 files changed, 1179 insertions, 18 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 9f2f2a7..f02c651 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -31,6 +31,8 @@ ADD_DEFINITIONS("-DLOG_TAG=\"SHORTCUT\"")
ADD_LIBRARY(${PROJECT_NAME} SHARED
src/main.c
+ src/icon.c
+ src/dlist.c
)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${svc_pkgs_LDFLAGS})
diff --git a/lib/include/dlist.h b/lib/include/dlist.h
new file mode 100644
index 0000000..cd1a421
--- /dev/null
+++ b/lib/include/dlist.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define dlist_remove_data(list, data) do { \
+ struct dlist *l; \
+ l = dlist_find_data(list, data); \
+ list = dlist_remove(list, l); \
+} while (0)
+
+#define dlist_foreach(list, l, data) \
+ for ((l) = (list); (l) && ((data) = dlist_data(l)); (l) = dlist_next(l))
+
+#define dlist_foreach_safe(list, l, n, data) \
+ for ((l) = (list), (n) = dlist_next(l); \
+ (l) && ((data) = dlist_data(l)); \
+ (l) = (n), (n) = dlist_next(l))
+
+struct dlist;
+
+extern struct dlist *dlist_append(struct dlist *list, void *data);
+extern struct dlist *dlist_prepend(struct dlist *list, void *data);
+extern struct dlist *dlist_remove(struct dlist *list, struct dlist *l);
+extern struct dlist *dlist_find_data(struct dlist *list, void *data);
+extern void *dlist_data(struct dlist *l);
+extern struct dlist *dlist_next(struct dlist *l);
+extern struct dlist *dlist_prev(struct dlist *l);
+extern int dlist_count(struct dlist *l);
+extern struct dlist *dlist_nth(struct dlist *l, int nth);
+
+/* End of a file */
diff --git a/lib/include/shortcut.h b/lib/include/shortcut.h
index 3bae74f..b2cd25e 100644
--- a/lib/include/shortcut.h
+++ b/lib/include/shortcut.h
@@ -36,6 +36,7 @@ extern "C" {
* The others for the application developers who should implement the Add to home feature.
*/
+struct shortcut_icon;
/**
* @brief This function prototype is used to define a callback function for the add_to_home reqeust.
* The homescreen should define a callback as this type and implementing the service code
@@ -70,6 +71,8 @@ typedef int (*request_cb_t)(const char *appid, const char *name, int type, const
*/
typedef int (*result_cb_t)(int ret, int pid, void *data);
+typedef int (*icon_request_cb_t)(struct shortcut_icon *handle, int ret, void *data);
+
/**
* @brief Basically, three types of shortcut is defined.
* Every homescreen developer should support these types of shortcut.
@@ -268,6 +271,88 @@ extern int add_to_home_remove_shortcut(const char *appid, const char *name, cons
extern int add_to_home_remove_livebox(const char *appid, const char *name, result_cb_t result_cb, void *data);
+
+
+/*!
+ * \note
+ * Example)
+ *
+ * static int init_cb(int status, void *data)
+ * {
+ * printf("Initializer returns: %d\n", status);
+ * if (status == 0) {
+ * printf("Succeed to initialize\n");
+ * } else {
+ * printf("Failed to initialize: %d\n", status);
+ * }
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * // Initialize the service request
+ * int ret;
+ *
+ * // After the init_cb is called, you can use below functions.
+ * struct shortcut_icon *handle;
+ *
+ * ret = shortcut_icon_init(init_cb, NULL);
+ * if (ret < 0) {
+ * ...
+ *
+ * // Create request for creating shortcut icon.
+ * handle = shortcut_icon_create();
+ * if (!handle) {
+ * ...
+ * }
+ *
+ * // Send the request to the shortcut service
+ * ret = shortcut_icon_request_set_info(handle, NULL, SHORTCUT_ICON_TYPE_IMAGE, "/usr/share/.../icon.png", NULL, NULL);
+ * if (ret < 0) {
+ * ...
+ * }
+ *
+ * ret = shortcut_icon_request_set_info(handle, NULL, SHORTCUT_ICON_TYPE_TEXT, "app icon", NULL, NULL);
+ * if (ret < 0) {
+ * ...
+ * }
+ *
+ * ret = shortcut_icon_request_send(handle, LB_SIZE_TYPE_1x1, NULL, NULL, "/opt/usr/apps/com.samsung.cluster-home/data/out.png", result_cb, NULL);
+ * if (ret < 0) {
+ * ...
+ * }
+ *
+ * ret = shortcut_icon_request_destroy(handle);
+ * if (ret < 0) {
+ * ...
+ * }
+ *
+ * // Don't finalize the icon service if you don't get result callbacks of all requests
+ * ret = shortcut_icon_fini();
+ * if (ret < 0) {
+ * ...
+ * }
+ *
+ * return 0;
+ * }
+ */
+
+#define DEFAULT_ICON_PART "icon"
+#define DEFAULT_NAME_PART "name"
+#define SHORTCUT_ICON_TYPE_IMAGE "image"
+#define SHORTCUT_ICON_TYPE_TEXT "text"
+#define SHORTCUT_ICON_TYPE_SCRIPT "script"
+
+extern int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data);
+extern int shortcut_icon_service_fini(void);
+
+extern struct shortcut_icon *shortcut_icon_request_create(void);
+extern int shortcut_icon_request_set_info(struct shortcut_icon *handle, const char *id, const char *type, const char *part, const char *data, const char *option, const char *subid);
+extern int shortcut_icon_request_send(struct shortcut_icon *handle, int size_type, const char *layout, const char *group, const char *outfile, icon_request_cb_t result_cb, void *data);
+extern int shortcut_icon_request_destroy(struct shortcut_icon *handle);
+
+extern int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data);
+extern void *shortcut_icon_request_data(struct shortcut_icon *handle);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/include/shortcut_internal.h b/lib/include/shortcut_internal.h
new file mode 100644
index 0000000..5009ba2
--- /dev/null
+++ b/lib/include/shortcut_internal.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...) LOGD("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...) LOGE("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+
+#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+#endif
+
+#define EAPI __attribute__((visibility("default")))
+
+#if !defined(VCONFKEY_MASTER_STARTED)
+#define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started"
+#endif
+
+#define DEFAULT_ICON_LAYOUT ""
+#define DEFAULT_ICON_GROUP ""
+
+/* End of a file */
diff --git a/lib/src/dlist.c b/lib/src/dlist.c
new file mode 100644
index 0000000..fa3082a
--- /dev/null
+++ b/lib/src/dlist.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2013 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "dlist.h"
+
+/*!
+ * \brief
+ * This dlist is called Modified Doubly Linked List.
+ *
+ * Noramlly, The dobule linked list contains address of previous and next element.
+ * This dlist also contains them, but the tail element only contains prev address.
+ *
+ * The head element's prev pointer indicates the last element.
+ * But the last element's next pointer indicates NIL.
+ *
+ * So we can find the last element while crawling this DList
+ * But we have to remember the address of the head element.
+ */
+
+struct dlist {
+ struct dlist *next;
+ struct dlist *prev;
+ void *data;
+};
+
+struct dlist *dlist_append(struct dlist *list, void *data)
+{
+ struct dlist *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return NULL;
+
+ item->next = NULL;
+ item->data = data;
+
+ if (!list) {
+ item->prev = item;
+
+ list = item;
+ } else {
+ item->prev = list->prev;
+ item->prev->next = item;
+ list->prev = item;
+ }
+
+ assert(!list->prev->next && "item NEXT");
+
+ return list;
+}
+
+struct dlist *dlist_prepend(struct dlist *list, void *data)
+{
+ struct dlist *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return NULL;
+
+ item->data = data;
+
+ if (!list) {
+ item->prev = item;
+ item->next = NULL;
+ } else {
+ if (list->prev->next)
+ list->prev->next = item;
+
+ item->prev = list->prev;
+ item->next = list;
+
+ list->prev = item;
+
+ }
+
+ return item;
+}
+
+struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
+{
+ if (!list || !l)
+ return NULL;
+
+ if (l == list)
+ list = l->next;
+ else
+ l->prev->next = l->next;
+
+ if (l->next)
+ l->next->prev = l->prev;
+ /*!
+ * \note
+ * If the removed entry 'l' has no next element, it is the last element.
+ * In this case, check the existence of the list first,
+ * and if the list is not empty, update the 'prev' of the list (which is a head element of the list)
+ *
+ * If we didn't care about this, the head element(list) can indicates the invalid element.
+ */
+ else if (list)
+ list->prev = l->prev;
+
+ free(l);
+ return list;
+}
+
+struct dlist *dlist_find_data(struct dlist *list, void *data)
+{
+ struct dlist *l;
+ void *_data;
+
+ dlist_foreach(list, l, _data) {
+ if (data == _data)
+ return l;
+ }
+
+ return NULL;
+}
+
+void *dlist_data(struct dlist *l)
+{
+ return l ? l->data : NULL;
+}
+
+struct dlist *dlist_next(struct dlist *l)
+{
+ return l ? l->next : NULL;
+}
+
+struct dlist *dlist_prev(struct dlist *l)
+{
+ return l ? l->prev : NULL;
+}
+
+int dlist_count(struct dlist *l)
+{
+ register int i;
+ struct dlist *n;
+ void *data;
+
+ i = 0;
+ dlist_foreach(l, n, data) {
+ i++;
+ }
+
+ return i;
+}
+
+struct dlist *dlist_nth(struct dlist *l, int nth)
+{
+ register int i;
+ struct dlist *n;
+
+ i = 0;
+ for (n = l; n; n = n->next) {
+ if (i == nth)
+ return n;
+ i++;
+ }
+
+ return NULL;
+}
+
+/* End of a file */
diff --git a/lib/src/icon.c b/lib/src/icon.c
new file mode 100644
index 0000000..c29445b
--- /dev/null
+++ b/lib/src/icon.c
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <libgen.h>
+
+#include <dlog.h>
+#include <glib.h>
+#include <db-util.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include <packet.h>
+#include <com-core.h>
+#include <com-core_packet.h>
+
+#include "shortcut_internal.h"
+#include "shortcut.h"
+#include "dlist.h"
+
+
+
+#define CREATED 0x00BEEF00
+#define DESTROYED 0x00DEAD00
+
+
+static struct info {
+ int fd;
+ int (*init_cb)(int status, void *data);
+ void *cbdata;
+ int initialized;
+
+ const char *utility_socket;
+
+ struct dlist *pending_list;
+} s_info = {
+ .fd = -1,
+ .init_cb = NULL,
+ .cbdata = NULL,
+ .initialized = 0,
+
+ .utility_socket = "/tmp/.utility.service",
+ .pending_list = NULL,
+};
+
+
+
+struct request_item {
+ struct shortcut_icon *handle;
+ icon_request_cb_t result_cb;
+ void *data;
+};
+
+
+
+struct pending_item {
+ struct request_item *item;
+ struct packet *packet;
+};
+
+
+
+struct block {
+ unsigned int idx;
+
+ char *type;
+ char *part;
+ char *data;
+ char *option;
+ char *id;
+ char *target_id;
+};
+
+
+
+struct shortcut_icon {
+ unsigned int state;
+ struct shortcut_desc *desc;
+ int refcnt;
+ void *data;
+};
+
+
+
+struct shortcut_desc {
+ int for_pd;
+
+ unsigned int last_idx;
+
+ struct dlist *block_list;
+};
+
+
+
+static inline void delete_block(struct block *block)
+{
+ DbgPrint("Release block: %p\n", block);
+ free(block->type);
+ free(block->part);
+ free(block->data);
+ free(block->option);
+ free(block->id);
+ free(block->target_id);
+ free(block);
+}
+
+
+
+static inline int shortcut_icon_desc_close(struct shortcut_desc *handle)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct block *block;
+
+ dlist_foreach_safe(handle->block_list, l, n, block) {
+ handle->block_list = dlist_remove(handle->block_list, l);
+ delete_block(block);
+ }
+
+ free(handle);
+ return 0;
+}
+
+
+
+static inline struct shortcut_icon *shortcut_icon_request_unref(struct shortcut_icon *handle)
+{
+ handle->refcnt--;
+ DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
+
+ if (handle->refcnt == 0) {
+ handle->state = DESTROYED;
+ shortcut_icon_desc_close(handle->desc);
+ free(handle);
+ handle = NULL;
+ }
+
+ return handle;
+}
+
+
+
+static inline struct shortcut_icon *shortcut_icon_request_ref(struct shortcut_icon *handle)
+{
+ handle->refcnt++;
+ DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
+ return handle;
+}
+
+
+
+static int disconnected_cb(int handle, void *data)
+{
+ if (s_info.fd != handle)
+ return 0;
+
+ ErrPrint("Disconnected\n");
+ s_info.fd = -1;
+ s_info.init_cb = NULL;
+ s_info.cbdata = NULL;
+ s_info.initialized = 0;
+ return 0;
+}
+
+
+
+static inline struct shortcut_desc *shortcut_icon_desc_open(void)
+{
+ struct shortcut_desc *handle;
+
+ handle = calloc(1, sizeof(*handle));
+ if (!handle) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ return handle;
+}
+
+
+
+static inline int shortcut_icon_desc_save(struct shortcut_desc *handle, const char *filename)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct block *block;
+ FILE *fp;
+
+ if (!handle)
+ return -EINVAL;
+
+ fp = fopen(filename, "w+t");
+ if (!fp) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ return -EIO;
+ }
+
+ DbgPrint("Close and flush\n");
+ dlist_foreach_safe(handle->block_list, l, n, block) {
+ DbgPrint("{\n");
+ fprintf(fp, "{\n");
+ if (block->type) {
+ fprintf(fp, "type=%s\n", block->type);
+ DbgPrint("type=%s\n", block->type);
+ }
+
+ if (block->part) {
+ fprintf(fp, "part=%s\n", block->part);
+ DbgPrint("part=%s\n", block->part);
+ }
+
+ if (block->data) {
+ fprintf(fp, "data=%s\n", block->data);
+ DbgPrint("data=%s\n", block->data);
+ }
+
+ if (block->option) {
+ fprintf(fp, "option=%s\n", block->option);
+ DbgPrint("option=%s\n", block->option);
+ }
+
+ if (block->id) {
+ fprintf(fp, "id=%s\n", block->id);
+ DbgPrint("id=%s\n", block->id);
+ }
+
+ if (block->target_id) {
+ fprintf(fp, "target=%s\n", block->target_id);
+ DbgPrint("target=%s\n", block->target_id);
+ }
+
+ fprintf(fp, "}\n");
+ DbgPrint("}\n");
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+
+
+static inline struct block *find_block(struct shortcut_desc *handle, const char *id, const char *part)
+{
+ struct block *block;
+ struct dlist *l;
+
+ dlist_foreach(handle->block_list, l, block) {
+ if (!strcmp(block->part, part) && !strcmp(block->id, id))
+ return block;
+ }
+
+ return NULL;
+}
+
+
+
+static inline int update_block(struct block *block, const char *data, const char *option)
+{
+ char *_data = NULL;
+ char *_option = NULL;
+
+ if (data) {
+ _data = strdup(data);
+ if (!_data) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+ }
+
+ if (option) {
+ _option = strdup(option);
+ if (!_option) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+ }
+
+ free(block->data);
+ free(block->option);
+
+ block->data = _data;
+ block->option = _option;
+ return 0;
+}
+
+
+
+/*!
+ * \return idx
+ */
+
+
+
+static inline int shortcut_icon_desc_add_block(struct shortcut_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option, const char *target_id)
+{
+ struct block *block;
+
+ if (!handle || !type)
+ return SHORTCUT_ERROR_INVALID;
+
+ if (!part)
+ part = "";
+
+ if (!data)
+ data = "";
+
+ if (target_id) {
+ if (strcmp(type, SHORTCUT_ICON_TYPE_SCRIPT)) {
+ ErrPrint("target id only can be used for script type\n");
+ return -EINVAL;
+ }
+ }
+
+ block = find_block(handle, id, part);
+ if (!block) {
+ block = calloc(1, sizeof(*block));
+ if (!block) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return SHORTCUT_ERROR_MEMORY;
+ }
+
+ block->type = strdup(type);
+ if (!block->type) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+
+ block->part = strdup(part);
+ if (!block->part) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block->type);
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+
+ block->data = strdup(data);
+ if (!block->data) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block->type);
+ free(block->part);
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+
+ if (option) {
+ block->option = strdup(option);
+ if (!block->option) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block->data);
+ free(block->type);
+ free(block->part);
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+ }
+
+ if (id) {
+ block->id = strdup(id);
+ if (!block->id) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block->option);
+ free(block->data);
+ free(block->type);
+ free(block->part);
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+ }
+
+ if (target_id) {
+ block->target_id = strdup(target_id);
+ if (!block->target_id) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(block->id);
+ free(block->option);
+ free(block->data);
+ free(block->type);
+ free(block->part);
+ free(block);
+ return SHORTCUT_ERROR_MEMORY;
+ }
+ }
+
+ block->idx = handle->last_idx++;
+ handle->block_list = dlist_append(handle->block_list, block);
+ } else {
+ if (strcmp(block->type, type) || strcmp(block->target_id, target_id)) {
+ ErrPrint("type or target id is not valid (%s, %s) or (%s, %s)\n",
+ block->type, type, block->target_id, target_id);
+ return -EINVAL;
+ }
+
+ update_block(block, data, option);
+ }
+
+ return block->idx;
+}
+
+
+
+static int icon_request_cb(pid_t pid, int handle, const struct packet *packet, void *data)
+{
+ struct request_item *item = data;
+ int ret;
+
+ if (!packet) {
+ ret = -EFAULT;
+ DbgPrint("Disconnected?\n");
+ } else {
+ if (packet_get(packet, "i", &ret) != 1) {
+ DbgPrint("Invalid packet\n");
+ ret = -EINVAL;
+ }
+ }
+
+ if (item->result_cb)
+ item->result_cb(item->handle, ret, item->data);
+
+ (void)shortcut_icon_request_unref(item->handle);
+ free(item);
+ return 0;
+}
+
+
+
+static inline int make_connection(void)
+{
+ int ret;
+ static struct method service_table[] = {
+ {
+ .cmd = NULL,
+ .handler = NULL,
+ },
+ };
+
+ s_info.fd = com_core_packet_client_init(s_info.utility_socket, 0, service_table);
+ if (s_info.fd < 0) {
+ ret = SHORTCUT_ERROR_COMM;
+
+ if (s_info.init_cb)
+ s_info.init_cb(ret, s_info.cbdata);
+ } else {
+ struct dlist *l;
+ struct dlist *n;
+ struct pending_item *pend;
+
+ if (s_info.init_cb)
+ s_info.init_cb(SHORTCUT_SUCCESS, s_info.cbdata);
+
+ dlist_foreach_safe(s_info.pending_list, l, n, pend) {
+ s_info.pending_list = dlist_remove(s_info.pending_list, l);
+
+ ret = com_core_packet_async_send(s_info.fd, pend->packet, 0.0f, icon_request_cb, pend->item);
+ packet_destroy(pend->packet);
+ if (ret < 0) {
+ ErrPrint("ret: %d\n", ret);
+ if (pend->item->result_cb)
+ pend->item->result_cb(pend->item->handle, ret, pend->item->data);
+ free(pend->item);
+ }
+
+ free(pend);
+ }
+
+ ret = SHORTCUT_SUCCESS;
+ }
+
+ return ret;
+}
+
+
+
+static void master_started_cb(keynode_t *node, void *user_data)
+{
+ int state = 0;
+
+ if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0)
+ ErrPrint("Unable to get \"%s\"\n", VCONFKEY_MASTER_STARTED);
+
+ if (state == 1 && make_connection() == SHORTCUT_SUCCESS) {
+ int ret;
+ ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
+ DbgPrint("Ignore VCONF [%d]\n", ret);
+ }
+}
+
+
+
+EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
+{
+ int ret;
+
+ if (s_info.fd >= 0)
+ return -EALREADY;
+
+ if (s_info.initialized) {
+ s_info.initialized = 1;
+ com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+ }
+
+ s_info.init_cb = init_cb;
+ s_info.cbdata = data;
+
+ ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
+ if (ret < 0)
+ ErrPrint("Failed to add vconf for service state [%d]\n", ret);
+ else
+ DbgPrint("vconf is registered\n");
+
+ master_started_cb(NULL, NULL);
+ return 0;
+}
+
+
+
+EAPI int shortcut_icon_service_fini(void)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct pending_item *pend;
+
+ if (s_info.initialized) {
+ com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+ s_info.initialized = 0;
+ }
+
+ if (s_info.fd < 0)
+ return -EINVAL;
+
+ com_core_packet_client_fini(s_info.fd);
+ s_info.init_cb = NULL;
+ s_info.cbdata = NULL;
+ s_info.fd = -1;
+
+ dlist_foreach_safe(s_info.pending_list, l, n, pend) {
+ s_info.pending_list = dlist_remove(s_info.pending_list, l);
+ packet_unref(pend->packet);
+ if (pend->item->result_cb)
+ pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
+ free(pend->item);
+ free(pend);
+ }
+ return 0;
+}
+
+
+
+EAPI struct shortcut_icon *shortcut_icon_request_create(void)
+{
+ struct shortcut_icon *handle;
+
+ handle = malloc(sizeof(*handle));
+ if (!handle) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ handle->desc = shortcut_icon_desc_open();
+ if (!handle->desc) {
+ ErrPrint("Uanble to open desc\n");
+ free(handle);
+ return NULL;
+ }
+
+ handle->state = CREATED;
+ handle->refcnt = 1;
+ return handle;
+}
+
+
+EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
+{
+ if (!handle || handle->state != CREATED) {
+ ErrPrint("Handle is not valid\n");
+ return -EINVAL;
+ }
+
+ handle->data = data;
+ return 0;
+}
+
+
+
+EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
+{
+ if (!handle || handle->state != CREATED) {
+ ErrPrint("Handle is not valid\n");
+ return NULL;
+ }
+
+ return handle->data;
+}
+
+
+
+EAPI int shortcut_icon_request_set_info(struct shortcut_icon *handle, const char *id, const char *type, const char *part, const char *data, const char *option, const char *subid)
+{
+ if (!handle || handle->state != CREATED) {
+ ErrPrint("Handle is not valid\n");
+ return -EINVAL;
+ }
+
+ return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
+}
+
+
+
+EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
+{
+ if (!handle || handle->state != CREATED) {
+ ErrPrint("Handle is not valid\n");
+ return -EINVAL;
+ }
+
+ (void)shortcut_icon_request_unref(handle);
+ return 0;
+}
+
+
+
+EAPI int shortcut_icon_request_send(struct shortcut_icon *handle, int size_type, const char *layout, const char *group, const char *outfile, icon_request_cb_t result_cb, void *data)
+{
+ int ret;
+ struct packet *packet;
+ struct request_item *item;
+ char *filename;
+ int len;
+
+ if (!handle || handle->state != CREATED) {
+ ErrPrint("Handle is not valid\n");
+ return -EINVAL;
+ }
+
+ if (!layout)
+ layout = DEFAULT_ICON_LAYOUT;
+
+ if (!group)
+ group = DEFAULT_ICON_GROUP;
+
+ len = strlen(outfile) + strlen(".desc") + 1;
+ filename = malloc(len);
+ if (!filename) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ snprintf(filename, len, "%s.desc", outfile);
+
+ ret = shortcut_icon_desc_save(handle->desc, filename);
+ if (ret < 0)
+ goto out;
+
+ item = malloc(sizeof(*item));
+ if (!item) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ if (unlink(filename) < 0)
+ ErrPrint("Unlink: %s\n", strerror(errno));
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ item->result_cb = result_cb;
+ item->data = data;
+ item->handle = shortcut_icon_request_ref(handle);
+
+ packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
+ if (!packet) {
+ ErrPrint("Failed to create a packet\n");
+ if (unlink(filename) < 0)
+ ErrPrint("Unlink: %s\n", strerror(errno));
+ free(item);
+ (void)shortcut_icon_request_unref(handle);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (s_info.fd >= 0 && !s_info.pending_list) {
+ ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
+ packet_destroy(packet);
+ if (ret < 0) {
+ ErrPrint("ret: %d\n", ret);
+ if (unlink(filename) < 0)
+ ErrPrint("Unlink: %s\n", strerror(errno));
+ free(item);
+ (void)shortcut_icon_request_unref(handle);
+ }
+ DbgPrint("Request is sent\n");
+ } else {
+ struct pending_item *pend;
+
+ pend = malloc(sizeof(*pend));
+ if (!pend) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ packet_destroy(packet);
+ free(item);
+ if (unlink(filename) < 0)
+ ErrPrint("Unlink: %s\n", strerror(errno));
+ (void)shortcut_icon_request_unref(handle);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pend->packet = packet;
+ pend->item = item;
+
+ s_info.pending_list = dlist_append(s_info.pending_list, pend);
+ DbgPrint("Request is pended\n");
+
+ ret = 0;
+ }
+
+out:
+ free(filename);
+ return ret;
+}
+
+
+/* End of a file */
diff --git a/lib/src/main.c b/lib/src/main.c
index 2410fb2..0a27aa3 100644
--- a/lib/src/main.c
+++ b/lib/src/main.c
@@ -35,22 +35,7 @@
#include <com-core_packet.h>
#include "shortcut.h"
-
-#if !defined(FLOG)
-#define DbgPrint(format, arg...) LOGD("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#define ErrPrint(format, arg...) LOGE("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#else
-extern FILE *__file_log_fp;
-#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
-
-#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
-#endif
-
-#define EAPI __attribute__((visibility("default")))
-
-#if !defined(VCONFKEY_MASTER_STARTED)
-#define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started"
-#endif
+#include "shortcut_internal.h"
int errno;
diff --git a/packaging/libshortcut.spec b/packaging/libshortcut.spec
index 334a59c..54d12f3 100644
--- a/packaging/libshortcut.spec
+++ b/packaging/libshortcut.spec
@@ -1,6 +1,6 @@
Name: libshortcut
-Summary: Shortcut add/remove request function supporting library
-Version: 0.5.1
+Summary: Shortcut add feature supporting library
+Version: 0.6.1
Release: 0
Group: HomeTF/Framework
License: Apache License
diff --git a/test/icon.c b/test/icon.c
new file mode 100644
index 0000000..3086729
--- /dev/null
+++ b/test/icon.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+#include <Elementary.h>
+#include <shortcut.h>
+
+static int result_cb(struct shortcut_icon *handle, int ret, void *data)
+{
+ printf("Client: Return %d (%p)\n", ret, handle);
+ return 0;
+}
+
+static Eina_Bool test_main(void *data)
+{
+ struct shortcut_icon *handle;
+ static int idx = 0;
+ int ret;
+ char filename[256];
+ int type;
+
+ idx++;
+
+ handle = shortcut_icon_request_create();
+ if (!handle) {
+ printf("Failed to create a request\n");
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ printf("Test: %d\n", idx);
+ ret = shortcut_icon_request_set_info(handle, NULL, SHORTCUT_ICON_TYPE_IMAGE, DEFAULT_ICON_PART, "/usr/share/icons/default/small/com.samsung.music-player.png", NULL, NULL);
+ printf("NAME set_info: %d\n", ret);
+
+ snprintf(filename, sizeof(filename), "App Name %d", idx);
+ ret = shortcut_icon_request_set_info(handle, NULL, SHORTCUT_ICON_TYPE_TEXT, DEFAULT_NAME_PART, filename, NULL, NULL);
+ printf("TEXT set_info: %d\n", ret);
+
+ snprintf(filename, sizeof(filename), "/opt/usr/share/live_magazine/always/out%d.png", idx);
+
+ switch (idx % 7) {
+ case 0: type = LIVEBOX_TYPE_1x1; break;
+ case 1: type = LIVEBOX_TYPE_2x1; break;
+ case 2: type = LIVEBOX_TYPE_2x2; break;
+ case 3: type = LIVEBOX_TYPE_4x1; break;
+ case 4: type = LIVEBOX_TYPE_4x2; break;
+ case 5: type = LIVEBOX_TYPE_4x3; break;
+ case 6: type = LIVEBOX_TYPE_4x4; break;
+ default: type = LIVEBOX_TYPE_1x1; break;
+ }
+
+ ret = shortcut_icon_request_send(handle, type, NULL, NULL, filename, result_cb, NULL);
+ printf("request: %d\n", ret);
+
+ ret = shortcut_icon_request_destroy(handle);
+ printf("destroy: %d\n", ret);
+ return ECORE_CALLBACK_RENEW;
+}
+
+static int initialized_cb(int status, void *data)
+{
+ printf("Hello initializer\n");
+ return 0;
+}
+
+int elm_main(int argc, char *argv[])
+{
+ shortcut_icon_service_init(NULL, NULL);
+
+ ecore_timer_add(5.0f, test_main, NULL);
+
+ elm_run();
+ shortcut_icon_service_fini();
+ elm_shutdown();
+ return 0;
+}
+
+ELM_MAIN()
+/* End of a file */