Icon service API is introduced. tizen_2.1 accepted/tizen/20130520.100932 submit/tizen/20130517.044820 submit/tizen_2.1/20130516.045513
authorSung-jae Park <nicesj.park@samsung.com>
Wed, 15 May 2013 02:13:11 +0000 (11:13 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Wed, 15 May 2013 02:13:11 +0000 (11:13 +0900)
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

lib/CMakeLists.txt
lib/include/dlist.h [new file with mode: 0644]
lib/include/shortcut.h
lib/include/shortcut_internal.h [new file with mode: 0644]
lib/src/dlist.c [new file with mode: 0644]
lib/src/icon.c [new file with mode: 0644]
lib/src/main.c
packaging/libshortcut.spec
test/icon.c [new file with mode: 0644]

index 9f2f2a7..f02c651 100644 (file)
@@ -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 (file)
index 0000000..cd1a421
--- /dev/null
@@ -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 */
index 3bae74f..b2cd25e 100644 (file)
@@ -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 (file)
index 0000000..5009ba2
--- /dev/null
@@ -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("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...)       LOGE("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+
+#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%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 (file)
index 0000000..fa3082a
--- /dev/null
@@ -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 (file)
index 0000000..c29445b
--- /dev/null
@@ -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 */
index 2410fb2..0a27aa3 100644 (file)
 #include <com-core_packet.h>
 
 #include "shortcut.h"
-
-#if !defined(FLOG)
-#define DbgPrint(format, arg...)       LOGD("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#define ErrPrint(format, arg...)       LOGE("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
-#else
-extern FILE *__file_log_fp;
-#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
-
-#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [\e[32m%s/%s\e[0m:%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;
 
index 334a59c..54d12f3 100644 (file)
@@ -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 (file)
index 0000000..3086729
--- /dev/null
@@ -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 */