2018-12-24 12:51:52 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_FORK
|
|
|
|
# ifdef HAVE_SYS_WAIT_H
|
|
|
|
# include <sys/wait.h>
|
|
|
|
# endif
|
|
|
|
# ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
# endif
|
|
|
|
# ifdef HAVE_SYS_SYSINFO_H
|
|
|
|
# include <sys/sysinfo.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
#include <Eo.h>
|
|
|
|
#include <Evas.h>
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Ecore_Getopt.h>
|
|
|
|
#include <Ecore_File.h>
|
|
|
|
#include <Ecore_Con.h>
|
|
|
|
#include <Elementary.h>
|
|
|
|
|
2020-03-03 08:03:41 -08:00
|
|
|
#include "common.h"
|
2018-12-24 12:51:52 -08:00
|
|
|
|
2020-02-12 09:10:04 -08:00
|
|
|
#define CMD_LINE_MAX 256
|
2018-12-24 12:51:52 -08:00
|
|
|
#define IMAGE_FILENAME_EXT ".png"
|
|
|
|
#define PAUSE_KEY_STR "F2"
|
|
|
|
|
2020-03-23 09:46:10 -07:00
|
|
|
#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
|
|
|
|
#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
|
|
|
|
|
|
|
|
static int _log_domain = -1;
|
|
|
|
|
2018-12-24 12:51:52 -08:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
FTYPE_UNKNOWN,
|
|
|
|
FTYPE_DIR,
|
|
|
|
FTYPE_REC = FTYPE_DIR,
|
|
|
|
FTYPE_EXU,
|
|
|
|
FTYPE_REMOTE
|
|
|
|
} File_Type;
|
|
|
|
|
|
|
|
static File_Type _dest_type = FTYPE_UNKNOWN;
|
|
|
|
static Eina_Stringshare *_dest = NULL;
|
|
|
|
static Exactness_Unit *_dest_unit = NULL;
|
|
|
|
|
|
|
|
static File_Type _src_type = FTYPE_UNKNOWN;
|
|
|
|
static Eina_Stringshare *_src_filename = NULL;
|
|
|
|
static Exactness_Unit *_src_unit = NULL;
|
|
|
|
|
|
|
|
static const char *_test_name = NULL;
|
|
|
|
static int _verbose = 0;
|
|
|
|
|
|
|
|
static Eina_List *_evas_list = NULL;
|
|
|
|
|
|
|
|
static Eina_List *_cur_event_list = NULL;
|
|
|
|
|
|
|
|
static int _cur_shot_id = 0;
|
|
|
|
static Eina_Bool _shot_needed = EINA_FALSE;
|
|
|
|
static Eina_Bool _scan_objects = EINA_FALSE, _disable_shots = EINA_FALSE, _stabilize_shots = EINA_FALSE;
|
|
|
|
|
|
|
|
static Eina_Debug_Session *_last_debug_session = NULL;
|
|
|
|
static int _last_debug_src_cid = 0;
|
|
|
|
static int _take_shot_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
|
|
|
|
static Eina_Bool _stabilization_timer_cb(void *);
|
|
|
|
static double _speed = 1.0;
|
|
|
|
|
|
|
|
static Eina_Bool _exit_required = EINA_FALSE;
|
|
|
|
static Eina_Bool _pause_request = EINA_FALSE;
|
|
|
|
static Eina_Bool _playing_status = EINA_FALSE;
|
|
|
|
|
|
|
|
static Exactness_Image *
|
|
|
|
_snapshot_shot_get(Evas *e)
|
|
|
|
{
|
|
|
|
Exactness_Image *ex_img;
|
|
|
|
Evas_Object *snapshot;
|
|
|
|
void *pixels;
|
|
|
|
int w, h, nb_bytes;
|
|
|
|
|
|
|
|
if (!e) return NULL;
|
|
|
|
|
|
|
|
evas_output_size_get(e, &w, &h);
|
|
|
|
if ((w < 1) || (h < 1)) return NULL;
|
|
|
|
|
|
|
|
snapshot = efl_key_data_get(e, "_snapshot");
|
|
|
|
if (!snapshot)
|
|
|
|
{
|
|
|
|
snapshot = evas_object_image_filled_add(e);
|
|
|
|
if (snapshot)
|
|
|
|
{
|
|
|
|
evas_object_image_snapshot_set(snapshot, EINA_TRUE);
|
|
|
|
evas_object_geometry_set(snapshot, 0, 0, w, h);
|
|
|
|
efl_gfx_entity_visible_set(snapshot, EINA_TRUE);
|
|
|
|
efl_key_data_set(e, "_snapshot", snapshot);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pixels = evas_object_image_data_get(snapshot, EINA_FALSE);
|
|
|
|
if (!pixels) return NULL;
|
|
|
|
|
|
|
|
ex_img = malloc(sizeof(*ex_img));
|
|
|
|
nb_bytes = w * h * 4;
|
|
|
|
ex_img->w = w;
|
|
|
|
ex_img->h = h;
|
|
|
|
ex_img->pixels = malloc(nb_bytes);
|
|
|
|
memcpy(ex_img->pixels, pixels, nb_bytes);
|
|
|
|
return ex_img;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_render_post_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
if (_shot_needed)
|
|
|
|
{
|
|
|
|
Evas_Event_Render_Post *post = event->info;
|
|
|
|
void *e_data = efl_key_data_get(event->object, "_shot");
|
|
|
|
|
|
|
|
// Nothing was updated, so let's not bother sending nothingness
|
|
|
|
if (post && !post->updated_area) return;
|
|
|
|
Exactness_Image *ex_shot = efl_key_data_get(event->object, "_last_shot");
|
|
|
|
if (!ex_shot) ex_shot = _snapshot_shot_get(event->object);
|
|
|
|
if (!ex_shot) return;
|
|
|
|
|
|
|
|
efl_key_data_set(event->object, "_last_shot", NULL);
|
|
|
|
|
|
|
|
if (e_data)
|
|
|
|
{
|
|
|
|
if (_dest_type == FTYPE_DIR)
|
|
|
|
{
|
|
|
|
char *filename = e_data;
|
|
|
|
Eo *o = evas_object_image_add(event->object);
|
|
|
|
evas_object_image_size_set(o, ex_shot->w, ex_shot->h);
|
|
|
|
evas_object_image_data_set(o, ex_shot->pixels);
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Shot taken (%s).\n", filename);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!evas_object_image_save(o, filename, NULL, NULL))
|
|
|
|
{
|
|
|
|
printf("Cannot save widget to <%s>\n", filename);
|
|
|
|
}
|
|
|
|
free(filename);
|
|
|
|
}
|
|
|
|
else if (_dest_type == FTYPE_EXU)
|
|
|
|
{
|
|
|
|
Exactness_Image *ex_img = e_data;
|
|
|
|
memcpy(ex_img, ex_shot, sizeof(Exactness_Image));
|
|
|
|
ex_shot->pixels = NULL;
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Shot taken (in %s).\n", _dest);
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
else if (_dest_type == FTYPE_REMOTE)
|
|
|
|
{
|
|
|
|
int len = sizeof(int) + sizeof(int) + ex_shot->w * ex_shot->h * 4;
|
|
|
|
char *buf = alloca(len);
|
|
|
|
char *tmp = buf;
|
|
|
|
STORE_INT(tmp, ex_shot->w);
|
|
|
|
STORE_INT(tmp, ex_shot->h);
|
|
|
|
memcpy(tmp, ex_shot->pixels, ex_shot->w * ex_shot->h * 4);
|
|
|
|
eina_debug_session_send(_last_debug_session, _last_debug_src_cid, _take_shot_op, buf, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exactness_image_free(ex_shot);
|
|
|
|
efl_key_data_set(event->object, "_shot", NULL);
|
|
|
|
evas_object_del(efl_key_data_get(event->object, "_snapshot"));
|
|
|
|
efl_key_data_set(event->object, "_snapshot", NULL);
|
|
|
|
/* This part is needed when the shot is needed at the end of the scenario.
|
|
|
|
* As it is async, we need to wait for the shot termination. */
|
|
|
|
_shot_needed = EINA_FALSE;
|
|
|
|
if (_exit_required) ecore_main_loop_quit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shot_do(Evas *e)
|
|
|
|
{
|
|
|
|
void *e_data = NULL;
|
|
|
|
if (!e) return;
|
|
|
|
|
|
|
|
if (!_disable_shots)
|
|
|
|
{
|
|
|
|
if (_dest_type == FTYPE_DIR)
|
|
|
|
{
|
|
|
|
int dir_name_len;
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
dir_name_len = strlen(_dest) + 1; /* includes space of a '/' */
|
|
|
|
filename = malloc(strlen(_test_name) + strlen(IMAGE_FILENAME_EXT) +
|
|
|
|
dir_name_len + 8); /* also space for serial */
|
|
|
|
|
|
|
|
sprintf(filename, "%s/%s%c%03d%s", _dest, _test_name,
|
|
|
|
SHOT_DELIMITER, _cur_shot_id, IMAGE_FILENAME_EXT);
|
|
|
|
e_data = filename;
|
|
|
|
}
|
|
|
|
else if (_dest_type == FTYPE_EXU)
|
|
|
|
{
|
|
|
|
Exactness_Image *ex_img = malloc(sizeof(*ex_img));
|
|
|
|
_dest_unit->imgs = eina_list_append(_dest_unit->imgs, ex_img);
|
|
|
|
_dest_unit->nb_shots++;
|
|
|
|
e_data = ex_img;
|
|
|
|
}
|
|
|
|
else if (_dest_type == FTYPE_REMOTE)
|
|
|
|
{
|
|
|
|
e_data = e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
efl_key_data_set(e, "_shot", e_data);
|
|
|
|
_shot_needed = EINA_TRUE;
|
|
|
|
Efl_Event ev;
|
|
|
|
ev.info = NULL;
|
|
|
|
ev.object = e;
|
|
|
|
_evas_render_post_cb(NULL, &ev);
|
|
|
|
|
|
|
|
if (_scan_objects && _dest_type == FTYPE_EXU)
|
|
|
|
{
|
|
|
|
Eina_Iterator *iter;
|
|
|
|
Eo *obj;
|
|
|
|
Exactness_Objects *e_objs = calloc(1, sizeof(*e_objs));
|
|
|
|
iter = eo_objects_iterator_new();
|
|
|
|
EINA_ITERATOR_FOREACH(iter, obj)
|
|
|
|
{
|
|
|
|
if (!efl_isa(obj, EFL_CANVAS_OBJECT_CLASS) &&
|
|
|
|
!efl_isa(obj, EFL_CANVAS_SCENE_INTERFACE)) continue;
|
|
|
|
Exactness_Object *e_obj = calloc(1, sizeof(*e_obj));
|
|
|
|
Eo *parent = efl_parent_get(obj);
|
|
|
|
e_obj->id = (long long) obj;
|
|
|
|
if (efl_isa(parent, EFL_CANVAS_OBJECT_CLASS) ||
|
|
|
|
efl_isa(parent, EFL_CANVAS_SCENE_INTERFACE))
|
|
|
|
{
|
|
|
|
e_obj->parent_id = (long long) efl_parent_get(obj);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
e_obj->parent_id = 0;
|
|
|
|
}
|
|
|
|
e_obj->kl_name = eina_stringshare_add(efl_class_name_get(obj));
|
|
|
|
if (efl_isa(obj, EFL_CANVAS_OBJECT_CLASS))
|
|
|
|
{
|
|
|
|
Eina_Size2D sz = efl_gfx_entity_size_get(obj);
|
|
|
|
e_obj->w = sz.w;
|
|
|
|
e_obj->h = sz.h;
|
|
|
|
Eina_Position2D pos = efl_gfx_entity_position_get(obj);
|
|
|
|
e_obj->x = pos.x;
|
|
|
|
e_obj->y = pos.y;
|
|
|
|
}
|
|
|
|
e_objs->objs = eina_list_append(e_objs->objs, e_obj);
|
|
|
|
}
|
|
|
|
eina_iterator_free(iter);
|
|
|
|
_dest_unit->objs = eina_list_append(_dest_unit->objs, e_objs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_feed_event(Exactness_Action_Type type, unsigned int n_evas, void *data)
|
|
|
|
{
|
|
|
|
static Evas_Object *rect = NULL;
|
|
|
|
static unsigned int rect_evas;
|
|
|
|
|
|
|
|
Eo *e = eina_list_nth(_evas_list, n_evas);
|
|
|
|
|
|
|
|
if (rect && rect_evas != n_evas)
|
|
|
|
{
|
|
|
|
efl_del(rect);
|
|
|
|
rect = NULL;
|
|
|
|
}
|
|
|
|
if (_verbose && !rect)
|
|
|
|
{
|
|
|
|
rect = evas_object_rectangle_add(e);
|
|
|
|
evas_object_repeat_events_set(rect, EINA_TRUE);
|
|
|
|
evas_object_color_set(rect, 255, 0, 0, 255);
|
|
|
|
evas_object_resize(rect, 15, 15);
|
|
|
|
evas_object_layer_set(rect, 100);
|
|
|
|
evas_object_show(rect);
|
|
|
|
rect_evas = n_evas;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case EXACTNESS_ACTION_MOUSE_IN:
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Mouse in\n");
|
|
|
|
DBG("%s evas_event_feed_mouse_in n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (e) evas_event_feed_mouse_in(e, time(NULL), NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_MOUSE_OUT:
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Mouse out\n");
|
|
|
|
DBG("%s evas_event_feed_mouse_out n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (e) evas_event_feed_mouse_out(e, time(NULL), NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_MOUSE_WHEEL:
|
|
|
|
{
|
|
|
|
Exactness_Action_Mouse_Wheel *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Mouse wheel\n");
|
|
|
|
DBG("%s evas_event_feed_mouse_wheel n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (e) evas_event_feed_mouse_wheel(e, t->direction, t->z, time(NULL), NULL);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_MULTI_DOWN:
|
|
|
|
{
|
|
|
|
Exactness_Action_Multi_Event *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s evas_event_feed_multi_down n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!t->d)
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_mouse_down(e, t->b, t->flags, time(NULL), NULL);
|
|
|
|
if (rect) evas_object_color_set(rect, 255, 255, 0, 255);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_multi_down(e,
|
|
|
|
t->d, t->x, t->y, t->rad,
|
|
|
|
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
|
|
|
|
t->flags, time(NULL), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_MULTI_UP:
|
|
|
|
{
|
|
|
|
Exactness_Action_Multi_Event *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s evas_event_feed_multi_up n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!t->d)
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_mouse_up(e, t->b, t->flags, time(NULL), NULL);
|
|
|
|
if (rect) evas_object_color_set(rect, 255, 0, 0, 255);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_multi_up(e,
|
|
|
|
t->d, t->x, t->y, t->rad,
|
|
|
|
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
|
|
|
|
t->flags, time(NULL), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_MULTI_MOVE:
|
|
|
|
{
|
|
|
|
Exactness_Action_Multi_Move *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s evas_event_feed_multi_move n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!t->d)
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_mouse_move(e, t->x, t->y, time(NULL), NULL);
|
|
|
|
if (rect)
|
|
|
|
{
|
|
|
|
evas_object_move(rect, t->x, t->y);
|
|
|
|
evas_object_color_set(rect, 255, 0, 0, 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (e) evas_event_feed_multi_move(e,
|
|
|
|
t->d, t->x, t->y, t->rad,
|
|
|
|
t->radx, t->rady, t->pres, t->ang, t->fx, t->fy,
|
|
|
|
time(NULL), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_KEY_DOWN:
|
|
|
|
{
|
|
|
|
Exactness_Action_Key_Down_Up *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s evas_event_feed_key_down n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (e)
|
|
|
|
evas_event_feed_key_down_with_keycode(e,
|
|
|
|
t->keyname, t->key, t->string,
|
|
|
|
t->compose, time(NULL), NULL, t->keycode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_KEY_UP:
|
|
|
|
{
|
|
|
|
Exactness_Action_Key_Down_Up *t = data;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s evas_event_feed_key_up n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (e) evas_event_feed_key_up_with_keycode(e,
|
|
|
|
t->keyname, t->key, t->string,
|
|
|
|
t->compose, time(NULL), NULL, t->keycode);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_TAKE_SHOT:
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s take shot n_evas=<%d>\n", __func__, n_evas);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (rect) evas_object_color_set(rect, 0, 0, 255, 255);
|
|
|
|
_cur_shot_id++;
|
|
|
|
if (_dest_type != FTYPE_UNKNOWN && e) _shot_do(e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_EFL_EVENT:
|
|
|
|
{
|
|
|
|
Exactness_Action_Efl_Event *t = data;
|
|
|
|
Eina_Bool found = EINA_FALSE;
|
|
|
|
Eina_List *itr;
|
|
|
|
EINA_LIST_FOREACH(_evas_list, itr, e)
|
|
|
|
{
|
|
|
|
Eo *o = efl_name_find(e, t->wdg_name);
|
|
|
|
if (o)
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s EFL event invoke %s on %s\n",
|
2018-12-24 12:51:52 -08:00
|
|
|
__func__, t->event_name, t->wdg_name);
|
|
|
|
Efl_Event_Description d;
|
|
|
|
found = EINA_TRUE;
|
|
|
|
memset(&d, 0, sizeof(d));
|
|
|
|
d.name = t->event_name;
|
|
|
|
d.legacy_is = EINA_TRUE;
|
|
|
|
efl_event_callback_legacy_call(o, &d, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) fprintf(stderr, "Failed finding %s.\n", t->wdg_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_CLICK_ON:
|
|
|
|
{
|
|
|
|
Exactness_Action_Click_On *t = data;
|
|
|
|
Eina_List *itr;
|
|
|
|
Eo *o;
|
|
|
|
n_evas = 0;
|
|
|
|
EINA_LIST_FOREACH(_evas_list, itr, e)
|
|
|
|
{
|
|
|
|
o = efl_name_find(e, t->wdg_name);
|
|
|
|
if (o) goto wdg_found;
|
|
|
|
n_evas++;
|
|
|
|
}
|
|
|
|
o = NULL;
|
|
|
|
wdg_found:
|
|
|
|
if (o)
|
|
|
|
{
|
|
|
|
Eina_Size2D sz = efl_gfx_entity_size_get(o);
|
|
|
|
Eina_Position2D pos = efl_gfx_entity_position_get(o);
|
|
|
|
int x = pos.x + (sz.w / 2);
|
|
|
|
int y = pos.y + (sz.h / 2);
|
|
|
|
Exactness_Action_Multi_Move *d_move = calloc(1, sizeof(*d_move));
|
|
|
|
Exactness_Action_Multi_Event *d_event = calloc(1, sizeof(*d_event));
|
|
|
|
Exactness_Action *act, *prev_act = eina_list_data_get(_cur_event_list);
|
|
|
|
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s click on %s\n", __func__, t->wdg_name);
|
2018-12-24 12:51:52 -08:00
|
|
|
act = calloc(1, sizeof(*act));
|
|
|
|
act->type = EXACTNESS_ACTION_MULTI_MOVE;
|
|
|
|
act->delay_ms = 100;
|
|
|
|
act->n_evas = n_evas;
|
|
|
|
act->data = d_move;
|
|
|
|
d_move->x = x;
|
|
|
|
d_move->y = y;
|
|
|
|
_cur_event_list = eina_list_append_relative(_cur_event_list,
|
|
|
|
act, prev_act);
|
|
|
|
prev_act = act;
|
|
|
|
|
|
|
|
act = calloc(1, sizeof(*act));
|
|
|
|
act->type = EXACTNESS_ACTION_MULTI_DOWN;
|
|
|
|
act->delay_ms = 100;
|
|
|
|
act->n_evas = n_evas;
|
|
|
|
act->data = d_event;
|
|
|
|
d_event->b = 1;
|
|
|
|
_cur_event_list = eina_list_append_relative(_cur_event_list,
|
|
|
|
act, prev_act);
|
|
|
|
prev_act = act;
|
|
|
|
|
|
|
|
act = calloc(1, sizeof(*act));
|
|
|
|
act->type = EXACTNESS_ACTION_MULTI_UP;
|
|
|
|
act->delay_ms = 100;
|
|
|
|
act->n_evas = n_evas;
|
|
|
|
d_event = calloc(1, sizeof(*d_event));
|
|
|
|
act->data = d_event;
|
|
|
|
d_event->b = 1;
|
|
|
|
_cur_event_list = eina_list_append_relative(_cur_event_list,
|
|
|
|
act, prev_act);
|
|
|
|
}
|
|
|
|
else fprintf(stderr, "Failed finding %s.\n", t->wdg_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXACTNESS_ACTION_STABILIZE:
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("%s stabilize\n", __func__);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (rect) evas_object_color_set(rect, 255, 165, 0, 255);
|
|
|
|
ecore_timer_add(0.1, _stabilization_timer_cb, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: /* All non-input events are not handeled */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_feed_event_timer_cb(void *data EINA_UNUSED)
|
|
|
|
{
|
|
|
|
if (_pause_request) return ECORE_CALLBACK_CANCEL;
|
|
|
|
Exactness_Action *act = eina_list_data_get(_cur_event_list);
|
|
|
|
if (act) _feed_event(act->type, act->n_evas, act->data);
|
|
|
|
|
|
|
|
_cur_event_list = eina_list_next(_cur_event_list);
|
|
|
|
if (!_cur_event_list)
|
|
|
|
{ /* Finished reading all events */
|
|
|
|
_exit_required = EINA_TRUE;
|
|
|
|
if (!_shot_needed) ecore_main_loop_quit();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (act->type != EXACTNESS_ACTION_STABILIZE)
|
|
|
|
{
|
|
|
|
act = eina_list_data_get(_cur_event_list);
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG(" %s timer_time=<%f>\n", __func__, act->delay_ms / 1000.0);
|
2018-12-24 12:51:52 -08:00
|
|
|
ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_stabilization_timer_cb(void *data EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eina_List *itr;
|
|
|
|
Evas *e;
|
|
|
|
#define STAB_MAX 5
|
|
|
|
static int need_more = STAB_MAX;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("Not stable yet!\n");
|
2018-12-24 12:51:52 -08:00
|
|
|
EINA_LIST_FOREACH(_evas_list, itr, e)
|
|
|
|
{
|
|
|
|
if (!e) continue;
|
|
|
|
Exactness_Image *last_img = efl_key_data_get(e, "_last_stab_shot");
|
|
|
|
Exactness_Image *cur_img = _snapshot_shot_get(e);
|
|
|
|
if (!last_img || exactness_image_compare(last_img, cur_img, NULL)) need_more = STAB_MAX;
|
|
|
|
exactness_image_free(last_img);
|
|
|
|
efl_key_data_set(e, "_last_stab_shot", cur_img);
|
|
|
|
}
|
|
|
|
EINA_LIST_FOREACH(_evas_list, itr, e)
|
|
|
|
{
|
|
|
|
if (!need_more)
|
|
|
|
{
|
|
|
|
evas_object_del(efl_key_data_get(e, "_snapshot"));
|
|
|
|
efl_key_data_set(e, "_snapshot", NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!need_more)
|
|
|
|
{
|
|
|
|
_playing_status = EINA_FALSE;
|
|
|
|
if (_src_type != FTYPE_REMOTE && !_pause_request)
|
|
|
|
{
|
|
|
|
Exactness_Action *act = eina_list_data_get(_cur_event_list);
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG(" %s timer_time=<%f>\n", __func__, act->delay_ms / 1000.0);
|
2018-12-24 12:51:52 -08:00
|
|
|
ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
|
|
|
|
}
|
|
|
|
need_more = STAB_MAX;
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
need_more--;
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_mouse_in_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MOUSE_IN, n_evas, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_mouse_out_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MOUSE_OUT, n_evas, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_mouse_wheel_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Mouse_Wheel t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.direction = EXTRACT_INT(buf);
|
|
|
|
t.z = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MOUSE_WHEEL, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_multi_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Multi_Event t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.d = EXTRACT_INT(buf);
|
|
|
|
t.b = EXTRACT_INT(buf);
|
|
|
|
t.x = EXTRACT_INT(buf);
|
|
|
|
t.y = EXTRACT_INT(buf);
|
|
|
|
t.rad = EXTRACT_DOUBLE(buf);
|
|
|
|
t.radx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.rady = EXTRACT_DOUBLE(buf);
|
|
|
|
t.pres = EXTRACT_DOUBLE(buf);
|
|
|
|
t.ang = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fy = EXTRACT_DOUBLE(buf);
|
|
|
|
t.flags = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MULTI_DOWN, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_multi_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Multi_Event t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.d = EXTRACT_INT(buf);
|
|
|
|
t.b = EXTRACT_INT(buf);
|
|
|
|
t.x = EXTRACT_INT(buf);
|
|
|
|
t.y = EXTRACT_INT(buf);
|
|
|
|
t.rad = EXTRACT_DOUBLE(buf);
|
|
|
|
t.radx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.rady = EXTRACT_DOUBLE(buf);
|
|
|
|
t.pres = EXTRACT_DOUBLE(buf);
|
|
|
|
t.ang = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fy = EXTRACT_DOUBLE(buf);
|
|
|
|
t.flags = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MULTI_UP, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_multi_move_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Multi_Move t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.d = EXTRACT_INT(buf);
|
|
|
|
t.x = EXTRACT_INT(buf);
|
|
|
|
t.y = EXTRACT_INT(buf);
|
|
|
|
t.rad = EXTRACT_DOUBLE(buf);
|
|
|
|
t.radx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.rady = EXTRACT_DOUBLE(buf);
|
|
|
|
t.pres = EXTRACT_DOUBLE(buf);
|
|
|
|
t.ang = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fx = EXTRACT_DOUBLE(buf);
|
|
|
|
t.fy = EXTRACT_DOUBLE(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_MULTI_MOVE, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_key_down_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Key_Down_Up t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.keyname = EXTRACT_STRING(buf);
|
|
|
|
t.key = EXTRACT_STRING(buf);
|
|
|
|
t.string = EXTRACT_STRING(buf);
|
|
|
|
t.compose = EXTRACT_STRING(buf);
|
|
|
|
t.keycode = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_KEY_DOWN, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_key_up_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Key_Down_Up t;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
t.keyname = EXTRACT_STRING(buf);
|
|
|
|
t.key = EXTRACT_STRING(buf);
|
|
|
|
t.string = EXTRACT_STRING(buf);
|
|
|
|
t.compose = EXTRACT_STRING(buf);
|
|
|
|
t.keycode = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_KEY_UP, n_evas, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_take_shot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
int n_evas = EXTRACT_INT(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_TAKE_SHOT, n_evas, NULL);
|
|
|
|
_last_debug_session = session;
|
|
|
|
_last_debug_src_cid = srcid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_efl_event_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Efl_Event t;
|
|
|
|
t.wdg_name = EXTRACT_STRING(buf);
|
|
|
|
t.event_name = EXTRACT_STRING(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_EFL_EVENT, 0, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_click_on_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
char *buf = buffer;
|
|
|
|
Exactness_Action_Click_On t;
|
|
|
|
t.wdg_name = EXTRACT_STRING(buf);
|
|
|
|
_feed_event(EXACTNESS_ACTION_CLICK_ON, 0, &t);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_stabilize_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_feed_event(EXACTNESS_ACTION_STABILIZE, 0, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_finish_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
ecore_main_loop_quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_in_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_out_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_mouse_wheel_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_multi_down_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_multi_up_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_multi_move_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_key_down_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_key_up_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_take_shot_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_efl_event_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_click_on_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_stabilize_cb)
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_finish_cb)
|
|
|
|
|
|
|
|
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
|
|
|
|
{"Exactness/Actions/Mouse In", NULL, &_mouse_in_cb},
|
|
|
|
{"Exactness/Actions/Mouse Out", NULL, &_mouse_out_cb},
|
|
|
|
{"Exactness/Actions/Mouse Wheel", NULL, &_mouse_wheel_cb},
|
|
|
|
{"Exactness/Actions/Multi Down", NULL, &_multi_down_cb},
|
|
|
|
{"Exactness/Actions/Multi Up", NULL, &_multi_up_cb},
|
|
|
|
{"Exactness/Actions/Multi Move", NULL, &_multi_move_cb},
|
|
|
|
{"Exactness/Actions/Key Down", NULL, &_key_down_cb},
|
|
|
|
{"Exactness/Actions/Key Up", NULL, &_key_up_cb},
|
|
|
|
{"Exactness/Actions/Take Shot", &_take_shot_op, &_take_shot_cb},
|
|
|
|
{"Exactness/Actions/EFL Event", NULL, &_efl_event_cb},
|
|
|
|
{"Exactness/Actions/Click On", NULL, &_click_on_cb},
|
|
|
|
{"Exactness/Actions/Stabilize", NULL, &_stabilize_cb},
|
|
|
|
{"Exactness/Actions/Finish", NULL, &_finish_cb},
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
);
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_src_feed(void *data EINA_UNUSED)
|
|
|
|
{
|
|
|
|
if (!_evas_list) return EINA_TRUE;
|
|
|
|
_cur_event_list = _src_unit->actions;
|
|
|
|
Exactness_Action *act = eina_list_data_get(_cur_event_list);
|
|
|
|
|
|
|
|
if (act && act->delay_ms)
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG(" Waiting <%f>\n", act->delay_ms / 1000.0);
|
2018-12-24 12:51:52 -08:00
|
|
|
ecore_timer_add(act->delay_ms / 1000.0, _feed_event_timer_cb, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_feed_event_timer_cb(NULL);
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_src_open()
|
|
|
|
{
|
|
|
|
if (_src_type != FTYPE_REMOTE)
|
|
|
|
{
|
|
|
|
Eina_List *itr, *itr2;
|
|
|
|
Exactness_Action *act;
|
2020-03-23 09:46:10 -07:00
|
|
|
DBG("<%s> Source file is <%s>\n", __func__, _src_filename);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (_src_type == FTYPE_EXU)
|
|
|
|
{
|
|
|
|
_src_unit = exactness_unit_file_read(_src_filename);
|
|
|
|
}
|
|
|
|
if (!_src_unit) return EINA_FALSE;
|
|
|
|
if (_stabilize_shots)
|
|
|
|
{
|
|
|
|
Exactness_Action_Type last_action_type = EXACTNESS_ACTION_UNKNOWN;
|
|
|
|
EINA_LIST_FOREACH_SAFE(_src_unit->actions, itr, itr2, act)
|
|
|
|
{
|
|
|
|
if (act->type == EXACTNESS_ACTION_TAKE_SHOT &&
|
|
|
|
last_action_type != EXACTNESS_ACTION_STABILIZE)
|
|
|
|
{
|
|
|
|
Exactness_Action *act2 = calloc(1, sizeof(*act2));
|
|
|
|
act2->type = EXACTNESS_ACTION_STABILIZE;
|
|
|
|
_src_unit->actions = eina_list_prepend_relative(_src_unit->actions, act2, act);
|
|
|
|
}
|
|
|
|
last_action_type = act->type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_speed && _speed != 1)
|
|
|
|
{
|
|
|
|
EINA_LIST_FOREACH(_src_unit->actions, itr, act)
|
|
|
|
act->delay_ms /= _speed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_debug_opcodes_register(NULL, _debug_ops(), NULL, NULL);
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_old_shots_rm_cb(const char *name, const char *path, void *data)
|
|
|
|
{
|
|
|
|
const char *prefix = data;
|
|
|
|
unsigned int len = strlen(prefix);
|
|
|
|
if (!strncmp(name, prefix, len) && (strlen(name) > len) && (name[len] == SHOT_DELIMITER))
|
|
|
|
{
|
2020-02-25 02:20:21 -08:00
|
|
|
unsigned int length = strlen(path) + strlen(name) + 2;
|
|
|
|
char *buf = alloca(length);
|
|
|
|
snprintf(buf, length, "%s/%s", path, name);
|
2018-12-24 12:51:52 -08:00
|
|
|
if (unlink(buf))
|
|
|
|
{
|
|
|
|
printf("Failed deleting '%s/%s': ", path, name);
|
|
|
|
perror("");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_del_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Eina_List *p = eina_list_data_find_list(_evas_list, event->object);
|
|
|
|
eina_list_data_set(p, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_event_key_cb(void *data EINA_UNUSED, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Input_Key *evk = event->info;
|
|
|
|
if (!evk) return;
|
|
|
|
const char *key = efl_input_key_name_get(evk);
|
|
|
|
|
|
|
|
if (!strcmp(key, PAUSE_KEY_STR) && efl_input_key_pressed_get(evk))
|
|
|
|
{
|
|
|
|
_pause_request = !_pause_request;
|
2020-03-23 09:46:10 -07:00
|
|
|
if (_pause_request) INF("Pausing scenario\n");
|
2018-12-24 12:51:52 -08:00
|
|
|
else
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("Playing scenario\n");
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!_playing_status)
|
|
|
|
_feed_event_timer_cb(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_evas_callbacks,
|
|
|
|
{ EFL_EVENT_DEL, _evas_del_cb },
|
|
|
|
{ EFL_CANVAS_SCENE_EVENT_RENDER_POST, _evas_render_post_cb },
|
|
|
|
{ EFL_EVENT_KEY_DOWN, _event_key_cb },
|
|
|
|
{ EFL_EVENT_KEY_UP, _event_key_cb }
|
|
|
|
)
|
|
|
|
|
|
|
|
static Evas *
|
|
|
|
_my_evas_new(int w EINA_UNUSED, int h EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Evas *e;
|
|
|
|
if (!_evas_new) return NULL;
|
|
|
|
e = _evas_new();
|
|
|
|
if (e)
|
|
|
|
{
|
2020-03-23 09:46:10 -07:00
|
|
|
INF("New Evas\n");
|
2018-12-24 12:51:52 -08:00
|
|
|
_evas_list = eina_list_append(_evas_list, e);
|
|
|
|
efl_event_callback_array_add(e, _evas_callbacks(), NULL);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Ecore_Getopt optdesc = {
|
|
|
|
"exactness_play",
|
|
|
|
"%prog [options] <-s|-o|-v|-t|-h> command",
|
|
|
|
PACKAGE_VERSION,
|
|
|
|
"(C) 2017 Enlightenment",
|
|
|
|
"BSD",
|
|
|
|
"A scenario player for EFL based applications.",
|
|
|
|
1,
|
|
|
|
{
|
|
|
|
ECORE_GETOPT_STORE_STR('o', "output",
|
|
|
|
" Set the destination for the shots.\n"
|
|
|
|
" If a .exu is given, the shots are stored in the file.\n"
|
|
|
|
" Otherwise the given path is considered as a directory\n"
|
|
|
|
" where shots will be stored.\n"
|
|
|
|
" If omitted, the output type (exu or dir) is determined\n"
|
2020-03-18 09:03:07 -07:00
|
|
|
" by the given test extension"),
|
2018-12-24 12:51:52 -08:00
|
|
|
ECORE_GETOPT_STORE_STR('t', "test", "Test to run on the given application"),
|
|
|
|
ECORE_GETOPT_STORE_TRUE('s', "show-on-screen", "Show on screen."),
|
|
|
|
ECORE_GETOPT_STORE_TRUE(0, "scan-objects", "Extract information of all the objects at every shot."),
|
|
|
|
ECORE_GETOPT_STORE_TRUE(0, "external-injection", "Expect events injection via Eina debug channel."),
|
|
|
|
ECORE_GETOPT_STORE_TRUE(0, "disable-screenshots", "Disable screenshots."),
|
|
|
|
ECORE_GETOPT_STORE_STR('f', "fonts-dir", "Specify a directory of the fonts that should be used."),
|
|
|
|
ECORE_GETOPT_STORE_TRUE(0, "stabilize-shots", "Wait for the frames to be stable before taking the shots."),
|
|
|
|
ECORE_GETOPT_STORE_DOUBLE(0, "speed", "Set the speed used to play the given test (default 1.0)."),
|
|
|
|
ECORE_GETOPT_COUNT('v', "verbose", "Turn verbose messages on."),
|
|
|
|
|
|
|
|
ECORE_GETOPT_LICENSE('L', "license"),
|
|
|
|
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
|
|
|
|
ECORE_GETOPT_VERSION('V', "version"),
|
|
|
|
ECORE_GETOPT_HELP('h', "help"),
|
|
|
|
ECORE_GETOPT_SENTINEL
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-27 07:08:46 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_setup_dest_type(const char *dest, Eina_Bool external_injection)
|
2018-12-24 12:51:52 -08:00
|
|
|
{
|
|
|
|
if (dest)
|
|
|
|
{
|
|
|
|
_dest = eina_stringshare_add(dest);
|
|
|
|
if (!strcmp(_dest + strlen(_dest) - 4,".exu"))
|
|
|
|
{
|
|
|
|
_dest_type = FTYPE_EXU;
|
2020-03-17 09:08:40 -07:00
|
|
|
/* Cut path at the beginning of the file name */
|
|
|
|
char *file_start = strrchr(dest, '/');
|
|
|
|
*file_start = '\0';
|
|
|
|
|
|
|
|
if (!ecore_file_mkpath(dest))
|
2018-12-24 12:51:52 -08:00
|
|
|
{
|
2020-03-17 09:08:40 -07:00
|
|
|
fprintf(stderr, "Path for %s cannot be created\n", dest);
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_FALSE;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_dest_type = FTYPE_DIR;
|
2020-03-17 09:08:40 -07:00
|
|
|
if (!ecore_file_mkpath(_dest))
|
2018-12-24 12:51:52 -08:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Directory %s cannot be created\n", _dest);
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_FALSE;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (external_injection)
|
|
|
|
{
|
|
|
|
_src_type = FTYPE_REMOTE;
|
|
|
|
if (_dest_type == FTYPE_UNKNOWN) _dest_type = FTYPE_REMOTE;
|
|
|
|
}
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_setup_names(const char *src)
|
|
|
|
{
|
2018-12-24 12:51:52 -08:00
|
|
|
if (src)
|
|
|
|
{
|
|
|
|
_src_filename = eina_stringshare_add(src);
|
|
|
|
if (!strcmp(_src_filename + strlen(_src_filename) - 4,".exu"))
|
|
|
|
{
|
|
|
|
_src_type = FTYPE_EXU;
|
|
|
|
if (_dest_type == FTYPE_UNKNOWN)
|
|
|
|
{
|
|
|
|
_dest_type = FTYPE_EXU;
|
|
|
|
_dest = "./output.exu";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
char *slash = strrchr(_src_filename, '/');
|
|
|
|
if (slash) _test_name = strdup(slash + 1);
|
|
|
|
else _test_name = strdup(_src_filename);
|
|
|
|
char *dot = strrchr(_test_name, '.');
|
|
|
|
if (dot) *dot = '\0';
|
|
|
|
}
|
2020-03-27 07:08:46 -07:00
|
|
|
}
|
2018-12-24 12:51:52 -08:00
|
|
|
|
2020-03-27 07:08:46 -07:00
|
|
|
static void
|
|
|
|
_setup_dest_unit(void)
|
|
|
|
{
|
2018-12-24 12:51:52 -08:00
|
|
|
if (_dest_type == FTYPE_EXU) _dest_unit = calloc(1, sizeof(*_dest_unit));
|
|
|
|
|
2020-03-27 07:08:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_remove_old_shots(void)
|
|
|
|
{
|
2018-12-24 12:51:52 -08:00
|
|
|
if (_dest_type == FTYPE_DIR && _test_name)
|
|
|
|
eina_file_dir_list(_dest, 0, _old_shots_rm_cb, (void *)_test_name);
|
2020-03-27 07:08:46 -07:00
|
|
|
}
|
2018-12-24 12:51:52 -08:00
|
|
|
|
2020-03-27 07:08:46 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_setup_font_settings(const char *fonts_dir)
|
|
|
|
{
|
|
|
|
const char *chosen_fonts = NULL;
|
2018-12-24 12:51:52 -08:00
|
|
|
if (_src_unit && _src_unit->fonts_path)
|
|
|
|
{
|
2020-03-03 08:36:15 -08:00
|
|
|
char buf[PATH_MAX];
|
2018-12-24 12:51:52 -08:00
|
|
|
if (!fonts_dir) fonts_dir = "./fonts";
|
|
|
|
sprintf(buf, "%s/%s", fonts_dir, _src_unit->fonts_path);
|
|
|
|
if (!ecore_file_exists(buf))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to use the fonts path '%s' provided in %s\n",
|
|
|
|
_src_unit->fonts_path, _src_filename);
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_FALSE;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
chosen_fonts = _src_unit->fonts_path;
|
|
|
|
}
|
|
|
|
if (fonts_dir)
|
|
|
|
{
|
|
|
|
Eina_Tmpstr *fonts_conf_name = NULL;
|
|
|
|
if (!ecore_file_exists(fonts_dir))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to find fonts directory %s\n", fonts_dir);
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_FALSE;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
if (!chosen_fonts)
|
|
|
|
{
|
|
|
|
Eina_List *dated_fonts = ecore_file_ls(fonts_dir);
|
|
|
|
char *date_dir;
|
|
|
|
chosen_fonts = eina_stringshare_add(eina_list_last_data_get(dated_fonts));
|
|
|
|
EINA_LIST_FREE(dated_fonts, date_dir) free(date_dir);
|
|
|
|
}
|
|
|
|
if (chosen_fonts)
|
|
|
|
{
|
|
|
|
int tmp_fd = eina_file_mkstemp("/tmp/fonts_XXXXXX.conf", &fonts_conf_name);
|
|
|
|
FILE *tmp_f = fdopen(tmp_fd, "wb");
|
|
|
|
fprintf(tmp_f,
|
|
|
|
"<?xml version=\"1.0\"?>\n<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n<fontconfig>\n"
|
|
|
|
"<dir prefix=\"default\">%s/%s</dir>\n</fontconfig>\n",
|
|
|
|
fonts_dir, chosen_fonts);
|
|
|
|
fclose(tmp_f);
|
|
|
|
close(tmp_fd);
|
|
|
|
|
|
|
|
setenv("FONTCONFIG_FILE", fonts_conf_name, 1);
|
|
|
|
}
|
|
|
|
}
|
2020-03-27 07:08:46 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_setup_ee_creation(void)
|
|
|
|
{
|
|
|
|
ecore_evas_callback_new_set(_my_evas_new);
|
|
|
|
if (_src_type != FTYPE_REMOTE)
|
|
|
|
ecore_idler_add(_src_feed, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_write_unit_file(void)
|
|
|
|
{
|
|
|
|
if (_dest && _dest_unit)
|
|
|
|
{
|
|
|
|
if (_src_unit)
|
|
|
|
{
|
|
|
|
Exactness_Unit *tmp = NULL;
|
|
|
|
if (_src_type == FTYPE_EXU) tmp = exactness_unit_file_read(_src_filename);
|
|
|
|
_dest_unit->actions = tmp->actions;
|
|
|
|
}
|
|
|
|
exactness_unit_file_write(_dest_unit, _dest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int pret = 1, opt_args = 0;
|
|
|
|
char *src = NULL, *dest = NULL, *eq;
|
|
|
|
char *fonts_dir = NULL;
|
|
|
|
Eina_Bool show_on_screen = EINA_FALSE;
|
|
|
|
Eina_Bool want_quit = EINA_FALSE, external_injection = EINA_FALSE;
|
|
|
|
_evas_new = NULL;
|
|
|
|
|
|
|
|
Ecore_Getopt_Value values[] = {
|
|
|
|
ECORE_GETOPT_VALUE_STR(dest),
|
|
|
|
ECORE_GETOPT_VALUE_STR(src),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(show_on_screen),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(_scan_objects),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(external_injection),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(_disable_shots),
|
|
|
|
ECORE_GETOPT_VALUE_STR(fonts_dir),
|
|
|
|
ECORE_GETOPT_VALUE_BOOL(_stabilize_shots),
|
|
|
|
ECORE_GETOPT_VALUE_DOUBLE(_speed),
|
|
|
|
ECORE_GETOPT_VALUE_INT(_verbose),
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
_log_domain = eina_log_domain_register("exactness_player", NULL);
|
|
|
|
|
|
|
|
if (!ecore_evas_init())
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
opt_args = ecore_getopt_parse(&optdesc, values, argc, argv);
|
|
|
|
if (opt_args < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Failed parsing arguments.\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (want_quit) goto end;
|
|
|
|
|
|
|
|
/* Check for a sentinel */
|
|
|
|
if (argv[opt_args] && !strcmp(argv[opt_args], "--")) opt_args++;
|
|
|
|
|
|
|
|
/* Check for env variables */
|
|
|
|
do
|
|
|
|
{
|
|
|
|
eq = argv[opt_args] ? strchr(argv[opt_args], '=') : NULL;
|
|
|
|
if (eq)
|
|
|
|
{
|
|
|
|
char *var = malloc(eq - argv[opt_args] + 1);
|
|
|
|
memcpy(var, argv[opt_args], eq - argv[opt_args]);
|
|
|
|
var[eq - argv[opt_args]] = '\0';
|
|
|
|
setenv(var, eq + 1, 1);
|
|
|
|
opt_args++;
|
|
|
|
}
|
|
|
|
} while (eq);
|
|
|
|
|
|
|
|
if (!src && !external_injection)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "no test file specified\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (src && external_injection)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Cannot inject events from a source file and from outside simultaneously\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!_setup_dest_type(dest, external_injection))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
_setup_names(src);
|
|
|
|
|
|
|
|
if (_scan_objects && _dest_type != FTYPE_EXU)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Scan objects options is available only if the destination is a EXU file\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
_setup_dest_unit();
|
|
|
|
_remove_old_shots();
|
|
|
|
|
|
|
|
if (!_src_open())
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to read source file\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!show_on_screen) setenv("ELM_ENGINE", "buffer", 1);
|
|
|
|
if (!_setup_font_settings(fonts_dir))
|
|
|
|
goto end;
|
exactness: handbuild a new argv array instead of reassemling the new one
this commit removes the code that was changing argv values, and replaces
it with a new array. Which is absolutly fine, as the argv / argc values
are never accessed later on. Only the copies that have been passed to
efl_main or elm_main.
This resolves several issues:
1. the for loop is useless, every single array element that gets
initialized with it, is some offset from argv[0] this may also crash
when argv[i] - argv[opt_args] is bigger strlen argv[0].
2. The memcpy here is super dangerous, the dest array is not garanteed
to have the same size as argv[0], this only works if the client
application name is shorter than the name "exactness_recorder"
3. The memset here is absolutly wrong. There is again no garantee that
the array has the expected size behind that, this was constantly
overwriting the segment after the place where argv was stored, which
was lukely enough on fedora always the environs, which deleted the
couple first segments. (This was not causing any fuzz, since they
have been sudo related env vars on the docker image). However, on
arch this just crashed right away. On Ubuntu this overwrote DISPLAY,
which resulted in the unability to launch the app.
Reviewed-by: Stefan Schmidt <stefan@datenfreihafen.org>
Differential Revision: https://phab.enlightenment.org/D11600
2020-03-25 07:24:09 -07:00
|
|
|
char **new_argv = argv;
|
|
|
|
int new_argc = argc;
|
2018-12-24 12:51:52 -08:00
|
|
|
|
|
|
|
if (argv[opt_args])
|
|
|
|
{
|
|
|
|
/* Replace the current command line to hide the Exactness part */
|
|
|
|
|
exactness: handbuild a new argv array instead of reassemling the new one
this commit removes the code that was changing argv values, and replaces
it with a new array. Which is absolutly fine, as the argv / argc values
are never accessed later on. Only the copies that have been passed to
efl_main or elm_main.
This resolves several issues:
1. the for loop is useless, every single array element that gets
initialized with it, is some offset from argv[0] this may also crash
when argv[i] - argv[opt_args] is bigger strlen argv[0].
2. The memcpy here is super dangerous, the dest array is not garanteed
to have the same size as argv[0], this only works if the client
application name is shorter than the name "exactness_recorder"
3. The memset here is absolutly wrong. There is again no garantee that
the array has the expected size behind that, this was constantly
overwriting the segment after the place where argv was stored, which
was lukely enough on fedora always the environs, which deleted the
couple first segments. (This was not causing any fuzz, since they
have been sudo related env vars on the docker image). However, on
arch this just crashed right away. On Ubuntu this overwrote DISPLAY,
which resulted in the unability to launch the app.
Reviewed-by: Stefan Schmidt <stefan@datenfreihafen.org>
Differential Revision: https://phab.enlightenment.org/D11600
2020-03-25 07:24:09 -07:00
|
|
|
new_argv = calloc(argc - opt_args + 1, sizeof(char*));
|
|
|
|
new_argc = argc - opt_args;
|
|
|
|
|
|
|
|
for (int i = 0; i < argc - opt_args + 1; ++i)
|
2018-12-24 12:51:52 -08:00
|
|
|
{
|
exactness: handbuild a new argv array instead of reassemling the new one
this commit removes the code that was changing argv values, and replaces
it with a new array. Which is absolutly fine, as the argv / argc values
are never accessed later on. Only the copies that have been passed to
efl_main or elm_main.
This resolves several issues:
1. the for loop is useless, every single array element that gets
initialized with it, is some offset from argv[0] this may also crash
when argv[i] - argv[opt_args] is bigger strlen argv[0].
2. The memcpy here is super dangerous, the dest array is not garanteed
to have the same size as argv[0], this only works if the client
application name is shorter than the name "exactness_recorder"
3. The memset here is absolutly wrong. There is again no garantee that
the array has the expected size behind that, this was constantly
overwriting the segment after the place where argv was stored, which
was lukely enough on fedora always the environs, which deleted the
couple first segments. (This was not causing any fuzz, since they
have been sudo related env vars on the docker image). However, on
arch this just crashed right away. On Ubuntu this overwrote DISPLAY,
which resulted in the unability to launch the app.
Reviewed-by: Stefan Schmidt <stefan@datenfreihafen.org>
Differential Revision: https://phab.enlightenment.org/D11600
2020-03-25 07:24:09 -07:00
|
|
|
if (i < argc - opt_args)
|
|
|
|
new_argv[i] = argv[opt_args + i];
|
|
|
|
else
|
|
|
|
new_argv[i] = NULL;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-27 06:03:07 -07:00
|
|
|
fprintf(stderr, "no program specified\nUse -h for more information\n");
|
|
|
|
goto end;
|
2018-12-24 12:51:52 -08:00
|
|
|
}
|
2020-03-27 07:08:46 -07:00
|
|
|
_setup_ee_creation();
|
2018-12-24 12:51:52 -08:00
|
|
|
|
exactness: handbuild a new argv array instead of reassemling the new one
this commit removes the code that was changing argv values, and replaces
it with a new array. Which is absolutly fine, as the argv / argc values
are never accessed later on. Only the copies that have been passed to
efl_main or elm_main.
This resolves several issues:
1. the for loop is useless, every single array element that gets
initialized with it, is some offset from argv[0] this may also crash
when argv[i] - argv[opt_args] is bigger strlen argv[0].
2. The memcpy here is super dangerous, the dest array is not garanteed
to have the same size as argv[0], this only works if the client
application name is shorter than the name "exactness_recorder"
3. The memset here is absolutly wrong. There is again no garantee that
the array has the expected size behind that, this was constantly
overwriting the segment after the place where argv was stored, which
was lukely enough on fedora always the environs, which deleted the
couple first segments. (This was not causing any fuzz, since they
have been sudo related env vars on the docker image). However, on
arch this just crashed right away. On Ubuntu this overwrote DISPLAY,
which resulted in the unability to launch the app.
Reviewed-by: Stefan Schmidt <stefan@datenfreihafen.org>
Differential Revision: https://phab.enlightenment.org/D11600
2020-03-25 07:24:09 -07:00
|
|
|
pret = ex_prg_invoke(ex_prg_full_path_guess(new_argv[0]), new_argc, new_argv, EINA_TRUE);
|
2018-12-24 12:51:52 -08:00
|
|
|
|
2020-03-27 07:08:46 -07:00
|
|
|
_write_unit_file();
|
2018-12-24 12:51:52 -08:00
|
|
|
|
|
|
|
end:
|
2020-01-31 04:34:23 -08:00
|
|
|
ecore_evas_shutdown();
|
2020-03-23 09:46:10 -07:00
|
|
|
eina_log_domain_unregister(_log_domain);
|
|
|
|
_log_domain = -1;
|
2018-12-24 12:51:52 -08:00
|
|
|
return pret;
|
|
|
|
}
|