diff options
author | Kyuho Jo <kyuho.jo@samsung.com> | 2015-02-12 22:01:19 +0900 |
---|---|---|
committer | Kyuho Jo <kyuho.jo@samsung.com> | 2015-02-13 11:03:37 +0900 |
commit | 1b30d07bb82b2a7f8f4770eb4dc0b148391447af (patch) | |
tree | ee404fd690577bf9d10f192289116f09e9a0b742 /src | |
parent | 45c2785cf0c16c49a79a50c2d27d0a5707cf2ebf (diff) | |
download | widget-service-1b30d07bb82b2a7f8f4770eb4dc0b148391447af.tar.gz widget-service-1b30d07bb82b2a7f8f4770eb4dc0b148391447af.tar.bz2 widget-service-1b30d07bb82b2a7f8f4770eb4dc0b148391447af.zip |
Rename to widget
Change-Id: I46ba39326c98db73aab92be5767384937fd3db4c
Signed-off-by: Kyuho Jo <kyuho.jo@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/dlist.c | 189 | ||||
-rwxr-xr-x | src/util.c | 287 | ||||
-rwxr-xr-x | src/util_wayland.c | 237 | ||||
-rwxr-xr-x | src/util_x11.c | 355 | ||||
-rwxr-xr-x | src/widget_conf.c | 1819 | ||||
-rwxr-xr-x | src/widget_service.c | 3230 |
6 files changed, 6117 insertions, 0 deletions
diff --git a/src/dlist.c b/src/dlist.c new file mode 100644 index 0000000..3ae571b --- /dev/null +++ b/src/dlist.c @@ -0,0 +1,189 @@ +/* + * 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/src/util.c b/src/util.c new file mode 100755 index 0000000..bec4eaf --- /dev/null +++ b/src/util.c @@ -0,0 +1,287 @@ +/* + * 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 <sys/time.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/statvfs.h> +#include <time.h> + +#include <sqlite3.h> +#include <unicode/uloc.h> + +#include <dlog.h> + +#include "widget_errno.h" +#include "util.h" +#include "debug.h" + +int errno; +#if defined(_USE_ECORE_TIME_GET) +static struct info { + clockid_t type; +} s_info = { + .type = CLOCK_MONOTONIC, +}; +#endif + +double util_timestamp(void) +{ +#if defined(_USE_ECORE_TIME_GET) + struct timespec ts; + + do { + if (clock_gettime(s_info.type, &ts) == 0) { + return ts.tv_sec + ts.tv_nsec / 1000000000.0f; + } + + ErrPrint("%d: %s\n", s_info.type, strerror(errno)); + if (s_info.type == CLOCK_MONOTONIC) { + s_info.type = CLOCK_REALTIME; + } else if (s_info.type == CLOCK_REALTIME) { + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) { + ErrPrint("gettimeofday: %s\n", strerror(errno)); + break; + } + + return tv.tv_sec + tv.tv_usec / 1000000.0f; + } + } while (1); + + return 0.0f; +#else + struct timeval tv; + + if (gettimeofday(&tv, NULL) < 0) { + ErrPrint("gettimeofday: %s\n", strerror(errno)); + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + return tv.tv_sec + tv.tv_usec / 1000000.0f; +#endif +} + +const char *util_basename(const char *name) +{ + int length; + length = name ? strlen(name) : 0; + if (!length) { + return "."; + } + + while (--length > 0 && name[length] != '/'); + + return length <= 0 ? name : (name + length + (name[length] == '/')); +} + +unsigned long util_free_space(const char *path) +{ + struct statvfs st; + unsigned long space; + + if (statvfs(path, &st) < 0) { + ErrPrint("statvfs: %s\n", strerror(errno)); + return 0lu; + } + + space = st.f_bsize * st.f_bfree; + /*! + * \note + * Must have to check the overflow + */ + return space; +} + +char *util_replace_string(const char *src, const char *pattern, const char *replace) +{ + int s_idx; + int p_idx; + int n_idx; + int t_idx; + int r_idx; + int idx; + char *result; + int len; + int rlen; + int matched; + + if (!src || !pattern || !replace || !src[0] || !pattern[0]) { + ErrPrint("Invalid argument: %s %s %s\n", src, pattern, replace); + return NULL; + } + + rlen = strlen(replace); + len = strlen(src); + result = malloc(len + 1); + if (!result) { + ErrPrint("Heap:%s\n", strerror(errno)); + return NULL; + } + + r_idx = 0; + idx = 0; + matched = 0; + for (s_idx = 0; src[s_idx]; s_idx++) { + if (idx == len) { + char *tmp; + + len += (rlen > len ? rlen : len); + tmp = realloc(result, len + 1); + if (!tmp) { + ErrPrint("Heap: %s\n", strerror(errno)); + free(result); + return NULL; + } + result = tmp; + } + + if (src[s_idx] == pattern[0]) { + n_idx = -1; + t_idx = s_idx; + r_idx = idx; + + if (r_idx == len) { + char *tmp; + len += (rlen > len ? rlen : len); + tmp = realloc(result, len + 1); + if (!tmp) { + ErrPrint("Heap: %s\n", strerror(errno)); + free(result); + return NULL; + } + result = tmp; + } + result[r_idx++] = src[t_idx++]; + p_idx = 1; + while (pattern[p_idx]) { + if (src[t_idx] == pattern[p_idx]) { + if (n_idx < 0) { + if (src[t_idx] == pattern[0]) { + n_idx = t_idx; + } else { + if (r_idx == len) { + char *tmp; + len += (rlen > len ? rlen : len); + tmp = realloc(result, len + 1); + if (!tmp) { + ErrPrint("Heap: %s\n", strerror(errno)); + free(result); + return NULL; + } + result = tmp; + } + result[r_idx++] = src[t_idx]; + } + } + + p_idx++; + t_idx++; + continue; + } + + if (n_idx < 0) { + s_idx = t_idx; + } else { + s_idx = n_idx; + } + + break; + } + + if (pattern[p_idx] == '\0') { + if (idx + rlen >= len) { + char *tmp; + len += (rlen > len ? rlen : len); + tmp = realloc(result, len + 1); + if (!tmp) { + ErrPrint("Heap: %s\n", strerror(errno)); + free(result); + return NULL; + } + result = tmp; + matched++; + } + strcpy(result + idx, replace); + idx += strlen(replace); + s_idx = t_idx - 1; + } else { + idx = r_idx; + s_idx = (n_idx < 0 ? t_idx : n_idx) - 1; + } + } else { + result[idx++] = src[s_idx]; + } + } + + result[idx] = '\0'; + + if (!matched) { + free(result); + result = NULL; + } + + return result; +} + +const char *util_uri_to_path(const char *uri) +{ + int len; + + len = strlen(SCHEMA_FILE); + if (strncasecmp(uri, SCHEMA_FILE, len)) { + return NULL; + } + + return uri + len; +} + +char *util_id_to_uri(const char *id) +{ + char *uri; + + if (!id) { + uri = strdup(""); + if (!uri) { + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + } else if (strncmp(id, SCHEMA_FILE, strlen(SCHEMA_FILE))) { + int len; + len = strlen(SCHEMA_FILE) + strlen(id) + 2; + uri = malloc(len); + if (!uri) { + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + + snprintf(uri, len, SCHEMA_FILE"%s", id); + } else { + uri = strdup(id); + if (!uri) { + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + } + + return uri; +} + +/* End of a file */ diff --git a/src/util_wayland.c b/src/util_wayland.c new file mode 100755 index 0000000..2ad812b --- /dev/null +++ b/src/util_wayland.c @@ -0,0 +1,237 @@ +#include <stdio.h> +#include <ctype.h> +#include <errno.h> + +#include <dlog.h> + +#include <sqlite3.h> +#include <unicode/uloc.h> + +#include "widget_errno.h" +#include "util.h" +#include "widget_service.h" +#include "debug.h" + +int errno; + +static int update_info(struct supported_size_list *SIZE_LIST, int width_type, int height_type, int width, int height) +{ + int idx; + + if (width_type == 1 && height_type == 1) { + idx = 0; + } else if (width_type == 2 && height_type == 1) { + idx = 1; + } else if (width_type == 2 && height_type == 2) { + idx = 2; + } else if (width_type == 4 && height_type == 1) { + idx = 3; + } else if (width_type == 4 && height_type == 2) { + idx = 4; + } else if (width_type == 4 && height_type == 3) { + idx = 5; + } else if (width_type == 4 && height_type == 4) { + idx = 6; + } else if (width_type == 4 && height_type == 5) { + idx = 7; + } else if (width_type == 4 && height_type == 6) { + idx = 8; + } else if (width_type == 21 && height_type == 21) { + idx = 9; + } else if (width_type == 23 && height_type == 21) { + idx = 10; + } else if (width_type == 23 && height_type == 23) { + idx = 11; + } else if (width_type == 0 && height_type == 0) { + idx = 12; + } else { + ErrPrint("Unknown size type: %dx%d (%dx%d)\n", width_type, height_type, width, height); + return 0; + } + + SIZE_LIST[idx].w = width; + SIZE_LIST[idx].h = height; + return 1; +} + +static inline int update_from_file(struct service_info *info, struct supported_size_list *SIZE_LIST) +{ + FILE *fp; + int updated; + int width_type; + int height_type; + int width; + int height; + char buffer[MAX_COLUMN]; + int ch; + int idx; + enum status { + START = 0x0, + TYPE = 0x01, + SIZE = 0x02, + COMMENT = 0x03, + ERROR = 0x04, + EOL = 0x05, + TYPE_END = 0x06, + SIZE_START = 0x07 + } status; + + fp = fopen(info->conf_file, "r"); + if (!fp) { + ErrPrint("Open failed: %s\n", strerror(errno)); + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + updated = 0; + status = START; + idx = 0; + do { + ch = fgetc(fp); + + if (idx == MAX_COLUMN) { + ErrPrint("Buffer overflow. Too long line. LINE MUST BE SHOT THAN %d\n", MAX_COLUMN); + status = ERROR; + } + + switch (status) { + case START: + if (isspace(ch) || ch == EOF) { + continue; + } + + info->base_parse = 0; + + if (ch == '#') { + status = COMMENT; + } else { + status = TYPE; + idx = 0; + ungetc(ch, fp); + } + break; + case TYPE: + if (isblank(ch)) { + buffer[idx] = '\0'; + status = TYPE_END; + if (sscanf(buffer, "%dx%d", &width_type, &height_type) != 2) { + if (!strcasecmp(buffer, "base")) { + info->base_parse = 1; + } else { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } + } + break; + } else if (ch == '=') { + buffer[idx] = '\0'; + status = SIZE_START; + if (sscanf(buffer, "%dx%d", &width_type, &height_type) != 2) { + if (!strcasecmp(buffer, "base")) { + info->base_parse = 1; + } else { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } + } + break; + } else if (ch == EOF) { + ErrPrint("Invalid Syntax\n"); + status = ERROR; + continue; + } + buffer[idx++] = ch; + break; + case TYPE_END: + if (ch == '=') { + status = SIZE_START; + } + break; + case SIZE_START: + if (isspace(ch) || ch == EOF) { + continue; + } + + status = SIZE; + idx = 0; + ungetc(ch, fp); + break; + case SIZE: + if (isspace(ch) || ch == EOF) { + buffer[idx] = '\0'; + status = EOL; + + if (sscanf(buffer, "%dx%d", &width, &height) != 2) { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } else if (ch == EOF) { + if (info->base_parse) { + info->base_w = width; + info->base_h = height; + } else { + updated += update_info(SIZE_LIST, width_type, height_type, width, height); + } + } + break; + } + buffer[idx++] = ch; + break; + case EOL: + if (!info->base_parse) { + updated += update_info(SIZE_LIST, width_type, height_type, width, height); + } else { + info->base_w = width; + info->base_h = height; + } + status = START; + ungetc(ch, fp); + break; + case ERROR: + if (ch == '\n' || ch == '\r' || ch == '\f') { + status = START; + } + break; + case COMMENT: + if (ch == '\n' || ch == '\r' || ch == '\f') { + status = START; + } + break; + default: + ErrPrint("Unknown status. couldn't be reach to here\n"); + break; + } + } while (!feof(fp)); + + if (fclose(fp) != 0) { + ErrPrint("fclose: %s\n", strerror(errno)); + } + + return WIDGET_NR_OF_SIZE_LIST - updated; +} + +int util_update_resolution(struct service_info *info, struct supported_size_list *SIZE_LIST) +{ + unsigned int width; + unsigned int height; + unsigned int border; + unsigned int depth; + register int i; + static int res_resolved = 0; + + if (res_resolved) { + return WIDGET_STATUS_ERROR_NONE; + } + + if (update_from_file(info, SIZE_LIST) == 0) { + DbgPrint("Resolution info is all updated by file\n"); + } + + res_resolved = 1; + return WIDGET_STATUS_ERROR_NONE; +} + +int util_screen_size_get(unsigned int *width, unsigned int *height) +{ + return WIDGET_STATUS_ERROR_NONE; +} + +/* End of a file */ diff --git a/src/util_x11.c b/src/util_x11.c new file mode 100755 index 0000000..2d1a30f --- /dev/null +++ b/src/util_x11.c @@ -0,0 +1,355 @@ +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <unistd.h> // access +#include <stdlib.h> // free + +#include <X11/X.h> +#include <X11/Xlib.h> + +#include <dlog.h> + +#include <sqlite3.h> +#include <unicode/uloc.h> + +#include "widget_errno.h" +#include "util.h" +#include "widget_service.h" +#include "debug.h" + +#define CONF_PATH_FORMAT "/usr/share/data-provider-master/%dx%d/resolution.ini" + +int errno; + +static struct { + unsigned int w; + unsigned int h; + int res_resolved; +} s_info = { + .w = 0, + .h = 0, + .res_resolved = 0, +}; + +static int update_info(struct supported_size_list *SIZE_LIST, int width_type, int height_type, int width, int height) +{ + int idx; + + if (width_type == 1 && height_type == 1) { + idx = 0; + } else if (width_type == 2 && height_type == 1) { + idx = 1; + } else if (width_type == 2 && height_type == 2) { + idx = 2; + } else if (width_type == 4 && height_type == 1) { + idx = 3; + } else if (width_type == 4 && height_type == 2) { + idx = 4; + } else if (width_type == 4 && height_type == 3) { + idx = 5; + } else if (width_type == 4 && height_type == 4) { + idx = 6; + } else if (width_type == 4 && height_type == 5) { + idx = 7; + } else if (width_type == 4 && height_type == 6) { + idx = 8; + } else if (width_type == 21 && height_type == 21) { + idx = 9; + } else if (width_type == 23 && height_type == 21) { + idx = 10; + } else if (width_type == 23 && height_type == 23) { + idx = 11; + } else if (width_type == 0 && height_type == 0) { + idx = 12; + } else { + ErrPrint("Unknown size type: %dx%d (%dx%d)\n", width_type, height_type, width, height); + return 0; + } + + SIZE_LIST[idx].w = width; + SIZE_LIST[idx].h = height; + return 1; +} + +static inline int update_from_file(struct service_info *info, struct supported_size_list *SIZE_LIST) +{ + FILE *fp; + int updated; + int width_type; + int height_type; + int width; + int height; + char buffer[MAX_COLUMN]; + int ch; + int idx; + enum status { + START = 0x0, + TYPE = 0x01, + SIZE = 0x02, + COMMENT = 0x03, + ERROR = 0x04, + EOL = 0x05, + TYPE_END = 0x06, + SIZE_START = 0x07 + } status; + + fp = fopen(info->conf_file, "r"); + if (!fp) { + ErrPrint("Open failed: %s\n", strerror(errno)); + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + updated = 0; + status = START; + idx = 0; + do { + ch = fgetc(fp); + + if (idx == MAX_COLUMN) { + ErrPrint("Buffer overflow. Too long line. LINE MUST BE SHOT THAN %d\n", MAX_COLUMN); + status = ERROR; + } + + switch (status) { + case START: + if (isspace(ch) || ch == EOF) { + continue; + } + + info->base_parse = 0; + + if (ch == '#') { + status = COMMENT; + } else { + status = TYPE; + idx = 0; + ungetc(ch, fp); + } + break; + case TYPE: + if (isblank(ch)) { + buffer[idx] = '\0'; + status = TYPE_END; + if (sscanf(buffer, "%dx%d", &width_type, &height_type) != 2) { + if (!strcasecmp(buffer, "base")) { + info->base_parse = 1; + } else { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } + } + break; + } else if (ch == '=') { + buffer[idx] = '\0'; + status = SIZE_START; + if (sscanf(buffer, "%dx%d", &width_type, &height_type) != 2) { + if (!strcasecmp(buffer, "base")) { + info->base_parse = 1; + } else { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } + } + break; + } else if (ch == EOF) { + ErrPrint("Invalid Syntax\n"); + status = ERROR; + continue; + } + buffer[idx++] = ch; + break; + case TYPE_END: + if (ch == '=') { + status = SIZE_START; + } + break; + case SIZE_START: + if (isspace(ch) || ch == EOF) { + continue; + } + + status = SIZE; + idx = 0; + ungetc(ch, fp); + break; + case SIZE: + if (isspace(ch) || ch == EOF) { + buffer[idx] = '\0'; + status = EOL; + + if (sscanf(buffer, "%dx%d", &width, &height) != 2) { + if (!strncasecmp(buffer, "screen", strlen("screen"))) { + width = s_info.w; + height = s_info.h; + DbgPrint("Select screen size: %dx%d\n", width, height); + } else { + ErrPrint("Invalid syntax: [%s]\n", buffer); + status = ERROR; + } + } + + if (status != ERROR && ch == EOF) { + if (info->base_parse) { + info->base_w = width; + info->base_h = height; + } else { + updated += update_info(SIZE_LIST, width_type, height_type, width, height); + } + } + break; + } + buffer[idx++] = ch; + break; + case EOL: + if (!info->base_parse) { + updated += update_info(SIZE_LIST, width_type, height_type, width, height); + } else { + info->base_w = width; + info->base_h = height; + } + status = START; + ungetc(ch, fp); + break; + case ERROR: + if (ch == '\n' || ch == '\r' || ch == '\f') { + status = START; + } + break; + case COMMENT: + if (ch == '\n' || ch == '\r' || ch == '\f') { + status = START; + } + break; + default: + ErrPrint("Unknown status. couldn't be reach to here\n"); + break; + } + } while (!feof(fp)); + + if (fclose(fp) != 0) { + ErrPrint("fclose: %s\n", strerror(errno)); + } + + return WIDGET_NR_OF_SIZE_LIST - updated; +} + +/* + * Find proper configuration and install(link) it to conf path. + */ +static char *conf_path(void) +{ + char *path; + int length; + + length = strlen(CONF_PATH_FORMAT) + 12; // 12 == RESERVED SPACE + path = calloc(1, length); + if (!path) { + ErrPrint("calloc: %s\n", strerror(errno)); + return NULL; + } + + if (s_info.w == 0 || s_info.h == 0) { + /* Try to update resolution first if it is not initialized */ + util_screen_size_get(NULL, NULL); + } + + snprintf(path, length, CONF_PATH_FORMAT, s_info.w, s_info.h); + DbgPrint("Selected conf file: %s\n", path); + if (access(path, F_OK) != 0) { + ErrPrint("Fallback to default, access: %s\n", strerror(errno)); + strncpy(path, RESOLUTION_FILE, length); + if (access(path, F_OK) != 0) { + ErrPrint("Serious error - there is no conf file, use default setting: %s\n", strerror(errno)); + free(path); + path = NULL; + } + } + + return path; +} + +int util_screen_size_get(unsigned int *width, unsigned int *height) +{ + Display *disp; + Window root; + Window dummy; + unsigned int border; + unsigned int depth; + int x; + int y; + int ret; + unsigned int _width; + unsigned int _height; + + if (!width) { + width = &_width; + } + + if (!height) { + height = &_height; + } + + if (s_info.w != 0 && s_info.h != 0) { + DbgPrint("Already prepared (%dx%d)\n", s_info.w, s_info.h); + goto out; + } + + disp = XOpenDisplay(NULL); + if (!disp) { + ErrPrint("Failed to open a display\n"); + return WIDGET_STATUS_ERROR_FAULT; + } + + root = XDefaultRootWindow(disp); + ret = XGetGeometry(disp, root, &dummy, &x, &y, &s_info.w, &s_info.h, &border, &depth); + XCloseDisplay(disp); + if (!ret) { + ErrPrint("Failed to get geometry\n"); + return WIDGET_STATUS_ERROR_FAULT; + } + +out: + *width = s_info.w; + *height = s_info.h; + return WIDGET_STATUS_ERROR_NONE; +} + +int util_update_resolution(struct service_info *info, struct supported_size_list *SIZE_LIST) +{ + if (s_info.res_resolved) { + return WIDGET_STATUS_ERROR_NONE; + } + + if (!info->conf_file) { + info->conf_file = conf_path(); + } + + if (info->conf_file) { + register int i; + unsigned int width; + unsigned int height; + + i = util_screen_size_get(&width, &height); + if (i != WIDGET_STATUS_ERROR_NONE) { + return i; + } + + if (update_from_file(info, SIZE_LIST) == 0) { + DbgPrint("Resolution info is all updated by file\n"); + } + + if (width != info->base_w) { + for (i = 0; i < WIDGET_NR_OF_SIZE_LIST; i++) { + SIZE_LIST[i].w = (unsigned int)((double)SIZE_LIST[i].w * (double)width / (double)info->base_w); + SIZE_LIST[i].h = (unsigned int)((double)SIZE_LIST[i].h * (double)width / (double)info->base_w); + } + } + } else { + DbgPrint("Conf file is not loaded\n"); + } + + s_info.res_resolved = 1; + return WIDGET_STATUS_ERROR_NONE; +} + +/* End of a file */ diff --git a/src/widget_conf.c b/src/widget_conf.c new file mode 100755 index 0000000..04b2bc0 --- /dev/null +++ b/src/widget_conf.c @@ -0,0 +1,1819 @@ +/* + * 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 <ctype.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> // access +#include <sqlite3.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <dlog.h> +#include <widget_errno.h> +#include <unicode/uloc.h> + +#include "widget_conf.h" +#include "util.h" +#include "debug.h" + +#define BASE_SHARE_DIR "/opt/usr/share/live_magazine/" +#define DEFAULT_INPUT_NODE "/dev/input/event2" +#define DEV_PATH "/dev/input/" +#define PROC_INPUT_DEVICES "/proc/bus/input/devices" +#define MAX_LINE_BUFFER 256 +#define NODE_PREFIX "event" + +#define CR 13 +#define LF 10 + +#define MAX_ABI 256 +#define MAX_PKGNAME 512 + +static const char *CONF_DEFAULT_SERVICES = "[widget],[shortcut],[notification],[badge],[utility],[file]"; +static const char *CONF_DEFAULT_EMERGENCY_DISK = "source=tmpfs;type=tmpfs;option=size=6M"; +static const char *CONF_DEFAULT_PATH_CONF = "/opt/usr/live/%s/etc/%s.conf"; +static const char *CONF_DEFAULT_PATH_IMAGE = BASE_SHARE_DIR; +static const char *CONF_DEFAULT_PATH_LOG = BASE_SHARE_DIR"log"; +static const char *CONF_DEFAULT_PATH_READER = BASE_SHARE_DIR"reader"; +static const char *CONF_DEFAULT_PATH_ALWAYS = BASE_SHARE_DIR"always"; +static const char *CONF_DEFAULT_PATH_SCRIPT = "/opt/usr/live/%s/res/script/%s.edj"; +static const char *CONF_DEFAULT_PATH_ROOT = "/opt/usr/live/"; +static const char *CONF_DEFAULT_PATH_SCRIPT_PORT = "/usr/share/data-provider-master/plugin-script/"; +static const char *CONF_DEFAULT_PATH_DB = "/opt/dbspace/.widget.db"; +static const char *CONF_DEFAULT_PATH_INPUT = DEFAULT_INPUT_NODE; +static const char *CONF_DEFAULT_SCRIPT_TYPE = "edje"; +static const char *CONF_DEFAULT_ABI = "c"; +static const char *CONF_DEFAULT_GBAR_GROUP = "disclosure"; +static const char *CONF_DEFAULT_LAUNCH_BUNDLE_NAME = "name"; +static const char *CONF_DEFAULT_LAUNCH_BUNDLE_SECURED = "secured"; +static const char *CONF_DEFAULT_LAUNCH_BUNDLE_ABI = "abi"; +static const char *CONF_DEFAULT_LAUNCH_BUNDLE_HW_ACCELERATION = "hw-acceleration"; +static const char *CONF_DEFAULT_CONTENT = "default"; +static const char *CONF_DEFAULT_TITLE = ""; +static const char *CONF_DEFAULT_EMPTY_CONTENT = ""; +static const char *CONF_DEFAULT_EMPTY_TITLE = ""; +static const char *CONF_DEFAULT_REPLACE_TAG = "/APPID/"; +static const char *CONF_DEFAULT_PROVIDER_METHOD = "pixmap"; +static const char *CONF_DEFAULT_CATEGORY_LIST = "com.samsung.wmanager.WATCH_CLOCK"; +static const int CONF_DEFAULT_WIDTH = 0; +static const int CONF_DEFAULT_HEIGHT = 0; +static const int CONF_DEFAULT_BASE_WIDTH = 720; +static const int CONF_DEFAULT_BASE_HEIGHT = 1280; +static const double CONF_DEFAULT_MINIMUM_PERIOD = 1.0f; +static const double CONF_DEFAULT_PERIOD = -1.0f; +static const double CONF_DEFAULT_PACKET_TIME = 0.0001f; +static const unsigned long CONF_DEFAULT_MINIMUM_SPACE = 5242880; +static const double CONF_DEFAULT_SLAVE_TTL = 30.0f; +static const double CONF_DEFAULT_SLAVE_ACTIVATE_TIME = 30.0f; +static const double CONF_DEFAULT_SLAVE_RELAUNCH_TIME = 3.0f; +static const int CONF_DEFAULT_SLAVE_RELAUNCH_COUNT = 3; +static const int CONF_DEFAULT_MAX_LOG_LINE = 1000; +static const int CONF_DEFAULT_MAX_LOG_FILE = 3; +static const int CONF_DEFAULT_SQLITE_FLUSH_MAX = 1048576; +static const double CONF_DEFAULT_PING_TIME = 240.0f; +static const int CONF_DEFAULT_SLAVE_MAX_LOAD = 30; +static const int CONF_DEFAULT_USE_SW_BACKEND = 0; +static const int CONF_DEFAULT_DEBUG_MODE = 0; +static const int CONF_DEFAULT_OVERWRITE_CONTENT = 0; +static const int CONF_DEFAULT_COM_CORE_THREAD = 1; +static const int CONF_DEFAULT_USE_XMONITOR = 0; +static const int CONF_DEFAULT_PREMULTIPLIED = 1; +static const double CONF_DEFAULT_SCALE_WIDTH_FACTOR = 1.0f; +static const double CONF_DEFAULT_SCALE_HEIGHT_FACTOR = 1.0f; +static const double CONF_DEFAULT_GBAR_REQUEST_TIMEOUT = 5.0f; +static const int CONF_DEFAULT_PIXELS = sizeof(int); +static const int CONF_DEFAULT_AUTO_ALIGN = 1; +static const int CONF_DEFAULT_USE_EVENT_TIME = 1; +static const int CONF_DEFAULT_CHECK_LCD = 1; +static const int CONF_DEFAULT_EXTRA_BUFFER_COUNT = 1; +static const int CONF_DEFAULT_USE_GETTIMEOFDAY = 0; +static const int CONF_DEFAULT_SLAVE_EVENT_BOOST_ON = 0; +static const int CONF_DEFAULT_SLAVE_EVENT_BOOST_OFF = 0; +static const double CONF_DEFAULT_EVENT_FILTER = 0.5f; +static const int CONF_DEFAULT_SLAVE_LIMIT_TO_TTL = 0; +static const int CONF_DEFAULT_SLAVE_AUTO_CACHE_FLUSH = 0; + +#define CONF_PATH_FORMAT "/usr/share/data-provider-master/%dx%d/conf.ini" + +int errno; + +struct widget_conf { + unsigned int width; + unsigned int height; + + unsigned int base_width; + unsigned int base_height; + double minimum_period; + + struct { + char *script; + char *abi; + char *gbar_group; + double period; + int pixels; + } default_conf; + + struct { + char *name; + char *secured; + char *abi; + char *hw_acceleration; + } launch_key; + + double default_packet_time; + + char *empty_content; + char *empty_title; + + char *default_content; + char *default_title; + + unsigned long minimum_space; + + char *replace_tag; + + double slave_ttl; + double slave_activate_time; + double slave_relaunch_time; + int slave_relaunch_count; + + int max_log_line; + int max_log_file; + + unsigned long sqlite_flush_max; + + struct { + char *conf; + char *image; + char *script; + char *root; + char *script_port; + char *slave_log; + char *reader; + char *always; + char *db; + char *input; + } path; + + int max_size_type; + + int slave_max_load; + + double ping_time; + + char *vconf_sys_cluster; + int max_pended_ctx_events; + + int use_sw_backend; + char *provider_method; + int debug_mode; + int overwrite_content; + int com_core_thread; + int use_xmonitor; + int premultiplied; + + double scale_width_factor; + double scale_height_factor; + + double gbar_request_timeout; + + char *emergency_disk; + char *services; + int auto_align; + int use_event_time; + int check_lcd; + int extra_buffer_count; + int use_gettimeofday; + int slave_event_boost_on; + int slave_event_boost_off; + double event_filter; + int slave_limit_to_ttl; + int frame_skip; + int slave_auto_cache_flush; + char *category_list; +}; + +static struct widget_conf s_conf; + +static struct info { + int conf_loaded; +} s_info = { + .conf_loaded = 0, +}; + +static void category_list_handler(char *buffer) +{ + s_conf.category_list = strdup(buffer); + if (!s_conf.category_list) { + ErrPrint("strdup: %s\n", strerror(errno)); + s_conf.category_list = (char *)CONF_DEFAULT_CATEGORY_LIST; + } +} + +static void slave_auto_cache_flush_handler(char *buffer) +{ + s_conf.slave_auto_cache_flush = !strcasecmp(buffer, "true"); +} + +static void frame_skip_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.frame_skip) != 1) { + ErrPrint("Unable to get frame skip: %d\n", s_conf.frame_skip); + } +} + +static void slave_limit_to_ttl_handler(char *buffer) +{ + s_conf.slave_limit_to_ttl = !strcasecmp(buffer, "true"); +} + +static void event_filter_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.event_filter) != 1) { + ErrPrint("Unable to get event filter: %lf\n", s_conf.event_filter); + } +} + +static void slave_event_boost_on_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.slave_event_boost_on) != 1) { + ErrPrint("Unable to get boost on: %d\n", s_conf.slave_event_boost_on); + } +} + +static void slave_event_boost_off_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.slave_event_boost_off) != 1) { + ErrPrint("Unable to get boost on: %d\n", s_conf.slave_event_boost_off); + } +} + +static void extra_buffer_count_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.extra_buffer_count) != 1) { + ErrPrint("Extra buffer count is not valid: [%s], remained %d\n", buffer, s_conf.extra_buffer_count); + } +} + +static void use_xmonitor(char *buffer) +{ + s_conf.use_xmonitor = !strcasecmp(buffer, "true"); +} + +static void emergency_disk_handler(char *buffer) +{ + s_conf.emergency_disk = strdup(buffer); + if (!s_conf.emergency_disk) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void check_lcd_handler(char *buffer) +{ + s_conf.check_lcd = !strcasecmp(buffer, "true"); +} + +static void use_gettimeofday_handler(char *buffer) +{ + s_conf.use_gettimeofday = !strcasecmp(buffer, "true"); +} + +static void use_event_time_handler(char *buffer) +{ + s_conf.use_event_time = !strcasecmp(buffer, "true"); +} + +static void auto_align_handler(char *buffer) +{ + s_conf.auto_align = !strcasecmp(buffer, "true"); +} + +static void services_handler(char *buffer) +{ + s_conf.services = strdup(buffer); + if (!s_conf.services) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void use_sw_backend_handler(char *buffer) +{ + s_conf.use_sw_backend = !strcasecmp(buffer, "true"); +} + +static void provider_method_handler(char *buffer) +{ + s_conf.provider_method = strdup(buffer); + if (!s_conf.provider_method) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void debug_mode_handler(char *buffer) +{ + s_conf.debug_mode = !strcasecmp(buffer, "true"); +} + +static void overwrite_content_handler(char *buffer) +{ + s_conf.overwrite_content = !strcasecmp(buffer, "true"); +} + +static void com_core_thread_handler(char *buffer) +{ + s_conf.com_core_thread = !strcasecmp(buffer, "true"); +} + +static void base_width_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.base_width) != 1) { + if (!strncasecmp(buffer, "screen", strlen("screen"))) { + s_conf.base_width = s_conf.width; + DbgPrint("Base width: %u (screen)\n", s_conf.base_width); + } else { + ErrPrint("Failed to parse the base_width\n"); + } + } +} + +static void base_height_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.base_height) != 1) { + if (!strncasecmp(buffer, "screen", strlen("screen"))) { + s_conf.base_height = s_conf.height; + DbgPrint("Base height: %u (screen)\n", s_conf.base_height); + } else { + ErrPrint("Failed to parse the base_height\n"); + } + } +} + +static void minimum_period_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.minimum_period) != 1) { + ErrPrint("Failed to parse the minimum_period\n"); + } + DbgPrint("Minimum period: %lf\n", s_conf.minimum_period); +} + +static void pixels_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.default_conf.pixels) != 1) { + ErrPrint("Failed to parse the minimum_period\n"); + } + DbgPrint("Default pixels: %lf\n", s_conf.default_conf.pixels); +} + +static void script_handler(char *buffer) +{ + s_conf.default_conf.script = strdup(buffer); + if (!s_conf.default_conf.script) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void default_abi_handler(char *buffer) +{ + s_conf.default_conf.abi = strdup(buffer); + if (!s_conf.default_conf.abi) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void default_group_handler(char *buffer) +{ + s_conf.default_conf.gbar_group = strdup(buffer); + if (!s_conf.default_conf.gbar_group) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void default_period_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.default_conf.period) != 1) { + ErrPrint("Failed to parse the default_period\n"); + } + DbgPrint("Default Period: %lf\n", s_conf.default_conf.period); +} + +static void default_packet_time_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.default_packet_time) != 1) { + ErrPrint("Failed to parse the default_packet_time\n"); + } + DbgPrint("Default packet time: %lf\n", s_conf.default_packet_time); +} + +static void default_content_handler(char *buffer) +{ + s_conf.default_content = strdup(buffer); + if (!s_conf.default_content) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void default_title_handler(char *buffer) +{ + s_conf.default_title = strdup(buffer); + if (!s_conf.default_title) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void minimum_space_handler(char *buffer) +{ + if (sscanf(buffer, "%lu", &s_conf.minimum_space) != 1) { + ErrPrint("Failed to parse the minimum_space\n"); + } +} + +static void replace_tag_handler(char *buffer) +{ + s_conf.replace_tag = strdup(buffer); + if (!s_conf.replace_tag) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void slave_ttl_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.slave_ttl) != 1) { + ErrPrint("Failed to parse the slave_ttl\n"); + } + DbgPrint("Slave TTL: %lf\n", s_conf.slave_ttl); +} + +static void slave_activate_time_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.slave_activate_time) != 1) { + ErrPrint("Failed to parse the slave_activate_time\n"); + } + DbgPrint("Slave activate time: %lf\n", s_conf.slave_activate_time); +} + +static void slave_relaunch_time_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.slave_relaunch_time) != 1) { + ErrPrint("Failed to parse the slave_activate_time\n"); + } + DbgPrint("Slave relaunch time: %lf\n", s_conf.slave_relaunch_time); +} + +static void slave_relaunch_count_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.slave_relaunch_count) != 1) { + ErrPrint("Failed to parse the max_log_line\n"); + } +} + +static void max_log_line_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.max_log_line) != 1) { + ErrPrint("Failed to parse the max_log_line\n"); + } +} + +static void max_log_file_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.max_log_file) != 1) { + ErrPrint("Failed to parse the max_log_file\n"); + } +} + +static void sqlite_flush_max_handler(char *buffer) +{ + if (sscanf(buffer, "%lu", &s_conf.sqlite_flush_max) != 1) { + ErrPrint("Failed to parse the sqlite_flush_max\n"); + } +} + +static void db_path_handler(char *buffer) +{ + s_conf.path.db = strdup(buffer); + if (!s_conf.path.db) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void reader_path_handler(char *buffer) +{ + s_conf.path.reader = strdup(buffer); + if (!s_conf.path.reader) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void always_path_handler(char *buffer) +{ + s_conf.path.always = strdup(buffer); + if (!s_conf.path.always) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void log_path_handler(char *buffer) +{ + s_conf.path.slave_log = strdup(buffer); + if (!s_conf.path.slave_log) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void script_port_path_handler(char *buffer) +{ + s_conf.path.script_port = strdup(buffer); + if (!s_conf.path.script_port) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static void share_path_handler(char *buffer) +{ + s_conf.path.image = strdup(buffer); + if (!s_conf.path.image) { + ErrPrint("Heap: %s\n", strerror(errno)); + } +} + +static char *parse_handler(const char *buffer) +{ + const char *node_prefix = NODE_PREFIX; + int idx = 0; + const char *ptr; + int node_idx = 0; + char *node = NULL; + + ptr = buffer; + while (*ptr) { + if (ptr[idx] == node_prefix[idx]) { + idx++; + } else if (idx > 0 && node_prefix[idx] == '\0') { + if (sscanf(ptr + idx, "%d", &node_idx) == 1) { + int node_len; + node_len = idx + strlen(DEV_PATH) + 10; + /* Gotcha */ + node = malloc(node_len); + if (node) { + int len; + + len = snprintf(node, node_len - 1, DEV_PATH "%s%d", node_prefix, node_idx); + if (len < 0) { + ErrPrint("snprintf: %s\n", strerror(errno)); + free(node); + node = NULL; + } else { + node[len] = '\0'; + DbgPrint("NODE FOUND: %s\n", node); + } + } else { + ErrPrint("malloc: %s\n", strerror(errno)); + } + + break; + } else { + DbgPrint("Invalid format: [%s] / [%s]\n", ptr, ptr + idx); + ptr++; + idx = 0; + } + } else { + ptr++; + idx = 0; + } + } + + return node; +} + +static char *find_input_device(const char *name) +{ + int fd; + char *node = NULL; + char ch; + int row; + int col; + int idx; + enum state { + STATE_BEGIN, + STATE_ID, + STATE_NAME, + STATE_PHYSICAL, + STATE_SYSFS, + STATE_UNIQ, + STATE_HANDLER, + STATE_BITMAPS, + STATE_ERROR, + } state; + char name_buffer[MAX_LINE_BUFFER] = { 0, }; + char handler_buffer[MAX_LINE_BUFFER] = { 0, }; + + fd = open(PROC_INPUT_DEVICES, O_RDONLY); + if (fd < 0) { + ErrPrint("open: %s\n", strerror(errno)); + return NULL; + } + + state = STATE_BEGIN; + row = 1; + col = 1; + idx = -1; + while (state != STATE_ERROR && node == NULL && read(fd, &ch, sizeof(ch)) == sizeof(ch)) { + if (ch == LF) { + row++; + col = 1; + + switch (state) { + case STATE_NAME: + state = STATE_BEGIN; + if (idx > 0) { + /* Remove last double-quotes */ + if (name_buffer[idx - 1] == '"') { + idx--; + } + name_buffer[idx] = '\0'; + idx = -1; + DbgPrint("Name: [%s]\n", name_buffer); + } + break; + case STATE_HANDLER: + state = STATE_BEGIN; + if (idx > 0) { + handler_buffer[idx] = '\0'; + idx = -1; + DbgPrint("Handler: [%s]\n", handler_buffer); + } + break; + case STATE_BEGIN: + DbgPrint("name: [%s], name_buffer[%s]\n", name, name_buffer); + if (!strcasecmp(name, name_buffer)) { + node = parse_handler(handler_buffer); + } + break; + default: + /* Ignore other attributes */ + state = STATE_BEGIN; + idx = -1; + break; + } + + continue; + } + + col++; + switch (state) { + case STATE_BEGIN: + switch (ch) { + case 'I': + state = STATE_ID; + break; + case 'N': + state = STATE_NAME; + break; + case 'P': + state = STATE_PHYSICAL; + break; + case 'S': + state = STATE_SYSFS; + break; + case 'U': + state = STATE_UNIQ; + break; + case 'H': + state = STATE_HANDLER; + break; + case 'B': + state = STATE_BITMAPS; + break; + default: + state = STATE_ERROR; + break; + } + break; + case STATE_NAME: + if (ch == '=') { + idx = 0; + } else if (idx == MAX_LINE_BUFFER - 1) { + ErrPrint("Out of buffer\n"); + } else if (idx == 0 && ch == '"') { + /* Ignore the first quotes */ + } else if (idx >= 0) { + name_buffer[idx++] = ch; + } + break; + case STATE_HANDLER: + if (ch == '=') { + idx = 0; + } else if (idx == MAX_LINE_BUFFER - 1) { + ErrPrint("Out of buffer\n"); + } else if (idx >= 0) { + handler_buffer[idx++] = ch; + } + break; + case STATE_ID: + case STATE_PHYSICAL: + case STATE_SYSFS: + case STATE_UNIQ: + case STATE_BITMAPS: + /* Ignore other attributes */ + break; + default: + break; + } + } + + if (state == STATE_ERROR) { + ErrPrint("Invalid state: ROW[%d] COL[%d]\n", row, col); + } + + if (close(fd) < 0) { + ErrPrint("close: %s\n", strerror(errno)); + } + + return node; +} + +static void input_path_handler(char *buffer) +{ + if (buffer[0] == '/') { + DbgPrint("Specifying the input device\n"); + s_conf.path.input = strdup(buffer); + if (!s_conf.path.input) { + ErrPrint("Heap: %s\n", strerror(errno)); + } + } else { + DbgPrint("Find the input device\n"); + s_conf.path.input = find_input_device(buffer); + if (s_conf.path.input == NULL) { + ErrPrint("Fallback to raw string\n"); + s_conf.path.input = strdup(buffer); + if (!s_conf.path.input) { + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + } +} + +static void ping_time_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.ping_time) != 1) { + ErrPrint("Failed to parse the ping_time\n"); + } + DbgPrint("Default ping time: %lf\n", s_conf.ping_time); +} + +static void slave_max_loader(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.slave_max_load) != 1) { + ErrPrint("Failed to parse the slave_max_load\n"); + } +} + +static void premultiplied_handler(char *buffer) +{ + if (sscanf(buffer, "%d", &s_conf.premultiplied) != 1) { + ErrPrint("Failed to parse the premultiplied color\n"); + } + + DbgPrint("Premultiplied: %d\n", s_conf.premultiplied); +} + +static void gbar_request_timeout_handler(char *buffer) +{ + if (sscanf(buffer, "%lf", &s_conf.gbar_request_timeout) != 1) { + ErrPrint("Failed to parse the request_timeout\n"); + } + DbgPrint("Default GBAR request timeout: %lf\n", s_conf.gbar_request_timeout); +} + +EAPI void widget_conf_init(void) +{ + if (s_info.conf_loaded) { + DbgPrint("Already initialized.\n"); + return; + } + + s_conf.width = CONF_DEFAULT_WIDTH; + s_conf.height = CONF_DEFAULT_HEIGHT; + s_conf.base_width = CONF_DEFAULT_BASE_WIDTH; + s_conf.base_height = CONF_DEFAULT_BASE_HEIGHT; + s_conf.minimum_period = CONF_DEFAULT_MINIMUM_PERIOD; + s_conf.default_conf.period = CONF_DEFAULT_PERIOD; + s_conf.default_conf.pixels = CONF_DEFAULT_PIXELS; + s_conf.minimum_space = CONF_DEFAULT_MINIMUM_SPACE; + s_conf.default_packet_time = CONF_DEFAULT_PACKET_TIME; + s_conf.slave_ttl = CONF_DEFAULT_SLAVE_TTL; + s_conf.slave_activate_time = CONF_DEFAULT_SLAVE_ACTIVATE_TIME; + s_conf.slave_relaunch_time = CONF_DEFAULT_SLAVE_RELAUNCH_TIME; + s_conf.slave_relaunch_count = CONF_DEFAULT_SLAVE_RELAUNCH_COUNT; + s_conf.max_log_line = CONF_DEFAULT_MAX_LOG_LINE; + s_conf.max_log_file = CONF_DEFAULT_MAX_LOG_FILE; + s_conf.sqlite_flush_max = CONF_DEFAULT_SQLITE_FLUSH_MAX; + s_conf.ping_time = CONF_DEFAULT_PING_TIME; + s_conf.slave_max_load = CONF_DEFAULT_SLAVE_MAX_LOAD; + s_conf.use_sw_backend = CONF_DEFAULT_USE_SW_BACKEND; + s_conf.debug_mode = CONF_DEFAULT_DEBUG_MODE; + s_conf.overwrite_content = CONF_DEFAULT_OVERWRITE_CONTENT; + s_conf.com_core_thread = CONF_DEFAULT_COM_CORE_THREAD; + s_conf.use_xmonitor = CONF_DEFAULT_USE_XMONITOR; + s_conf.scale_width_factor = CONF_DEFAULT_SCALE_WIDTH_FACTOR; + s_conf.scale_height_factor = CONF_DEFAULT_SCALE_HEIGHT_FACTOR; + s_conf.gbar_request_timeout = CONF_DEFAULT_GBAR_REQUEST_TIMEOUT; + s_conf.premultiplied = CONF_DEFAULT_PREMULTIPLIED; + s_conf.default_conf.script = (char *)CONF_DEFAULT_SCRIPT_TYPE; + s_conf.default_conf.abi = (char *)CONF_DEFAULT_ABI; + s_conf.default_conf.gbar_group = (char *)CONF_DEFAULT_GBAR_GROUP; + s_conf.launch_key.name = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_NAME; + s_conf.launch_key.secured = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_SECURED; + s_conf.launch_key.abi = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_ABI; + s_conf.launch_key.hw_acceleration = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_HW_ACCELERATION; + s_conf.empty_content = (char *)CONF_DEFAULT_EMPTY_CONTENT; + s_conf.empty_title = (char *)CONF_DEFAULT_EMPTY_TITLE; + s_conf.default_content = (char *)CONF_DEFAULT_CONTENT; + s_conf.default_title = (char *)CONF_DEFAULT_TITLE; + s_conf.replace_tag = (char *)CONF_DEFAULT_REPLACE_TAG; + s_conf.path.conf = (char *)CONF_DEFAULT_PATH_CONF; + s_conf.path.image = (char *)CONF_DEFAULT_PATH_IMAGE; + s_conf.path.slave_log = (char *)CONF_DEFAULT_PATH_LOG; + s_conf.path.reader = (char *)CONF_DEFAULT_PATH_READER; + s_conf.path.always = (char *)CONF_DEFAULT_PATH_ALWAYS; + s_conf.path.script = (char *)CONF_DEFAULT_PATH_SCRIPT; + s_conf.path.root = (char *)CONF_DEFAULT_PATH_ROOT; + s_conf.path.script_port = (char *)CONF_DEFAULT_PATH_SCRIPT_PORT; + s_conf.path.db = (char *)CONF_DEFAULT_PATH_DB; + s_conf.path.input = (char *)CONF_DEFAULT_PATH_INPUT; + s_conf.provider_method = (char *)CONF_DEFAULT_PROVIDER_METHOD; + s_conf.emergency_disk = (char *)CONF_DEFAULT_EMERGENCY_DISK; + s_conf.services = (char *)CONF_DEFAULT_SERVICES; + s_conf.category_list = (char *)CONF_DEFAULT_CATEGORY_LIST; + s_conf.auto_align = CONF_DEFAULT_AUTO_ALIGN; + s_conf.use_event_time = CONF_DEFAULT_USE_EVENT_TIME; + s_conf.check_lcd = CONF_DEFAULT_CHECK_LCD; + s_conf.extra_buffer_count = CONF_DEFAULT_EXTRA_BUFFER_COUNT; + s_conf.use_gettimeofday = CONF_DEFAULT_USE_GETTIMEOFDAY; + s_conf.slave_event_boost_on = CONF_DEFAULT_SLAVE_EVENT_BOOST_ON; + s_conf.slave_event_boost_off = CONF_DEFAULT_SLAVE_EVENT_BOOST_OFF; + s_conf.event_filter = CONF_DEFAULT_EVENT_FILTER; + s_conf.slave_limit_to_ttl = CONF_DEFAULT_SLAVE_LIMIT_TO_TTL; + s_conf.slave_auto_cache_flush = CONF_DEFAULT_SLAVE_AUTO_CACHE_FLUSH; +} + +/* + * Find proper configuration and install(link) it to conf path. + */ +static char *conf_path(void) +{ + char *path; + int length; + + length = strlen(CONF_PATH_FORMAT) + 12; // 12 == RESERVED SPACE + path = calloc(1, length); + if (!path) { + ErrPrint("calloc: %s\n", strerror(errno)); + return NULL; + } + + snprintf(path, length, CONF_PATH_FORMAT, s_conf.width, s_conf.height); + DbgPrint("Selected conf file: %s\n", path); + if (access(path, F_OK) != 0) { + ErrPrint("Fallback to default, access: %s\n", strerror(errno)); + strncpy(path, DEFAULT_MASTER_CONF, length); + if (access(path, F_OK) != 0) { + ErrPrint("Serious error - there is no conf file, use default setting: %s\n", strerror(errno)); + free(path); + path = NULL; + } + } + + return path; +} + +EAPI int widget_conf_load(void) +{ + char *conf_file; + FILE *fp; + int c; + enum state { + START, + SPACE, + TOKEN, + VALUE, + ERROR, + COMMENT, + END + } state; + int ch_idx; + int token_idx; + int buffer_idx; + int quote; + int linelen; + char buffer[256]; + static const struct token_parser { + const char *name; + void (*handler)(char *buffer); + } token_handler[] = { + { + .name = "base_width", + .handler = base_width_handler, + }, + { + .name = "base_height", + .handler = base_height_handler, + }, + { + .name = "minimum_period", + .handler = minimum_period_handler, + }, + { + .name = "script", + .handler = script_handler, + }, + { + .name = "pixels", + .handler = pixels_handler, + }, + { + .name = "default_abi", + .handler = default_abi_handler, + }, + { + .name = "default_group", + .handler = default_group_handler, + }, + { + .name = "default_period", + .handler = default_period_handler, + }, + { + .name = "default_packet_time", + .handler = default_packet_time_handler, + }, + { + .name = "default_content", + .handler = default_content_handler, + }, + { + .name = "default_title", + .handler = default_title_handler, + }, + { + .name = "minimum_space", + .handler = minimum_space_handler, + }, + { + .name = "replace_tag", + .handler = replace_tag_handler, + }, + { + .name = "slave_ttl", + .handler = slave_ttl_handler, + }, + { + .name = "slave_activate_time", + .handler = slave_activate_time_handler, + }, + { + .name = "slave_relaunch_time", + .handler = slave_relaunch_time_handler, + }, + { + .name = "slave_relaunch_count", + .handler = slave_relaunch_count_handler, + }, + { + .name = "max_log_line", + .handler = max_log_line_handler, + }, + { + .name = "max_log_file", + .handler = max_log_file_handler, + }, + { + .name = "sqilte_flush_max", + .handler = sqlite_flush_max_handler, + }, + { + .name = "db_path", + .handler = db_path_handler, + }, + { + .name = "log_path", + .handler = log_path_handler, + }, + { + .name = "reader_path", + .handler = reader_path_handler, + }, + { + .name = "always_path", + .handler = always_path_handler, + }, + { + .name = "share_path", + .handler = share_path_handler, + }, + { + .name = "script_port_path", + .handler = script_port_path_handler, + }, + { + .name = "ping_interval", + .handler = ping_time_handler, + }, + { + .name = "slave_max_load", + .handler = slave_max_loader, + }, + { + .name = "use_sw_backend", + .handler = use_sw_backend_handler, + }, + { + .name = "emergency_disk", + .handler = emergency_disk_handler, + }, + { + .name = "services", + .handler = services_handler, + }, + { + .name = "auto_align", + .handler = auto_align_handler, + }, + { + .name = "use_event_time", + .handler = use_event_time_handler, + }, + { + .name = "use_gettimeofday", + .handler = use_gettimeofday_handler, + }, + { + .name = "check_lcd", + .handler = check_lcd_handler, + }, + { + .name = "use_xmonitor", + .handler = use_xmonitor, + }, + { + .name = "provider_method", + .handler = provider_method_handler, + }, + { + .name = "debug_mode", + .handler = debug_mode_handler, + }, + { + .name = "overwrite_content", + .handler = overwrite_content_handler, + }, + { + .name = "com_core_thread", + .handler = com_core_thread_handler, + }, + { + .name = "input", + .handler = input_path_handler, + }, + { + .name = "gbar_request_timeout", + .handler = gbar_request_timeout_handler, + }, + { + .name = "premultiplied", + .handler = premultiplied_handler, + }, + { + .name = "extra_buffer_count", + .handler = extra_buffer_count_handler, + }, + { + .name = "slave_event_boost_on", + .handler = slave_event_boost_on_handler, + }, + { + .name = "slave_event_boost_off", + .handler = slave_event_boost_off_handler, + }, + { + .name = "event_filter", + .handler = event_filter_handler, + }, + { + .name = "slave_limit_to_ttl", + .handler = slave_limit_to_ttl_handler, + }, + { + .name = "frame_skip", + .handler = frame_skip_handler, + }, + { + .name = "slave_auto_cache_flush", + .handler = slave_auto_cache_flush_handler, + }, + { + .name = "category_list", + .handler = category_list_handler, + }, + { + .name = NULL, + .handler = NULL, + }, + }; + + if (s_info.conf_loaded) { + ErrPrint("Already loaded\n"); + return WIDGET_STATUS_ERROR_ALREADY; + } + + util_screen_size_get(&s_conf.width, &s_conf.height); + + conf_file = conf_path(); + if (!conf_file) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + fp = fopen(conf_file, "rt"); + free(conf_file); + if (!fp) { + ErrPrint("Error: %s\n", strerror(errno)); + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + state = START; + ch_idx = 0; + token_idx = -1; + buffer_idx = 0; + quote = 0; + linelen = 0; + do { + c = getc(fp); + if ((c == EOF) && (state == VALUE)) { + DbgPrint("[%s:%d] VALUE state EOF\n", __func__, __LINE__); + state = END; + } + + switch (state) { + case COMMENT: + if (c == CR || c == LF || c == EOF) { + buffer[buffer_idx] = '\0'; + + state = START; + token_idx = -1; + ch_idx = 0; + buffer_idx = 0; + linelen = -1; /* Will be ZERO by follwing increment code */ + quote = 0; + } else { + buffer[buffer_idx++] = c; + if (buffer_idx == (sizeof(buffer) - 1)) { + buffer[buffer_idx] = '\0'; + buffer_idx = 0; + } + } + break; + case START: + if (linelen == 0 && c == '#') { + state = COMMENT; + } else if (isspace(c)) { + /* Ignore empty space */ + } else { + state = TOKEN; + ungetc(c, fp); + } + break; + case SPACE: + if (c == '=') { + state = VALUE; + } else if (!isspace(c)) { + state = ERROR; + } + break; + case VALUE: + if (c == '"') { + if (quote == 1) { + buffer[buffer_idx] = '\0'; + state = END; + } else if (buffer_idx != 0) { + buffer[buffer_idx++] = c; + if (buffer_idx >= sizeof(buffer)) { + state = ERROR; + } + } else { + quote = 1; + } + } else if (isspace(c)) { + if (buffer_idx == 0) { + /* Ignore */ + } else if (quote == 1) { + buffer[buffer_idx++] = c; + if (buffer_idx >= sizeof(buffer)) { + state = ERROR; + } + } else { + buffer[buffer_idx] = '\0'; + ungetc(c, fp); + state = END; + } + } else { + buffer[buffer_idx++] = c; + if (buffer_idx >= sizeof(buffer)) { + state = ERROR; + } + } + break; + case TOKEN: + if (c == '=') { + if (token_idx < 0) { + state = ERROR; + } else { + state = VALUE; + } + } else if (isspace(c)) { + if (token_idx < 0) { + break; + } + + if (token_handler[token_idx].name[ch_idx] != '\0') { + state = ERROR; + } else { + state = SPACE; + } + } else { + if (token_idx < 0) { + /* Now start to find a token! */ + token_idx = 0; + } + + if (token_handler[token_idx].name[ch_idx] == c) { + ch_idx++; + } else { + ungetc(c, fp); + while (ch_idx-- > 0) + ungetc(token_handler[token_idx].name[ch_idx], fp); + + token_idx++; + + if (token_handler[token_idx].name == NULL) { + state = ERROR; + } else { + ch_idx = 0; + } + } + } + break; + case ERROR: + if (c == CR || c == LF || c == EOF) { + state = START; + token_idx = -1; + buffer_idx = 0; + ch_idx = 0; + linelen = -1; + quote = 0; + } + break; + case END: + if (c == LF || c == CR || c == EOF) { + state = START; + + if (token_idx >= 0 && token_handler[token_idx].handler) { + buffer[buffer_idx] = '\0'; + token_handler[token_idx].handler(buffer); + } + + token_idx = -1; + ch_idx = 0; + buffer_idx = 0; + linelen = -1; + quote = 0; + /* Finish */ + } else if (isspace(c)) { + /* ignore */ + } else { + state = ERROR; + } + break; + default: + /* ?? */ + break; + } + + linelen++; + } while (c != EOF); + + if (fclose(fp) != 0) { + ErrPrint("fclose: %s\n", strerror(errno)); + } + + s_conf.scale_width_factor = (double)s_conf.width / (double)WIDGET_CONF_BASE_W; + s_conf.scale_height_factor = (double)s_conf.height / (double)WIDGET_CONF_BASE_H; + s_info.conf_loaded = 1; + + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI void widget_conf_reset(void) +{ + s_conf.width = CONF_DEFAULT_WIDTH; + s_conf.height = CONF_DEFAULT_HEIGHT; + s_conf.base_width = CONF_DEFAULT_BASE_WIDTH; + s_conf.base_height = CONF_DEFAULT_BASE_HEIGHT; + s_conf.minimum_period = CONF_DEFAULT_MINIMUM_PERIOD; + s_conf.default_conf.period = CONF_DEFAULT_PERIOD; + s_conf.minimum_space = CONF_DEFAULT_MINIMUM_SPACE; + s_conf.default_packet_time = CONF_DEFAULT_PACKET_TIME; + s_conf.slave_ttl = CONF_DEFAULT_SLAVE_TTL; + s_conf.slave_activate_time = CONF_DEFAULT_SLAVE_ACTIVATE_TIME; + s_conf.slave_relaunch_time = CONF_DEFAULT_SLAVE_RELAUNCH_TIME; + s_conf.slave_relaunch_count = CONF_DEFAULT_SLAVE_RELAUNCH_COUNT; + s_conf.max_log_line = CONF_DEFAULT_MAX_LOG_LINE; + s_conf.max_log_file = CONF_DEFAULT_MAX_LOG_FILE; + s_conf.sqlite_flush_max = CONF_DEFAULT_SQLITE_FLUSH_MAX; + s_conf.ping_time = CONF_DEFAULT_PING_TIME; + s_conf.slave_max_load = CONF_DEFAULT_SLAVE_MAX_LOAD; + s_conf.use_sw_backend = CONF_DEFAULT_USE_SW_BACKEND; + s_conf.debug_mode = CONF_DEFAULT_DEBUG_MODE; + s_conf.overwrite_content = CONF_DEFAULT_OVERWRITE_CONTENT; + s_conf.com_core_thread = CONF_DEFAULT_COM_CORE_THREAD; + s_conf.use_xmonitor = CONF_DEFAULT_USE_XMONITOR; + s_conf.scale_width_factor = CONF_DEFAULT_SCALE_WIDTH_FACTOR; + s_conf.scale_height_factor = CONF_DEFAULT_SCALE_HEIGHT_FACTOR; + s_conf.gbar_request_timeout = CONF_DEFAULT_GBAR_REQUEST_TIMEOUT; + s_conf.premultiplied = CONF_DEFAULT_PREMULTIPLIED; + s_conf.default_conf.pixels = CONF_DEFAULT_PIXELS; + s_conf.auto_align = CONF_DEFAULT_AUTO_ALIGN; + s_conf.use_event_time = CONF_DEFAULT_USE_EVENT_TIME; + s_conf.check_lcd = CONF_DEFAULT_CHECK_LCD; + s_conf.extra_buffer_count = CONF_DEFAULT_EXTRA_BUFFER_COUNT; + s_conf.use_gettimeofday = CONF_DEFAULT_USE_GETTIMEOFDAY; + s_conf.slave_event_boost_on = CONF_DEFAULT_SLAVE_EVENT_BOOST_ON; + s_conf.slave_event_boost_off = CONF_DEFAULT_SLAVE_EVENT_BOOST_OFF; + s_conf.event_filter = CONF_DEFAULT_EVENT_FILTER; + s_conf.slave_limit_to_ttl = CONF_DEFAULT_SLAVE_LIMIT_TO_TTL; + s_conf.slave_auto_cache_flush = CONF_DEFAULT_SLAVE_AUTO_CACHE_FLUSH; + + if (s_conf.category_list != CONF_DEFAULT_CATEGORY_LIST) { + free(s_conf.category_list); + s_conf.category_list = (char *)CONF_DEFAULT_CATEGORY_LIST; + } + + if (s_conf.default_conf.script != CONF_DEFAULT_SCRIPT_TYPE) { + free(s_conf.default_conf.script); + s_conf.default_conf.script = (char *)CONF_DEFAULT_SCRIPT_TYPE; + } + + if (s_conf.default_conf.abi != CONF_DEFAULT_ABI) { + free(s_conf.default_conf.abi); + s_conf.default_conf.abi = (char *)CONF_DEFAULT_ABI; + } + + if (s_conf.default_conf.gbar_group != CONF_DEFAULT_GBAR_GROUP) { + free(s_conf.default_conf.gbar_group); + s_conf.default_conf.gbar_group = (char *)CONF_DEFAULT_GBAR_GROUP; + } + + if (s_conf.launch_key.name != CONF_DEFAULT_LAUNCH_BUNDLE_NAME) { + free(s_conf.launch_key.name); + s_conf.launch_key.name = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_NAME; + } + + if (s_conf.launch_key.secured != CONF_DEFAULT_LAUNCH_BUNDLE_SECURED) { + free(s_conf.launch_key.secured); + s_conf.launch_key.secured = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_SECURED; + } + + if (s_conf.launch_key.abi != CONF_DEFAULT_LAUNCH_BUNDLE_ABI) { + free(s_conf.launch_key.abi); + s_conf.launch_key.abi = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_ABI; + } + + if (s_conf.launch_key.hw_acceleration != CONF_DEFAULT_LAUNCH_BUNDLE_HW_ACCELERATION) { + free(s_conf.launch_key.hw_acceleration); + s_conf.launch_key.hw_acceleration = (char *)CONF_DEFAULT_LAUNCH_BUNDLE_HW_ACCELERATION; + } + + if (s_conf.empty_content != CONF_DEFAULT_EMPTY_CONTENT) { + free(s_conf.empty_content); + s_conf.empty_content = (char *)CONF_DEFAULT_EMPTY_CONTENT; + } + + if (s_conf.empty_title != CONF_DEFAULT_EMPTY_TITLE) { + free(s_conf.empty_title); + s_conf.empty_title = (char *)CONF_DEFAULT_EMPTY_TITLE; + } + + if (s_conf.default_content != CONF_DEFAULT_CONTENT) { + free(s_conf.default_content); + s_conf.default_content = (char *)CONF_DEFAULT_CONTENT; + } + + if (s_conf.default_title != CONF_DEFAULT_TITLE) { + free(s_conf.default_title); + s_conf.default_title = (char *)CONF_DEFAULT_TITLE; + } + + if (s_conf.replace_tag != CONF_DEFAULT_REPLACE_TAG) { + free(s_conf.replace_tag); + s_conf.replace_tag = (char *)CONF_DEFAULT_REPLACE_TAG; + } + + if (s_conf.path.conf != CONF_DEFAULT_PATH_CONF) { + free(s_conf.path.conf); + s_conf.path.conf = (char *)CONF_DEFAULT_PATH_CONF; + } + + if (s_conf.path.image != CONF_DEFAULT_PATH_IMAGE) { + free(s_conf.path.image); + s_conf.path.image = (char *)CONF_DEFAULT_PATH_IMAGE; + } + + if (s_conf.path.slave_log != CONF_DEFAULT_PATH_LOG) { + free(s_conf.path.slave_log); + s_conf.path.slave_log = (char *)CONF_DEFAULT_PATH_LOG; + } + + if (s_conf.path.reader != CONF_DEFAULT_PATH_READER) { + free(s_conf.path.reader); + s_conf.path.reader = (char *)CONF_DEFAULT_PATH_READER; + } + + if (s_conf.path.always != CONF_DEFAULT_PATH_ALWAYS) { + free(s_conf.path.always); + s_conf.path.always = (char *)CONF_DEFAULT_PATH_ALWAYS; + } + + if (s_conf.path.script != CONF_DEFAULT_PATH_SCRIPT) { + free(s_conf.path.script); + s_conf.path.script = (char *)CONF_DEFAULT_PATH_SCRIPT; + } + + if (s_conf.path.root != CONF_DEFAULT_PATH_ROOT) { + free(s_conf.path.root); + s_conf.path.root = (char *)CONF_DEFAULT_PATH_ROOT; + } + + if (s_conf.path.script_port != CONF_DEFAULT_PATH_SCRIPT_PORT) { + free(s_conf.path.script_port); + s_conf.path.script_port = (char *)CONF_DEFAULT_PATH_SCRIPT_PORT; + } + + if (s_conf.path.db != CONF_DEFAULT_PATH_DB) { + free(s_conf.path.db); + s_conf.path.db = (char *)CONF_DEFAULT_PATH_DB; + } + + if (s_conf.path.input != CONF_DEFAULT_PATH_INPUT) { + free(s_conf.path.input); + s_conf.path.input = (char *)CONF_DEFAULT_PATH_INPUT; + } + + if (s_conf.provider_method != CONF_DEFAULT_PROVIDER_METHOD) { + free(s_conf.provider_method); + s_conf.provider_method = (char *)CONF_DEFAULT_PROVIDER_METHOD; + } + + if (s_conf.emergency_disk != CONF_DEFAULT_EMERGENCY_DISK) { + free(s_conf.emergency_disk); + s_conf.emergency_disk = (char *)CONF_DEFAULT_EMERGENCY_DISK; + } + + if (s_conf.services != CONF_DEFAULT_SERVICES) { + free(s_conf.services); + s_conf.services = (char *)CONF_DEFAULT_SERVICES; + } + + s_info.conf_loaded = 0; +} + +EAPI const int const widget_conf_extra_buffer_count(void) +{ + return s_conf.extra_buffer_count; +} + +EAPI const int const widget_conf_use_xmonitor(void) +{ + return s_conf.use_xmonitor; +} + +EAPI const char * const widget_conf_emergency_disk(void) +{ + return s_conf.emergency_disk; +} + +EAPI const int const widget_conf_check_lcd(void) +{ + return s_conf.check_lcd; +} + +EAPI const int const widget_conf_use_event_time(void) +{ + return s_conf.use_event_time; +} + +EAPI const int const widget_conf_auto_align(void) +{ + return s_conf.auto_align; +} + +EAPI const char * const widget_conf_services(void) +{ + return s_conf.services; +} + +EAPI const int const widget_conf_use_sw_backend(void) +{ + return s_conf.use_sw_backend; +} + +EAPI const char * const widget_conf_provider_method(void) +{ + return s_conf.provider_method; +} + +EAPI const int const widget_conf_debug_mode(void) +{ + return s_conf.debug_mode; +} + +EAPI const int const widget_conf_overwrite_content(void) +{ + return s_conf.overwrite_content; +} + +EAPI const int const widget_conf_com_core_thread(void) +{ + return s_conf.com_core_thread; +} + +EAPI const unsigned int const widget_conf_base_width(void) +{ + return s_conf.base_width; +} + +EAPI const unsigned int const widget_conf_base_height(void) +{ + return s_conf.base_height; +} + +EAPI const double const widget_conf_minimum_period(void) +{ + return s_conf.minimum_period; +} + +EAPI const int const widget_conf_default_pixels(void) +{ + return s_conf.default_conf.pixels; +} + +EAPI const char * const widget_conf_default_script(void) +{ + return s_conf.default_conf.script; +} + +EAPI const char * const widget_conf_default_abi(void) +{ + return s_conf.default_conf.abi; +} + +EAPI const char * const widget_conf_default_gbar_group(void) +{ + return s_conf.default_conf.gbar_group; +} + +EAPI const double const widget_conf_default_period(void) +{ + return s_conf.default_conf.period; +} + +EAPI const double const widget_conf_default_packet_time(void) +{ + return s_conf.default_packet_time; +} + +EAPI const char * const widget_conf_default_content(void) +{ + return s_conf.default_content; +} + +EAPI const char * const widget_conf_default_title(void) +{ + return s_conf.default_title; +} + +EAPI const unsigned long const widget_conf_minimum_space(void) +{ + return s_conf.minimum_space; +} + +EAPI const char * const widget_conf_replace_tag(void) +{ + return s_conf.replace_tag; +} + +EAPI const double const widget_conf_slave_ttl(void) +{ + return s_conf.slave_ttl; +} + +EAPI const double const widget_conf_slave_activate_time(void) +{ + return s_conf.slave_activate_time; +} + +EAPI const double const widget_conf_slave_relaunch_time(void) +{ + return s_conf.slave_relaunch_time; +} + +EAPI const int const widget_conf_slave_relaunch_count(void) +{ + return s_conf.slave_relaunch_count; +} + +EAPI const int const widget_conf_max_log_line(void) +{ + return s_conf.max_log_line; +} + +EAPI const int const widget_conf_max_log_file(void) +{ + return s_conf.max_log_file; +} + +EAPI const unsigned long const widget_conf_sqlite_flush_max(void) +{ + return s_conf.sqlite_flush_max; +} + +EAPI const char * const widget_conf_db_path(void) +{ + return s_conf.path.db; +} + +EAPI const char * const widget_conf_reader_path(void) +{ + return s_conf.path.reader; +} + +EAPI const char * const widget_conf_always_path(void) +{ + return s_conf.path.always; +} + +EAPI const char * const widget_conf_log_path(void) +{ + return s_conf.path.slave_log; +} + +EAPI const char * const widget_conf_script_port(void) +{ + return s_conf.path.script_port; +} + +EAPI const char * const widget_conf_script_path(void) +{ + return s_conf.path.script; +} + +EAPI const char * const widget_conf_share_path(void) +{ + return s_conf.path.image; +} + +EAPI const char * const widget_conf_input_path(void) +{ + return s_conf.path.input; +} + +EAPI const double const widget_conf_ping_time(void) +{ + return s_conf.ping_time; +} + +EAPI const int const widget_conf_slave_max_load(void) +{ + return s_conf.slave_max_load; +} + +EAPI const int const widget_conf_premultiplied_alpha(void) +{ + return s_conf.premultiplied; +} + +EAPI const double const widget_conf_gbar_request_timeout(void) +{ + return s_conf.gbar_request_timeout; +} + +EAPI const double const widget_conf_scale_width_factor(void) +{ + return s_conf.scale_width_factor; +} + +EAPI const double const widget_conf_scale_height_factor(void) +{ + return s_conf.scale_height_factor; +} + +EAPI const char * const widget_conf_launch_key_name(void) +{ + return s_conf.launch_key.name; +} + +EAPI const char * const widget_conf_launch_key_secured(void) +{ + return s_conf.launch_key.secured; +} + +EAPI const char * const widget_conf_launch_key_abi(void) +{ + return s_conf.launch_key.abi; +} + +EAPI const char * const widget_conf_launch_key_hw_acceleration(void) +{ + return s_conf.launch_key.hw_acceleration; +} + +EAPI const char * const widget_conf_empty_content(void) +{ + return s_conf.empty_content; +} + +EAPI const char * const widget_conf_empty_title(void) +{ + return s_conf.empty_title; +} + +EAPI const char * const widget_conf_path(void) +{ + return s_conf.path.conf; +} + +EAPI const char * const widget_conf_root_path(void) +{ + return s_conf.path.root; +} + +EAPI const int const widget_conf_is_loaded(void) +{ + return s_info.conf_loaded; +} + +EAPI const int const widget_conf_use_gettimeofday(void) +{ + return s_conf.use_gettimeofday; +} + +EAPI const int const widget_conf_slave_event_boost_on(void) +{ + return s_conf.slave_event_boost_on; +} + +EAPI const int const widget_conf_slave_event_boost_off(void) +{ + return s_conf.slave_event_boost_off; +} + +EAPI const double const widget_conf_event_filter(void) +{ + return s_conf.event_filter; +} + +EAPI const int const widget_conf_slave_limit_to_ttl(void) +{ + return s_conf.slave_limit_to_ttl; +} + +EAPI const int const widget_conf_frame_skip(void) +{ + return s_conf.frame_skip; +} + +EAPI const int const widget_conf_slave_auto_cache_flush(void) +{ + return s_conf.slave_auto_cache_flush; +} + +EAPI const char * const widget_conf_category_list(void) +{ + return s_conf.category_list; +} + +/* End of a file */ diff --git a/src/widget_service.c b/src/widget_service.c new file mode 100755 index 0000000..a885164 --- /dev/null +++ b/src/widget_service.c @@ -0,0 +1,3230 @@ +/* + * 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 <errno.h> +#include <stdlib.h> /* malloc */ +#include <string.h> /* strdup, strerror */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sqlite3.h> +#include <ctype.h> +#include <fcntl.h> + +#include <com-core_packet.h> +#include <packet.h> +#include <dlog.h> +#include <db-util.h> +#include <package-manager.h> +#include <pkgmgr-info.h> +#include <vconf.h> +#include <vconf-keys.h> +#include <ail.h> +#include <unicode/uloc.h> + +#include "widget_errno.h" +#include "dlist.h" +#include "util.h" +#include "debug.h" +#include "widget_service.h" +#include "widget_cmd_list.h" +#include "widget_buffer.h" + +#define WIDGET_ID_PREFIX "org.tizen." +#define DEFAULT_TIMEOUT 2.0 + +/* "/shared/res/" */ +#define RESOURCE_PATH "/" + +/* "/shared/libexec/" */ +#define LIBEXEC_PATH "/" + +static struct supported_size_list SIZE_LIST[WIDGET_NR_OF_SIZE_LIST] = { + { 175, 175 }, /*!< 1x1 */ + { 354, 175 }, /*!< 2x1 */ + { 354, 354 }, /*!< 2x2 */ + { 712, 175 }, /*!< 4x1 */ + { 712, 354 }, /*!< 4x2 */ + { 712, 533 }, /*!< 4x3 */ + { 712, 712 }, /*!< 4x4 */ + { 712, 891 }, /*!< 4x5 */ + { 712, 1070 }, /*!< 4x6 */ + { 224, 215 }, /*!< 21x21 */ + { 680, 215 }, /*!< 23x21 */ + { 680, 653 }, /*!< 23x23 */ + { 720, 1280 }, /*!< 0x0 */ +}; + +struct widget_pkglist_handle { + enum pkglist_type { + PKGLIST_TYPE_WIDGET_LIST = 0x00beef00, + PKGLIST_TYPE_UNKNOWN = 0x00dead00 + } type; + sqlite3 *handle; + sqlite3_stmt *stmt; +}; + +static struct service_info s_info = { + .handle = NULL, + .dbfile = DB_FILE, + .conf_file = NULL, + .init_count = 0, + + .iso3lang = NULL, + .country = { 0, }, + .syslang = NULL, + .country_len = 0, + + .base_w = 720, + .base_h = 1280, + + .base_parse = 0, + + .last_status = WIDGET_STATUS_ERROR_NONE, +}; + +struct pkgmgr_cbdata { + const char *widgetid; + void (*cb)(const char *widgetid, const char *appid, void *data); + void *cbdata; +}; + +static sqlite3 *open_db(void) +{ + sqlite3 *handle; + + if (!s_info.handle) { + int ret; + + ret = db_util_open_with_options(s_info.dbfile, &handle, SQLITE_OPEN_READONLY, NULL); + if (ret != SQLITE_OK) { + switch (ret) { + case SQLITE_PERM: + widget_set_last_status(WIDGET_STATUS_ERROR_PERMISSION_DENIED); + break; + default: + widget_set_last_status(WIDGET_STATUS_ERROR_IO_ERROR); + break; + } + + ErrPrint("Failed to open a DB\n"); + return NULL; + } + } else { + handle = s_info.handle; + } + + return handle; +} + +static inline __attribute__((always_inline)) void close_db(sqlite3 *handle) +{ + if (!s_info.handle) { + db_util_close(handle); + } +} + +static int convert_size_from_type(widget_size_type_e type, int *width, int *height) +{ + int idx; + + switch (type) { + case WIDGET_SIZE_TYPE_1x1: /*!< 175x175 */ + idx = 0; + break; + case WIDGET_SIZE_TYPE_2x1: /*!< 354x175 */ + idx = 1; + break; + case WIDGET_SIZE_TYPE_2x2: /*!< 354x354 */ + idx = 2; + break; + case WIDGET_SIZE_TYPE_4x1: /*!< 712x175 */ + idx = 3; + break; + case WIDGET_SIZE_TYPE_4x2: /*!< 712x354 */ + idx = 4; + break; + case WIDGET_SIZE_TYPE_4x3: /*!< 712x533 */ + idx = 5; + break; + case WIDGET_SIZE_TYPE_4x4: /*!< 712x712 */ + idx = 6; + break; + case WIDGET_SIZE_TYPE_4x5: /*!< 712x891 */ + idx = 7; + break; + case WIDGET_SIZE_TYPE_4x6: /*!< 712x1070 */ + idx = 8; + break; + case WIDGET_SIZE_TYPE_EASY_1x1: /*< 224x215 */ + idx = 9; + break; + case WIDGET_SIZE_TYPE_EASY_3x1: /*!< 680x215 */ + idx = 10; + break; + case WIDGET_SIZE_TYPE_EASY_3x3: /*!< 680x653 */ + idx = 11; + break; + case WIDGET_SIZE_TYPE_0x0: /*!< 720x1280 */ + idx = 12; + break; + default: + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + if (util_update_resolution(&s_info, SIZE_LIST) < 0) { + ErrPrint("Failed to update resolution\n"); + } + + *width = SIZE_LIST[idx].w; + *height = SIZE_LIST[idx].h; + return WIDGET_STATUS_ERROR_NONE; +} + +static int pkgmgr_cb(const pkgmgrinfo_appinfo_h handle, void *user_data) +{ + struct pkgmgr_cbdata *cbdata = (struct pkgmgr_cbdata *)user_data; + char *appid; + int ret; + + ret = pkgmgrinfo_appinfo_get_appid(handle, &appid); + if (ret < 0) { + ErrPrint("Unable to get appid\n"); + } else { + cbdata->cb(cbdata->widgetid, appid, cbdata->cbdata); + } + + return 0; +} + +static inline char *pkgmgr_get_mainapp(const char *pkgid) +{ + pkgmgrinfo_pkginfo_h handle; + char *ret = NULL; + + if (pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle) != PMINFO_R_OK) { + ErrPrint("Unable to get mainapp: %s\n", pkgid); + return NULL; + } + + if (pkgmgrinfo_pkginfo_get_mainappid(handle, &ret) == PMINFO_R_OK) { + ret = strdup(ret); + } else { + ErrPrint("Failed to get mainappid\n"); + ret = NULL; /* I cannot believe the pkgmgrinfo_pkginfo_get_mainappid. it maybe able to touch my "ret" even though it fails */ + + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return ret; +} + +static inline int pkgmgr_get_applist(const char *pkgid, const char *widgetid, void (*cb)(const char *widgetid, const char *appid, void *data), void *data) +{ + struct pkgmgr_cbdata cbdata; + pkgmgrinfo_pkginfo_h handle; + int ret; + + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle); + if (ret < 0) { + ErrPrint("Unable to get pkginfo: %s\n", pkgid); + return ret; + } + + cbdata.widgetid = widgetid; + cbdata.cb = cb; + cbdata.cbdata = data; + + ret = pkgmgrinfo_appinfo_get_list(handle, PM_UI_APP, pkgmgr_cb, &cbdata); + if (ret < 0) { + ErrPrint("Failed to get applist\n"); + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return ret; +} + +static char *cur_locale(void) +{ + char *language; + language = vconf_get_str(VCONFKEY_LANGSET); + if (language) { + char *ptr; + + ptr = language; + while (*ptr) { + if (*ptr == '.') { + *ptr = '\0'; + break; + } + + if (*ptr == '_') { + *ptr = '-'; + } + + ptr++; + } + } else { + language = strdup("en-us"); + if (!language) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + + return language; +} + +static char *get_default_name(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *name = NULL; + int ret; + + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT name FROM client WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + name = strdup(tmp); + if (!name) { + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return name; +} + +static char *get_default_icon(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *icon = NULL; + int ret; + + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT icon FROM client WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + icon = strdup(tmp); + if (!icon) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + } else if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return icon; +} + +static char *get_widget_pkgname_by_appid(const char *appid) +{ + sqlite3_stmt *stmt; + char *pkgid; + char *tmp; + sqlite3 *handle; + int ret; + + if (!appid) { + return NULL; + } + + pkgid = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgid FROM pkgmap WHERE (appid = ? AND prime = 1) OR (uiapp = ? AND prime = 1) OR pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + close_db(handle); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, appid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + goto out; + } + + ret = sqlite3_bind_text(stmt, 3, appid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + goto out; + } + + if (sqlite3_step(stmt) != SQLITE_ROW) { + ErrPrint("Error: %s (has no record? - %s)\n", sqlite3_errmsg(handle), appid); + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + goto out; + } + + tmp = (char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + pkgid = strdup(tmp); + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + } + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return pkgid; +} + +static inline int update_lang_info(void) +{ + char *syslang; + UErrorCode err; + + syslang = vconf_get_str(VCONFKEY_LANGSET); + if (!syslang) { + ErrPrint("Failed to get vconf-lang\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + return -EFAULT; + } + + if (s_info.syslang && !strcmp(s_info.syslang, syslang)) { + DbgPrint("Syslang is not changed: %s\n", syslang); + free(syslang); + return 0; + } + + free(s_info.syslang); + s_info.syslang = syslang; + + err = U_ZERO_ERROR; + uloc_setDefault((const char *)s_info.syslang, &err); + if (!U_SUCCESS(err)) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to set default lang: %s\n", u_errorName(err)); + free(s_info.syslang); + s_info.syslang = NULL; + return -EFAULT; + } + + s_info.iso3lang = uloc_getISO3Language(uloc_getDefault()); + if (!s_info.iso3lang || !strlen(s_info.iso3lang)) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to get iso3lang\n"); + free(s_info.syslang); + s_info.syslang = NULL; + return -EFAULT; + } + + err = U_ZERO_ERROR; + s_info.country_len = uloc_getCountry(uloc_getDefault(), s_info.country, ULOC_COUNTRY_CAPACITY, &err); + if (!U_SUCCESS(err) || s_info.country_len <= 0) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to get locale: %s, %s, %d (%s)\n", u_errorName(err), s_info.iso3lang, s_info.country_len, s_info.country); + free(s_info.syslang); + s_info.syslang = NULL; + return -EFAULT; + } + + return 0; +} + +EAPI int widget_service_change_period(const char *pkgname, const char *id, double period) +{ + struct packet *packet; + struct packet *result; + unsigned int cmd = CMD_SERVICE_CHANGE_PERIOD; + char *uri; + int ret; + + if (!pkgname || !id || period < 0.0f) { + ErrPrint("Invalid argument\n"); + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + uri = util_id_to_uri(id); + if (!uri) { + return WIDGET_STATUS_ERROR_OUT_OF_MEMORY; + } + + packet = packet_create((const char *)&cmd, "ssd", pkgname, uri, period); + free(uri); + if (!packet) { + ErrPrint("Failed to create a packet for period changing\n"); + return WIDGET_STATUS_ERROR_FAULT; + } + + result = com_core_packet_oneshot_send(SERVICE_SOCKET, packet, DEFAULT_TIMEOUT); + packet_unref(packet); + + if (result) { + if (packet_get(result, "i", &ret) != 1) { + ErrPrint("Failed to parse a result packet\n"); + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + packet_unref(result); + } else { + ErrPrint("Failed to get result packet\n"); + ret = WIDGET_STATUS_ERROR_FAULT; + } + + return ret; +} + +EAPI int widget_service_get_instance_count(const char *pkgname, const char *cluster, const char *category) +{ + struct packet *packet; + struct packet *result; + unsigned int cmd = CMD_SERVICE_INST_CNT; + int ret; + + if (!pkgname) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + packet = packet_create((const char *)&cmd, "sssd", pkgname, cluster, category, util_timestamp()); + if (!packet) { + ErrPrint("Failed to create a packet for period changing\n"); + return WIDGET_STATUS_ERROR_FAULT; + } + + result = com_core_packet_oneshot_send(SERVICE_SOCKET, packet, DEFAULT_TIMEOUT); + packet_unref(packet); + + if (result) { + if (packet_get(result, "i", &ret) != 1) { + ErrPrint("Failed to parse a result packet\n"); + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + packet_unref(result); + } else { + ErrPrint("Failed to get result packet\n"); + ret = WIDGET_STATUS_ERROR_FAULT; + } + + return ret; +} + +EAPI int widget_service_trigger_update(const char *pkgname, const char *id, const char *cluster, const char *category, const char *content, int force) +{ + struct packet *packet; + struct packet *result; + unsigned int cmd = CMD_SERVICE_UPDATE; + char *uri; + int ret; + + if (!pkgname) { + ErrPrint("Invalid argument\n"); + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + if (!force && access("/tmp/.live.paused", R_OK) == 0) { + DbgPrint("Provider is paused\n"); + return WIDGET_STATUS_ERROR_CANCEL; + } + + if (id) { + uri = util_id_to_uri(id); + if (!uri) { + return WIDGET_STATUS_ERROR_OUT_OF_MEMORY; + } + } else { + uri = NULL; + } + + if (!cluster) { + cluster = "user,created"; + } + + if (!category) { + category = "default"; + } + + packet = packet_create((const char *)&cmd, "sssssi", pkgname, uri, cluster, category, content, force); + /*! + * \note + * "free" function accepts NULL + */ + free(uri); + if (!packet) { + ErrPrint("Failed to create a packet for service_update\n"); + return WIDGET_STATUS_ERROR_FAULT; + } + + result = com_core_packet_oneshot_send(SERVICE_SOCKET, packet, DEFAULT_TIMEOUT); + packet_unref(packet); + + if (result) { + if (packet_get(result, "i", &ret) != 1) { + ErrPrint("Failed to parse a result packet\n"); + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + packet_unref(result); + } else { + ErrPrint("Failed to get result packet\n"); + ret = WIDGET_STATUS_ERROR_FAULT; + } + + return ret; +} + +EAPI widget_pkglist_h widget_service_pkglist_create(const char *pkgid, widget_pkglist_h handle) +{ + int ret; + + if (handle) { + if (handle->type != PKGLIST_TYPE_WIDGET_LIST) { + ErrPrint("Invalid handle\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + if (pkgid) { + ErrPrint("pkgid should be NULL\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + sqlite3_reset(handle->stmt); + return handle; + } + + handle = calloc(1, sizeof(*handle)); + if (!handle) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + + handle->type = PKGLIST_TYPE_WIDGET_LIST; + + handle->handle = open_db(); + if (!handle->handle) { + free(handle); + return NULL; + } + + if (!pkgid) { + ret = sqlite3_prepare_v2(handle->handle, "SELECT appid, pkgid, prime FROM pkgmap", -1, &handle->stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle->handle)); + close_db(handle->handle); + free(handle); + return NULL; + } + } else { + ret = sqlite3_prepare_v2(handle->handle, "SELECT appid, pkgid, prime FROM pkgmap WHERE appid = ?", -1, &handle->stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle->handle)); + close_db(handle->handle); + free(handle); + return NULL; + } + + ret = sqlite3_bind_text(handle->stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle->handle)); + sqlite3_finalize(handle->stmt); + close_db(handle->handle); + free(handle); + return NULL; + } + } + + return handle; +} + +EAPI int widget_service_get_pkglist_item(widget_pkglist_h handle, char **appid, char **pkgname, int *is_prime) +{ + const char *tmp; + char *_appid = NULL; + char *_pkgname = NULL; + + if (!handle || handle->type != PKGLIST_TYPE_WIDGET_LIST) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + if (sqlite3_step(handle->stmt) != SQLITE_ROW) { + return WIDGET_STATUS_ERROR_NOT_EXIST; + } + + if (appid) { + tmp = (const char *)sqlite3_column_text(handle->stmt, 0); + if (tmp && strlen(tmp)) { + _appid = strdup(tmp); + if (!_appid) { + ErrPrint("Heap: %s\n", strerror(errno)); + return WIDGET_STATUS_ERROR_OUT_OF_MEMORY; + } + } + } + + if (pkgname) { + tmp = (const char *)sqlite3_column_text(handle->stmt, 1); + if (tmp && strlen(tmp)) { + _pkgname = strdup(tmp); + if (!_pkgname) { + ErrPrint("Heap: %s\n", strerror(errno)); + free(_appid); + return WIDGET_STATUS_ERROR_OUT_OF_MEMORY; + } + } + } + + if (is_prime) { + *is_prime = sqlite3_column_int(handle->stmt, 2); + } + + if (appid) { + *appid = _appid; + } + + if (pkgname) { + *pkgname = _pkgname; + } + + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI int widget_service_pkglist_destroy(widget_pkglist_h handle) +{ + if (!handle || handle->type != PKGLIST_TYPE_WIDGET_LIST) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle->type = PKGLIST_TYPE_UNKNOWN; + sqlite3_reset(handle->stmt); + sqlite3_finalize(handle->stmt); + close_db(handle->handle); + free(handle); + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI int widget_service_get_pkglist(int (*cb)(const char *appid, const char *pkgname, int is_prime, void *data), void *data) +{ + int ret; + sqlite3_stmt *stmt; + char *appid; + char *pkgid; + int is_prime; + sqlite3 *handle; + + if (!cb) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT appid, pkgid, prime FROM pkgmap", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + appid = (char *)sqlite3_column_text(stmt, 0); + if (!appid || !strlen(appid)) { + ErrPrint("APPID is not valid\n"); + continue; + } + + pkgid = (char *)sqlite3_column_text(stmt, 1); + if (!pkgid || !strlen(pkgid)) { + ErrPrint("pkgid is not valid\n"); + continue; + } + + is_prime = sqlite3_column_int(stmt, 2); + + ret++; + + if (cb(appid, pkgid, is_prime, data) < 0) { + DbgPrint("Callback stopped package crawling\n"); + break; + } + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + +out: + close_db(handle); + return ret; +} + +EAPI int widget_service_get_pkglist_by_pkgid(const char *pkgid, int (*cb)(const char *widgetid, int is_prime, void *data), void *data) +{ + int ret; + sqlite3_stmt *stmt; + const char *widgetid; + int is_prime; + sqlite3 *handle; + + if (!cb || !pkgid) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgid, prime FROM pkgmap WHERE appid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + widgetid = (const char *)sqlite3_column_text(stmt, 0); + if (!widgetid || !strlen(widgetid)) { + ErrPrint("WIDGETID is not valid\n"); + continue; + } + + is_prime = sqlite3_column_int(stmt, 1); + + ret++; + + if (cb(widgetid, is_prime, data) < 0) { + DbgPrint("Callback stopped package crawling\n"); + break; + } + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + +out: + close_db(handle); + return ret; +} + +EAPI int widget_service_get_pkglist_by_category(const char *category, int (*cb)(const char *widgetid, void *data), void *data) +{ + int ret; + sqlite3_stmt *stmt; + const char *widgetid; + sqlite3 *handle; + + if (!cb || !category) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgid FROM pkgmap WHERE category = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, category, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + widgetid = (const char *)sqlite3_column_text(stmt, 0); + if (!widgetid || !strlen(widgetid)) { + ErrPrint("WIDGETID is not valid\n"); + continue; + } + + ret++; + + if (cb(widgetid, data) < 0) { + DbgPrint("Callback stopped package crawling\n"); + break; + } + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + +out: + close_db(handle); + return ret; +} + +EAPI int widget_service_get_applist(const char *widgetid, void (*cb)(const char *widgetid, const char *appid, void *data), void *data) +{ + sqlite3_stmt *stmt; + const char *tmp; + char *pkgid; + sqlite3 *handle; + int ret; + + if (!widgetid || !cb) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT appid FROM pkgmap WHERE (pkgid = ?) or (appid = ?)", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + if (sqlite3_step(stmt) != SQLITE_ROW) { + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + ErrPrint("Invalid package name (%s)\n", widgetid); + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + pkgid = strdup(tmp); + if (!pkgid) { + ErrPrint("Error: %s\n", strerror(errno)); + ret = WIDGET_STATUS_ERROR_OUT_OF_MEMORY; + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + + ret = pkgmgr_get_applist(pkgid, widgetid, cb, data); + free(pkgid); + + switch (ret) { + case PMINFO_R_EINVAL: + ret = WIDGET_STATUS_ERROR_INVALID_PARAMETER; + break; + case PMINFO_R_OK: + ret = WIDGET_STATUS_ERROR_NONE; + break; + case PMINFO_R_ERROR: + default: + ret = WIDGET_STATUS_ERROR_FAULT; + break; + } + +out: + close_db(handle); + return ret; +} + +EAPI char *widget_service_mainappid(const char *widgetid) +{ + sqlite3_stmt *stmt; + const char *tmp; + const char *pkgid; + sqlite3 *handle; + char *ret = NULL; + + if (!widgetid) { + return NULL; + } + + handle = open_db(); + if (!handle) { + return NULL; + } + + if (sqlite3_prepare_v2(handle, "SELECT appid, uiapp FROM pkgmap WHERE (pkgid = ?) or (appid = ? and prime = 1)", -1, &stmt, NULL) != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + if (sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT) != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + if (sqlite3_bind_text(stmt, 2, widgetid, -1, SQLITE_TRANSIENT) != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + if (sqlite3_step(stmt) != SQLITE_ROW) { + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + ErrPrint("Invalid package name (%s)\n", widgetid); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + pkgid = (const char *)sqlite3_column_text(stmt, 1); + if (!pkgid || !strlen(pkgid)) { + /* + * This record has no uiapp. + * Try to find the main ui-app id. + */ + ret = pkgmgr_get_mainapp(tmp); + } else { + ret = strdup(pkgid); + if (!ret) { + ErrPrint("Error: %s\n", strerror(errno)); + } + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + +out: + close_db(handle); + return ret; +} + +EAPI int widget_service_get_supported_size_types(const char *pkgid, int *cnt, int *types) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int size; + int ret; + + if (!types || !cnt || !pkgid) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT size_type FROM box_size WHERE pkgid = ? ORDER BY size_type ASC", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + if (*cnt > WIDGET_NR_OF_SIZE_LIST) { + *cnt = WIDGET_NR_OF_SIZE_LIST; + } + + ret = 0; + while (sqlite3_step(stmt) == SQLITE_ROW && ret < *cnt) { + size = sqlite3_column_int(stmt, 0); + types[ret] = size; + ret++; + } + + *cnt = ret; + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = WIDGET_STATUS_ERROR_NONE; +out: + close_db(handle); + return ret; +} + +EAPI char *widget_service_content(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *content = NULL; + int ret; + + handle = open_db(); + if (!handle) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT content FROM client WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + content = strdup(tmp); + if (!content) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + } + } else if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return content; +} + +EAPI char *widget_service_setup_appid(const char *widgetid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *appid; + + if (!widgetid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT setup FROM client WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return NULL; + } + + appid = NULL; + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + goto out; + } + + appid = strdup(tmp); + if (!appid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Error: %s\n", strerror(errno)); + } + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return appid; +} + +EAPI int widget_service_nodisplay(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return 0; + } + + handle = open_db(); + if (!handle) { + return 0; + } + + ret = sqlite3_prepare_v2(handle, "SELECT nodisplay FROM client WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return 0; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 0; + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + ret = !!sqlite3_column_int(stmt, 0); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + ret = 0; + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return ret; +} + +EAPI int widget_service_need_frame(const char *pkgid, int size_type) +{ + char *widgetid; + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + + handle = open_db(); + if (!handle) { + ErrPrint("Unable to open a DB\n"); + return 0; + } + + ret = sqlite3_prepare_v2(handle, "SELECT need_frame FROM box_size WHERE pkgid = ? AND size_type = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return 0; + } + + /*! + */ + widgetid = widget_service_widget_id(pkgid); + if (!widgetid) { + ErrPrint("Invalid appid (%s)\n", pkgid); + ret = 0; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + free(widgetid); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 0; + goto out; + } + + ret = sqlite3_bind_int(stmt, 2, size_type); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 0; + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + ret = !!sqlite3_column_int(stmt, 0); + } else { + ret = 0; + ErrPrint("There is no such result\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return ret; +} + +EAPI int widget_service_touch_effect(const char *pkgid, int size_type) +{ + char *widgetid; + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + + handle = open_db(); + if (!handle) { + ErrPrint("Unable to open a DB\n"); + return 1; + } + + ret = sqlite3_prepare_v2(handle, "SELECT touch_effect FROM box_size WHERE pkgid = ? AND size_type = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + close_db(handle); + return 1; + } + + /** + * @note + * This function will validate the "pkgid" + * call the exported API in the exported API is not recomended + * but... I used. + */ + widgetid = widget_service_widget_id(pkgid); + if (!widgetid) { + ErrPrint("Invalid appid (%s)\n", pkgid); + ret = 1; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + free(widgetid); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 1; + goto out; + } + + ret = sqlite3_bind_int(stmt, 2, size_type); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 1; + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + ret = !!sqlite3_column_int(stmt, 0); + } else { + ret = 1; /**< Default true: In this case the DB is corrupted. */ + ErrPrint("There is no result\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return ret; +} + +EAPI int widget_service_mouse_event(const char *pkgid, int size_type) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *widgetid; + int ret; + + handle = open_db(); + if (!handle) { + return 0; + } + + ret = sqlite3_prepare_v2(handle, "SELECT mouse_event FROM box_size WHERE pkgid = ? AND size_type = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + close_db(handle); + return 0; + } + + widgetid = widget_service_widget_id(pkgid); + if (!widgetid) { + ErrPrint("Failed to get widgetid: %s\n", pkgid); + ret = 0; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + free(widgetid); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 0; + goto out; + } + + ret = sqlite3_bind_int(stmt, 2, size_type); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = 0; + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + ret = !!sqlite3_column_int(stmt, 0); + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + } else { + ret = 0; /**< Default is false, In this case the DB is corrupted */ + ErrPrint("There is no result.\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return ret; +} + +static char *convert_to_abspath(const char *appid, const char *tmp, const char *mid_path, int *tmp_len) +{ + pkgmgrinfo_pkginfo_h handle; + const char *path; + int abspath_len; + char *abspath = NULL; + int ret; + + if (!tmp || tmp[0] == '/' || !appid) { + return NULL; + } + + ret = pkgmgrinfo_pkginfo_get_pkginfo(appid, &handle); + if (ret != PMINFO_R_OK) { + ErrPrint("Unable to get package info for %s\n", appid); + return NULL; + } + + ret = pkgmgrinfo_pkginfo_get_root_path(handle, (char **)&path); + if (ret != PMINFO_R_OK) { + ErrPrint("Unable to get path for %s\n", appid); + goto out; + } + + abspath_len = strlen(tmp) + strlen(path) + strlen(mid_path) + 1; + abspath = malloc(abspath_len); + if (!abspath) { + ErrPrint("malloc: %s\n", strerror(errno)); + goto out; + } + + if (snprintf(abspath, abspath_len, "%s%s%s", path, mid_path, tmp) < 0) { + ErrPrint("snprintf: %s\n", strerror(errno)); + free(abspath); + abspath = NULL; + goto out; + } + + if (tmp_len) { + *tmp_len = abspath_len; + } + + DbgPrint("Converted path: %s (%d)\n", abspath, abspath_len); +out: + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return abspath; +} + +static char *get_appid(sqlite3 *handle, const char *pkgid) +{ + sqlite3_stmt *stmt; + int ret; + char *appid = NULL; + + ret = sqlite3_prepare_v2(handle, "SELECT appid FROM pkgmap WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + appid = strdup(tmp); + if (!appid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + } + } else if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + return appid; +} + +EAPI char *widget_service_preview(const char *pkgid, int size_type) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *preview = NULL; + const char *tmp; + char *appid; + int tmp_len; + int buf_len; + register int i; + int printed; + char *abspath; + + handle = open_db(); + if (!handle) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT preview FROM box_size WHERE pkgid = ? AND size_type = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, %s\n", sqlite3_errmsg(handle), pkgid); + close_db(handle); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, %s\n", sqlite3_errmsg(handle), pkgid); + goto out; + } + + ret = sqlite3_bind_int(stmt, 2, size_type); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, %s\n", sqlite3_errmsg(handle), pkgid); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("Error: %s, %s\n", sqlite3_errmsg(handle), pkgid); + goto out; + } + + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !(tmp_len = strlen(tmp))) { + ErrPrint("Failed to get data (%s)\n", pkgid); + goto out; + } + + appid = get_appid(handle, pkgid); + abspath = convert_to_abspath(appid, tmp, RESOURCE_PATH, &tmp_len); + free(appid); + if (!abspath) { + abspath = strdup(tmp); + if (!abspath) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("strdup: %s\n", strerror(errno)); + goto out; + } + } + + if (update_lang_info() != 0) { + preview = abspath; + if (!preview) { + ErrPrint("Heap: %s\n", strerror(errno)); + } + goto out; + } + + buf_len = tmp_len + strlen(s_info.iso3lang) + s_info.country_len + 3; /* '/' '-' '/' */ + preview = malloc(buf_len + 1); + if (!preview) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + free(abspath); + goto out; + } + + for (i = tmp_len; i >= 0 && abspath[i] != '/'; i--); + i++; /* Skip '/' */ + + strncpy(preview, abspath, i); + printed = snprintf(preview + i, buf_len - i, "%s-%s/%s", s_info.iso3lang, s_info.country, abspath + i); + if (preview[i + printed] != '\0') { + ErrPrint("Path is truncated\n"); + preview[i + printed] = '\0'; + } + + if (access(preview, R_OK) != 0) { + DbgPrint("Access failed: %s, %s\n", preview, strerror(errno)); + free(preview); + + preview = abspath; + } else { + free(abspath); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return preview; +} + +EAPI char *widget_service_i18n_icon(const char *pkgid, const char *lang) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *language; + char *icon = NULL; + char *appid; + int ret; + char *ret_icon; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + if (lang) { + language = strdup(lang); + if (!language) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + return NULL; + } + } else { + language = cur_locale(); + if (!language) { + return NULL; + } + } + + handle = open_db(); + if (!handle) { + free(language); + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT icon FROM i18n WHERE pkgid = ? AND lang = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + free(language); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, language, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + icon = get_default_icon(pkgid); + } else { + icon = strdup(tmp); + if (!icon) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + } else { + icon = get_default_icon(pkgid); + } + + appid = get_appid(handle, pkgid); + ret_icon = convert_to_abspath(appid, icon, RESOURCE_PATH, NULL); + free(appid); + if (ret_icon) { + free(icon); + icon = ret_icon; + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + free(language); + return icon; +} + +EAPI char *widget_service_i18n_name(const char *pkgid, const char *lang) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + char *language; + char *name = NULL; + int ret; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + if (lang) { + language = strdup(lang); + if (!language) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Error: %s\n", strerror(errno)); + return NULL; + } + } else { + language = cur_locale(); + if (!language) { + return NULL; + } + } + + handle = open_db(); + if (!handle) { + free(language); + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT name FROM i18n WHERE pkgid = ? AND lang = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + free(language); + return NULL; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, language, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) { + const char *tmp; + tmp = (const char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + name = get_default_name(pkgid); + } else { + name = strdup(tmp); + if (!name) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + } else { + name = get_default_name(pkgid); + } + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + free(language); + return name; +} + +EAPI int widget_service_get_supported_sizes(const char *pkgid, int *cnt, int *w, int *h) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int size; + int ret; + + if (!w || !h || !cnt || !pkgid) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT size_type FROM box_size WHERE pkgid = ? ORDER BY size_type ASC", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + if (*cnt > WIDGET_NR_OF_SIZE_LIST) { + *cnt = WIDGET_NR_OF_SIZE_LIST; + } + + ret = 0; + while (sqlite3_step(stmt) == SQLITE_ROW && ret < *cnt) { + size = sqlite3_column_int(stmt, 0); + ret += (convert_size_from_type((widget_size_type_e)size, w + ret, h + ret) == 0); + } + + *cnt = ret; + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + ret = 0; +out: + close_db(handle); + return ret; +} + +EAPI char *widget_service_abi(const char *widgetid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *abi; + char *tmp; + + if (!widgetid) { + ErrPrint("Invalid argument\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + abi = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT abi FROM provider WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + + ErrPrint("Error: %s (%d)\n", sqlite3_errmsg(handle), ret); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + tmp = (char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + ErrPrint("Invalid abi: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + abi = strdup(tmp); + if (!abi) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("strdup: %s\n", strerror(errno)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + DbgPrint("abi: %s\n", abi); + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return abi; +} + +EAPI char *widget_service_widget_id_by_libexec(const char *libexec) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *pkgid; + char *tmp; + char *_libexec; + int len; + + if (!libexec) { + ErrPrint("Invalid argument\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + pkgid = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + len = strlen(libexec) + 3; + + _libexec = malloc(len); + if (!_libexec) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + close_db(handle); + return NULL; + } + + snprintf(_libexec, len - 1, "%%%s", libexec); + + ret = sqlite3_prepare_v2(handle, "SELECT pkgid FROM provider WHERE libexec like ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, _libexec, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("No records (%s) for (%s)\n", sqlite3_errmsg(handle), libexec); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + ErrPrint("Invalid pkgid: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + pkgid = strdup(tmp); + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + + DbgPrint("pkgid: %s\n", pkgid); + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + free(_libexec); + return pkgid; +} + +EAPI char *widget_service_libexec(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *libexec; + char *appid; + char *path; + + if (!pkgid) { + ErrPrint("Invalid argument\n"); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + libexec = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgmap.appid, provider.libexec FROM pkgmap, provider WHERE pkgmap.pkgid = ? AND provider.pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + appid = (char *)sqlite3_column_text(stmt, 0); + if (!appid || !strlen(appid)) { + ErrPrint("Invalid appid: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + path = (char *)sqlite3_column_text(stmt, 1); + if (!path || !strlen(path)) { + ErrPrint("Invalid libexec: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + libexec = convert_to_abspath(appid, path, LIBEXEC_PATH, NULL); + if (!libexec) { + libexec = strdup(path); + if (!libexec) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + + DbgPrint("libexec: %s\n", libexec); + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return libexec; +} + +EAPI char *widget_service_widget_id(const char *appid) +{ + char *widget_pkgname; + pkgmgrinfo_appinfo_h handle; + int ret; + char *new_appid; + + if (!appid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + widget_pkgname = get_widget_pkgname_by_appid(appid); + if (widget_pkgname) { + return widget_pkgname; + } + + /*! + * \note + * Try to get the package id using given appid + */ + ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle); + if (ret != PKGMGR_R_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to get appinfo\n"); + return NULL; + } + + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &new_appid); + if (ret != PKGMGR_R_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + ErrPrint("Failed to get pkgname for (%s)\n", appid); + return NULL; + } + + widget_pkgname = get_widget_pkgname_by_appid(new_appid); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + + if (!widget_pkgname) { + widget_pkgname = strdup(appid); + if (!widget_pkgname) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + } + + return widget_pkgname; +} + +EAPI char *widget_service_package_id(const char *pkgname) +{ + sqlite3_stmt *stmt; + char *appid; + char *tmp; + sqlite3 *handle; + int is_prime __attribute__((__unused__)); + int ret; + + if (!pkgname) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + appid = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT appid, prime FROM pkgmap WHERE pkgid = ? OR appid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, pkgname, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + pkgmgrinfo_appinfo_h pkg_handle; + char *new_appid; + + if (ret == SQLITE_DONE) { + ErrPrint("No records: %s\n", sqlite3_errmsg(handle)); + } else { + ErrPrint("Failed to get record: %s\n", sqlite3_errmsg(handle)); + } + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + + ret = pkgmgrinfo_appinfo_get_appinfo(pkgname, &pkg_handle); + if (ret != PKGMGR_R_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to get appinfo: %s\n", pkgname); + goto out; + } + + ret = pkgmgrinfo_appinfo_get_pkgid(pkg_handle, &new_appid); + if (ret != PKGMGR_R_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to get pkgname for (%s)\n", appid); + pkgmgrinfo_appinfo_destroy_appinfo(pkg_handle); + goto out; + } + + appid = strdup(new_appid); + if (!appid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + + pkgmgrinfo_appinfo_destroy_appinfo(pkg_handle); + goto out; + } + + tmp = (char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + ErrPrint("APPID is NIL\n"); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + appid = strdup(tmp); + if (!appid) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + is_prime = sqlite3_column_int(stmt, 1); + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return appid; +} + +EAPI char *widget_service_provider_name(const char *widgetid) +{ + char *ret; + int stage = 0; + int seq = 0; + int idx = 0; + char *str = WIDGET_ID_PREFIX; + + if (!widgetid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + while (str[idx] && widgetid[idx] && widgetid[idx] == str[idx]) { + idx++; + if (seq < 2 && widgetid[idx] == '.') { + stage = idx; + seq++; + } + } + + if (!str[idx] && widgetid[idx]) { + ret = strdup(widgetid); + /* Inhouse */ + if (!ret) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + return ret; + } else if (seq < 2) { + while (seq < 2) { + if (widgetid[idx] == '.') { + seq++; + } else if (!widgetid[idx]) { + ErrPrint("Invalid widgetid: %s\n", widgetid); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + idx++; + } + + stage = idx; + } else { + stage++; + } + + ret = strdup(widgetid + stage); + if (!ret) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Error: %s\n", strerror(errno)); + return NULL; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + return ret; +} + +EAPI int widget_service_is_enabled(const char *widgetid) +{ + return 1; + /* + ail_appinfo_h ai; + char *pkgname; + bool enabled; + int ret; + + pkgname = widget_service_package_id(widgetid); + if (!pkgname) + return 0; + + ret = ail_get_appinfo(pkgname, &ai); + if (ret != AIL_ERROR_OK) { + free(pkgname); + return 0; + } + + if (ail_appinfo_get_bool(ai, AIL_PROP_X_SLP_ENABLED_BOOL, &enabled) != AIL_ERROR_OK) + enabled = false; + + ail_destroy_appinfo(ai); + free(pkgname); + return enabled == true; + */ +} + +EAPI int widget_service_is_primary(const char *widgetid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret = 0; + + if (!widgetid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return 0; + } + + handle = open_db(); + if (!handle) { + return 0; + } + + ret = sqlite3_prepare_v2(handle, "SELECT prime FROM pkgmap WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + close_db(handle); + return 0; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_column_int(stmt, 0); + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + +out: + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + close_db(handle); + return ret; +} + +EAPI char *widget_service_category(const char *widgetid) +{ + sqlite3_stmt *stmt; + char *category = NULL; + char *tmp; + sqlite3 *handle; + int ret; + + if (!widgetid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + category = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT category FROM pkgmap WHERE pkgid = ? OR appid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, widgetid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + ErrPrint("Has no record?: %s\n", sqlite3_errmsg(handle)); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Failed to retrieve record set: %s\n", sqlite3_errmsg(handle)); + } + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (char *)sqlite3_column_text(stmt, 0); + if (!tmp || !strlen(tmp)) { + ErrPrint("APPID is NIL\n"); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + category = strdup(tmp); + if (!category) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return category; +} + +EAPI char *widget_service_widget_script_path(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *path; + char *appid; + char *widget_src; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + path = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgmap.appid, provider.box_src FROM provider, pkgmap WHERE pkgmap.pkgid = ? AND provider.pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, pkgid(%s), ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, pkgid(%s), ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s, pkgid(%s), ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("Error: %s, pkgid(%s), ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + appid = (char *)sqlite3_column_text(stmt, 0); + if (!appid || !strlen(appid)) { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + ErrPrint("Invalid appid : %s, pkgid(%s)\n", sqlite3_errmsg(handle), pkgid); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_src = (char *)sqlite3_column_text(stmt, 1); + if (!widget_src || !strlen(widget_src)) { + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + ErrPrint("No records for widget src : %s, pkgid(%s), appid(%s)\n", sqlite3_errmsg(handle), pkgid, appid); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + path = convert_to_abspath(appid, widget_src, RESOURCE_PATH, NULL); + if (!path) { + path = strdup(widget_src); + if (!path) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + } + + DbgPrint("WIDGET Src: %s\n", path); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return path; +} + +EAPI char *widget_service_widget_script_group(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *group; + char *tmp; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + group = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT box_group FROM provider WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + group = strdup(tmp); + if (!group) { + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + ErrPrint("Heap: %s\n", strerror(errno)); + } + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return group; +} + +EAPI char *widget_service_gbar_script_path(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *path; + char *gbar_src; + const char *appid; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + path = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pkgmap.appid, provider.pd_src FROM provider, pkgmap WHERE provider.pkgid = ? AND pkgmap.pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s pkgid(%s) ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s pkgid(%s) ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s pkgid(%s) ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + if (ret == SQLITE_DONE) { + widget_set_last_status(WIDGET_STATUS_ERROR_NOT_EXIST); + } else { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + } + ErrPrint("Error: %s pkgid(%s) ret(%d)\n", sqlite3_errmsg(handle), pkgid, ret); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + + appid = (char *)sqlite3_column_text(stmt, 0); + if (!appid || !strlen(appid)) { + ErrPrint("Error: %s pkgid(%s)\n", sqlite3_errmsg(handle), pkgid); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + gbar_src = (char *)sqlite3_column_text(stmt, 1); + if (!gbar_src || !strlen(gbar_src)) { + ErrPrint("Error: %s pkgid(%s) appid(%s)\n", sqlite3_errmsg(handle), pkgid, appid); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + path = convert_to_abspath(appid, gbar_src, RESOURCE_PATH, NULL); + if (!path) { + path = strdup(gbar_src); + if (!path) { + ErrPrint("Heap: %s\n", strerror(errno)); + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + } + + DbgPrint("GBAR Src: %s\n", path); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return path; +} + +EAPI char *widget_service_gbar_script_group(const char *pkgid) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + int ret; + char *group; + char *tmp; + + if (!pkgid) { + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + group = NULL; + handle = open_db(); + if (!handle) { + return NULL; + } + + ret = sqlite3_prepare_v2(handle, "SELECT pd_group FROM provider WHERE pkgid = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + goto out; + } + + ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT); + if (ret != SQLITE_OK) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_finalize(stmt); + goto out; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) { + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + goto out; + } + + widget_set_last_status(WIDGET_STATUS_ERROR_NONE); + tmp = (char *)sqlite3_column_text(stmt, 0); + if (tmp && strlen(tmp)) { + group = strdup(tmp); + if (!group) { + ErrPrint("Heap: %s\n", strerror(errno)); + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + } + } + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return group; +} + +EAPI int widget_service_enumerate_cluster_list(int (*cb)(const char *cluster, void *data), void *data) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + const char *cluster; + int cnt; + int ret; + + if (!cb) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + cnt = 0; + ret = sqlite3_prepare_v2(handle, "SELECT DISTINCT cluster FROM groupinfo", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + cnt = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + cluster = (const char *)sqlite3_column_text(stmt, 0); + if (!cluster || !strlen(cluster)) { + continue; + } + + if (cb(cluster, data) < 0) { + break; + } + + cnt++; + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return cnt; +} + +EAPI int widget_service_enumerate_category_list(const char *cluster, int (*cb)(const char *cluster, const char *category, void *data), void *data) +{ + sqlite3_stmt *stmt; + sqlite3 *handle; + const char *category; + int cnt; + int ret; + + if (!cluster || !cb) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + handle = open_db(); + if (!handle) { + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + ret = sqlite3_prepare_v2(handle, "SELECT DISTINCT category FROM groupinfo WHERE cluster = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + ErrPrint("Error: %s\n", sqlite3_errmsg(handle)); + cnt = WIDGET_STATUS_ERROR_IO_ERROR; + goto out; + } + + cnt = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + category = (const char *)sqlite3_column_text(stmt, 0); + if (!category || !strlen(category)) { + continue; + } + + if (cb(cluster, category, data) < 0) { + break; + } + + cnt++; + } + + sqlite3_reset(stmt); + sqlite3_finalize(stmt); +out: + close_db(handle); + return cnt; +} + +EAPI int widget_service_init(void) +{ + if (s_info.handle) { + DbgPrint("Already initialized\n"); + s_info.init_count++; + return WIDGET_STATUS_ERROR_NONE; + } + + s_info.handle = open_db(); + if (s_info.handle) { + s_info.init_count++; + return WIDGET_STATUS_ERROR_NONE; + } + + return WIDGET_STATUS_ERROR_IO_ERROR; +} + +EAPI int widget_service_fini(void) +{ + if (!s_info.handle || s_info.init_count <= 0) { + ErrPrint("Service is not initialized\n"); + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + s_info.init_count--; + if (s_info.init_count > 0) { + DbgPrint("Init count %d\n", s_info.init_count); + return WIDGET_STATUS_ERROR_NONE; + } + + db_util_close(s_info.handle); + s_info.handle = NULL; + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI int widget_service_get_size(widget_size_type_e type, int *width, int *height) +{ + int _width; + int _height; + + if (!width) { + width = &_width; + } + + if (!height) { + height = &_height; + } + + return convert_size_from_type(type, width, height); +} + +EAPI widget_size_type_e widget_service_size_type(int width, int height) +{ + int idx; + + if (util_update_resolution(&s_info, SIZE_LIST) < 0) { + ErrPrint("Failed to update the size list\n"); + } + + for (idx = 0; idx < WIDGET_NR_OF_SIZE_LIST; idx++) { + if (SIZE_LIST[idx].w == width && SIZE_LIST[idx].h == height) { + break; + } + } + + switch (idx) { + case 0: + return WIDGET_SIZE_TYPE_1x1; + case 1: + return WIDGET_SIZE_TYPE_2x1; + case 2: + return WIDGET_SIZE_TYPE_2x2; + case 3: + return WIDGET_SIZE_TYPE_4x1; + case 4: + return WIDGET_SIZE_TYPE_4x2; + case 5: + return WIDGET_SIZE_TYPE_4x3; + case 6: + return WIDGET_SIZE_TYPE_4x4; + case 7: + return WIDGET_SIZE_TYPE_4x5; + case 8: + return WIDGET_SIZE_TYPE_4x6; + case 9: + return WIDGET_SIZE_TYPE_EASY_1x1; + case 10: + return WIDGET_SIZE_TYPE_EASY_3x1; + case 11: + return WIDGET_SIZE_TYPE_EASY_3x3; + case 12: + return WIDGET_SIZE_TYPE_0x0; + default: + break; + } + + return WIDGET_SIZE_TYPE_UNKNOWN; +} + +EAPI void widget_set_last_status(widget_status_e status) +{ + s_info.last_status = status; +} + +EAPI widget_status_e widget_last_status(void) +{ + return s_info.last_status; +} + +EAPI widget_lock_info_t widget_service_create_lock(const char *uri, widget_target_type_e type, widget_lock_type_e option) +{ + widget_lock_info_t info; + int len; + int flags; + + info = malloc(sizeof(*info)); + if (!info) { + ErrPrint("malloc: %s\n", strerror(errno)); + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + return NULL; + } + + len = strlen(uri); + info->filename = malloc(len + 20); + if (!info->filename) { + ErrPrint("malloc: %s\n", strerror(errno)); + free(info); + widget_set_last_status(WIDGET_STATUS_ERROR_OUT_OF_MEMORY); + return NULL; + } + + len = snprintf(info->filename, len + 20, "%s.%s.lck", util_uri_to_path(uri), type == WIDGET_TYPE_GBAR ? "gbar" : "widget"); + if (len < 0) { + ErrPrint("snprintf: %s\n", strerror(errno)); + free(info->filename); + free(info); + widget_set_last_status(WIDGET_STATUS_ERROR_FAULT); + return NULL; + } + + if (option == WIDGET_LOCK_WRITE) { + flags = O_WRONLY | O_CREAT; + } else if (option == WIDGET_LOCK_READ) { + flags = O_RDONLY; + } else { + ErrPrint("Invalid paramter\n"); + free(info->filename); + free(info); + widget_set_last_status(WIDGET_STATUS_ERROR_INVALID_PARAMETER); + return NULL; + } + + info->type = option; + + info->fd = open(info->filename, flags, 0644); + if (info->fd < 0) { + ErrPrint("open: %s\n", strerror(errno)); + free(info->filename); + free(info); + widget_set_last_status(WIDGET_STATUS_ERROR_IO_ERROR); + return NULL; + } + + return info; +} + +EAPI int widget_service_destroy_lock(widget_lock_info_t info) +{ + if (!info || !info->filename || info->fd < 0) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + if (close(info->fd) < 0) { + ErrPrint("close: %s\n", strerror(errno)); + return WIDGET_STATUS_ERROR_IO_ERROR; + } + + if (unlink(info->filename) < 0) { + ErrPrint("unlink: %s\n", strerror(errno)); + } + + free(info->filename); + free(info); + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI int widget_service_acquire_lock(widget_lock_info_t info) +{ + struct flock flock; + int ret; + + if (!info || info->fd < 0) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + if (info->type == WIDGET_LOCK_WRITE) { + flock.l_type = F_WRLCK; + } else if (info->type == WIDGET_LOCK_READ) { + flock.l_type = F_RDLCK; + } + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = getpid(); + + do { + ret = fcntl(info->fd, F_SETLKW, &flock); + if (ret < 0) { + ret = errno; + ErrPrint("fcntl: %s\n", strerror(errno)); + } + } while (ret == EINTR); + + return WIDGET_STATUS_ERROR_NONE; +} + +EAPI int widget_service_release_lock(widget_lock_info_t info) +{ + struct flock flock; + int ret; + + if (info->fd < 0) { + return WIDGET_STATUS_ERROR_INVALID_PARAMETER; + } + + flock.l_type = F_UNLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = getpid(); + + do { + ret = fcntl(info->fd, F_SETLKW, &flock); + if (ret < 0) { + ret = errno; + ErrPrint("fcntl: %s\n", strerror(errno)); + } + } while (ret == EINTR); + + return WIDGET_STATUS_ERROR_NONE; +} + +/* End of a file */ |