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) {
532 ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb);
533 DbgPrint("Ignore VCONF [%d]\n", ret);
539 EAPI int shortcut_icon_service_init(int (*init_cb)(int status, void *data), void *data)
543 if (s_info.fd >= 0) {
544 return SHORTCUT_ERROR_INVALID;
547 if (s_info.initialized) {
548 s_info.initialized = 1;
549 com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
552 s_info.init_cb = init_cb;
553 s_info.cbdata = data;
555 ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, master_started_cb, NULL);
557 ErrPrint("Failed to add vconf for service state [%d]\n", ret);
559 DbgPrint("vconf is registered\n");
562 master_started_cb(NULL, NULL);
563 return SHORTCUT_SUCCESS;
568 EAPI int shortcut_icon_service_fini(void)
572 struct pending_item *pend;
574 if (s_info.initialized) {
575 com_core_del_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
576 s_info.initialized = 0;
580 return SHORTCUT_ERROR_INVALID;
583 com_core_packet_client_fini(s_info.fd);
584 s_info.init_cb = NULL;
585 s_info.cbdata = NULL;
588 dlist_foreach_safe(s_info.pending_list, l, n, pend) {
589 s_info.pending_list = dlist_remove(s_info.pending_list, l);
590 packet_unref(pend->packet);
591 if (pend->item->result_cb) {
592 pend->item->result_cb(pend->item->handle, SHORTCUT_ERROR_COMM, pend->item->data);
597 return SHORTCUT_SUCCESS;
602 EAPI struct shortcut_icon *shortcut_icon_request_create(void)
604 struct shortcut_icon *handle;
606 handle = malloc(sizeof(*handle));
608 ErrPrint("Heap: %s\n", strerror(errno));
612 handle->desc = shortcut_icon_desc_open();
614 ErrPrint("Uanble to open desc\n");
619 handle->state = CREATED;
625 EAPI int shortcut_icon_request_set_data(struct shortcut_icon *handle, void *data)
627 if (!handle || handle->state != CREATED) {
628 ErrPrint("Handle is not valid\n");
629 return SHORTCUT_ERROR_INVALID;
633 return SHORTCUT_SUCCESS;
638 EAPI void *shortcut_icon_request_data(struct shortcut_icon *handle)
640 if (!handle || handle->state != CREATED) {
641 ErrPrint("Handle is not valid\n");
650 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)
652 if (!handle || handle->state != CREATED) {
653 ErrPrint("Handle is not valid\n");
654 return SHORTCUT_ERROR_INVALID;
657 return shortcut_icon_desc_add_block(handle->desc, id, type, part, data, option, subid);
662 EAPI int shortcut_icon_request_destroy(struct shortcut_icon *handle)
664 if (!handle || handle->state != CREATED) {
665 ErrPrint("Handle is not valid\n");
666 return SHORTCUT_ERROR_INVALID;
669 (void)shortcut_icon_request_unref(handle);
670 return SHORTCUT_SUCCESS;
675 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)
678 struct packet *packet;
679 struct request_item *item;
683 if (!handle || handle->state != CREATED) {
684 ErrPrint("Handle is not valid\n");
685 return SHORTCUT_ERROR_INVALID;
689 layout = DEFAULT_ICON_LAYOUT;
693 group = DEFAULT_ICON_GROUP;
696 len = strlen(outfile) + strlen(".desc") + 1 + 30; /* 30 == strlen(tv.tv_sec) + strlen(tv.tv_usec) + 10 (reserved) */
697 filename = malloc(len);
699 ErrPrint("Heap: %s\n", strerror(errno));
700 return SHORTCUT_ERROR_MEMORY;
703 #if defined(_USE_ECORE_TIME_GET)
707 if (clock_gettime(s_info.type, &ts) == 0) {
708 tv = ts.tv_sec + ts.tv_nsec / 1000000000.0f;
712 ErrPrint("%d: %s\n", s_info.type, strerror(errno));
713 if (s_info.type == CLOCK_MONOTONIC) {
714 s_info.type = CLOCK_REALTIME;
715 } else if (s_info.type == CLOCK_REALTIME) {
717 if (gettimeofday(&_tv, NULL) < 0) {
718 ErrPrint("gettimeofday: %s\n", strerror(errno));
720 _tv.tv_usec = rand();
723 tv = (double)_tv.tv_sec + (double)_tv.tv_usec / 1000000.0f;
727 ret = snprintf(filename, len, "%s.%lf.desc", outfile, tv);
730 if (gettimeofday(&tv, NULL) != 0) {
731 ErrPrint("gettimeofday: %s\n", strerror(errno));
736 ret = snprintf(filename, len, "%s.%lu.%lu.desc", outfile, tv.tv_sec, tv.tv_usec);
739 ErrPrint("snprintf: %s\n", strerror(errno));
743 ret = shortcut_icon_desc_save(handle->desc, filename);
748 item = malloc(sizeof(*item));
750 ErrPrint("Heap: %s\n", strerror(errno));
751 if (unlink(filename) < 0) {
752 ErrPrint("Unlink: %s\n", strerror(errno));
754 ret = SHORTCUT_ERROR_MEMORY;
758 item->result_cb = result_cb;
760 item->handle = shortcut_icon_request_ref(handle);
762 packet = packet_create("icon_create", "sssis", layout, group, filename, size_type, outfile);
764 ErrPrint("Failed to create a packet\n");
765 if (unlink(filename) < 0) {
766 ErrPrint("Unlink: %s\n", strerror(errno));
769 (void)shortcut_icon_request_unref(handle);
770 ret = SHORTCUT_ERROR_FAULT;
774 if (s_info.fd >= 0 && !s_info.pending_list) {
775 ret = com_core_packet_async_send(s_info.fd, packet, 0.0f, icon_request_cb, item);
776 packet_destroy(packet);
778 ErrPrint("ret: %d\n", ret);
779 if (unlink(filename) < 0) {
780 ErrPrint("Unlink: %s\n", strerror(errno));
783 (void)shortcut_icon_request_unref(handle);
785 DbgPrint("Request is sent\n");
787 struct pending_item *pend;
789 pend = malloc(sizeof(*pend));
791 ErrPrint("Heap: %s\n", strerror(errno));
792 packet_destroy(packet);
794 if (unlink(filename) < 0) {
795 ErrPrint("Unlink: %s\n", strerror(errno));
797 (void)shortcut_icon_request_unref(handle);
798 ret = SHORTCUT_ERROR_MEMORY;
802 pend->packet = packet;
805 s_info.pending_list = dlist_append(s_info.pending_list, pend);
806 DbgPrint("Request is pended\n");
808 ret = SHORTCUT_SUCCESS;