2 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
33 #include <vconf-keys.h>
37 #include <com-core_packet.h>
39 #include "shortcut_internal.h"
45 #define CREATED 0x00BEEF00
46 #define DESTROYED 0x00DEAD00
50 int (*init_cb)(int status, void *data);
54 const char *utility_socket;
56 struct dlist *pending_list;
57 #if defined(_USE_ECORE_TIME_GET)
66 .utility_socket = "/tmp/.utility.service",
68 #if defined(_USE_ECORE_TIME_GET)
69 .type = CLOCK_MONOTONIC,
76 struct shortcut_icon *handle;
77 icon_request_cb_t result_cb;
84 struct request_item *item;
85 struct packet *packet;
103 struct shortcut_icon {
105 struct shortcut_desc *desc;
112 struct shortcut_desc {
115 unsigned int last_idx;
117 struct dlist *block_list;
122 static inline void delete_block(struct block *block)
124 DbgPrint("Release block: %p\n", block);
130 free(block->target_id);
136 static inline int shortcut_icon_desc_close(struct shortcut_desc *handle)
142 dlist_foreach_safe(handle->block_list, l, n, block) {
143 handle->block_list = dlist_remove(handle->block_list, l);
153 static inline struct shortcut_icon *shortcut_icon_request_unref(struct shortcut_icon *handle)
156 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
158 if (handle->refcnt == 0) {
159 handle->state = DESTROYED;
160 shortcut_icon_desc_close(handle->desc);
170 static inline struct shortcut_icon *shortcut_icon_request_ref(struct shortcut_icon *handle)
173 DbgPrint("Handle: refcnt[%d]\n", handle->refcnt);
179 static int disconnected_cb(int handle, void *data)
181 if (s_info.fd != handle) {
185 ErrPrint("Disconnected\n");
187 s_info.init_cb = NULL;
188 s_info.cbdata = NULL;
189 s_info.initialized = 0;
195 static inline struct shortcut_desc *shortcut_icon_desc_open(void)
197 struct shortcut_desc *handle;
199 handle = calloc(1, sizeof(*handle));
201 ErrPrint("Error: %s\n", strerror(errno));
210 static inline int shortcut_icon_desc_save(struct shortcut_desc *handle, const char *filename)
218 return SHORTCUT_ERROR_INVALID;
221 fp = fopen(filename, "w+t");
223 ErrPrint("Error: %s\n", strerror(errno));
224 return SHORTCUT_ERROR_IO;
227 DbgPrint("Close and flush\n");
228 dlist_foreach_safe(handle->block_list, l, n, block) {
232 fprintf(fp, "type=%s\n", block->type);
233 DbgPrint("type=%s\n", block->type);
237 fprintf(fp, "part=%s\n", block->part);
238 DbgPrint("part=%s\n", block->part);
242 fprintf(fp, "data=%s\n", block->data);
243 DbgPrint("data=%s\n", block->data);
247 fprintf(fp, "option=%s\n", block->option);
248 DbgPrint("option=%s\n", block->option);
252 fprintf(fp, "id=%s\n", block->id);
253 DbgPrint("id=%s\n", block->id);
256 if (block->target_id) {
257 fprintf(fp, "target=%s\n", block->target_id);
258 DbgPrint("target=%s\n", block->target_id);
265 if (fclose(fp) != 0) {
266 ErrPrint("fclose: %s\n", strerror(errno));
268 return SHORTCUT_SUCCESS;
273 static inline struct block *find_block(struct shortcut_desc *handle, const char *id, const char *part)
278 dlist_foreach(handle->block_list, l, block) {
279 if (!strcmp(block->part, part) && (!id || !strcmp(block->id, id))) {
289 static inline int update_block(struct block *block, const char *data, const char *option)
292 char *_option = NULL;
295 _data = strdup(data);
297 ErrPrint("Heap: %s\n", strerror(errno));
298 return SHORTCUT_ERROR_MEMORY;
303 _option = strdup(option);
305 ErrPrint("Heap: %s\n", strerror(errno));
306 return SHORTCUT_ERROR_MEMORY;
314 block->option = _option;
326 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)
330 if (!handle || !type) {
331 return SHORTCUT_ERROR_INVALID;
343 if (strcmp(type, SHORTCUT_ICON_TYPE_SCRIPT)) {
344 ErrPrint("target id only can be used for script type\n");
345 return SHORTCUT_ERROR_INVALID;
349 block = find_block(handle, id, part);
351 block = calloc(1, sizeof(*block));
353 ErrPrint("Heap: %s\n", strerror(errno));
354 return SHORTCUT_ERROR_MEMORY;
357 block->type = strdup(type);
359 ErrPrint("Heap: %s\n", strerror(errno));
361 return SHORTCUT_ERROR_MEMORY;
364 block->part = strdup(part);
366 ErrPrint("Heap: %s\n", strerror(errno));
369 return SHORTCUT_ERROR_MEMORY;
372 block->data = strdup(data);
374 ErrPrint("Heap: %s\n", strerror(errno));
378 return SHORTCUT_ERROR_MEMORY;
382 block->option = strdup(option);
383 if (!block->option) {
384 ErrPrint("Heap: %s\n", strerror(errno));
389 return SHORTCUT_ERROR_MEMORY;
394 block->id = strdup(id);
396 ErrPrint("Heap: %s\n", strerror(errno));
402 return SHORTCUT_ERROR_MEMORY;
407 block->target_id = strdup(target_id);
408 if (!block->target_id) {
409 ErrPrint("Heap: %s\n", strerror(errno));
416 return SHORTCUT_ERROR_MEMORY;
420 block->idx = handle->last_idx++;
421 handle->block_list = dlist_append(handle->block_list, block);
423 if (strcmp(block->type, type)) {
424 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
425 return SHORTCUT_ERROR_INVALID;
428 if ((block->target_id && !target_id) || (!block->target_id && target_id)) {
429 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
430 return SHORTCUT_ERROR_INVALID;
433 if (block->target_id && target_id && strcmp(block->target_id, target_id)) {
434 ErrPrint("type is not valid (%s, %s)\n", block->type, type);
435 return SHORTCUT_ERROR_INVALID;
438 update_block(block, data, option);
446 static int icon_request_cb(pid_t pid, int handle, const struct packet *packet, void *data)
448 struct request_item *item = data;
453 DbgPrint("Disconnected?\n");
455 if (packet_get(packet, "i", &ret) != 1) {
456 DbgPrint("Invalid packet\n");
461 if (item->result_cb) {
462 item->result_cb(item->handle, ret, item->data);
465 (void)shortcut_icon_request_unref(item->handle);
472 static inline int make_connection(void)
475 static struct method service_table[] = {
482 s_info.fd = com_core_packet_client_init(s_info.utility_socket, 0, service_table);
484 ret = SHORTCUT_ERROR_COMM;
486 if (s_info.init_cb) {
487 s_info.init_cb(ret, s_info.cbdata);
492 struct pending_item *pend;
494 if (s_info.init_cb) {
495 s_info.init_cb(SHORTCUT_SUCCESS, s_info.cbdata);
498 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
499 s_info.pending_list = dlist_remove(s_info.pending_list, l);
501 ret = com_core_packet_async_send(s_info.fd, pend->packet, 0.0f, icon_request_cb, pend->item);
502 packet_destroy(pend->packet);
504 ErrPrint("ret: %d\n", ret);
505 if (pend->item->result_cb) {
506 pend->item->result_cb(pend->item->handle, ret, pend->item->data);
514 ret = SHORTCUT_SUCCESS;
522 static void master_started_cb(keynode_t *node, void *user_data)
526 if (vconf_get_bool(VCONFKEY_MASTER_STARTED, &state) < 0) {
527 ErrPrint("Unable to get \"%s\"\n", VCONFKEY_MASTER_STARTED);
530 if (state == 1 && make_connection() == SHORTCUT_SUCCESS) {
531 (void)vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
537 EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
541 if (s_info.fd >= 0) {
542 return SHORTCUT_ERROR_INVALID;
545 if (s_info.initialized) {
546 s_info.initialized = 1;
547 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
550 s_info.init_cb = init_cb;
551 s_info.cbdata = data;
553 ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
555 ErrPrint("Failed to add vconf for service state [%d]\n", ret);
557 DbgPrint("vconf is registered\n");
560 master_started_cb(NULL, NULL);
561 return SHORTCUT_SUCCESS;
566 EAPI int shortcut_icon_service_fini(void)
570 struct pending_item *pend;
572 if (s_info.initialized) {
573 com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
574 s_info.initialized = 0;
578 return SHORTCUT_ERROR_INVALID;
581 com_core_packet_client_fini(s_info.fd);
582 s_info.init_cb = NULL;
583 s_info.cbdata = NULL;
586 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
587 s_info.pending_list = dlist_remove(s_info.pending_list, l);
588 packet_unref(pend->packet);
589 if (pend->item->result_cb) {
590 pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
595 return SHORTCUT_SUCCESS;
600 EAPI struct shortcut_icon *shortcut_icon_request_create(void)
602 struct shortcut_icon *handle;
604 handle = malloc(sizeof(*handle));
606 ErrPrint("Heap: %s\n", strerror(errno));
610 handle->desc = shortcut_icon_desc_open();
612 ErrPrint("Uanble to open desc\n");
617 handle->state = CREATED;
623 EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
625 if (!handle || handle->state != CREATED) {
626 ErrPrint("Handle is not valid\n");
627 return SHORTCUT_ERROR_INVALID;
631 return SHORTCUT_SUCCESS;
636 EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
638 if (!handle || handle->state != CREATED) {
639 ErrPrint("Handle is not valid\n");
648 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)
650 if (!handle || handle->state != CREATED) {
651 ErrPrint("Handle is not valid\n");
652 return SHORTCUT_ERROR_INVALID;
655 return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
660 EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
662 if (!handle || handle->state != CREATED) {
663 ErrPrint("Handle is not valid\n");
664 return SHORTCUT_ERROR_INVALID;
667 (void)shortcut_icon_request_unref(handle);
668 return SHORTCUT_SUCCESS;
673 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)
676 struct packet *packet;
677 struct request_item *item;
681 if (!handle || handle->state != CREATED) {
682 ErrPrint("Handle is not valid\n");
683 return SHORTCUT_ERROR_INVALID;
687 layout = DEFAULT_ICON_LAYOUT;
691 group = DEFAULT_ICON_GROUP;
694 len = strlen(outfile) + strlen(".desc") + 1 + 30; /* 30 == strlen(tv.tv_sec) + strlen(tv.tv_usec) + 10 (reserved) */
695 filename = malloc(len);
697 ErrPrint("Heap: %s\n", strerror(errno));
698 return SHORTCUT_ERROR_MEMORY;
701 #if defined(_USE_ECORE_TIME_GET)
705 if (clock_gettime(s_info.type, &ts) == 0) {
706 tv = ts.tv_sec + ts.tv_nsec / 1000000000.0f;
710 ErrPrint("%d: %s\n", s_info.type, strerror(errno));
711 if (s_info.type == CLOCK_MONOTONIC) {
712 s_info.type = CLOCK_REALTIME;
713 } else if (s_info.type == CLOCK_REALTIME) {
715 if (gettimeofday(&_tv, NULL) < 0) {
716 ErrPrint("gettimeofday: %s\n", strerror(errno));
718 _tv.tv_usec = rand();
721 tv = (double)_tv.tv_sec + (double)_tv.tv_usec / 1000000.0f;
725 ret = snprintf(filename, len, "%s.%lf.desc", outfile, tv);
728 if (gettimeofday(&tv, NULL) != 0) {
729 ErrPrint("gettimeofday: %s\n", strerror(errno));
734 ret = snprintf(filename, len, "%s.%lu.%lu.desc", outfile, tv.tv_sec, tv.tv_usec);
737 ErrPrint("snprintf: %s\n", strerror(errno));
741 ret = shortcut_icon_desc_save(handle->desc, filename);
746 item = malloc(sizeof(*item));
748 ErrPrint("Heap: %s\n", strerror(errno));
749 if (unlink(filename) < 0) {
750 ErrPrint("Unlink: %s\n", strerror(errno));
752 ret = SHORTCUT_ERROR_MEMORY;
756 item->result_cb = result_cb;
758 item->handle = shortcut_icon_request_ref(handle);
760 packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
762 ErrPrint("Failed to create a packet\n");
763 if (unlink(filename) < 0) {
764 ErrPrint("Unlink: %s\n", strerror(errno));
767 (void)shortcut_icon_request_unref(handle);
768 ret = SHORTCUT_ERROR_FAULT;
772 if (s_info.fd >= 0 && !s_info.pending_list) {
773 ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
774 packet_destroy(packet);
776 ErrPrint("ret: %d\n", ret);
777 if (unlink(filename) < 0) {
778 ErrPrint("Unlink: %s\n", strerror(errno));
781 (void)shortcut_icon_request_unref(handle);
783 DbgPrint("Request is sent\n");
785 struct pending_item *pend;
787 pend = malloc(sizeof(*pend));
789 ErrPrint("Heap: %s\n", strerror(errno));
790 packet_destroy(packet);
792 if (unlink(filename) < 0) {
793 ErrPrint("Unlink: %s\n", strerror(errno));
795 (void)shortcut_icon_request_unref(handle);
796 ret = SHORTCUT_ERROR_MEMORY;
800 pend->packet = packet;
803 s_info.pending_list = dlist_append(s_info.pending_list, pend);
804 DbgPrint("Request is pended\n");
806 ret = SHORTCUT_SUCCESS;