2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <stdlib.h> /* free */
22 #include <sys/types.h>
26 #include <Ecore_Evas.h>
33 #include "slave_life.h"
34 #include "slave_rpc.h"
35 #include "client_life.h"
38 #include "buffer_handler.h"
39 #include "script_handler.h"
45 #define TYPE_COLOR "color"
46 #define TYPE_TEXT "text"
47 #define TYPE_IMAGE "image"
48 #define TYPE_EDJE "script"
49 #define TYPE_SIGNAL "signal"
50 #define TYPE_INFO "info"
51 #define TYPE_DRAG "drag"
52 #define INFO_SIZE "size"
53 #define INFO_CATEGORY "category"
59 Eina_List *script_port_list;
60 enum buffer_type env_buf_type;
62 .script_port_list = NULL,
63 .env_buf_type = BUFFER_TYPE_FILE,
69 const char *(*magic_id)(void);
70 int (*update_color)(void *handle, Evas *e, const char *id, const char *part, const char *rgba);
71 int (*update_text)(void *handle, Evas *e, const char *id, const char *part, const char *text);
72 int (*update_image)(void *handle, Evas *e, const char *id, const char *part, const char *path, const char *option);
73 int (*update_script)(void *handle, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *option);
74 int (*update_signal)(void *handle, Evas *e, const char *id, const char *part, const char *signal);
75 int (*update_drag)(void *handle, Evas *e, const char *id, const char *part, double x, double y);
76 int (*update_size)(void *handle, Evas *e, const char *id, int w, int h);
77 int (*update_category)(void *handle, Evas *e, const char *id, const char *category);
79 void *(*create)(const char *file, const char *option);
80 int (*destroy)(void *handle);
82 int (*load)(void *handle, Evas *e, int w, int h);
83 int (*unload)(void *handle, Evas *e);
115 struct inst_info *inst;
125 struct script_port *port;
129 static inline struct script_port *find_port(const char *magic_id)
132 struct script_port *item;
134 EINA_LIST_FOREACH(s_info.script_port_list, l, item) {
135 if (!strcmp(item->magic_id(), magic_id))
142 static void render_pre_cb(void *data, Evas *e, void *event_info)
144 struct inst_info *inst = data;
145 struct script_info *info;
147 if (instance_state(inst) != INST_ACTIVATED) {
148 DbgPrint("Render pre invoked but instance is not activated\n");
152 info = instance_lb_script(inst);
153 if (info && script_handler_evas(info) == e) {
157 info = instance_pd_script(inst);
158 if (info && script_handler_evas(info) == e) {
162 ErrPrint("Failed to do sync\n");
166 static void render_post_cb(void *data, Evas *e, void *event_info)
168 struct inst_info *inst;
169 struct script_info *info;
173 if (instance_state(inst) != INST_ACTIVATED) {
174 DbgPrint("Render post invoked but instance is not activated\n");
178 info = instance_lb_script(inst);
179 if (info && script_handler_evas(info) == e) {
180 fb_sync(script_handler_fb(info));
181 instance_lb_updated_by_instance(inst);
185 info = instance_pd_script(inst);
186 if (info && script_handler_evas(info) == e) {
187 fb_sync(script_handler_fb(info));
188 instance_pd_updated_by_instance(inst, NULL);
192 ErrPrint("Failed to sync\n");
200 int script_signal_emit(Evas *e, const char *part, const char *signal, double sx, double sy, double ex, double ey)
203 struct script_info *info;
206 ee = ecore_evas_ecore_evas_get(e);
208 ErrPrint("Evas has no Ecore_Evas\n");
212 info = ecore_evas_data_get(ee, "script,info");
214 ErrPrint("ecore_evas doesn't carry info data\n");
218 if (!signal || strlen(signal) == 0)
221 if (!part || strlen(part) == 0)
224 ret = instance_signal_emit(info->inst, signal, part, sx, sy, ex, ey, info->x, info->y, info->down);
228 HAPI int script_handler_load(struct script_info *info, int is_pd)
233 if (!info || !info->port) {
234 ErrPrint("Script handler is not created\n");
238 if (info->loaded > 0) {
243 ret = fb_create_buffer(info->fb);
247 info->ee = fb_canvas(info->fb);
249 ErrPrint("Failed to get canvas\n");
250 fb_destroy_buffer(info->fb);
254 ecore_evas_data_set(info->ee, "script,info", info);
256 e = script_handler_evas(info);
258 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb, info->inst);
259 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, render_post_cb, info->inst);
260 if (info->port->load(info->port_data, e, info->w, info->h) < 0) {
261 ErrPrint("Failed to add new script object\n");
262 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
263 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
264 fb_destroy_buffer(info->fb);
269 ErrPrint("Evas: (nil) %dx%d\n", info->w, info->h);
272 ecore_evas_manual_render_set(info->ee, EINA_FALSE);
273 ecore_evas_resize(info->ee, info->w, info->h);
274 ecore_evas_show(info->ee);
275 ecore_evas_activate(info->ee);
279 script_signal_emit(e, util_uri_to_path(instance_id(info->inst)),
280 is_pd ? "pd,show" : "lb,show", 0.0f, 0.0f, 0.0f, 0.0f);
284 HAPI int script_handler_unload(struct script_info *info, int is_pd)
289 if (!info || !info->port)
293 if (info->loaded > 0)
296 if (info->loaded < 0) {
301 e = script_handler_evas(info);
303 script_signal_emit(e, util_uri_to_path(instance_id(info->inst)), is_pd ? "pd,hide" : "lb,hide", 0.0f, 0.0f, 0.0f, 0.0f);
304 if (info->port->unload(info->port_data, e) < 0)
305 ErrPrint("Failed to unload script object. but go ahead\n");
306 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
307 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
309 ErrPrint("Evas(nil): Unload script\n");
312 ee = fb_canvas(info->fb);
314 ecore_evas_data_set(ee, "script,info", NULL);
316 fb_destroy_buffer(info->fb);
320 HAPI struct script_info *script_handler_create(struct inst_info *inst, const char *file, const char *option, int w, int h)
322 struct script_info *info;
324 DbgPrint("Create script: %s (%s)\n", file, option);
329 info = calloc(1, sizeof(*info));
331 ErrPrint("Heap: %s\n", strerror(errno));
335 info->fb = fb_create(inst, w, h, s_info.env_buf_type);
337 ErrPrint("Failed to create a FB (%dx%d)\n", w, h);
343 info->port = find_port(package_script(instance_package(inst)));
345 ErrPrint("Failed to find a proper port for [%s]%s\n",
346 instance_package(inst), package_script(instance_package(inst)));
347 fb_destroy(info->fb);
352 DbgPrint("Update info [%dx%d]\n", w, h);
356 info->port_data = info->port->create(file, option);
357 if (!info->port_data) {
358 ErrPrint("Failed to create a port (%s - %s)\n", file, option);
359 fb_destroy(info->fb);
367 HAPI int script_handler_destroy(struct script_info *info)
369 if (!info || !info->port) {
370 ErrPrint("port is not valid\n");
374 if (info->loaded != 0) {
375 ErrPrint("Script handler is not unloaded\n");
379 if (info->port->destroy(info->port_data) < 0)
380 ErrPrint("Failed to destroy port, but go ahead\n");
382 fb_destroy(info->fb);
387 HAPI int script_handler_is_loaded(struct script_info *info)
389 return info ? info->loaded > 0 : 0;
392 HAPI struct fb_info *script_handler_fb(struct script_info *info)
394 return info ? info->fb : NULL;
397 HAPI void *script_handler_evas(struct script_info *info)
405 return ecore_evas_get(info->ee);
408 static int update_script_color(struct inst_info *inst, struct block *block, int is_pd)
410 struct script_info *info;
413 if (!block || !block->part || !block->data) {
414 ErrPrint("Block or part or data is not valid\n");
418 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
420 ErrPrint("info is NIL\n");
425 ErrPrint("info->port is NIL\n");
429 e = script_handler_evas(info);
431 info->port->update_color(info->port_data, e, block->id, block->part, block->data);
433 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
438 static int update_script_text(struct inst_info *inst, struct block *block, int is_pd)
440 struct script_info *info;
443 if (!block || !block->part || !block->data) {
444 ErrPrint("Block or part or data is not valid\n");
448 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
450 ErrPrint("info is NIL\n");
455 ErrPrint("info->port is NIL\n");
459 e = script_handler_evas(info);
461 info->port->update_text(info->port_data, e, block->id, block->part, block->data);
463 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
467 static int update_script_image(struct inst_info *inst, struct block *block, int is_pd)
469 struct script_info *info;
472 if (!block || !block->part) {
473 ErrPrint("Block or part is not valid\n");
477 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
479 ErrPrint("info is NIL\n");
484 ErrPrint("info->port is NIL\n");
488 e = script_handler_evas(info);
490 info->port->update_image(info->port_data, e, block->id, block->part, block->data, block->option);
492 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
496 static int update_script_script(struct inst_info *inst, struct block *block, int is_pd)
498 struct script_info *info;
501 if (!block || !block->part) {
502 ErrPrint("Block or part is NIL\n");
506 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
508 ErrPrint("info is NIL\n");
513 ErrPrint("info->port is NIL\n");
517 e = script_handler_evas(info);
519 info->port->update_script(info->port_data, e, block->id, block->target_id, block->part, block->data, block->option);
521 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s] option[%s]\n",
522 block->id, block->part, block->data, block->option);
526 static int update_script_signal(struct inst_info *inst, struct block *block, int is_pd)
528 struct script_info *info;
532 ErrPrint("block is NIL\n");
536 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
538 ErrPrint("info is NIL\n");
543 ErrPrint("info->port is NIL\n");
547 e = script_handler_evas(info);
549 info->port->update_signal(info->port_data, e, block->id, block->part, block->data);
551 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
555 static int update_script_drag(struct inst_info *inst, struct block *block, int is_pd)
557 struct script_info *info;
561 if (!block || !block->data || !block->part) {
562 ErrPrint("block or block->data or block->part is NIL\n");
566 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
568 ErrPrint("info is NIL\n");
572 if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
573 ErrPrint("Invalid format of data (DRAG data [%s])\n", block->data);
578 ErrPrint("info->port is NIL\n");
582 e = script_handler_evas(info);
584 info->port->update_drag(info->port_data, e, block->id, block->part, dx, dy);
586 ErrPrint("Evas(nil) id[%s] part[%s] %lfx%lf\n", block->id, block->part, dx, dy);
590 HAPI int script_handler_resize(struct script_info *info, int w, int h)
593 //|| (info->w == w && info->h == h)) {
594 ErrPrint("info[%p] resize is not changed\n", info);
598 fb_resize(script_handler_fb(info), w, h);
600 if (info->port->update_size) {
602 e = script_handler_evas(info);
604 info->port->update_size(info->port_data, e, NULL , w, h);
606 ErrPrint("Evas(nil) resize to %dx%d\n", w, h);
615 static int update_info(struct inst_info *inst, struct block *block, int is_pd)
617 struct script_info *info;
619 if (!block || !block->part || !block->data) {
620 ErrPrint("block or block->part or block->data is NIL\n");
624 info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
626 ErrPrint("info is NIL\n");
631 ErrPrint("info->port is NIL\n");
635 if (!strcasecmp(block->part, INFO_SIZE)) {
638 if (sscanf(block->data, "%dx%d", &w, &h) != 2) {
639 ErrPrint("Invalid format for SIZE(%s)\n", block->data);
647 resized = (instance_pd_width(inst) != w) || (instance_pd_height(inst) != h);
648 instance_set_pd_info(inst, w, h);
652 * LB Size is already scaled by livebox-service.
653 * Each livebox uses the LB_SIZE_TYPE_XXX for its size.
655 resized = (instance_lb_width(inst) != w) || (instance_lb_height(inst) != h);
656 instance_set_lb_info(inst, w, h, NO_CHANGE, CONTENT_NO_CHANGE, TITLE_NO_CHANGE);
660 instance_send_resized_event(inst, is_pd, w, h, 0);
662 script_handler_resize(info, w, h);
665 e = script_handler_evas(info);
667 info->port->update_size(info->port_data, e, block->id, w, h);
669 ErrPrint("Evas(nil): id[%s] %dx%d\n", block->id, w, h);
671 } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
673 e = script_handler_evas(info);
675 info->port->update_category(info->port_data, e, block->id, block->data);
677 ErrPrint("Evas(nil): id[%s] data[%s]\n", block->id, block->data);
683 HAPI int script_handler_parse_desc(const char *pkgname, const char *id, const char *descfile, int is_pd)
685 struct inst_info *inst;
704 const char *field_name[] = {
715 register int field_idx;
716 register int idx = 0;
721 int (*handler)(struct inst_info *inst, struct block *block, int is_pd);
725 .handler = update_script_color,
729 .handler = update_script_text,
733 .handler = update_script_image,
737 .handler = update_script_script,
741 .handler = update_script_signal,
745 .handler = update_script_drag,
749 .handler = update_info,
758 inst = package_find_instance_by_id(pkgname, id);
760 ErrPrint("Instance is not exists\n");
764 fp = fopen(descfile, "rt");
766 ErrPrint("Error: %s [%s]\n", descfile, strerror(errno));
787 if (!isspace(ch) && ch != EOF) {
788 ErrPrint("%d: Syntax error: Desc is not started with '{' or space - (%c = 0x%x)\n", lineno, ch, ch);
799 ErrPrint("%d: Syntax error: New line must has to be started right after '{'\n", lineno);
803 block = calloc(1, sizeof(*block));
805 ErrPrint("Heap: %s\n", strerror(errno));
825 if (field_name[field_idx][idx] != '\0') {
826 ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
834 DbgFree(block->type);
843 DbgFree(block->part);
852 DbgFree(block->data);
861 DbgFree(block->file);
868 state = VALUE_OPTION;
870 DbgFree(block->option);
871 block->option = NULL;
872 block->option_len = 0;
886 state = VALUE_TARGET;
887 if (block->target_id) {
888 DbgFree(block->target_id);
889 block->target_id = NULL;
890 block->target_len = 0;
895 ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
905 if (field_name[field_idx][idx] != ch) {
911 ungetc(field_name[field_idx][idx], fp);
914 if (field_name[field_idx] == NULL) {
915 ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
927 if (idx == block->type_len) {
929 block->type_len += ADDEND;
930 tmp = realloc(block->type, block->type_len);
932 ErrPrint("Heap: %s\n", strerror(errno));
939 block->type[idx] = '\0';
946 block->type[idx] = ch;
951 if (idx == block->part_len) {
953 block->part_len += ADDEND;
954 tmp = realloc(block->part, block->part_len);
956 ErrPrint("Heap: %s\n", strerror(errno));
963 block->part[idx] = '\0';
970 block->part[idx] = ch;
975 if (idx == block->data_len) {
977 block->data_len += ADDEND;
978 tmp = realloc(block->data, block->data_len);
980 ErrPrint("Heap: %s\n", strerror(errno));
987 block->data[idx] = '\0';
994 block->data[idx] = ch;
999 if (idx == block->file_len) {
1001 block->file_len += ADDEND;
1002 tmp = realloc(block->file, block->file_len);
1004 ErrPrint("Heap: %s\n", strerror(errno));
1011 block->file[idx] = '\0';
1018 block->file[idx] = ch;
1023 if (idx == block->option_len) {
1025 block->option_len += ADDEND;
1026 tmp = realloc(block->option, block->option_len);
1028 ErrPrint("Heap: %s\n", strerror(errno));
1031 block->option = tmp;
1035 block->option[idx] = '\0';
1042 block->option[idx] = ch;
1046 if (idx == block->id_len) {
1048 block->id_len += ADDEND;
1049 tmp = realloc(block->id, block->id_len);
1051 ErrPrint("Heap: %s\n", strerror(errno));
1058 block->id[idx] = '\0';
1065 block->id[idx] = ch;
1069 if (idx == block->target_len) {
1071 block->target_len += ADDEND;
1072 tmp = realloc(block->target_id, block->target_len);
1074 ErrPrint("Heap: %s\n", strerror(errno));
1077 block->target_id = tmp;
1081 block->target_id[idx] = '\0';
1088 block->target_id[idx] = ch;
1093 block->file = strdup(util_uri_to_path(id));
1095 ErrPrint("Heap: %s\n", strerror(errno));
1101 while (handlers[i].type) {
1102 if (!strcasecmp(handlers[i].type, block->type)) {
1103 handlers[i].handler(inst, block, is_pd);
1109 if (!handlers[i].type)
1110 ErrPrint("%d: Unknown block type: %s\n", lineno, block->type);
1112 DbgFree(block->file);
1113 DbgFree(block->type);
1114 DbgFree(block->part);
1115 DbgFree(block->data);
1116 DbgFree(block->option);
1118 DbgFree(block->target_id);
1130 if (state != UNKNOWN) {
1131 ErrPrint("%d: Unknown state\n", lineno);
1139 ErrPrint("Parse error at %d file %s\n", lineno, util_basename(descfile));
1141 DbgFree(block->file);
1142 DbgFree(block->type);
1143 DbgFree(block->part);
1144 DbgFree(block->data);
1145 DbgFree(block->option);
1147 DbgFree(block->target_id);
1154 HAPI int script_init(void)
1156 struct script_port *item;
1162 if (!strcasecmp(PROVIDER_METHOD, "shm"))
1163 s_info.env_buf_type = BUFFER_TYPE_SHM;
1164 else if (!strcasecmp(PROVIDER_METHOD, "pixmap"))
1165 s_info.env_buf_type = BUFFER_TYPE_PIXMAP;
1167 dir = opendir(SCRIPT_PORT_PATH);
1169 ErrPrint("Error: %s\n", strerror(errno));
1173 while ((ent = readdir(dir))) {
1174 if (ent->d_name[0] == '.')
1177 pathlen = strlen(ent->d_name) + strlen(SCRIPT_PORT_PATH) + 1;
1178 path = malloc(pathlen);
1180 ErrPrint("Heap: %s %d\n", strerror(errno), pathlen);
1185 snprintf(path, pathlen, "%s%s", SCRIPT_PORT_PATH, ent->d_name);
1187 item = malloc(sizeof(*item));
1189 ErrPrint("Heap: %s\n", strerror(errno));
1195 DbgPrint("Open SCRIPT PORT: %s\n", path);
1196 item->handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW | RTLD_DEEPBIND);
1198 if (!item->handle) {
1199 ErrPrint("Error: %s\n", dlerror());
1205 item->magic_id = dlsym(item->handle, "script_magic_id");
1206 if (!item->magic_id)
1209 DbgPrint("SCRIPT PORT magic id: %s\n", item->magic_id());
1211 item->update_color = dlsym(item->handle, "script_update_color");
1212 if (!item->update_color)
1215 item->update_text = dlsym(item->handle, "script_update_text");
1216 if (!item->update_text)
1219 item->update_image = dlsym(item->handle, "script_update_image");
1220 if (!item->update_image)
1223 item->update_script = dlsym(item->handle, "script_update_script");
1224 if (!item->update_script)
1227 item->update_signal = dlsym(item->handle, "script_update_signal");
1228 if (!item->update_signal)
1231 item->update_drag = dlsym(item->handle, "script_update_drag");
1232 if (!item->update_drag)
1235 item->update_size = dlsym(item->handle, "script_update_size");
1236 if (!item->update_size)
1239 item->update_category = dlsym(item->handle, "script_update_category");
1240 if (!item->update_category)
1243 item->create = dlsym(item->handle, "script_create");
1247 item->destroy = dlsym(item->handle, "script_destroy");
1251 item->load = dlsym(item->handle, "script_load");
1255 item->unload = dlsym(item->handle, "script_unload");
1259 item->init = dlsym(item->handle, "script_init");
1263 item->fini = dlsym(item->handle, "script_fini");
1267 if (item->init() < 0) {
1268 ErrPrint("Failed to initialize script engine\n");
1272 s_info.script_port_list = eina_list_append(s_info.script_port_list, item);
1279 ErrPrint("Error: %s\n", dlerror());
1280 dlclose(item->handle);
1286 HAPI int script_fini(void)
1288 struct script_port *item;
1290 * \TODO: Release all handles
1292 EINA_LIST_FREE(s_info.script_port_list, item) {
1294 dlclose(item->handle);
1301 HAPI int script_handler_update_pointer(struct script_info *info, double x, double y, int down)