Add an new executable to help on recordings maintenance

An issue that currently happens in Exactness is that we don't have any
way to debug the recordings.
Only debug information can help us to figure out what data is stored
inside the rec files.

Three commands are available:
- Clean: remove bad timestamp events and duplicate events
- Add a delay: because of the first event is directly treated if no
first timestamp is present, we need a way to fix recordings by adding
them a delay before the first event.
- List information: display the list of events, as vieet doesn't work at
all. Really helpful to figure out bugs.
This commit is contained in:
Daniel Zaoui 2016-03-23 14:41:47 +02:00
parent 4effc37ab0
commit a21c2f39cc
7 changed files with 292 additions and 7 deletions

1
src/bin/.gitignore vendored
View File

@ -1 +1,2 @@
/exactness
/exactness_helper

View File

@ -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

246
src/bin/exactness_helper.c Normal file
View File

@ -0,0 +1,246 @@
#include <Ecore.h>
#include <Ecore_Getopt.h>
#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] <rec file>",
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;
}

View File

@ -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@

View File

@ -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))

View File

@ -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);

View File

@ -1,11 +1,40 @@
#ifndef _TSUITE_EVAS_HOOK_H
#define _TSUITE_EVAS_HOOK_H
#include <Evas.h>
#include <Eet.h>
#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