summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Zaoui <daniel.zaoui@yahoo.com>2018-12-24 22:51:52 +0200
committerStefan Schmidt <s.schmidt@samsung.com>2020-01-31 14:14:01 +0100
commit9a8078cb799d2a34f1c5682c2e42dbdf19d2ee57 (patch)
tree01fa7bfe2dd23596b13d8d0c67348f922c640fe5
parent478863862a4e669e652d2e6ed9b7204b39503a08 (diff)
Exactness: code importation
Differential Revision: https://phab.enlightenment.org/D7590
-rw-r--r--meson.build1
-rw-r--r--src/bin/exactness/.gitignore5
-rw-r--r--src/bin/exactness/exactness.c675
-rw-r--r--src/bin/exactness/injector.c483
-rw-r--r--src/bin/exactness/inspect.c1653
-rw-r--r--src/bin/exactness/meson.build42
-rw-r--r--src/bin/exactness/player.c1393
-rw-r--r--src/bin/exactness/player_entry.edc932
-rw-r--r--src/bin/exactness/recorder.c531
-rw-r--r--src/lib/exactness/Exactness.h268
-rw-r--r--src/lib/exactness/exactness_private.h10
-rw-r--r--src/lib/exactness/legacy_file.c876
-rw-r--r--src/lib/exactness/meson.build31
-rw-r--r--src/lib/exactness/unit.c424
14 files changed, 7324 insertions, 0 deletions
diff --git a/meson.build b/meson.build
index 5ee96f0f09..fb77c43570 100644
--- a/meson.build
+++ b/meson.build
@@ -335,6 +335,7 @@ subprojects = [
335['elua' ,['elua'] , false, true, true, false, true, false, ['eina', 'luajit'], []], 335['elua' ,['elua'] , false, true, true, false, true, false, ['eina', 'luajit'], []],
336['ecore_wayland' ,['wl-deprecated'] , false, true, false, false, false, false, ['eina'], []], 336['ecore_wayland' ,['wl-deprecated'] , false, true, false, false, false, false, ['eina'], []],
337['ecore_drm' ,['drm-deprecated'] , false, true, false, false, false, false, ['eina'], []], 337['ecore_drm' ,['drm-deprecated'] , false, true, false, false, false, false, ['eina'], []],
338['exactness' ,[] , false, true, true, false, false, false, ['eina, evas, eet'], []],
338] 339]
339 340
340# We generate Efl_Config.h and config.h later, they will be available here 341# We generate Efl_Config.h and config.h later, they will be available here
diff --git a/src/bin/exactness/.gitignore b/src/bin/exactness/.gitignore
new file mode 100644
index 0000000000..2760101039
--- /dev/null
+++ b/src/bin/exactness/.gitignore
@@ -0,0 +1,5 @@
1/exactness
2/exactness_inject
3/exactness_inspect
4/exactness_play
5/exactness_record
diff --git a/src/bin/exactness/exactness.c b/src/bin/exactness/exactness.c
new file mode 100644
index 0000000000..06c6097cf5
--- /dev/null
+++ b/src/bin/exactness/exactness.c
@@ -0,0 +1,675 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore.h>
6#include <Ecore_Getopt.h>
7#include <Ecore_Evas.h>
8#include <Ecore_File.h>
9
10#include "exactness_private.h"
11
12#ifdef _WIN32
13# include <evil_private.h> /* mkdir */
14#endif
15
16#define SCHEDULER_CMD_SIZE 1024
17
18#define ORIG_SUBDIR "orig"
19#define CURRENT_SUBDIR "current"
20
21#define EXACTNESS_PATH_MAX 1024
22
23#define BUF_SIZE 1024
24
25typedef struct
26{
27 EINA_INLIST;
28 char *name;
29 const char *command;
30} List_Entry;
31
32typedef enum
33{
34 RUN_SIMULATION,
35 RUN_PLAY,
36 RUN_INIT
37} Run_Mode;
38
39static unsigned short _running_jobs = 0, _max_jobs = 1;
40static Eina_List *_base_dirs = NULL;
41static char *_dest_dir;
42static char *_wrap_command = NULL, *_fonts_dir = NULL;
43static int _verbose = 0;
44static Eina_Bool _scan_objs = EINA_FALSE, _disable_screenshots = EINA_FALSE, _stabilize_shots = EINA_FALSE;
45
46static Run_Mode _mode;
47static List_Entry *_next_test_to_run = NULL;
48static unsigned int _tests_executed = 0;
49
50static Eina_List *_errors;
51static Eina_List *_compare_errors;
52
53static Eina_Bool _job_consume();
54
55static void
56_printf(int verbose, const char *fmt, ...)
57{
58 va_list ap;
59 if (!_verbose || verbose > _verbose) return;
60
61 va_start(ap, fmt);
62 vprintf(fmt, ap);
63 va_end(ap);
64}
65
66static Exactness_Image *
67_image_load(const char *filename)
68{
69 int w, h;
70 Evas_Load_Error err;
71 Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
72 Eo *e = ecore_evas_get(ee);
73
74 Eo *img = evas_object_image_add(e);
75 evas_object_image_file_set(img, filename, NULL);
76 err = evas_object_image_load_error_get(img);
77 if (err != EVAS_LOAD_ERROR_NONE)
78 {
79 fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
80 filename, evas_load_error_str(err));
81 return NULL;
82 }
83
84 Exactness_Image *ex_img = malloc(sizeof(*ex_img));
85 int len;
86 evas_object_image_size_get(img, &w, &h);
87 ex_img->w = w;
88 ex_img->h = h;
89 len = w * h * 4;
90 ex_img->pixels = malloc(len);
91 memcpy(ex_img->pixels, evas_object_image_data_get(img, EINA_FALSE), len);
92
93 ecore_evas_free(ee);
94 return ex_img;
95}
96
97static void
98_image_save(Exactness_Image *ex_img, const char *output)
99{
100 Ecore_Evas *ee;
101 Eo *e, *img;
102 ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
103 e = ecore_evas_get(ee);
104 img = evas_object_image_add(e);
105 evas_object_image_size_set(img, ex_img->w, ex_img->h);
106 evas_object_image_data_set(img, ex_img->pixels);
107 evas_object_image_save(img, output, NULL, NULL);
108 ecore_evas_free(ee);
109}
110
111static Eina_Bool
112_file_compare(const char *orig_dir, const char *ent_name)
113{
114 Eina_Bool result = EINA_FALSE;
115 Exactness_Image *img1, *img2, *imgO = NULL;
116 char *filename1 = alloca(strlen(orig_dir) + strlen(ent_name) + 20);
117 char *filename2 = alloca(strlen(_dest_dir) + strlen(ent_name) + 20);
118 sprintf(filename1, "%s/%s", orig_dir, ent_name);
119 sprintf(filename2, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ent_name);
120
121 img1 = _image_load(filename1);
122 img2 = _image_load(filename2);
123
124 if (exactness_image_compare(img1, img2, &imgO))
125 {
126 char *buf = alloca(strlen(_dest_dir) + strlen(ent_name));
127 sprintf(buf, "%s/%s/comp_%s", _dest_dir, CURRENT_SUBDIR, ent_name);
128 _image_save(imgO, buf);
129 _compare_errors = eina_list_append(_compare_errors, strdup(ent_name));
130 result = EINA_TRUE;
131 }
132 exactness_image_free(img1);
133 exactness_image_free(img2);
134 exactness_image_free(imgO);
135 return result;
136}
137
138static void
139_exu_imgs_unpack(const char *exu_path, const char *dir, const char *ent_name)
140{
141 Exactness_Unit *unit = exactness_unit_file_read(exu_path);
142 Exactness_Image *img;
143 Eina_List *itr;
144 Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
145 Eo *e = ecore_evas_get(ee);
146 int n = 1;
147 if (!unit) return;
148 EINA_LIST_FOREACH(unit->imgs, itr, img)
149 {
150 Eo *o = evas_object_image_add(e);
151 char *filename = alloca(strlen(dir) + strlen(ent_name) + 20);
152 snprintf(filename, EXACTNESS_PATH_MAX, "%s/%s%c%.3d.png",
153 dir, ent_name, SHOT_DELIMITER, n++);
154 evas_object_image_size_set(o, img->w, img->h);
155 evas_object_image_data_set(o, img->pixels);
156 if (!evas_object_image_save(o, filename, NULL, NULL))
157 {
158 printf("Cannot save widget to <%s>\n", filename);
159 }
160 efl_del(o);
161 }
162 efl_del(e);
163 ecore_evas_free(ee);
164}
165
166static void
167_run_test_compare(const List_Entry *ent)
168{
169 char *path = alloca(EXACTNESS_PATH_MAX);
170 char *origdir = alloca(strlen(_dest_dir) + 20);
171 const char *base_dir;
172 Eina_List *itr;
173 int n = 1, nb_fails = 0;
174 printf("STATUS %s: COMPARE\n", ent->name);
175 EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
176 {
177 sprintf(path, "%s/%s.exu", base_dir, ent->name);
178 if (ecore_file_exists(path))
179 {
180 char *currentdir;
181 sprintf(origdir, "%s/%s/%s", _dest_dir, CURRENT_SUBDIR, ORIG_SUBDIR);
182 mkdir(origdir, 0744);
183 _exu_imgs_unpack(path, origdir, ent->name);
184 sprintf(path, "%s/%s/%s.exu", _dest_dir, CURRENT_SUBDIR, ent->name);
185 currentdir = alloca(strlen(_dest_dir) + 20);
186 sprintf(currentdir, "%s/%s", _dest_dir, CURRENT_SUBDIR);
187 _exu_imgs_unpack(path, currentdir, ent->name);
188 goto found;
189 }
190 else
191 {
192 sprintf(path, "%s/%s.rec", base_dir, ent->name);
193 if (ecore_file_exists(path))
194 {
195 sprintf(origdir, "%s/%s", _dest_dir, ORIG_SUBDIR);
196 goto found;
197 }
198 }
199 }
200found:
201 do
202 {
203 sprintf(path, "%s/%s%c%.3d.png", origdir, ent->name, SHOT_DELIMITER, n);
204 if (ecore_file_exists(path))
205 {
206 sprintf(path, "%s%c%.3d.png", ent->name, SHOT_DELIMITER, n);
207 if (_file_compare(origdir, path)) nb_fails++;
208 }
209 else break;
210 n++;
211 } while (EINA_TRUE);
212 if (!nb_fails)
213 printf("STATUS %s: END - SUCCESS\n", ent->name);
214 else
215 printf("STATUS %s: END - FAIL (%d/%d)\n", ent->name, nb_fails, n - 1);
216}
217
218#define CONFIG "ELM_SCALE=1 ELM_FINGER_SIZE=10 "
219static Eina_Bool
220_run_command_prepare(const List_Entry *ent, char *buf)
221{
222 char scn_path[EXACTNESS_PATH_MAX];
223 Eina_Strbuf *sbuf;
224 const char *base_dir;
225 Eina_List *itr;
226 Eina_Bool is_exu;
227 EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
228 {
229 is_exu = EINA_TRUE;
230 sprintf(scn_path, "%s/%s.exu", base_dir, ent->name);
231 if (ecore_file_exists(scn_path)) goto ok;
232 else
233 {
234 is_exu = EINA_FALSE;
235 sprintf(scn_path, "%s/%s.rec", base_dir, ent->name);
236 if (ecore_file_exists(scn_path)) goto ok;
237 }
238 }
239 fprintf(stderr, "Test %s not found in the provided base directories\n", ent->name);
240 return EINA_FALSE;
241ok:
242 sbuf = eina_strbuf_new();
243 printf("STATUS %s: START\n", ent->name);
244 eina_strbuf_append_printf(sbuf,
245 "%s exactness_play %s %s%s %s%.*s %s%s%s-t '%s' ",
246 _wrap_command ? _wrap_command : "",
247 _mode == RUN_SIMULATION ? "-s" : "",
248 _fonts_dir ? "-f " : "", _fonts_dir ? _fonts_dir : "",
249 _verbose ? "-" : "", _verbose, "vvvvvvvvvv",
250 _scan_objs ? "--scan-objects " : "",
251 _disable_screenshots ? "--disable-screenshots " : "",
252 _stabilize_shots ? "--stabilize-shots " : "",
253 scn_path
254 );
255 if (is_exu)
256 {
257 if (_mode == RUN_PLAY)
258 eina_strbuf_append_printf(sbuf, "-o '%s/%s/%s.exu' ", _dest_dir, CURRENT_SUBDIR, ent->name);
259 if (_mode == RUN_INIT)
260 eina_strbuf_append_printf(sbuf, "-o '%s' ", scn_path);
261 }
262 else
263 {
264 if (_mode == RUN_PLAY)
265 eina_strbuf_append_printf(sbuf, "-o '%s/%s' ", _dest_dir, CURRENT_SUBDIR);
266 if (_mode == RUN_INIT)
267 eina_strbuf_append_printf(sbuf, "-o '%s/%s' ", _dest_dir, ORIG_SUBDIR);
268 }
269 if (ent->command)
270 {
271 eina_strbuf_append(sbuf, "-- ");
272 eina_strbuf_append(sbuf, CONFIG);
273 eina_strbuf_append(sbuf, ent->command);
274 }
275 strncpy(buf, eina_strbuf_string_get(sbuf), SCHEDULER_CMD_SIZE-1);
276 eina_strbuf_free(sbuf);
277 _printf(1, "Command: %s\n", buf);
278 return EINA_TRUE;
279}
280
281static void
282_job_compare(void *data)
283{
284 _run_test_compare(data);
285
286 _running_jobs--;
287 _job_consume();
288 /* If all jobs are done. */
289 if (!_running_jobs) ecore_main_loop_quit();
290}
291
292static Eina_Bool
293_job_deleted_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
294{
295 Ecore_Exe_Event_Del *msg = (Ecore_Exe_Event_Del *) event;
296 List_Entry *ent = ecore_exe_data_get(msg->exe);
297
298 if ((msg->exit_code != 0) || (msg->exit_signal != 0))
299 {
300 _errors = eina_list_append(_errors, ent);
301 }
302
303 if (_mode == RUN_PLAY)
304 {
305 ecore_job_add(_job_compare, ent);
306 }
307 else
308 {
309 _running_jobs--;
310 _job_consume();
311 if (!_running_jobs) ecore_main_loop_quit();
312 }
313
314 return ECORE_CALLBACK_RENEW;
315}
316
317static Eina_Bool
318_job_consume()
319{
320 static Ecore_Event_Handler *job_del_callback_handler = NULL;
321 char buf[SCHEDULER_CMD_SIZE];
322 List_Entry *ent = _next_test_to_run;
323
324 if (_running_jobs == _max_jobs) return EINA_FALSE;
325 if (!ent) return EINA_FALSE;
326
327 if (_run_command_prepare(ent, buf))
328 {
329 _running_jobs++;
330 _tests_executed++;
331
332 if (!job_del_callback_handler)
333 {
334 job_del_callback_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
335 _job_deleted_cb, NULL);
336 }
337
338 if (!ecore_exe_pipe_run(buf, ECORE_EXE_TERM_WITH_PARENT, ent))
339 {
340 fprintf(stderr, "Failed executing test '%s'\n", ent->name);
341 }
342 }
343 _next_test_to_run = EINA_INLIST_CONTAINER_GET(
344 EINA_INLIST_GET(ent)->next, List_Entry);
345
346
347 return EINA_TRUE;
348}
349
350static void
351_scheduler_run()
352{
353 while (_job_consume());
354}
355
356static List_Entry *
357_list_file_load(const char *filename)
358{
359 List_Entry *ret = NULL;
360 char buf[BUF_SIZE] = "";
361 FILE *file;
362 file = fopen(filename, "r");
363 if (!file)
364 {
365 perror("Failed opening list file");
366 return NULL;
367 }
368
369 while (fgets(buf, BUF_SIZE, file))
370 {
371 /* Skip comment/empty lines. */
372 if ((*buf == '#') || (*buf == '\n') || (!*buf))
373 continue;
374
375 char *tmp;
376 List_Entry *cur = calloc(1, sizeof(*cur));
377 cur->name = strdup(buf);
378
379 /* Set the command to the second half and put a \0 in between. */
380 tmp = strchr(cur->name, ' ');
381 if (tmp)
382 {
383 *tmp = '\0';
384 cur->command = tmp + 1;
385 }
386 else
387 {
388 /* FIXME: error. */
389 cur->command = "";
390 }
391
392 /* Replace the newline char with a \0. */
393 tmp = strchr(cur->command, '\n');
394 if (tmp)
395 {
396 *tmp = '\0';
397 }
398
399 ret = EINA_INLIST_CONTAINER_GET(
400 eina_inlist_append(EINA_INLIST_GET(ret), EINA_INLIST_GET(cur)),
401 List_Entry);
402 }
403
404 return ret;
405}
406
407static void
408_list_file_free(List_Entry *list)
409{
410 while (list)
411 {
412 List_Entry *ent = list;
413 list = EINA_INLIST_CONTAINER_GET(EINA_INLIST_GET(list)->next,
414 List_Entry);
415
416 free(ent->name);
417 free(ent);
418 /* we don't free ent->command because it's allocated together. */
419 }
420}
421
422static int
423_errors_sort_cb(List_Entry *a, List_Entry *b)
424{
425 return strcmp(a->name, b->name);
426}
427
428static const Ecore_Getopt optdesc = {
429 "exactness",
430 "%prog [options] <-r|-p|-i|-s> <list file>",
431 PACKAGE_VERSION,
432 "(C) 2013 Enlightenment",
433 "BSD",
434 "A pixel perfect test suite for EFL based applications.",
435 0,
436 {
437 ECORE_GETOPT_APPEND('b', "base-dir", "The location of the exu/rec files.", ECORE_GETOPT_TYPE_STR),
438 ECORE_GETOPT_STORE_STR('o', "output", "The location of the images."),
439 ECORE_GETOPT_STORE_STR('w', "wrap", "Use a custom command to launch the tests (e.g valgrind)."),
440 ECORE_GETOPT_STORE_USHORT('j', "jobs", "The number of jobs to run in parallel."),
441 ECORE_GETOPT_STORE_TRUE('p', "play", "Run in play mode."),
442 ECORE_GETOPT_STORE_TRUE('i', "init", "Run in init mode."),
443 ECORE_GETOPT_STORE_TRUE('s', "simulation", "Run in simulation mode."),
444 ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."),
445 ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots."),
446 ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
447 ECORE_GETOPT_STORE_TRUE(0, "stabilize-shots", "Wait for the frames to be stable before taking the shots."),
448 ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
449
450 ECORE_GETOPT_LICENSE('L', "license"),
451 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
452 ECORE_GETOPT_VERSION('V', "version"),
453 ECORE_GETOPT_HELP('h', "help"),
454 ECORE_GETOPT_SENTINEL
455 }
456};
457
458int
459main(int argc, char *argv[])
460{
461 int ret = 0;
462 List_Entry *test_list;
463 int args = 0;
464 const char *list_file;
465 Eina_List *itr;
466 const char *base_dir;
467 char tmp[EXACTNESS_PATH_MAX];
468 Eina_Bool mode_play = EINA_FALSE, mode_init = EINA_FALSE, mode_simulation = EINA_FALSE;
469 Eina_Bool want_quit = EINA_FALSE, scan_objs = EINA_FALSE;
470 Ecore_Getopt_Value values[] = {
471 ECORE_GETOPT_VALUE_LIST(_base_dirs),
472 ECORE_GETOPT_VALUE_STR(_dest_dir),
473 ECORE_GETOPT_VALUE_STR(_wrap_command),
474 ECORE_GETOPT_VALUE_USHORT(_max_jobs),
475 ECORE_GETOPT_VALUE_BOOL(mode_play),
476 ECORE_GETOPT_VALUE_BOOL(mode_init),
477 ECORE_GETOPT_VALUE_BOOL(mode_simulation),
478 ECORE_GETOPT_VALUE_BOOL(scan_objs),
479 ECORE_GETOPT_VALUE_BOOL(_disable_screenshots),
480 ECORE_GETOPT_VALUE_STR(_fonts_dir),
481 ECORE_GETOPT_VALUE_BOOL(_stabilize_shots),
482 ECORE_GETOPT_VALUE_INT(_verbose),
483
484 ECORE_GETOPT_VALUE_BOOL(want_quit),
485 ECORE_GETOPT_VALUE_BOOL(want_quit),
486 ECORE_GETOPT_VALUE_BOOL(want_quit),
487 ECORE_GETOPT_VALUE_BOOL(want_quit),
488 ECORE_GETOPT_VALUE_NONE
489 };
490
491 ecore_init();
492 ecore_evas_init();
493 evas_init();
494 mode_play = mode_init = mode_simulation = EINA_FALSE;
495 want_quit = EINA_FALSE;
496 _dest_dir = "./";
497 _scan_objs = scan_objs;
498
499 args = ecore_getopt_parse(&optdesc, values, argc, argv);
500 if (args < 0)
501 {
502 fprintf(stderr, "Failed parsing arguments.\n");
503 ret = 1;
504 goto end;
505 }
506 else if (want_quit)
507 {
508 ret = 1;
509 goto end;
510 }
511 else if (args == argc)
512 {
513 fprintf(stderr, "Expected test list as the last argument..\n");
514 ecore_getopt_help(stderr, &optdesc);
515 ret = 1;
516 goto end;
517 }
518 else if (mode_play + mode_init + mode_simulation != 1)
519 {
520 fprintf(stderr, "At least and only one of the running modes can be set.\n");
521 ecore_getopt_help(stderr, &optdesc);
522 ret = 1;
523 goto end;
524 }
525
526 if (!_base_dirs) _base_dirs = eina_list_append(NULL, "./recordings");
527
528 list_file = argv[args];
529
530 /* Load the list file and start iterating over the records. */
531 test_list = _list_file_load(list_file);
532 _next_test_to_run = test_list;
533
534 if (!test_list)
535 {
536 fprintf(stderr, "No matching tests found in '%s'\n", list_file);
537 ret = 1;
538 goto end;
539 }
540
541 /* Pre-run summary */
542 fprintf(stderr, "Running with settings:\n");
543 fprintf(stderr, "\tConcurrent jobs: %d\n", _max_jobs);
544 fprintf(stderr, "\tTest list: %s\n", list_file);
545 fprintf(stderr, "\tBase dirs:\n");
546 EINA_LIST_FOREACH(_base_dirs, itr, base_dir)
547 fprintf(stderr, "\t\t%s\n", base_dir);
548 fprintf(stderr, "\tDest dir: %s\n", _dest_dir);
549
550 if (mode_play)
551 {
552 _mode = RUN_PLAY;
553 if (snprintf(tmp, EXACTNESS_PATH_MAX, "%s/%s", _dest_dir, CURRENT_SUBDIR)
554 >= EXACTNESS_PATH_MAX)
555 {
556 fprintf(stderr, "Path too long: %s", tmp);
557 ret = 1;
558 goto end;
559 }
560 mkdir(tmp, 0744);
561 }
562 else if (mode_init)
563 {
564 _mode = RUN_INIT;
565 if (snprintf(tmp, EXACTNESS_PATH_MAX, "%s/%s", _dest_dir, ORIG_SUBDIR)
566 >= EXACTNESS_PATH_MAX)
567 {
568 fprintf(stderr, "Path too long: %s", tmp);
569 ret = 1;
570 goto end;
571 }
572 mkdir(tmp, 0744);
573 }
574 else if (mode_simulation)
575 {
576 _mode = RUN_SIMULATION;
577 }
578 _scheduler_run();
579
580
581 ecore_main_loop_begin();
582
583 /* Results */
584 printf("*******************************************************\n");
585 if (mode_play && EINA_FALSE)
586 {
587 List_Entry *list_itr;
588
589 EINA_INLIST_FOREACH(test_list, list_itr)
590 {
591 _run_test_compare(list_itr);
592 }
593 }
594
595 printf("Finished executing %u out of %u tests.\n",
596 _tests_executed,
597 eina_inlist_count(EINA_INLIST_GET(test_list)));
598
599 /* Sort the errors and the compare_errors. */
600 _errors = eina_list_sort(_errors, 0, (Eina_Compare_Cb) _errors_sort_cb);
601 _compare_errors = eina_list_sort(_compare_errors, 0, (Eina_Compare_Cb) strcmp);
602
603 if (_errors || _compare_errors)
604 {
605 FILE *report_file;
606 char report_filename[EXACTNESS_PATH_MAX] = "";
607 /* Generate the filename. */
608 snprintf(report_filename, EXACTNESS_PATH_MAX,
609 "%s/%s/errors.html",
610 _dest_dir, mode_init ? ORIG_SUBDIR : CURRENT_SUBDIR);
611 report_file = fopen(report_filename, "w+");
612 if (report_file)
613 {
614 printf("%s %p\n", report_filename, report_file);
615 fprintf(report_file,
616 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
617 "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>Exactness report</title></head><body>");
618
619 if (_errors)
620 {
621 fprintf(report_file,
622 "<h1>Tests that failed execution:</h1><ul>");
623 List_Entry *ent;
624 printf("List of tests that failed execution:\n");
625 EINA_LIST_FOREACH(_errors, itr, ent)
626 {
627 printf("\t* %s\n", ent->name);
628
629 fprintf(report_file, "<li>%s</li>", ent->name);
630 }
631 fprintf(report_file, "</ul>");
632 }
633
634 if (_compare_errors)
635 {
636 fprintf(report_file,
637 "<h1>Images that failed comparison: (Original, Current, Diff)</h1><ul>");
638 char *test_name;
639 printf("List of images that failed comparison:\n");
640 EINA_LIST_FREE(_compare_errors, test_name)
641 {
642 Eina_Bool is_from_exu;
643 char origpath[EXACTNESS_PATH_MAX];
644 snprintf(origpath, EXACTNESS_PATH_MAX, "%s/%s/orig/%s",
645 _dest_dir, CURRENT_SUBDIR, test_name);
646 is_from_exu = ecore_file_exists(origpath);
647 printf("\t* %s\n", test_name);
648
649 fprintf(report_file, "<li><h2>%s</h2> <img src='%sorig/%s' alt='Original' /> <img src='%s' alt='Current' /> <img src='comp_%s' alt='Diff' /></li>",
650 test_name, is_from_exu ? "" : "../",
651 test_name, test_name, test_name);
652 free(test_name);
653 }
654 fprintf(report_file, "</ul>");
655 }
656 fprintf(report_file,
657 "</body></html>");
658
659 printf("Report html: %s\n", report_filename);
660 ret = 1;
661 }
662 else
663 {
664 perror("Failed opening report file");
665 }
666 }
667
668 _list_file_free(test_list);
669end:
670 evas_shutdown();
671 ecore_evas_shutdown();
672 ecore_shutdown();
673
674 return ret;
675}
diff --git a/src/bin/exactness/injector.c b/src/bin/exactness/injector.c
new file mode 100644
index 0000000000..95e71a6927
--- /dev/null
+++ b/src/bin/exactness/injector.c
@@ -0,0 +1,483 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <getopt.h>
8#include <unistd.h>
9
10#ifndef EFL_EO_API_SUPPORT
11#define EFL_EO_API_SUPPORT
12#endif
13#include <Eina.h>
14#include <Eet.h>
15#include <Ecore.h>
16#include <Ecore_Getopt.h>
17#include <Elementary.h>
18
19#include <Exactness.h>
20
21#include "exactness_private.h"
22
23typedef struct
24{
25 Eina_Debug_Session *session;
26 int srcid;
27 void *buffer;
28 unsigned int size;
29} _Main_Loop_Info;
30
31#define WRAPPER_TO_XFER_MAIN_LOOP(foo) \
32static void \
33_intern_main_loop ## foo(void *data) \
34{ \
35 _Main_Loop_Info *info = data; \
36 _main_loop ## foo(info->session, info->srcid, info->buffer, info->size); \
37 free(info->buffer); \
38 free(info); \
39} \
40static Eina_Bool \
41foo(Eina_Debug_Session *session, int srcid, void *buffer, int size) \
42{ \
43 _Main_Loop_Info *info = calloc(1, sizeof(*info)); \
44 info->session = session; \
45 info->srcid = srcid; \
46 info->size = size; \
47 if (info->size) \
48 { \
49 info->buffer = malloc(info->size); \
50 memcpy(info->buffer, buffer, info->size); \
51 } \
52 ecore_main_loop_thread_safe_call_async(_intern_main_loop ## foo, info); \
53 return EINA_TRUE; \
54}
55
56#ifndef WORDS_BIGENDIAN
57#define SWAP_64(x) x
58#define SWAP_32(x) x
59#define SWAP_16(x) x
60#define SWAP_DBL(x) x
61#else
62#define SWAP_64(x) eina_swap64(x)
63#define SWAP_32(x) eina_swap32(x)
64#define SWAP_16(x) eina_swap16(x)
65#define SWAP_DBL(x) SWAP_64(x)
66#endif
67
68#define EXTRACT_INT(_buf) \
69({ \
70 int __i; \
71 memcpy(&__i, _buf, sizeof(int)); \
72 _buf += sizeof(int); \
73 SWAP_32(__i); \
74})
75
76#define STORE_INT(_buf, __i) \
77{ \
78 int __i2 = SWAP_32(__i); \
79 memcpy(_buf, &__i2, sizeof(int)); \
80 _buf += sizeof(int); \
81}
82
83#define STORE_DOUBLE(_buf, __d) \
84{ \
85 double __d2 = SWAP_DBL(__d); \
86 memcpy(_buf, &__d2, sizeof(double)); \
87 _buf += sizeof(double); \
88}
89
90#define STORE_STRING(_buf, __s) \
91{ \
92 int __len = (__s ? strlen(__s) : 0) + 1; \
93 if (__s) memcpy(_buf, __s, __len); \
94 else *_buf = '\0'; \
95 _buf += __len; \
96}
97
98static Eina_Stringshare *_src_filename = NULL;
99static Exactness_Unit *_src_unit = NULL;
100static int _verbose = 0;
101
102static Eina_Debug_Session *_session = NULL;
103static int _cid = -1, _pid = -1;
104static Eina_List *_cur_event_list = NULL;
105
106static int _all_apps_get_op = EINA_DEBUG_OPCODE_INVALID;
107static int _mouse_in_op = EINA_DEBUG_OPCODE_INVALID;
108static int _mouse_out_op = EINA_DEBUG_OPCODE_INVALID;
109static int _mouse_wheel_op = EINA_DEBUG_OPCODE_INVALID;
110static int _multi_down_op = EINA_DEBUG_OPCODE_INVALID;
111static int _multi_up_op = EINA_DEBUG_OPCODE_INVALID;
112static int _multi_move_op = EINA_DEBUG_OPCODE_INVALID;
113static int _key_down_op = EINA_DEBUG_OPCODE_INVALID;
114static int _key_up_op = EINA_DEBUG_OPCODE_INVALID;
115static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
116static int _efl_event_op = EINA_DEBUG_OPCODE_INVALID;
117static int _click_on_op = EINA_DEBUG_OPCODE_INVALID;
118static int _stabilize_op = EINA_DEBUG_OPCODE_INVALID;
119static int _finish_op = EINA_DEBUG_OPCODE_INVALID;
120
121static Eina_Bool _all_apps_get_cb(Eina_Debug_Session *, int , void *, int);
122
123EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
124 {"Daemon/Client/register_observer", &_all_apps_get_op, NULL},
125 {"Daemon/Client/added", NULL, &_all_apps_get_cb},
126 {"Exactness/Actions/Mouse In", &_mouse_in_op, NULL},
127 {"Exactness/Actions/Mouse Out", &_mouse_out_op, NULL},
128 {"Exactness/Actions/Mouse Wheel", &_mouse_wheel_op, NULL},
129 {"Exactness/Actions/Multi Down", &_multi_down_op, NULL},
130 {"Exactness/Actions/Multi Up", &_multi_up_op, NULL},
131 {"Exactness/Actions/Multi Move", &_multi_move_op, NULL},
132 {"Exactness/Actions/Key Down", &_key_down_op, NULL},
133 {"Exactness/Actions/Key Up", &_key_up_op, NULL},
134 {"Exactness/Actions/Take Shot", &_take_shot_op, NULL},
135 {"Exactness/Actions/EFL Event", &_efl_event_op, NULL},
136 {"Exactness/Actions/Click On", &_click_on_op, NULL},
137 {"Exactness/Actions/Stabilize", &_stabilize_op, NULL},
138 {"Exactness/Actions/Finish", &_finish_op, NULL},
139 {NULL, NULL, NULL}
140 );
141
142static void
143_printf(int verbose, const char *fmt, ...)
144{
145 va_list ap;
146 if (!_verbose || verbose > _verbose) return;
147
148 va_start(ap, fmt);
149 vprintf(fmt, ap);
150 va_end(ap);
151}
152
153static void
154_feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
155{
156 switch (type)
157 {
158 case EXACTNESS_ACTION_MOUSE_IN:
159 {
160 _printf(1, "Mouse in\n");
161 _printf(2, "%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
162 eina_debug_session_send(_session, _cid, _mouse_in_op, &n_evas, sizeof(int));
163 break;
164 }
165 case EXACTNESS_ACTION_MOUSE_OUT:
166 {
167 _printf(1, "Mouse out\n");
168 _printf(2, "%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
169 eina_debug_session_send(_session, _cid, _mouse_out_op, &n_evas, sizeof(int));
170 break;
171 }
172 case EXACTNESS_ACTION_MOUSE_WHEEL:
173 {
174 Exactness_Action_Mouse_Wheel *t = data;
175 int len = 3*sizeof(int);
176 char *buf = malloc(len), *tmp = buf;
177 _printf(1, "Mouse wheel\n");
178 _printf(2, "%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
179 STORE_INT(tmp, n_evas);
180 STORE_INT(tmp, t->direction);
181 STORE_INT(tmp, t->z);
182 eina_debug_session_send(_session, _cid, _mouse_wheel_op, buf, len);
183 break;
184 }
185 case EXACTNESS_ACTION_MULTI_DOWN:
186 case EXACTNESS_ACTION_MULTI_UP:
187 {
188 Exactness_Action_Multi_Event *t = data;
189 int len = 5*sizeof(int)+7*sizeof(double)+sizeof(int);
190 char *buf = malloc(len), *tmp = buf;
191 _printf(2, "%s %s n_evas=<%d>\n", __func__,
192 type == EXACTNESS_ACTION_MULTI_DOWN ? "evas_event_feed_multi_down" :
193 "evas_event_feed_multi_up", n_evas);
194 STORE_INT(tmp, n_evas);
195 STORE_INT(tmp, t->d);
196 STORE_INT(tmp, t->b);
197 STORE_INT(tmp, t->x);
198 STORE_INT(tmp, t->y);
199 STORE_DOUBLE(tmp, t->rad);
200 STORE_DOUBLE(tmp, t->radx);
201 STORE_DOUBLE(tmp, t->rady);
202 STORE_DOUBLE(tmp, t->pres);
203 STORE_DOUBLE(tmp, t->ang);
204 STORE_DOUBLE(tmp, t->fx);
205 STORE_DOUBLE(tmp, t->fy);
206 STORE_INT(tmp, t->flags);
207 eina_debug_session_send(_session, _cid,
208 type == EXACTNESS_ACTION_MULTI_DOWN ? _multi_down_op : _multi_up_op,
209 buf, len);
210 break;
211 }
212 case EXACTNESS_ACTION_MULTI_MOVE:
213 {
214 Exactness_Action_Multi_Move *t = data;
215 int len = 4*sizeof(int)+7*sizeof(double);
216 char *buf = malloc(len), *tmp = buf;
217 _printf(2, "%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
218 STORE_INT(tmp, n_evas);
219 STORE_INT(tmp, t->d);
220 STORE_INT(tmp, t->x);
221 STORE_INT(tmp, t->y);
222 STORE_DOUBLE(tmp, t->rad);
223 STORE_DOUBLE(tmp, t->radx);
224 STORE_DOUBLE(tmp, t->rady);
225 STORE_DOUBLE(tmp, t->pres);
226 STORE_DOUBLE(tmp, t->ang);
227 STORE_DOUBLE(tmp, t->fx);
228 STORE_DOUBLE(tmp, t->fy);
229 eina_debug_session_send(_session, _cid, _multi_move_op, buf, len);
230 break;
231 }
232 case EXACTNESS_ACTION_KEY_DOWN:
233 case EXACTNESS_ACTION_KEY_UP:
234 {
235 Exactness_Action_Key_Down_Up *t = data;
236 int len = 2*sizeof(int) + 4;
237 len += t->keyname ? strlen(t->keyname) : 0;
238 len += t->key ? strlen(t->key) : 0;
239 len += t->string ? strlen(t->string) : 0;
240 len += t->compose ? strlen(t->compose) : 0;
241 char *buf = malloc(len), *tmp = buf;
242 _printf(2, "%s %s n_evas=<%d>\n", __func__,
243 type == EXACTNESS_ACTION_KEY_DOWN ? "evas_event_feed_key_down " :
244 "evas_event_feed_key_up", n_evas);
245 STORE_INT(tmp, n_evas);
246 STORE_STRING(tmp, t->keyname);
247 STORE_STRING(tmp, t->key);
248 STORE_STRING(tmp, t->string);
249 STORE_STRING(tmp, t->compose);
250 STORE_INT(tmp, t->keycode);
251 eina_debug_session_send(_session, _cid,
252 type == EXACTNESS_ACTION_KEY_DOWN ? _key_down_op : _key_up_op,
253 buf, len);
254 break;
255 }
256 case EXACTNESS_ACTION_TAKE_SHOT:
257 {
258 _printf(2, "%s take shot n_evas=<%d>\n", __func__, n_evas);
259 eina_debug_session_send(_session, _cid, _take_shot_op, &n_evas, sizeof(int));
260 break;
261 }
262 case EXACTNESS_ACTION_EFL_EVENT:
263 {
264 Exactness_Action_Efl_Event *t = data;
265 int len = 0;
266 len += t->wdg_name ? strlen(t->wdg_name) : 0;
267 len += t->event_name ? strlen(t->event_name) : 0;
268 char *buf = malloc(len), *tmp = buf;
269 _printf(2, "%s %s\n", __func__, "EFL event");
270 STORE_STRING(tmp, t->wdg_name);
271 STORE_STRING(tmp, t->event_name);
272 eina_debug_session_send(_session, _cid, _efl_event_op, buf, len);
273 break;
274 }
275 case EXACTNESS_ACTION_CLICK_ON:
276 {
277 Exactness_Action_Click_On *t = data;
278 int len = 0;
279 len += t->wdg_name ? strlen(t->wdg_name) : 0;
280 char *buf = malloc(len), *tmp = buf;
281 _printf(2, "%s %s\n", __func__, "Click On");
282 STORE_STRING(tmp, t->wdg_name);
283 eina_debug_session_send(_session, _cid, _click_on_op, buf, len);
284 break;
285 }
286 case EXACTNESS_ACTION_STABILIZE:
287 {
288 _printf(2, "%s stabilize\n", __func__);
289 eina_debug_session_send(_session, _cid, _stabilize_op, NULL, 0);
290 break;
291 }
292 default: /* All non-input events are not handeled */
293 break;
294 }
295}
296
297static Eina_Bool
298_feed_event_timer_cb(void *data EINA_UNUSED)
299{
300 Exactness_Action *act = eina_list_data_get(_cur_event_list);
301 _feed_event(act->type, act->n_evas, act->data);
302
303 _cur_event_list = eina_list_next(_cur_event_list);
304
305 if (!_cur_event_list)
306 { /* Finished reading all events */
307 eina_debug_session_send(_session, _cid, _finish_op, NULL, 0);
308 ecore_main_loop_quit();
309 }
310 else
311 {
312 Exactness_Action *cur_act = eina_list_data_get(_cur_event_list);
313 ecore_timer_add(cur_act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
314 }
315 return ECORE_CALLBACK_CANCEL;
316}
317
318static Eina_Bool
319_src_open()
320{
321 double diff_time = 0; /* Time to wait before feeding the first event */
322
323 _printf(2, "<%s> Source file is <%s>\n", __func__, _src_filename);
324 if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
325 {
326 _src_unit = exactness_unit_file_read(_src_filename);
327 }
328 else if (!strcmp(_src_filename + strlen(_src_filename) - 4,".rec"))
329 {
330 _src_unit = legacy_rec_file_read(_src_filename);
331 }
332 if (!_src_unit) return EINA_FALSE;
333 _cur_event_list = _src_unit->actions;
334 Exactness_Action *act = eina_list_data_get(_cur_event_list);
335
336 if (act->delay_ms)
337 {
338 _printf(2, " Waiting <%f>\n", diff_time);
339 ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
340 }
341 else
342 {
343 _feed_event_timer_cb(NULL);
344 }
345 return EINA_TRUE;
346}
347
348static void
349_main_loop_all_apps_get_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
350{
351 char *buf = buffer;
352 int chosen_cid = -1;
353 if (_cid != -1) return;
354 while (size > 0)
355 {
356 int cid, pid, len;
357 cid = EXTRACT_INT(buf);
358 pid = EXTRACT_INT(buf);
359 if (_pid != -1)
360 {
361 if (_pid == pid)
362 {
363 _cid = cid;
364 _src_open();
365 return;
366 }
367 }
368 else
369 {
370 if (!strcmp(buf, "exactness_play"))
371 {
372 if (chosen_cid != -1)
373 {
374 fprintf(stderr, "Need to specify a PID - too much choice\n");
375 return;
376 }
377 chosen_cid = cid;
378 }
379 }
380 len = strlen(buf) + 1;
381 buf += len;
382 size -= (2 * sizeof(int) + len);
383 }
384 if (chosen_cid != -1)
385 {
386 _cid = chosen_cid;
387 _src_open();
388 }
389}
390
391WRAPPER_TO_XFER_MAIN_LOOP(_all_apps_get_cb)
392
393static void
394_ops_ready_cb(void *data EINA_UNUSED, Eina_Bool status)
395{
396 static Eina_Bool on = EINA_FALSE;
397 if (status)
398 {
399 if (!on)
400 {
401 eina_debug_session_send(_session, 0, _all_apps_get_op, NULL, 0);
402 }
403 on = EINA_TRUE;
404 }
405}
406
407static const Ecore_Getopt optdesc = {
408 "exactness_inject",
409 "%prog [options] <-v|-p|-t|-h> command",
410 PACKAGE_VERSION,
411 "(C) 2018 Enlightenment",
412 "BSD",
413 "A scenario events injector for EFL based applications.",
414 1,
415 {
416 ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
417 ECORE_GETOPT_STORE_INT('p', "pid", "PID of the application to connect to"),
418 ECORE_GETOPT_STORE_INT('r', "remote-port", "Port to connect remotely to the daemon. Local connection if not specified"),
419 ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
420
421 ECORE_GETOPT_LICENSE('L', "license"),
422 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
423 ECORE_GETOPT_VERSION('V', "version"),
424 ECORE_GETOPT_HELP('h', "help"),
425 ECORE_GETOPT_SENTINEL
426 }
427};
428
429int main(int argc, char **argv)
430{
431 int opt_args = 0, real__ = 1, port = -1;
432 char *src = NULL;
433 Eina_Value *ret__;
434 Eina_Bool want_quit = EINA_FALSE;
435
436 Ecore_Getopt_Value values[] = {
437 ECORE_GETOPT_VALUE_STR(src),
438 ECORE_GETOPT_VALUE_INT(_pid),
439 ECORE_GETOPT_VALUE_INT(port),
440 ECORE_GETOPT_VALUE_INT(_verbose),
441
442 ECORE_GETOPT_VALUE_BOOL(want_quit),
443 ECORE_GETOPT_VALUE_BOOL(want_quit),
444 ECORE_GETOPT_VALUE_BOOL(want_quit),
445 ECORE_GETOPT_VALUE_BOOL(want_quit),
446 ECORE_GETOPT_VALUE_NONE
447 };
448
449 eina_init();
450 eet_init();
451 ecore_init();
452
453 opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
454 if (opt_args < 0)
455 {
456 fprintf(stderr, "Failed parsing arguments.\n");
457 goto end;
458 }
459 if (want_quit) goto end;
460
461 if (!src)
462 {
463 fprintf(stderr, "no test file specified\n");
464 goto end;
465 }
466 _src_filename = eina_stringshare_add(src);
467
468 if (port == -1)
469 _session = eina_debug_local_connect(EINA_TRUE);
470 else
471 _session = eina_debug_remote_connect(port);
472 eina_debug_opcodes_register(_session, _debug_ops(), _ops_ready_cb, NULL);
473
474 elm_init(argc, argv);
475 ret__ = efl_loop_begin(efl_main_loop_get());
476 real__ = efl_loop_exit_code_process(ret__);
477 elm_shutdown();
478end:
479 eet_shutdown();
480 eina_shutdown();
481 return real__;
482}
483
diff --git a/src/bin/exactness/inspect.c b/src/bin/exactness/inspect.c
new file mode 100644
index 0000000000..54f6627f22
--- /dev/null
+++ b/src/bin/exactness/inspect.c
@@ -0,0 +1,1653 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifndef EFL_BETA_API_SUPPORT
6#define EFL_BETA_API_SUPPORT
7#endif
8#ifndef EFL_EO_API_SUPPORT
9#define EFL_EO_API_SUPPORT
10#endif
11#include <Ecore.h>
12#include <Ecore_Getopt.h>
13#include <Ecore_Evas.h>
14#include <Elementary.h>
15#include <Exactness.h>
16#include <Efl_Ui.h>
17
18#include "exactness_private.h"
19
20#define LDIFF(x) "<b><color=#F0F>"#x"</color></b>"
21#define RDIFF(x) "<b><color=#0FF>"#x"</color></b>"
22
23typedef enum
24{
25 EX_FONTS_DIR,
26 EX_SCENARIO,
27 EX_IMAGE,
28 EX_OBJ_INFO
29} _Data_Type;
30
31typedef struct
32{
33 void *p1;
34 void *p2;
35 _Data_Type dt;
36} _Compare_Item_Data;
37
38typedef struct
39{
40 void *ex_parent;
41 Eo *gl_item;
42} _Item_Info;
43
44static Eo *_main_box = NULL;
45static Eina_List *_gls = NULL;
46static Eina_List *_units = NULL;
47static Eo *_comp_selected_item = NULL;
48
49static Elm_Genlist_Item_Class *_grp_itc = NULL, *_scn_itc = NULL, *_img_itc = NULL;
50static Elm_Genlist_Item_Class *_objs_itc = NULL, *_obj_itc = NULL;
51
52static Eina_Hash *_item_infos_hash = NULL;
53
54static Eina_Bool _show_only_diffs = EINA_FALSE;
55static Eina_List *_comp_vvs = NULL;
56
57static Eina_List *_modified_units = NULL;
58
59static const char *
60_action_name_get(Exactness_Action *act)
61{
62 if (!act) return NULL;
63 switch(act->type)
64 {
65 case EXACTNESS_ACTION_MOUSE_IN: return "Mouse In";
66 case EXACTNESS_ACTION_MOUSE_OUT: return "Mouse Out";
67 case EXACTNESS_ACTION_MOUSE_WHEEL: return "Mouse Wheel";
68 case EXACTNESS_ACTION_MULTI_DOWN: return "Multi Down";
69 case EXACTNESS_ACTION_MULTI_UP: return "Multi Up";
70 case EXACTNESS_ACTION_MULTI_MOVE: return "Multi Move";
71 case EXACTNESS_ACTION_KEY_DOWN: return "Key Down";
72 case EXACTNESS_ACTION_KEY_UP: return "Key Up";
73 case EXACTNESS_ACTION_TAKE_SHOT: return "Take shot";
74 case EXACTNESS_ACTION_EFL_EVENT: return "EFL Event";
75 case EXACTNESS_ACTION_CLICK_ON: return "Click On";
76 case EXACTNESS_ACTION_STABILIZE: return "Stabilize";
77 default: return NULL;
78 }
79}
80
81static int
82_event_struct_len_get(Exactness_Action_Type type)
83{
84 switch(type)
85 {
86 case EXACTNESS_ACTION_MOUSE_WHEEL:
87 return sizeof(Exactness_Action_Mouse_Wheel);
88 case EXACTNESS_ACTION_MULTI_DOWN:
89 case EXACTNESS_ACTION_MULTI_UP:
90 return sizeof(Exactness_Action_Multi_Event);
91 case EXACTNESS_ACTION_MULTI_MOVE:
92 return sizeof(Exactness_Action_Multi_Move);
93 case EXACTNESS_ACTION_KEY_DOWN:
94 case EXACTNESS_ACTION_KEY_UP:
95 return sizeof(Exactness_Action_Key_Down_Up);
96 case EXACTNESS_ACTION_EFL_EVENT:
97 return sizeof(Exactness_Action_Efl_Event);
98 case EXACTNESS_ACTION_CLICK_ON:
99 return sizeof(Exactness_Action_Click_On);
100 default: return 0;
101 }
102}
103
104static void
105_action_specific_info_get(const Exactness_Action *act, char output[1024])
106{
107 switch(act->type)
108 {
109 case EXACTNESS_ACTION_MOUSE_WHEEL:
110 {
111 Exactness_Action_Mouse_Wheel *t = act->data;
112 sprintf(output, "Direction %d Z %d", t->direction, t->z);
113 break;
114 }
115 case EXACTNESS_ACTION_MULTI_UP: case EXACTNESS_ACTION_MULTI_DOWN:
116 {
117 Exactness_Action_Multi_Event *t = act->data;
118 if (!t->d)
119 sprintf(output, "Button %d Flags %d", t->b, t->flags);
120 else
121 sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f Flags %d",
122 t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy, t->flags);
123 break;
124 }
125 case EXACTNESS_ACTION_MULTI_MOVE:
126 {
127 Exactness_Action_Multi_Move *t = act->data;
128 if (!t->d)
129 sprintf(output, "X %d Y %d", t->x, t->y);
130 else
131 sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f",
132 t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy);
133 break;
134 }
135 case EXACTNESS_ACTION_KEY_UP: case EXACTNESS_ACTION_KEY_DOWN:
136 {
137 Exactness_Action_Key_Down_Up *t = act->data;
138 sprintf(output, "Keyname %s Key %s String %s Compose %s Keycode %d",
139 t->keyname, t->key, t->string, t->compose, t->keycode);
140 break;
141 }
142 case EXACTNESS_ACTION_EFL_EVENT:
143 {
144 Exactness_Action_Efl_Event *t = act->data;
145 sprintf(output, "Widget %s Event %s", t->wdg_name, t->event_name);
146 break;
147 }
148 case EXACTNESS_ACTION_CLICK_ON:
149 {
150 Exactness_Action_Click_On *t = act->data;
151 sprintf(output, "Widget %s", t->wdg_name);
152 break;
153 }
154 default:
155 {
156 output[0] = '\0';
157 break;
158 }
159 }
160}
161
162static Eina_Bool
163_is_hook_duplicate(const Exactness_Action *cur_act, const Exactness_Action *prev_act)
164{
165 if (!prev_act) return EINA_FALSE;
166 if (cur_act->type == prev_act->type)
167 {
168 int len = _event_struct_len_get(cur_act->type);
169 return (!len || !memcmp(cur_act->data, prev_act->data, len));
170 }
171 return EINA_FALSE;
172}
173
174static Eina_Bool
175_are_scenario_entries_different(Exactness_Action *act1, Exactness_Action *act2)
176{
177 if (!act1 ^ !act2) return EINA_TRUE;
178 if (act1->type != act2->type) return EINA_TRUE;
179 switch(act1->type)
180 {
181 case EXACTNESS_ACTION_MOUSE_WHEEL:
182 return !!memcmp(act1->data, act2->data, sizeof(Exactness_Action_Mouse_Wheel));
183 case EXACTNESS_ACTION_MULTI_DOWN: case EXACTNESS_ACTION_MULTI_UP:
184 return !!memcmp(act1->data, act2->data, sizeof(Exactness_Action_Multi_Event));
185 case EXACTNESS_ACTION_MULTI_MOVE:
186 return !!memcmp(act1->data, act2->data, sizeof(Exactness_Action_Multi_Move));
187 case EXACTNESS_ACTION_KEY_UP: case EXACTNESS_ACTION_KEY_DOWN:
188 return !!memcmp(act1->data, act2->data, sizeof(Exactness_Action_Key_Down_Up));
189 case EXACTNESS_ACTION_EFL_EVENT:
190 {
191 Exactness_Action_Efl_Event *e1 = act1->data;
192 Exactness_Action_Efl_Event *e2 = act2->data;
193 return (!!strcmp(e1->wdg_name, e2->wdg_name) ||
194 !!strcmp(e1->event_name, e2->event_name));
195 }
196 case EXACTNESS_ACTION_CLICK_ON:
197 {
198 Exactness_Action_Click_On *e1 = act1->data;
199 Exactness_Action_Click_On *e2 = act2->data;
200 return (!!strcmp(e1->wdg_name, e2->wdg_name));
201 }
202 default:
203 return EINA_FALSE;
204 }
205 return EINA_FALSE;
206}
207
208static Eina_Bool
209_are_images_different(Exactness_Image *e_img1, Exactness_Image *e_img2)
210{
211 unsigned int w, h;
212 int *pxs1 = NULL;
213 int *pxs2 = NULL;
214 if (!e_img1 ^ !e_img2) return EINA_TRUE;
215 if (e_img1->w != e_img2->w) return EINA_TRUE;
216 if (e_img1->h != e_img2->h) return EINA_TRUE;
217 pxs1 = e_img1->pixels;
218 pxs2 = e_img2->pixels;
219 for (w = 0; w < e_img1->w; w++)
220 {
221 for (h = 0; h < e_img1->h; h++)
222 {
223 if (pxs1[h * e_img1->w + w] != pxs2[h * e_img1->w + w])
224 return EINA_TRUE;
225 }
226 }
227 return EINA_FALSE;
228}
229
230static Eina_Bool
231_are_objs_different(Exactness_Object *e_obj1, Exactness_Object *e_obj2, Eina_Bool check_objs)
232{
233 if (!e_obj1 ^ !e_obj2) return EINA_TRUE;
234 Eina_List *itr1 = e_obj1->children;
235 Eina_List *itr2 = e_obj2->children;
236 if (check_objs &&
237 (strcmp(e_obj1->kl_name, e_obj2->kl_name) ||
238 e_obj1->x != e_obj2->x || e_obj1->y != e_obj2->y ||
239 e_obj1->w != e_obj2->w || e_obj1->h != e_obj2->h)) return EINA_TRUE;
240 while (itr1 || itr2)
241 {
242 if ((!itr1) ^ (!itr2)) return EINA_TRUE;
243 e_obj1 = eina_list_data_get(itr1);
244 e_obj2 = eina_list_data_get(itr2);
245
246 if (_are_objs_different(e_obj1, e_obj2, EINA_TRUE)) return EINA_TRUE;
247
248 itr1 = eina_list_next(itr1);
249 itr2 = eina_list_next(itr2);
250 }
251 return EINA_FALSE;
252}
253
254static Eina_Bool
255_are_objs_trees_different(Exactness_Objects *e_objs1, Exactness_Objects *e_objs2)
256{
257 if (!e_objs1 ^ !e_objs2) return EINA_TRUE;
258 Eina_List *itr1 = e_objs1->objs;
259 Eina_List *itr2 = e_objs2->objs;
260 Exactness_Object *e_obj1, *e_obj2;
261 while (itr1 || itr2)
262 {
263 if ((!itr1) ^ (!itr2)) return EINA_TRUE;
264 e_obj1 = eina_list_data_get(itr1);
265 e_obj2 = eina_list_data_get(itr2);
266
267 if (_are_objs_different(e_obj1, e_obj2, EINA_TRUE)) return EINA_TRUE;
268
269 itr1 = eina_list_next(itr1);
270 itr2 = eina_list_next(itr2);
271 }
272 return EINA_FALSE;
273}
274
275static void
276_win_del(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
277{
278 efl_exit(0); /* exit the program's main loop that runs in elm_run() */
279}
280
281static void
282_gui_win_create()
283{
284 Eo *win, *bg;
285
286 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
287 win = elm_win_add(NULL, "Window", ELM_WIN_BASIC);
288 evas_object_smart_callback_add(win, "delete,request", _win_del, NULL);
289 elm_win_maximized_set(win, EINA_TRUE);
290 elm_win_autodel_set(win, EINA_TRUE);
291 elm_win_title_set(win, "Exactness Inspector");
292 efl_gfx_entity_size_set(win, EINA_SIZE2D(1000, 800));
293
294 bg = elm_bg_add(win);
295 evas_object_size_hint_weight_set(bg, 1.000000, 1.000000);
296 efl_gfx_entity_visible_set(bg, EINA_TRUE);
297 elm_win_resize_object_add(win, bg);
298
299 _main_box = elm_box_add(win);
300 elm_box_horizontal_set(_main_box, EINA_TRUE);
301 elm_box_homogeneous_set(_main_box, EINA_TRUE);
302 evas_object_size_hint_weight_set(_main_box, 1.000000, 1.000000);
303 efl_gfx_entity_visible_set(_main_box, EINA_TRUE);
304 elm_win_resize_object_add(win, _main_box);
305
306 efl_gfx_entity_visible_set(win, EINA_TRUE);
307}
308
309static char *
310_grp_text_get(void *data, Evas_Object *gl, const char *part EINA_UNUSED)
311{
312 char buf[256];
313 const char *str = NULL;
314 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
315 _Data_Type dt = (_Data_Type) data;
316 switch (dt)
317 {
318 case EX_FONTS_DIR:
319 {
320 char buf2[256];
321 if (!compare)
322 {
323 Exactness_Unit *unit = efl_key_data_get(gl, "unit");
324 sprintf(buf2, "Fonts directory: %s", unit->fonts_path?unit->fonts_path:"None");
325 }
326 else
327 {
328 Eo *gl1 = eina_list_nth(_gls, 0);
329 Eo *gl2 = eina_list_nth(_gls, 1);
330 Exactness_Unit *unit1 = efl_key_data_get(gl1, "unit");
331 Exactness_Unit *unit2 = efl_key_data_get(gl2, "unit");
332 if (!!unit1->fonts_path ^ !!unit2->fonts_path)
333 sprintf(buf2, "Fonts directory comparison: XXXXX");
334 else if (!strcmp(unit1->fonts_path, unit2->fonts_path))
335 sprintf(buf2, "Fonts directory comparison: %s", unit1->fonts_path);
336 else
337 sprintf(buf2, "Fonts directory comparison: "LDIFF(%s)"/"RDIFF(%s),
338 unit1->fonts_path, unit2->fonts_path);
339 }
340 return strdup(buf2);
341 }
342 case EX_SCENARIO: { str = "Scenario"; break; }
343 case EX_IMAGE: { str = "Images"; break; }
344 case EX_OBJ_INFO: { str = "Objects"; break; }
345 default: { str = "Unknown"; break; }
346 }
347 sprintf(buf, "%s%s", str, compare ? " comparison" : "");
348 if (dt == EX_FONTS_DIR) eina_stringshare_del(str);
349 return strdup(buf);
350}
351
352static char *
353_scn_text_get(void *data, Evas_Object *gl, const char *part EINA_UNUSED)
354{
355 Eina_Strbuf *buf = eina_strbuf_new();
356 char *ret = NULL;
357 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
358 if (compare)
359 {
360 _Compare_Item_Data *vv = data;
361 Exactness_Action *a1 = vv->p1;
362 Exactness_Action *a2 = vv->p2;
363
364 if (!a1 ^ !a2) return strdup("XXXXX");
365
366 if (a1->delay_ms != a2->delay_ms) eina_strbuf_append_printf(buf, "[+"LDIFF(%.3f)"/+"RDIFF(%.3f)"]: ", a1->delay_ms/1000.0, a2->delay_ms/1000.0);
367 else eina_strbuf_append_printf(buf, "+%.3f: ", a1->delay_ms / 1000.0);
368
369 if (a1->type != a2->type)
370 eina_strbuf_append_printf(buf, "["LDIFF(%s)"/"RDIFF(%s)"] - XXXXXX", _action_name_get(a1), _action_name_get(a2));
371 else
372 {
373 char params1[1024];
374 char params2[2024];
375 _action_specific_info_get(a1, params1);
376 _action_specific_info_get(a2, params2);
377
378 eina_strbuf_append_printf(buf, "%s", _action_name_get(a1));
379 if (*params1 || *params2)
380 {
381 if (strcmp(params1, params2))
382 eina_strbuf_append_printf(buf, " - ["LDIFF(%s)"/"RDIFF(%s)"]", params1, params2);
383 else
384 eina_strbuf_append_printf(buf, " - %s", params1);
385 }
386 }
387 }
388 else
389 {
390 Exactness_Action *act = data;
391 char specific_output[1024];
392 if (act)
393 {
394 eina_strbuf_append_printf(buf, "+%.3f: ", act->delay_ms / 1000.0);
395 eina_strbuf_append_printf(buf, "%s", _action_name_get(act));
396 _action_specific_info_get(act, specific_output);
397 if (*specific_output) eina_strbuf_append_printf(buf, " - %s", specific_output);
398 }
399 else
400 eina_strbuf_append(buf, "XXXXX");
401 }
402
403 ret = eina_strbuf_string_steal(buf);
404 eina_strbuf_free(buf);
405 return ret;
406}
407
408static int
409_unit_shot_no_get(Exactness_Unit *unit, Exactness_Action *act_ref)
410{
411 Eina_List *itr;
412 Exactness_Action *act;
413 int ret = 0;
414 if (!unit) return -1;
415 EINA_LIST_FOREACH(unit->actions, itr, act)
416 {
417 if (act->type == EXACTNESS_ACTION_TAKE_SHOT)
418 {
419 if (act == act_ref) return ret;
420 ret++;
421 }
422 }
423 return -1;
424}
425
426static void
427_goto_shot(void *data EINA_UNUSED, Evas_Object *bt, void *event_info EINA_UNUSED)
428{
429 Eo *gl = efl_key_data_get(bt, "gl");
430 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
431 if (compare)
432 {
433 _Compare_Item_Data *vv;
434 Eina_List *itr;
435 Eo *gl1 = eina_list_nth(_gls, 0);
436 Eo *gl2 = eina_list_nth(_gls, 1);
437 Exactness_Unit *unit1 = efl_key_data_get(gl1, "unit");
438 Exactness_Unit *unit2 = efl_key_data_get(gl2, "unit");
439 int shot1_no = (intptr_t)efl_key_data_get(bt, "shot1_no");
440 int shot2_no = (intptr_t)efl_key_data_get(bt, "shot2_no");
441 Exactness_Image *ex_img1 = shot1_no != -1 ? eina_list_nth(unit1->imgs, shot1_no) : NULL;
442 Exactness_Image *ex_img2 = shot2_no != -1 ? eina_list_nth(unit2->imgs, shot2_no) : NULL;
443 EINA_LIST_FOREACH(_comp_vvs, itr, vv)
444 {
445 if (vv->p1 == ex_img1 && vv->p2 == ex_img2)
446 {
447 _Item_Info *ii = eina_hash_find(_item_infos_hash, &vv);
448 if (ii && ii->gl_item)
449 elm_genlist_item_show(ii->gl_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
450 }
451 }
452 }
453 else
454 {
455 Exactness_Unit *unit = efl_key_data_get(gl, "unit");
456 int shot_no = (intptr_t)efl_key_data_get(bt, "shot_no");
457 Exactness_Image *ex_img = shot_no != -1 ? eina_list_nth(unit->imgs, shot_no) : NULL;
458 _Item_Info *ii = eina_hash_find(_item_infos_hash, &ex_img);
459 if (ii && ii->gl_item)
460 elm_genlist_item_show(ii->gl_item, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
461 }
462}
463
464static Evas_Object *
465_scn_content_get(void *data, Evas_Object *gl, const char *part)
466{
467 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
468 if (compare)
469 {
470 if (!strcmp(part, "elm.swallow.end"))
471 {
472 _Compare_Item_Data *vv = data;
473 Exactness_Action *v1 = vv->p1;
474 Exactness_Action *v2 = vv->p2;
475 if (v1 && v2 && v1->type == EXACTNESS_ACTION_TAKE_SHOT &&
476 v2->type == EXACTNESS_ACTION_TAKE_SHOT)
477 {
478 Eo *gl1 = eina_list_nth(_gls, 0);
479 Eo *gl2 = eina_list_nth(_gls, 1);
480 Exactness_Unit *unit1 = efl_key_data_get(gl1, "unit");
481 Exactness_Unit *unit2 = efl_key_data_get(gl2, "unit");
482 int shot1_no = _unit_shot_no_get(unit1, v1);
483 int shot2_no = _unit_shot_no_get(unit2, v2);
484 Exactness_Image *ex_img1 = shot1_no != -1 ? eina_list_nth(unit1->imgs, shot1_no) : NULL;
485 Exactness_Image *ex_img2 = shot2_no != -1 ? eina_list_nth(unit2->imgs, shot2_no) : NULL;
486 Exactness_Image *ex_imgO = NULL;
487 exactness_image_compare(ex_img1, ex_img2, &ex_imgO);
488
489 if (ex_imgO)
490 {
491 Eo *bt, *ic, *evas_img;
492
493 bt = elm_button_add(gl);
494 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
495 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
496 evas_object_show(bt);
497 efl_key_data_set(bt, "gl", gl);
498 efl_key_data_set(bt, "shot1_no", (void *)(intptr_t)shot1_no);
499 efl_key_data_set(bt, "shot2_no", (void *)(intptr_t)shot2_no);
500 evas_object_smart_callback_add(bt, "clicked", _goto_shot, NULL);
501
502 ic = elm_icon_add(bt);
503 evas_img = elm_image_object_get(ic);
504 evas_object_image_size_set(evas_img, ex_imgO->w, ex_imgO->h);
505 evas_object_image_data_set(evas_img, ex_imgO->pixels);
506 evas_object_show(ic);
507 elm_object_part_content_set(bt, "icon", ic);
508 return bt;
509 }
510 }
511 }
512 }
513 else
514 {
515 if (!strcmp(part, "elm.swallow.end"))
516 {
517 Exactness_Action *v = data;
518 Exactness_Unit *unit = efl_key_data_get(gl, "unit");
519 int shot_no = _unit_shot_no_get(unit, v);
520 Exactness_Image *ex_img = shot_no != -1 ? eina_list_nth(unit->imgs, shot_no) : NULL;
521
522 if (ex_img)
523 {
524 Eo *bt, *ic, *evas_img;
525
526 bt = elm_button_add(gl);
527 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
528 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
529 evas_object_show(bt);
530 efl_key_data_set(bt, "gl", gl);
531 efl_key_data_set(bt, "shot_no", (void *)(intptr_t)shot_no);
532 evas_object_smart_callback_add(bt, "clicked", _goto_shot, NULL);
533
534 ic = elm_icon_add(bt);
535 evas_img = elm_image_object_get(ic);
536 evas_object_image_size_set(evas_img, ex_img->w, ex_img->h);
537 evas_object_image_data_set(evas_img, ex_img->pixels);
538 evas_object_show(ic);
539 elm_object_part_content_set(bt, "icon", ic);
540
541 return bt;
542 }
543 }
544 }
545 return NULL;
546}
547
548static Evas_Object *
549_img_content_get(void *data, Evas_Object *gl, const char *part)
550{
551 if (strcmp(part, "elm.swallow.content")) return NULL;
552 Eo *img = elm_image_add(gl);
553 Eo *evas_img = elm_image_object_get(img);
554 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
555 if (compare)
556 {
557 _Compare_Item_Data *vv = data;
558 Exactness_Image *ex_img1 = vv->p1;
559 Exactness_Image *ex_img2 = vv->p2;
560 Exactness_Image *ex_imgO = NULL;
561 exactness_image_compare(ex_img1, ex_img2, &ex_imgO);
562
563 evas_object_image_size_set(evas_img, ex_imgO->w, ex_imgO->h);
564 evas_object_image_data_set(evas_img, ex_imgO->pixels);
565 evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(300), ELM_SCALE_SIZE(300));
566 }
567 else
568 {
569 if (!data)
570 {
571 efl_del(img);
572 return NULL;
573 }
574 Exactness_Image *ex_img = data;
575 evas_object_image_size_set(evas_img, ex_img->w, ex_img->h);
576 evas_object_image_data_set(evas_img, ex_img->pixels);
577 evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(300), ELM_SCALE_SIZE(300));
578 }
579 return img;
580}
581
582static char *
583_objs_text_get(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED)
584{
585 return strdup("Shot");
586}
587
588static char *
589_obj_text_get(void *data, Evas_Object *gl, const char *part EINA_UNUSED)
590{
591 Eina_Strbuf *buf = eina_strbuf_new();
592 char *ret = NULL;
593 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
594 if (compare)
595 {
596 _Compare_Item_Data *vv = data;
597 Exactness_Object *e_obj1 = vv->p1;
598 Exactness_Object *e_obj2 = vv->p2;
599 if ((!e_obj1 ^ !e_obj2) || strcmp(e_obj1->kl_name, e_obj2->kl_name))
600 eina_strbuf_append_printf(buf, "("LDIFF(%s)"/"RDIFF(%s)")",
601 e_obj1 ? e_obj1->kl_name : "XXXXX",
602 e_obj2 ? e_obj2->kl_name : "XXXXX");
603 else
604 eina_strbuf_append_printf(buf, "%s", e_obj1->kl_name);
605
606 eina_strbuf_append(buf, " x = ");
607 if ((!e_obj1 ^ !e_obj2) || e_obj1->x != e_obj2->x)
608 eina_strbuf_append_printf(buf, LDIFF(%d)"/"RDIFF(%d),
609 e_obj1 ? e_obj1->x : -1,
610 e_obj2 ? e_obj2->x : -1);
611 else
612 eina_strbuf_append_printf(buf, "%d", e_obj1->x);
613
614 eina_strbuf_append(buf, " y = ");
615 if ((!e_obj1 ^ !e_obj2) || e_obj1->y != e_obj2->y)
616 eina_strbuf_append_printf(buf, LDIFF(%d)"/"RDIFF(%d),
617 e_obj1 ? e_obj1->y : -1,
618 e_obj2 ? e_obj2->y : -1);
619 else
620 eina_strbuf_append_printf(buf, "%d", e_obj1->y);
621
622 eina_strbuf_append(buf, " w = ");
623 if ((!e_obj1 ^ !e_obj2) || e_obj1->w != e_obj2->w)
624 eina_strbuf_append_printf(buf, LDIFF(%d)"/"RDIFF(%d),
625 e_obj1 ? e_obj1->w : -1,
626 e_obj2 ? e_obj2->w : -1);
627 else
628 eina_strbuf_append_printf(buf, "%d", e_obj1->w);
629
630 eina_strbuf_append(buf, " h = ");
631 if ((!e_obj1 ^ !e_obj2) || e_obj1->h != e_obj2->h)
632 eina_strbuf_append_printf(buf, LDIFF(%d)"/"RDIFF(%d),
633 e_obj1 ? e_obj1->h : -1,
634 e_obj2 ? e_obj2->h : -1);
635 else
636 eina_strbuf_append_printf(buf, "%d", e_obj1->h);
637
638 if (e_obj1 && e_obj2 && _are_objs_different(e_obj1, e_obj2, EINA_FALSE))
639 eina_strbuf_append(buf, " - DIFF INSIDE");
640 }
641 else
642 {
643 Exactness_Object *e_obj = data;
644 eina_strbuf_append_printf(buf,
645 "%s: x = %d y = %d w = %d h = %d",
646 e_obj->kl_name,
647 e_obj->x, e_obj->y, e_obj->w, e_obj->h);
648 }
649
650 ret = eina_strbuf_string_steal(buf);
651 eina_strbuf_free(buf);
652 return ret;
653}
654
655static void
656_itc_init()
657{
658 if (!_grp_itc)
659 {
660 _grp_itc = elm_genlist_item_class_new();
661 _grp_itc->item_style = "group_index";
662 _grp_itc->func.text_get = _grp_text_get;
663 }
664
665 if (!_scn_itc)
666 {
667 _scn_itc = elm_genlist_item_class_new();
668 _scn_itc->item_style = "default_style";
669 _scn_itc->func.text_get = _scn_text_get;
670 _scn_itc->func.content_get = _scn_content_get;
671 }
672
673 if (!_img_itc)
674 {
675 _img_itc = elm_genlist_item_class_new();
676 _img_itc->item_style = "full";
677 _img_itc->func.content_get = _img_content_get;
678 }
679
680 if (!_objs_itc)
681 {
682 _objs_itc = elm_genlist_item_class_new();
683 _objs_itc->item_style = "default_style";
684 _objs_itc->func.text_get = _objs_text_get;
685 }
686
687 if (!_obj_itc)
688 {
689 _obj_itc = elm_genlist_item_class_new();
690 _obj_itc->item_style = "default_style";
691 _obj_itc->func.text_get = _obj_text_get;
692 }
693}
694
695static void
696_comp_gl_dragged_cb(Evas_Object *obj, void *data EINA_UNUSED)
697{
698 int x = 0, y = 0;
699 Eo *gl;
700 Eina_List *itr;
701 elm_interface_scrollable_content_pos_get(obj, &x, &y);
702 EINA_LIST_FOREACH(_gls, itr, gl)
703 {
704 if (gl != obj)
705 elm_interface_scrollable_content_pos_set(gl, x, y, EINA_FALSE);
706 }
707}
708
709static void
710_obj_item_realize(Exactness_Object *ex_obj)
711{
712 _Item_Info *ii = eina_hash_find(_item_infos_hash, &ex_obj);
713 if (!ii) return;
714 if (ii->gl_item) return;
715 _obj_item_realize(ii->ex_parent);
716 _Item_Info *iip = eina_hash_find(_item_infos_hash, &(ii->ex_parent));
717 if (iip->gl_item) elm_genlist_item_expanded_set(iip->gl_item, EINA_TRUE);
718}
719
720static void
721_gl_expand_request_cb(void *data EINA_UNUSED, Evas_Object *gl, void *event_info)
722{
723 Elm_Object_Item *glit = event_info;
724 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
725 if (compare)
726 {
727 const Elm_Genlist_Item_Class *itc = elm_genlist_item_item_class_get(glit);
728 if (itc == _objs_itc)
729 {
730 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
731 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p1));
732 if (ii) elm_genlist_item_expanded_set(ii->gl_item, EINA_TRUE);
733 ii = eina_hash_find(_item_infos_hash, &(vv->p2));
734 if (ii) elm_genlist_item_expanded_set(ii->gl_item, EINA_TRUE);
735 }
736 else if (itc == _obj_itc)
737 {
738 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
739 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p1));
740 if (!ii || !ii->gl_item) _obj_item_realize(vv->p1);
741 if (!ii) ii = eina_hash_find(_item_infos_hash, &(vv->p1));
742 if (ii && ii->gl_item) elm_genlist_item_expanded_set(ii->gl_item, EINA_TRUE);
743
744 ii = eina_hash_find(_item_infos_hash, &(vv->p2));
745 if (!ii || !ii->gl_item) _obj_item_realize(vv->p2);
746 if (!ii) ii = eina_hash_find(_item_infos_hash, &(vv->p2));
747 if (ii && ii->gl_item) elm_genlist_item_expanded_set(ii->gl_item, EINA_TRUE);
748 }
749 }
750 elm_genlist_item_expanded_set(glit, EINA_TRUE);
751}
752
753static void
754_gl_contract_request_cb(void *data EINA_UNUSED, Evas_Object *gl EINA_UNUSED, void *event_info)
755{
756 Elm_Object_Item *glit = event_info;
757 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
758 if (compare)
759 {
760 const Elm_Genlist_Item_Class *itc = elm_genlist_item_item_class_get(glit);
761 if (itc == _objs_itc)
762 {
763 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
764 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p1));
765 if (ii) elm_genlist_item_expanded_set(ii->gl_item, EINA_FALSE);
766 ii = eina_hash_find(_item_infos_hash, &(vv->p2));
767 if (ii) elm_genlist_item_expanded_set(ii->gl_item, EINA_FALSE);
768 }
769 else if (itc == _obj_itc)
770 {
771 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
772 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p1));
773 if (ii && ii->gl_item) elm_genlist_item_expanded_set(ii->gl_item, EINA_FALSE);
774
775 ii = eina_hash_find(_item_infos_hash, &(vv->p2));
776 if (ii && ii->gl_item) elm_genlist_item_expanded_set(ii->gl_item, EINA_FALSE);
777 }
778 }
779 elm_genlist_item_expanded_set(glit, EINA_FALSE);
780}
781
782static void
783_gl_expanded_cb(void *_data EINA_UNUSED, Evas_Object *gl EINA_UNUSED, void *event_info)
784{
785 Elm_Object_Item *glit = event_info;
786 const Elm_Genlist_Item_Class *itc = elm_genlist_item_item_class_get(glit);
787 Eina_Bool compare = !!efl_key_data_get(gl, "_exactness_gl_compare");
788 if (itc == _objs_itc)
789 {
790 if (compare)
791 {
792 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
793 Exactness_Objects *e_objs1 = vv->p1;
794 Exactness_Objects *e_objs2 = vv->p2;
795 Eina_List *itr1 = e_objs1->main_objs, *itr2 = e_objs2->main_objs;
796
797 while (itr1 || itr2)
798 {
799 Exactness_Object *e_obj1 = eina_list_data_get(itr1);
800 Exactness_Object *e_obj2 = eina_list_data_get(itr2);
801 vv = calloc(1, sizeof(*vv));
802 vv->p1 = e_obj1;
803 vv->p2 = e_obj2;
804 vv->dt = EX_OBJ_INFO;
805 elm_genlist_item_append(gl, _obj_itc, vv, glit,
806 e_obj1->children || e_obj2->children ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
807 NULL, NULL);
808 itr1 = eina_list_next(itr1);
809 itr2 = eina_list_next(itr2);
810 }
811 }
812 else
813 {
814 Exactness_Objects *e_objs = elm_object_item_data_get(glit);
815 Eina_List *itr;
816 Exactness_Object *e_obj;
817 EINA_LIST_FOREACH(e_objs->main_objs, itr, e_obj)
818 {
819 _Item_Info *ii = eina_hash_find(_item_infos_hash, &e_obj);
820 if (!ii)
821 {
822 ii = calloc(1, sizeof(*ii));
823 eina_hash_set(_item_infos_hash, &e_obj, ii);
824 }
825 ii->ex_parent = e_objs;
826 ii->gl_item = elm_genlist_item_append(gl, _obj_itc, e_obj, glit,
827 e_obj->children ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
828 NULL, NULL);
829 efl_wref_add(ii->gl_item, &(ii->gl_item));
830 }
831 }
832 }
833 else if (itc == _obj_itc)
834 {
835 if (compare)
836 {
837 _Compare_Item_Data *vv = elm_object_item_data_get(glit);
838 Exactness_Object *e_obj1 = vv->p1;
839 Exactness_Object *e_obj2 = vv->p2;
840 Eina_List *itr1 = e_obj1->children, *itr2 = e_obj2->children;
841
842 while (itr1 || itr2)
843 {
844 e_obj1 = eina_list_data_get(itr1);
845 e_obj2 = eina_list_data_get(itr2);
846 vv = calloc(1, sizeof(*vv));
847 vv->p1 = e_obj1;
848 vv->p2 = e_obj2;
849 vv->dt = EX_OBJ_INFO;
850 elm_genlist_item_append(gl, _obj_itc, vv, glit,
851 (e_obj1 && e_obj1->children) || (e_obj2 && e_obj2->children) ?
852 ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
853 NULL, NULL);
854 itr1 = eina_list_next(itr1);
855 itr2 = eina_list_next(itr2);
856 }
857 }
858 else
859 {
860 Exactness_Object *e_obj = elm_object_item_data_get(glit), *e_obj2;
861 Eina_List *itr;
862
863 EINA_LIST_FOREACH(e_obj->children, itr, e_obj2)
864 {
865 _Item_Info *ii = eina_hash_find(_item_infos_hash, &e_obj2);
866 if (!ii)
867 {
868 ii = calloc(1, sizeof(*ii));
869 eina_hash_set(_item_infos_hash, &e_obj2, ii);
870 }
871 ii->ex_parent = e_obj;
872 ii->gl_item = elm_genlist_item_append(gl, _obj_itc, e_obj2, glit,
873 e_obj2->children ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
874 NULL, NULL);
875 efl_wref_add(ii->gl_item, &(ii->gl_item));
876 }
877 }
878 }
879}
880
881static void
882_gl_contracted_cb(void *data EINA_UNUSED, Evas_Object *gl EINA_UNUSED, void *event_info)
883{
884 Elm_Object_Item *glit = event_info;
885 elm_genlist_item_subitems_clear(glit);
886}
887
888static void
889_comp_gl_selected_cb(void *data EINA_UNUSED, Evas_Object *gl EINA_UNUSED, void *event_info)
890{
891 _comp_selected_item = event_info;
892 _Compare_Item_Data *vv = elm_object_item_data_get(_comp_selected_item);
893 if (vv->p1)
894 {
895 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p1));
896 if (!ii || !ii->gl_item) _obj_item_realize(vv->p1);
897 elm_genlist_item_selected_set(ii->gl_item, EINA_TRUE);
898 }
899
900 if (vv->p2)
901 {
902 _Item_Info *ii = eina_hash_find(_item_infos_hash, &(vv->p2));
903 if (!ii || !ii->gl_item) _obj_item_realize(vv->p2);
904 elm_genlist_item_selected_set(ii->gl_item, EINA_TRUE);
905 }
906}
907
908static void
909_scn_item_remove(void *data, Evas_Object *menu EINA_UNUSED, void *item EINA_UNUSED)
910{
911 Eo *glit = data;
912 Exactness_Unit *unit = efl_key_data_get(efl_parent_get(glit), "unit");
913 Exactness_Action *act = elm_object_item_data_get(glit);
914 unit->actions = eina_list_remove(unit->actions, act);
915 if (!eina_list_data_find(_modified_units, unit))
916 _modified_units = eina_list_append(_modified_units, unit);
917 efl_del(glit);
918}
919
920static void
921_gl_clicked_right_cb(void *data, Evas_Object *gl, void *event_info)
922{
923 int x = 0, y = 0;
924 Eo *win = data, *menu;
925 Elm_Object_Item *glit = event_info;
926
927 if (elm_genlist_item_item_class_get(glit) == _scn_itc)
928 {
929 elm_genlist_item_selected_set(glit, EINA_TRUE);
930 evas_pointer_canvas_xy_get(evas_object_evas_get(gl), &x, &y);
931
932 menu = elm_menu_add(win);
933 elm_menu_move(menu, x, y);
934 elm_menu_item_add(menu, NULL, NULL, "Remove", _scn_item_remove, glit);
935 efl_gfx_entity_visible_set(menu, EINA_TRUE);
936 }
937}
938
939static void
940_gl_img_show(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
941{
942 static Eo *_img_win = NULL;
943 Exactness_Image *ex_img = data;
944 if (_img_win) efl_del(_img_win);
945 _img_win = efl_add(EFL_UI_WIN_CLASS, elm_win_get(obj),
946 efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_DIALOG_BASIC),
947 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
948 efl_wref_add(_img_win, &_img_win);
949
950 Evas_Object *image = elm_image_add(_img_win);
951 Eo *evas_img = elm_image_object_get(image);
952 evas_object_image_size_set(evas_img, ex_img->w, ex_img->h);
953 evas_object_image_data_set(evas_img, ex_img->pixels);
954 efl_content_set(_img_win, image);
955
956 efl_gfx_entity_size_set(_img_win, EINA_SIZE2D(550, 500));
957}
958
959static void
960_gui_unit_display(Exactness_Unit *unit1, Exactness_Unit *unit2)
961{
962 Eina_List *itr1, *itr2;
963 Eo *gl1, *gl2 = NULL, *glc = NULL;
964
965 gl1 = elm_genlist_add(_main_box);
966 elm_genlist_homogeneous_set(gl1, EINA_TRUE);
967 evas_object_size_hint_weight_set(gl1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
968 evas_object_size_hint_align_set(gl1, EVAS_HINT_FILL, EVAS_HINT_FILL);
969 efl_gfx_entity_visible_set(gl1, EINA_TRUE);
970 _gls = eina_list_append(_gls, gl1);
971 elm_box_pack_end(_main_box, gl1);
972
973 efl_key_data_set(gl1, "unit", unit1);
974 evas_object_smart_callback_add(gl1, "expand,request", _gl_expand_request_cb, NULL);
975 evas_object_smart_callback_add(gl1, "contract,request", _gl_contract_request_cb, NULL);
976 evas_object_smart_callback_add(gl1, "expanded", _gl_expanded_cb, NULL);
977 evas_object_smart_callback_add(gl1, "contracted", _gl_contracted_cb, NULL);
978 if (!unit2)
979 evas_object_smart_callback_add(gl1, "clicked,right", _gl_clicked_right_cb, elm_win_get(_main_box));
980
981 if (unit2)
982 {
983 glc = elm_genlist_add(_main_box);
984 elm_genlist_homogeneous_set(glc, EINA_TRUE);
985 evas_object_size_hint_weight_set(glc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
986 evas_object_size_hint_align_set(glc, EVAS_HINT_FILL, EVAS_HINT_FILL);
987 efl_gfx_entity_visible_set(glc, EINA_TRUE);
988 elm_box_pack_end(_main_box, glc);
989
990 evas_object_smart_callback_add(glc, "expand,request", _gl_expand_request_cb, NULL);
991 evas_object_smart_callback_add(glc, "contract,request", _gl_contract_request_cb, NULL);
992 evas_object_smart_callback_add(glc, "expanded", _gl_expanded_cb, NULL);
993 evas_object_smart_callback_add(glc, "contracted", _gl_contracted_cb, NULL);
994
995 efl_key_data_set(glc, "_exactness_gl_compare", glc);
996 elm_interface_scrollable_scroll_down_cb_set(glc, _comp_gl_dragged_cb);
997 elm_interface_scrollable_scroll_up_cb_set(glc, _comp_gl_dragged_cb);
998 evas_object_smart_callback_add(glc, "selected", _comp_gl_selected_cb, NULL);
999
1000 gl2 = elm_genlist_add(_main_box);
1001 elm_genlist_homogeneous_set(gl2, EINA_TRUE);
1002 evas_object_size_hint_weight_set(gl2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1003 evas_object_size_hint_align_set(gl2, EVAS_HINT_FILL, EVAS_HINT_FILL);
1004 efl_gfx_entity_visible_set(gl2, EINA_TRUE);
1005 _gls = eina_list_append(_gls, gl2);
1006 elm_box_pack_end(_main_box, gl2);
1007
1008 efl_key_data_set(gl2, "unit", unit2);
1009 evas_object_smart_callback_add(gl2, "expand,request", _gl_expand_request_cb, NULL);
1010 evas_object_smart_callback_add(gl2, "contract,request", _gl_contract_request_cb, NULL);
1011 evas_object_smart_callback_add(gl2, "expanded", _gl_expanded_cb, NULL);
1012 evas_object_smart_callback_add(gl2, "contracted", _gl_contracted_cb, NULL);
1013 }
1014 _itc_init();
1015
1016 if (unit1->fonts_path || (unit2 && unit2->fonts_path))
1017 {
1018 if (!_show_only_diffs || !unit1 || !unit2 ||
1019 !unit1->fonts_path || !unit2->fonts_path ||
1020 strcmp(unit1->fonts_path, unit2->fonts_path))
1021 {
1022 elm_genlist_item_append(gl1, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1023 elm_genlist_item_append(gl2, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1024 elm_genlist_item_append(glc, _grp_itc, (void *)EX_FONTS_DIR, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1025 }
1026 }
1027 itr1 = unit1 ? unit1->actions : NULL;
1028 itr2 = unit2 ? unit2->actions : NULL;
1029
1030 if (itr1 || itr2)
1031 {
1032 elm_genlist_item_append(gl1, _grp_itc, (void *)EX_SCENARIO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1033 elm_genlist_item_append(gl2, _grp_itc, (void *)EX_SCENARIO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1034 elm_genlist_item_append(glc, _grp_itc, (void *)EX_SCENARIO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1035 }
1036 while (itr1 || itr2)
1037 {
1038 Exactness_Action *v1 = itr1 ? eina_list_data_get(itr1) : NULL;
1039 Exactness_Action *v2 = itr2 ? eina_list_data_get(itr2) : NULL;
1040 if (!_show_only_diffs || _are_scenario_entries_different(v1, v2))
1041 {
1042 _Item_Info *ii = calloc(1, sizeof(*ii));
1043 eina_hash_set(_item_infos_hash, &v1, ii);
1044 ii->gl_item = elm_genlist_item_append(gl1, _scn_itc, v1, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
1045 if (unit2)
1046 {
1047 _Compare_Item_Data *vv = calloc(1, sizeof(*vv));
1048 vv->p1 = v1;
1049 vv->p2 = v2;
1050 vv->dt = EX_SCENARIO;
1051 ii = calloc(1, sizeof(*ii));
1052 eina_hash_set(_item_infos_hash, &v2, ii);
1053 ii->gl_item = elm_genlist_item_append(gl2, _scn_itc, v2, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
1054 elm_genlist_item_append(glc, _scn_itc, vv, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
1055 }
1056 }
1057 if (itr1) itr1 = eina_list_next(itr1);
1058 if (itr2) itr2 = eina_list_next(itr2);
1059 }
1060
1061 itr1 = unit1 ? unit1->imgs : NULL;
1062 itr2 = unit2 ? unit2->imgs : NULL;
1063
1064 if (itr1 || itr2)
1065 {
1066 elm_genlist_item_append(gl1, _grp_itc, (void *)EX_IMAGE, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1067 elm_genlist_item_append(gl2, _grp_itc, (void *)EX_IMAGE, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1068 elm_genlist_item_append(glc, _grp_itc, (void *)EX_IMAGE, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1069 }
1070 while (itr1 || itr2)
1071 {
1072 Exactness_Image *img1 = itr1 ? eina_list_data_get(itr1) : NULL;
1073 Exactness_Image *img2 = itr2 ? eina_list_data_get(itr2) : NULL;
1074 if (!_show_only_diffs || _are_images_different(img1, img2))
1075 {
1076 _Item_Info *ii = calloc(1, sizeof(*ii));
1077 eina_hash_set(_item_infos_hash, &img1, ii);
1078 ii->gl_item = elm_genlist_item_append(gl1, _img_itc, img1, NULL, ELM_GENLIST_ITEM_NONE, _gl_img_show, img1);
1079 if (unit2)
1080 {
1081 _Compare_Item_Data *vv = calloc(1, sizeof(*vv));
1082 vv->p1 = img1;
1083 vv->p2 = img2;
1084 vv->dt = EX_IMAGE;
1085 ii = calloc(1, sizeof(*ii));
1086 eina_hash_set(_item_infos_hash, &img2, ii);
1087 ii->gl_item = elm_genlist_item_append(gl2, _img_itc, img2, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
1088 /* This item info is needed to go to images from scenario shot entry */
1089 ii = calloc(1, sizeof(*ii));
1090 eina_hash_set(_item_infos_hash, &vv, ii);
1091 ii->gl_item = elm_genlist_item_append(glc, _img_itc, vv, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
1092 _comp_vvs = eina_list_append(_comp_vvs, vv);
1093 }
1094 }
1095 if (itr1) itr1 = eina_list_next(itr1);
1096 if (itr2) itr2 = eina_list_next(itr2);
1097 }
1098
1099 itr1 = unit1 ? unit1->objs : NULL;
1100 itr2 = unit2 ? unit2->objs : NULL;
1101
1102 if (itr1 || itr2)
1103 {
1104 elm_genlist_item_append(gl1, _grp_itc, (void *)EX_OBJ_INFO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1105 elm_genlist_item_append(gl2, _grp_itc, (void *)EX_OBJ_INFO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1106 elm_genlist_item_append(glc, _grp_itc, (void *)EX_OBJ_INFO, NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL);
1107 }
1108 while (itr1 || itr2)
1109 {
1110 Exactness_Objects *objs1 = itr1 ? eina_list_data_get(itr1) : NULL;
1111 Exactness_Objects *objs2 = itr2 ? eina_list_data_get(itr2) : NULL;
1112 if (!_show_only_diffs || _are_objs_trees_different(objs1, objs2))
1113 {
1114 _Item_Info *ii = calloc(1, sizeof(*ii));
1115 eina_hash_set(_item_infos_hash, &objs1, ii);
1116 ii->gl_item = elm_genlist_item_append(gl1, _objs_itc, objs1, NULL,
1117 ELM_GENLIST_ITEM_TREE, NULL, NULL);
1118 efl_wref_add(ii->gl_item, &(ii->gl_item));
1119 if (unit2)
1120 {
1121 _Compare_Item_Data *vv = calloc(1, sizeof(*vv));
1122 vv->p1 = objs1;
1123 vv->p2 = objs2;
1124 vv->dt = EX_OBJ_INFO;
1125 ii = calloc(1, sizeof(*ii));
1126 eina_hash_set(_item_infos_hash, &objs2, ii);
1127 ii->gl_item = elm_genlist_item_append(gl2, _objs_itc, objs2, NULL,
1128 ELM_GENLIST_ITEM_TREE, NULL, NULL);
1129 efl_wref_add(ii->gl_item, &(ii->gl_item));
1130 elm_genlist_item_append(glc, _objs_itc, vv, NULL, ELM_GENLIST_ITEM_TREE, NULL, NULL);
1131 }
1132 }
1133 if (itr1) itr1 = eina_list_next(itr1);
1134 if (itr2) itr2 = eina_list_next(itr2);
1135 }
1136}
1137
1138static void
1139_diff_result_print(Exactness_Unit *unit1, Exactness_Unit *unit2)
1140{
1141 Eina_List *itr1, *itr2;
1142
1143 int nb_scenario = 0, nb_diff_scenario = 0;
1144 int nb_image = 0, nb_diff_image = 0;
1145 int nb_objtree= 0, nb_diff_objtree = 0;
1146
1147 itr1 = unit1 ? unit1->actions : NULL;
1148 itr2 = unit2 ? unit2->actions : NULL;
1149
1150 while (itr1 || itr2)
1151 {
1152 Exactness_Action *v1 = itr1 ? eina_list_data_get(itr1) : NULL;
1153 Exactness_Action *v2 = itr2 ? eina_list_data_get(itr2) : NULL;
1154
1155 nb_scenario++;
1156 if (_are_scenario_entries_different(v1, v2))
1157 nb_diff_scenario++;
1158
1159 if (itr1) itr1 = eina_list_next(itr1);
1160 if (itr2) itr2 = eina_list_next(itr2);
1161 }
1162
1163 itr1 = unit1 ? unit1->imgs : NULL;
1164 itr2 = unit2 ? unit2->imgs : NULL;
1165
1166 while (itr1 || itr2)
1167 {
1168 Exactness_Image *img1 = itr1 ? eina_list_data_get(itr1) : NULL;
1169 Exactness_Image *img2 = itr2 ? eina_list_data_get(itr2) : NULL;
1170
1171 nb_image++;
1172 if (_are_images_different(img1, img2))
1173 nb_diff_image++;
1174
1175 if (itr1) itr1 = eina_list_next(itr1);
1176 if (itr2) itr2 = eina_list_next(itr2);
1177 }
1178
1179 itr1 = unit1 ? unit1->objs : NULL;
1180 itr2 = unit2 ? unit2->objs : NULL;
1181
1182 while (itr1 || itr2)
1183 {
1184 Exactness_Objects *objs1 = itr1 ? eina_list_data_get(itr1) : NULL;
1185 Exactness_Objects *objs2 = itr2 ? eina_list_data_get(itr2) : NULL;
1186
1187 nb_objtree++;
1188 if (_are_objs_trees_different(objs1, objs2))
1189 nb_diff_objtree++;
1190
1191 if (itr1) itr1 = eina_list_next(itr1);
1192 if (itr2) itr2 = eina_list_next(itr2);
1193 }
1194
1195 printf("%s\nscenario (%d/%d)\nimage (%d/%d)\nobjs_tree (%d/%d)\n",
1196 nb_diff_scenario || nb_diff_image || nb_diff_objtree ?
1197 "Failure" : "Success",
1198 nb_scenario - nb_diff_scenario, nb_scenario,
1199 nb_image - nb_diff_image, nb_image,
1200 nb_objtree - nb_diff_objtree, nb_objtree);
1201}
1202
1203static Exactness_Image *
1204_image_read(const char *filename)
1205{
1206 int w, h;
1207 Evas_Load_Error err;
1208 Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
1209
1210 /* the canvas pointer, de facto */
1211 Eo *e = ecore_evas_get(ee);
1212
1213 Eo *img = evas_object_image_add(e);
1214 evas_object_image_file_set(img, filename, NULL);
1215 err = evas_object_image_load_error_get(img);
1216 if (err != EVAS_LOAD_ERROR_NONE)
1217 {
1218 fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
1219 filename, evas_load_error_str(err));
1220 return NULL;
1221 }
1222
1223 Exactness_Image *ex_img = malloc(sizeof(*ex_img));
1224 int len;
1225 evas_object_image_size_get(img, &w, &h);
1226 ex_img->w = w;
1227 ex_img->h = h;
1228 len = w * h * 4;
1229 ex_img->pixels = malloc(len);
1230 memcpy(ex_img->pixels, evas_object_image_data_get(img, EINA_FALSE), len);
1231
1232 ecore_evas_free(ee);
1233 return ex_img;
1234}
1235
1236static const Ecore_Getopt optdesc = {
1237 "exactness_inspect",
1238 "%prog [options] [<rec file> | <file1 file2>]",
1239 NULL,
1240 "(C) 2016 Enlightenment",
1241 "BSD",
1242 "Inspector for Exactness",
1243 0,
1244 {
1245 ECORE_GETOPT_STORE_USHORT('d', "delay", "Delay the given recording by a given time (in milliseconds)."),
1246 ECORE_GETOPT_STORE_TRUE('c', "clean", "Clean the given recording from wrong actions."),
1247 ECORE_GETOPT_STORE_TRUE('l', "list", "List the actions of the given recording."),
1248 ECORE_GETOPT_STORE_TRUE('C', "compare", "Compare given files (images files or objects eet files)."),
1249 ECORE_GETOPT_STORE_TRUE(0, "show-only-diffs", "Show only differences during comparison."),
1250 ECORE_GETOPT_STORE_TRUE(0, "stabilize", "Stabilize after the given shot number in --shot."),
1251 ECORE_GETOPT_STORE_TRUE(0, "pack", "Pack the given input files (scenario and images) into the given output."),
1252 ECORE_GETOPT_STORE_STR('o', "output", "Output."),
1253 ECORE_GETOPT_STORE_USHORT('s', "shot", "Select a specific shot (1 = 1st shot...)."),
1254
1255 ECORE_GETOPT_LICENSE('L', "license"),
1256 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
1257 ECORE_GETOPT_VERSION('V', "version"),
1258 ECORE_GETOPT_HELP('h', "help"),
1259 ECORE_GETOPT_SENTINEL
1260 }
1261};
1262
1263int
1264main(int argc, char *argv[])
1265{
1266 Eina_List *units_filenames = NULL;
1267 const char *ext = NULL;
1268 char *output = NULL;
1269 Exactness_Unit *unit = NULL;
1270 int ret = 1, args = 0;
1271 unsigned short delay = 0, shot = 0;
1272 Eina_Bool write_file = EINA_FALSE;
1273 Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE, compare_files = EINA_FALSE;
1274 Eina_Bool stabilize = EINA_FALSE, show_only_diffs = EINA_FALSE, gui_needed = EINA_TRUE;
1275 Eina_Bool pack = EINA_FALSE;
1276
1277 Ecore_Getopt_Value values[] = {
1278 ECORE_GETOPT_VALUE_USHORT(delay),
1279 ECORE_GETOPT_VALUE_BOOL(clean),
1280 ECORE_GETOPT_VALUE_BOOL(list_get),
1281 ECORE_GETOPT_VALUE_BOOL(compare_files),
1282 ECORE_GETOPT_VALUE_BOOL(show_only_diffs),
1283 ECORE_GETOPT_VALUE_BOOL(stabilize),
1284 ECORE_GETOPT_VALUE_BOOL(pack),
1285 ECORE_GETOPT_VALUE_STR(output),
1286 ECORE_GETOPT_VALUE_USHORT(shot),
1287
1288 ECORE_GETOPT_VALUE_BOOL(want_quit),
1289 ECORE_GETOPT_VALUE_BOOL(want_quit),
1290 ECORE_GETOPT_VALUE_BOOL(want_quit),
1291 ECORE_GETOPT_VALUE_BOOL(want_quit),
1292 ECORE_GETOPT_VALUE_NONE
1293 };
1294
1295 ecore_evas_init();
1296 ecore_init();
1297 eet_init();
1298 elm_init(0, NULL);
1299 want_quit = EINA_FALSE;
1300
1301 args = ecore_getopt_parse(&optdesc, values, argc, argv);
1302 if (args < 0)
1303 {
1304 fprintf(stderr, "Failed parsing arguments.\n");
1305 goto end;
1306 }
1307 if (want_quit)
1308 {
1309 goto end;
1310 }
1311 if ((clean || delay || shot || list_get || stabilize || pack) && args == argc)
1312 {
1313 fprintf(stderr, "Expected scenario (.rec/.exu) as the last argument.\n");
1314 ecore_getopt_help(stderr, &optdesc);
1315 goto end;
1316 }
1317 if (shot && (!delay && !stabilize))
1318 {
1319 fprintf(stderr, "shot option can only be used with delay or stabilize option.\n");
1320 goto end;
1321 }
1322 if (delay && !shot)
1323 {
1324 fprintf(stderr, "delay option can only be used with shot option.\n");
1325 goto end;
1326 }
1327 if (stabilize && !shot)
1328 {
1329 fprintf(stderr, "stabilize option can only be used with shot option.\n");
1330 goto end;
1331 }
1332 if (compare_files && argc - args < 2)
1333 {
1334 fprintf(stderr, "Expected at least two files to compare as last arguments.\n");
1335 ecore_getopt_help(stderr, &optdesc);
1336 goto end;
1337 }
1338 if (show_only_diffs && !compare_files)
1339 {
1340 fprintf(stderr, "--show-only-diffs is available with --compare only\n");
1341 goto end;
1342 }
1343 if (show_only_diffs && output)
1344 {
1345 fprintf(stderr, "--show-only-diffs works in GUI only\n");
1346 goto end;
1347 }
1348 _show_only_diffs = show_only_diffs;
1349
1350 if (clean || delay || list_get || stabilize || pack)
1351 {
1352 int arg;
1353 Eina_List *images = NULL;
1354 gui_needed = EINA_FALSE;
1355 for (arg = args; arg < argc; arg++)
1356 {
1357 const char *src_file = argv[arg];
1358 ext = strrchr(src_file, '.');
1359 if (!ext)
1360 {
1361 fprintf(stderr, "Extension required\n");
1362 goto end;
1363 }
1364 if (!strcmp(ext, ".exu"))
1365 {
1366 if (!unit) unit = exactness_unit_file_read(src_file);
1367 else
1368 {
1369 fprintf(stderr, "%s - scenario already provided\n", src_file);
1370 goto end;
1371 }
1372 }
1373 else if (!strcmp(ext, ".rec"))
1374 {
1375 if (!unit) unit = legacy_rec_file_read(src_file);
1376 else
1377 {
1378 fprintf(stderr, "%s - scenario already provided\n", src_file);
1379 goto end;
1380 }
1381 }
1382 else if (!strcmp(ext, ".png"))
1383 {
1384 Exactness_Image *ex_img = _image_read(src_file);
1385 if (!ex_img)
1386 {
1387 fprintf(stderr, "Issue while reading %s\n", src_file);
1388 goto end;
1389 }
1390 images = eina_list_append(images, ex_img);
1391 }
1392 else
1393 {
1394 fprintf(stderr, "Correct extension (.exu/.rec/.png) required\n");
1395 goto end;
1396 }
1397 }
1398 if (unit)
1399 {
1400 Exactness_Image *ex_img;
1401 EINA_LIST_FREE(images, ex_img)
1402 {
1403 unit->imgs = eina_list_append(unit->imgs, ex_img);
1404 unit->nb_shots++;
1405 }
1406 }
1407 }
1408 else
1409 {
1410 int arg;
1411 if (output) gui_needed = EINA_FALSE;
1412 for (arg = args; arg < argc; arg++)
1413 {
1414 ext = strrchr(argv[arg], '.');
1415 if (!ext)
1416 {
1417 fprintf(stderr, "Extension required\n");
1418 goto end;
1419 }
1420 if (!strcmp(ext, ".exu"))
1421 {
1422 Exactness_Unit *ex_unit = exactness_unit_file_read(argv[arg]);
1423 units_filenames = eina_list_append(units_filenames, argv[arg]);
1424 _units = eina_list_append(_units, ex_unit);
1425 }
1426 else if (!strcmp(ext, ".rec"))
1427 {
1428 Exactness_Unit *ex_unit = legacy_rec_file_read(argv[arg]);
1429 if (!ex_unit)
1430 {
1431 fprintf(stderr, "Issue while reading %s\n", argv[arg]);
1432 goto end;
1433 }
1434 _units = eina_list_append(_units, ex_unit);
1435 }
1436 else if (!strcmp(ext, ".png"))
1437 {
1438 Exactness_Unit *ex_unit = calloc(1, sizeof(*ex_unit));
1439 Exactness_Image *ex_img = _image_read(argv[arg]);
1440 if (!ex_img)
1441 {
1442 fprintf(stderr, "Issue while reading %s\n", argv[arg]);
1443 goto end;
1444 }
1445 ex_unit->imgs = eina_list_append(ex_unit->imgs, ex_img);
1446 ex_unit->nb_shots++;
1447 _units = eina_list_append(_units, ex_unit);
1448 }
1449 }
1450 }
1451
1452 if (clean)
1453 {
1454 Exactness_Action *act;
1455 Eina_List *itr, *itr2;
1456 EINA_LIST_FOREACH_SAFE(unit->actions, itr, itr2, act)
1457 {
1458 Exactness_Action *prev_act = eina_list_data_get(eina_list_prev(itr));
1459 if (_is_hook_duplicate(act, prev_act))
1460 {
1461 prev_act->delay_ms += act->delay_ms;
1462 unit->actions = eina_list_remove_list(unit->actions, itr);
1463 }
1464 }
1465 EINA_LIST_REVERSE_FOREACH_SAFE(unit->actions, itr, itr2, act)
1466 {
1467 if (act->type == EXACTNESS_ACTION_TAKE_SHOT) break;
1468 unit->actions = eina_list_remove(unit->actions, act);
1469 }
1470 write_file = EINA_TRUE;
1471 }
1472
1473 if (delay || stabilize)
1474 {
1475 Exactness_Action *act;
1476 Eina_List *itr;
1477 unsigned int cur_shot = 0;
1478 EINA_LIST_FOREACH(unit->actions, itr, act)
1479 {
1480 if (act->type == EXACTNESS_ACTION_TAKE_SHOT)
1481 {
1482 cur_shot++;
1483 if (cur_shot == shot)
1484 {
1485 if (delay) act->delay_ms = delay;
1486 if (stabilize)
1487 {
1488 Exactness_Action *s_act = malloc(sizeof(*s_act));
1489 s_act->type = EXACTNESS_ACTION_STABILIZE;
1490 s_act->delay_ms = act->delay_ms;
1491 s_act->n_evas = act->n_evas;
1492 s_act->data = NULL;
1493 act->delay_ms = 0; /* Shot right after stabilization */
1494 unit->actions = eina_list_prepend_relative(unit->actions, s_act, act);
1495 }
1496 write_file = EINA_TRUE;
1497 break;
1498 }
1499 }
1500 }
1501 }
1502
1503 if (pack) write_file = EINA_TRUE;
1504
1505 if (list_get)
1506 {
1507 Exactness_Action *act;
1508 Eina_List *itr;
1509 if (unit->fonts_path) printf("Fonts dir: %s\n", unit->fonts_path);
1510 EINA_LIST_FOREACH(unit->actions, itr, act)
1511 {
1512 char specific_output[1024];
1513 printf("+%.3f: %s", act->delay_ms / 1000.0, _action_name_get(act));
1514 _action_specific_info_get(act, specific_output);
1515 if (*specific_output) printf(" - %s", specific_output);
1516 printf("\n");
1517 }
1518 }
1519
1520 if (compare_files && output)
1521 {
1522 const char *out_ext = strrchr(output, '.');
1523 Exactness_Unit *unit1 = NULL, *unit2 = NULL, *unitO = NULL;
1524 int nb_diffs = 0;
1525 Eina_List *itr1, *itr2;
1526 EINA_LIST_FOREACH(_units, itr1, unit)
1527 {
1528 if (!unit1) unit1 = unit;
1529 else if (!unit2) unit2 = unit;
1530 else
1531 {
1532 fprintf(stderr, "Too much files to compare (only 2).\n");
1533 goto end;
1534 }
1535 }
1536
1537 if (!strcmp(out_ext, ".png"))
1538 {
1539 if (unit1->nb_shots != 1 || unit2->nb_shots != 1)
1540 {
1541 fprintf(stderr, "Comparison output can be png only if the number of shots to compare is 1.\n");
1542 goto end;
1543 }
1544 }
1545
1546 itr1 = unit1 ? unit1->imgs : NULL;
1547 itr2 = unit2 ? unit2->imgs : NULL;
1548
1549 while (itr1 || itr2)
1550 {
1551 Exactness_Image *ex_img1 = itr1 ? eina_list_data_get(itr1) : NULL;
1552 Exactness_Image *ex_img2 = itr2 ? eina_list_data_get(itr2) : NULL;
1553 Exactness_Image *ex_imgO = NULL;
1554 Eina_Bool has_diff = exactness_image_compare(ex_img1, ex_img2, &ex_imgO);
1555 if (has_diff || !strcmp(out_ext, ".exu"))
1556 {
1557 if (has_diff) nb_diffs++;
1558 if (!unitO) unitO = calloc(1, sizeof(*unitO));
1559 unitO->imgs = eina_list_append(unitO->imgs, ex_imgO);
1560 unitO->nb_shots++;
1561 }
1562 itr1 = eina_list_next(itr1);
1563 itr2 = eina_list_next(itr2);
1564 }
1565 if (!strcmp(out_ext, ".png"))
1566 {
1567 Ecore_Evas *ee;
1568 Eo *e, *img;
1569 if (unitO->nb_shots == 1)
1570 {
1571 Exactness_Image *ex_imgO = eina_list_data_get(unitO->imgs);
1572 ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL);
1573 e = ecore_evas_get(ee);
1574 img = evas_object_image_add(e);
1575 evas_object_image_size_set(img, ex_imgO->w, ex_imgO->h);
1576 evas_object_image_data_set(img, ex_imgO->pixels);
1577 evas_object_image_save(img, output, NULL, NULL);
1578 ecore_evas_free(ee);
1579 goto end;
1580 }
1581 ret = 0;
1582 }
1583 else if (!strcmp(out_ext, ".exu"))
1584 {
1585 _diff_result_print(unit1, unit2);
1586 if (nb_diffs) exactness_unit_file_write(unitO, output);
1587 else ret = 0;
1588 }
1589 else
1590 {
1591 fprintf(stderr, "Correct output extension (.exu/.png) required\n");
1592 }
1593 goto end;
1594 }
1595
1596 ret = 0;
1597 if (write_file)
1598 {
1599 if (!output)
1600 {
1601 fprintf(stderr, "An output file is required to write the modifications.\n");
1602 }
1603 else
1604 {
1605 const char *out_ext = strrchr(output, '.');
1606 if (!out_ext || strcmp(out_ext, ".exu"))
1607 {
1608 fprintf(stderr, "Only exu extension is supported as output.\n");
1609 goto end;
1610 }
1611 exactness_unit_file_write(unit, output);
1612 }
1613 goto end;
1614 }
1615
1616 if (gui_needed)
1617 {
1618 Eina_List *itr;
1619 Exactness_Unit *unit1 = NULL, *unit2 = NULL;
1620 Eina_Bool need_compare = compare_files && eina_list_count(_units) == 2;
1621 _item_infos_hash = eina_hash_pointer_new(NULL);
1622 _gui_win_create();
1623 EINA_LIST_FOREACH(_units, itr, unit)
1624 {
1625 if (need_compare)
1626 {
1627 if (!unit1) unit1 = unit;
1628 else unit2 = unit;
1629 }
1630 else _gui_unit_display(unit, NULL);
1631 }
1632 if (need_compare) _gui_unit_display(unit1, unit2);
1633 elm_run();
1634 EINA_LIST_FREE(_modified_units, unit)
1635 {
1636 int i = 0;
1637 EINA_LIST_FOREACH(_units, itr, unit2)
1638 {
1639 if (unit2 == unit) break;
1640 i++;
1641 }
1642 exactness_unit_file_write(unit, eina_list_nth(units_filenames, i));
1643 }
1644 }
1645
1646end:
1647 elm_shutdown();
1648 eet_shutdown();
1649 ecore_shutdown();
1650 ecore_evas_shutdown();
1651
1652 return ret;
1653}
diff --git a/src/bin/exactness/meson.build b/src/bin/exactness/meson.build
new file mode 100644
index 0000000000..6303e3fffe
--- /dev/null
+++ b/src/bin/exactness/meson.build
@@ -0,0 +1,42 @@
1exactness_bin = executable('exactness',
2 [ 'exactness.c' ],
3 dependencies: [ ecore, ecore_evas, ecore_file, exactness ],
4 install: true,
5 )
6
7exactness_inject_bin = executable('exactness_inject',
8 [ 'injector.c' ],
9 dependencies: [ elementary, exactness ],
10 install: true,
11 )
12
13exactness_inspect_bin = executable('exactness_inspect',
14 [ 'inspect.c' ],
15 dependencies: [ elementary, exactness ],
16 install: true,
17 )
18
19edjs = custom_target('player_entry',
20 input : 'player_entry.edc',
21 output : 'player_entry.edj',
22 install : true,
23 install_dir : 'share/exactness',
24 command : edje_cc_exe + [
25 '-id', join_paths(meson.source_root(), 'data', 'elementary', 'themes', 'img'),
26 '-sd', join_paths(meson.source_root(), 'data', 'elementary', 'themes', 'snd'),
27 '@INPUT@', '@OUTPUT@'],
28 depends : edje_cc)
29
30exactness_play_bin = executable('exactness_play',
31 [ 'player.c', edjs ],
32 dependencies: [ elementary, exactness ],
33 c_args: '-DDATA_DIR="'+join_paths(dir_data, 'exactness')+'"',
34 install: true,
35 )
36
37exactness_record_bin = executable('exactness_record',
38 [ 'recorder.c' ],
39 dependencies: [ elementary, exactness ],
40 install: true,
41 )
42
diff --git a/src/bin/exactness/player.c b/src/bin/exactness/player.c
new file mode 100644
index 0000000000..a2700f4653
--- /dev/null
+++ b/src/bin/exactness/player.c
@@ -0,0 +1,1393 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#define _POSIX_
6#include <limits.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <getopt.h>
10#include <unistd.h>
11
12#ifdef HAVE_FORK
13# ifdef HAVE_SYS_WAIT_H
14# include <sys/wait.h>
15# endif
16# ifdef HAVE_SYS_TYPES_H
17# include <sys/types.h>
18# endif
19# ifdef HAVE_SYS_SYSINFO_H
20# include <sys/sysinfo.h>
21# endif
22#endif
23
24#ifndef EFL_EO_API_SUPPORT
25#define EFL_EO_API_SUPPORT
26#endif
27#include <Eina.h>
28#include <Eo.h>
29#include <Evas.h>
30#include <Ecore.h>
31#include <Ecore_Getopt.h>
32#include <Ecore_File.h>
33#include <Ecore_Con.h>
34#include <Elementary.h>
35#include <Exactness.h>
36
37#include "exactness_private.h"
38
39#define PATH_ 1024
40#define IMAGE_FILENAME_EXT ".png"
41#define PAUSE_KEY_STR "F2"
42
43typedef struct
44{
45 Eina_Debug_Session *session;
46 int srcid;
47 void *buffer;
48 unsigned int size;
49} _Main_Loop_Info;
50
51#define WRAPPER_TO_XFER_MAIN_LOOP(foo) \
52static void \
53_intern_main_loop ## foo(void *data) \
54{ \
55 _Main_Loop_Info *info = data; \
56 _main_loop ## foo(info->session, info->srcid, info->buffer, info->size); \
57 free(info->buffer); \
58 free(info); \
59} \
60static Eina_Bool \
61foo(Eina_Debug_Session *session, int srcid, void *buffer, int size) \
62{ \
63 _Main_Loop_Info *info = calloc(1, sizeof(*info)); \
64 info->session = session; \
65 info->srcid = srcid; \
66 info->size = size; \
67 if (info->size) \
68 { \
69 info->buffer = malloc(info->size); \
70 memcpy(info->buffer, buffer, info->size); \
71 } \
72 ecore_main_loop_thread_safe_call_async(_intern_main_loop ## foo, info); \
73 return EINA_TRUE; \
74}
75
76#ifndef WORDS_BIGENDIAN
77#define SWAP_64(x) x
78#define SWAP_32(x) x
79#define SWAP_16(x) x
80#define SWAP_DBL(x) x
81#else
82#define SWAP_64(x) eina_swap64(x)
83#define SWAP_32(x) eina_swap32(x)
84#define SWAP_16(x) eina_swap16(x)
85#define SWAP_DBL(x) SWAP_64(x)
86#endif
87
88#define EXTRACT_INT(_buf) \
89({ \
90 int __i; \
91 memcpy(&__i, _buf, sizeof(int)); \
92 _buf += sizeof(int); \
93 SWAP_32(__i); \
94})
95
96#define EXTRACT_DOUBLE(_buf) \
97({ \
98 double __d; \
99 memcpy(&__d, _buf, sizeof(double)); \
100 _buf += sizeof(double); \
101 SWAP_DBL(__d); \
102})
103
104#define EXTRACT_STRING(_buf) \
105({ \
106 char *__s = _buf ? strdup(_buf) : NULL; \
107 int __len = (__s ? strlen(__s) : 0) + 1; \
108 _buf += __len; \
109 __s; \
110})
111
112#define STORE_INT(_buf, __i) \
113({ \
114 int __si = SWAP_32(__i); \
115 memcpy(_buf, &__si, sizeof(int)); \
116 _buf += sizeof(int); \
117})
118
119typedef enum
120{
121 FTYPE_UNKNOWN,
122 FTYPE_DIR,
123 FTYPE_REC = FTYPE_DIR,
124 FTYPE_EXU,
125 FTYPE_REMOTE
126} File_Type;
127
128static File_Type _dest_type = FTYPE_UNKNOWN;
129static Eina_Stringshare *_dest = NULL;
130static Exactness_Unit *_dest_unit = NULL;
131
132static File_Type _src_type = FTYPE_UNKNOWN;
133static Eina_Stringshare *_src_filename = NULL;
134static Exactness_Unit *_src_unit = NULL;
135
136static const char *_test_name = NULL;
137static int _verbose = 0;
138
139static Evas *(*_evas_new)(void) = NULL;
140static Eina_List *_evas_list = NULL;
141
142static Eina_List *_cur_event_list = NULL;
143
144static int _cur_shot_id = 0;
145static Eina_Bool _shot_needed = EINA_FALSE;
146static Eina_Bool _scan_objects = EINA_FALSE, _disable_shots = EINA_FALSE, _stabilize_shots = EINA_FALSE;
147
148static Eina_Debug_Session *_last_debug_session = NULL;
149static int _last_debug_src_cid = 0;
150static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
151
152static Eina_Bool _stabilization_timer_cb(void *);
153static double _speed = 1.0;
154
155static Eina_Bool _exit_required = EINA_FALSE;
156static Eina_Bool _pause_request = EINA_FALSE;
157static Eina_Bool _playing_status = EINA_FALSE;
158
159static void
160_printf(int verbose, const char *fmt, ...)
161{
162 va_list ap;
163 if (!_verbose || verbose > _verbose) return;
164
165 va_start(ap, fmt);
166 vprintf(fmt, ap);
167 va_end(ap);
168}
169
170static Exactness_Image *
171_snapshot_shot_get(Evas *e)
172{
173 Exactness_Image *ex_img;
174 Evas_Object *snapshot;
175 void *pixels;
176 int w, h, nb_bytes;
177
178 if (!e) return NULL;
179
180 evas_output_size_get(e, &w, &h);
181 if ((w < 1) || (h < 1)) return NULL;
182
183 snapshot = efl_key_data_get(e, "_snapshot");
184 if (!snapshot)
185 {
186 snapshot = evas_object_image_filled_add(e);
187 if (snapshot)
188 {
189 evas_object_image_snapshot_set(snapshot, EINA_TRUE);
190 evas_object_geometry_set(snapshot, 0, 0, w, h);
191 efl_gfx_entity_visible_set(snapshot, EINA_TRUE);
192 efl_key_data_set(e, "_snapshot", snapshot);
193 }
194 return NULL;
195 }
196
197 pixels = evas_object_image_data_get(snapshot, EINA_FALSE);
198 if (!pixels) return NULL;
199
200 ex_img = malloc(sizeof(*ex_img));
201 nb_bytes = w * h * 4;
202 ex_img->w = w;
203 ex_img->h = h;
204 ex_img->pixels = malloc(nb_bytes);
205 memcpy(ex_img->pixels, pixels, nb_bytes);
206 return ex_img;
207}
208
209static void
210_evas_render_post_cb(void *data EINA_UNUSED, const Efl_Event *event)
211{
212 if (_shot_needed)
213 {
214 Evas_Event_Render_Post *post = event->info;
215 void *e_data = efl_key_data_get(event->object, "_shot");
216
217 // Nothing was updated, so let's not bother sending nothingness
218 if (post && !post->updated_area) return;
219 Exactness_Image *ex_shot = efl_key_data_get(event->object, "_last_shot");
220 if (!ex_shot) ex_shot = _snapshot_shot_get(event->object);
221 if (!ex_shot) return;
222
223 efl_key_data_set(event->object, "_last_shot", NULL);
224
225 if (e_data)
226 {
227 if (_dest_type == FTYPE_DIR)
228 {
229 char *filename = e_data;
230 Eo *o = evas_object_image_add(event->object);
231 evas_object_image_size_set(o, ex_shot->w, ex_shot->h);
232 evas_object_image_data_set(o, ex_shot->pixels);
233 _printf(1, "Shot taken (%s).\n", filename);
234 if (!evas_object_image_save(o, filename, NULL, NULL))
235 {
236 printf("Cannot save widget to <%s>\n", filename);
237 }
238 free(filename);
239 }
240 else if (_dest_type == FTYPE_EXU)
241 {
242 Exactness_Image *ex_img = e_data;
243 memcpy(ex_img, ex_shot, sizeof(Exactness_Image));
244 ex_shot->pixels = NULL;
245 _printf(1, "Shot taken (in %s).\n", _dest);
246 }
247 else if (_dest_type == FTYPE_REMOTE)
248 {
249 int len = sizeof(int) + sizeof(int) + ex_shot->w * ex_shot->h * 4;
250 char *buf = alloca(len);
251 char *tmp = buf;
252 STORE_INT(tmp, ex_shot->w);
253 STORE_INT(tmp, ex_shot->h);
254 memcpy(tmp, ex_shot->pixels, ex_shot->w * ex_shot->h * 4);
255 eina_debug_session_send(_last_debug_session, _last_debug_src_cid, _take_shot_op, buf, len);
256 }
257 }
258 exactness_image_free(ex_shot);
259 efl_key_data_set(event->object, "_shot", NULL);
260 evas_object_del(efl_key_data_get(event->object, "_snapshot"));
261 efl_key_data_set(event->object, "_snapshot", NULL);
262 /* This part is needed when the shot is needed at the end of the scenario.
263 * As it is async, we need to wait for the shot termination. */
264 _shot_needed = EINA_FALSE;
265 if (_exit_required) ecore_main_loop_quit();
266 }
267}
268
269static void
270_shot_do(Evas *e)
271{
272 void *e_data = NULL;
273 if (!e) return;
274
275 if (!_disable_shots)
276 {
277 if (_dest_type == FTYPE_DIR)
278 {
279 int dir_name_len;
280 char *filename;
281
282 dir_name_len = strlen(_dest) + 1; /* includes space of a '/' */
283 filename = malloc(strlen(_test_name) + strlen(IMAGE_FILENAME_EXT) +
284 dir_name_len + 8); /* also space for serial */
285
286 sprintf(filename, "%s/%s%c%03d%s", _dest, _test_name,
287 SHOT_DELIMITER, _cur_shot_id, IMAGE_FILENAME_EXT);
288 e_data = filename;
289 }
290 else if (_dest_type == FTYPE_EXU)
291 {
292 Exactness_Image *ex_img = malloc(sizeof(*ex_img));
293 _dest_unit->imgs = eina_list_append(_dest_unit->imgs, ex_img);
294 _dest_unit->nb_shots++;
295 e_data = ex_img;
296 }
297 else if (_dest_type == FTYPE_REMOTE)
298 {
299 e_data = e;
300 }
301 }
302 efl_key_data_set(e, "_shot", e_data);
303 _shot_needed = EINA_TRUE;
304 Efl_Event ev;
305 ev.info = NULL;
306 ev.object = e;
307 _evas_render_post_cb(NULL, &ev);
308
309 if (_scan_objects && _dest_type == FTYPE_EXU)
310 {
311 Eina_Iterator *iter;
312 Eo *obj;
313 Exactness_Objects *e_objs = calloc(1, sizeof(*e_objs));
314 iter = eo_objects_iterator_new();
315 EINA_ITERATOR_FOREACH(iter, obj)
316 {
317 if (!efl_isa(obj, EFL_CANVAS_OBJECT_CLASS) &&
318 !efl_isa(obj, EFL_CANVAS_SCENE_INTERFACE)) continue;
319 Exactness_Object *e_obj = calloc(1, sizeof(*e_obj));
320 Eo *parent = efl_parent_get(obj);
321 e_obj->id = (long long) obj;
322 if (efl_isa(parent, EFL_CANVAS_OBJECT_CLASS) ||
323 efl_isa(parent, EFL_CANVAS_SCENE_INTERFACE))
324 {
325 e_obj->parent_id = (long long) efl_parent_get(obj);
326 }
327 else
328 {
329 e_obj->parent_id = 0;
330 }
331 e_obj->kl_name = eina_stringshare_add(efl_class_name_get(obj));
332 if (efl_isa(obj, EFL_CANVAS_OBJECT_CLASS))
333 {
334 Eina_Size2D sz = efl_gfx_entity_size_get(obj);
335 e_obj->w = sz.w;
336 e_obj->h = sz.h;
337 Eina_Position2D pos = efl_gfx_entity_position_get(obj);
338 e_obj->x = pos.x;
339 e_obj->y = pos.y;
340 }
341 e_objs->objs = eina_list_append(e_objs->objs, e_obj);
342 }
343 eina_iterator_free(iter);
344 _dest_unit->objs = eina_list_append(_dest_unit->objs, e_objs);
345 }
346}
347
348static void
349_feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
350{
351 static Evas_Object *rect = NULL;
352 static unsigned int rect_evas;
353
354 Eo *e = eina_list_nth(_evas_list, n_evas);
355
356 if (rect && rect_evas != n_evas)
357 {
358 efl_del(rect);
359 rect = NULL;
360 }
361 if (_verbose && !rect)
362 {
363 rect = evas_object_rectangle_add(e);
364 evas_object_repeat_events_set(rect, EINA_TRUE);
365 evas_object_color_set(rect, 255, 0, 0, 255);
366 evas_object_resize(rect, 15, 15);
367 evas_object_layer_set(rect, 100);
368 evas_object_show(rect);
369 rect_evas = n_evas;
370 }
371
372 switch (type)
373 {
374 case EXACTNESS_ACTION_MOUSE_IN:
375 {
376 _printf(1, "Mouse in\n");
377 _printf(2, "%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
378 if (e) evas_event_feed_mouse_in(e, time(NULL), NULL);
379 break;
380 }
381 case EXACTNESS_ACTION_MOUSE_OUT:
382 {
383 _printf(1, "Mouse out\n");
384 _printf(2, "%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
385 if (e) evas_event_feed_mouse_out(e, time(NULL), NULL);
386 break;
387 }
388 case EXACTNESS_ACTION_MOUSE_WHEEL:
389 {
390 Exactness_Action_Mouse_Wheel *t = data;
391 _printf(1, "Mouse wheel\n");
392 _printf(2, "%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
393 if (e) evas_event_feed_mouse_wheel(e, t->direction, t->z, time(NULL), NULL);
394
395 break;
396 }
397 case EXACTNESS_ACTION_MULTI_DOWN:
398 {
399 Exactness_Action_Multi_Event *t = data;
400 _printf(2, "%s evas_event_feed_multi_down n_evas=<%d>\n", __func__, n_evas);
401 if (!t->d)
402 {
403 if (e) evas_event_feed_mouse_down(e, t->b, t->flags, time(NULL), NULL);
404 if (rect) evas_object_color_set(rect, 255, 255, 0, 255);
405 }
406 else
407 {
408 if (e) evas_event_feed_multi_down(e,
409 t->d, t->x, t->y, t->rad,
410 t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
411 t->flags, time(NULL), NULL);
412 }
413
414 break;
415 }
416 case EXACTNESS_ACTION_MULTI_UP:
417 {
418 Exactness_Action_Multi_Event *t = data;
419 _printf(2, "%s evas_event_feed_multi_up n_evas=<%d>\n", __func__, n_evas);
420 if (!t->d)
421 {
422 if (e) evas_event_feed_mouse_up(e, t->b, t->flags, time(NULL), NULL);
423 if (rect) evas_object_color_set(rect, 255, 0, 0, 255);
424 }
425 else
426 {
427 if (e) evas_event_feed_multi_up(e,
428 t->d, t->x, t->y, t->rad,
429 t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
430 t->flags, time(NULL), NULL);
431 }
432
433 break;
434 }
435 case EXACTNESS_ACTION_MULTI_MOVE:
436 {
437 Exactness_Action_Multi_Move *t = data;
438 _printf(2, "%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
439 if (!t->d)
440 {
441 if (e) evas_event_feed_mouse_move(e, t->x, t->y, time(NULL), NULL);
442 if (rect)
443 {
444 evas_object_move(rect, t->x, t->y);
445 evas_object_color_set(rect, 255, 0, 0, 255);
446 }
447 }
448 else
449 {
450 if (e) evas_event_feed_multi_move(e,
451 t->d, t->x, t->y, t->rad,
452 t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
453 time(NULL), NULL);
454 }
455
456 break;
457 }
458 case EXACTNESS_ACTION_KEY_DOWN:
459 {
460 Exactness_Action_Key_Down_Up *t = data;
461 _printf(2, "%s evas_event_feed_key_down n_evas=<%d>\n", __func__, n_evas);
462 if (e)
463 evas_event_feed_key_down_with_keycode(e,
464 t->keyname, t->key, t->string,
465 t->compose, time(NULL), NULL, t->keycode);
466 break;
467 }
468 case EXACTNESS_ACTION_KEY_UP:
469 {
470 Exactness_Action_Key_Down_Up *t = data;
471 _printf(2, "%s evas_event_feed_key_up n_evas=<%d>\n", __func__, n_evas);
472 if (e) evas_event_feed_key_up_with_keycode(e,
473 t->keyname, t->key, t->string,
474 t->compose, time(NULL), NULL, t->keycode);
475
476 break;
477 }
478 case EXACTNESS_ACTION_TAKE_SHOT:
479 {
480 _printf(2, "%s take shot n_evas=<%d>\n", __func__, n_evas);
481 if (rect) evas_object_color_set(rect, 0, 0, 255, 255);
482 _cur_shot_id++;
483 if (_dest_type != FTYPE_UNKNOWN && e) _shot_do(e);
484 break;
485 }
486 case EXACTNESS_ACTION_EFL_EVENT:
487 {
488 Exactness_Action_Efl_Event *t = data;
489 Eina_Bool found = EINA_FALSE;
490 Eina_List *itr;
491 EINA_LIST_FOREACH(_evas_list, itr, e)
492 {
493 Eo *o = efl_name_find(e, t->wdg_name);
494 if (o)
495 {
496 _printf(2, "%s EFL event invoke %s on %s\n",
497 __func__, t->event_name, t->wdg_name);
498 Efl_Event_Description d;
499 found = EINA_TRUE;
500 memset(&d, 0, sizeof(d));
501 d.name = t->event_name;
502 d.legacy_is = EINA_TRUE;
503 efl_event_callback_legacy_call(o, &d, NULL);
504#if 0
505 /* Remove when events stuff work well */
506 Eina_Size2D sz = efl_gfx_size_get(o);
507 Eina_Position2D pos = efl_gfx_position_get(o);
508 if (!strcmp(t->event_name, "clicked") ||
509 !strcmp(t->event_name, "clicked,double"))
510 {
511 int x = pos.x + (sz.w / 2);
512 int y = pos.y + (sz.h / 2);
513 evas_event_feed_mouse_move(e, x, y, time(NULL), NULL);
514 evas_event_feed_mouse_down(e, 0, EVAS_BUTTON_NONE, time(NULL), NULL);
515 evas_event_feed_mouse_up(e, 0, EVAS_BUTTON_NONE, time(NULL), NULL);
516 if (rect)
517 {
518 evas_object_move(rect, x, y);
519 evas_object_color_set(rect, 255, 0, 0, 255);
520 }
521 if (!strcmp(t->event_name, "clicked,double"))
522 {
523 evas_event_feed_mouse_down(e, 0, EVAS_BUTTON_DOUBLE_CLICK,
524 time(NULL), NULL);
525 evas_event_feed_mouse_up(e, 0, EVAS_BUTTON_DOUBLE_CLICK,
526 time(NULL), NULL);
527 }
528 }
529#endif
530 }
531 }
532 if (!found) fprintf(stderr, "Failed finding %s.\n", t->wdg_name);
533 break;
534 }
535 case EXACTNESS_ACTION_CLICK_ON:
536 {
537 Exactness_Action_Click_On *t = data;
538 Eina_List *itr;
539 Eo *o;
540 n_evas = 0;
541 EINA_LIST_FOREACH(_evas_list, itr, e)
542 {
543 o = efl_name_find(e, t->wdg_name);
544 if (o) goto wdg_found;
545 n_evas++;
546 }
547 o = NULL;
548wdg_found:
549 if (o)
550 {
551 Eina_Size2D sz = efl_gfx_entity_size_get(o);
552 Eina_Position2D pos = efl_gfx_entity_position_get(o);
553 int x = pos.x + (sz.w / 2);
554 int y = pos.y + (sz.h / 2);
555 Exactness_Action_Multi_Move *d_move = calloc(1, sizeof(*d_move));
556 Exactness_Action_Multi_Event *d_event = calloc(1, sizeof(*d_event));
557 Exactness_Action *act, *prev_act = eina_list_data_get(_cur_event_list);
558
559 _printf(2, "%s click on %s\n", __func__, t->wdg_name);
560 act = calloc(1, sizeof(*act));
561 act->type = EXACTNESS_ACTION_MULTI_MOVE;
562 act->delay_ms = 100;
563 act->n_evas = n_evas;
564 act->data = d_move;
565 d_move->x = x;
566 d_move->y = y;
567 _cur_event_list = eina_list_append_relative(_cur_event_list,
568 act, prev_act);
569 prev_act = act;
570
571 act = calloc(1, sizeof(*act));
572 act->type = EXACTNESS_ACTION_MULTI_DOWN;
573 act->delay_ms = 100;
574 act->n_evas = n_evas;
575 act->data = d_event;
576 d_event->b = 1;
577 _cur_event_list = eina_list_append_relative(_cur_event_list,
578 act, prev_act);
579 prev_act = act;
580
581 act = calloc(1, sizeof(*act));
582 act->type = EXACTNESS_ACTION_MULTI_UP;
583 act->delay_ms = 100;
584 act->n_evas = n_evas;
585 d_event = calloc(1, sizeof(*d_event));
586 act->data = d_event;
587 d_event->b = 1;
588 _cur_event_list = eina_list_append_relative(_cur_event_list,
589 act, prev_act);
590 }
591 else fprintf(stderr, "Failed finding %s.\n", t->wdg_name);
592 break;
593 }
594 case EXACTNESS_ACTION_STABILIZE:
595 {
596 _printf(2, "%s stabilize\n", __func__);
597 if (rect) evas_object_color_set(rect, 255, 165, 0, 255);
598 ecore_timer_add(0.1, _stabilization_timer_cb, NULL);
599 break;
600 }
601 default: /* All non-input events are not handeled */
602 break;
603 }
604}
605
606static Eina_Bool
607_feed_event_timer_cb(void *data EINA_UNUSED)
608{
609 if (_pause_request) return ECORE_CALLBACK_CANCEL;
610 Exactness_Action *act = eina_list_data_get(_cur_event_list);
611 if (act) _feed_event(act->type, act->n_evas, act->data);
612
613 _cur_event_list = eina_list_next(_cur_event_list);
614 if (!_cur_event_list)
615 { /* Finished reading all events */
616 _exit_required = EINA_TRUE;
617 if (!_shot_needed) ecore_main_loop_quit();
618 }
619 else
620 {
621 if (act->type != EXACTNESS_ACTION_STABILIZE)
622 {
623 act = eina_list_data_get(_cur_event_list);
624 _printf(2, " %s timer_time=<%f>\n", __func__, act->delay_ms / 1000.0);
625 ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
626 }
627 }
628 return ECORE_CALLBACK_CANCEL;
629}
630
631static Eina_Bool
632_stabilization_timer_cb(void *data EINA_UNUSED)
633{
634 Eina_List *itr;
635 Evas *e;
636#define STAB_MAX 5
637 static int need_more = STAB_MAX;
638 _printf(2, "Not stable yet!\n");
639 EINA_LIST_FOREACH(_evas_list, itr, e)
640 {
641 if (!e) continue;
642 Exactness_Image *last_img = efl_key_data_get(e, "_last_stab_shot");
643 Exactness_Image *cur_img = _snapshot_shot_get(e);
644 if (!last_img || exactness_image_compare(last_img, cur_img, NULL)) need_more = STAB_MAX;
645 exactness_image_free(last_img);
646 efl_key_data_set(e, "_last_stab_shot", cur_img);
647 }
648 EINA_LIST_FOREACH(_evas_list, itr, e)
649 {
650 if (!need_more)
651 {
652 evas_object_del(efl_key_data_get(e, "_snapshot"));
653 efl_key_data_set(e, "_snapshot", NULL);
654 }
655 }
656 if (!need_more)
657 {
658 _playing_status = EINA_FALSE;
659 if (_src_type != FTYPE_REMOTE && !_pause_request)
660 {
661 Exactness_Action *act = eina_list_data_get(_cur_event_list);
662 _printf(2, " %s timer_time=<%f>\n", __func__, act->delay_ms / 1000.0);
663 ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
664 }
665 need_more = STAB_MAX;
666 return ECORE_CALLBACK_CANCEL;
667 }
668 need_more--;
669 return ECORE_CALLBACK_RENEW;
670}
671
672static void
673_main_loop_mouse_in_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
674{
675 char *buf = buffer;
676 int n_evas = EXTRACT_INT(buf);
677 _feed_event(EXACTNESS_ACTION_MOUSE_IN, n_evas, NULL);
678}
679
680static void
681_main_loop_mouse_out_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
682{
683 char *buf = buffer;
684 int n_evas = EXTRACT_INT(buf);
685 _feed_event(EXACTNESS_ACTION_MOUSE_OUT, n_evas, NULL);
686}
687
688static void
689_main_loop_mouse_wheel_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
690{
691 char *buf = buffer;
692 Exactness_Action_Mouse_Wheel t;
693 int n_evas = EXTRACT_INT(buf);
694 t.direction = EXTRACT_INT(buf);
695 t.z = EXTRACT_INT(buf);
696 _feed_event(EXACTNESS_ACTION_MOUSE_WHEEL, n_evas, &t);
697}
698
699static void
700_main_loop_multi_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
701{
702 char *buf = buffer;
703 Exactness_Action_Multi_Event t;
704 int n_evas = EXTRACT_INT(buf);
705 t.d = EXTRACT_INT(buf);
706 t.b = EXTRACT_INT(buf);
707 t.x = EXTRACT_INT(buf);
708 t.y = EXTRACT_INT(buf);
709 t.rad = EXTRACT_DOUBLE(buf);
710 t.radx = EXTRACT_DOUBLE(buf);
711 t.rady = EXTRACT_DOUBLE(buf);
712 t.pres = EXTRACT_DOUBLE(buf);
713 t.ang = EXTRACT_DOUBLE(buf);
714 t.fx = EXTRACT_DOUBLE(buf);
715 t.fy = EXTRACT_DOUBLE(buf);
716 t.flags = EXTRACT_INT(buf);
717 _feed_event(EXACTNESS_ACTION_MULTI_DOWN, n_evas, &t);
718}
719
720static void
721_main_loop_multi_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
722{
723 char *buf = buffer;
724 Exactness_Action_Multi_Event t;
725 int n_evas = EXTRACT_INT(buf);
726 t.d = EXTRACT_INT(buf);
727 t.b = EXTRACT_INT(buf);
728 t.x = EXTRACT_INT(buf);
729 t.y = EXTRACT_INT(buf);
730 t.rad = EXTRACT_DOUBLE(buf);
731 t.radx = EXTRACT_DOUBLE(buf);
732 t.rady = EXTRACT_DOUBLE(buf);
733 t.pres = EXTRACT_DOUBLE(buf);
734 t.ang = EXTRACT_DOUBLE(buf);
735 t.fx = EXTRACT_DOUBLE(buf);
736 t.fy = EXTRACT_DOUBLE(buf);
737 t.flags = EXTRACT_INT(buf);
738 _feed_event(EXACTNESS_ACTION_MULTI_UP, n_evas, &t);
739}
740
741static void
742_main_loop_multi_move_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
743{
744 char *buf = buffer;
745 Exactness_Action_Multi_Move t;
746 int n_evas = EXTRACT_INT(buf);
747 t.d = EXTRACT_INT(buf);
748 t.x = EXTRACT_INT(buf);
749 t.y = EXTRACT_INT(buf);
750 t.rad = EXTRACT_DOUBLE(buf);
751 t.radx = EXTRACT_DOUBLE(buf);
752 t.rady = EXTRACT_DOUBLE(buf);
753 t.pres = EXTRACT_DOUBLE(buf);
754 t.ang = EXTRACT_DOUBLE(buf);
755 t.fx = EXTRACT_DOUBLE(buf);
756 t.fy = EXTRACT_DOUBLE(buf);
757 _feed_event(EXACTNESS_ACTION_MULTI_MOVE, n_evas, &t);
758}
759
760static void
761_main_loop_key_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
762{
763 char *buf = buffer;
764 Exactness_Action_Key_Down_Up t;
765 int n_evas = EXTRACT_INT(buf);
766 t.keyname = EXTRACT_STRING(buf);
767 t.key = EXTRACT_STRING(buf);
768 t.string = EXTRACT_STRING(buf);
769 t.compose = EXTRACT_STRING(buf);
770 t.keycode = EXTRACT_INT(buf);
771 _feed_event(EXACTNESS_ACTION_KEY_DOWN, n_evas, &t);
772}
773
774static void
775_main_loop_key_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
776{
777 char *buf = buffer;
778 Exactness_Action_Key_Down_Up t;
779 int n_evas = EXTRACT_INT(buf);
780 t.keyname = EXTRACT_STRING(buf);
781 t.key = EXTRACT_STRING(buf);
782 t.string = EXTRACT_STRING(buf);
783 t.compose = EXTRACT_STRING(buf);
784 t.keycode = EXTRACT_INT(buf);
785 _feed_event(EXACTNESS_ACTION_KEY_UP, n_evas, &t);
786}
787
788static void
789_main_loop_take_shot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size EINA_UNUSED)
790{
791 char *buf = buffer;
792 int n_evas = EXTRACT_INT(buf);
793 _feed_event(EXACTNESS_ACTION_TAKE_SHOT, n_evas, NULL);
794 _last_debug_session = session;
795 _last_debug_src_cid = srcid;
796}
797
798static void
799_main_loop_efl_event_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
800{
801 char *buf = buffer;
802 Exactness_Action_Efl_Event t;
803 t.wdg_name = EXTRACT_STRING(buf);
804 t.event_name = EXTRACT_STRING(buf);
805 _feed_event(EXACTNESS_ACTION_EFL_EVENT, 0, &t);
806}
807
808static void
809_main_loop_click_on_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
810{
811 char *buf = buffer;
812 Exactness_Action_Click_On t;
813 t.wdg_name = EXTRACT_STRING(buf);
814 _feed_event(EXACTNESS_ACTION_CLICK_ON, 0, &t);
815}
816
817static void
818_main_loop_stabilize_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
819{
820 _feed_event(EXACTNESS_ACTION_STABILIZE, 0, NULL);
821}
822
823static void
824_main_loop_finish_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
825{
826 ecore_main_loop_quit();
827}
828
829WRAPPER_TO_XFER_MAIN_LOOP(_mouse_in_cb)
830WRAPPER_TO_XFER_MAIN_LOOP(_mouse_out_cb)
831WRAPPER_TO_XFER_MAIN_LOOP(_mouse_wheel_cb)
832WRAPPER_TO_XFER_MAIN_LOOP(_multi_down_cb)
833WRAPPER_TO_XFER_MAIN_LOOP(_multi_up_cb)
834WRAPPER_TO_XFER_MAIN_LOOP(_multi_move_cb)
835WRAPPER_TO_XFER_MAIN_LOOP(_key_down_cb)
836WRAPPER_TO_XFER_MAIN_LOOP(_key_up_cb)
837WRAPPER_TO_XFER_MAIN_LOOP(_take_shot_cb)
838WRAPPER_TO_XFER_MAIN_LOOP(_efl_event_cb)
839WRAPPER_TO_XFER_MAIN_LOOP(_click_on_cb)
840WRAPPER_TO_XFER_MAIN_LOOP(_stabilize_cb)
841WRAPPER_TO_XFER_MAIN_LOOP(_finish_cb)
842
843EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
844 {"Exactness/Actions/Mouse In", NULL, &_mouse_in_cb},
845 {"Exactness/Actions/Mouse Out", NULL, &_mouse_out_cb},
846 {"Exactness/Actions/Mouse Wheel", NULL, &_mouse_wheel_cb},
847 {"Exactness/Actions/Multi Down", NULL, &_multi_down_cb},
848 {"Exactness/Actions/Multi Up", NULL, &_multi_up_cb},
849 {"Exactness/Actions/Multi Move", NULL, &_multi_move_cb},
850 {"Exactness/Actions/Key Down", NULL, &_key_down_cb},
851 {"Exactness/Actions/Key Up", NULL, &_key_up_cb},
852 {"Exactness/Actions/Take Shot", &_take_shot_op, &_take_shot_cb},
853 {"Exactness/Actions/EFL Event", NULL, &_efl_event_cb},
854 {"Exactness/Actions/Click On", NULL, &_click_on_cb},
855 {"Exactness/Actions/Stabilize", NULL, &_stabilize_cb},
856 {"Exactness/Actions/Finish", NULL, &_finish_cb},
857 {NULL, NULL, NULL}
858);
859
860static Eina_Bool
861_src_feed(void *data EINA_UNUSED)
862{
863 if (!_evas_list) return EINA_TRUE;
864 _cur_event_list = _src_unit->actions;
865 Exactness_Action *act = eina_list_data_get(_cur_event_list);
866
867 if (act && act->delay_ms)
868 {
869 _printf(2, " Waiting <%f>\n", act->delay_ms / 1000.0);
870 ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
871 }
872 else
873 {
874 _feed_event_timer_cb(NULL);
875 }
876 return EINA_FALSE;
877}
878
879static Eina_Bool
880_src_open()
881{
882 if (_src_type != FTYPE_REMOTE)
883 {
884 Eina_List *itr, *itr2;
885 Exactness_Action *act;
886 _printf(2, "<%s> Source file is <%s>\n", __func__, _src_filename);
887 if (_src_type == FTYPE_EXU)
888 {
889 _src_unit = exactness_unit_file_read(_src_filename);
890 }
891 else if (_src_type == FTYPE_REC)
892 {
893 _src_unit = legacy_rec_file_read(_src_filename);
894 }
895 if (!_src_unit) return EINA_FALSE;
896 if (_stabilize_shots)
897 {
898 Exactness_Action_Type last_action_type = EXACTNESS_ACTION_UNKNOWN;
899 EINA_LIST_FOREACH_SAFE(_src_unit->actions, itr, itr2, act)
900 {
901 if (act->type == EXACTNESS_ACTION_TAKE_SHOT &&
902 last_action_type != EXACTNESS_ACTION_STABILIZE)
903 {
904 Exactness_Action *act2 = calloc(1, sizeof(*act2));
905 act2->type = EXACTNESS_ACTION_STABILIZE;
906 _src_unit->actions = eina_list_prepend_relative(_src_unit->actions, act2, act);
907 }
908 last_action_type = act->type;
909 }
910 }
911 if (_speed && _speed != 1)
912 {
913 EINA_LIST_FOREACH(_src_unit->actions, itr, act)
914 act->delay_ms /= _speed;
915 }
916 }
917 else
918 {
919 eina_debug_opcodes_register(NULL, _debug_ops(), NULL, NULL);
920 }
921 return EINA_TRUE;