Import shapes master
authorThomas Pietrzak <thomas.pietrzak@gmail.com>
Wed, 30 Mar 2011 14:33:38 +0000 (14:33 +0000)
committerThomas Pietrzak <thomas.pietrzak@gmail.com>
Wed, 30 Mar 2011 14:33:38 +0000 (14:33 +0000)
git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@3 47cf9a05-e0a8-4ed5-9e9b-101a649bc004

27 files changed:
Makefile [new file with mode: 0644]
Makefile-win32 [new file with mode: 0644]
include/control_request.h [new file with mode: 0644]
include/display.h [new file with mode: 0644]
include/divers.h [new file with mode: 0644]
include/ecrire.h [new file with mode: 0644]
include/evenements.h [new file with mode: 0644]
include/gettimeofday.h [new file with mode: 0644]
include/guidance.h [new file with mode: 0644]
include/icons.h [new file with mode: 0644]
include/instructions.h [new file with mode: 0644]
include/params.h [new file with mode: 0644]
include/vtplayer-ctrl.h [new file with mode: 0644]
session [new file with mode: 0755]
src/display.c [new file with mode: 0644]
src/divers.c [new file with mode: 0644]
src/ecrire.c [new file with mode: 0644]
src/evenements.c [new file with mode: 0644]
src/exemple.c [new file with mode: 0644]
src/gettimeofday.c [new file with mode: 0644]
src/guidance.c [new file with mode: 0644]
src/icons.c [new file with mode: 0644]
src/instructions.c [new file with mode: 0644]
src/params.c [new file with mode: 0644]
src/saveshapes.c [new file with mode: 0644]
src/shapes.c [new file with mode: 0644]
src/vtplayer-ctrl.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..c376786
--- /dev/null
@@ -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 (file)
index 0000000..cf1faa4
--- /dev/null
@@ -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 (file)
index 0000000..4b355b4
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __DISPLAY__
+#define __DISPLAY__
+#include <SDL/SDL.h>
+#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 (file)
index 0000000..cd7adf1
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/stat.h>
+#define MKDIR(r) mkdir(r,0777)
+#else
+#include <io.h>
+#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 (file)
index 0000000..bbfdba0
--- /dev/null
@@ -0,0 +1,25 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+
+#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 (file)
index 0000000..68c33a0
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __EVTS__
+#define __EVTS__
+
+#include <SDL/SDL.h>
+
+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 (file)
index 0000000..61f38a5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __GETTIMEOFDAY__
+#define __GETTIMEOFDAY__
+#include <sys/time.h>
+
+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 (file)
index 0000000..36fc834
--- /dev/null
@@ -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 (file)
index 0000000..ba2bb94
--- /dev/null
@@ -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 (file)
index 0000000..de9337b
--- /dev/null
@@ -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 (file)
index 0000000..55f6b99
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __PARAMS__
+#define __PARAMS__
+
+#include <stdlib.h>
+
+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 (file)
index 0000000..033f34e
--- /dev/null
@@ -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 (executable)
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 (file)
index 0000000..c9a916f
--- /dev/null
@@ -0,0 +1,309 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <SDL/SDL_opengl.h>
+#include <SDL/SDL_ttf.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#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 (file)
index 0000000..7002f23
--- /dev/null
@@ -0,0 +1,14 @@
+#include "divers.h"
+
+#include <stdio.h>
+
+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 (file)
index 0000000..db67752
--- /dev/null
@@ -0,0 +1,277 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <math.h>
+#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 (file)
index 0000000..d967884
--- /dev/null
@@ -0,0 +1,206 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_thread.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..b80fcab
--- /dev/null
@@ -0,0 +1,383 @@
+// xsetwacom set stylus bottomx 12700 ; xsetwacom set stylus bottomy 20300
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_opengl.h>
+#include <SDL/SDL_image.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+
+#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 (file)
index 0000000..6292101
--- /dev/null
@@ -0,0 +1,85 @@
+#include <windows.h>
+
+#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 (file)
index 0000000..f687341
--- /dev/null
@@ -0,0 +1,134 @@
+#include "guidance.h"
+
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <SDL/SDL_opengl.h>
+#include <SDL/SDL_ttf.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..ebcd426
--- /dev/null
@@ -0,0 +1,727 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_thread.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <sys/time.h>
+
+#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 (file)
index 0000000..b4b022b
--- /dev/null
@@ -0,0 +1,119 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <SDL/SDL_keysym.h>
+#include <SDL/SDL_opengl.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..e90eb28
--- /dev/null
@@ -0,0 +1,125 @@
+#include "params.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..ca1f815
--- /dev/null
@@ -0,0 +1,515 @@
+#include <SDL/SDL.h>
+#include <SDL/SDL_opengl.h>
+#include <SDL/SDL_ttf.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+#include <math.h>
+
+#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 (file)
index 0000000..b80fcab
--- /dev/null
@@ -0,0 +1,383 @@
+// xsetwacom set stylus bottomx 12700 ; xsetwacom set stylus bottomy 20300
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_opengl.h>
+#include <SDL/SDL_image.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+
+#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 (file)
index 0000000..0369f40
--- /dev/null
@@ -0,0 +1,188 @@
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+#include <errno.h>
+#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;
+}
+