parent
7a4e7f2e55
commit
76a433273e
3 changed files with 489 additions and 1 deletions
@ -1,4 +1,5 @@ |
||||
/exactness |
||||
/exactness_helper |
||||
/exactness_play |
||||
/exactness_record |
||||
/exactness_canvas.eo.* |
||||
|
@ -0,0 +1,481 @@ |
||||
#define _GNU_SOURCE 1 |
||||
#define EFL_EO_API_SUPPORT |
||||
#define EFL_BETA_API_SUPPORT |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <getopt.h> |
||||
#include <unistd.h> |
||||
|
||||
#include <sys/types.h> |
||||
#include <sys/sysinfo.h> |
||||
#include <dlfcn.h> |
||||
|
||||
#include <Eina.h> |
||||
#include <Eo.h> |
||||
#include <Evas.h> |
||||
#include <Ecore.h> |
||||
#include <Ecore_File.h> |
||||
#include <Ecore_Con.h> |
||||
#include <Elementary.h> |
||||
|
||||
#include "tsuite_file_data.h" |
||||
#include "exactness_private.h" |
||||
|
||||
#define MAX_PATH 1024 |
||||
#define SHOT_KEY_STR "F2" |
||||
#define SAVE_KEY_STR "F3" |
||||
|
||||
<<<<<<< HEAD |
||||
#include <canvas/evas_canvas.eo.h> |
||||
#include "exactness_canvas.eo.h" |
||||
|
||||
static const char *_rec_filename = NULL; |
||||
======= |
||||
static Evas *(*_evas_new)(void) = NULL; |
||||
static const char *_out_filename = NULL; |
||||
>>>>>>> 0cce6b6... SqR |
||||
static const char *_test_name = NULL; |
||||
static int _verbose = 0; |
||||
|
||||
static Eina_List *_evas_list = NULL; |
||||
static int _last_evas_id = 0; |
||||
|
||||
static Lists_st *_events_list = NULL; |
||||
|
||||
static char *_shot_key = NULL; |
||||
|
||||
static void |
||||
_printf(int verbose, const char *fmt, ...) |
||||
{ |
||||
va_list ap; |
||||
if (!_verbose || verbose > _verbose) return; |
||||
|
||||
va_start(ap, fmt); |
||||
vprintf(fmt, ap); |
||||
va_end(ap); |
||||
} |
||||
|
||||
static Tsuite_Event_Type |
||||
_event_pointer_type_get(Efl_Pointer_Action t) |
||||
{ |
||||
switch(t) |
||||
{ |
||||
case EFL_POINTER_ACTION_IN: return TSUITE_EVENT_MOUSE_IN; |
||||
case EFL_POINTER_ACTION_OUT: return TSUITE_EVENT_MOUSE_OUT; |
||||
case EFL_POINTER_ACTION_DOWN: return TSUITE_EVENT_MULTI_DOWN; |
||||
case EFL_POINTER_ACTION_UP: return TSUITE_EVENT_MULTI_UP; |
||||
case EFL_POINTER_ACTION_MOVE: return TSUITE_EVENT_MULTI_MOVE; |
||||
case EFL_POINTER_ACTION_WHEEL: return TSUITE_EVENT_MOUSE_WHEEL; |
||||
default: |
||||
return TSUITE_EVENT_NOT_SUPPORTED; |
||||
} |
||||
} |
||||
|
||||
static const char * |
||||
_event_name_get(Tsuite_Event_Type type) |
||||
{ |
||||
switch(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 Eina_Bool |
||||
_is_hook_duplicate(const Variant_st *v, Tsuite_Event_Type ev_type, const void *info, int len) |
||||
{ |
||||
if (v->t.type == tsuite_event_mapping_type_str_get(ev_type) && |
||||
!memcmp(v->data, info, len)) return EINA_TRUE; |
||||
return EINA_FALSE; |
||||
} |
||||
|
||||
/* Adding variant to list, this list is later written to EET file */ |
||||
#define ADD_TO_LIST(EVT_TYPE, INFO) \ |
||||
do { /* This macro will add event to EET data list */ \
|
||||
if (_events_list) \
|
||||
{ \
|
||||
const Variant_st *prev_v = eina_list_last_data_get(_events_list->variant_list); \
|
||||
if (!prev_v || !_is_hook_duplicate(prev_v, EVT_TYPE, &INFO, sizeof(INFO))) \
|
||||
{ \
|
||||
_printf(1, "Recording %s\n", tsuite_event_mapping_type_str_get(EVT_TYPE)); \
|
||||
Variant_st *v = malloc(sizeof(Variant_st)); \
|
||||
v->data = malloc(sizeof(INFO)); \
|
||||
_variant_type_set(tsuite_event_mapping_type_str_get(EVT_TYPE), \
|
||||
&v->t, EINA_FALSE); \
|
||||
memcpy(v->data, &INFO, sizeof(INFO)); \
|
||||
_events_list->variant_list = eina_list_append(_events_list->variant_list, v); \
|
||||
} \
|
||||
} \
|
||||
} while (0) |
||||
|
||||
static int |
||||
_evas_id_get(Evas *e) |
||||
{ |
||||
return (intptr_t)efl_key_data_get(e, "__evas_id"); |
||||
} |
||||
|
||||
static void |
||||
_event_pointer_cb(void *data, const Efl_Event *event) |
||||
{ |
||||
Eo *eo_e = data; |
||||
Eo *evp = event->info; |
||||
if (!evp) return; |
||||
|
||||
int timestamp = efl_input_timestamp_get(evp); |
||||
int n_evas = _evas_id_get(eo_e); |
||||
Efl_Pointer_Action action = efl_input_pointer_action_get(evp); |
||||
Tsuite_Event_Type evt = _event_pointer_type_get(action); |
||||
|
||||
if (!timestamp) return; |
||||
|
||||
_printf(2, "Calling \"%s\" timestamp=<%u>\n", _event_name_get(evt), timestamp); |
||||
|
||||
switch (action) |
||||
{ |
||||
case EFL_POINTER_ACTION_MOVE: |
||||
{ |
||||
double rad = 0, radx = 0, rady = 0, pres = 0, ang = 0, fx = 0, fy = 0; |
||||
int tool = efl_input_pointer_tool_get(evp); |
||||
Eina_Position2D pos = efl_input_pointer_position_get(evp); |
||||
multi_move t = { tool, pos.x, pos.y, rad, radx, rady, pres, ang, fx, fy, timestamp, n_evas }; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(evt, t); |
||||
break; |
||||
} |
||||
case EFL_POINTER_ACTION_DOWN: case EFL_POINTER_ACTION_UP: |
||||
{ |
||||
double rad = 0, radx = 0, rady = 0, pres = 0, ang = 0, fx = 0, fy = 0; |
||||
int b = efl_input_pointer_button_get(evp); |
||||
int tool = efl_input_pointer_tool_get(evp); |
||||
Eina_Position2D pos = efl_input_pointer_position_get(evp); |
||||
Efl_Pointer_Flags flags = efl_input_pointer_button_flags_get(evp); |
||||
multi_event t = { tool, b, pos.x, pos.y, rad, radx, rady, pres, ang, |
||||
fx, fy, flags, timestamp, n_evas }; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(evt, t); |
||||
break; |
||||
} |
||||
case EFL_POINTER_ACTION_IN: case EFL_POINTER_ACTION_OUT: |
||||
{ |
||||
mouse_in_mouse_out t = { timestamp, n_evas }; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(evt, t); |
||||
break; |
||||
} |
||||
case EFL_POINTER_ACTION_WHEEL: |
||||
{ |
||||
Eina_Bool horiz = efl_input_pointer_wheel_horizontal_get(evp); |
||||
int z = efl_input_pointer_wheel_delta_get(evp); |
||||
mouse_wheel t = { horiz, z, timestamp, n_evas }; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(evt, t); |
||||
break; |
||||
} |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static void |
||||
_event_key_cb(void *data, const Efl_Event *event) |
||||
{ |
||||
Efl_Input_Key *evk = event->info; |
||||
Eo *eo_e = data; |
||||
if (!evk) return; |
||||
const char *key = efl_input_key_name_get(evk); |
||||
int timestamp = efl_input_timestamp_get(evk); |
||||
unsigned int n_evas = _evas_id_get(eo_e); |
||||
Tsuite_Event_Type evt = TSUITE_EVENT_KEY_UP_WITH_KEYCODE; |
||||
|
||||
if (efl_input_key_pressed_get(evk)) |
||||
{ |
||||
if (!strcmp(key, _shot_key)) |
||||
{ |
||||
_printf(2, "Take Screenshot: %s timestamp=<%u>\n", __func__, timestamp); |
||||
take_screenshot t = { timestamp, n_evas }; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(TSUITE_EVENT_TAKE_SHOT, t); |
||||
return; |
||||
} |
||||
if (!strcmp(key, SAVE_KEY_STR)) |
||||
{ |
||||
if (_events_list) |
||||
write_events(_rec_filename, _events_list); |
||||
_printf(2, "Save events: %s timestamp=<%u>\n", __func__, timestamp); |
||||
return; |
||||
} |
||||
evt = TSUITE_EVENT_KEY_DOWN_WITH_KEYCODE; |
||||
} |
||||
else |
||||
{ |
||||
if (!strcmp(key, _shot_key) || !strcmp(key, SAVE_KEY_STR)) return; |
||||
} |
||||
if (_events_list) |
||||
{ /* Construct duplicate strings, free them when list if freed */ |
||||
key_down_key_up_with_keycode t; |
||||
t.timestamp = timestamp; |
||||
t.keyname = eina_stringshare_add(key); |
||||
t.key = eina_stringshare_add(efl_input_key_get(evk)); |
||||
t.string = eina_stringshare_add(efl_input_key_string_get(evk)); |
||||
t.compose = eina_stringshare_add(efl_input_key_compose_get(evk)); |
||||
t.keycode = efl_input_key_code_get(evk); |
||||
t.n_evas = n_evas; |
||||
if (t.n_evas >= 0) ADD_TO_LIST(evt, t); |
||||
} |
||||
} |
||||
|
||||
// note: "hold" event comes from above (elm), not below (ecore)
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_event_pointer_callbacks, |
||||
{ EFL_EVENT_POINTER_MOVE, _event_pointer_cb }, |
||||
{ EFL_EVENT_POINTER_DOWN, _event_pointer_cb }, |
||||
{ EFL_EVENT_POINTER_UP, _event_pointer_cb }, |
||||
{ EFL_EVENT_POINTER_IN, _event_pointer_cb }, |
||||
{ EFL_EVENT_POINTER_OUT, _event_pointer_cb }, |
||||
{ EFL_EVENT_POINTER_WHEEL, _event_pointer_cb }, |
||||
{ EFL_EVENT_FINGER_MOVE, _event_pointer_cb }, |
||||
{ EFL_EVENT_FINGER_DOWN, _event_pointer_cb }, |
||||
{ EFL_EVENT_FINGER_UP, _event_pointer_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) |
||||
{ |
||||
_printf(1, "New Evas\n"); |
||||
_evas_list = eina_list_append(_evas_list, e); |
||||
efl_key_data_set(e, "__evas_id", (void *)(intptr_t)_last_evas_id++); |
||||
efl_event_callback_array_add(e, _event_pointer_callbacks(), e); |
||||
} |
||||
return e; |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_prg_invoke(const char *full_path, int argc, char **argv) |
||||
{ |
||||
Eina_Value *ret__; |
||||
int real__; |
||||
|
||||
void (*efl_main)(void *data, const Efl_Event *ev); |
||||
int (*elm_main)(int argc, char **argv); |
||||
int (*c_main)(int argc, char **argv); |
||||
Eina_Module *h = eina_module_new(full_path); |
||||
if (!h || !eina_module_load(h)) |
||||
{ |
||||
fprintf(stderr, "Failed loading %s.\n", full_path); |
||||
if (h) eina_module_free(h); |
||||
return EINA_FALSE; |
||||
} |
||||
efl_main = eina_module_symbol_get(h, "efl_main"); |
||||
elm_main = eina_module_symbol_get(h, "elm_main"); |
||||
c_main = eina_module_symbol_get(h, "main"); |
||||
_evas_new = eina_module_symbol_get(h, "evas_new"); |
||||
if (!_evas_new) |
||||
{ |
||||
fprintf(stderr, "Failed loading symbol 'evas_new' from %s.\n", full_path); |
||||
eina_module_free(h); |
||||
return 1; |
||||
} |
||||
if (efl_main) |
||||
{ |
||||
elm_init(argc, argv); |
||||
efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL); |
||||
ret__ = efl_loop_begin(efl_main_loop_get()); |
||||
real__ = efl_loop_exit_code_process(ret__); |
||||
elm_shutdown(); |
||||
} |
||||
else if (elm_main) |
||||
{ |
||||
elm_init(argc, argv); |
||||
real__ = elm_main(argc, argv); |
||||
elm_shutdown(); |
||||
} |
||||
else if (c_main) |
||||
{ |
||||
real__ = c_main(argc, argv); |
||||
} |
||||
else |
||||
{ |
||||
fprintf(stderr, "Failed loading symbol 'efl_main', 'elm_main' or 'main' from %s.\n", full_path); |
||||
eina_module_free(h); |
||||
real__ = 1; |
||||
} |
||||
return real__; |
||||
} |
||||
|
||||
static Eina_Stringshare * |
||||
_prg_full_path_guess(const char *prg) |
||||
{ |
||||
char full_path[MAX_PATH]; |
||||
if (strchr(prg, '/')) return eina_stringshare_add(prg); |
||||
char *paths = strdup(getenv("PATH")); |
||||
Eina_Stringshare *ret = NULL; |
||||
while (paths && *paths && !ret) |
||||
{ |
||||
char *real_path; |
||||
char *colon = strchr(paths, ':'); |
||||
if (colon) *colon = '\0'; |
||||
|
||||
sprintf(full_path, "%s/%s", paths, prg); |
||||
real_path = ecore_file_realpath(full_path); |
||||
if (*real_path) |
||||
{ |
||||
ret = eina_stringshare_add(real_path); |
||||
// check if executable
|
||||
} |
||||
free(real_path); |
||||
|
||||
paths += strlen(paths); |
||||
if (colon) paths++; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static void |
||||
_print_usage(const char *progn, FILE *outf) |
||||
{ |
||||
fprintf(outf, "Usage: %s [options] [program]\n", progn); |
||||
fprintf(outf, "Options:\n" |
||||
" -t file.rec Name of the filename where to store the test\n" |
||||
" -v Verbose mode\n" |
||||
" -h Print this message and exit\n" |
||||
"\n"); |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_mkdir(const char *dir) |
||||
{ |
||||
if (!ecore_file_exists(dir)) |
||||
{ |
||||
const char *cur = dir + 1; |
||||
do |
||||
{ |
||||
char *slash = strchr(cur, '/'); |
||||
if (slash) *slash = '\0'; |
||||
if (!ecore_file_exists(dir) && !ecore_file_mkdir(dir)) return EINA_FALSE; |
||||
if (slash) *slash = '/'; |
||||
if (slash) cur = slash + 1; |
||||
else cur = NULL; |
||||
} |
||||
while (cur); |
||||
} |
||||
return EINA_TRUE; |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
int pret = 1; |
||||
|
||||
eina_init(); |
||||
|
||||
opterr = 0; |
||||
for (int opt; (opt = getopt(argc, argv, "+vt:h")) != -1;) |
||||
switch (opt) |
||||
{ |
||||
case 0: |
||||
break; |
||||
case 't': |
||||
{ |
||||
_rec_filename = eina_stringshare_add(optarg); |
||||
break; |
||||
} |
||||
case 'v': |
||||
{ |
||||
_verbose++; |
||||
break; |
||||
} |
||||
case 'h': |
||||
{ |
||||
_print_usage(argv[0], stdout); |
||||
pret = 0; |
||||
goto end; |
||||
} |
||||
default: |
||||
{ |
||||
_print_usage(argv[0], stderr); |
||||
goto end; |
||||
} |
||||
} |
||||
|
||||
if (!argv[optind]) |
||||
{ |
||||
fprintf(stderr, "no program specified\nUse -h for more information\n"); |
||||
goto end; |
||||
} |
||||
if (!_rec_filename) |
||||
{ |
||||
fprintf(stderr, "no test file specified\n"); |
||||
goto end; |
||||
} |
||||
else |
||||
{ |
||||
char *slash = strrchr(_rec_filename, '/'); |
||||
if (slash) _test_name = strdup(slash + 1); |
||||
else _test_name = strdup(_rec_filename); |
||||
char *dot = strrchr(_test_name, '.'); |
||||
if (dot) *dot = '\0'; |
||||
if (slash) |
||||
{ |
||||
*slash = '\0'; |
||||
if (!_mkdir(_rec_filename)) |
||||
{ |
||||
fprintf(stderr, "Can't create %s\n", _rec_filename); |
||||
goto end; |
||||
} |
||||
*slash = '/'; |
||||
} |
||||
} |
||||
|
||||
efl_object_init(); |
||||
evas_init(); |
||||
|
||||
/* Replace the current command line to hide the Exactness part */ |
||||
int len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[optind]; |
||||
memcpy(argv[0], argv[optind], len); |
||||
memset(argv[0] + len, 0, _POSIX_PATH_MAX - len); |
||||
|
||||
for (int i = optind; i < argc; i++) |
||||
{ |
||||
if (i != optind) |
||||
{ |
||||
argv[i - optind] = argv[0] + (argv[i] - argv[optind]); |
||||
} |
||||
_printf(1, "%s ", argv[i - optind]); |
||||
} |
||||
_printf(1, "\n"); |
||||
|
||||
if (!_shot_key) _shot_key = getenv("TSUITE_SHOT_KEY"); |
||||
if (!_shot_key) _shot_key = SHOT_KEY_STR; |
||||
|
||||
if (!_events_list) |
||||
{ |
||||
struct sysinfo s_info; |
||||
sysinfo(&s_info); |
||||
_events_list = calloc(1, sizeof(*_events_list)); |
||||
_events_list->first_timestamp = s_info.uptime * 1000; |
||||
_printf(2, "Uptime=<%u>\n", _events_list->first_timestamp); |
||||
} |
||||
|
||||
ecore_evas_callback_new_set(_my_evas_new); |
||||
_prg_invoke(_prg_full_path_guess(argv[0]), argc - optind, argv); |
||||
write_events(_rec_filename, _events_list); |
||||
free_events(_events_list, EINA_TRUE); |
||||
_events_list = NULL; |
||||
|
||||
end: |
||||
eina_shutdown(); |
||||
return pret; |
||||
} |
Loading…
Reference in new issue