diff --git a/src/bin/.gitignore b/src/bin/.gitignore index ac82ee4..cffebe9 100644 --- a/src/bin/.gitignore +++ b/src/bin/.gitignore @@ -1 +1,2 @@ /exactness +/exactness_helper diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 079a7f1..35ae159 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -1,6 +1,6 @@ MAINTAINERCLEANFILES = Makefile.in -bin_PROGRAMS = exactness +bin_PROGRAMS = exactness exactness_helper exactness_SOURCES = \ exactness.c \ @@ -9,11 +9,18 @@ exactness_SOURCES = \ scheduler.c \ run_test.c +exactness_helper_SOURCES = exactness_helper.c + exactness_LDADD = \ @EFL_LIBS@ +exactness_helper_LDADD = \ + @EFL_LIBS@ ../lib/libexactness.la + exactness_CFLAGS = \ @EFL_CFLAGS@ \ -I$(top_srcdir)/src/lib \ -DPACKAGE_LIBDIR=\"$(libdir)\" \ -DPACKAGE_DATADIR=\"$(datadir)\" + +exactness_helper_CFLAGS = @EFL_CFLAGS@ -I$(top_srcdir)/src/lib diff --git a/src/bin/exactness_helper.c b/src/bin/exactness_helper.c new file mode 100644 index 0000000..ab5cc03 --- /dev/null +++ b/src/bin/exactness_helper.c @@ -0,0 +1,246 @@ +#include +#include + +#include "tsuite_file_data.h" + +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; + 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; + 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_helper", + "%prog [options] ", + NULL, + "(C) 2016 Enlightenment", + "BSD", + "Helper for Exactness", + 0, + { + ECORE_GETOPT_STORE_USHORT('d', "delay", "Delay the given recording by a given time (in seconds)."), + 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_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; +} + +int +main(int argc, char *argv[]) +{ + const char *rec_file = NULL; + int ret = 0, args = 0; + unsigned short delay = 0; + Eina_Bool want_quit, clean = EINA_FALSE, list_get = EINA_FALSE; + Ecore_Getopt_Value values[] = { + ECORE_GETOPT_VALUE_USHORT(delay), + ECORE_GETOPT_VALUE_BOOL(clean), + ECORE_GETOPT_VALUE_BOOL(list_get), + + 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_init(); + want_quit = EINA_FALSE; + + args = ecore_getopt_parse(&optdesc, values, argc, argv); + if (args < 0) + { + fprintf(stderr, "Failed parsing arguments.\n"); + ret = 1; + goto end; + } + else if (want_quit) + { + ret = 1; + goto end; + } + else if (args == argc) + { + fprintf(stderr, "Expected rec file as the last argument..\n"); + ecore_getopt_help(stderr, &optdesc); + ret = 1; + goto end; + } + + rec_file = argv[args]; + Timer_Data td; + Lists_st *list = read_events(rec_file, &td); + + 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); + } + } + if (!list->first_timestamp) + { + list->first_timestamp = evt_time_get(0, eina_list_data_get(list->variant_list)); + } + } + + if (delay) + { + delay *= 1000; + + if (!list->first_timestamp) + { + list->first_timestamp = evt_time_get(0, eina_list_data_get(list->variant_list)); + } + list->first_timestamp -= delay; + } + + if (list_get) + { + Variant_st *v; + Eina_List *itr; + printf("First timestamp: "); + if (list->first_timestamp) printf("%u\n", list->first_timestamp); + else printf("undefined\n"); + EINA_LIST_FOREACH(list->variant_list, itr, v) + { + char specific_output[1024]; + unsigned int timestamp = evt_time_get(0, v); + if (!timestamp) printf("BAD_TIME: "); + else printf("%.3f: ", (list->first_timestamp ? timestamp - list->first_timestamp : timestamp) / 1000.0); + printf("%s", _event_name_get(v)); + _event_specific_info_get(v, specific_output); + if (*specific_output) printf(" - %s", specific_output); + printf("\n"); + } + } + + write_events(rec_file, list); + +end: + ecore_shutdown(); + + return ret; +} diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index b983abf..35b7e4d 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -18,7 +18,7 @@ libexactness_la_SOURCES = \ tsuite_evas_hook.c \ tsuite_file_data.c -libexactness_la_LDFLAGS = -module -avoid-version -rdynamic +libexactness_la_LDFLAGS = -avoid-version -rdynamic libexactness_la_DEPENDENCIES = $(top_builddir)/config.h libexactness_la_LIBADD = @EFL_LIBS@ libexactness_la_CFLAGS = @EFL_CFLAGS@ diff --git a/src/lib/tsuite_evas_hook.c b/src/lib/tsuite_evas_hook.c index fdb4ac3..e2dcdf7 100644 --- a/src/lib/tsuite_evas_hook.c +++ b/src/lib/tsuite_evas_hook.c @@ -65,7 +65,7 @@ _tsuite_verbosef(const char *fmt, ...) * @ingroup Tsuite */ -static unsigned int +unsigned int evt_time_get(unsigned int tm, Variant_st *v) { switch(tsuite_event_mapping_type_get(v->t.type)) diff --git a/src/lib/tsuite_file_data.c b/src/lib/tsuite_file_data.c index 5afe7d7..ecbaa45 100644 --- a/src/lib/tsuite_file_data.c +++ b/src/lib/tsuite_file_data.c @@ -211,7 +211,7 @@ write_events(const char *filename, Lists_st *vr_list) } Lists_st * -read_events(char *filename, Timer_Data *td) +read_events(const char *filename, Timer_Data *td) { Lists_st *vr_list; Eet_File *fp = eet_open(filename, EET_FILE_MODE_READ); diff --git a/src/lib/tsuite_file_data.h b/src/lib/tsuite_file_data.h index 8f53856..f453f22 100644 --- a/src/lib/tsuite_file_data.h +++ b/src/lib/tsuite_file_data.h @@ -1,11 +1,40 @@ #ifndef _TSUITE_EVAS_HOOK_H #define _TSUITE_EVAS_HOOK_H +#include +#include + #define CACHE_FILE_ENTRY "cache" /* Macro declaring a function argument to be unused */ #define __UNUSED__ __attribute__((unused)) +#ifdef EAPI +# undef EAPI +#endif + +#ifdef _WIN32 +# ifdef EXACTNESS_BUILD +# ifdef DLL_EXPORT +# define EAPI __declspec(dllexport) +# else +# define EAPI +# endif /* ! DLL_EXPORT */ +# else +# define EAPI __declspec(dllimport) +# endif /* ! EXACTNESS_BUILD */ +#else +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +# else +# define EAPI +# endif +#endif /* ! _WIN32 */ + enum _Tsuite_Event_Type { /* Add any supported events here */ TSUITE_EVENT_NOT_SUPPORTED = 0, @@ -220,7 +249,9 @@ const char * tsuite_event_mapping_type_str_get(Tsuite_Event_Type t); const char * _variant_type_get(const void *data, Eina_Bool *unknow); Eina_Bool _variant_type_set(const char *type, void *data, Eina_Bool unknow); -Lists_st * free_events(Lists_st *st, char *recording); -void write_events(const char *filename, Lists_st *vr_list); -Lists_st *read_events(char *filename, Timer_Data *td); +EAPI Tsuite_Event_Type tsuite_event_mapping_type_get(const char *name); +EAPI Lists_st * free_events(Lists_st *st, char *recording); +EAPI void write_events(const char *filename, Lists_st *vr_list); +EAPI Lists_st *read_events(const char *filename, Timer_Data *td); +EAPI unsigned int evt_time_get(unsigned int tm, Variant_st *v); #endif