1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <ctype.h>
12
13 #include <Evas.h>
14 #include <Ecore.h>
15 #include <Ecore_Getopt.h>
16 #include <Ecore_Evas.h>
17 #include <Edje.h>
18
19 struct opts
20 {
21 char *file;
22 char *group;
23 Eina_Bool list_groups;
24 char *engine;
25 Eina_Rectangle size;
26 unsigned char color[3];
27 Eina_Bool borderless;
28 Eina_Bool sticky;
29 Eina_Bool shaped;
30 Eina_Bool alpha;
31 Eina_Bool print;
32 Eina_Bool slave_mode;
33 double scale;
34 int pad;
35 char *title;
36 };
37
38 static Eina_Bool _edje_load_or_show_error(Evas_Object *edje, const char *file, const char *group);
39
40 static Ecore_Evas *win;
41 static Evas *evas;
42 static Evas_Object *bg, *bg2 = NULL, *edje;
43 static struct opts opts;
44
45 static void
_win_title_set(const char * group,const char * file)46 _win_title_set(const char *group, const char *file)
47 {
48 char buf[1024];
49 snprintf(buf, sizeof(buf), "Edje_Player - %s of %s", group, file);
50 ecore_evas_title_set(win, buf);
51 }
52
53 static char *
_slave_mode_tok(char ** p_arg)54 _slave_mode_tok(char **p_arg)
55 {
56 char *s, *e;
57 Eina_Bool is_quoted;
58
59 if (!*p_arg) return NULL;
60
61 s = *p_arg;
62 while (isspace(*s))
63 s++;
64
65 if (*s == '\0')
66 {
67 *p_arg = NULL;
68 return NULL;
69 }
70 else if (*s == '"')
71 {
72 is_quoted = EINA_TRUE;
73 s++;
74 *p_arg = s;
75 }
76 else
77 {
78 is_quoted = EINA_FALSE;
79 *p_arg = s;
80 }
81
82 for (e = s; *e != '\0'; e++)
83 {
84 if ((!is_quoted) && (isspace(*e)))
85 break;
86 else if ((is_quoted) && (*e == '"'))
87 break;
88 }
89
90 if (*e == '\0') return NULL;
91
92 *e = '\0';
93 return e + 1;
94 }
95
96 static void
_slave_mode_signal(Evas_Object * edje,char * args)97 _slave_mode_signal(Evas_Object *edje, char *args)
98 {
99 char *emission, *source;
100
101 emission = args;
102 source = _slave_mode_tok(&emission);
103 _slave_mode_tok(&source);
104
105 if ((!emission) || (!source))
106 {
107 fputs("ERROR: Invalid command arguments.\n", stderr);
108 return;
109 }
110
111 edje_object_signal_emit(edje, emission, source);
112 }
113
114 static void
_slave_mode_message_string(Evas_Object * edje,int id,char * arg)115 _slave_mode_message_string(Evas_Object *edje, int id, char *arg)
116 {
117 Edje_Message_String msg;
118 msg.str = arg;
119 edje_object_message_send(edje, EDJE_MESSAGE_STRING, id, &msg);
120 }
121
122 static void
_slave_mode_message_int(Evas_Object * edje,int id,char * arg)123 _slave_mode_message_int(Evas_Object *edje, int id, char *arg)
124 {
125 Edje_Message_Int msg;
126 msg.val = atoi(arg);
127 edje_object_message_send(edje, EDJE_MESSAGE_INT, id, &msg);
128 }
129
130 static void
_slave_mode_message_float(Evas_Object * edje,int id,char * arg)131 _slave_mode_message_float(Evas_Object *edje, int id, char *arg)
132 {
133 Edje_Message_Float msg;
134 msg.val = atof(arg);
135 edje_object_message_send(edje, EDJE_MESSAGE_FLOAT, id, &msg);
136 }
137
138 static void
_slave_mode_message_string_set(Evas_Object * edje,int id,char * arg,char * extra_args)139 _slave_mode_message_string_set(Evas_Object *edje, int id, char *arg,
140 char *extra_args)
141 {
142 Edje_Message_String_Set *msg;
143 int count, i;
144
145 count = atoi(arg);
146 msg = alloca(sizeof(Edje_Message_String_Set) + (count - 1) * sizeof(char *));
147
148 for (i = 0; i < count; i++)
149 {
150 char *next = _slave_mode_tok(&extra_args);
151 if (!extra_args)
152 {
153 fputs("ERROR: Message missing arg.\n", stderr);
154 return;
155 }
156 msg->str[i] = extra_args;
157 extra_args = next;
158 }
159
160 msg->count = count;
161 edje_object_message_send(edje, EDJE_MESSAGE_STRING_SET, id, msg);
162 }
163
164 static void
_slave_mode_message_int_set(Evas_Object * edje,int id,char * arg,char * extra_args)165 _slave_mode_message_int_set(Evas_Object *edje, int id, char *arg,
166 char *extra_args)
167 {
168 Edje_Message_Int_Set *msg;
169 int count, i;
170
171 count = atoi(arg);
172 msg = alloca(sizeof(Edje_Message_Int_Set) + (count - 1) * sizeof(int));
173
174 for (i = 0; i < count; i++)
175 {
176 char *next = _slave_mode_tok(&extra_args);
177 if (!extra_args)
178 {
179 fputs("ERROR: Message missing arg.\n", stderr);
180 return;
181 }
182 msg->val[i] = atoi(extra_args);
183 extra_args = next;
184 }
185
186 msg->count = count;
187 edje_object_message_send(edje, EDJE_MESSAGE_INT_SET, id, msg);
188 }
189
190 static void
_slave_mode_message_float_set(Evas_Object * edje,int id,char * arg,char * extra_args)191 _slave_mode_message_float_set(Evas_Object *edje, int id, char *arg,
192 char *extra_args)
193 {
194 Edje_Message_Float_Set *msg;
195 int count, i;
196
197 count = atoi(arg);
198 msg = alloca(sizeof(Edje_Message_Float_Set) + (count - 1) * sizeof(double));
199
200 for (i = 0; i < count; i++)
201 {
202 char *next = _slave_mode_tok(&extra_args);
203 if (!extra_args)
204 {
205 fputs("ERROR: Message missing arg.\n", stderr);
206 return;
207 }
208 msg->val[i] = atof(extra_args);
209 extra_args = next;
210 }
211
212 msg->count = count;
213 edje_object_message_send(edje, EDJE_MESSAGE_FLOAT_SET, id, msg);
214 }
215
216 static void
_slave_mode_message_string_int(Evas_Object * edje,int id,char * arg,char * extra_args)217 _slave_mode_message_string_int(Evas_Object *edje, int id, char *arg,
218 char *extra_args)
219 {
220 Edje_Message_String_Int msg;
221
222 if (!extra_args)
223 {
224 fputs("ERROR: Message STRING_INT requires integer arg.\n", stderr);
225 return;
226 }
227 _slave_mode_tok(&extra_args);
228
229 msg.str = arg;
230 msg.val = atoi(extra_args);
231
232 edje_object_message_send(edje, EDJE_MESSAGE_STRING_INT, id, &msg);
233 }
234
235 static void
_slave_mode_message_string_float(Evas_Object * edje,int id,char * arg,char * extra_args)236 _slave_mode_message_string_float(Evas_Object *edje, int id, char *arg,
237 char *extra_args)
238 {
239 Edje_Message_String_Float msg;
240
241 if (!extra_args)
242 {
243 fputs("ERROR: Message STRING_FLOAT requires float arg.\n", stderr);
244 return;
245 }
246 _slave_mode_tok(&extra_args);
247
248 msg.str = arg;
249 msg.val = atof(extra_args);
250
251 edje_object_message_send(edje, EDJE_MESSAGE_STRING_FLOAT, id, &msg);
252 }
253
254 static void
_slave_mode_message_string_int_set(Evas_Object * edje,int id,char * arg,char * extra_args)255 _slave_mode_message_string_int_set(Evas_Object *edje, int id, char *arg,
256 char *extra_args)
257 {
258 Edje_Message_String_Int_Set *msg;
259 int count, i;
260 char *val;
261
262 if (!extra_args)
263 {
264 fputs("ERROR: Message STRING_INT_SET requires int args.\n", stderr);
265 return;
266 }
267
268 val = _slave_mode_tok(&extra_args);
269 count = atoi(extra_args);
270 msg = alloca(sizeof(Edje_Message_String_Int_Set) +
271 (count - 1) * sizeof(int));
272
273 for (i = 0; i < count; i++)
274 {
275 char *next = _slave_mode_tok(&val);
276 if (!val)
277 {
278 fputs("ERROR: Message missing arg.\n", stderr);
279 return;
280 }
281 msg->val[i] = atoi(val);
282 val = next;
283 }
284
285 msg->count = count;
286 msg->str = arg;
287 edje_object_message_send(edje, EDJE_MESSAGE_STRING_INT_SET, id, msg);
288 }
289
290 static void
_slave_mode_message_string_float_set(Evas_Object * edje,int id,char * arg,char * extra_args)291 _slave_mode_message_string_float_set(Evas_Object *edje, int id, char *arg,
292 char *extra_args)
293 {
294 Edje_Message_String_Float_Set *msg;
295 int count, i;
296 char *val;
297
298 if (!extra_args)
299 {
300 fputs("ERROR: Message STRING_FLOAT_SET requires float set.\n", stderr);
301 return;
302 }
303
304 val = _slave_mode_tok(&extra_args);
305 count = atoi(extra_args);
306 msg = alloca(sizeof(Edje_Message_String_Float_Set) +
307 (count - 1) * sizeof(double));
308
309 for (i = 0; i < count; i++)
310 {
311 char *next = _slave_mode_tok(&val);
312 if (!val)
313 {
314 fputs("ERROR: Message missing arg.\n", stderr);
315 return;
316 }
317 msg->val[i] = atof(val);
318 val = next;
319 }
320
321 msg->count = count;
322 msg->str = arg;
323 edje_object_message_send(edje, EDJE_MESSAGE_STRING_FLOAT_SET, id, msg);
324 }
325
326 static void
_slave_mode_message(Evas_Object * edje,char * args)327 _slave_mode_message(Evas_Object *edje, char *args)
328 {
329 char *id_str, *type, *message_arg, *extra_args;
330 int id;
331
332 id_str = args;
333 type = _slave_mode_tok(&id_str);
334 message_arg = _slave_mode_tok(&type);
335 extra_args = _slave_mode_tok(&message_arg);
336
337 if (!id_str)
338 {
339 fputs("ERROR: Message id is required.\n", stderr);
340 return;
341 }
342
343 id = atoi(id_str);
344
345 if (!type)
346 {
347 fputs("ERROR: Message type is required.\n", stderr);
348 return;
349 }
350
351 if (!message_arg)
352 {
353 fputs("ERROR: Missing message argument.\n", stderr);
354 return;
355 }
356
357 if (!strcmp(type, "STRING"))
358 {
359 _slave_mode_message_string(edje, id, message_arg);
360 return;
361 }
362
363 if (!strcmp(type, "INT"))
364 {
365 _slave_mode_message_int(edje, id, message_arg);
366 return;
367 }
368
369 if (!strcmp(type, "FLOAT"))
370 {
371 _slave_mode_message_float(edje, id, message_arg);
372 return;
373 }
374
375 if (!strcmp(type, "STRING_SET"))
376 {
377 _slave_mode_message_string_set(edje, id, message_arg, extra_args);
378 return;
379 }
380
381 if (!strcmp(type, "INT_SET"))
382 {
383 _slave_mode_message_int_set(edje, id, message_arg, extra_args);
384 return;
385 }
386
387 if (!strcmp(type, "FLOAT_SET"))
388 {
389 _slave_mode_message_float_set(edje, id, message_arg, extra_args);
390 return;
391 }
392
393 if (!strcmp(type, "STRING_INT"))
394 {
395 _slave_mode_message_string_int(edje, id, message_arg, extra_args);
396 return;
397 }
398
399 if (!strcmp(type, "STRING_FLOAT"))
400 {
401 _slave_mode_message_string_float(edje, id, message_arg, extra_args);
402 return;
403 }
404
405 if (!strcmp(type, "STRING_INT_SET"))
406 {
407 _slave_mode_message_string_int_set(edje, id, message_arg, extra_args);
408 return;
409 }
410
411 if (!strcmp(type, "STRING_FLOAT_SET"))
412 {
413 _slave_mode_message_string_float_set(edje, id, message_arg, extra_args);
414 return;
415 }
416
417 fputs("ERROR: Invalid type. Check types list using \"help\".\n", stderr);
418 }
419
420 static void
_slave_mode_info(Evas_Object * edje,char * args)421 _slave_mode_info(Evas_Object *edje, char *args)
422 {
423 _slave_mode_tok(&args);
424
425 if (!args)
426 {
427 fputs("ERROR: Invalid command arguments.\n", stderr);
428 return;
429 }
430
431 if (!edje_object_part_exists(edje, args))
432 {
433 printf("INFO: \"%s\" does not exist.\n", args);
434 }
435 else
436 {
437 Evas_Coord x, y, w, h;
438 edje_object_part_geometry_get(edje, args, &x, &y, &w, &h);
439 printf("INFO: \"%s\" %d,%d,%d,%d\n", args, x, y, w, h);
440 }
441 }
442
443 static void
_slave_mode_text(Evas_Object * edje,char * args)444 _slave_mode_text(Evas_Object *edje, char *args)
445 {
446 char *part, *text, *p;
447
448 if (!args) return;
449 p = strchr(args, ' ');
450 if (!p) return;
451 part = malloc(p - args + 1);
452 strncpy(part, args, p - args);
453 part[p - args] = 0;
454 text = p + 1;
455 edje_object_part_text_set(edje, part, text);
456 free(part);
457 }
458
459 static void
_slave_mode_quit(Evas_Object * edje EINA_UNUSED,char * args EINA_UNUSED)460 _slave_mode_quit(Evas_Object *edje EINA_UNUSED, char *args EINA_UNUSED)
461 {
462 puts("Bye!");
463 ecore_main_loop_quit();
464 }
465
466 static void
_slave_mode_help(Evas_Object * edje EINA_UNUSED,char * args EINA_UNUSED)467 _slave_mode_help(Evas_Object *edje EINA_UNUSED, char *args EINA_UNUSED)
468 {
469 puts("Help:\n"
470 "One command per line, arguments separated by space.\n"
471 "Strings may have spaces if enclosed in quotes (\").\n"
472 "\n"
473 "\t<command> [arguments]\n"
474 "\n"
475 "Available commands:\n"
476 "\tsignal <emission> <source>\n"
477 "\t sends a signal to edje\n"
478 "\tmessage <id> <type> <args list>\n"
479 "\t sends a message to edje.\n"
480 "\t Possible types (and args):\n"
481 "\t * STRING \"string\"\n"
482 "\t * INT integer\n"
483 "\t * FLOAT float\n"
484 "\t * STRING_SET <set length> \"string1\" \"string2\" ...\n"
485 "\t * INT_SET <set length> integer1 integer2 integer3 ...\n"
486 "\t * FLOAT_SET <set length> float1 float2 float3 ...\n"
487 "\t * STRING_INT \"message\" integer\n"
488 "\t * STRING_FLOAT \"message\" float\n"
489 "\t * STRING_INT_SET \"string\" <set length> integer1 ...\n"
490 "\t * STRING_FLOAT_SET \"string\" <set length> float1 float2 ...\n"
491 "\tinfo <part>\n"
492 "\t Print part geometry: <x>,<y>,<w>,<h>\n"
493 "\ttext <part> <text string>\n"
494 "\t Set text of named part\n"
495 "\tquit\n"
496 "\t exit edje player.\n"
497 "\thelp\n"
498 "\t shows this message.\n");
499 /*
500 * Extension ideas (are they useful?):
501 * - data: show data value
502 * - color_class: set color class values (maybe also list?)
503 * - text_class: set text class values (maybe also list?)
504 * - play_set: change play state
505 * - animation_set: change animation state
506 */
507 }
508
509 struct slave_cmd
510 {
511 const char *cmd;
512 void (*func)(Evas_Object *edje, char *args);
513 } _slave_mode_commands[] = {
514 {"signal", _slave_mode_signal},
515 {"message", _slave_mode_message},
516 {"info", _slave_mode_info},
517 {"text", _slave_mode_text},
518 {"quit", _slave_mode_quit},
519 {"help", _slave_mode_help},
520 {NULL, NULL}
521 };
522
523 #ifndef _WIN32
524 static Eina_Bool
_slave_mode(void * data,Ecore_Fd_Handler * fd_handler)525 _slave_mode(void *data, Ecore_Fd_Handler *fd_handler)
526 {
527 Evas_Object *edje = data;
528 char buf[1024], *p;
529 const struct slave_cmd *itr;
530 size_t len;
531
532 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
533 {
534 fputs("ERROR: error on stdin! Exit.\n", stderr);
535 ecore_main_loop_quit();
536 return ECORE_CALLBACK_CANCEL;
537 }
538 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
539 return ECORE_CALLBACK_RENEW;
540
541 if (!fgets(buf, sizeof(buf), stdin))
542 {
543 fputs("ERROR: end of stdin! Exit.\n", stderr);
544 ecore_main_loop_quit();
545 return ECORE_CALLBACK_CANCEL;
546 }
547
548 len = strlen(buf);
549 if (len < 1)
550 {
551 fputs("ERROR: no input! Try: help\n", stderr);
552 return ECORE_CALLBACK_RENEW;
553 }
554 if (buf[len - 1] == '\n')
555 {
556 len--;
557 buf[len] = '\0';
558 }
559
560 p = strchr(buf, ' ');
561 if (p)
562 {
563 *p = '\0';
564 p++;
565
566 while (isspace(*p))
567 p++;
568 if (*p == '\0')
569 p = NULL;
570
571 if (p)
572 {
573 char *q = p + strlen(p) - 1;
574 while (isspace(*q))
575 {
576 *q = '\0';
577 q--;
578 }
579 }
580 }
581
582 for (itr = _slave_mode_commands; itr->cmd; itr++)
583 {
584 if (strcasecmp(itr->cmd, buf) == 0)
585 {
586 itr->func(edje, p);
587 break;
588 }
589 }
590
591 return ECORE_CALLBACK_RENEW;
592 }
593
594 #endif
595
596 static void
_print_signal(void * data EINA_UNUSED,Evas_Object * o EINA_UNUSED,const char * emission,const char * source)597 _print_signal(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, const char *emission, const char *source)
598 {
599 printf("SIGNAL: \"%s\" \"%s\"\n", emission, source);
600 }
601
602 static void
_print_message(void * data EINA_UNUSED,Evas_Object * edje EINA_UNUSED,Edje_Message_Type type,int id,void * msg)603 _print_message(void *data EINA_UNUSED, Evas_Object *edje EINA_UNUSED, Edje_Message_Type type, int id, void *msg)
604 {
605 const char *typestr;
606 char buf[64];
607
608 switch (type)
609 {
610 case EDJE_MESSAGE_NONE:
611 typestr = "NONE";
612 break;
613
614 case EDJE_MESSAGE_SIGNAL:
615 typestr = "SIGNAL";
616 break;
617
618 case EDJE_MESSAGE_STRING:
619 typestr = "STRING";
620 break;
621
622 case EDJE_MESSAGE_INT:
623 typestr = "INT";
624 break;
625
626 case EDJE_MESSAGE_FLOAT:
627 typestr = "FLOAT";
628 break;
629
630 case EDJE_MESSAGE_STRING_SET:
631 typestr = "STRING_SET";
632 break;
633
634 case EDJE_MESSAGE_INT_SET:
635 typestr = "INT_SET";
636 break;
637
638 case EDJE_MESSAGE_FLOAT_SET:
639 typestr = "FLOAT_SET";
640 break;
641
642 case EDJE_MESSAGE_STRING_INT:
643 typestr = "STRING_INT";
644 break;
645
646 case EDJE_MESSAGE_STRING_FLOAT:
647 typestr = "STRING_FLOAT";
648 break;
649
650 case EDJE_MESSAGE_STRING_INT_SET:
651 typestr = "STRING_INT_SET";
652 break;
653
654 case EDJE_MESSAGE_STRING_FLOAT_SET:
655 typestr = "STRING_FLOAT_SET";
656 break;
657
658 default:
659 snprintf(buf, sizeof(buf), "UNKNOWN(%d)", type);
660 typestr = buf;
661 }
662
663 printf("MESSAGE: type=%s, id=%d", typestr, id);
664
665 switch (type)
666 {
667 case EDJE_MESSAGE_NONE: break;
668
669 case EDJE_MESSAGE_SIGNAL: break;
670
671 case EDJE_MESSAGE_STRING:
672 {
673 Edje_Message_String *m = msg;
674 printf(" \"%s\"", m->str);
675 }
676 break;
677
678 case EDJE_MESSAGE_INT:
679 {
680 Edje_Message_Int *m = msg;
681 printf(" %d", m->val);
682 }
683 break;
684
685 case EDJE_MESSAGE_FLOAT:
686 {
687 Edje_Message_Float *m = msg;
688 printf(" %f", m->val);
689 }
690 break;
691
692 case EDJE_MESSAGE_STRING_SET:
693 {
694 Edje_Message_String_Set *m = msg;
695 int i;
696 for (i = 0; i < m->count; i++)
697 printf(" \"%s\"", m->str[i]);
698 }
699 break;
700
701 case EDJE_MESSAGE_INT_SET:
702 {
703 Edje_Message_Int_Set *m = msg;
704 int i;
705 for (i = 0; i < m->count; i++)
706 printf(" %d", m->val[i]);
707 }
708 break;
709
710 case EDJE_MESSAGE_FLOAT_SET:
711 {
712 Edje_Message_Float_Set *m = msg;
713 int i;
714 for (i = 0; i < m->count; i++)
715 printf(" %f", m->val[i]);
716 }
717 break;
718
719 case EDJE_MESSAGE_STRING_INT:
720 {
721 Edje_Message_String_Int *m = msg;
722 printf(" \"%s\" %d", m->str, m->val);
723 }
724 break;
725
726 case EDJE_MESSAGE_STRING_FLOAT:
727 {
728 Edje_Message_String_Float *m = msg;
729 printf(" \"%s\" %f", m->str, m->val);
730 }
731 break;
732
733 case EDJE_MESSAGE_STRING_INT_SET:
734 {
735 Edje_Message_String_Int_Set *m = msg;
736 int i;
737 printf(" \"%s\"", m->str);
738 for (i = 0; i < m->count; i++)
739 printf(" %d", m->val[i]);
740 }
741 break;
742
743 case EDJE_MESSAGE_STRING_FLOAT_SET:
744 {
745 Edje_Message_String_Float_Set *m = msg;
746 int i;
747 printf(" \"%s\"", m->str);
748 for (i = 0; i < m->count; i++)
749 printf(" %f", m->val[i]);
750 }
751 break;
752
753 default:
754 break;
755 }
756
757 putchar('\n');
758 }
759
760 static void
_key_down(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)761 _key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
762 {
763 Evas_Event_Key_Down *ev = event_info;
764
765 if ((!strcmp(ev->keyname, "equal")) ||
766 (!strcmp(ev->keyname, "plus")))
767 opts.scale += 0.1;
768 else if ((!strcmp(ev->keyname, "minus")) ||
769 (!strcmp(ev->keyname, "underscore")))
770 opts.scale -= 0.1;
771 else if ((!strcmp(ev->keyname, "0")))
772 opts.scale = 1.0;
773 if (opts.scale < 0.1) opts.scale = 0.1;
774 else if (opts.scale > 10.0)
775 opts.scale = 10.0;
776 edje_scale_set(opts.scale);
777 }
778
779 static Evas_Object *
_create_bg(void)780 _create_bg(void)
781 {
782 const unsigned char *color = opts.color;
783 Evas_Object *o = evas_object_rectangle_add(evas);
784 if (!o)
785 {
786 fputs("ERROR: could not create background.\n", stderr);
787 return NULL;
788 }
789 evas_object_color_set(o, color[0], color[1], color[2], 255);
790 evas_object_show(o);
791 return o;
792 }
793
794 static void
_edje_reload(void * data EINA_UNUSED,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)795 _edje_reload(void *data EINA_UNUSED, Evas_Object *obj, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
796 {
797 const char *file;
798 const char *group;
799 edje_object_signal_callback_del(obj, "edje,change,file", "edje", _edje_reload);
800 edje_object_file_get(obj, &file, &group);
801 _edje_load_or_show_error(obj, file, group);
802 }
803
804 static void
_edje_circul(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)805 _edje_circul(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
806 {
807 char buf[1024] = "";
808 Eina_List *parts = event_info;
809 Eina_List *l;
810 char *part_name;
811 char *group = data;
812
813 part_name = eina_list_data_get(eina_list_last(parts));
814 strncpy(buf, part_name, sizeof(buf) - 1);
815 part_name[sizeof(buf) - 1] = 0;
816 EINA_LIST_FOREACH(parts, l, part_name)
817 {
818 strncat(buf, " -> ", sizeof(buf) - strlen(buf) - 1);
819 part_name[sizeof(buf) - 1] = 0;
820 strncat(buf, part_name, sizeof(buf) - strlen(buf) - 1);
821 part_name[sizeof(buf) - 1] = 0;
822 }
823
824 fprintf(stderr, "Group '%s' have a circul dependency between parts: %s\n",
825 group, buf);
826 }
827
828 static Eina_Bool
_edje_load_or_show_error(Evas_Object * edje,const char * file,const char * group)829 _edje_load_or_show_error(Evas_Object *edje, const char *file, const char *group)
830 {
831 Eina_File *f = NULL;
832 const char *errmsg;
833 int err;
834
835 f = eina_file_open(file, EINA_FALSE);
836 if (edje_object_file_set(edje, file, group))
837 {
838 edje_object_signal_callback_add(edje, "edje,change,file", "edje", _edje_reload, NULL);
839 evas_object_focus_set(edje, EINA_TRUE);
840 eina_file_close(f);
841 return EINA_TRUE;
842 }
843
844 err = edje_object_load_error_get(edje);
845 errmsg = edje_load_error_str(err);
846 eina_file_close(f);
847 fprintf(stderr, "ERROR: could not load edje file '%s', group '%s': %s\n",
848 file, group, errmsg);
849 return EINA_FALSE;
850 }
851
852 static Evas_Object *
_create_edje(void)853 _create_edje(void)
854 {
855 Evas_Coord minw, minh, maxw, maxh;
856 Evas_Object *o = edje_object_add(evas);
857 if (!o)
858 {
859 fputs("ERROR: could not create edje.\n", stderr);
860 return NULL;
861 }
862
863 if (opts.group)
864 {
865 if (!_edje_load_or_show_error(o, opts.file, opts.group))
866 {
867 evas_object_del(edje);
868 return NULL;
869 }
870 if (!opts.title) _win_title_set(opts.group, opts.file);
871 }
872 else
873 {
874 if (edje_file_group_exists(opts.file, "main"))
875 {
876 if (!_edje_load_or_show_error(o, opts.file, "main"))
877 {
878 evas_object_del(edje);
879 return NULL;
880 }
881 if (!opts.title) _win_title_set("main", opts.file);
882 }
883 else
884 {
885 Eina_List *groups = edje_file_collection_list(opts.file);
886 const char *group;
887 if (!groups)
888 {
889 fprintf(stderr, "ERROR: file '%s' has no groups!\n",
890 opts.file);
891 evas_object_del(edje);
892 return NULL;
893 }
894 group = groups->data;
895 if (!_edje_load_or_show_error(o, opts.file, group))
896 {
897 edje_file_collection_list_free(groups);
898 evas_object_del(edje);
899 return NULL;
900 }
901 if (!opts.title) _win_title_set(group, opts.file);
902 edje_file_collection_list_free(groups);
903 }
904 }
905 evas_object_smart_callback_add(o, "circular,dependency", _edje_circul, opts.group);
906
907 edje_object_size_max_get(o, &maxw, &maxh);
908 edje_object_size_min_get(o, &minw, &minh);
909 if ((minw <= 0) && (minh <= 0))
910 edje_object_size_min_calc(o, &minw, &minh);
911
912 ecore_evas_size_max_set(win,
913 maxw > 0 ? (maxw + opts.pad * 2) : 0,
914 maxh > 0 ? (maxh + opts.pad * 2) : 0);
915 ecore_evas_size_min_set(win, (minw + opts.pad * 2), (minh + opts.pad * 2));
916
917 evas_object_show(o);
918
919 return o;
920 }
921
922 static unsigned char
_parse_color(EINA_UNUSED const Ecore_Getopt * parser,EINA_UNUSED const Ecore_Getopt_Desc * desc,const char * str,EINA_UNUSED void * data,Ecore_Getopt_Value * storage)923 _parse_color(EINA_UNUSED const Ecore_Getopt *parser, EINA_UNUSED const Ecore_Getopt_Desc *desc, const char *str, EINA_UNUSED void *data, Ecore_Getopt_Value *storage)
924 {
925 unsigned char *color = (unsigned char *)storage->ptrp;
926
927 if (sscanf(str, "%hhu,%hhu,%hhu", color, color + 1, color + 2) != 3)
928 {
929 fprintf(stderr, "ERROR: incorrect color value '%s'\n", str);
930 return 0;
931 }
932
933 return 1;
934 }
935
936 static void
_cb_delete(EINA_UNUSED Ecore_Evas * ee)937 _cb_delete(EINA_UNUSED Ecore_Evas *ee)
938 {
939 ecore_main_loop_quit();
940 }
941
942 static void
_cb_resize(Ecore_Evas * ee)943 _cb_resize(Ecore_Evas *ee)
944 {
945 int w, h;
946 ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
947 evas_object_move(edje, opts.pad, opts.pad);
948 evas_object_resize(edje, w - (opts.pad * 2), h - (opts.pad * 2));
949 evas_object_move(bg, opts.pad, opts.pad);
950 evas_object_resize(bg, w - (opts.pad * 2), h - (opts.pad * 2));
951 if (bg2) evas_object_resize(bg2, w, h);
952 }
953
954 const Ecore_Getopt optdesc = {
955 "edje_player",
956 "%prog [options] <filename.edj>",
957 PACKAGE_VERSION,
958 "(C) 2010 Enlightenment",
959 "BSD with advertisement clause",
960 "Simple application to view edje files.",
961 0,
962 {
963 ECORE_GETOPT_STORE_STR
964 ('g', "group", "The edje group to view (defaults to 'main')."),
965 ECORE_GETOPT_STORE_TRUE
966 ('G', "list-groups", "The groups in the given file."),
967 ECORE_GETOPT_STORE_STR
968 ('e', "engine", "The Ecore-Evas engine to use (see --list-engines)"),
969 ECORE_GETOPT_CALLBACK_NOARGS
970 ('E', "list-engines", "list Ecore-Evas engines",
971 ecore_getopt_callback_ecore_evas_list_engines, NULL),
972 ECORE_GETOPT_CALLBACK_ARGS
973 ('Z', "size", "size to use in wxh form.", "WxH",
974 ecore_getopt_callback_size_parse, NULL),
975 ECORE_GETOPT_CALLBACK_ARGS
976 ('c', "bg-color", "Color of the background (if not shaped or alpha) e.g. 255,150,50",
977 "R,G,B", _parse_color, NULL),
978 ECORE_GETOPT_STORE_TRUE
979 ('b', "borderless", "Display window without border."),
980 ECORE_GETOPT_STORE_TRUE
981 ('y', "sticky", "Display window sticky."),
982 ECORE_GETOPT_STORE_TRUE
983 ('s', "shaped", "Display window shaped."),
984 ECORE_GETOPT_STORE_TRUE
985 ('a', "alpha", "Display window with alpha channel "
986 "(needs composite manager!)"),
987 ECORE_GETOPT_STORE_STR
988 ('t', "title", "Define the window title string"),
989 ECORE_GETOPT_STORE_TRUE
990 ('p', "print", "Print signals and messages to stdout"),
991 ECORE_GETOPT_STORE_TRUE
992 ('S', "slave-mode", "Listen for commands on stdin"),
993 ECORE_GETOPT_STORE_DOUBLE
994 ('z', "scale", "Set scale factor"),
995 ECORE_GETOPT_STORE_INT
996 ('P', "pad", "Set pixel padding around object"),
997 ECORE_GETOPT_LICENSE('L', "license"),
998 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
999 ECORE_GETOPT_VERSION('V', "version"),
1000 ECORE_GETOPT_HELP('h', "help"),
1001 ECORE_GETOPT_SENTINEL
1002 }
1003 };
1004
1005 int
main(int argc,char ** argv)1006 main(int argc, char **argv)
1007 {
1008 Eina_Bool quit_option = EINA_FALSE;
1009 int args;
1010 Eina_List *groups;
1011 const char *group;
1012 Ecore_Getopt_Value values[] = {
1013 ECORE_GETOPT_VALUE_STR(opts.group),
1014 ECORE_GETOPT_VALUE_BOOL(opts.list_groups),
1015 ECORE_GETOPT_VALUE_STR(opts.engine),
1016 ECORE_GETOPT_VALUE_BOOL(quit_option),
1017 ECORE_GETOPT_VALUE_PTR_CAST(opts.size),
1018 ECORE_GETOPT_VALUE_PTR_CAST(opts.color),
1019 ECORE_GETOPT_VALUE_BOOL(opts.borderless),
1020 ECORE_GETOPT_VALUE_BOOL(opts.sticky),
1021 ECORE_GETOPT_VALUE_BOOL(opts.shaped),
1022 ECORE_GETOPT_VALUE_BOOL(opts.alpha),
1023 ECORE_GETOPT_VALUE_STR(opts.title),
1024 ECORE_GETOPT_VALUE_BOOL(opts.print),
1025 ECORE_GETOPT_VALUE_BOOL(opts.slave_mode),
1026 ECORE_GETOPT_VALUE_DOUBLE(opts.scale),
1027 ECORE_GETOPT_VALUE_INT(opts.pad),
1028 ECORE_GETOPT_VALUE_BOOL(quit_option),
1029 ECORE_GETOPT_VALUE_BOOL(quit_option),
1030 ECORE_GETOPT_VALUE_BOOL(quit_option),
1031 ECORE_GETOPT_VALUE_BOOL(quit_option),
1032 ECORE_GETOPT_VALUE_NONE
1033 };
1034
1035 memset(&opts, 0, sizeof(opts));
1036 opts.scale = 1.0;
1037
1038 if (!ecore_evas_init())
1039 return EXIT_FAILURE;
1040 if (!edje_init())
1041 goto shutdown_ecore_evas;
1042 edje_frametime_set(1.0 / 60.0);
1043
1044 args = ecore_getopt_parse(&optdesc, values, argc, argv);
1045 if (args < 0)
1046 {
1047 fputs("Could not parse arguments.\n", stderr);
1048 goto shutdown_edje;
1049 }
1050 else if (quit_option)
1051 {
1052 goto end;
1053 }
1054 else if (args >= argc)
1055 {
1056 fputs("Missing edje file to load.\n", stderr);
1057 goto shutdown_edje;
1058 }
1059
1060 ecore_app_args_set(argc, (const char **)argv);
1061 edje_scale_set(opts.scale);
1062
1063 // check if the given edj file is there
1064 if (access(argv[args], R_OK) == -1)
1065 {
1066 int e = errno;
1067 fprintf(stderr, "ERROR: file '%s' not accessible, error %d (%s).\n",
1068 argv[args], e, strerror(e));
1069 goto end;
1070 }
1071
1072 opts.file = argv[args];
1073 groups = edje_file_collection_list(opts.file);
1074 if (opts.list_groups)
1075 {
1076 Eina_List *n;
1077 printf("%d groups in file '%s':\n", eina_list_count(groups), opts.file);
1078 EINA_LIST_FOREACH(groups, n, group)
1079 printf("\t'%s'\n", group);
1080 edje_file_collection_list_free(groups);
1081 goto end;
1082 }
1083
1084 if (opts.size.w <= 0) opts.size.w = 320;
1085 if (opts.size.h <= 0) opts.size.h = 240;
1086 win = ecore_evas_new(opts.engine, 0, 0, opts.size.w, opts.size.h, NULL);
1087 if (!win)
1088 {
1089 fprintf(stderr,
1090 "ERROR: could not create window of "
1091 "size %dx%d using engine %s.\n",
1092 opts.size.w, opts.size.h, opts.engine ? opts.engine : "(auto)");
1093 goto shutdown_edje;
1094 }
1095
1096 ecore_evas_callback_delete_request_set(win, _cb_delete);
1097 evas = ecore_evas_get(win);
1098
1099 if (opts.alpha)
1100 ecore_evas_alpha_set(win, EINA_TRUE);
1101 else if (opts.shaped)
1102 ecore_evas_shaped_set(win, EINA_TRUE);
1103
1104 if (opts.pad > 0)
1105 {
1106 bg2 = evas_object_rectangle_add(evas);
1107 evas_object_resize(bg2, opts.size.w, opts.size.h);
1108 if (opts.alpha)
1109 evas_object_color_set(bg2, 0, 0, 0, 64);
1110 else
1111 evas_object_color_set(bg2, 64, 64, 64, 255);
1112 evas_object_show(bg2);
1113 }
1114 bg = _create_bg();
1115
1116 edje = _create_edje();
1117 if (!edje) goto free_ecore_evas;
1118
1119 ecore_evas_callback_resize_set(win, _cb_resize);
1120 _cb_resize(win);
1121 evas_object_focus_set(bg, EINA_TRUE);
1122 evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN,
1123 _key_down, &opts);
1124
1125 if (opts.print)
1126 {
1127 edje_object_signal_callback_add(edje, "*", "*", _print_signal, NULL);
1128 edje_object_message_handler_set(edje, _print_message, NULL);
1129 }
1130
1131 if (opts.slave_mode)
1132 {
1133 #ifndef _WIN32
1134 int flags;
1135 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
1136 flags |= O_NONBLOCK;
1137 if (fcntl(STDIN_FILENO, F_SETFL, flags) < 0)
1138 {
1139 fprintf(stderr, "ERROR: Could not set stdin to non-block: %s\n",
1140 strerror(errno));
1141 goto free_ecore_evas;
1142 }
1143 ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ | ECORE_FD_ERROR,
1144 _slave_mode, edje, NULL, NULL);
1145 #else
1146 /* TODO: port the code above to Windows */
1147 fprintf(stderr, "ERROR: slave mode not working on Windows\n");
1148 goto free_ecore_evas;
1149 #endif
1150 }
1151
1152 ecore_evas_borderless_set(win, opts.borderless);
1153 ecore_evas_sticky_set(win, opts.sticky);
1154 if (opts.title)
1155 ecore_evas_title_set(win, opts.title);
1156
1157 ecore_evas_show(win);
1158 ecore_main_loop_begin();
1159
1160 ecore_evas_free(win);
1161 end:
1162 edje_shutdown();
1163 ecore_evas_shutdown();
1164
1165 return 0;
1166
1167 free_ecore_evas:
1168 ecore_evas_free(win);
1169 shutdown_edje:
1170 edje_shutdown();
1171 shutdown_ecore_evas:
1172 ecore_evas_shutdown();
1173 return EXIT_FAILURE;
1174 }
1175
1176