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