/* * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include "engine.h" #include "bus.h" #include "defs.h" #include "dbg.h" #define SECTION_USER "user" #define SECTION_UBAR_ITEMS "ubar.items" #define SECTION_ITEMS "items" #define ATTR_NAME "name" #define ATTR_THUMB_BG "thumb_bg" #define ATTR_THUMB "thumb" #define ATTR_AGE "age" #define ATTR_PASSWORD "password" #define ATTR_AUTHORITY "authority" #define ATTR_ICON "icon" #define ATTR_ICON_FOCUS "icon_focus" #define ATTR_BUS_NAME "bus_name" #define ATTR_OBJECT_PATH "object_path" #define ATTR_APP "app" #define ATTR_COLOR "color" #define ATTR_RED "red" #define ATTR_GREEN "green" #define ATTR_BLUE "blue" #define ATTR_CONTENTS "contents" #define ATTR_NOCTNT_TITLE "noctnt_title" #define ATTR_NOCTNT_DESC "noctnt_desc" #define ATTR_CONTENT_COLUMN "content_column" #define ATTR_TITLE "title" #define ATTR_PACKAGE "package" #define ATTR_CATEGORY "category" #define ATTR_IN "in" #define SIZE_32 32 #define SIZE_4 4 #define MULTIPLIER 1024 #define PACKAGE_LIVE_TV "org.tizen.live-tv-ref" struct engine { struct { char *name; char *thumb_bg; char *thumb; } user; struct bus *bus; Eina_List *client_buslist; Eina_List *hbar_its; Eina_List *ubar_its; Eina_List *pin_its; Eina_Bool is_full; void (*update_cb)(void *data, bool focus); void *update_cb_data; }; struct engine_bar_item { struct engine *eng; char *icon; char *icon_focus; char *name; char *svcid; char *bus_name; char *object_path; char *app; char *noctnt_title; char *noctnt_desc; int r; int g; int b; int content_column; Eina_List *dbar_its; int ctnt_id; char *in; char *args; char *pinid; enum app_content_favorite_type type; Eina_Bool is_pinned; void (*update_cb)(struct engine_bar_item *it, void *data); void *update_cb_data; }; struct engine_dbar_item_content { enum engine_dbar_content_type type; char *subtitle; char *description; char *detail; char *thumbnail; char *icon; }; struct engine_ubar_item { struct engine *eng; char *name; char *thumb_bg; char *thumb; char *password; int age; int authority; bool visible; }; struct engine_dbar_item { int ctnt_id; struct engine_bar_item *hit; enum engine_dbar_item_style style; char *name; enum bus_data_action_op action; char *actor; char *args; Eina_List *ctnts; }; static int _is_member_exist(JsonReader *reader, const char *member_name) { gchar **members; int i, cnt; int r; cnt = json_reader_count_members(reader); if (cnt == -1) { _ERR("No member"); return 0; } members = json_reader_list_members(reader); if (!members) { _ERR("No member"); return 0; } r = 0; for (i = 0; i < cnt; i++) { if (!strcmp(member_name, members[i])) { r = 1; break; } } g_strfreev(members); return r; } static inline const char *_read_attr(JsonReader *reader, const char *attr) { const char *val; if (!reader || !attr) return NULL; if (!_is_member_exist(reader, attr)) { _ERR("There is no %s attribute", attr); return NULL; } json_reader_read_member(reader, attr); val = json_reader_get_string_value(reader); json_reader_end_member(reader); return val; } static inline gint64 _read_attr_int(JsonReader *reader, const char *attr) { gint64 val; if (!reader || !attr) return 0; if (!_is_member_exist(reader, attr)) { _ERR("There is no %s attribute", attr); return 0; } json_reader_read_member(reader, attr); val = json_reader_get_int_value(reader); json_reader_end_member(reader); return val; } static JsonReader *_get_reader(JsonParser *parser) { if (!parser) { _ERR("Invalid argument"); return NULL; } return json_reader_new(json_parser_get_root(parser)); } static inline void _unload_config_user(struct engine *eng) { if (!eng) return; free(eng->user.name); free(eng->user.thumb_bg); free(eng->user.thumb); } static int _read_color(JsonReader *reader, gint64 *r, gint64 *g, gint64 *b) { if (!reader || !r || !g || !b) { _ERR("Invalid argument"); return -1; } if (!_is_member_exist(reader, ATTR_COLOR)) { _ERR("There is no "ATTR_COLOR" attribute"); return -1; } json_reader_read_member(reader, ATTR_COLOR); *r = _read_attr_int(reader, ATTR_RED); *g = _read_attr_int(reader, ATTR_GREEN); *b = _read_attr_int(reader, ATTR_BLUE); json_reader_end_member(reader); return 0; } static void _string_to_uppercase(char *str) { while (*str != '\0') *(str++) = toupper(*str); } static char *_get_unique_id(const char *object_path) { struct timezone timezone; struct timeval timeval; char uuid[SIZE_32]; unsigned int len; int i; union { unsigned int t; unsigned char ct[SIZE_4]; } u1, u2; if (!object_path) return NULL; gettimeofday(&timeval, &timezone); u1.t = (unsigned int)timeval.tv_usec; len = strlen(object_path); u2.t = 0; for (i = 0; i < len; i++) u2.t = u2.t + MULTIPLIER * (unsigned int)object_path[i]; snprintf(uuid, sizeof(uuid), "%02x%02x.%02x%02x.%02x%02x.%02x%02x", (unsigned char)u2.ct[3], (unsigned char)u2.ct[2], (unsigned char)u2.ct[1], (unsigned char)u2.ct[0], (unsigned char)u1.ct[3], (unsigned char)u1.ct[2], (unsigned char)u1.ct[1], (unsigned char)u1.ct[0]); _string_to_uppercase(uuid); return strdup(uuid); } static struct engine_bar_item *_new_bar_item(JsonReader *reader, int idx) { struct engine_bar_item *it; const char *name, *icon, *icon_focus, *app, *in; const char *object_path, *bus_name; const char *noctnt_title, *noctnt_desc; gint64 r, g, b; gint64 column; if (!json_reader_read_element(reader, idx)) { _ERR("Cannot read element of index %d", idx); return NULL; } it = calloc(1, sizeof(*it)); if (!it) { _ERR("calloc failed"); return NULL; } name = _read_attr(reader, ATTR_NAME); if (!name) goto err; icon = _read_attr(reader, ATTR_ICON); if (!icon) goto err; icon_focus = _read_attr(reader, ATTR_ICON_FOCUS); if (!icon_focus) goto err; bus_name = _read_attr(reader, ATTR_BUS_NAME); if (!bus_name) goto err; object_path = _read_attr(reader, ATTR_OBJECT_PATH); if (!object_path) goto err; in = _read_attr(reader, ATTR_IN); if (!in) goto err; app = _read_attr(reader, ATTR_APP); noctnt_title = _read_attr(reader, ATTR_NOCTNT_TITLE); noctnt_desc = _read_attr(reader, ATTR_NOCTNT_DESC); column = _read_attr_int(reader, ATTR_CONTENT_COLUMN); if (!column) column = 1; if (_read_color(reader, &r, &g, &b) != 0) { r = 69; g = 143; b = 255; } json_reader_end_element(reader); it->name = strdup(name); it->icon = strdup(icon); it->icon_focus = strdup(icon_focus); it->object_path = strdup(object_path); it->bus_name = strdup(bus_name); it->svcid = _get_unique_id(it->object_path); it->in = strdup(in); if (app) it->app = strdup(app); if (noctnt_title) it->noctnt_title = strdup(noctnt_title); if (noctnt_desc) it->noctnt_desc = strdup(noctnt_desc); it->r = r; it->g = g; it->b = b; it->content_column = column; return it; err: json_reader_end_element(reader); free(it); return NULL; } static struct engine_ubar_item *_new_ubar_item(JsonReader *reader, int idx) { struct engine_ubar_item *it; const char *name, *thumb_bg, *thumb, *password; int age, authority; if (!json_reader_read_element(reader, idx)) { _ERR("Cannot read element of index %d", idx); return NULL; } it = calloc(1, sizeof(*it)); if (!it) { _ERR("calloc failed"); return NULL; } name = _read_attr(reader, ATTR_NAME); if (!name) goto err; thumb_bg = _read_attr(reader, ATTR_THUMB_BG); if (!thumb_bg) goto err; thumb = _read_attr(reader, ATTR_THUMB); if (!thumb) goto err; password = _read_attr(reader, ATTR_PASSWORD); age = _read_attr_int(reader, ATTR_AGE); authority = _read_attr_int(reader, ATTR_AUTHORITY); it->name = strdup(name); it->thumb_bg = strdup(thumb_bg); it->thumb = strdup(thumb); if (password) it->password = strdup(password); if (age) it->age = age; if (authority) it->authority = authority; json_reader_end_member(reader); return it; err: json_reader_end_member(reader); free(it); return NULL; } static inline void _unload_bar_item(struct engine_bar_item *it) { if (!it) return; free(it->name); free(it->icon); free(it->icon_focus); free(it->svcid); free(it->bus_name); free(it->object_path); free(it->app); free(it->args); free(it->noctnt_title); free(it->noctnt_desc); free(it->in); free(it); } static int _load_bar_items(JsonReader *reader, struct engine *eng) { struct engine_bar_item *it; int i, cnt; struct client_bus *cbus; if (!reader || !eng) { _ERR("Invalid argument"); return -1; } if (!_is_member_exist(reader, SECTION_ITEMS)) { _ERR("There is no "SECTION_ITEMS" field"); return -1; } json_reader_read_member(reader, SECTION_ITEMS); if (!json_reader_is_array(reader)) { _ERR(SECTION_ITEMS" is not array"); goto err; } cnt = json_reader_count_elements(reader); for (i = 0; i < cnt; i++) { it = _new_bar_item(reader, i); if (!it) continue; it->eng = eng; eng->hbar_its = eina_list_append(eng->hbar_its, it); /* send unique id to each content provider */ cbus = bus_client_init(it->bus_name, it->object_path, it->svcid); if (!cbus) { _ERR(" Unable to init client bus "); continue; } bus_client_send_svcid(cbus); eng->client_buslist = eina_list_append(eng->client_buslist, cbus); } json_reader_end_member(reader); return 0; err: json_reader_end_member(reader); return -1; } static inline void _unload_bar_items(struct engine *eng) { struct engine_bar_item *it; if (!eng || !eng->hbar_its) { _ERR("Invalid argument"); return; } EINA_LIST_FREE(eng->hbar_its, it) _unload_bar_item(it); eng->hbar_its = NULL; } static int _load_ubar_items(JsonReader *reader, struct engine *eng) { struct engine_ubar_item *it; int i, cnt; if (!reader || !eng) { _ERR("Invalid argument"); return -1; } if (!_is_member_exist(reader, SECTION_UBAR_ITEMS)) { _ERR("There is no "SECTION_UBAR_ITEMS" field"); return -1; } json_reader_read_member(reader, SECTION_UBAR_ITEMS); if (!json_reader_is_array(reader)) { _ERR(SECTION_UBAR_ITEMS" is not array"); goto err; } cnt = json_reader_count_elements(reader); for (i = 0; i < cnt; i++) { it = _new_ubar_item(reader, i); if (!it) continue; it->eng = eng; eng->ubar_its = eina_list_append(eng->ubar_its, it); } json_reader_end_member(reader); return 0; err: json_reader_end_member(reader); return -1; } static inline void _unload_ubar_items(struct engine *eng) { struct engine_ubar_item *it; if (!eng || !eng->ubar_its) { _ERR("Invalid argument"); return; } EINA_LIST_FREE(eng->ubar_its, it) { free(it->name); free(it->thumb_bg); free(it->thumb); } eng->ubar_its = NULL; } static JsonParser *_get_parser(const char *config) { JsonParser *parser; gboolean r; if (!config) { _ERR("Invalid argument"); return NULL; } parser = json_parser_new(); if (!parser) { _ERR("json parser new failed"); return NULL; } r = json_parser_load_from_file(parser, config, NULL); if (!r) { _ERR("parser load from file failed"); g_object_unref(parser); return NULL; } return parser; } static int _load_item_config(struct engine *eng) { JsonParser *parser; JsonReader *reader; if (!eng) { _ERR("Invalid argument"); return -1; } parser = _get_parser(DEF_CONFIG); if (!parser) { _ERR("json parser new failed"); return -1; } reader = _get_reader(parser); if (!reader) { _ERR("reader get failed"); goto unref_parser; } if (_load_bar_items(reader, eng) != 0) goto unref_reader; g_object_unref(reader); g_object_unref(parser); return 0; unref_reader: g_object_unref(reader); unref_parser: g_object_unref(parser); return -1; } static int _load_user_config(struct engine *eng) { JsonParser *parser; JsonReader *reader; if (!eng) { _ERR("Invalid argument"); return -1; } parser = _get_parser(DEF_CONFIG_USER); if (!parser) { _ERR("json parser new failed"); return -1; } reader = _get_reader(parser); if (!reader) { _ERR("reader get failed"); goto unref_parser; } if (_load_ubar_items(reader, eng) != 0) goto unref_reader; g_object_unref(reader); g_object_unref(parser); return 0; unref_reader: g_object_unref(reader); unref_parser: g_object_unref(parser); return -1; } static void _unload_config(struct engine *eng) { if (!eng) return; _unload_config_user(eng); _unload_bar_items(eng); _unload_ubar_items(eng); } static void _bus_ready(struct bus *bus, void *data) { bus_send_signal(bus, BUS_SIGNAL_REFRESH); } static void _bus_end(struct bus *bus, void *data) { } static inline struct engine_dbar_item_content *_new_ctnt( struct bus_data_content *bus_ctnt) { struct engine_dbar_item_content *ctnt; if (!bus_ctnt) return NULL; ctnt = calloc(1, sizeof(*ctnt)); if (!ctnt) { _ERR("calloc failed"); return NULL; } switch (bus_ctnt->type) { case BUS_DATA_CONTENT_IMAGE: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_IMAGE; break; case BUS_DATA_CONTENT_VIDEO: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_VIDEO; break; case BUS_DATA_CONTENT_MUSIC: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_MUSIC; break; case BUS_DATA_CONTENT_BROADCAST: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_BROADCAST; break; case BUS_DATA_CONTENT_APP: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_APP; break; case BUS_DATA_CONTENT_SOURCE: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_SOURCE; break; case BUS_DATA_CONTENT_NOTIFICATION_NOTI: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_NOTI; break; case BUS_DATA_CONTENT_NOTIFICATION_ONGOING: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_NOTIFICATION_ONGOING; break; case BUS_DATA_CONTENT_HISTORY: ctnt->type = ENGINE_DBAR_CONTENT_TYPE_HISTORY; break; default: _ERR("Invalid content type"); free(ctnt); return NULL; } if (bus_ctnt->subtitle) ctnt->subtitle = strdup(bus_ctnt->subtitle); if (bus_ctnt->description) ctnt->description = strdup(bus_ctnt->description); if (bus_ctnt->detail) ctnt->detail = strdup(bus_ctnt->detail); if (bus_ctnt->thumbnail) ctnt->thumbnail = strdup(bus_ctnt->thumbnail); if (bus_ctnt->icon) ctnt->icon = strdup(bus_ctnt->icon); return ctnt; } static inline void _free_ctnt(struct engine_dbar_item_content *ctnt) { if (!ctnt) return; free(ctnt->subtitle); free(ctnt->description); free(ctnt->detail); free(ctnt->icon); free(ctnt->thumbnail); free(ctnt); } static int _add_dbar_item(struct engine_bar_item *hit, enum engine_dbar_item_style style, const char *name, struct bus_data_content bus_ctnt[], int ctnt_cnt, enum bus_data_action_op action, const char *actor, const char *args) { struct engine_dbar_item *dit; struct engine_dbar_item_content *ctnt; int i; if (!hit) { _ERR("Invalid argument"); return -1; } dit = calloc(1, sizeof(*dit)); if (!dit) { _ERR("calloc failed"); return -1; } dit->name = strdup(name ? name : "No Information"); if (ctnt_cnt > BUS_DATA_ALBUM_CONTENT_MAX) ctnt_cnt = BUS_DATA_ALBUM_CONTENT_MAX; if (bus_ctnt) { for (i = 0; i < ctnt_cnt; i++) { ctnt = _new_ctnt(&bus_ctnt[i]); if (!ctnt) break; dit->ctnts = eina_list_append(dit->ctnts, ctnt); } } dit->ctnt_id = hit->ctnt_id++; dit->hit = hit; dit->style = style; dit->action = action; if (actor) dit->actor = strdup(actor); if (args) dit->args = strdup(args); hit->dbar_its = eina_list_append(hit->dbar_its, dit); if (hit->update_cb) hit->update_cb(hit, hit->update_cb_data); return dit->ctnt_id; } static inline void _free_dbar_item(struct engine_dbar_item *dit) { struct engine_dbar_item_content *ctnt; EINA_LIST_FREE(dit->ctnts, ctnt) _free_ctnt(ctnt); free(dit->actor); free(dit->args); free(dit->name); free(dit); } static int _del_dbar_item(struct engine_bar_item *hit, int ctnt_id) { struct engine_dbar_item *dit; Eina_List *l; if (!hit) return -1; EINA_LIST_FOREACH(hit->dbar_its, l, dit) { if (dit->ctnt_id == ctnt_id) { hit->dbar_its = eina_list_remove_list( hit->dbar_its, l); _free_dbar_item(dit); if (hit->update_cb) hit->update_cb(hit, hit->update_cb_data); return 0; } } return -1; } static int _del_dbar_item_all(struct engine_bar_item *hit) { struct engine_dbar_item *dit; if (!hit) return -1; EINA_LIST_FREE(hit->dbar_its, dit) _free_dbar_item(dit); hit->dbar_its = NULL; if (hit->update_cb) hit->update_cb(hit, hit->update_cb_data); return 0; } static int _bus_add_label(struct bus_data_label *lbl, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; if (!lbl || !data) { _ERR("Invalid argument"); return -1; } eng = data; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (strcmp(hit->svcid, lbl->svcid)) continue; return _add_dbar_item(hit, ENGINE_DBAR_ITEM_STYLE_LABEL, lbl->title, NULL, 0, BUS_DATA_ACTION_LAUNCH_NONE, NULL, NULL); } return -1; } static int _bus_add_album(struct bus_data_album *album, struct bus_data_action *act, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; if (!album || !act || !data) { _ERR("Invalid argument"); return -1; } eng = data; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (strcmp(hit->svcid, album->svcid)) continue; return _add_dbar_item(hit, ENGINE_DBAR_ITEM_STYLE_ALBUM, album->title, album->contents, album->content_cnt, act->action, act->actor, act->args); } return -1; } static int _bus_add_content(struct bus_data_content *content, struct bus_data_action *act, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; if (!content || !act || !data) { _ERR("Invalid argument"); return -1; } eng = data; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (strcmp(hit->svcid, content->svcid)) continue; return _add_dbar_item(hit, ENGINE_DBAR_ITEM_STYLE_CONTENT, content->title, content, 1, act->action, act->actor, act->args); } return -1; } static void _get_item_bg_and_icon(enum bus_data_pin_type type, const char *icon, struct engine_bar_item *it) { switch (type) { case BUS_DATA_PIN_CHANNEL: it->r = ITEM_CHANNEL_BG_R; it->g = ITEM_CHANNEL_BG_G; it->b = ITEM_CHANNEL_BG_B; it->icon = strdup(DEF_PIN_ITEM_CHANNEL_ICON); it->icon_focus = strdup(DEF_PIN_ITEM_CHANNEL_ICON_FOCUS); it->type = APP_CF_CHANNEL; break; case BUS_DATA_PIN_PACKAGE: it->r = ITEM_PACKAGE_BG_R; it->g = ITEM_PACKAGE_BG_G; it->b = ITEM_PACKAGE_BG_B; if (icon) { it->icon = strdup(icon); it->icon_focus = strdup(icon); } else { it->icon = strdup(DEF_PIN_ITEM_DEFAULT_ICON); it->icon_focus = strdup(DEF_PIN_ITEM_DEFAULT_ICON_FOCUS); } it->type = APP_CF_APPS; break; default: it->r = ITEM_DEFAULT_BG_R; it->g = ITEM_DEFAULT_BG_G; it->b = ITEM_DEFAULT_BG_B; it->icon = strdup(DEF_PIN_ITEM_DEFAULT_ICON); it->icon_focus = strdup(DEF_PIN_ITEM_DEFAULT_ICON_FOCUS); break; } } static struct engine_bar_item *_new_pin_item(struct engine *eng, const char *title, enum bus_data_pin_type type, const char *icon, const char *svcid, enum bus_data_action_op action, const char *actor, const char *args, const char *pinid) { struct engine_bar_item *it; if (!title || !svcid || type > BUS_DATA_PIN_MAX || !pinid) return NULL; it = calloc(1, sizeof(*it)); if (!it) { _ERR("calloc failed"); return NULL; } it->name = strdup(title); it->svcid = strdup(svcid); it->in = strdup("custombar"); it->is_pinned = EINA_TRUE; it->ctnt_id++; it->pinid = strdup(pinid); _get_item_bg_and_icon(type, icon, it); if (action == BUS_DATA_ACTION_LAUNCH_APP) it->app = strdup(actor); if (args) it->args = strdup(args); return it; } static void _update_pin_list(struct engine *eng) { GList *cp_list; Eina_List *l; struct engine_bar_item *hit; int i; const char *pinid; if (!eng) { _ERR("Invalid argument"); return; } cp_list = app_content_pin_get_list(); if (!cp_list) { _ERR("failed to get pin list"); return; } for (i = 0; i < g_list_length(cp_list); i++) { pinid = g_list_nth_data(cp_list, i); if (!pinid) continue; EINA_LIST_FOREACH(eng->pin_its, l, hit) { if (!strcmp(hit->pinid, pinid)) eng->hbar_its = eina_list_append(eng->hbar_its, hit); } } eng->is_full = EINA_TRUE; } static void _unload_pin_item(struct engine_bar_item *it) { if (!it) return; free(it->name); free(it->icon); free(it->icon_focus); free(it->svcid); free(it->app); free(it->args); free(it->in); free(it->pinid); free(it); } static int _del_pin_item(struct engine *eng, Eina_Bool free) { struct engine_bar_item *hit; Eina_List *l; if (!eng || !eng->hbar_its) return -1; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (!hit->is_pinned) continue; eng->hbar_its = eina_list_remove_list(eng->hbar_its, l); if (free) _unload_pin_item(hit); } return 0; } static int _bus_add_pin(struct bus_data_pin *pin, struct bus_data_action *act, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; int cnt; int r; if (!pin || !act || !data) { _ERR("Invalid argument"); return -1; } eng = data; r = _del_pin_item(eng, EINA_TRUE); if (r < 0) { _ERR("failed to delete pin item in hbar list"); return -1; } if (eng->is_full) { EINA_LIST_FOREACH(eng->pin_its, l, hit) eng->pin_its = eina_list_remove_list(eng->pin_its, l); eng->is_full = EINA_FALSE; } hit = _new_pin_item(eng, pin->title, pin->type, pin->icon, pin->svcid, act->action, act->actor, act->args, pin->pinid); if (!hit) return -1; eng->pin_its = eina_list_append(eng->pin_its, hit); cnt = eina_list_count(eng->pin_its); if (engine_bar_item_get_pin_count() != cnt) return hit->ctnt_id; _update_pin_list(eng); if (eng->update_cb) eng->update_cb(eng->update_cb_data, true); return hit->ctnt_id; } static int _bus_add_ctnt(struct bus *bus, enum bus_op op, void *opdata, struct bus_data_action *act, void *data) { switch (op) { case BUS_OP_ADD_LABEL: return _bus_add_label(opdata, data); case BUS_OP_ADD_ALBUM: return _bus_add_album(opdata, act, data); case BUS_OP_ADD_CONTENT: return _bus_add_content(opdata, act, data); case BUS_OP_ADD_PIN: return _bus_add_pin(opdata, act, data); default: _ERR("Operation not supported"); break; } return -1; } static int _bus_del_ctnt(struct bus *bus, const char *svcid, int ctnt_id, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; if (!data || !svcid || ctnt_id < 0) { _ERR("Invalid argument"); return -1; } eng = data; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (strcmp(hit->svcid, svcid)) continue; return _del_dbar_item(hit, ctnt_id); } return -1; } static int _bus_del_ctnt_all(struct bus *bus, const char *svcid, bool reload, void *data) { struct engine_bar_item *hit; struct engine *eng; Eina_List *l; if (!data || !svcid) { _ERR("Invalid argument"); return -1; } eng = data; if (reload) { _del_pin_item(eng, EINA_TRUE); if (eng->update_cb) eng->update_cb(eng->update_cb_data, true); return 0; } EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (strcmp(hit->svcid, svcid)) continue; return _del_dbar_item_all(hit); } return -1; } struct engine *engine_init(void) { struct engine *eng; struct bus *bus; int r; struct bus_cbs cbs = { .ready = _bus_ready, .add_ctnt = _bus_add_ctnt, .del_ctnt = _bus_del_ctnt, .del_all = _bus_del_ctnt_all, .end = _bus_end }; eng = calloc(1, sizeof(*eng)); if (!eng) { _ERR("calloc failed"); return NULL; } r = _load_user_config(eng); if (r != 0) { free(eng); return NULL; } r = _load_item_config(eng); if (r != 0) { free(eng); return NULL; } bus = bus_init(&cbs, eng); if (!bus) { _unload_config(eng); free(eng); return NULL; } eng->bus = bus; return eng; } void engine_fini(struct engine *eng) { struct client_bus *cbus; if (!eng) { _ERR("Invalid argument"); return; } _unload_config(eng); bus_fini(eng->bus); EINA_LIST_FREE(eng->client_buslist, cbus) bus_client_fini(cbus); free(eng); } int engine_get_user_info(struct engine *eng, const char **name, const char **thumb_bg, const char **thumb) { if (!eng) { _ERR("Invalid argument"); return -1; } if (name) *name = eng->user.name; if (thumb_bg) *thumb_bg = eng->user.thumb_bg; if (thumb) *thumb = eng->user.thumb; return 0; } const Eina_List *engine_get_bar_items(struct engine *eng) { if (!eng) { _ERR("Invalid argument"); return NULL; } return eng->hbar_its; } const char *engine_bar_item_get_name(struct engine_bar_item *it) { if (!it) return NULL; return it->name; } const char *engine_bar_item_get_icon(struct engine_bar_item *it) { if (!it) return NULL; return it->icon; } const char *engine_bar_item_get_icon_focus(struct engine_bar_item *it) { if (!it) return NULL; return it->icon_focus; } const char *engine_bar_item_get_svcid(struct engine_bar_item *it) { if (!it) return NULL; return it->svcid; } const char *engine_bar_item_get_bus_name(struct engine_bar_item *it) { if (!it) return NULL; return it->bus_name; } const char *engine_bar_item_get_object_path(struct engine_bar_item *it) { if (!it) return NULL; return it->object_path; } const char *engine_bar_item_get_noctnt_title(struct engine_bar_item *it) { if (!it) return NULL; return it->noctnt_title; } const char *engine_bar_item_get_noctnt_desc(struct engine_bar_item *it) { if (!it) return NULL; return it->noctnt_desc; } int engine_bar_item_get_color(struct engine_bar_item *it, int *r, int *g, int *b) { if (!it || !r || !g || !b) return -1; *r = it->r; *g = it->g; *b = it->b; return 0; } int engine_bar_item_get_content_column(struct engine_bar_item *it, int *content_column) { if (!it || !content_column) return -1; *content_column = it->content_column; return 0; } int engine_bar_item_launch(struct engine_bar_item *it) { int r; bundle *args; if (!it) return -1; if (!it->app) { _ERR("Application name is not found"); return -1; } if (it->args) args = bundle_decode((const bundle_raw*)it->args, strlen(it->args)); else args = NULL; r = aul_launch_app(it->app, args); if (args) bundle_free(args); if (r < 0) { _ERR("Open app failed"); if (args) bundle_free(args); return -1; } return 0; } void engine_bar_item_set_update_cb(struct engine_bar_item *it, void (*update_cb)(struct engine_bar_item *it, void *data), void *data) { if (!it) return; it->update_cb = update_cb; it->update_cb_data = data; } void engine_bar_item_set_pin_update_cb(struct engine *eng, void (*update_cb)(void *data, bool focus), void *data) { if (!eng) return; eng->update_cb = update_cb; eng->update_cb_data = data; } void engine_ubar_item_set_visible(struct engine_ubar_item *it, bool visible) { if (!it) { _ERR("Invalid argument"); return; } it->visible = visible; } int engine_ubar_item_get_info(struct engine_ubar_item *it, const char **name, const char **thumb_bg, const char **thumb, int *age, bool *visible) { if (!it) { _ERR("invalid argument"); return -1; } if (name) *name = it->name; if (thumb_bg) *thumb_bg = it->thumb_bg; if (thumb) *thumb = it->thumb; if (age) *age = it->age; if (visible) *visible = it->visible; return 0; } const Eina_List *engine_get_ubar_items(struct engine *eng) { if (!eng) { _ERR("invalid argument"); return NULL; } return eng->ubar_its; } const Eina_List *engine_get_dbar_items(struct engine_bar_item *it) { if (!it) { _ERR("Invalid argument"); return NULL; } return it->dbar_its; } const Eina_List *engine_dbar_item_get_contents(struct engine_dbar_item *it) { if (!it) { _ERR("Invalid argument"); return NULL; } return it->ctnts; } const char *engine_dbar_item_get_name(struct engine_dbar_item *it) { if (!it) { _ERR("Invalid argument"); return NULL; } return it->name; } enum engine_dbar_item_style engine_dbar_item_get_style( struct engine_dbar_item *it) { if (!it) { _ERR("Invalid argument"); return ENGINE_DBAR_ITEM_STYLE_CONTENT; } return it->style; } int engine_dbar_item_get_color(struct engine_dbar_item *it, int *r, int *g, int *b) { if (!it || !r || !g || !b) { _ERR("Invalid argument"); return -1; } return engine_bar_item_get_color(it->hit, r, g, b); } static inline int _launch_app(struct engine_dbar_item *it) { int r; bundle *args; struct engine_dbar_item_content *ctnt; if (!it) return -1; if (it->args) args = bundle_decode((const bundle_raw*)it->args, strlen(it->args)); else args = NULL; r = aul_launch_app(it->actor, args); if (args) bundle_free(args); if (r < 0) { _ERR("launch app failed"); return -1; } ctnt = eina_list_data_get(it->ctnts); if (!ctnt) { _ERR("get ctnt failed"); return 0; } return 0; } int engine_dbar_item_launch(struct engine_dbar_item *it) { if (!it) return -1; switch (it->action) { case BUS_DATA_ACTION_LAUNCH_NONE: _ERR("Non-launchable item"); break; case BUS_DATA_ACTION_LAUNCH_APP: return _launch_app(it); case BUS_DATA_ACTION_LAUNCH_SERVICE: _ERR("Service launching is not supported yet"); break; default: _ERR("Invalid action type"); break; } return 0; } enum engine_dbar_content_type engine_dbar_item_get_content_type( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return ENGINE_DBAR_CONTENT_TYPE_IMAGE; } return ctnt->type; } const char *engine_dbar_item_get_content_subtitle( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return NULL; } return ctnt->subtitle; } const char *engine_dbar_item_get_content_description( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return NULL; } return ctnt->description; } const char *engine_dbar_item_get_content_detail( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return NULL; } return ctnt->detail; } const char *engine_dbar_item_get_content_thumbnail( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return NULL; } return ctnt->thumbnail; } const char *engine_dbar_item_get_content_icon( struct engine_dbar_item_content *ctnt) { if (!ctnt) { _ERR("Invalid argument"); return NULL; } return ctnt->icon; } const char *engine_bar_item_get_in(struct engine_bar_item *it) { if (!it) return NULL; return it->in; } const char *engine_dbar_item_get_in(struct engine_dbar_item *it) { if (!it) return NULL; return engine_bar_item_get_in(it->hit); } Eina_Bool engine_bar_item_get_is_pinned(struct engine_bar_item *it) { if (!it) return EINA_FALSE; return it->is_pinned; } int engine_bar_item_del_pin(struct engine *eng, struct engine_bar_item *it) { Eina_List *l; struct engine_bar_item *hit; int r, cnt; if (!it || !eng) return -1; r = app_content_pin_unset(NULL, it->type, it->pinid); if (r < 0) { _ERR("failed to unset pin item"); return -1; } cnt = app_content_pin_get_count(); if (cnt != 0) return 0; EINA_LIST_FOREACH(eng->hbar_its, l, hit) { if (!hit->pinid) continue; if (!strcmp(hit->pinid, it->pinid)) { eng->hbar_its = eina_list_remove_list(eng->hbar_its, l); _unload_pin_item(hit); break; } } return 0; } int engine_bar_item_get_pin_count(void) { int r; r = app_content_pin_get_count(); if (r < 0) { _ERR("failed to get pin count"); return 0; } return r; } int engine_bar_item_swap_pin(struct engine *eng, struct engine_bar_item *it1, struct engine_bar_item *it2) { int r; if (!eng || !it1 || !it2) { _ERR("Invalid argument"); return -1; } if (!it1->pinid || !it2->pinid) { _ERR("No pin item"); return -1; } r = app_content_pin_swap_position(it1->type, it1->pinid, it2->type, it2->pinid); if (r < 0) { _ERR("failed to swap pin item"); return -1; } _del_pin_item(eng, EINA_FALSE); _update_pin_list(eng); return 0; }