#ifndef EFL_BETA_API_SUPPORT #define EFL_BETA_API_SUPPORT #endif #ifndef EFL_EO_API_SUPPORT #define EFL_EO_API_SUPPORT #endif #include #include #include #include #include "tsuite_file_data.h" typedef struct { void *p1; void *p2; } _Two_Ptrs; static Eo *_main_box = NULL; static Eina_List *_gls = NULL; static Eina_List *_units = NULL; static Elm_Genlist_Item_Class *_grp_itc = NULL, *_scn_itc = NULL, *_img_itc = NULL; static Elm_Genlist_Item_Class *_comp_scn_itc = NULL, *_comp_img_itc = NULL; static const char * _event_name_get(const Variant_st *v) { switch(tsuite_event_mapping_type_get(v->t.type)) { case TSUITE_EVENT_MOUSE_IN: return "Mouse In"; case TSUITE_EVENT_MOUSE_OUT: return "Mouse Out"; case TSUITE_EVENT_MOUSE_DOWN: return "Mouse Down"; case TSUITE_EVENT_MOUSE_UP: return "Mouse Up"; case TSUITE_EVENT_MOUSE_MOVE: return "Mouse Move"; case TSUITE_EVENT_MOUSE_WHEEL: return "Mouse Wheel"; case TSUITE_EVENT_MULTI_DOWN: return "Multi Down"; case TSUITE_EVENT_MULTI_UP: return "Multi Up"; case TSUITE_EVENT_MULTI_MOVE: return "Multi Move"; case TSUITE_EVENT_KEY_DOWN: return "Key Down"; case TSUITE_EVENT_KEY_UP: return "Key Up"; case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE: return "Key Down with Keycode"; case TSUITE_EVENT_KEY_UP_WITH_KEYCODE: return "Key Up with Keycode"; case TSUITE_EVENT_TAKE_SHOT: return "Take shot"; default: return NULL; } } static int _event_struct_len_get(Tsuite_Event_Type type) { switch(type) { case TSUITE_EVENT_MOUSE_IN: case TSUITE_EVENT_MOUSE_OUT: return sizeof(mouse_in_mouse_out); case TSUITE_EVENT_MOUSE_DOWN: case TSUITE_EVENT_MOUSE_UP: return sizeof(mouse_down_mouse_up); case TSUITE_EVENT_MOUSE_MOVE: return sizeof(mouse_move); case TSUITE_EVENT_MOUSE_WHEEL: return sizeof(mouse_wheel); case TSUITE_EVENT_MULTI_DOWN: case TSUITE_EVENT_MULTI_UP: return sizeof(multi_move); case TSUITE_EVENT_MULTI_MOVE: return sizeof(multi_event); case TSUITE_EVENT_KEY_DOWN: case TSUITE_EVENT_KEY_UP: return sizeof(key_down_key_up); case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE: case TSUITE_EVENT_KEY_UP_WITH_KEYCODE: return sizeof(key_down_key_up_with_keycode); case TSUITE_EVENT_TAKE_SHOT: return sizeof(take_screenshot); default: return 0; } } static void _event_specific_info_get(const Variant_st *v, char output[1024]) { switch(tsuite_event_mapping_type_get(v->t.type)) { case TSUITE_EVENT_MOUSE_DOWN: { mouse_down_mouse_up *t = v->data; sprintf(output, "Button %d Flags %d", t->b, t->flags); break; } case TSUITE_EVENT_MOUSE_UP: { mouse_down_mouse_up *t = v->data; sprintf(output, "Button %d Flags %d", t->b, t->flags); break; } case TSUITE_EVENT_MOUSE_MOVE: { mouse_move *t = v->data; sprintf(output, "X %d Y %d", t->x, t->y); break; } case TSUITE_EVENT_MOUSE_WHEEL: { mouse_wheel *t = v->data; sprintf(output, "Direction %d Z %d", t->direction, t->z); break; } case TSUITE_EVENT_MULTI_DOWN: case TSUITE_EVENT_MULTI_UP: { multi_event *t = v->data; if (!t->d) sprintf(output, "Button %d Flags %d", t->b, t->flags); else sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f Flags %d", t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy, t->flags); break; } case TSUITE_EVENT_MULTI_MOVE: { multi_move *t = v->data; if (!t->d) sprintf(output, "X %d Y %d", t->x, t->y); else sprintf(output, "D %d X %d Y %d Rad %f RadX %f RadY %f Pres %f Ang %f FX %f FY %f", t->d, t->x, t->y, t->rad, t->radx, t->rady, t->pres, t->ang, t->fx, t->fy); break; } case TSUITE_EVENT_KEY_UP: case TSUITE_EVENT_KEY_DOWN: { key_down_key_up *t = v->data; sprintf(output, "Keyname %s Key %s String %s Compose %s", t->keyname, t->key, t->string, t->compose); break; } case TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE: case TSUITE_EVENT_KEY_UP_WITH_KEYCODE: { key_down_key_up_with_keycode *t = v->data; sprintf(output, "Keyname %s Key %s String %s Compose %s Keycode %d", t->keyname, t->key, t->string, t->compose, t->keycode); break; } default: { output[0] = '\0'; break; } } } static const Ecore_Getopt optdesc = { "exactness_inspect", "%prog [options] [ | ]", NULL, "(C) 2016 Enlightenment", "BSD", "Inspector for Exactness", 0, { ECORE_GETOPT_STORE_USHORT('d', "delay", "Delay the given recording by a given time (in milliseconds)."), ECORE_GETOPT_STORE_TRUE('c', "clean", "Clean the given recording from wrong events."), ECORE_GETOPT_STORE_TRUE('l', "list", "List the events of the given recording."), ECORE_GETOPT_STORE_TRUE('C', "compare", "Compare given files (images files or objects eet files)."), ECORE_GETOPT_STORE_STR('o', "compare_output", "Output of the comparison."), ECORE_GETOPT_STORE_USHORT('s', "shot", "Select a specific shot (1 = 1st shot...)."), ECORE_GETOPT_LICENSE('L', "license"), ECORE_GETOPT_COPYRIGHT('C', "copyright"), ECORE_GETOPT_VERSION('V', "version"), ECORE_GETOPT_HELP('h', "help"), ECORE_GETOPT_SENTINEL } }; static Eina_Bool _is_hook_duplicate(const Variant_st *cur_v, const Variant_st *prev_v) { if (!prev_v) return EINA_FALSE; Tsuite_Event_Type cur_type = tsuite_event_mapping_type_get(cur_v->t.type); Tsuite_Event_Type prev_type = tsuite_event_mapping_type_get(prev_v->t.type); if (cur_type == prev_type && !memcmp(cur_v->data, prev_v->data, _event_struct_len_get(cur_type))) return EINA_TRUE; return EINA_FALSE; } static Exactness_Image * _pixels_compare(Exactness_Image *img1, Exactness_Image *img2, Eina_Bool *has_diff) { Exactness_Image *imgO = malloc(sizeof(*imgO)); int w, h; int *pxs1, *pxs2, *pxsO; int w1 = img1 ? img1->w : 0, h1 = img1 ? img1->h : 0; int w2 = img2 ? img2->w : 0, h2 = img2 ? img2->h : 0; imgO->w = MAX(w1, w2); imgO->h = MAX(h1, h2); if (has_diff) *has_diff = EINA_FALSE; if (!imgO->w || !imgO->h) { free(imgO); return NULL; } imgO->pixels_count = imgO->w * imgO->h *4; imgO->pixels = malloc(imgO->pixels_count); pxs1 = img1 ? img1->pixels : NULL; pxs2 = img2 ? img2->pixels : NULL; pxsO = imgO->pixels; for (w = 0; w < imgO->w; w++) { for (h = 0; h < imgO->h; h++) { Eina_Bool valid1 = w <= w1 && h <= h1; Eina_Bool valid2 = w <= w2 && h <= h2; int px1 = valid1 ? pxs1[h * w1 + w] : 0; int px2 = valid2 ? pxs2[h * w2 + w] : 0; int r1 = (px1 & 0x00FF0000) >> 16; int r2 = (px2 & 0x00FF0000) >> 16; int g1 = (px1 & 0x0000FF00) >> 8; int g2 = (px2 & 0x0000FF00) >> 8; int b1 = (px1 & 0x000000FF); int b2 = (px2 & 0x000000FF); int new_r, new_g, new_b; if (valid1 || valid2) { if (px1 != px2) { new_r = 0xFF; new_g = ((g1 + g2) >> 1) >> 2; new_b = ((b1 + b2) >> 1) >> 2; if (has_diff) *has_diff = EINA_TRUE; } else { new_r = (((r1 + r2) >> 1) >> 2) + 0xC0; new_g = (((g1 + g2) >> 1) >> 2) + 0xC0; new_b = (((b1 + b2) >> 1) >> 2) + 0xC0; } } else { new_r = new_g = new_b = 0x0; } pxsO[h * imgO->w + w] = 0xFF000000 | new_r << 16 | new_g << 8 | new_b; } } return imgO; } static void _gui_win_create() { Eo *win, *bg; elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); win = elm_win_add(NULL, "Window", ELM_WIN_BASIC); elm_win_maximized_set(win, EINA_TRUE); elm_win_autodel_set(win, EINA_TRUE); elm_win_title_set(win, "Exactness Inspector"); efl_gfx_entity_size_set(win, EINA_SIZE2D(1000, 800)); bg = elm_bg_add(win); evas_object_size_hint_weight_set(bg, 1.000000, 1.000000); efl_gfx_entity_visible_set(bg, EINA_TRUE); elm_win_resize_object_add(win, bg); _main_box = elm_box_add(win); elm_box_horizontal_set(_main_box, EINA_TRUE); elm_box_homogeneous_set(_main_box, EINA_TRUE); evas_object_size_hint_weight_set(_main_box, 1.000000, 1.000000); efl_gfx_entity_visible_set(_main_box, EINA_TRUE); elm_win_resize_object_add(win, _main_box); efl_gfx_entity_visible_set(win, EINA_TRUE); } static char * _grp_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { return strdup(data); } static char * _scn_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { Variant_st *v = data; Eina_Strbuf *buf = eina_strbuf_new(); char *ret = NULL; unsigned int timestamp = evt_time_get(0, v); char specific_output[1024]; eina_strbuf_append_printf(buf, "%.3f: ", timestamp / 1000.0); eina_strbuf_append_printf(buf, "%s", _event_name_get(v)); _event_specific_info_get(v, specific_output); if (*specific_output) eina_strbuf_append_printf(buf, " - %s", specific_output); ret = eina_strbuf_string_steal(buf); eina_strbuf_free(buf); return ret; } static char * _comp_scn_text_get(void *data, Evas_Object *obj EINA_UNUSED, const char *part EINA_UNUSED) { _Two_Ptrs *vv = data; Variant_st *v1 = vv->p1; Variant_st *v2 = vv->p2; int tm1 = evt_time_get(0, v1); int tm2 = evt_time_get(0, v2); Tsuite_Event_Type t1 = tsuite_event_mapping_type_get(v1->t.type); Tsuite_Event_Type t2 = tsuite_event_mapping_type_get(v2->t.type); Eina_Strbuf *buf = eina_strbuf_new(); char *ret = NULL; if (tm1 != tm2) eina_strbuf_append_printf(buf, "[%.3f/%.3f]: ", tm1/1000.0, tm2/1000.0); else eina_strbuf_append_printf(buf, "%.3f: ", tm1 / 1000.0); if (t1 != t2) eina_strbuf_append_printf(buf, "[%s/%s] - XXXXXX", _event_name_get(v1), _event_name_get(v2)); else { char params1[1024]; char params2[2024]; _event_specific_info_get(v1, params1); _event_specific_info_get(v2, params2); eina_strbuf_append_printf(buf, "%s", _event_name_get(v1)); if (*params1 || *params2) { if (strcmp(params1, params2)) eina_strbuf_append_printf(buf, " - [%s/%s]", params1, params2); else eina_strbuf_append_printf(buf, " - %s", params1); } } ret = eina_strbuf_string_steal(buf); eina_strbuf_free(buf); return ret; } static Evas_Object * _img_content_get(void *data, Evas_Object *obj, const char *part) { if (strcmp(part, "elm.swallow.content")) return NULL; Exactness_Image *ex_img = data; Eo *img = elm_image_add(obj); Eo *evas_img = elm_image_object_get(img); evas_object_image_size_set(evas_img, ex_img->w, ex_img->h); evas_object_image_data_set(evas_img, ex_img->pixels); evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(300), ELM_SCALE_SIZE(300)); return img; } static Evas_Object * _comp_img_content_get(void *data, Evas_Object *obj, const char *part) { if (strcmp(part, "elm.swallow.content")) return NULL; _Two_Ptrs *vv = data; Exactness_Image *img1 = vv->p1; Exactness_Image *img2 = vv->p2; Exactness_Image *imgO = _pixels_compare(img1, img2, NULL); Eo *img = elm_image_add(obj); Eo *evas_img = elm_image_object_get(img); evas_object_image_size_set(evas_img, imgO->w, imgO->h); evas_object_image_data_set(evas_img, imgO->pixels); evas_object_size_hint_min_set(img, ELM_SCALE_SIZE(300), ELM_SCALE_SIZE(300)); return img; } static void _itc_init() { if (!_grp_itc) { _grp_itc = elm_genlist_item_class_new(); _grp_itc->item_style = "group_index"; _grp_itc->func.text_get = _grp_text_get; } if (!_scn_itc) { _scn_itc = elm_genlist_item_class_new(); _scn_itc->item_style = "default"; _scn_itc->func.text_get = _scn_text_get; } if (!_img_itc) { _img_itc = elm_genlist_item_class_new(); _img_itc->item_style = "full"; _img_itc->func.content_get = _img_content_get; } if (!_comp_scn_itc) { _comp_scn_itc = elm_genlist_item_class_new(); _comp_scn_itc->item_style = "default"; _comp_scn_itc->func.text_get = _comp_scn_text_get; } if (!_comp_img_itc) { _comp_img_itc = elm_genlist_item_class_new(); _comp_img_itc->item_style = "full"; _comp_img_itc->func.content_get = _comp_img_content_get; } } static void _comp_gl_dragged_cb(Evas_Object *obj, void *data EINA_UNUSED) { int x = 0, y = 0; Eo *gl; Eina_List *itr; elm_interface_scrollable_content_pos_get(obj, &x, &y); EINA_LIST_FOREACH(_gls, itr, gl) { if (gl != obj) elm_interface_scrollable_content_pos_set(gl, x, y, EINA_FALSE); } } static void _gui_unit_display(Exactness_Unit *unit1, Exactness_Unit *unit2, int position) { Eina_List *itr1, *itr2; Eo *gl; gl = elm_genlist_add(_main_box); elm_genlist_homogeneous_set(gl, EINA_TRUE); evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL); efl_gfx_visible_set(gl, EINA_TRUE); _gls = eina_list_append(_gls, gl); if (position == -1) elm_box_pack_end(_main_box, gl); else if (position == 0) elm_box_pack_start(_main_box, gl); else { Eina_List *children = elm_box_children_get(_main_box); Eo *before = eina_list_nth(children, position - 1); elm_box_pack_after(_main_box, gl, before); eina_list_free(children); } if (unit2) { elm_interface_scrollable_vbar_drag_cb_set(gl, _comp_gl_dragged_cb); } _itc_init(); itr1 = unit1 ? unit1->events : NULL; itr2 = unit2 ? unit2->events : NULL; if (itr1) elm_genlist_item_append(gl, _grp_itc, "Scenario", NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); while (itr1 || itr2) { Variant_st *v1 = itr1 ? eina_list_data_get(itr1) : NULL; if (unit2) { Variant_st *v2 = itr2 ? eina_list_data_get(itr2) : NULL; _Two_Ptrs *vv = malloc(sizeof(*vv)); vv->p1 = v1; vv->p2 = v2; elm_genlist_item_append(gl, _comp_scn_itc, vv, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); } else { elm_genlist_item_append(gl, _scn_itc, v1, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); } if (itr1) itr1 = eina_list_next(itr1); if (itr2) itr2 = eina_list_next(itr2); } itr1 = unit1 ? unit1->imgs : NULL; itr2 = unit2 ? unit2->imgs : NULL; if (itr1) elm_genlist_item_append(gl, _grp_itc, "Images", NULL, ELM_GENLIST_ITEM_GROUP, NULL, NULL); while (itr1 || itr2) { Exactness_Image *img1 = itr1 ? eina_list_data_get(itr1) : NULL; if (unit2) { Exactness_Image *img2 = itr2 ? eina_list_data_get(itr2) : NULL; _Two_Ptrs *vv = malloc(sizeof(*vv)); vv->p1 = img1; vv->p2 = img2; elm_genlist_item_append(gl, _comp_img_itc, vv, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); } else { elm_genlist_item_append(gl, _img_itc, img1, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL); } if (itr1) itr1 = eina_list_next(itr1); if (itr2) itr2 = eina_list_next(itr2); } } static Exactness_Image * _image_read(const char *filename) { int w, h; Evas_Load_Error err; Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL); /* the canvas pointer, de facto */ Eo *e = ecore_evas_get(ee); Eo *img = evas_object_image_add(e); evas_object_image_file_set(img, filename, NULL); err = evas_object_image_load_error_get(img); if (err != EVAS_LOAD_ERROR_NONE) { fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n", filename, evas_load_error_str(err)); return NULL; } Exactness_Image *ex_img = malloc(sizeof(*ex_img)); int len; evas_object_image_size_get(img, &w, &h); ex_img->w = w; ex_img->h = h; ex_img->pixels_count = w * h * 4; len = ex_img->pixels_count; ex_img->pixels = malloc(len); memcpy(ex_img->pixels, evas_object_image_data_get(img, EINA_FALSE), len); ecore_evas_free(ee); return ex_img; } int main(int argc, char *argv[]) { const char *ext = NULL; const char *rec_file = NULL; char *compare_output = NULL; int ret = 1, args = 0; unsigned short delay = 0, shot = 0; Eina_Bool write_file = EINA_FALSE; Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE, compare_files = EINA_FALSE; Eina_Bool gui_needed = EINA_TRUE; Ecore_Getopt_Value values[] = { ECORE_GETOPT_VALUE_USHORT(delay), ECORE_GETOPT_VALUE_BOOL(clean), ECORE_GETOPT_VALUE_BOOL(list_get), ECORE_GETOPT_VALUE_BOOL(compare_files), ECORE_GETOPT_VALUE_STR(compare_output), ECORE_GETOPT_VALUE_USHORT(shot), ECORE_GETOPT_VALUE_BOOL(want_quit), ECORE_GETOPT_VALUE_BOOL(want_quit), ECORE_GETOPT_VALUE_BOOL(want_quit), ECORE_GETOPT_VALUE_BOOL(want_quit), ECORE_GETOPT_VALUE_NONE }; ecore_evas_init(); ecore_init(); eet_init(); elm_init(0, NULL); want_quit = EINA_FALSE; args = ecore_getopt_parse(&optdesc, values, argc, argv); if (args < 0) { fprintf(stderr, "Failed parsing arguments.\n"); goto end; } else if (want_quit) { goto end; } else if ((clean || delay || shot || list_get) && args == argc) { fprintf(stderr, "Expected rec file as the last argument.\n"); ecore_getopt_help(stderr, &optdesc); goto end; } else if (shot && !delay) { fprintf(stderr, "shot option can only be used with delay option.\n"); goto end; } else if (compare_files && argc - args < 2) { fprintf(stderr, "Expected at least two files to compare as last arguments.\n"); ecore_getopt_help(stderr, &optdesc); goto end; } Lists_st *list = NULL; if (clean || delay || list_get) { rec_file = argv[args]; Timer_Data td; gui_needed = EINA_FALSE; list = read_events(rec_file, &td); } else { int arg; if (compare_output) gui_needed = EINA_FALSE; for (arg = args; arg < argc; arg++) { if (!ext) ext = strrchr(argv[arg], '.'); if (!ext) { fprintf(stderr, "Extension required\n"); goto end; } if (!strcmp(ext, ".exu")) { Exactness_Unit *ex_unit; Eet_File *file = eet_open(argv[arg], EET_FILE_MODE_READ); if (!file) { fprintf(stderr, "Impossible to extract EET from %s\n", argv[arg]); goto end; } ex_unit = eet_data_read(file, unit_desc_make(), CACHE_FILE_ENTRY); eet_close(file); _units = eina_list_append(_units, ex_unit); } else if (!strcmp(ext, ".rec")) { Exactness_Unit *ex_unit = calloc(1, sizeof(*ex_unit)); Timer_Data td; list = read_events(argv[arg], &td); if (!list) { fprintf(stderr, "Issue while reading %s\n", argv[arg]); goto end; } ex_unit->events = list->variant_list; _units = eina_list_append(_units, ex_unit); } else if (!strcmp(ext, ".png")) { Exactness_Unit *ex_unit = calloc(1, sizeof(*ex_unit)); Exactness_Image *ex_img = _image_read(argv[arg]); if (!ex_img) { fprintf(stderr, "Issue while reading %s\n", argv[arg]); goto end; } ex_unit->imgs = eina_list_append(ex_unit->imgs, ex_img); _units = eina_list_append(_units, ex_unit); } } } if (clean) { Variant_st *v; Eina_List *itr, *itr2; EINA_LIST_FOREACH_SAFE(list->variant_list, itr, itr2, v) { if (!evt_time_get(0, v)) list->variant_list = eina_list_remove_list(list->variant_list, itr); else { if (_is_hook_duplicate(v, eina_list_data_get(eina_list_prev(itr)))) list->variant_list = eina_list_remove_list(list->variant_list, itr); } } write_file = EINA_TRUE; } if (delay) { if (!shot) { if (!list->first_timestamp) { list->first_timestamp = evt_time_get(0, eina_list_data_get(list->variant_list)); } list->first_timestamp -= delay; } else { Variant_st *v; Eina_List *itr; unsigned int cur_shot = 0; EINA_LIST_FOREACH(list->variant_list, itr, v) { if (tsuite_event_mapping_type_get(v->t.type) == TSUITE_EVENT_TAKE_SHOT) { cur_shot++; if (cur_shot == shot) { take_screenshot *t = v->data; t->timestamp += delay; break; } } } } write_file = EINA_TRUE; } if (list_get) { Variant_st *v; Eina_List *itr; EINA_LIST_FOREACH(list->variant_list, itr, v) { char specific_output[1024]; unsigned int timestamp = evt_time_get(0, v); printf("%.3f: %s", timestamp / 1000.0, _event_name_get(v)); _event_specific_info_get(v, specific_output); if (*specific_output) printf(" - %s", specific_output); printf("\n"); } } if (compare_files && compare_output) { Exactness_Unit *unit1 = NULL, *unit2 = NULL; Eina_List *itr; Exactness_Unit *unit; EINA_LIST_FOREACH(_units, itr, unit) { if (!unit1) unit1 = unit; else if (!unit2) unit2 = unit; else { fprintf(stderr, "Too much files to compare (only 2)."); goto end; } } if (!strcmp(ext, ".png")) { Eina_Bool has_diff = EINA_FALSE; Exactness_Image *ex_img1 = eina_list_data_get(unit1->imgs); Exactness_Image *ex_img2 = eina_list_data_get(unit2->imgs); Exactness_Image *ex_imgO = _pixels_compare(ex_img1, ex_img2, &has_diff); if (has_diff) { Ecore_Evas *ee; Eo *e, *img; ee = ecore_evas_new(NULL, 0, 0, 100, 100, NULL); e = ecore_evas_get(ee); img = evas_object_image_add(e); evas_object_image_size_set(img, ex_imgO->w, ex_imgO->h); evas_object_image_data_set(img, ex_imgO->pixels); evas_object_image_save(img, compare_output, NULL, NULL); ecore_evas_free(ee); goto end; } } } ret = 0; if (rec_file && write_file) write_events(rec_file, list); if (gui_needed) { Eina_List *itr; Exactness_Unit *unit, *unit1 = NULL, *unit2 = NULL; Eina_Bool need_compare = compare_files && eina_list_count(_units) == 2; _gui_win_create(); EINA_LIST_FOREACH(_units, itr, unit) { if (need_compare) { if (!unit1) unit1 = unit; else unit2 = unit; } _gui_unit_display(unit, NULL, -1); } if (need_compare) { _gui_unit_display(unit1, unit2, 1); } elm_run(); } end: elm_shutdown(); eet_shutdown(); ecore_shutdown(); ecore_evas_shutdown(); return ret; }