Initialize the project.
[apps/livebox/data-provider-master.git] / src / script_handler.c
1 /*
2  * Copyright 2012  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 <errno.h>
19 #include <stdlib.h> /* free */
20 #include <ctype.h>
21 #include <dlfcn.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <string.h>
25
26 #include <Ecore_Evas.h>
27 #include <Ecore.h>
28 #include <Evas.h>
29
30 #include <dlog.h>
31 #include <packet.h>
32
33 #include "slave_life.h"
34 #include "slave_rpc.h"
35 #include "client_life.h"
36 #include "package.h"
37 #include "instance.h"
38 #include "buffer_handler.h"
39 #include "script_handler.h"
40 #include "fb.h"
41 #include "debug.h"
42 #include "conf.h"
43 #include "util.h"
44
45 #define TYPE_TEXT "text"
46 #define TYPE_IMAGE "image"
47 #define TYPE_EDJE "script"
48 #define TYPE_SIGNAL "signal"
49 #define TYPE_INFO "info"
50 #define TYPE_DRAG "drag"
51 #define INFO_SIZE "size"
52 #define INFO_CATEGORY "category"
53 #define ADDEND 256
54
55 int errno;
56
57 static struct info {
58         Eina_List *script_port_list;
59         enum buffer_type env_buf_type;
60 } s_info = {
61         .script_port_list = NULL,
62         .env_buf_type = BUFFER_TYPE_FILE,
63 };
64
65 struct script_port {
66         void *handle;
67
68         const char *(*magic_id)(void);
69         int (*update_text)(void *handle, Evas *e, const char *id, const char *part, const char *text);
70         int (*update_image)(void *handle, Evas *e, const char *id, const char *part, const char *path);
71         int (*update_script)(void *handle, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group);
72         int (*update_signal)(void *handle, Evas *e, const char *id, const char *part, const char *signal);
73         int (*update_drag)(void *handle, Evas *e, const char *id, const char *part, double x, double y);
74         int (*update_size)(void *handle, Evas *e, const char *id, int w, int h);
75         int (*update_category)(void *handle, Evas *e, const char *id, const char *category);
76
77         void *(*create)(const char *file, const char *group);
78         int (*destroy)(void *handle);
79
80         int (*load)(void *handle, Evas *e, int w, int h);
81         int (*unload)(void *handle, Evas *e);
82
83         int (*init)(void);
84         int (*fini)(void);
85 };
86
87 struct block {
88         char *type;
89         int type_len;
90
91         char *part;
92         int part_len;
93
94         char *data;
95         int data_len;
96
97         char *file;
98         int file_len;
99
100         char *group;
101         int group_len;
102
103         char *id;
104         int id_len;
105
106         char *target_id;
107         int target_len;
108 };
109
110 struct script_info {
111         Ecore_Evas *ee;
112         struct fb_info *fb;
113         struct inst_info *inst;
114         int loaded;
115
116         int w;
117         int h;
118
119         double x;
120         double y;
121         int down;
122
123         struct script_port *port;
124         void *port_data;
125 };
126
127 static inline struct script_port *find_port(const char *magic_id)
128 {
129         Eina_List *l;
130         struct script_port *item;
131
132         EINA_LIST_FOREACH(s_info.script_port_list, l, item) {
133                 if (!strcmp(item->magic_id(), magic_id))
134                         return item;
135         }
136
137         return NULL;
138 }
139
140 static void render_pre_cb(void *data, Evas *e, void *event_info)
141 {
142         struct inst_info *inst = data;
143         struct script_info *info;
144
145         if (instance_state(inst) != INST_ACTIVATED) {
146                 DbgPrint("Render pre invoked but instance is not activated\n");
147                 return;
148         }
149
150         info = instance_lb_script(inst);
151         if (info && script_handler_evas(info) == e) {
152                 return;
153         }
154
155         info = instance_pd_script(inst);
156         if (info && script_handler_evas(info) == e) {
157                 return;
158         }
159
160         ErrPrint("Failed to do sync\n");
161         return;
162 }
163
164 static void render_post_cb(void *data, Evas *e, void *event_info)
165 {
166         struct inst_info *inst;
167         struct script_info *info;
168
169         inst = data;
170
171         if (instance_state(inst) != INST_ACTIVATED) {
172                 DbgPrint("Render post invoked but instance is not activated\n");
173                 return;
174         }
175
176         info = instance_lb_script(inst);
177         if (info && script_handler_evas(info) == e) {
178                 fb_sync(script_handler_fb(info));
179                 instance_lb_updated_by_instance(inst);
180                 return;
181         }
182
183         info = instance_pd_script(inst);
184         if (info && script_handler_evas(info) == e) {
185                 fb_sync(script_handler_fb(info));
186                 instance_pd_updated_by_instance(inst, NULL);
187                 return;
188         }
189
190         ErrPrint("Failed to sync\n");
191         return;
192 }
193
194 /*!
195  * \NOTE
196  * Exported API
197  */
198 int script_signal_emit(Evas *e, const char *part, const char *signal, double sx, double sy, double ex, double ey)
199 {
200         Ecore_Evas *ee;
201         struct script_info *info;
202         int ret;
203
204         ee = ecore_evas_ecore_evas_get(e);
205         if (!ee) {
206                 ErrPrint("Evas has no Ecore_Evas\n");
207                 return -EINVAL;
208         }
209
210         info = ecore_evas_data_get(ee, "script,info");
211         if (!info) {
212                 ErrPrint("ecore_evas doesn't carry info data\n");
213                 return -EINVAL;
214         }
215
216         if (!signal || strlen(signal) == 0)
217                 signal = "";
218
219         if (!part || strlen(part) == 0)
220                 part = "";
221
222         ret = instance_signal_emit(info->inst, signal, part, sx, sy, ex, ey, info->x, info->y, info->down);
223         return ret;
224 }
225
226 HAPI int script_handler_load(struct script_info *info, int is_pd)
227 {
228         int ret;
229         Evas *e;
230
231         if (!info || !info->port) {
232                 ErrPrint("Script handler is not created\n");
233                 return -EINVAL;
234         }
235
236         if (info->loaded > 0) {
237                 info->loaded++;
238                 return 0;
239         }
240
241         ret = fb_create_buffer(info->fb);
242         if (ret < 0)
243                 return ret;
244
245         info->ee = fb_canvas(info->fb);
246         if (!info->ee) {
247                 ErrPrint("Failed to get canvas\n");
248                 fb_destroy_buffer(info->fb);
249                 return -EFAULT;
250         }
251
252         ecore_evas_data_set(info->ee, "script,info", info);
253
254         e = script_handler_evas(info);
255         if (e) {
256                 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb, info->inst);
257                 evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, render_post_cb, info->inst);
258                 if (info->port->load(info->port_data, e, info->w, info->h) < 0) {
259                         ErrPrint("Failed to add new script object\n");
260                         evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
261                         evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
262                         fb_destroy_buffer(info->fb);
263                         return -EFAULT;
264                 }
265                 info->loaded = 1;
266         } else {
267                 ErrPrint("Evas: (nil) %dx%d\n", info->w, info->h);
268         }
269
270         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
271         ecore_evas_resize(info->ee, info->w, info->h);
272         ecore_evas_show(info->ee);
273         ecore_evas_activate(info->ee);
274         fb_sync(info->fb);
275
276         if (e)
277                 script_signal_emit(e, util_uri_to_path(instance_id(info->inst)),
278                                         is_pd ? "pd,show" : "lb,show", 0.0f, 0.0f, 0.0f, 0.0f);
279         return 0;
280 }
281
282 HAPI int script_handler_unload(struct script_info *info, int is_pd)
283 {
284         Ecore_Evas *ee;
285         Evas *e;
286
287         if (!info || !info->port)
288                 return -EINVAL;
289
290         info->loaded--;
291         if (info->loaded > 0)
292                 return 0;
293
294         if (info->loaded < 0) {
295                 info->loaded = 0;
296                 return 0;
297         }
298
299         e = script_handler_evas(info);
300         if (e) {
301                 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);
302                 if (info->port->unload(info->port_data, e) < 0)
303                         ErrPrint("Failed to unload script object. but go ahead\n");
304                 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_POST, render_post_cb);
305                 evas_event_callback_del(e, EVAS_CALLBACK_RENDER_PRE, render_pre_cb);
306         } else {
307                 ErrPrint("Evas(nil): Unload script\n");
308         }
309
310         ee = fb_canvas(info->fb);
311         if (ee)
312                 ecore_evas_data_set(ee, "script,info", NULL);
313
314         fb_destroy_buffer(info->fb);
315         return 0;
316 }
317
318 HAPI struct script_info *script_handler_create(struct inst_info *inst, const char *file, const char *group, int w, int h)
319 {
320         struct script_info *info;
321
322         DbgPrint("Create script: %s (%s)\n", file, group);
323
324         if (!file)
325                 return NULL;
326
327         info = calloc(1, sizeof(*info));
328         if (!info) {
329                 ErrPrint("Heap: %s\n", strerror(errno));
330                 return NULL;
331         }
332
333         info->fb = fb_create(inst, w, h, s_info.env_buf_type);
334         if (!info->fb) {
335                 ErrPrint("Failed to create a FB (%dx%d)\n", w, h);
336                 DbgFree(info);
337                 return NULL;
338         }
339
340         info->inst = inst;
341         info->port = find_port(package_script(instance_package(inst)));
342         if (!info->port) {
343                 ErrPrint("Failed to find a proper port for [%s]%s\n",
344                                         instance_package(inst), package_script(instance_package(inst)));
345                 fb_destroy(info->fb);
346                 DbgFree(info);
347                 return NULL;
348         }
349
350         DbgPrint("Update info [%dx%d]\n", w, h);
351         info->w = w;
352         info->h = h;
353
354         info->port_data = info->port->create(file, group);
355         if (!info->port_data) {
356                 ErrPrint("Failed to create a port (%s - %s)\n", file, group);
357                 fb_destroy(info->fb);
358                 DbgFree(info);
359                 return NULL;
360         }
361
362         return info;
363 }
364
365 HAPI int script_handler_destroy(struct script_info *info)
366 {
367         if (!info || !info->port) {
368                 ErrPrint("port is not valid\n");
369                 return -EINVAL;
370         }
371
372         if (info->loaded != 0) {
373                 ErrPrint("Script handler is not unloaded\n");
374                 return -EINVAL;
375         }
376
377         if (info->port->destroy(info->port_data) < 0)
378                 ErrPrint("Failed to destroy port, but go ahead\n");
379
380         fb_destroy(info->fb);
381         DbgFree(info);
382         return 0;
383 }
384
385 HAPI int script_handler_is_loaded(struct script_info *info)
386 {
387         return info ? info->loaded > 0 : 0;
388 }
389
390 HAPI struct fb_info *script_handler_fb(struct script_info *info)
391 {
392         return info ? info->fb : NULL;
393 }
394
395 HAPI void *script_handler_evas(struct script_info *info)
396 {
397         if (!info)
398                 return NULL;
399
400         if (!info->ee)
401                 return NULL;
402
403         return ecore_evas_get(info->ee);
404 }
405
406 static int update_script_text(struct inst_info *inst, struct block *block, int is_pd)
407 {
408         struct script_info *info;
409         Evas *e;
410
411         if (!block || !block->part || !block->data) {
412                 ErrPrint("Block or part or data is not valid\n");
413                 return -EINVAL;
414         }
415
416         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
417         if (!info) {
418                 ErrPrint("info is NIL\n");
419                 return -EFAULT;
420         }
421
422         if (!info->port) {
423                 ErrPrint("info->port is NIL\n");
424                 return -EINVAL;
425         }
426
427         e = script_handler_evas(info);
428         if (e)
429                 info->port->update_text(info->port_data, e, block->id, block->part, block->data);
430         else
431                 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
432         return 0;
433 }
434
435 static int update_script_image(struct inst_info *inst, struct block *block, int is_pd)
436 {
437         struct script_info *info;
438         Evas *e;
439
440         if (!block || !block->part) {
441                 ErrPrint("Block or part is not valid\n");
442                 return -EINVAL;
443         }
444
445         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
446         if (!info) {
447                 ErrPrint("info is NIL\n");
448                 return -EFAULT;
449         }
450
451         if (!info->port) {
452                 ErrPrint("info->port is NIL\n");
453                 return -EINVAL;
454         }
455
456         e = script_handler_evas(info);
457         if (e)
458                 info->port->update_image(info->port_data, e, block->id, block->part, block->data);
459         else
460                 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
461         return 0;
462 }
463
464 static int update_script_script(struct inst_info *inst, struct block *block, int is_pd)
465 {
466         struct script_info *info;
467         Evas *e;
468
469         if (!block || !block->part) {
470                 ErrPrint("Block or part is NIL\n");
471                 return -EINVAL;
472         }
473
474         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
475         if (!info) {
476                 ErrPrint("info is NIL\n");
477                 return -EFAULT;
478         }
479
480         if (!info->port) {
481                 ErrPrint("info->port is NIL\n");
482                 return -EINVAL;
483         }
484
485         e = script_handler_evas(info);
486         if (e)
487                 info->port->update_script(info->port_data, e, block->id, block->target_id, block->part, block->data, block->group);
488         else
489                 ErrPrint("Evas: (nil) id[%s] part[%s] data[%s] group[%s]\n",
490                                                 block->id, block->part, block->data, block->group);
491         return 0;
492 }
493
494 static int update_script_signal(struct inst_info *inst, struct block *block, int is_pd)
495 {
496         struct script_info *info;
497         Evas *e;
498
499         if (!block) {
500                 ErrPrint("block is NIL\n");
501                 return -EINVAL;
502         }
503
504         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
505         if (!info) {
506                 ErrPrint("info is NIL\n");
507                 return -EFAULT;
508         }
509
510         if (!info->port) {
511                 ErrPrint("info->port is NIL\n");
512                 return -EINVAL;
513         }
514
515         e = script_handler_evas(info);
516         if (e)
517                 info->port->update_signal(info->port_data, e, block->id, block->part, block->data);
518         else
519                 ErrPrint("Evas(nil) id[%s] part[%s] data[%s]\n", block->id, block->part, block->data);
520         return 0;
521 }
522
523 static int update_script_drag(struct inst_info *inst, struct block *block, int is_pd)
524 {
525         struct script_info *info;
526         double dx, dy;
527         Evas *e;
528
529         if (!block || !block->data || !block->part) {
530                 ErrPrint("block or block->data or block->part is NIL\n");
531                 return -EINVAL;
532         }
533
534         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
535         if (!info) {
536                 ErrPrint("info is NIL\n");
537                 return -EFAULT;
538         }
539
540         if (sscanf(block->data, "%lfx%lf", &dx, &dy) != 2) {
541                 ErrPrint("Invalid format of data (DRAG data [%s])\n", block->data);
542                 return -EINVAL;
543         }
544
545         if (!info->port) {
546                 ErrPrint("info->port is NIL\n");
547                 return -EINVAL;
548         }
549
550         e = script_handler_evas(info);
551         if (e)
552                 info->port->update_drag(info->port_data, e, block->id, block->part, dx, dy);
553         else
554                 ErrPrint("Evas(nil) id[%s] part[%s] %lfx%lf\n", block->id, block->part, dx, dy);
555         return 0;
556 }
557
558 HAPI int script_handler_resize(struct script_info *info, int w, int h)
559 {
560         if (!info) {
561         //|| (info->w == w && info->h == h)) {
562                 ErrPrint("info[%p] resize is not changed\n", info);
563                 return 0;
564         }
565
566         fb_resize(script_handler_fb(info), w, h);
567
568         if (info->port->update_size) {
569                 Evas *e;
570                 e = script_handler_evas(info);
571                 if (e)
572                         info->port->update_size(info->port_data, e, NULL , w, h);
573                 else
574                         ErrPrint("Evas(nil) resize to %dx%d\n", w, h);
575         }
576
577         info->w = w;
578         info->h = h;
579
580         return 0;
581 }
582
583 static int update_info(struct inst_info *inst, struct block *block, int is_pd)
584 {
585         struct script_info *info;
586
587         if (!block || !block->part || !block->data) {
588                 ErrPrint("block or block->part or block->data is NIL\n");
589                 return -EINVAL;
590         }
591
592         info = is_pd ? instance_pd_script(inst) : instance_lb_script(inst);
593         if (!info) {
594                 ErrPrint("info is NIL\n");
595                 return -EFAULT;
596         }
597
598         if (!info->port) {
599                 ErrPrint("info->port is NIL\n");
600                 return -EINVAL;
601         }
602
603         if (!strcasecmp(block->part, INFO_SIZE)) {
604                 Evas_Coord w, h;
605
606                 if (sscanf(block->data, "%dx%d", &w, &h) != 2) {
607                         ErrPrint("Invalid format for SIZE(%s)\n", block->data);
608                         return -EINVAL;
609                 }
610
611                 if (!block->id) {
612                         if (is_pd)
613                                 instance_set_pd_info(inst, w, h);
614                         else
615                                 instance_set_lb_info(inst, w, h, NO_CHANGE, CONTENT_NO_CHANGE, TITLE_NO_CHANGE);
616
617                         script_handler_resize(info, w, h);
618                 } else {
619                         Evas *e;
620                         e = script_handler_evas(info);
621                         if (e)
622                                 info->port->update_size(info->port_data, e, block->id, w, h);
623                         else
624                                 ErrPrint("Evas(nil): id[%s] %dx%d\n", block->id, w, h);
625                 }
626         } else if (!strcasecmp(block->part, INFO_CATEGORY)) {
627                 Evas *e;
628                 e = script_handler_evas(info);
629                 if (e)
630                         info->port->update_category(info->port_data, e, block->id, block->data);
631                 else
632                         ErrPrint("Evas(nil): id[%s] data[%s]\n", block->id, block->data);
633         }
634
635         return 0;
636 }
637
638 HAPI int script_handler_parse_desc(const char *pkgname, const char *id, const char *descfile, int is_pd)
639 {
640         struct inst_info *inst;
641         FILE *fp;
642         int ch;
643         int lineno;
644         enum state {
645                 UNKNOWN = 0x10,
646                 BLOCK_OPEN = 0x11,
647                 FIELD = 0x12,
648                 VALUE = 0x13,
649                 BLOCK_CLOSE = 0x14,
650
651                 VALUE_TYPE = 0x00,
652                 VALUE_PART = 0x01,
653                 VALUE_DATA = 0x02,
654                 VALUE_FILE = 0x03,
655                 VALUE_GROUP = 0x04,
656                 VALUE_ID = 0x05,
657                 VALUE_TARGET = 0x06,
658         };
659         const char *field_name[] = {
660                 "type",
661                 "part",
662                 "data",
663                 "file",
664                 "group",
665                 "id",
666                 "target",
667                 NULL
668         };
669         enum state state;
670         register int field_idx;
671         register int idx = 0;
672         register int i;
673         struct block *block;
674         struct {
675                 const char *type;
676                 int (*handler)(struct inst_info *inst, struct block *block, int is_pd);
677         } handlers[] = {
678                 {
679                         .type = TYPE_TEXT,
680                         .handler = update_script_text,
681                 },
682                 {
683                         .type = TYPE_IMAGE,
684                         .handler = update_script_image,
685                 },
686                 {
687                         .type = TYPE_EDJE,
688                         .handler = update_script_script,
689                 },
690                 {
691                         .type = TYPE_SIGNAL,
692                         .handler = update_script_signal,
693                 },
694                 {
695                         .type = TYPE_DRAG,
696                         .handler = update_script_drag,
697                 },
698                 {
699                         .type = TYPE_INFO,
700                         .handler = update_info,
701                 },
702                 {
703                         .type = NULL,
704                         .handler = NULL,
705                 },
706         };
707
708         block = NULL;
709         inst = package_find_instance_by_id(pkgname, id);
710         if (!inst) {
711                 ErrPrint("Instance is not exists\n");
712                 return -ENOENT;
713         }
714
715         fp = fopen(descfile, "rt");
716         if (!fp) {
717                 ErrPrint("Error: %s [%s]\n", descfile, strerror(errno));
718                 return -EIO;
719         }
720
721         state = UNKNOWN;
722         field_idx = 0;
723         lineno = 1;
724
725         block = NULL;
726         while (!feof(fp)) {
727                 ch = getc(fp);
728                 if (ch == '\n')
729                         lineno++;
730
731                 switch (state) {
732                 case UNKNOWN:
733                         if (ch == '{') {
734                                 state = BLOCK_OPEN;
735                                 break;
736                         }
737
738                         if (!isspace(ch) && ch != EOF) {
739                                 ErrPrint("%d: Syntax error: Desc is not started with '{' or space - (%c = 0x%x)\n", lineno, ch, ch);
740                                 fclose(fp);
741                                 return -EINVAL;
742                         }
743                         break;
744
745                 case BLOCK_OPEN:
746                         if (isblank(ch))
747                                 break;
748
749                         if (ch != '\n') {
750                                 ErrPrint("%d: Syntax error: New line must has to be started right after '{'\n", lineno);
751                                 goto errout;
752                         }
753
754                         block = calloc(1, sizeof(*block));
755                         if (!block) {
756                                 ErrPrint("Heap: %s\n", strerror(errno));
757                                 fclose(fp);
758                                 return -ENOMEM;
759                         }
760
761                         state = FIELD;
762                         idx = 0;
763                         field_idx = 0;
764                         break;
765
766                 case FIELD:
767                         if (isspace(ch))
768                                 break;
769
770                         if (ch == '}') {
771                                 state = BLOCK_CLOSE;
772                                 break;
773                         }
774
775                         if (ch == '=') {
776                                 if (field_name[field_idx][idx] != '\0') {
777                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
778                                         goto errout;
779                                 }
780
781                                 switch (field_idx) {
782                                 case 0:
783                                         state = VALUE_TYPE;
784                                         if (block->type) {
785                                                 DbgFree(block->type);
786                                                 block->type = NULL;
787                                                 block->type_len = 0;
788                                         }
789                                         idx = 0;
790                                         break;
791                                 case 1:
792                                         state = VALUE_PART;
793                                         if (block->part) {
794                                                 DbgFree(block->part);
795                                                 block->part = NULL;
796                                                 block->part_len = 0;
797                                         }
798                                         idx = 0;
799                                         break;
800                                 case 2:
801                                         state = VALUE_DATA;
802                                         if (block->data) {
803                                                 DbgFree(block->data);
804                                                 block->data = NULL;
805                                                 block->data_len = 0;
806                                         }
807                                         idx = 0;
808                                         break;
809                                 case 3:
810                                         state = VALUE_FILE;
811                                         if (block->file) {
812                                                 DbgFree(block->file);
813                                                 block->file = NULL;
814                                                 block->file_len = 0;
815                                         }
816                                         idx = 0;
817                                         break;
818                                 case 4:
819                                         state = VALUE_GROUP;
820                                         if (block->group) {
821                                                 DbgFree(block->group);
822                                                 block->group = NULL;
823                                                 block->group_len = 0;
824                                         }
825                                         idx = 0;
826                                         break;
827                                 case 5:
828                                         state = VALUE_ID;
829                                         if (block->id) {
830                                                 DbgFree(block->id);
831                                                 block->id = NULL;
832                                                 block->id_len = 0;
833                                         }
834                                         idx = 0;
835                                         break;
836                                 case 6:
837                                         state = VALUE_TARGET;
838                                         if (block->target_id) {
839                                                 DbgFree(block->target_id);
840                                                 block->target_id = NULL;
841                                                 block->target_len = 0;
842                                         }
843                                         idx = 0;
844                                         break;
845                                 default:
846                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
847                                         goto errout;
848                                 }
849
850                                 break;
851                         }
852
853                         if (ch == '\n')
854                                 goto errout;
855
856                         if (field_name[field_idx][idx] != ch) {
857                                 ungetc(ch, fp);
858                                 if (ch == '\n')
859                                         lineno--;
860
861                                 while (--idx >= 0)
862                                         ungetc(field_name[field_idx][idx], fp);
863
864                                 field_idx++;
865                                 if (field_name[field_idx] == NULL) {
866                                         ErrPrint("%d: Syntax error: Unrecognized field\n", lineno);
867                                         goto errout;
868                                 }
869
870                                 idx = 0;
871                                 break;
872                         }
873
874                         idx++;
875                         break;
876
877                 case VALUE_TYPE:
878                         if (idx == block->type_len) {
879                                 char *tmp;
880                                 block->type_len += ADDEND;
881                                 tmp = realloc(block->type, block->type_len);
882                                 if (!tmp) {
883                                         ErrPrint("Heap: %s\n", strerror(errno));
884                                         goto errout;
885                                 }
886                                 block->type = tmp;
887                         }
888
889                         if (ch == '\n') {
890                                 block->type[idx] = '\0';
891                                 state = FIELD;
892                                 idx = 0;
893                                 field_idx = 0;
894                                 break;
895                         }
896
897                         block->type[idx] = ch;
898                         idx++;
899                         break;
900
901                 case VALUE_PART:
902                         if (idx == block->part_len) {
903                                 char *tmp;
904                                 block->part_len += ADDEND;
905                                 tmp = realloc(block->part, block->part_len);
906                                 if (!tmp) {
907                                         ErrPrint("Heap: %s\n", strerror(errno));
908                                         goto errout;
909                                 }
910                                 block->part = tmp;
911                         }
912
913                         if (ch == '\n') {
914                                 block->part[idx] = '\0';
915                                 state = FIELD;
916                                 idx = 0;
917                                 field_idx = 0;
918                                 break;
919                         }
920
921                         block->part[idx] = ch;
922                         idx++;
923                         break;
924
925                 case VALUE_DATA:
926                         if (idx == block->data_len) {
927                                 char *tmp;
928                                 block->data_len += ADDEND;
929                                 tmp = realloc(block->data, block->data_len);
930                                 if (!tmp) {
931                                         ErrPrint("Heap: %s\n", strerror(errno));
932                                         goto errout;
933                                 }
934                                 block->data = tmp;
935                         }
936
937                         if (ch == '\n') {
938                                 block->data[idx] = '\0';
939                                 state = FIELD;
940                                 idx = 0;
941                                 field_idx = 0;
942                                 break;
943                         }
944
945                         block->data[idx] = ch;
946                         idx++;
947                         break;
948
949                 case VALUE_FILE:
950                         if (idx == block->file_len) {
951                                 char *tmp;
952                                 block->file_len += ADDEND;
953                                 tmp = realloc(block->file, block->file_len);
954                                 if (!tmp) {
955                                         ErrPrint("Heap: %s\n", strerror(errno));
956                                         goto errout;
957                                 }
958                                 block->file = tmp;
959                         }
960
961                         if (ch == '\n') {
962                                 block->file[idx] = '\0';
963                                 state = FIELD;
964                                 idx = 0;
965                                 field_idx = 0;
966                                 break;
967                         }
968
969                         block->file[idx] = ch;
970                         idx++;
971                         break;
972
973                 case VALUE_GROUP:
974                         if (idx == block->group_len) {
975                                 char *tmp;
976                                 block->group_len += ADDEND;
977                                 tmp = realloc(block->group, block->group_len);
978                                 if (!tmp) {
979                                         ErrPrint("Heap: %s\n", strerror(errno));
980                                         goto errout;
981                                 }
982                                 block->group = tmp;
983                         }
984
985                         if (ch == '\n') {
986                                 block->group[idx] = '\0';
987                                 state = FIELD;
988                                 idx = 0;
989                                 field_idx = 0;
990                                 break;
991                         }
992
993                         block->group[idx] = ch;
994                         idx++;
995                         break;
996                 case VALUE_ID:
997                         if (idx == block->id_len) {
998                                 char *tmp;
999                                 block->id_len += ADDEND;
1000                                 tmp = realloc(block->id, block->id_len);
1001                                 if (!tmp) {
1002                                         ErrPrint("Heap: %s\n", strerror(errno));
1003                                         goto errout;
1004                                 }
1005                                 block->id = tmp;
1006                         }
1007
1008                         if (ch == '\n') {
1009                                 block->id[idx] = '\0';
1010                                 state = FIELD;
1011                                 idx = 0;
1012                                 field_idx = 0;
1013                                 break;
1014                         }
1015
1016                         block->id[idx] = ch;
1017                         idx++;
1018                         break;
1019                 case VALUE_TARGET:
1020                         if (idx == block->target_len) {
1021                                 char *tmp;
1022                                 block->target_len += ADDEND;
1023                                 tmp = realloc(block->target_id, block->target_len);
1024                                 if (!tmp) {
1025                                         ErrPrint("Heap: %s\n", strerror(errno));
1026                                         goto errout;
1027                                 }
1028                                 block->target_id = tmp;
1029                         }
1030
1031                         if (ch == '\n') {
1032                                 block->target_id[idx] = '\0';
1033                                 state = FIELD;
1034                                 idx = 0;
1035                                 field_idx = 0;
1036                                 break;
1037                         }
1038
1039                         block->target_id[idx] = ch;
1040                         idx++;
1041                         break;
1042                 case BLOCK_CLOSE:
1043                         if (!block->file) {
1044                                 block->file = strdup(util_uri_to_path(id));
1045                                 if (!block->file) {
1046                                         ErrPrint("Heap: %s\n", strerror(errno));
1047                                         goto errout;
1048                                 }
1049                         }
1050
1051                         i = 0;
1052                         while (handlers[i].type) {
1053                                 if (!strcasecmp(handlers[i].type, block->type)) {
1054                                         handlers[i].handler(inst, block, is_pd);
1055                                         break;
1056                                 }
1057                                 i++;
1058                         }
1059
1060                         if (!handlers[i].type)
1061                                 ErrPrint("%d: Unknown block type: %s\n", lineno, block->type);
1062
1063                         DbgFree(block->file);
1064                         DbgFree(block->type);
1065                         DbgFree(block->part);
1066                         DbgFree(block->data);
1067                         DbgFree(block->group);
1068                         DbgFree(block->id);
1069                         DbgFree(block->target_id);
1070                         DbgFree(block);
1071                         block = NULL;
1072
1073                         state = UNKNOWN;
1074                         break;
1075
1076                 default:
1077                         break;
1078                 } /* switch */
1079         } /* while */
1080
1081         if (state != UNKNOWN) {
1082                 ErrPrint("%d: Unknown state\n", lineno);
1083                 goto errout;
1084         }
1085
1086         fclose(fp);
1087         return 0;
1088
1089 errout:
1090         ErrPrint("Parse error at %d file %s\n", lineno, util_basename(descfile));
1091         if (block) {
1092                 DbgFree(block->file);
1093                 DbgFree(block->type);
1094                 DbgFree(block->part);
1095                 DbgFree(block->data);
1096                 DbgFree(block->group);
1097                 DbgFree(block->id);
1098                 DbgFree(block->target_id);
1099                 DbgFree(block);
1100         }
1101         fclose(fp);
1102         return -EINVAL;
1103 }
1104
1105 HAPI int script_init(void)
1106 {
1107         struct script_port *item;
1108         struct dirent *ent;
1109         DIR *dir;
1110         char *path;
1111         int pathlen;
1112
1113         if (!strcasecmp(PROVIDER_METHOD, "shm"))
1114                 s_info.env_buf_type = BUFFER_TYPE_SHM;
1115         else if (!strcasecmp(PROVIDER_METHOD, "pixmap"))
1116                 s_info.env_buf_type = BUFFER_TYPE_PIXMAP;
1117
1118         dir = opendir(SCRIPT_PORT_PATH);
1119         if (!dir) {
1120                 ErrPrint("Error: %s\n", strerror(errno));
1121                 return -EIO;
1122         }
1123
1124         while ((ent = readdir(dir))) {
1125                 if (ent->d_name[0] == '.')
1126                         continue;
1127
1128                 pathlen = strlen(ent->d_name) + strlen(SCRIPT_PORT_PATH) + 1;
1129                 path = malloc(pathlen);
1130                 if (!path) {
1131                         ErrPrint("Heap: %s %d\n", strerror(errno), pathlen);
1132                         closedir(dir);
1133                         return -ENOMEM;
1134                 }
1135
1136                 snprintf(path, pathlen, "%s%s", SCRIPT_PORT_PATH, ent->d_name);
1137
1138                 item = malloc(sizeof(*item));
1139                 if (!item) {
1140                         ErrPrint("Heap: %s\n", strerror(errno));
1141                         DbgFree(path);
1142                         closedir(dir);
1143                         return -ENOMEM;
1144                 }
1145
1146                 DbgPrint("Open SCRIPT PORT: %s\n", path);
1147                 item->handle = dlopen(path, RTLD_LOCAL | RTLD_LAZY);
1148                 DbgFree(path);
1149                 if (!item->handle) {
1150                         ErrPrint("Error: %s\n", dlerror());
1151                         DbgFree(item);
1152                         closedir(dir);
1153                         return -EFAULT;
1154                 }
1155
1156                 item->magic_id = dlsym(item->handle, "script_magic_id");
1157                 if (!item->magic_id)
1158                         goto errout;
1159
1160                 DbgPrint("SCRIPT PORT magic id: %s\n", item->magic_id());
1161
1162                 item->update_text = dlsym(item->handle, "script_update_text");
1163                 if (!item->update_text)
1164                         goto errout;
1165
1166                 item->update_image = dlsym(item->handle, "script_update_image");
1167                 if (!item->update_image)
1168                         goto errout;
1169
1170                 item->update_script = dlsym(item->handle, "script_update_script");
1171                 if (!item->update_script)
1172                         goto errout;
1173
1174                 item->update_signal = dlsym(item->handle, "script_update_signal");
1175                 if (!item->update_signal)
1176                         goto errout;
1177
1178                 item->update_drag = dlsym(item->handle, "script_update_drag");
1179                 if (!item->update_drag)
1180                         goto errout;
1181
1182                 item->update_size = dlsym(item->handle, "script_update_size");
1183                 if (!item->update_size)
1184                         goto errout;
1185
1186                 item->update_category = dlsym(item->handle, "script_update_category");
1187                 if (!item->update_category)
1188                         goto errout;
1189
1190                 item->create = dlsym(item->handle, "script_create");
1191                 if (!item->create)
1192                         goto errout;
1193
1194                 item->destroy = dlsym(item->handle, "script_destroy");
1195                 if (!item->destroy)
1196                         goto errout;
1197
1198                 item->load = dlsym(item->handle, "script_load");
1199                 if (!item->load)
1200                         goto errout;
1201
1202                 item->unload = dlsym(item->handle, "script_unload");
1203                 if (!item->unload)
1204                         goto errout;
1205
1206                 item->init = dlsym(item->handle, "script_init");
1207                 if (!item->init)
1208                         goto errout;
1209
1210                 item->fini = dlsym(item->handle, "script_fini");
1211                 if (!item->fini)
1212                         goto errout;
1213
1214                 if (item->init() < 0) {
1215                         ErrPrint("Failed to initialize script engine\n");
1216                         goto errout;
1217                 }
1218
1219                 s_info.script_port_list = eina_list_append(s_info.script_port_list, item);
1220         }
1221
1222         closedir(dir);
1223         return 0;
1224
1225 errout:
1226         ErrPrint("Error: %s\n", dlerror());
1227         dlclose(item->handle);
1228         DbgFree(item);
1229         closedir(dir);
1230         return -EFAULT;
1231 }
1232
1233 HAPI int script_fini(void)
1234 {
1235         struct script_port *item;
1236         /*!
1237          * \TODO: Release all handles
1238          */
1239         EINA_LIST_FREE(s_info.script_port_list, item) {
1240                 item->fini();
1241                 dlclose(item->handle);
1242                 DbgFree(item);
1243         }
1244
1245         return 0;
1246 }
1247
1248 HAPI int script_handler_update_pointer(struct script_info *info, double x, double y, int down)
1249 {
1250         if (!info)
1251                 return 0;
1252
1253         info->x = x;
1254         info->y = y;
1255
1256         if (down == 0)
1257                 info->down = 0;
1258         else if (down == 1)
1259                 info->down = 1;
1260
1261         return 0;
1262 }
1263
1264 /* End of a file */