From 6187406f27d5ccd913c3750c359e44a60ba3d6e1 Mon Sep 17 00:00:00 2001 From: Thomas Pietrzak Date: Wed, 30 Mar 2011 14:33:38 +0000 Subject: [PATCH 1/1] Import shapes git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@3 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- Makefile | 46 +++ Makefile-win32 | 28 ++ include/control_request.h | 69 ++++ include/display.h | 19 + include/divers.h | 33 ++ include/ecrire.h | 25 ++ include/evenements.h | 29 ++ include/gettimeofday.h | 8 + include/guidance.h | 17 + include/icons.h | 12 + include/instructions.h | 6 + include/params.h | 31 ++ include/vtplayer-ctrl.h | 38 ++ session | 37 ++ src/display.c | 309 ++++++++++++++++ src/divers.c | 14 + src/ecrire.c | 277 +++++++++++++++ src/evenements.c | 206 +++++++++++ src/exemple.c | 383 ++++++++++++++++++++ src/gettimeofday.c | 85 +++++ src/guidance.c | 134 +++++++ src/icons.c | 727 ++++++++++++++++++++++++++++++++++++++ src/instructions.c | 119 +++++++ src/params.c | 125 +++++++ src/saveshapes.c | 515 +++++++++++++++++++++++++++ src/shapes.c | 383 ++++++++++++++++++++ src/vtplayer-ctrl.c | 188 ++++++++++ 27 files changed, 3863 insertions(+) create mode 100644 Makefile create mode 100644 Makefile-win32 create mode 100644 include/control_request.h create mode 100644 include/display.h create mode 100644 include/divers.h create mode 100644 include/ecrire.h create mode 100644 include/evenements.h create mode 100644 include/gettimeofday.h create mode 100644 include/guidance.h create mode 100644 include/icons.h create mode 100644 include/instructions.h create mode 100644 include/params.h create mode 100644 include/vtplayer-ctrl.h create mode 100755 session create mode 100644 src/display.c create mode 100644 src/divers.c create mode 100644 src/ecrire.c create mode 100644 src/evenements.c create mode 100644 src/exemple.c create mode 100644 src/gettimeofday.c create mode 100644 src/guidance.c create mode 100644 src/icons.c create mode 100644 src/instructions.c create mode 100644 src/params.c create mode 100644 src/saveshapes.c create mode 100644 src/shapes.c create mode 100644 src/vtplayer-ctrl.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bfbb55c --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +COMP = gcc +RM = rm -f +# VERSION = 3 +OBJS = obj/shapes.o obj/display.o obj/params.o obj/vtplayer-ctrl.o obj/evenements.o obj/icons.o obj/divers.o obj/guidance.o +LIBS = -lSDL -lGL -lGLU -lusb +# -lefence +# export EF_ALLOW_MALLOC_0=1 +FLAGS = -Wall -g -DDEBUG +# -DWITHOUTVTP +CFLAGS = $(FLAGS) -Iinclude/ +TARGET = bin/shapes +TAR = shapes +REPARCHIVE = shapes-vtp + +all :$(TARGET) + +$(TARGET) : $(OBJS) + $(COMP) $(CFLAGS) -o $@ $^ $(LIBS) + +clean : + $(RM) $(OBJS) + +mrproper : + $(RM) $(OBJS) $(TARGET) $(TARGETDEMO) + +tar: + mkdir $(REPARCHIVE) + mkdir $(REPARCHIVE)/src + mkdir $(REPARCHIVE)/include + mkdir $(REPARCHIVE)/data + mkdir $(REPARCHIVE)/bin + cp Makefile* $(REPARCHIVE)/ + cp data/shape* $(REPARCHIVE)/data + cp data/params $(REPARCHIVE)/data + cp $(TARGET) $(REPARCHIVE)/bin + cp $(TARGET).exe $(REPARCHIVE)/bin + cp src/*.c $(REPARCHIVE)/src + cp include/*.h $(REPARCHIVE)/include + tar -cvzf $(TAR).tar.gz $(REPARCHIVE) + rm -rf $(REPARCHIVE) + +obj/shapes.o : src/shapes.c + $(COMP) $(CFLAGS) -o $@ -c $< + +obj/%.o : src/%.c include/%.h + $(COMP) $(CFLAGS) -o $@ -c $< diff --git a/Makefile-win32 b/Makefile-win32 new file mode 100644 index 0000000..c376786 --- /dev/null +++ b/Makefile-win32 @@ -0,0 +1,28 @@ +COMP = i586-mingw32msvc-gcc -mwindows -Dmain=SDLmain +RM = rm -f +# VERSION = 3 +OBJS = obj/shapes.o obj/display.o obj/params.o obj/vtplayer-ctrl.o obj/evenements.o obj/icons.o obj/divers.o obj/guidance.o obj/gettimeofday.o +LIBS = -lusb -mwindows -lmingw32 -lSDLmain -lSDL -lopengl32 -lglu32 +FLAGS = -Wall +CFLAGS = $(FLAGS) -Iinclude/ +TARGET = bin/shapes.exe + +all : $(TARGET) + +$(TARGET) : $(OBJS) + $(COMP) $(CFLAGS) -o $@ $^ $(LIBS) + +clean : + $(RM) $(OBJS) + +mrproper : + $(RM) $(OBJS) $(TARGET) + +zipwin: + zip shapes.zip $(TARGET) data/* bin/*.dll + +obj/shapes.o : src/shapes.c + $(COMP) $(CFLAGS) -o $@ -c $< + +obj/%.o : src/%.c include/%.h + $(COMP) $(CFLAGS) -o $@ -c $< diff --git a/include/control_request.h b/include/control_request.h new file mode 100644 index 0000000..cf1faa4 --- /dev/null +++ b/include/control_request.h @@ -0,0 +1,69 @@ +#ifndef __CONTROL_REQUEST_H__ +#define __CONTROL_REQUEST_H__ + +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +/* + * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and + * are read as a bit array returned by USB_REQ_GET_STATUS. (So there + * are at most sixteen features of each type.) + */ +#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ +#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ +#define USB_DEVICE_TEST_MODE 2 /* (high speed only) */ +#define USB_DEVICE_B_HNP_ENABLE 3 /* dev may initiate HNP */ +#define USB_DEVICE_A_HNP_SUPPORT 4 /* RH port supports HNP */ +#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* other RH port does */ +#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ + +#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + +#endif diff --git a/include/display.h b/include/display.h new file mode 100644 index 0000000..4b355b4 --- /dev/null +++ b/include/display.h @@ -0,0 +1,19 @@ +#ifndef __DISPLAY__ +#define __DISPLAY__ +#include +#include "vtplayer-ctrl.h" + +int setup_opengl(); + +void draw_screen(); + +// void load_cursor(char *name); +// void draw_cursor(int mousex, int mousey); +void draw_configuration(u32 config, int mousex, int mousey); + +int get_x_from_screen(int x); +int get_y_from_screen(int y); +int get_x_from_opengl(int x); +int get_y_from_opengl(int y); + +#endif diff --git a/include/divers.h b/include/divers.h new file mode 100644 index 0000000..cd7adf1 --- /dev/null +++ b/include/divers.h @@ -0,0 +1,33 @@ +#ifndef __DIVERS__ +#define __DIVERS__ + +#define NULLE_PART -1 +#define HAUT 0 +#define HAUT_DROITE 1 +#define DROITE 2 +#define BAS_DROITE 3 +#define BAS 4 +#define BAS_GAUCHE 5 +#define GAUCHE 6 +#define HAUT_GAUCHE 7 +#define CENTRE 8 + +#ifdef __linux__ +#include +#include +#define MKDIR(r) mkdir(r,0777) +#else +#include +#define MKDIR(r) mkdir(r) +#endif + +#define BUFFERSIZE 256 + +#define CONDITION_PT 0 +#define CONDITION_PV 1 +#define CONDITION_MT 2 +#define CONDITION_MV 3 + +int fileExists(char *f); + +#endif diff --git a/include/ecrire.h b/include/ecrire.h new file mode 100644 index 0000000..bbfdba0 --- /dev/null +++ b/include/ecrire.h @@ -0,0 +1,25 @@ +#include +#include + +#ifndef __ECRIRE__ +#define __ECRIRE__ + +typedef struct text_t +{ + unsigned int texnum; + SDL_Surface *pixels; + SDL_Color color; + int h, w; +} Text; + +/*void vTexte(char *message, short x, short y, char *font_face="./police.ttf", short font_size=16, Uint32 iColor=0, bool shaded=false, Uint32 iColorShaded=0);*/ +Text *SDL_GL_RenderText(char *text, + TTF_Font *font, + SDL_Color color); + +void drawText(Text, SDL_Rect *location); + +void freeText(Text *); +int load_fonts(); + +#endif diff --git a/include/evenements.h b/include/evenements.h new file mode 100644 index 0000000..68c33a0 --- /dev/null +++ b/include/evenements.h @@ -0,0 +1,29 @@ +#ifndef __EVTS__ +#define __EVTS__ + +#include + +struct mouse_status_t +{ + int x, y, b[4];//, min_screen_x, min_screen_y, max_screen_x, max_screen_y; + double vtpx, vtpy; +} mouse_status; + +typedef struct events_t { + int symbol, buttons; +} events_t; + +int get_mouse_x(); +int get_mouse_y(); +int get_vtp_x(); +int get_vtp_y(); +int get_mouse_b(int i); +int get_mouse_any_button(); +/*void set_min_screen_x(int x); +void set_min_screen_y(int y); +void set_max_screen_x(int x); +void set_max_screen_y(int y);*/ +events_t process_events(); +SDL_Thread *create_mouse_status_thread(); + +#endif diff --git a/include/gettimeofday.h b/include/gettimeofday.h new file mode 100644 index 0000000..61f38a5 --- /dev/null +++ b/include/gettimeofday.h @@ -0,0 +1,8 @@ +#ifndef __GETTIMEOFDAY__ +#define __GETTIMEOFDAY__ +#include + +int gettimeofday (struct timeval *tv, void *tz); +int diff_time (struct timeval *debut, int precision); + +#endif diff --git a/include/guidance.h b/include/guidance.h new file mode 100644 index 0000000..36fc834 --- /dev/null +++ b/include/guidance.h @@ -0,0 +1,17 @@ +#ifndef __GUIDANCE__ +#define __GUIDANCE__ + +typedef struct shape_t +{ + int nbv; + int *x, *y; +}shape_type; + +int load_shape(char *name); +void unload_shape(); + +void draw_shape(); + +int get_direction(int posx, int posy); + +#endif diff --git a/include/icons.h b/include/icons.h new file mode 100644 index 0000000..ba2bb94 --- /dev/null +++ b/include/icons.h @@ -0,0 +1,12 @@ +#ifndef __ICONS__ +#define __ICONS__ + +#include "../include/vtplayer-ctrl.h" + +SDL_Thread *create_tacton_thread(); +SDL_Thread *create_pins_thread(); +SDL_Thread *create_translation_thread(); +// void load_set(); +u32 get_tacton(); + +#endif diff --git a/include/instructions.h b/include/instructions.h new file mode 100644 index 0000000..de9337b --- /dev/null +++ b/include/instructions.h @@ -0,0 +1,6 @@ +#ifndef __INSTRUCTIONS__ +#define __INSTRUCTIONS__ + +void instructions(TTF_Font *font, int *pinsconfig, int min_ecran_x, int min_ecran_y, int max_ecran_x, int max_ecran_y ); + +#endif diff --git a/include/params.h b/include/params.h new file mode 100644 index 0000000..55f6b99 --- /dev/null +++ b/include/params.h @@ -0,0 +1,31 @@ +#ifndef __PARAMS__ +#define __PARAMS__ + +#include + +typedef struct param_list_type +{ + char *name; + char *value; + struct param_list_type *next; +} param_list; + +//reads parameters from file +void read_file_params(); + +//reads parameters from command line +int read_command_params(int argc, char *argv[]); + +//add parameters directly +void add_param(char *name, char *value); + +//get one of the parameters value +char *get_params(char *name); + +//get one of the parameters value +void display_params(); + +void delete_params(param_list *l); + +#endif + diff --git a/include/vtplayer-ctrl.h b/include/vtplayer-ctrl.h new file mode 100644 index 0000000..033f34e --- /dev/null +++ b/include/vtplayer-ctrl.h @@ -0,0 +1,38 @@ +#ifndef __VTPLAYER__ +#define __VTPLAYER__ + +typedef unsigned char u8; +typedef unsigned short int u16; +typedef unsigned long int u32; + +// Initialisation de la VTplayer en scannant +// les périphériques USB notament +// retourne 1 si il y a eu une erreur, 0 sinon +int init_vtplayer(void); + +/* "affiche" une configuration sur les pads + numérotation b32...b1 : + +----+----+----+----+ +----+----+----+----+ + | 1 | 2 | 3 | 4 | | 17 | 18 | 19 | 20 | + +----+----+----+----+ +----+----+----+----+ + | 5 | 6 | 7 | 8 | | 21 | 22 | 23 | 24 | + +----+----+----+----+ +----+----+----+----+ + | 9 | 10 | 11 | 12 | | 25 | 26 | 27 | 28 | + +----+----+----+----+ +----+----+----+----+ + | 13 | 14 | 15 | 16 | | 29 | 30 | 31 | 32 | + +----+----+----+----+ +----+----+----+----+ +*/ + +int release_vtplayer(void) + +int set_pads(u32 pads); + +/* retourne le mouvement en x,y et les boutons enfoncés + - le premier octet contient le mouvement en x + - le deuxième octet contient le mouvement en y + - le troisième octet n'est pas utilisé + - le quatrième octet contient les boutons enfoncés (de 1 à 4) +*/ +int get_status(u8 * data); + +#endif diff --git a/session b/session new file mode 100755 index 0000000..3cab154 --- /dev/null +++ b/session @@ -0,0 +1,37 @@ +#!/bin/bash +NBCONDITIONS=2 +NBPERSERIES=11 +NBSHAPES=29 + +if [ $# -le $NBCONDITIONS ] ; then + echo "Usage : $0 name Condition1 Condition2 Condition 3 Condition4"; + echo " Condition = PT | Pv | Mt | Mv"; + exit; +fi + +# shapes=(`seq 1 1 $NBSHAPES`) +for n in `seq 0 1 $[$NBSHAPES - 1]` ; do + shapes[$n]=0; +done + +for i in `seq 2 1 $[$NBCONDITIONS + 1]` ; do + #generate series for condition i + for j in `seq 1 1 $NBPERSERIES` ; do + numcircuit=$RANDOM; + let "numcircuit %= $NBSHAPES" + while [ ${shapes[$numcircuit]} -eq 1 ] ; do + numcircuit=$RANDOM; + let "numcircuit %= $NBSHAPES" + done + if [ $j -le 1 ] ; then + echo "sudo xinit ./bin/shapes -name $1 -condition ${!i} -shape shape$[$numcircuit + 1] -training yes -- :1 -ac -xf86config ./xorgmono.conf" +# echo "sudo ./bin/shapes -name $1 -condition ${!i} -training yes -shape shape$[$numcircuit + 1]"; + else + echo "sudo xinit ./bin/shapes -name $1 -condition ${!i} -shape shape$[$numcircuit + 1] -- :1 -ac -xf86config ./xorgmono.conf" +# echo "sudo ./bin/shapes -name $1 -condition ${!i} -shape shape$[$numcircuit + 1]"; + fi +# ./bin/shapes -name $1 -condition ${!i} -shape shape$[$numcircuit + 1]; + shapes[numcircuit]=1; + done +done +# ${shapes[$numcircuit]} diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..c9a916f --- /dev/null +++ b/src/display.c @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include +#include + +#include "display.h" +#include "evenements.h" +#include "divers.h" +#include "guidance.h" +#include "params.h" +#include "icons.h" + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +#define COLOR_FOND 1.0, 1.0, 1.0 + +SDL_Surface *screen = NULL; +// SDL_Surface *cursor = NULL; +unsigned int cursortexture; +const SDL_VideoInfo *info; +int max_screen_x; +int min_screen_x; +int max_screen_y; +int min_screen_y; +int resol_x; +int resol_y; +extern u32 tacton; +extern int condition; +extern int left_handed; + +int setup_opengl() +{ + dprintf("List video modes\n"); + SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); + if (modes == NULL) + { + printf("Impossible to find the screen resolution!\n"); + return 1; + } + else if (modes == (SDL_Rect **)-1) + { + resol_x = 1024; + resol_y = 768; + } + else + { + resol_x = modes[0]->w; + resol_y = modes[0]->h; + } + dprintf("Resolution choosen: %dx%d\n", resol_x, resol_y); + max_screen_x = (int)(500 *((float) resol_x) / ((float) resol_y)); + min_screen_x = - max_screen_x; + max_screen_y = 500; + min_screen_y = - max_screen_y; + + dprintf("Init SDL subsystem\n"); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + { + printf("Couldn't initialise Video SubSystem: %s\n", SDL_GetError()); + return 1; + } + + dprintf("Init GL Attributes\n"); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8); + + int flags = SDL_OPENGLBLIT | SDL_HWSURFACE | SDL_FULLSCREEN; + dprintf("Set video mode %dx%d %08x\n", resol_x, resol_y, flags); + //this appears to cause the segfault at the end of the program + screen = SDL_SetVideoMode(resol_x, resol_y, 0, flags); + + if (!screen) + { + printf("Impossible de changer le mode video : %s\n", SDL_GetError()); + return 1; + } + +// SDL_LockSurface(screen); + GLdouble ratio = (GLdouble) screen->w / screen->h; + printf("infos : %08x %d %d %d\n", screen->flags, screen->w, screen->h, screen->pitch); + printf("Video resolution: %dx%dx%d (ratio = %3.2f)\n", screen->w, screen->h, screen->format->BitsPerPixel, ratio); +// SDL_UnlockSurface(screen); + + printf("OpenGL infos\n"); + printf("------------\n"); + printf("Vendor : %s\n", glGetString(GL_VENDOR)); + printf("Renderer : %s\n", glGetString(GL_RENDERER)); + printf("Version : %s\n", glGetString(GL_VERSION)); + printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)); + + glClearColor(COLOR_FOND, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dprintf("Setting viewport\n"); + glViewport(0, 0, resol_x, resol_y); + switch(glGetError()) + { + case GL_INVALID_VALUE: + printf("Wrong resolution\n"); + return 1; + case GL_INVALID_OPERATION: + printf("Check the position of the glViewport instruction\n"); + return 1; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + dprintf("Setting projection\n"); + gluOrtho2D(0, resol_x, resol_y, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + return 0; +} + +void draw_screen() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + //draws the shape + draw_shape(); + + //draws the cursor + switch (condition) + { + case CONDITION_PV: + draw_configuration(get_tacton(), get_mouse_x(), get_mouse_y()); + break; + case CONDITION_MV: + draw_configuration(get_tacton(), get_vtp_x(), get_vtp_y()); + break; + case CONDITION_PT: + draw_configuration(get_tacton(), get_mouse_x(), get_mouse_y()); + break; + case CONDITION_MT: + draw_configuration(get_tacton(), get_vtp_x(), get_vtp_y()); + break; + } + SDL_GL_SwapBuffers(); +} + +#if 0 +void load_cursor(char *name) +{ + cursor = IMG_Load (name); + if (cursor) + { + glGenTextures (1, &cursortexture); + glBindTexture (GL_TEXTURE_2D, cursortexture); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + SDL_Surface *temp = NULL; + SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255}; + switch(cursor->format->BitsPerPixel) + { + case 24: + //convert to 32bits + temp = SDL_ConvertSurface(cursor, &format, SDL_SWSURFACE); + SDL_FreeSurface(cursor); + cursor = temp; + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, cursor->w, cursor->h, GL_RGB, GL_UNSIGNED_BYTE, cursor->pixels); + break; + case 32: + //convert if it's ABGR + if (cursor->format->Rshift > cursor->format->Bshift) + { + temp = SDL_ConvertSurface(cursor, &format, SDL_SWSURFACE); + SDL_FreeSurface(cursor); + cursor = temp; + } + break; + } + gluBuild2DMipmaps(GL_TEXTURE_2D, 4, cursor->w, cursor->h, GL_RGBA, GL_UNSIGNED_BYTE, cursor->pixels); + } +} + +void draw_cursor(int mousex, int mousey) +{ + if (cursor) + { + glEnable(GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glColor3d(1.0, 1.0, 1.0); + glBindTexture(GL_TEXTURE_2D, cursortexture); + glBegin(GL_QUADS); + glTexCoord2d(0,0) ; glVertex2d(mousex - 15, mousey - 15); + glTexCoord2d(1,0) ; glVertex2d(mousex + 15, mousey - 15); + glTexCoord2d(1,1) ; glVertex2d(mousex + 15, mousey + 15); + glTexCoord2d(0,1) ; glVertex2d(mousex - 15, mousey + 15); + glEnd(); + glDisable(GL_TEXTURE_2D); +// glColor3d(1.0, 1.0, 1.0); + } + else + { + glDisable(GL_BLEND); + glBegin(GL_LINES); + glColor3d(1.0, 0.5, 0.5); + glVertex2d(mousex - 10, mousey); + glVertex2d(mousex + 10, mousey); + glVertex2d(mousex, mousey-10); + glVertex2d(mousex, mousey+10); + glEnd(); + glBegin(GL_POLYGON); + glColor3d(0.0, 0.0, 0.0); + glVertex2d(mousex - 7, mousey - 7); + glVertex2d(mousex + 7, mousey - 7); + glVertex2d(mousex + 7, mousey + 7); + glVertex2d(mousex - 7, mousey + 7); + glEnd(); + /* glBegin(GL_POLYGON); + glColor3d(1.0, 1.0, 1.0); + glVertex2d(mousex - 5, mousey - 5); + glVertex2d(mousex + 5, mousey - 5); + glVertex2d(mousex + 5, mousey + 5); + glVertex2d(mousex - 5, mousey + 5); + glEnd();*/ + glEnable(GL_BLEND); + } +} +#endif + +void draw_configuration(u32 config, int mousex, int mousey) +{ + glDisable(GL_BLEND); + int i, j; + for (i = 0 ; i < 4 ; i++) + { + for (j = 0 ; j < 4 ; j++) + { + glBegin(GL_POLYGON); + switch (condition) + { + case CONDITION_MV: case CONDITION_PV: + if (0x00000001 & config >> (i + 4 * j)) + glColor3d(0.0, 0.0, 0.0); + else if ((0x00010000 & config >> (i + 4 * j))) + glColor3d(1.0, 0.0, 0.0); + else + glColor3d(0.8, 0.8, 0.8); + break; + case CONDITION_MT: case CONDITION_PT: + if (0x00000001 & config >> (i + 4 * j)) + glColor3d(0.0, 0.0, 0.0); + else if ((0x00010000 & config >> (i + 4 * j))) + glColor3d(1.0, 0.0, 0.0); + else + glColor3d(0.8, 0.8, 0.8); + break; + } + glVertex2d(mousex - 10 + 5 * i, mousey - 10 + 5 * j); + glVertex2d(mousex - 4 + 5 * i, mousey - 10 + 5 * j); + glVertex2d(mousex - 4 + 5 * i, mousey - 5 + 5 * j); + glVertex2d(mousex - 10 + 5 * i, mousey - 5 + 5 * j); + glEnd(); + } + glBegin(GL_LINE_LOOP); + glColor3d(0.0, 0.0, 0.0); + glVertex2d(mousex - 10, mousey - 10); + glVertex2d(mousex + 10, mousey - 10); + glVertex2d(mousex + 10, mousey + 10); + glVertex2d(mousex - 10, mousey + 10); + glEnd(); + } + glEnable(GL_BLEND); +} + +//translate the x coordinate from screen position to opengl surface +int get_x_from_screen(int x) +{ + return (x * (max_screen_x - min_screen_x)) / resol_x + min_screen_x; +} + +//translate the y coordinate from screen position to opengl surface +int get_y_from_screen(int y) +{ + return (y * (max_screen_y - min_screen_y)) / resol_y + min_screen_y; +} + +//translate the x coordinate from opengl surface to screen position +int get_x_from_opengl(int x) +{ + return ((x - min_screen_x) * resol_x) / (max_screen_x - min_screen_x); +} + +//translate the y coordinate from opengl surface to screen position +int get_y_from_opengl(int y) +{ + return resol_y - ((y - min_screen_y) * resol_y) / (max_screen_y - min_screen_y); +} diff --git a/src/divers.c b/src/divers.c new file mode 100644 index 0000000..7002f23 --- /dev/null +++ b/src/divers.c @@ -0,0 +1,14 @@ +#include "divers.h" + +#include + +int fileExists(char *f) +{ + FILE *file; + if ((file = fopen(f, "rb")) != NULL) + { + fclose(file); + return 1; + } + return 0; +} diff --git a/src/ecrire.c b/src/ecrire.c new file mode 100644 index 0000000..db67752 --- /dev/null +++ b/src/ecrire.c @@ -0,0 +1,277 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ecrire.h" +#include "divers.h" + +//on définit un décalage des polices. Bizarrement sous windows et linux il n'y a pas les mêmes +//tailles pour les surfaces de rendu. +#ifdef WIN32 + #define TEXTSHIFT 8 +#else + #define TEXTSHIFT 0 +#endif + +SDL_Surface *text; +TTF_Font *font, *fontsmall; + +//un chouilla pompé sur +//http://64.233.183.104/search?q=cache:KPK8UvSs0_MJ:www.gamedev.net/community/forums/topic.asp%3Ftopic_id%3D284259+SDL_TTF+opengl&hl=en&client=firefox +int arrondit(double x) +{ + return (int)(x + 0.5); +} +int nextpoweroftwo(int x) +{ + double logbase2 = log(x) / log(2); + return arrondit(pow(2,ceil(logbase2))); +} + +//c'est notre fonction qui affiche un, texte +Text *SDL_GL_RenderText(char *text, TTF_Font *font, SDL_Color color/*, SDL_Rect *location*/) +{ + //on va avoir besoin de quelques surfaces + SDL_Surface *initial; + SDL_Surface *intermediary; + //les tailles du texte + int w,h; + //la texture où on va mettre le texte + GLuint texture; + Text *t = (Text *) malloc(sizeof(Text)); + + //on veut écrire en blanc sur noir dansun premier temps + SDL_Color color2; + color2.r = 255; + color2.g = 255; + color2.b = 255; + + //on écrit le texte sur la premi�re surface + if ((initial = TTF_RenderText_Blended(font, text, color2)) == NULL) + { + free(t); + return NULL; + } +// if ((initial = TTF_RenderText_Solid(font, text, color2)) == NULL) +// return NULL; + + //on va créer une surface en puissance de 2 + w = nextpoweroftwo(initial->w); + h = nextpoweroftwo(initial->h); + + intermediary = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); + + //on va copier la première surface dans la deuxième + SDL_BlitSurface(initial, 0, intermediary, 0); +// SDL_UpdateRects(intermediary, 1, &location); + //on met le fond en transparent (alpha à 0) et le reste à la couleur voulue + int i; + for (i=0 ; i< h * w ; i++) + { + ((char *)(intermediary->pixels))[i * 4 + 3] = ((char *)(intermediary->pixels))[i * 4 + 0]; + ((char *)(intermediary->pixels))[i * 4 + 0] = color.r; + ((char *)(intermediary->pixels))[i * 4 + 1] = color.g; + ((char *)(intermediary->pixels))[i * 4 + 2] = color.b; + } + + //on crée une texxture openGL + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, intermediary->pixels ); + + t->pixels = intermediary; + t->texnum = texture; + t->color = color; + t->h = h; + t->w = w; +// //on la paramètre + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);//GL_REPLACE); + +// //on l'utilise +// glEnable(GL_TEXTURE_2D); +// glBindTexture(GL_TEXTURE_2D, texture); +// +// //on s'occuppe de nos couleurs et on dit qu'on veut de la transparence +// glColor4f(color.r/255.0, color.g/255.0, color.b/255.0, 1.0); +// glEnable(GL_BLEND); +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// +// //on dessine le texte où on le voulait +// glBegin(GL_QUADS); +// glTexCoord2f(0.0f, 1.0f); +// glVertex2f(location->x, location->y - h + TEXTSHIFT); +// glTexCoord2f(1.0f, 1.0f); +// glVertex2f(location->x + w, location->y - h + TEXTSHIFT); +// glTexCoord2f(1.0f, 0.0f); +// glVertex2f(location->x + w, location->y + TEXTSHIFT); +// glTexCoord2f(0.0f, 0.0f); +// glVertex2f(location->x, location->y + TEXTSHIFT); +// glEnd(); +// +// //on désactive la transparence +// glDisable(GL_BLEND); +// glColor4f(1.0f, 1.0f, 1.0f, 0.0f); +// // glFinish(); +// glDisable(GL_TEXTURE_2D); +// +// //on recopie les tailles au cas où ça intéresse quelqu'un +// location->w = initial->w; +// location->h = initial->h; + + //on détruit les surfaces et es textures qu'on a utilisé + SDL_FreeSurface(initial); + SDL_FreeSurface(intermediary); +// glDeleteTextures(1, &texture); + return t; +} + + +void drawText(Text texture, SDL_Rect *location) +{ +// //on la paramètre +// glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); +// glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);//GL_REPLACE); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + //on l'utilise + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texture.texnum); + //on s'occuppe de nos couleurs et on dit qu'on veut de la transparence +// glColor4f(texture.color.r/255.0, texture.color.g/255.0, texture.color.b/255.0, 1.0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +/* Dessin du sprite avec transparence */ + //on dessine le texte où on le voulait + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(location->x, location->y - texture.h + TEXTSHIFT); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(location->x + texture.w, location->y - texture.h + TEXTSHIFT); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(location->x + texture.w, location->y + TEXTSHIFT); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(location->x, location->y + TEXTSHIFT); + glEnd(); + + //on désactive la transparence + glDisable(GL_BLEND); +/* glFinish();*/ + glDisable(GL_TEXTURE_2D); + + //on recopie les tailles au cas où ça intéresse quelqu'un +// location->w = initial->w; +// location->h = initial->h; +} + +void freeText(Text *text) +{ +// SDL_FreeSurface(text->pixels); + glDeleteTextures(1, &text->texnum); + free(text); +} + +int load_fonts() +{ + char *buffer; + if (fileExists("FreeMono.ttf")) + buffer = "FreeMono.ttf"; + else if (fileExists("data/FreeMono.ttf")) + buffer = "data/FreeMono.ttf"; + else if (fileExists("../data/FreeMono.ttf")) + buffer = "../data/FreeMono.ttf"; + else + return 1; + if(TTF_Init()) + { + printf("Erreur while loading TTF: %s\n", TTF_GetError()); + return 1; + } + if(!(font = TTF_OpenFont(buffer, 50))) + { + printf("Erreur while loading the font: %s\n", TTF_GetError()); + return 1; + } + if(!(fontsmall = TTF_OpenFont(buffer, 25))) + { + printf("Erreur while loading the font: %s\n", TTF_GetError()); + return 1; + } + return 0; +} + + +// void SDL_GL_RenderText(char *text, +// TTF_Font *font, +// SDL_Color color, +// SDL_Rect *location) +// { +// SDL_Surface *initial; +// SDL_Surface *intermediary; +// // SDL_Rect rect; +// int w,h; +// GLuint texture; +// +// // Use SDL_TTF to render our text +// initial = TTF_RenderText_Blended(font, text, color); +// +// // Convert the rendered text to a known format +// w = nextpoweroftwo(initial->w); +// h = nextpoweroftwo(initial->h); +// +// intermediary = SDL_CreateRGBSurface(0, w, h, 32, +// 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); +// +// SDL_BlitSurface(initial, 0, intermediary, 0); +// +// // Tell GL about our new texture +// glGenTextures(1, &texture); +// glBindTexture(GL_TEXTURE_2D, texture); +// glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, +// GL_UNSIGNED_BYTE, intermediary->pixels ); +// +// // GL_NEAREST looks horrible, if scaled... +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// +// // prepare to render our texture +// glEnable(GL_TEXTURE_2D); +// glBindTexture(GL_TEXTURE_2D, texture); +// glColor3f(1.0f, 1.0f, 1.0f); +// +// // Draw a quad at location +// glBegin(GL_QUADS); +// // Recall that the origin is in the lower-left corner +// // That is why the TexCoords specify different corners +// // than the Vertex coors seem to. +// glTexCoord2f(0.0f, 1.0f); +// glVertex2f(location->x , location->y); +// glTexCoord2f(1.0f, 1.0f); +// glVertex2f(location->x + w, location->y); +// glTexCoord2f(1.0f, 0.0f); +// glVertex2f(location->x + w, location->y + h); +// glTexCoord2f(0.0f, 0.0f); +// glVertex2f(location->x , location->y + h); +// glEnd(); +// +// // Bad things happen if we delete the texture before it finishes +// glFinish(); +// +// // return the deltas in the unused w,h part of the rect +// location->w = initial->w; +// location->h = initial->h; +// +// // Clean up +// SDL_FreeSurface(initial); +// SDL_FreeSurface(intermediary); +// glDeleteTextures(1, &texture); +// } diff --git a/src/evenements.c b/src/evenements.c new file mode 100644 index 0000000..d967884 --- /dev/null +++ b/src/evenements.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include + +#include "divers.h" +#include "evenements.h" +#include "vtplayer-ctrl.h" + +#define SLOWDOWN 3.0 + +SDL_mutex * mouse_status_mutex; +#define LOCK SDL_mutexP(mouse_status_mutex) +#define UNLOCK SDL_mutexV(mouse_status_mutex) + +extern int resol_x; +extern int resol_y; +extern int running; +extern int condition; +int startx = -1, starty = -1; +int absstartx = -1, absstarty = -1; +int init = 1; + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +int get_mouse_x() +{ + int r; + LOCK; + r = mouse_status.x; + UNLOCK; + return r; +} + +int get_mouse_y() +{ + int r; + LOCK; + r = mouse_status.y; + UNLOCK; + return r; +} + +int get_vtp_x() +{ + int r; + LOCK; + r = (int)mouse_status.vtpx; + UNLOCK; + return r; +} + +int get_vtp_y() +{ + int r; + LOCK; + r = (int)mouse_status.vtpy; + UNLOCK; + return r; +} + +int get_mouse_b(int i) +{ + int r; + LOCK; + r = mouse_status.b[i]; + UNLOCK; + return r; +} + +int get_mouse_any_button() +{ + int r; + LOCK; + r = mouse_status.b[0] || mouse_status.b[1] || mouse_status.b[2] || mouse_status.b[3]; + UNLOCK; + return r; +} + +/*void set_min_screen_x(int x) { LOCK; mouse_status.min_screen_x = x; UNLOCK; } +void set_min_screen_y(int y) { LOCK; mouse_status.min_screen_y = y; UNLOCK; } +void set_max_screen_x(int x) { LOCK; mouse_status.max_screen_x = x; UNLOCK; } +void set_max_screen_y(int y) { LOCK; mouse_status.max_screen_y = y; UNLOCK; } +*/ + +int mouse_status_thread(void * p) +{ + int temp = 0; + struct + { + char rx, ry, dummy, buttons; + } __attribute__((packed)) evts; + evts.rx = 0; + evts.ry = 0; + evts.dummy = 0; + evts.buttons = 0; + while(running) + { + SDL_Delay(10); + if (temp++ % 100 == 0) + printf("mouse_status_thread still alive %d, x=%f, y=%f\n", temp, mouse_status.vtpx, mouse_status.vtpy); + if (get_status((u8 *) &evts) < 0) + continue; + LOCK; +// if (condition == CONDITION_MV) +// { +// dprintf("vtpx=%d, vtpy=%d, dx=%d, dy=%d\n", mouse_status.vtpx, mouse_status.vtpy, (int)(evts.rx / SLOWDOWN), (int)(evts.rx / SLOWDOWN)); + mouse_status.vtpx += evts.rx / SLOWDOWN; + mouse_status.vtpy += evts.ry / SLOWDOWN; +// } +// else +// { +// mouse_status.vtpx += evts.rx; +// mouse_status.vtpy += evts.ry; +// } + if (mouse_status.vtpx < 0) + mouse_status.vtpx = 0; + if (mouse_status.vtpy < 0) + mouse_status.vtpy = 0; + if (mouse_status.vtpx > resol_x) + mouse_status.vtpx = resol_x; + if (mouse_status.vtpy > resol_y) + mouse_status.vtpy = resol_y; + mouse_status.b[0] = evts.buttons & 1 ? 1 : 0; + mouse_status.b[1] = evts.buttons & 2 ? 1 : 0; + mouse_status.b[2] = evts.buttons & 4 ? 1 : 0; + mouse_status.b[3] = evts.buttons & 8 ? 1 : 0; + UNLOCK; + } + dprintf("Destroying mouse status mutex\n"); + SDL_DestroyMutex(mouse_status_mutex); + dprintf("Mouse status thread quitting\n"); + return 0; +} + +SDL_Thread *create_mouse_status_thread() +{ + SDL_Thread *r; + dprintf("Create the mouse status thread\n"); + memset(&mouse_status, 0, sizeof(mouse_status)); + mouse_status.vtpx = resol_x / 2; + mouse_status.vtpy = resol_y / 2; + if((mouse_status_mutex = SDL_CreateMutex()) == NULL) + { + printf("Error while creating the mutex mutex : %s\n", SDL_GetError()); + return NULL; + } + if ((r = SDL_CreateThread(mouse_status_thread, 0)) == NULL) + { + printf("Error while creating the mouse polling thread: %s\n", SDL_GetError()); + return NULL; + } + return r; +} + +events_t process_events() +{ + SDL_Event event; + SDL_MouseMotionEvent *me; + events_t r; + r.buttons = get_mouse_any_button(); + r.symbol = 0; + + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_KEYDOWN: + r.symbol = event.key.keysym.sym; + return r; + case SDL_MOUSEMOTION: + if ((me = (SDL_MouseMotionEvent *)(&event)) == NULL) + { + fprintf(stderr, "Can't get mouse coordinates\n"); + return r; + } + LOCK; +// if (condition == CONDITION_PV) +// { +/* dprintf("mouse %4d %4d\n", mouse_status.x, mouse_status.y);*/ + mouse_status.x = (me->x / SLOWDOWN) + resol_x * (0.5 - 0.5 / SLOWDOWN); + mouse_status.y = (me->y / SLOWDOWN) + resol_y * (0.5 - 0.5 / SLOWDOWN); +// } +// else +// { +// mouse_status.x = me->x;//me->xrel/2 + startx; +// mouse_status.y = me->y; +// } + UNLOCK; + break; + case SDL_QUIT: + dprintf("Caught Exit\n"); + running = 0; + exit(0); + break; + } + } + return r; +} + +#undef LOCK +#undef UNLOCK diff --git a/src/exemple.c b/src/exemple.c new file mode 100644 index 0000000..b80fcab --- /dev/null +++ b/src/exemple.c @@ -0,0 +1,383 @@ +// xsetwacom set stylus bottomx 12700 ; xsetwacom set stylus bottomy 20300 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "divers.h" +#include "vtplayer-ctrl.h" +#include "icons.h" +#include "evenements.h" +#include "params.h" +#include "display.h" +#include "guidance.h" +#define COLOR_FOND 1.0, 1.0, 1.0 + +extern param_list *list_params; +extern const SDL_VideoInfo *info; +extern SDL_Surface *screen; +extern int *pinsconfig; +extern int currentdirection; +extern int max_screen_x; +extern int min_screen_x; +extern int max_screen_y; +extern int min_screen_y; +extern int resol_x; +extern int resol_y; +extern unsigned char *shapepixels; +int left_handed = 0; +int condition = 0; +FILE *logfile = NULL; +int running = 1; +int maxtime = 180; +int training = 0; + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +int main(int argc, char *argv[]) +{ + //user name and condition + char *name = NULL, *conditionname = NULL, *shape = NULL, *tempstring = NULL; + + if (argc > 1 && read_command_params(argc, argv) > 0) + { + name = get_params("name"); + conditionname = get_params("condition"); + if (conditionname && (strcmp(conditionname, "Pt") == 0)) + condition = CONDITION_PT; + else if (conditionname && (strcmp(conditionname, "Pv") == 0)) + condition = CONDITION_PV; + else if (conditionname && (strcmp(conditionname, "Mt") == 0)) + condition = CONDITION_MT; + else if (conditionname && (strcmp(conditionname, "Mv") == 0)) + condition = CONDITION_MV; + shape = get_params("shape"); + tempstring = get_params("hand"); + if (tempstring && (strcmp(tempstring, "left") == 0)) + left_handed = 1; + tempstring = get_params("training"); + if (tempstring && (strcmp(tempstring, "yes") == 0)) + training = 1; + } + else + { + printf("Usage : shapes -name username -condition Pt|Pv|Mt|Mv -shape shapefile [-hand left]\n"); + display_params(); + return 1; + } + + time_t tim = time(NULL); + struct tm *t = gmtime(&tim); + + if (name) + { + char logfilename[BUFFERSIZE+1]; + snprintf(logfilename, BUFFERSIZE, "%s-%s-%04d-%02d-%02d-%02d-%02d-%02d-%s", name, conditionname, 1900 + t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, shape); + dprintf("Logfile: %s\n",logfilename); + logfile = fopen(logfilename, "w"); + if (logfile) + dprintf("logfile OK\n"); + else + { + dprintf("Error with logfile\n"); + return 1; + } + } + + //read parameters + read_file_params(); + tempstring = get_params("maxtime"); + if (tempstring) + maxtime = atoi(tempstring); + display_params(); + + //initialize everything: SDL, VTPlayer, etc. +#ifndef WITHOUTVTP + dprintf("Loading VTPlayer\n"); + if (init_vtplayer()) + { +#ifdef __linux__ + printf("Impossible to find the VTPlayer! Are you root?\n"); +#else + printf("Impossible to find the VTPlayer! Try to unplug/replug it.\n"); +#endif + return 1; + } +#endif + + atexit(SDL_Quit); + dprintf("Loading SDL\n"); + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + printf("Error while loading SDL: %s\n", SDL_GetError()); + return 1; + } + + dprintf("Loading SDL VideoInfo\n"); + if ((info = SDL_GetVideoInfo()) == NULL) + { + printf("Impossible to get SDL information: %s\n", SDL_GetError()); + return 1; + } + + dprintf("List video modes\n"); + SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); + if (modes == NULL) + { + printf("Impossible to find the screen resolution!\n"); + return 1; + } + else if (modes == (SDL_Rect **)-1) + { + resol_x = 1024; + resol_y = 768; + } + else + { + resol_x = modes[0]->w; + resol_y = modes[0]->h; + } + dprintf("Resolution choosen: %dx%d\n", resol_x, resol_y); + max_screen_x = (int)(500 *((float) resol_x) / ((float) resol_y)); + min_screen_x = - max_screen_x; + max_screen_y = 500; + min_screen_y = - max_screen_y; + + dprintf("Init SDL subsystem\n"); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + { + printf("Couldn't initialise Video SubSystem: %s\n", SDL_GetError()); + return 1; + } + + dprintf("Init GL Attributes\n"); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8); + + int flags = SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN; +// resol_x = 1024; +// resol_y = 768; + dprintf("Set video mode %dx%d %08x\n", resol_x, resol_y, flags); + //this appears to cause the segfault at the end of the program + screen = SDL_SetVideoMode(resol_x, resol_y, 0, flags); + + if (!screen) + { + printf("Impossible de changer le mode video : %s\n", SDL_GetError()); + return 1; + } + +// SDL_LockSurface(screen); + GLdouble ratio = (GLdouble) screen->w / screen->h; + printf("infos : %08x %d %d %d\n", screen->flags, screen->w, screen->h, screen->pitch); + printf("Video resolution: %dx%dx%d (ratio = %3.2f)\n", screen->w, screen->h, screen->format->BitsPerPixel, ratio); +// SDL_UnlockSurface(screen); + + printf("OpenGL infos\n"); + printf("------------\n"); + printf("Vendor : %s\n", glGetString(GL_VENDOR)); + printf("Renderer : %s\n", glGetString(GL_RENDERER)); + printf("Version : %s\n", glGetString(GL_VERSION)); + printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)); + + glClearColor(COLOR_FOND, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dprintf("Setting viewport\n"); + glViewport(0, 0, resol_x, resol_y); + switch(glGetError()) + { + case GL_INVALID_VALUE: + printf("Wrong resolution\n"); + return 1; + case GL_INVALID_OPERATION: + printf("Check the position of the glViewport instruction\n"); + return 1; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + dprintf("Setting projection\n"); + gluOrtho2D(0, resol_x, resol_y, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +// SDL_ShowCursor(SDL_DISABLE); + + dprintf("Load shape\n"); + if (load_shape(shape)) + { + printf("Failed to load the shape '%s'\n", shape); + return 1; + } + + //we store the pixels of the shape vir the visual => tactile transation + glClearColor(1.0, 1.0, 1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dprintf("Draw shape\n"); + draw_shape(); + dprintf("%dx%d : %d pixels\n", resol_x, resol_y, 4 * resol_x * resol_y); + + shapepixels = (unsigned char *) malloc(4 * resol_x * resol_y); + if (!shapepixels) + printf("Impossible to store the pixels\n"); + glReadPixels(0, 0, resol_x, resol_y, GL_RGBA, GL_UNSIGNED_BYTE, shapepixels); +#ifdef DEBUG + SDL_Surface *temp; + if (!(temp = SDL_CreateRGBSurface(SDL_SWSURFACE, resol_x, resol_y, 32, + #if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 + #else + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + #endif + ))) + return 1; + int i; + for (i = 0 ; i < resol_y ; i++) + memcpy(((char *) temp->pixels) + temp->pitch * i, shapepixels + 4 * resol_x * (resol_y - 1 - i), resol_x * 4); + + int nbpixels = 0; + for (i = 0 ; i < 4 * resol_x * resol_y ; i += 4) + if (!shapepixels[i]) + nbpixels++; + printf("\033[31m%d pixels colorés\033[0m, %d total\n", nbpixels, resol_x * resol_y); + + char screenshotstring[BUFFERSIZE]; + sprintf(screenshotstring, "%s.bmp", shape); + dprintf("Save screenshot %s\n", screenshotstring); + SDL_SaveBMP(temp, screenshotstring); + SDL_FreeSurface(temp); +#endif +// for (int i = 0 ; i < resolution[C_Y] ; i++) +// memcpy(((char *) temp->pixels) + temp->pitch * i, pixels + 4 * resolution[C_X] * (resolution[C_Y] - i - 1), resolution[C_X] * 4); + + SDL_Thread *mouse_status_thread = NULL, *tacton_thread = NULL, *pins_thread = NULL, *translation_thread = NULL; + //run the threads + switch (condition) + { + case CONDITION_MT: + if ((mouse_status_thread = create_mouse_status_thread()) == NULL) + { + printf("Impossible tu create the mouse events thread\n"); + return 1; + } + case CONDITION_PT: + dprintf("Conditions T\n"); + if ((tacton_thread = create_tacton_thread()) == NULL) + { + printf("Impossible to create the tactons thread\n"); + return 1; + } + if ((pins_thread = create_pins_thread()) == NULL) + { + printf("Impossible to create the tactile display thread\n"); + return 1; + } + break; + case CONDITION_MV: + if ((mouse_status_thread = create_mouse_status_thread()) == NULL) + { + printf("Impossible tu create the mouse events thread\n"); + return 1; + } + case CONDITION_PV: + dprintf("Conditions V\n"); + if ((translation_thread = create_translation_thread()) == NULL) + { + printf("Impossible to create the tactile display thread\n"); + return 1; + } + break; + } + + struct events_t evt; + while(running) + { + evt = process_events(); + if (evt.symbol == SDLK_ESCAPE) + break; +// currentdirection = (currentdirection + 1) % 9; + draw_screen(); + glFinish(); + SDL_Delay(10); + } + running = 0; + set_pads(0); + + + dprintf("Wait for the Threads\n"); + int status; + if (mouse_status_thread) + { + dprintf("Wait mouse_status_thread\n"); + SDL_WaitThread(mouse_status_thread, &status); + dprintf("Thread mouse_status_thread : %d\n", status); +// SDL_KillThread(mouse_status_thread); + } + if (tacton_thread) + { + dprintf("Wait tacton_thread\n"); + SDL_WaitThread(tacton_thread, &status); + dprintf("Thread tacton_thread : %d\n", status); +// SDL_KillThread(tacton_thread); + } + if (pins_thread) + { + dprintf("Wait pins_thread\n"); + SDL_WaitThread(pins_thread, &status); + dprintf("Thread pins_thread : %d\n", status); +// SDL_KillThread(pins_thread); + } + if (translation_thread) + { + dprintf("Wait translation_thread\n"); + SDL_WaitThread(translation_thread, &status); + dprintf("Thread translation_thread : %d\n", status); +// SDL_KillThread(translation_thread); + } + if (name) + { + dprintf("Closes the logfile\n"); + fclose(logfile); + } + dprintf("Unloads the shape\n"); + unload_shape(); + dprintf("Frees the surface\n"); + if (shapepixels) + free(shapepixels); + dprintf("Deletes the parameters\n"); + delete_params(list_params); + dprintf("Shows the cursor back\n"); +// SDL_ShowCursor(SDL_ENABLE); + dprintf("Freeing the screen\n"); + if (screen) + SDL_FreeSurface(screen); +// dprintf("Quit subsystem\n"); +// SDL_QuitSubSystem(SDL_INIT_EVERYTHING); +// dprintf("Quit SDL\n"); +// SDL_Quit(); + + dprintf("The end\n"); + + return 0; +} diff --git a/src/gettimeofday.c b/src/gettimeofday.c new file mode 100644 index 0000000..6292101 --- /dev/null +++ b/src/gettimeofday.c @@ -0,0 +1,85 @@ +#include + +#include "gettimeofday.h" + +#define FACTOR (0x19db1ded53e8000LL) +#define NSPERSEC 10000000LL + +typedef long long LONGLONG; + +static int inited = 0; +static LARGE_INTEGER primed_pc, primed_ft; +static double freq; +static int justdelta = 0; + +static void prime() { + LARGE_INTEGER ifreq; + if (!QueryPerformanceFrequency (&ifreq)) + { + inited = -1; + return; + } + + FILETIME f; + int priority = GetThreadPriority (GetCurrentThread ()); + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); + if (!QueryPerformanceCounter (&primed_pc)) + { + SetThreadPriority (GetCurrentThread (), priority); + inited = -1; + return; + } + + GetSystemTimeAsFileTime (&f); + SetThreadPriority (GetCurrentThread (), priority); + + inited = 1; + primed_ft.HighPart = f.dwHighDateTime; + primed_ft.LowPart = f.dwLowDateTime; + primed_ft.QuadPart -= FACTOR; + primed_ft.QuadPart /= 10; + freq = (double) ((double) 1000000. / (double) ifreq.QuadPart); + return; +} + +static LONGLONG usec() { + if (!inited) + prime (); + + LARGE_INTEGER now; + if (!QueryPerformanceCounter (&now)) + { + return -1; + } + + // FIXME: Use round() here? + now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart)); + LONGLONG res = justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart; + return res; +} + +int gettimeofday (struct timeval *tv, void *tz) +{ + LONGLONG now = usec(); + if (now == (LONGLONG) -1) + return -1; + + tv->tv_sec = now / 1000000; + tv->tv_usec = now % 1000000; + + return 0; +} + +//retourne des centiemes de secondes +int diff_time (struct timeval *debut, int precision) +{ + struct timeval *fin = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(fin, NULL); + + int sec = fin->tv_sec - debut->tv_sec; + int msec = fin->tv_usec - debut->tv_usec; + + free(fin); + + return (1000000 * sec + msec)/precision; +} diff --git a/src/guidance.c b/src/guidance.c new file mode 100644 index 0000000..f687341 --- /dev/null +++ b/src/guidance.c @@ -0,0 +1,134 @@ +#include "guidance.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "divers.h" +#include "display.h" + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +extern int resol_x; +extern int resol_y; +extern int currentsegment; +extern int condition; + +shape_type shape; + +int load_shape(char *name) +{ + if (!name) + { + printf("No shape specified\n"); + return 1; + } + + FILE *filename; + char buffer[BUFFERSIZE + 1], *namebuffer; + snprintf(buffer, BUFFERSIZE, "%s", name); + if (fileExists(buffer)) + namebuffer = strdup(buffer); + else + { + snprintf(buffer, BUFFERSIZE, "data/%s", name); + if (fileExists(buffer)) + namebuffer = strdup(buffer); + else + { + snprintf(buffer, BUFFERSIZE, "../data/%s", name); + if (fileExists(buffer)) + namebuffer = strdup(buffer); + else + return 1; + } + } + if ((filename = fopen(namebuffer,"r")) == NULL) + return 1; + free(namebuffer); + + + //we read the number of points + if (fgets(buffer, BUFFERSIZE, filename) == NULL) + { + fprintf(stderr, "some Tactons are missing\n"); + shape.nbv = 0; + shape.x = NULL; + shape.y = NULL; + return 1; + } + shape.nbv = atoi(buffer); + if (shape.nbv <= 0) + { + fprintf(stderr, "No frames\n"); + shape.nbv = 0; + shape.x = NULL; + shape.y = NULL; + return 1; + } + + shape.x = (int *) malloc(shape.nbv * sizeof(int)); + shape.y = (int *) malloc(shape.nbv * sizeof(int)); + int i; + for (i = 0 ; i < shape.nbv ; i++) + { + if (fgets(buffer, BUFFERSIZE, filename) == NULL) + { + shape.x[i] = 0; + shape.y[i] = 0; + continue; + } + int x, y; + sscanf(buffer, "%d,%d", &x, &y); + shape.x[i] = get_x_from_opengl(x); + shape.y[i] = get_y_from_opengl(y);// - 1; + dprintf("Shape: %d,%d\n",shape.x[i], shape.y[i]); + } + fclose(filename); + return 0; +} + +void unload_shape() +{ + if (shape.x) + free(shape.x); + if (shape.y) + free(shape.y); +} + +void draw_shape() +{ + if (shape.nbv <= 0) + return; + int i; + + glBegin(GL_LINE_LOOP); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glColor3d(0.0, 0.0, 0.0); + for (i = 0 ; i < shape.nbv ; i++) + { + if (i == currentsegment && (condition == CONDITION_PT || condition == CONDITION_MT)) + glColor3d(1.0, 0.0, 0.0); + else + glColor3d(0.0, 0.0, 0.0); + glVertex2d(shape.x[i], shape.y[i]); + } + glEnd(); +} + +int get_direction(int posx, int posy) +{ + return 1; +} + diff --git a/src/icons.c b/src/icons.c new file mode 100644 index 0000000..ebcd426 --- /dev/null +++ b/src/icons.c @@ -0,0 +1,727 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "icons.h" + +#include "divers.h" +#include "vtplayer-ctrl.h" +#include "params.h" +#include "evenements.h" +#include "guidance.h" + +#ifdef __WIN32 +#include "gettimeofday.h" +#endif + +#define EPSILON 0.0000001 + +#define RESET 0x00000000 + +#define RIGHT_H 0 +#define LEFT_H 1 + +#define LEFT_H 1 + +SDL_mutex * tacton_mutex; +#define LOCK SDL_mutexP(tacton_mutex) +#define UNLOCK SDL_mutexV(tacton_mutex) + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +/// A set is composed of the icons of the 8 directions +typedef struct set_t +{ + u32 *icons[8]; + int nbframes[8]; + int speeds[3]; +}iconset_t; + +iconset_t *set = NULL; + +int currentspeed = 100; +int currentsegment = 0; +unsigned char *shapepixels; +u32 currenttacton; +u32 tacton; +u32 tactonfixed; + +extern param_list **list_params; +extern param_list **list_params; +extern struct mouse_status_t mouse_status; +extern int resol_x; +extern int resol_y; +extern shape_type shape; +extern int condition; +extern int left_handed; +extern FILE *logfile; +extern int running; +extern int maxtime; +extern int training; + +u32 get_tacton() +{ + u32 r; + LOCK; + switch(condition) + { + case CONDITION_MT: + if (left_handed) + r = (tacton >> 16) + (tactonfixed << 16); + else + r = tacton + tactonfixed; + break; + case CONDITION_MV: + if (left_handed) + r = tacton >> 16; + else + r = tacton; + break; + case CONDITION_PT: + if (left_handed) + r = tacton + tactonfixed; + else + r = (tacton >> 16) + (tactonfixed << 16); + break; + case CONDITION_PV: + if (left_handed) + r = tacton; + else + r = tacton >> 16; + break; + } +// r = tacton; + UNLOCK; + return r; +} + +/// Loads a Tacton set from a text file +// format : +// 8 lines for the eight directions +// separator : ';' +// - nb frames : integer +// - the frames : u32 +void load_set() +{ + FILE *f; + int i, j, k, currentnumber = 0; + char buffer[BUFFERSIZE + 1]; + //Left handed + int hand = RIGHT_H; + char *temp; + if ((temp = get_params("hand")) && (strcmp(temp, "left") == 0)) + hand = LEFT_H; + + char buffer2[BUFFERSIZE + 1], *namebuffer; + snprintf(buffer2, BUFFERSIZE, "%s", get_params("tactonsfile")); + if (fileExists(buffer2)) + namebuffer = strdup(buffer2); + else + { + snprintf(buffer2, BUFFERSIZE, "data/%s", get_params("tactonsfile")); + if (fileExists(buffer2)) + namebuffer = strdup(buffer2); + else + { + snprintf(buffer2, BUFFERSIZE, "../data/%s", get_params("tactonsfile")); + if (fileExists(buffer2)) + namebuffer = strdup(buffer2); + else + return; + } + } + if ((f = fopen(namebuffer,"r")) == NULL) + return; + free(namebuffer); + + set = (iconset_t *) malloc(sizeof(iconset_t)); + + for (i = 0 ; i < 8 ; i++) + { + dprintf("reading Tacton %d : ", i); + //we read a line from the buffer + if (fgets(buffer, BUFFERSIZE, f) == NULL) + { + fprintf(stderr, "some Tactons are missing\n"); + free(set); + set = NULL; + return; + } + //we get the first number : the number of frames + j = 0, currentnumber = 0; + while(j < BUFFERSIZE && j < strlen(buffer) && buffer[j] != ';') + { + if ( buffer[j] >= '0' && buffer[j] <= '9' ) + currentnumber = currentnumber * 10 + buffer[j] - '0'; + j++; + } + j++; + set->nbframes[i] = currentnumber; + set->icons[i] = (u32 *) malloc(set->nbframes[i] * sizeof(u32)); + dprintf("%d frames :\n", set->nbframes[i]); + + //we read the frames + for (k = 0 ; k < set->nbframes[i] ; k++) + { + currentnumber = 0; + while(j < BUFFERSIZE && j < strlen(buffer) && buffer[j] != ';') + { + if ( buffer[j] >= '0' && buffer[j] <= '9' ) + currentnumber = currentnumber * 16 + buffer[j] - '0'; + if ( buffer[j] >= 'a' && buffer[j] <= 'f' ) + currentnumber = currentnumber * 16 + buffer[j] - 'a' + 10; + j++; + } + j++; + if (hand == 1) + set->icons[i][k] = currentnumber << 16; + else + set->icons[i][k] = currentnumber; + dprintf("frame %2d : %08lx\n", k, set->icons[i][k]); + } + } + //read speed values from parameters + temp = get_params("speed1"); + if (temp) + set->speeds[0] = atoi(temp); + else + set->speeds[0] = 100; + temp = get_params("speed2"); + if (temp) + set->speeds[1] = atoi(temp); + else + set->speeds[1] = 100; + temp = get_params("speed3"); + if (temp) + set->speeds[2] = atoi(temp); + else + set->speeds[2] = 100; + + dprintf("speed1 = %d, speed2 = %d, speed3 = %d\n", set->speeds[0], set->speeds[1], set->speeds[2]); + + return; +} + +int tacton_thread(void *p) +{ + int temp = 0;//, temp2=0; + struct timeval *now = (struct timeval *) malloc(sizeof(struct timeval)); + struct timeval *start = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(start, NULL); + int status = 1; + while(running) + { + #if 0 +// LOCK; + if (tacton != currenttacton) + { + status = 1; + gettimeofday(start, NULL); + currenttacton = tacton; + set_pads(tacton); +// UNLOCK; + continue; + } +// UNLOCK; +#endif +// printf("current=%ld, target=%ld, diff=%d\n", 1000 * now->tv_sec + now->tv_usec / 1000, currentspeed + 1000 *start->tv_sec + start->tv_usec / 1000, currentspeed); + gettimeofday(now, NULL); + unsigned int sec = now->tv_sec - start->tv_sec; + unsigned int msec = (unsigned int)((now->tv_usec - start->tv_usec) / 1000); + + temp++; +// if (temp % 100 == 0) +// dprintf("tacton_thread still alive %d@%d:%d, tacton=%08lx %d:%d\n", temp, (int)now->tv_sec, (int)now->tv_usec, tacton, sec, msec); + if (1000 * sec + msec > currentspeed) + { +// temp2 = 0; + status = !status; + start->tv_usec += 1000 * currentspeed; + if (start->tv_usec >= 1000000) + { + start->tv_usec -= 1000000; + start->tv_sec++; + } + sec = now->tv_sec - start->tv_sec; + msec = (unsigned int)((now->tv_usec - start->tv_usec) / 1000); + +// gettimeofday(start, NULL); + +// LOCK; + if (status == 1) + set_pads(tacton | tactonfixed); + else + set_pads(tactonfixed); +// UNLOCK; + } +// else +// { +// temp2++; +// if (temp2 > 10) +// dprintf("Too many times ! %d, tacton=%08lx %d:%d=>%d\n", temp2, tacton, sec, msec, 1000 * sec + msec); +// } + + SDL_Delay(10); + } + + if (now) + free(now); + if (start) + free(start); + + dprintf("Tacton thread quitting\n"); + return (0); +} + +SDL_Thread *create_tacton_thread() +{ + SDL_Thread *r; + dprintf("Create the tactons thread\n"); + if ((r = SDL_CreateThread(tacton_thread, NULL)) == NULL) + { + printf("Impossible to run the tactons thread: %s\n", SDL_GetError()); + return NULL; + } + return r; +} + +void display_config_from_angle(double angle, int outside) +{ + angle += M_PI/8; + while (angle < EPSILON) + angle += 2 * M_PI; +// LOCK; + if (angle < M_PI_4 + EPSILON) + tacton = 0x88880000; + else if (angle < M_PI_2 + EPSILON) + tacton = 0x888f0000; + else if (angle < 3*M_PI_4 + EPSILON) + tacton = 0x000f0000; + else if (angle < M_PI + EPSILON) + tacton = 0x111f0000; + else if (angle < 5*M_PI_4 + EPSILON) + tacton = 0x11110000; + else if (angle < 3*M_PI_2 + EPSILON) + tacton = 0xf1110000; + else if (angle < 7*M_PI_4 + EPSILON) + tacton = 0xf0000000; + else //if (angle < 2*M_PI + EPSILON) + tacton = 0xf8880000; + if (((condition == CONDITION_MT) && !left_handed) || (!(condition == CONDITION_MT) && left_handed)) + { + tacton >>= 16; + if (outside) + tactonfixed = 0xffff0000; + else + tactonfixed = 0x00000000; + } + else if (outside) + tactonfixed = 0x0000ffff; + else + tactonfixed = 0x00000000; +// UNLOCK; +// set_pads(tacton); +// dprintf("%08lx %08lx\n", config, config | 0x0000ffff); +} + +int pins_thread(void *p) +{ +// int temp = 0; + dprintf("Guidance start\n"); + if (shape.nbv < 2) + { + printf("Shape too small\n"); + return (1); + } + + //récupération des paramètres. Il serait temps de faire une fonction sympa pour ça... + dprintf("Get parameters\n"); + currentsegment = 0; + char *buffer; + buffer = get_params("distance1"); + int distance1; + if (buffer) + distance1 = atoi(buffer); + else + distance1 = 100; + buffer = get_params("distance2"); + int distance2; + if (buffer) + distance2 = atoi(buffer); + else + distance2 = 100; + buffer = get_params("distance3"); + int distance3; + if (buffer) + distance3 = atoi(buffer); + else + distance3 = 100; + buffer = get_params("stripwidth"); + int stripwidth; + if (buffer) + stripwidth = atoi(buffer); + else + stripwidth = 50; + buffer = get_params("speed1"); + int speed1; + if (buffer) + speed1 = atoi(buffer); + else + speed1 = 50; + buffer = get_params("speed2"); + int speed2; + if (buffer) + speed2 = atoi(buffer); + else + speed2 = 50; + buffer = get_params("speed3"); + int speed3; + if (buffer) + speed3 = atoi(buffer); + else + speed3 = 50; + + dprintf("Set coordinates function\n"); + int (*x)(), (*y)(); + if (condition == CONDITION_PT) + { + x = get_mouse_x; + y = get_mouse_y; + } + else// if (strcmp(get_params("condition"),"Mv") == 0) + { + x = get_vtp_x; + y = get_vtp_y; + } + + dprintf("Compute first segment\n"); + int abx = shape.x[1] - shape.x[0]; + int aby = shape.y[1] - shape.y[0]; + double abl = sqrt(abx * abx + aby * aby); + double segmentangle = acos(abx / abl); + if (aby > -EPSILON) + segmentangle *= -1; + dprintf("abx=%d, aby=%d, abl=%f, segmentangle=%f\n", abx, aby, abl, segmentangle); + dprintf("Run the loop\n"); + + struct timeval *now = (struct timeval *) malloc(sizeof(struct timeval)); + struct timeval *start = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(start, NULL); + + //compute the cartesian equation of the line + double line_a = shape.y[(currentsegment + 1) % shape.nbv] - shape.y[currentsegment]; + double line_b = shape.x[currentsegment] - shape.x[(currentsegment + 1) % shape.nbv]; + double line_c = shape.x[(currentsegment + 1) % shape.nbv] * shape.y[currentsegment] - shape.x[currentsegment] * shape.y[(currentsegment + 1) % shape.nbv]; + + //position relative to the line for the guidance + double outsidepos = line_a * x() + line_b * y() + line_c; + + while(running) + { + gettimeofday(now, NULL); + int sec = now->tv_sec - start->tv_sec; + int msec = (int)((now->tv_usec - start->tv_usec) / 1000); + if (logfile) + fprintf(logfile, "%ld;%d;%d;%08lx;%d\n", 1000 * (long int)sec + msec, x(), resol_y - y() - 1, tacton, currentspeed); +// else +// dprintf("Error with logfile\n"); + //if maxtime is elapsed we exit the test + if (sec > maxtime && !training) + { + dprintf("time : %d/%d\n", sec, maxtime); + running = 0; + break; + } + + int amx = x() - shape.x[currentsegment]; + int amy = y() - shape.y[currentsegment]; + double aml = sqrt(amx * amx + amy * amy); + int bmx = x() - shape.x[(currentsegment + 1) % shape.nbv]; + int bmy = y() - shape.y[(currentsegment + 1) % shape.nbv]; + double bml = sqrt(bmx * bmx + bmy * bmy); + + //distance from the pointer's projection to the target + double between; +// dprintf("abx=%d, aby=%d, abl=%f, amx=%d, amy=%d, aml=%f, bmx=%d, bmy=%d, bml=%f\n", abx, aby, abl, amx, amy, aml, bmx, bmy, bml); + if (aml > bml) + between = abl - (amx * abx + amy * aby) / abl; + else + between = (bmx * (-abx) + bmy * (-aby)) / abl; + + //distance from the cursor to the segment + //we have to add fabs, otherwise sqrt(-0.0) = nan + double dist = sqrt(fabs(bml * bml - between * between)); +// dprintf("dist=%f, between=%f, abl=%f, aml=%f, stripwidth=%d, test=%f\n", dist, between, abl, aml, stripwidth, bml * bml - between * between); + + if (between > 0) + { + //if we are before the first point + if ((between > abl) && (aml > stripwidth)) + { + if (aml < distance1) + currentspeed = speed1; + else if (aml < distance2) + currentspeed = speed2; + else //if (between < distance3) + currentspeed = speed3; + double guideangle = acos((-amx) / aml); + if (amy < 0) + guideangle *= -1; + display_config_from_angle(guideangle, 1); + outsidepos = 0;//line_a * x() + line_b * y() + line_c; + } + else //we are between the two points + { + double newoutsidepos = line_a * x() + line_b * y() + line_c; + //we are in the strip + //we continue to guide if we come back from the outside and we didn't cross the line + if (dist < stripwidth && outsidepos * newoutsidepos <= EPSILON) + { + if (between < distance1) + currentspeed = speed1; + else if (between < distance2) + currentspeed = speed2; + else //if (between < distance3) + currentspeed = speed3; + display_config_from_angle(segmentangle, 0); + outsidepos = 0; + } + else + { + if (dist < distance1) + currentspeed = speed1; + else if (dist < distance2) + currentspeed = speed2; + else //if (dist < distance3) + currentspeed = speed3; + if (abx > 0) + { + if (amy / aml > aby / abl) + display_config_from_angle(segmentangle + M_PI_2, 1); + else + display_config_from_angle(segmentangle - M_PI_2, 1); + } + else if (abx < 0) + { + if (amy / aml > aby / abl) + display_config_from_angle(segmentangle - M_PI_2, 1); + else + display_config_from_angle(segmentangle + M_PI_2, 1); + } + else // abx == 0 + { + if (aby > 0) + { + if (amx > 0) + display_config_from_angle(segmentangle - M_PI_2, 1); + else + display_config_from_angle(segmentangle + M_PI_2, 1); + } + else if (aby < 0) + { + if (amx > 0) + display_config_from_angle(segmentangle + M_PI_2, 1); + else + display_config_from_angle(segmentangle - M_PI_2, 1); + } + else // aby == 0 // should not happen + { + printf("Vector too short!\n"); + display_config_from_angle(segmentangle, 1); + } + } + outsidepos = line_a * x() + line_b * y() + line_c; + } + } + } + else //we are too far => guide to the target + { + // if we are at the target + if (bml < stripwidth) + { + currentsegment++; + dprintf("Point %d/%d\n", currentsegment, shape.nbv); + //if we dit a complete lap + if (currentsegment >= shape.nbv) + { + dprintf("New lap\n"); + currentsegment = 0; + } + abx = shape.x[(currentsegment + 1) % shape.nbv] - shape.x[currentsegment]; + aby = shape.y[(currentsegment + 1) % shape.nbv] - shape.y[currentsegment]; + abl = sqrt(abx * abx + aby * aby); + line_a = shape.y[(currentsegment + 1) % shape.nbv] - shape.y[currentsegment]; + line_b = shape.x[currentsegment] - shape.x[(currentsegment + 1) % shape.nbv]; + line_c = shape.x[(currentsegment + 1) % shape.nbv] * shape.y[currentsegment] - shape.x[currentsegment] * shape.y[(currentsegment + 1) % shape.nbv]; + + segmentangle = acos(abx / abl); + if (aby > -EPSILON) + segmentangle *= -1; + // dprintf("abx=%d, aby=%d, abl=%f, segmentangle=%f\n", abx, aby, abl, segmentangle); + display_config_from_angle(segmentangle, 0); +// SDL_Delay(10); +// continue; + } + else + { + if (bml < distance1) + currentspeed = speed1; + else if (bml < distance2) + currentspeed = speed2; + else //if (between < distance3) + currentspeed = speed3; + double guideangle = acos((-bmx) / bml); + if (bmy < 0) + guideangle *= -1; + display_config_from_angle(guideangle, 1); + } +/* double guideangle = acos(bmx / bml); + if (bmy > 0) + guideangle *= -1; + guideangle += segmentangle - M_PI; + display_config_from_angle(guideangle, 1);*/ + } +// temp++; +// if (temp % 100 == 0) +// dprintf("pins_thread still alive %d, tacton=%08lx %d:%d\n", temp, tacton, sec, msec); + + SDL_Delay(10); + } + dprintf("Destroying Tacton Mutex\n"); + SDL_DestroyMutex(tacton_mutex); + dprintf("Pins thread quitting\n"); + return (0); +} + +SDL_Thread *create_pins_thread() +{ + SDL_Thread *r; + //load theTactons set +// printf("Load the tactons\n"); +// load_set(get_params("tactonsfile")); + dprintf("Create the tacton mutex\n"); + if((tacton_mutex = SDL_CreateMutex()) == NULL) + { + printf("Error while creating the mutex : %s\n", SDL_GetError()); + return NULL; + } + dprintf("Create the pins thread\n"); + if ((r = SDL_CreateThread(pins_thread, NULL)) == NULL) + { + printf("Impossible to run the pins thread: %s\n", SDL_GetError()); + return NULL; + } + return r; +} + +u32 getpixel(int x, int y) +{ + if (x < 0) + x = 0; + if (x >= resol_x) + x = resol_x - 1; + if (y < 0) + y = 0; + if (y >= resol_y) + y = resol_y - 1; + int pixel = 4 * (x + (resol_y - y - 1) * resol_x); + + if (shapepixels[pixel]) + return 0x00000000; + else + return 0xffffffff; +} + +int translation_thread(void *p) +{ +// int temp = 0; + int (*x)(), (*y)(); + if (condition == CONDITION_PV) + { + x = get_mouse_x; + y = get_mouse_y; + } + else// if (strcmp(get_params("condition"),"Mv") == 0) + { + x = get_vtp_x; + y = get_vtp_y; + } + + struct timeval *now = (struct timeval *) malloc(sizeof(struct timeval)); + struct timeval *start = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(start, NULL); + while (running) + { + gettimeofday(now, NULL); + int sec = now->tv_sec - start->tv_sec; + int msec = (now->tv_usec - start->tv_usec) / 1000; + if (logfile) + fprintf(logfile, "%ld;%d;%d;%08lx\n", 1000 * (long int)sec + msec, x(), resol_y - y() - 1, tacton); +// else +// dprintf("Error with logfile\n"); + //if maxtime is elapsed we exit the test + if (sec > maxtime && !training) + { + dprintf("time : %d/%d\n", sec, maxtime); + running = 0; + break; + } + +// printf("%d %d\n", x(), y()); +// LOCK; + tacton = + (0x80000000 & getpixel(x() + 2, y() + 2)) + \ + (0x40000000 & getpixel(x() + 1, y() + 2)) + \ + (0x20000000 & getpixel(x(), y() + 2)) + \ + (0x10000000 & getpixel(x() - 1, y() + 2)) + \ + (0x08000000 & getpixel(x() + 2, y() + 1)) + \ + (0x04000000 & getpixel(x() + 1, y() + 1)) + \ + (0x02000000 & getpixel(x(), y() + 1)) + \ + (0x01000000 & getpixel(x() - 1, y() + 1)) + \ + (0x00800000 & getpixel(x() + 2, y())) + \ + (0x00400000 & getpixel(x() + 1, y())) + \ + (0x00200000 & getpixel(x(), y())) + \ + (0x00100000 & getpixel(x() - 1, y())) + \ + (0x00080000 & getpixel(x() + 2, y() - 1)) + \ + (0x00040000 & getpixel(x() + 1, y() - 1)) + \ + (0x00020000 & getpixel(x(), y() - 1)) + \ + (0x00010000 & getpixel(x() - 1, y() - 1)); + if (((condition == CONDITION_MV) && !left_handed) || (!(condition == CONDITION_MV) && left_handed)) + tacton >>= 16; + set_pads(tacton); +// UNLOCK; + SDL_Delay(30); + } + if (now) + free(now); + if (start) + free(start); + dprintf("Translation thread quitting\n"); + return(0); +} + +SDL_Thread *create_translation_thread() +{ + SDL_Thread *r; + //load theTactons set + dprintf("Create the conversion thread\n"); + if ((r = SDL_CreateThread(translation_thread, NULL)) == NULL) + { + printf("Impossible to run the translation thread: %s\n", SDL_GetError()); + return NULL; + } + return r; +} + +#undef LOCK +#undef UNLOCK diff --git a/src/instructions.c b/src/instructions.c new file mode 100644 index 0000000..b4b022b --- /dev/null +++ b/src/instructions.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define COLOR_FOND 0.2, 0.2, 0.2 +#include "instructions.h" +#include "vtplayer-ctrl.h" +#include "divers.h" +#include "evenements.h" +#include "icons.h" + +#ifndef __DEMO__ +#include "ecrire.h" +#endif + +Text *ttt[8]; + +void draw_screen_ins(int min_ecran_x, int min_ecran_y, int max_ecran_x, int max_ecran_y, TTF_Font *font, int mousex, int mousey) +{ + glClearColor(COLOR_FOND, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +#ifndef __DEMO__ +// #if 0 + SDL_Rect position; + position.x = - 600; + position.y = 450; + // Règle ******************************************************************************** + drawText(*(ttt[0]), &position); + position.y -= 20; + drawText(*(ttt[1]), &position); + position.y -= 20; + drawText(*(ttt[2]), &position); + position.y -= 20; + drawText(*(ttt[3]), &position); + position.y -= 20; + drawText(*(ttt[4]), &position); + position.y -= 20; + drawText(*(ttt[5]), &position); + position.y -= 20; + drawText(*(ttt[6]), &position); + + position.y = - 400; + position.x = - 410; + drawText(*(ttt[7]), &position); +#else + // beuark +// #ifdef __WIN32 +// Sleep(5); +// #else +// usleep(5000); +// #endif + SDL_Delay(5); +#endif + + draw_cubes(); + + //curseur VTPLAYER + draw_cursor(mousex, mousey); +// SDL_Delay(5); + + SDL_GL_SwapBuffers(); +} + +void instructions(TTF_Font *font, int *pinsconfig, int min_ecran_x, int min_ecran_y, int max_ecran_x, int max_ecran_y ) +{ + int mx; + int my; + struct events_t evt; + int pins = -1; + int i; + for (i = 0 ; i < 8 ; i++) + ttt[i] = NULL; + SDL_Color color; + color.r = 255; + color.g = 255; + color.b = 255; + ttt[0] = SDL_GL_RenderText("Vous allez sentir des icones par les cellules braille. Elles représentent 8", font, color); + ttt[1] = SDL_GL_RenderText("directions : haut, bas, droite, gauche, en haut à gauche, en bas à gauche, en", font, color); + ttt[2] = SDL_GL_RenderText("haut à droite et en bas à droite. ", font, color); + ttt[3] = SDL_GL_RenderText("A chaque étape vous sentirez une seule icône : vous devez cliquer dans la zone", font, color); + ttt[4] = SDL_GL_RenderText("correspondant à la direction que vous avez senti. Cela arrêtera l'icône. Pour", font, color); + ttt[5] = SDL_GL_RenderText("déclencher la suivante vous devez revenir dans la zone centrale.", font, color); + ttt[6] = SDL_GL_RenderText("Vous pouvez découvrir les icones dans les cases du carré ci-dessous.", font, color); + ttt[7] = SDL_GL_RenderText("Pressez sur Enter pour commencer quand vous serez prêt.", font, color); + + while(1) + { + evt = process_events(); + mx = get_mouse_x(); + my = get_mouse_y(); + + //exemple + if ((pins = dans_cube(mx, my)) == CENTRE) + *pinsconfig = NULLE_PART; + else + *pinsconfig = pins; + + if (evt.symbol == SDLK_RETURN) + break; + else if (evt.symbol == SDLK_ESCAPE) + exit(1); + +// SDL_Delay(50); + draw_screen_ins(min_ecran_x, min_ecran_y, max_ecran_x, max_ecran_y, font, mx, my); +// SDL_Delay(70); + glFinish(); + } + *pinsconfig = NULLE_PART; + for (i = 0 ; i < 8 ; i++) + freeText(ttt[i]); +} diff --git a/src/params.c b/src/params.c new file mode 100644 index 0000000..e90eb28 --- /dev/null +++ b/src/params.c @@ -0,0 +1,125 @@ +#include "params.h" + +#include +#include +#include + +#include "divers.h" +param_list *list_params = NULL; + +int is_caracter(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');// || c == 'é' || c == 'è' || c == 'ç' || c == 'à' || c == 'â' || c == 'ê' || c == 'î' || c == 'ô' || c == 'û' ||c == 'ä' || c == 'ë' || c == 'ï' || c == 'ö' || c == 'ü'; +} + +void read_file_params()//, int *nbtests, int *gridsize, int *precision) +{ + FILE *fp; + int i; + char buffer[BUFFERSIZE + 1], name[BUFFERSIZE + 1], value[BUFFERSIZE + 1]; + + char *namebuffer; + if (fileExists("params")) + namebuffer = "params"; + else if (fileExists("data/params")) + namebuffer = "data/params"; + else if (fileExists("../data/params")) + namebuffer = "../data/params"; + else + { + printf("Could not find the parameters file\n"); + return; + } + + if ((fp = fopen(namebuffer, "r")) == NULL) + { + printf("Impossible to read the parameters, using defaults\n"); + return; + } + while(fgets(buffer, BUFFERSIZE, fp) != NULL) + { + if (buffer[0] == '#') + continue; + memset(name, 0, BUFFERSIZE + 1); + memset(value, 0, BUFFERSIZE + 1); + i = 0; + while(buffer[i] != '=' && i < strlen(buffer)) + { + if (is_caracter(buffer[i])) + name[strlen(name)] = buffer[i]; + i++; + } + i++; + while(i < strlen(buffer)) + { + if (is_caracter(buffer[i])) + value[strlen(value)] = buffer[i]; + i++; + } + add_param(name, value); + } + fclose (fp); +} + +int read_command_params(int argc, char *argv[]) +{ + int i, nb=0; + char *name = NULL; + for (i = 1 ; i < argc ; i++) + { + if (argv[i][0] == '-') + name = argv[i] + 1; + else if (name != NULL) + { + add_param(name, argv[i]); + name = NULL; + nb++; + } + else + return -1; + } + return nb; +} + +void add_param(char *name, char *value) +{ + param_list *new = (param_list *) malloc(sizeof(param_list)); + new->name = strdup(name); + new->value = strdup(value); + new->next = list_params; + list_params = new; +} + +//get one of the parameters value +char *get_params(char *name) +{ + param_list *temp = list_params; + while(temp) + { + if (strcmp(temp->name, name) == 0) + return temp->value; + temp = temp->next; + } + return NULL; +} + +void display_params() +{ + param_list *temp = list_params; + while(temp) + { + printf("%s = %s\n", temp->name, temp->value); + temp = temp->next; + } +} + +void delete_params(param_list *l) +{ + if (l) + { + delete_params(l->next); + free(l->name); + free(l->value); + free(l); + } +} diff --git a/src/saveshapes.c b/src/saveshapes.c new file mode 100644 index 0000000..ca1f815 --- /dev/null +++ b/src/saveshapes.c @@ -0,0 +1,515 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ecrire.h" +#include "saisienom.h" +#include "instructions.h" +#include "vtplayer-ctrl.h" +#include "divers.h" +#include "fini.h" +#include "evenements.h" +#include "icons.h" + +#ifdef __WIN32 +#include "gettimeofday.h" +#endif + +#define TAILLE_PROGRESSIONBAR 500 + +#define COLOR_FOND 0.8, 0.8, 0.8 + +//default values for these parameters +#define NBTESTS 100 +#define TAILLE_GRILLE 10 +//1000000 = s +//1000 = ms +//1 = s +#define PRECISION_TIME 1000 +#define ANIMATION_SPEED 100 + +SDL_Surface *Screen, *text; +char fontpath[] = "../data/FreeMono.ttf"; +char fontpath2[] = "../data/police.ttf"; +char paramsfile[] = "../data/params"; + +struct params_type +{ + int nbparams; + char **names; + int **values; +} params_vals; + +Text *t1; +Text *t2; +int lastnb; + +void draw_progressionbar(TTF_Font *font, int current, int total, int px, int py, int tx, int ty) +{ + int largeurprogression = (current * tx) / total; + glColor3d(0.0, 0.8, 0.0); + glDisable(GL_BLEND); + glBegin(GL_POLYGON); + glVertex2d(px - tx / 2, py + ty); + glVertex2d(px + largeurprogression - tx / 2, py + ty); + glVertex2d(px + largeurprogression - tx / 2, py); + glVertex2d(px - tx / 2, py); + glEnd(); + glColor3d(0.0, 0.0, 0.0); + glBegin(GL_POLYGON); + glVertex2d(px + largeurprogression - tx / 2, py + ty); + glVertex2d(px + tx / 2, py + ty); + glVertex2d(px + tx / 2, py); + glVertex2d(px + largeurprogression - tx / 2, py); + glEnd(); + glEnable(GL_BLEND); + + SDL_Rect position; + position.x = - 85; + position.y = py + 50; + SDL_Color color; + color.r = 255; + color.g = 0; + color.b = 0; + char buffer[BUFFERSIZE]; + sprintf(buffer,"%d / %d", current, total); + if (t2 == NULL) + t2 = SDL_GL_RenderText(buffer, font, color); + else if (current > lastnb) + { + freeText(t2); + t2 = SDL_GL_RenderText(buffer, font, color); + } + drawText(*t2, &position); +/* freeText(tt);*/ +} + +void draw_screen(TTF_Font *font, int mousex, int mousey, int current, int total) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + draw_cubes(); + + SDL_Color color; + color.r = 50; + color.g = 50; + color.b = 255; + SDL_Rect position; + position.x = - 100; + position.y = 400; + + drawText(*t1, &position); + + draw_progressionbar(font, current, total, 0, -400, TAILLE_PROGRESSIONBAR, 50); + + //curseur VTPLAYER + draw_cursor(mousex, mousey); + + SDL_GL_SwapBuffers(); +} + +SDL_Surface * setup_opengl( int width, int height, int min_screen_x, int min_screen_y, int max_screen_x, int max_screen_y) +{ + SDL_Surface * screen; + + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + { + printf("Couldn't initialise Video SubSystem: %s\n", SDL_GetError()); + return NULL; + } + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); + + int flags = SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN; + if (!(screen = SDL_SetVideoMode(width, height, 0, flags))) + { + printf("Impossible de changer le mode video : %s\n", SDL_GetError()); + return NULL; + } + + GLdouble ratio = (GLdouble) screen->w / screen->h; + + printf("infos : %d %d %d %d\n", screen->flags, screen->w, screen->h, screen->pitch); + printf("Video resolution: %dx%dx%d (ratio = %3.2f)\n", screen->w, screen->h, screen->format->BitsPerPixel, ratio); + printf("OpenGL infos\n"); + printf("------------\n"); + printf("Vendor : %s\n", glGetString(GL_VENDOR)); + printf("Renderer : %s\n", glGetString(GL_RENDERER)); + printf("Version : %s\n", glGetString(GL_VERSION)); + printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)); + + glClearColor(COLOR_FOND, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(min_screen_x, max_screen_x, min_screen_y, max_screen_y);//-ratio, ratio, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +// glBlendFunc(GL_ONE, GL_ONE);//GL_ONE_MINUS_DST_COLOR, GL_ONE);//GL_ONE, GL_ONE); +// glEnable(GL_BLEND); + + return screen; +} + +void read_params(char *fichier)//, int *nbtests, int *gridsize, int *precision) +{ + FILE *fp; + int value = 0, i; + char buffer[BUFFERSIZE + 1], name[BUFFERSIZE + 1]; + + if ((fp = fopen(fichier, "r")) == NULL) + { + printf("Impossible to read the parameters, using defaults\n"); + return; + } + while(fgets(buffer, BUFFERSIZE, fp) != NULL) + { + if (buffer[0] == '#') + continue; + memset(name, 0, BUFFERSIZE+1); + value = 0; + i = 0; + while(buffer[i] != '=' && i < strlen(buffer)) + { +#ifdef __DEBUG__ + printf("%c", buffer[i]); +#endif + if (buffer[i] >= 'a' && buffer[i] <= 'z') + name[strlen(name)] = buffer[i]; + i++; + } +#ifdef __DEBUG__ + printf("%c", buffer[i]); +#endif + i++; +#ifdef __DEBUG__ + printf("%c", buffer[i]); +#endif + while(i < strlen(buffer)) + { +#ifdef __DEBUG__ + printf("%c", buffer[i]); +#endif + if (buffer[i] >= '0' && buffer[i] <= '9') + value = value * 10 + buffer[i] - '0'; + i++; + } + + for (i = 0 ; i < params_vals.nbparams ; i++) + { + if (strcmp(name, params_vals.names[i]) == 0) + { +#ifdef __DEBUG__ + printf("=> %s = %d\n", name, value); +#endif + *(params_vals.values[i]) = value; + } + } + } + fclose (fp); +} + +//retourne des centiemes de secondes +int diff_time (struct timeval *debut, int precision) +{ + struct timeval *fin = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(fin, NULL); + + int sec = fin->tv_sec - debut->tv_sec; + int msec = fin->tv_usec - debut->tv_usec; + + free(fin); + +/* if (msec < 0) + return (1000 * (sec - 1) + msec)/(PRECISION_TIME*PRECISION_TIME) + PRECISION_TIME; + else*/ + return (1000000 * sec + msec)/precision; +} + +int main (int argc, char *argv[]) +{ +#ifndef __DEMO__ + FILE *fp = NULL, *fpserie = NULL; + char *nom = NULL, *logfile = NULL; +#endif + const SDL_VideoInfo* info = NULL; + TTF_Font *font, *fontsmall, *fontcursive; + int numset = -1, nbtests = NBTESTS, gridsize = TAILLE_GRILLE, precision = PRECISION_TIME, animationspeed = ANIMATION_SPEED; + char gaucher; + + if (argc > 1) + { + sscanf(argv[1], "%d", &numset); + if (argc > 2) + sscanf(argv[2], "%c", &gaucher); + } + else + { + printf("Usage : shapes [iconsnumber] [g]\n"); + return 1; + } + + params_vals.nbparams = 4; + params_vals.names = (char **) malloc(4 * sizeof(char *)); + params_vals.values = (int **) malloc(4 * sizeof(int *)); + params_vals.names[0] = strdup("nbtests"); + params_vals.values[0] = &nbtests; + params_vals.names[1] = strdup("gridsize"); + params_vals.values[1] = &gridsize; + params_vals.names[2] = strdup("precisiontime"); + params_vals.values[2] = &precision; + params_vals.names[3] = strdup("animationspeed"); + params_vals.values[3] = &animationspeed; + read_params(paramsfile); + + atexit(SDL_Quit); + + if( SDL_Init(SDL_INIT_VIDEO) <0 ) + { + printf("Error while loading SDL: %s\n", SDL_GetError()); + return 1; + } + info = SDL_GetVideoInfo(); + if(!info) + { + printf("Impossible to get SDL information: %s\n", SDL_GetError()); + return 1; + } + if(TTF_Init()) + { + printf("Erreur while loading TTF: %s\n", TTF_GetError()); + return 1; + } + if(!(font = TTF_OpenFont(fontpath, 50))) + { + printf("Erreur while loading the font: %s\n", TTF_GetError()); + return 1; + } + if(!(fontcursive = TTF_OpenFont(fontpath2, 50))) + { + printf("Erreur while loading the font: %s\n", TTF_GetError()); + return 1; + } + if(!(fontsmall = TTF_OpenFont(fontpath, 25))) + { + printf("Erreur while loading the font: %s\n", TTF_GetError()); + return 1; + } + if (init_vtplayer()) + { +#ifdef __linux__ + printf("Impossible to find the VTPlayer! Are you root?\n"); +#else + printf("Impossible to find the VTPlayer! Try to unplug/replug it.\n"); +#endif + return 1; + } + + int * pinsconfig; + pinsconfig = (int *) malloc(sizeof(int)); + *pinsconfig = -1; + if (create_pins_thread(pinsconfig, numset, animationspeed, gaucher)) + { + printf("Impossible to create the tactile display thread\n"); + return 1; + } + + if (create_mouse_status_thread()) + { + printf("Impossible tu create the mouse events thread\n"); + return 1; + } + + int width, height; + SDL_Rect **modes; + modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE); + if (modes == NULL) + { + printf("Impossible to find the screen resolution!\n"); + return 1; + } + else if (modes == (SDL_Rect **)-1) + { + width = 1024; + height = 768; + } + else + { + width = modes[0]->w; + height = modes[0]->h; + } + + int max_screen_x = (int)(500 *((float) width) / ((float) height)); + int min_screen_x = - max_screen_x; + int max_screen_y = 500; + int min_screen_y = - max_screen_y; + + set_max_screen_x(max_screen_x); + set_max_screen_y(max_screen_y); + set_min_screen_x(min_screen_x); + set_min_screen_y(min_screen_y); + +// SDL_Surface *screen = + setup_opengl(width, height, min_screen_x, min_screen_y, max_screen_x, max_screen_y); + + load_cursor("../data/cursor.png"); + +#ifndef __DEMO__ + //on lit le nom de l'utilisateur + //en verifiant que ce nom n'est pas deja utilise + do + { + if (nom != NULL) + free (nom); + if (logfile != NULL) + free (logfile); + nom = nomuser(min_screen_x, min_screen_y, max_screen_x, max_screen_y, font, fontcursive); + if ( fp != NULL ) + fclose(fp); + if (strlen(nom) > 0) + { + logfile = logfilename(nom, numset); + fp = fopen (logfile, "r"); + } + } + while ( strlen(nom) == 0 || fp != NULL ); + + //logfile = logfilename(nom, numset); + if (logfile == NULL || (fp = fopen (logfile, "w")) == NULL) + { + printf("Impossible to create the log file: %s\n", logfile); + return 1; + } + + int grille_x = 0; + int grille_y = 0; + int mx, my; +#endif + + //affichage des instructions + instructions(fontsmall, pinsconfig, min_screen_x, min_screen_y, max_screen_x, max_screen_y); +#ifndef __DEMO__ + + SDL_Color color; + color.r = 255; + color.g = 0; + color.b = 0; + t1 = SDL_GL_RenderText("Tests !", font, color); + t2 = NULL; + lastnb = -1; + + //on dessine le nouvel ecran + glClearColor(COLOR_FOND, 1.0); + draw_screen (font, 0, 0, 0, nbtests); + + //on lit la serie + char *seriefile = (char *) malloc((6 + (int)log10(numset) + 10) * sizeof(char)); + sprintf(seriefile, "icons%d/serie%03d", numset, nbtests); + logfilename("serie", numset); + if ((fpserie = fopen (seriefile, "r")) == NULL) + generer_serie(seriefile, nbtests); + else if (!serie_ok(fpserie, nbtests)) + { + fclose(fpserie); + generer_serie(seriefile, nbtests); + } + if ((fpserie = fopen (seriefile, "r")) == NULL) + { + printf("Impossible de lire la nouvelle serie\n"); + return 1; + } + + char tampon[16]; + struct events_t evt; + struct timeval *depart = (struct timeval *) malloc(sizeof(struct timeval)); + gettimeofday(depart, NULL); + int current = 0; + + while (fgets (tampon, sizeof tampon, fpserie) != NULL) + { + //on lit le caractere a afficher" + if (sscanf(tampon,"%d", pinsconfig) != 1) + *pinsconfig = NULLE_PART; + + //traite tout le bouzin tant que l'utilisateur n'a pas clique + while(1) + { + evt = process_events(); + if (evt.buttons) + break; + if (evt.symbol == SDLK_ESCAPE) + { + fclose(fp); + exit(1); + } + + //si la souris est dans une autre case de la grille on loggue + mx = get_mouse_x(); + my = get_mouse_y(); + if (mx / gridsize != grille_x || my / gridsize != grille_y) + { + grille_x = mx / gridsize; + grille_y = my / gridsize; + fprintf(fp, "%4d ; %4d ; %4d ; %4d\n", diff_time(depart, precision), grille_x, grille_y, dans_cube(mx, my)); + } + draw_screen(font, get_mouse_x(), get_mouse_y(), current, nbtests); + glFinish(); + SDL_Delay(10); + } + fprintf(fp, "%4d ; %4d ; %4d ; %4d ; %4d\n", diff_time(depart, precision), grille_x, grille_y, dans_cube(mx, my), *pinsconfig); + //il a clique : on coupe l'icone + *pinsconfig = NULLE_PART; + //on attend que le bouton soit relache et que l'utilisateur revienne au centre + while(1) + { + evt = process_events(); + mx = get_mouse_x(); + my = get_mouse_y(); + if (!evt.buttons && dans_cube(mx, my) == CENTRE) + break; + if (evt.symbol == SDLK_ESCAPE) + { + fclose(fp); + exit(1); + } + + //si la souris est dans une autre case de la grille on loggue + if (mx / gridsize != grille_x || my / gridsize != grille_y) + { + grille_x = mx / gridsize; + grille_y = my / gridsize; + fprintf(fp, "%4d ; %4d ; %4d ; %4d\n", diff_time(depart, precision), grille_x, grille_y, dans_cube(mx, my)); + } + draw_screen(font, mx, my, current, nbtests); + glFinish(); + SDL_Delay(10); + } + current++; + } + fclose(fp); + freeText(t1); + freeText(t2); + + fini(fontcursive, logfile, min_screen_x, min_screen_y, max_screen_x, max_screen_y); +#endif + return 0; +} diff --git a/src/shapes.c b/src/shapes.c new file mode 100644 index 0000000..b80fcab --- /dev/null +++ b/src/shapes.c @@ -0,0 +1,383 @@ +// xsetwacom set stylus bottomx 12700 ; xsetwacom set stylus bottomy 20300 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "divers.h" +#include "vtplayer-ctrl.h" +#include "icons.h" +#include "evenements.h" +#include "params.h" +#include "display.h" +#include "guidance.h" +#define COLOR_FOND 1.0, 1.0, 1.0 + +extern param_list *list_params; +extern const SDL_VideoInfo *info; +extern SDL_Surface *screen; +extern int *pinsconfig; +extern int currentdirection; +extern int max_screen_x; +extern int min_screen_x; +extern int max_screen_y; +extern int min_screen_y; +extern int resol_x; +extern int resol_y; +extern unsigned char *shapepixels; +int left_handed = 0; +int condition = 0; +FILE *logfile = NULL; +int running = 1; +int maxtime = 180; +int training = 0; + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +int main(int argc, char *argv[]) +{ + //user name and condition + char *name = NULL, *conditionname = NULL, *shape = NULL, *tempstring = NULL; + + if (argc > 1 && read_command_params(argc, argv) > 0) + { + name = get_params("name"); + conditionname = get_params("condition"); + if (conditionname && (strcmp(conditionname, "Pt") == 0)) + condition = CONDITION_PT; + else if (conditionname && (strcmp(conditionname, "Pv") == 0)) + condition = CONDITION_PV; + else if (conditionname && (strcmp(conditionname, "Mt") == 0)) + condition = CONDITION_MT; + else if (conditionname && (strcmp(conditionname, "Mv") == 0)) + condition = CONDITION_MV; + shape = get_params("shape"); + tempstring = get_params("hand"); + if (tempstring && (strcmp(tempstring, "left") == 0)) + left_handed = 1; + tempstring = get_params("training"); + if (tempstring && (strcmp(tempstring, "yes") == 0)) + training = 1; + } + else + { + printf("Usage : shapes -name username -condition Pt|Pv|Mt|Mv -shape shapefile [-hand left]\n"); + display_params(); + return 1; + } + + time_t tim = time(NULL); + struct tm *t = gmtime(&tim); + + if (name) + { + char logfilename[BUFFERSIZE+1]; + snprintf(logfilename, BUFFERSIZE, "%s-%s-%04d-%02d-%02d-%02d-%02d-%02d-%s", name, conditionname, 1900 + t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, shape); + dprintf("Logfile: %s\n",logfilename); + logfile = fopen(logfilename, "w"); + if (logfile) + dprintf("logfile OK\n"); + else + { + dprintf("Error with logfile\n"); + return 1; + } + } + + //read parameters + read_file_params(); + tempstring = get_params("maxtime"); + if (tempstring) + maxtime = atoi(tempstring); + display_params(); + + //initialize everything: SDL, VTPlayer, etc. +#ifndef WITHOUTVTP + dprintf("Loading VTPlayer\n"); + if (init_vtplayer()) + { +#ifdef __linux__ + printf("Impossible to find the VTPlayer! Are you root?\n"); +#else + printf("Impossible to find the VTPlayer! Try to unplug/replug it.\n"); +#endif + return 1; + } +#endif + + atexit(SDL_Quit); + dprintf("Loading SDL\n"); + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) + { + printf("Error while loading SDL: %s\n", SDL_GetError()); + return 1; + } + + dprintf("Loading SDL VideoInfo\n"); + if ((info = SDL_GetVideoInfo()) == NULL) + { + printf("Impossible to get SDL information: %s\n", SDL_GetError()); + return 1; + } + + dprintf("List video modes\n"); + SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); + if (modes == NULL) + { + printf("Impossible to find the screen resolution!\n"); + return 1; + } + else if (modes == (SDL_Rect **)-1) + { + resol_x = 1024; + resol_y = 768; + } + else + { + resol_x = modes[0]->w; + resol_y = modes[0]->h; + } + dprintf("Resolution choosen: %dx%d\n", resol_x, resol_y); + max_screen_x = (int)(500 *((float) resol_x) / ((float) resol_y)); + min_screen_x = - max_screen_x; + max_screen_y = 500; + min_screen_y = - max_screen_y; + + dprintf("Init SDL subsystem\n"); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) + { + printf("Couldn't initialise Video SubSystem: %s\n", SDL_GetError()); + return 1; + } + + dprintf("Init GL Attributes\n"); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8); + + int flags = SDL_OPENGL | SDL_HWSURFACE | SDL_FULLSCREEN; +// resol_x = 1024; +// resol_y = 768; + dprintf("Set video mode %dx%d %08x\n", resol_x, resol_y, flags); + //this appears to cause the segfault at the end of the program + screen = SDL_SetVideoMode(resol_x, resol_y, 0, flags); + + if (!screen) + { + printf("Impossible de changer le mode video : %s\n", SDL_GetError()); + return 1; + } + +// SDL_LockSurface(screen); + GLdouble ratio = (GLdouble) screen->w / screen->h; + printf("infos : %08x %d %d %d\n", screen->flags, screen->w, screen->h, screen->pitch); + printf("Video resolution: %dx%dx%d (ratio = %3.2f)\n", screen->w, screen->h, screen->format->BitsPerPixel, ratio); +// SDL_UnlockSurface(screen); + + printf("OpenGL infos\n"); + printf("------------\n"); + printf("Vendor : %s\n", glGetString(GL_VENDOR)); + printf("Renderer : %s\n", glGetString(GL_RENDERER)); + printf("Version : %s\n", glGetString(GL_VERSION)); + printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)); + + glClearColor(COLOR_FOND, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dprintf("Setting viewport\n"); + glViewport(0, 0, resol_x, resol_y); + switch(glGetError()) + { + case GL_INVALID_VALUE: + printf("Wrong resolution\n"); + return 1; + case GL_INVALID_OPERATION: + printf("Check the position of the glViewport instruction\n"); + return 1; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + dprintf("Setting projection\n"); + gluOrtho2D(0, resol_x, resol_y, 0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + +// SDL_ShowCursor(SDL_DISABLE); + + dprintf("Load shape\n"); + if (load_shape(shape)) + { + printf("Failed to load the shape '%s'\n", shape); + return 1; + } + + //we store the pixels of the shape vir the visual => tactile transation + glClearColor(1.0, 1.0, 1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + dprintf("Draw shape\n"); + draw_shape(); + dprintf("%dx%d : %d pixels\n", resol_x, resol_y, 4 * resol_x * resol_y); + + shapepixels = (unsigned char *) malloc(4 * resol_x * resol_y); + if (!shapepixels) + printf("Impossible to store the pixels\n"); + glReadPixels(0, 0, resol_x, resol_y, GL_RGBA, GL_UNSIGNED_BYTE, shapepixels); +#ifdef DEBUG + SDL_Surface *temp; + if (!(temp = SDL_CreateRGBSurface(SDL_SWSURFACE, resol_x, resol_y, 32, + #if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 + #else + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + #endif + ))) + return 1; + int i; + for (i = 0 ; i < resol_y ; i++) + memcpy(((char *) temp->pixels) + temp->pitch * i, shapepixels + 4 * resol_x * (resol_y - 1 - i), resol_x * 4); + + int nbpixels = 0; + for (i = 0 ; i < 4 * resol_x * resol_y ; i += 4) + if (!shapepixels[i]) + nbpixels++; + printf("\033[31m%d pixels colorés\033[0m, %d total\n", nbpixels, resol_x * resol_y); + + char screenshotstring[BUFFERSIZE]; + sprintf(screenshotstring, "%s.bmp", shape); + dprintf("Save screenshot %s\n", screenshotstring); + SDL_SaveBMP(temp, screenshotstring); + SDL_FreeSurface(temp); +#endif +// for (int i = 0 ; i < resolution[C_Y] ; i++) +// memcpy(((char *) temp->pixels) + temp->pitch * i, pixels + 4 * resolution[C_X] * (resolution[C_Y] - i - 1), resolution[C_X] * 4); + + SDL_Thread *mouse_status_thread = NULL, *tacton_thread = NULL, *pins_thread = NULL, *translation_thread = NULL; + //run the threads + switch (condition) + { + case CONDITION_MT: + if ((mouse_status_thread = create_mouse_status_thread()) == NULL) + { + printf("Impossible tu create the mouse events thread\n"); + return 1; + } + case CONDITION_PT: + dprintf("Conditions T\n"); + if ((tacton_thread = create_tacton_thread()) == NULL) + { + printf("Impossible to create the tactons thread\n"); + return 1; + } + if ((pins_thread = create_pins_thread()) == NULL) + { + printf("Impossible to create the tactile display thread\n"); + return 1; + } + break; + case CONDITION_MV: + if ((mouse_status_thread = create_mouse_status_thread()) == NULL) + { + printf("Impossible tu create the mouse events thread\n"); + return 1; + } + case CONDITION_PV: + dprintf("Conditions V\n"); + if ((translation_thread = create_translation_thread()) == NULL) + { + printf("Impossible to create the tactile display thread\n"); + return 1; + } + break; + } + + struct events_t evt; + while(running) + { + evt = process_events(); + if (evt.symbol == SDLK_ESCAPE) + break; +// currentdirection = (currentdirection + 1) % 9; + draw_screen(); + glFinish(); + SDL_Delay(10); + } + running = 0; + set_pads(0); + + + dprintf("Wait for the Threads\n"); + int status; + if (mouse_status_thread) + { + dprintf("Wait mouse_status_thread\n"); + SDL_WaitThread(mouse_status_thread, &status); + dprintf("Thread mouse_status_thread : %d\n", status); +// SDL_KillThread(mouse_status_thread); + } + if (tacton_thread) + { + dprintf("Wait tacton_thread\n"); + SDL_WaitThread(tacton_thread, &status); + dprintf("Thread tacton_thread : %d\n", status); +// SDL_KillThread(tacton_thread); + } + if (pins_thread) + { + dprintf("Wait pins_thread\n"); + SDL_WaitThread(pins_thread, &status); + dprintf("Thread pins_thread : %d\n", status); +// SDL_KillThread(pins_thread); + } + if (translation_thread) + { + dprintf("Wait translation_thread\n"); + SDL_WaitThread(translation_thread, &status); + dprintf("Thread translation_thread : %d\n", status); +// SDL_KillThread(translation_thread); + } + if (name) + { + dprintf("Closes the logfile\n"); + fclose(logfile); + } + dprintf("Unloads the shape\n"); + unload_shape(); + dprintf("Frees the surface\n"); + if (shapepixels) + free(shapepixels); + dprintf("Deletes the parameters\n"); + delete_params(list_params); + dprintf("Shows the cursor back\n"); +// SDL_ShowCursor(SDL_ENABLE); + dprintf("Freeing the screen\n"); + if (screen) + SDL_FreeSurface(screen); +// dprintf("Quit subsystem\n"); +// SDL_QuitSubSystem(SDL_INIT_EVERYTHING); +// dprintf("Quit SDL\n"); +// SDL_Quit(); + + dprintf("The end\n"); + + return 0; +} diff --git a/src/vtplayer-ctrl.c b/src/vtplayer-ctrl.c new file mode 100644 index 0000000..0369f40 --- /dev/null +++ b/src/vtplayer-ctrl.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include "vtplayer-ctrl.h" + +#include "control_request.h" + +#define STRLEN 1024 + +// Vendir ID and Product ID (see lsusb) +int VID = 0x1100; +int PID = 0x0001; + +#define TIMEOUT 100 + +#ifdef DEBUG +#define dprintf(x...) printf(x) +#else +#define dprintf(x...) +#endif + +usb_dev_handle * vtplayer_handle = NULL; +u32 lasttacton = 0; + +int init_vtplayer(void) +{ + struct usb_bus * bus; + struct usb_device * dev; +#ifdef __linux__ + char buf[STRLEN]; +#endif + + dprintf("Init usb\n"); + usb_init(); + dprintf("Find busses\n"); + usb_find_busses(); + dprintf("Find devices\n"); + usb_find_devices(); + + dprintf("Explore busses\n"); + for (bus = usb_get_busses(); bus; bus = bus->next) + { + dprintf("Parsing usb bus %s.\n", bus->dirname); + for (dev = bus->devices; dev; dev = dev->next) + { + dprintf(" Parsing usb device [%04X:%04X] %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, dev->filename); + + if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID)) + { + if (vtplayer_handle) + { + printf("Another vtplayer is connected. Please remove one.\n"); +// return -1; + } + dprintf("Found vtplayer. Opening interface.\n"); + if (!(vtplayer_handle = usb_open(dev))) + { + perror("vtplayer"); + return -1; + } +#ifdef __linux__ + if (usb_get_driver_np(vtplayer_handle, 0, buf, STRLEN) == 0) + { + dprintf("Done. Interface is bound to driver %s, detaching.\n", buf); + if (usb_detach_kernel_driver_np(vtplayer_handle, 0) < 0) + { + perror("vtplayer"); + return -1; + } + } +#endif + dprintf("Done. Setting configuration.\n"); + if (usb_set_configuration(vtplayer_handle, dev->config[0].bConfigurationValue) < 0) + { + perror("vtplayer"); + return -1; + } + dprintf("Done. Claiming interface.\n"); + if (usb_claim_interface(vtplayer_handle, 0) < 0) + { + perror("vtplayer"); + return -1; + } + dprintf("Done. Setting alternate interface.\n"); + if (usb_set_altinterface(vtplayer_handle, 0) < 0) + { + perror("vtplayer"); + return -1; + } + dprintf("Done.\n"); + } + } + } + + return vtplayer_handle != NULL ? 0 : 1; +} + +int release_vtplayer(void) +{ + if (vtplayer_handle) + { + if (usb_release_interface(vtplayer_handle, 0) < 0) + { + perror("usb_release"); + return -1; + } + if (usb_close(vtplayer_handle) < 0) + { + perror("usb_close"); + return -1; + } + } + vtplayer_handle = NULL; + return 0; +} + +int get_status(u8 * data) { + return usb_interrupt_read(vtplayer_handle, 0x81, (void *)data, 4, TIMEOUT); +} + +/* + We change the bit order so that the 4bytes set to the VTPlayer are + easy to read. + Each digit represent one line, each of its bits represent one pin. + => 4 digits for the left cell and 4 for the right cell. +*/ +u32 reorder(u32 pad) { +#define B(z, y) (((pad & (1 << (y - 1))) ? 1 : 0) << (z - 1)) + return ~(B( 8, 1) | B( 7, 2) | B(16, 3) | B(15, 4) | + B(24, 17) | B(23, 18) | B(32, 19) | B(31, 20) | + B( 6, 5) | B( 5, 6) | B(14, 7) | B(13, 8) | + B(22, 21) | B(21, 22) | B(30, 23) | B(29, 24) | + B( 2, 9) | B( 1, 10) | B(10, 11) | B( 9, 12) | + B(18, 25) | B(17, 26) | B(26, 27) | B(25, 28) | + B( 4, 13) | B( 3, 14) | B(12, 15) | B(11, 16) | + B(20, 29) | B(19, 30) | B(28, 31) | B(27, 32)); +} + +int set_pads(u32 pads) +{ + if (lasttacton != pads && vtplayer_handle) + { + pads = reorder(pads); + lasttacton = pads; + int ret = usb_control_msg(vtplayer_handle, 0x21, 0x09, 0x0200, 0x0000, (void *)&pads, 4, TIMEOUT); + if (ret < 0) + { + switch(-ret) + { + case EBADF: //9 + dprintf("USB ERROR: EBADF %d\n", ret); + break; + case ENXIO: //6 + dprintf("USB ERROR: ENXIO %d\n", ret); + break; + case EBUSY: //19 + dprintf("USB ERROR: EBUSY %d\n", ret); + break; +// case (LUSBDARWINSTALL): +// printf("USB ERROR: LUSBDARWINSTALL %d\n", ret); +// break; + case EINVAL: //22 + dprintf("USB ERROR: EINVAL %d\n", ret); + break; +#ifdef __linux__ + case ETIMEDOUT: //110 + dprintf("USB ERROR: ETIMEDOUT %d\n", ret); + break; +#endif + case EIO: //5 + dprintf("USB ERROR: EIO %d\n", ret); + break; + default: + dprintf("USB ERROR: %d\n", ret); + break; + } + //Dirty fix: if the vtplayer crashes for any reasonwe reload it + //seems that this makes the program crashes anyway in certain circumstances + //This occured only once, when there was a bug in the USB driver in the Linux kernel + release_vtplayer(); + init_vtplayer(); + } + return ret; + } + return 0; +} + -- 2.30.2