Sync to I97773092923a0223505ede7be707c67cedc0832f
[apps/livebox/livebox-edje.git] / src / script_port.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
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
7  *
8  * http://www.tizenopensource.org/license
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <libgen.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <ctype.h>
22
23 #include <Elementary.h>
24 #include <Evas.h>
25 #include <Edje.h>
26 #include <Eina.h>
27 #include <Ecore.h>
28 #include <Ecore_Evas.h>
29 #include <Eet.h>
30 #include <Ecore_X.h>
31
32 #include <dlog.h>
33 #include <debug.h>
34 #include <vconf.h>
35 #include <livebox-errno.h>
36
37 #include "script_port.h"
38
39 #define TEXT_CLASS      "tizen"
40 #define BASE_WIDTH      720.0f
41
42 #define PUBLIC __attribute__((visibility("default")))
43
44 struct image_option {
45         int orient;
46         int aspect;
47         enum {
48                 FILL_DISABLE,
49                 FILL_IN_SIZE,
50                 FILL_OVER_SIZE,
51         } fill;
52
53         int width;
54         int height;
55 };
56
57 struct info {
58         char *file;
59         char *group;
60         char *category;
61         int w;
62         int h;
63
64         Evas *e;
65
66         Eina_List *obj_list;
67 };
68
69 struct child {
70         Evas_Object *obj;
71         char *part;
72 };
73
74 struct obj_info {
75         char *id;
76         Eina_List *children;
77         Evas_Object *win;
78 };
79
80 static inline double scale_get(void)
81 {
82         int width;
83         int height;
84         ecore_x_window_size_get(0, &width, &height);
85         return (double)width / BASE_WIDTH;
86 }
87
88 static inline Evas_Object *find_edje(struct info *handle, const char *id)
89 {
90         Eina_List *l;
91         Evas_Object *edje;
92         struct obj_info *obj_info;
93
94         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
95                 obj_info = evas_object_data_get(edje, "obj_info");
96                 if (!obj_info) {
97                         ErrPrint("Object info is not valid\n");
98                         continue;
99                 }
100
101                 if (!id) {
102                         if (!obj_info->id)
103                                 return edje;
104
105                         continue;
106                 } else if (!obj_info->id) {
107                         continue;
108                 }
109
110                 if (!strcmp(obj_info->id, id))
111                         return edje;
112         }
113
114         DbgPrint("EDJE[%s] is not found\n", id);
115         return NULL;
116 }
117
118 PUBLIC const char *script_magic_id(void)
119 {
120         return "edje";
121 }
122
123 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
124 {
125         struct info *handle = h;
126         Evas_Object *edje;
127         int r[3], g[3], b[3], a[3];
128         int ret;
129
130         edje = find_edje(handle, id);
131         if (!edje)
132                 return LB_STATUS_ERROR_NOT_EXIST;
133
134         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
135                                         r, g, b, a,                     /* OBJECT */
136                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
137                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
138         if (ret != 12) {
139                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
140                 return LB_STATUS_ERROR_INVALID;
141         }
142
143         ret = edje_object_color_class_set(elm_layout_edje_get(edje), part,
144                                 r[0], g[0], b[0], a[0], /* OBJECT */
145                                 r[1], g[1], b[1], a[1], /* OUTLINE */
146                                 r[2], g[2], b[2], a[2]); /* SHADOW */
147
148         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
149         return LB_STATUS_SUCCESS;
150 }
151
152 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
153 {
154         struct info *handle = h;
155         Evas_Object *edje;
156
157         edje = find_edje(handle, id);
158         if (!edje)
159                 return LB_STATUS_ERROR_NOT_EXIST;
160
161         elm_object_part_text_set(edje, part, text);
162         return LB_STATUS_SUCCESS;
163 }
164
165 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
166 {
167         while (len > 0 && *value == ' ') {
168                 value++;
169                 len--;
170         }
171
172         if (len < 4)
173                 return;
174
175         img_opt->aspect = !strncasecmp(value, "true", 4);
176         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
177 }
178
179 static void parse_orient(struct image_option *img_opt, const char *value, int len)
180 {
181         while (len > 0 && *value == ' ') {
182                 value++;
183                 len--;
184         }
185
186         if (len < 4)
187                 return;
188
189         img_opt->orient = !strncasecmp(value, "true", 4);
190         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->aspect, value);
191 }
192
193 static void parse_size(struct image_option *img_opt, const char *value, int len)
194 {
195         int width;
196         int height;
197         char *buf;
198
199         while (len > 0 && *value == ' ') {
200                 value++;
201                 len--;
202         }
203
204         buf = strndup(value, len);
205         if (!buf) {
206                 ErrPrint("Heap: %s\n", strerror(errno));
207                 return;
208         }
209
210         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
211                 img_opt->width = width;
212                 img_opt->height = height;
213                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
214         } else {
215                 DbgPrint("Invalid size tag[%s]\n", buf);
216         }
217
218         free(buf);
219 }
220
221 static void parse_fill(struct image_option *img_opt, const char *value, int len)
222 {
223         while (len > 0 && *value == ' ') {
224                 value++;
225                 len--;
226         }
227
228         if (!strncasecmp(value, "in-size", len))
229                 img_opt->fill = FILL_IN_SIZE;
230         else if (!strncasecmp(value, "over-size", len))
231                 img_opt->fill = FILL_OVER_SIZE;
232         else
233                 img_opt->fill = FILL_DISABLE;
234
235         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
236 }
237
238 static inline void parse_image_option(const char *option, struct image_option *img_opt)
239 {
240         const char *ptr;
241         const char *cmd;
242         const char *value;
243         struct {
244                 const char *cmd;
245                 void (*handler)(struct image_option *img_opt, const char *value, int len);
246         } cmd_list[] = {
247                 {
248                         .cmd = "aspect", /* Keep the aspect ratio */
249                         .handler = parse_aspect,
250                 },
251                 {
252                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
253                         .handler = parse_orient,
254                 },
255                 {
256                         .cmd = "fill", /* Fill the image to its container */
257                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
258                 },
259                 {
260                         .cmd = "size",
261                         .handler = parse_size,
262                 },
263         };
264         enum {
265                 STATE_START,
266                 STATE_TOKEN,
267                 STATE_DATA,
268                 STATE_IGNORE,
269                 STATE_ERROR,
270                 STATE_END,
271         } state;
272         int idx;
273         int tag;
274
275         if (!option || !*option)
276                 return;
277
278         state = STATE_START;
279         /*!
280          * \note
281          * GCC 4.7 warnings uninitialized idx and tag value.
282          * But it will be initialized by the state machine. :(
283          * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
284          */
285         idx = 0;
286         tag = 0;
287         cmd = NULL;
288         value = NULL;
289
290         for (ptr = option; state != STATE_END; ptr++) {
291                 switch (state) {
292                 case STATE_START:
293                         if (*ptr == '\0') {
294                                 state = STATE_END;
295                                 continue;
296                         }
297
298                         if (isalpha(*ptr)) {
299                                 state = STATE_TOKEN;
300                                 ptr--;
301                         }
302                         tag = 0;
303                         idx = 0;
304
305                         cmd = cmd_list[tag].cmd;
306                         break;
307                 case STATE_IGNORE:
308                         if (*ptr == '=') {
309                                 state = STATE_DATA;
310                                 value = ptr;
311                         } else if (*ptr == '\0') {
312                                 state = STATE_END;
313                         }
314                         break;
315                 case STATE_TOKEN:
316                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
317                                 if (*ptr == '=') {
318                                         value = ptr;
319                                         state = STATE_DATA;
320                                 } else {
321                                         state = STATE_IGNORE;
322                                 }
323                                 idx = 0;
324                         } else if (*ptr == '\0') {
325                                 state = STATE_END;
326                         } else if (cmd[idx] == *ptr) {
327                                 idx++;
328                         } else {
329                                 ptr -= (idx + 1);
330
331                                 tag++;
332                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
333                                         tag = 0;
334                                         state = STATE_ERROR;
335                                 } else {
336                                         cmd = cmd_list[tag].cmd;
337                                 }
338                                 idx = 0;
339                         }
340                         break;
341                 case STATE_DATA:
342                         if (*ptr == ';' || *ptr == '\0') {
343                                 cmd_list[tag].handler(img_opt, value + 1, idx);
344                                 state = *ptr ? STATE_START : STATE_END;
345                         } else {
346                                 idx++;
347                         }
348                         break;
349                 case STATE_ERROR:
350                         if (*ptr == ';')
351                                 state = STATE_START;
352                         else if (*ptr == '\0')
353                                 state = STATE_END;
354                         break;
355                 default:
356                         break;
357                 }
358         }
359 }
360
361 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
362 {
363         struct info *handle = _h;
364         Evas_Load_Error err;
365         Evas_Object *edje;
366         Evas_Object *img;
367         Evas_Coord w, h;
368         struct obj_info *obj_info;
369         struct child *child;
370         struct image_option img_opt = {
371                 .aspect = 0,
372                 .orient = 0,
373                 .fill = FILL_DISABLE,
374                 .width = -1,
375                 .height = -1,
376         };
377
378         edje = find_edje(handle, id);
379         if (!edje) {
380                 ErrPrint("No such object: %s\n", id);
381                 return LB_STATUS_ERROR_NOT_EXIST;
382         }
383
384         obj_info = evas_object_data_get(edje, "obj_info");
385         if (!obj_info) {
386                 ErrPrint("Object info is not available\n");
387                 return LB_STATUS_ERROR_FAULT;
388         }
389
390         img = elm_object_part_content_unset(edje, part);
391         if (img) {
392                 Eina_List *l;
393                 Eina_List *n;
394
395                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
396                         if (child->obj != img)
397                                 continue;
398
399                         obj_info->children = eina_list_remove(obj_info->children, child);
400                         free(child->part);
401                         free(child);
402                         break;
403                 }
404
405                 DbgPrint("delete object %s %p\n", part, img);
406                 evas_object_del(img);
407         }
408
409         if (!path || !strlen(path) || access(path, R_OK) != 0) {
410                 DbgPrint("SKIP - Path: [%s]\n", path);
411                 return LB_STATUS_SUCCESS;
412         }
413
414         child = malloc(sizeof(*child));
415         if (!child) {
416                 ErrPrint("Heap: %s\n", strerror(errno));
417                 return LB_STATUS_ERROR_MEMORY;
418         }
419
420         child->part = strdup(part);
421         if (!child->part) {
422                 ErrPrint("Heap: %s\n", strerror(errno));
423                 free(child);
424                 return LB_STATUS_ERROR_MEMORY;
425         }
426
427         img = evas_object_image_add(e);
428         if (!img) {
429                 ErrPrint("Failed to add an image object\n");
430                 free(child->part);
431                 free(child);
432                 return LB_STATUS_ERROR_FAULT;
433         }
434
435         evas_object_image_preload(img, EINA_FALSE);
436         parse_image_option(option, &img_opt);
437         evas_object_image_load_orientation_set(img, img_opt.orient);
438
439         evas_object_image_file_set(img, path, NULL);
440         err = evas_object_image_load_error_get(img);
441         if (err != EVAS_LOAD_ERROR_NONE) {
442                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
443                 evas_object_del(img);
444                 free(child->part);
445                 free(child);
446                 return LB_STATUS_ERROR_IO;
447         }
448
449         evas_object_image_size_get(img, &w, &h);
450         if (img_opt.aspect) {
451                 if (img_opt.fill == FILL_OVER_SIZE) {
452                         Evas_Coord part_w;
453                         Evas_Coord part_h;
454
455                         if (img_opt.width >= 0 && img_opt.height >= 0) {
456                                 part_w = img_opt.width * scale_get();
457                                 part_h = img_opt.height * scale_get();
458                         } else {
459                                 part_w = 0;
460                                 part_h = 0;
461                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
462                         }
463                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
464
465                         if (part_w > w || part_h > h) {
466                                 double fw;
467                                 double fh;
468
469                                 fw = (double)part_w / (double)w;
470                                 fh = (double)part_h / (double)h;
471
472                                 if (fw > fh) {
473                                         w = part_w;
474                                         h = (double)h * fw;
475                                 } else {
476                                         h = part_h;
477                                         w = (double)w * fh;
478                                 }
479                         }
480                         DbgPrint("Size: %dx%d\n", w, h);
481
482                         evas_object_image_load_size_set(img, w, h);
483                         evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
484                         evas_object_image_fill_set(img, 0, 0, part_w, part_h);
485                         evas_object_image_reload(img);
486                 } else {
487                         evas_object_image_fill_set(img, 0, 0, w, h);
488                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
489                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
490                 }
491         } else {
492                 if (img_opt.width >= 0 && img_opt.height >= 0) {
493                         w = img_opt.width;
494                         h = img_opt.height;
495                         DbgPrint("Using given image size: %dx%d\n", w, h);
496                 }
497
498                 evas_object_image_fill_set(img, 0, 0, w, h);
499                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
500                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
501         }
502
503         /*!
504          * \note
505          * object will be shown by below statement automatically
506          */
507         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
508         child->obj = img;
509         elm_object_part_content_set(edje, part, img);
510         obj_info->children = eina_list_append(obj_info->children, child);
511
512         return LB_STATUS_SUCCESS;
513 }
514
515 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
516 {
517         struct info *handle = data;
518         Evas_Coord w;
519         Evas_Coord h;
520         Evas_Coord px = 0;
521         Evas_Coord py = 0;
522         Evas_Coord pw = 0;
523         Evas_Coord ph = 0;
524         double sx;
525         double sy;
526         double ex;
527         double ey;
528
529         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
530         edje_object_part_geometry_get(elm_layout_edje_get(obj), source, &px, &py, &pw, &ph);
531
532         sx = ex = 0.0f;
533         if (w) {
534                 sx = (double)px / (double)w;
535                 ex = (double)(px + pw) / (double)w;
536         }
537
538         sy = ey = 0.0f;
539         if (h) {
540                 sy = (double)py / (double)h;
541                 ey = (double)(py + ph) / (double)h;
542         }
543
544         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
545         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
546 }
547
548 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
549 {
550         struct info *handle = _info;
551         struct obj_info *obj_info;
552         struct child *child;
553
554         handle->obj_list = eina_list_remove(handle->obj_list, obj);
555
556         obj_info = evas_object_data_del(obj, "obj_info");
557         if (!obj_info) {
558                 ErrPrint("Object info is not valid\n");
559                 return;
560         }
561
562         DbgPrint("delete object %s %p\n", obj_info->id, obj);
563
564         elm_object_signal_callback_del(obj, "*", "*", script_signal_cb);
565
566         EINA_LIST_FREE(obj_info->children, child) {
567                 DbgPrint("delete object %s %p\n", child->part, child->obj);
568                 if (child->obj)
569                         evas_object_del(child->obj);
570                 free(child->part);
571                 free(child);
572         }
573
574         free(obj_info->id);
575         free(obj_info);
576 }
577
578 PUBLIC int script_update_script(void *h, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group)
579 {
580         struct info *handle = h;
581         Evas_Object *edje;
582         Evas_Object *obj;
583         struct obj_info *obj_info;
584         struct child *child;
585
586         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
587
588         edje = find_edje(handle, src_id);
589         if (!edje) {
590                 ErrPrint("Edje is not exists\n");
591                 return LB_STATUS_ERROR_NOT_EXIST;
592         }
593
594         obj_info = evas_object_data_get(edje, "obj_info");
595         if (!obj_info) {
596                 ErrPrint("Object info is not valid\n");
597                 return LB_STATUS_ERROR_INVALID;
598         }
599
600         obj = elm_object_part_content_unset(edje, part);
601         if (obj) {
602                 Eina_List *l;
603                 Eina_List *n;
604
605                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
606                         if (child->obj != obj)
607                                 continue;
608
609                         obj_info->children = eina_list_remove(obj_info->children, child);
610                         free(child->part);
611                         free(child);
612                         break;
613                 }
614
615                 DbgPrint("delete object %s %p\n", part, obj);
616                 evas_object_del(obj);
617         }
618
619         if (!path || !strlen(path) || access(path, R_OK) != 0) {
620                 DbgPrint("SKIP - Path: [%s]\n", path);
621                 return LB_STATUS_SUCCESS;
622         }
623
624         obj = elm_layout_add(edje);
625         if (!obj) {
626                 ErrPrint("Failed to add a new edje object\n");
627                 return LB_STATUS_ERROR_FAULT;
628         }
629
630         if (!elm_layout_file_set(obj, path, group)) {
631                 int err;
632                 const char *errmsg;
633
634                 err = edje_object_load_error_get(elm_layout_edje_get(obj));
635                 errmsg = edje_load_error_str(err);
636                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
637                 evas_object_del(obj);
638                 return LB_STATUS_ERROR_IO;
639         }
640
641         evas_object_show(obj);
642
643         obj_info = calloc(1, sizeof(*obj_info));
644         if (!obj_info) {
645                 ErrPrint("Failed to add a obj_info\n");
646                 evas_object_del(obj);
647                 return LB_STATUS_ERROR_MEMORY;
648         }
649
650         obj_info->id = strdup(target_id);
651         if (!obj_info->id) {
652                 ErrPrint("Failed to add a obj_info\n");
653                 free(obj_info);
654                 evas_object_del(obj);
655                 return LB_STATUS_ERROR_MEMORY;
656         }
657
658         child = malloc(sizeof(*child));
659         if (!child) {
660                 ErrPrint("Error: %s\n", strerror(errno));
661                 free(obj_info->id);
662                 free(obj_info);
663                 evas_object_del(obj);
664                 return LB_STATUS_ERROR_MEMORY;
665         }
666
667         child->part = strdup(part);
668         if (!child->part) {
669                 ErrPrint("Error: %s\n", strerror(errno));
670                 free(child);
671                 free(obj_info->id);
672                 free(obj_info);
673                 evas_object_del(obj);
674                 return LB_STATUS_ERROR_MEMORY;
675         }
676
677         child->obj = obj;
678
679         evas_object_data_set(obj, "obj_info", obj_info);
680         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
681         elm_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
682         handle->obj_list = eina_list_append(handle->obj_list, obj);
683
684         DbgPrint("%s part swallow edje %p\n", part, obj);
685         elm_object_part_content_set(edje, part, obj);
686         obj_info = evas_object_data_get(edje, "obj_info");
687         obj_info->children = eina_list_append(obj_info->children, child);
688         return LB_STATUS_SUCCESS;
689 }
690
691 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
692 {
693         struct info *handle = h;
694         Evas_Object *edje;
695
696         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
697
698         edje = find_edje(handle, id);
699         if (!edje)
700                 return LB_STATUS_ERROR_NOT_EXIST;
701
702         elm_object_signal_emit(edje, signal, part);
703         return LB_STATUS_SUCCESS;
704 }
705
706 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
707 {
708         struct info *handle = h;
709         Evas_Object *edje;
710
711         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
712
713         edje = find_edje(handle, id);
714         if (!edje)
715                 return LB_STATUS_ERROR_NOT_EXIST;
716
717         edje_object_part_drag_value_set(elm_layout_edje_get(edje), part, x, y);
718         return LB_STATUS_SUCCESS;
719 }
720
721 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
722 {
723         struct info *handle = han;
724         Evas_Object *edje;
725
726         edje = find_edje(handle, id);
727         if (!edje)
728                 return LB_STATUS_ERROR_NOT_EXIST;
729
730         if (!id) {
731                 handle->w = w;
732                 handle->h = h;
733         }
734
735         DbgPrint("Resize object to %dx%d\n", w, h);
736         evas_object_resize(edje, w, h);
737         return LB_STATUS_SUCCESS;
738 }
739
740 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
741 {
742         struct info *handle = h;
743
744         DbgPrint("id[%s], category[%s]\n", id, category);
745
746         if (handle->category) {
747                 free(handle->category);
748                 handle->category = NULL;
749         }
750
751         if (!category)
752                 return LB_STATUS_SUCCESS;
753
754         handle->category = strdup(category);
755         if (!handle->category) {
756                 ErrPrint("Error: %s\n", strerror(errno));
757                 return LB_STATUS_ERROR_MEMORY;
758         }
759
760         return LB_STATUS_SUCCESS;
761 }
762
763 PUBLIC void *script_create(const char *file, const char *group)
764 {
765         struct info *handle;
766
767         DbgPrint("file[%s], group[%s]\n", file, group);
768
769         handle = calloc(1, sizeof(*handle));
770         if (!handle) {
771                 ErrPrint("Error: %s\n", strerror(errno));
772                 return NULL;
773         }
774
775         handle->file = strdup(file);
776         if (!handle->file) {
777                 ErrPrint("Error: %s\n", strerror(errno));
778                 free(handle);
779                 return NULL;
780         }
781
782         handle->group = strdup(group);
783         if (!handle->group) {
784                 ErrPrint("Error: %s\n", strerror(errno));
785                 free(handle->file);
786                 free(handle);
787                 return NULL;
788         }
789
790         return handle;
791 }
792
793 PUBLIC int script_destroy(void *_handle)
794 {
795         struct info *handle;
796         Evas_Object *edje;
797
798         handle = _handle;
799
800         edje = eina_list_nth(handle->obj_list, 0);
801         if (edje)
802                 evas_object_del(edje);
803
804         free(handle->category);
805         free(handle->file);
806         free(handle->group);
807         free(handle);
808         return LB_STATUS_SUCCESS;
809 }
810
811 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
812 {
813         struct info *handle;
814         Evas_Object *edje;
815         struct obj_info *obj_info;
816
817         handle = _handle;
818
819         obj_info = calloc(1, sizeof(*obj_info));
820         if (!obj_info) {
821                 ErrPrint("Heap: %s\n", strerror(errno));
822                 return LB_STATUS_ERROR_MEMORY;
823         }
824
825         obj_info->win = evas_object_rectangle_add(e);
826         if (!obj_info->win) {
827                 free(obj_info);
828                 return LB_STATUS_ERROR_FAULT;
829         }
830
831         edje = elm_layout_add(obj_info->win);
832         if (!edje) {
833                 ErrPrint("Failed to create an edje object\n");
834                 evas_object_del(obj_info->win);
835                 free(obj_info);
836                 return LB_STATUS_ERROR_FAULT;
837         }
838
839         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
840         if (!elm_layout_file_set(edje, handle->file, handle->group)) {
841                 int err;
842                 const char *errmsg;
843
844                 err = edje_object_load_error_get(elm_layout_edje_get(edje));
845                 errmsg = edje_load_error_str(err);
846                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
847                 evas_object_del(edje);
848                 evas_object_del(obj_info->win);
849                 free(obj_info);
850                 return LB_STATUS_ERROR_IO;
851         }
852
853         handle->e = e;
854         handle->w = w;
855         handle->h = h;
856
857         elm_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
858         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
859         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
860         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
861         evas_object_resize(edje, handle->w, handle->h);
862         evas_object_show(edje);
863         evas_object_data_set(edje, "obj_info", obj_info);
864
865         handle->obj_list = eina_list_append(handle->obj_list, edje);
866         return LB_STATUS_SUCCESS;
867 }
868
869 PUBLIC int script_unload(void *_handle, Evas *e)
870 {
871         struct info *handle;
872         Evas_Object *edje;
873
874         handle = _handle;
875
876         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
877         edje = eina_list_nth(handle->obj_list, 0);
878         if (edje)
879                 evas_object_del(edje);
880         handle->e = NULL;
881         return LB_STATUS_SUCCESS;
882 }
883
884 PUBLIC int script_init(void)
885 {
886         char *argv[] = {
887                 "livebox.edje",
888                 NULL,
889         };
890         /* ecore is already initialized */
891         elm_init(1, argv);
892         elm_config_scale_set(scale_get());
893
894         return LB_STATUS_SUCCESS;
895 }
896
897 PUBLIC int script_fini(void)
898 {
899         elm_shutdown();
900         return LB_STATUS_SUCCESS;
901 }
902
903 /* End of a file */