Je travaille actuellement sur un programme qui lit les valeurs des axes d'un joystick.
Mon problème est que ce programme ne lit ces valeurs que occasionnellement, et comme le device est géré de manière comparable a un FIFO, je me retrouve avec une valeur de l'axe qui n'est plus du tout d'actualité.
J'aimerais pouvoir obtenir la valeur correspondant au dernier event du joystick.
J'ai envisager plusieurs possibilités:
- "lseek(device_fd,-sizeof(struct js_event),SEEK_END)" mais ça n'a aucun résultat
- Emission d'un signal lors d'une réception dans le fichier (device) et connexion de ce signal a une fonction qui met à jour la valeur de mon axe, mais je ne trouve aucun moyen d'émettre un signal lors d'une réception dans le fichier.
- Un fonctionnement similaire en créant un thread qui contiendrait une boucle infinie contenant un "select" (sans timeout) sur le descripteur de fichier et qui mettrait à jour la valeur de l'axe. Mais je n'ai jamais joué avec les threads et je ne sais pas si je peux modifier une variable globale (int) sans vérifier qu'il ne soit pas utilisé dans un autre thread!
#define IMAGES_PATH "/mnt/ramdisk/img"
#define DEVICE_FILE "/dev/input/js0"
gint imagecpt=0;
GtkWidget *image=NULL;
GList *namelist=NULL;
gint windowwidth=800;
gint windowheight=600;
struct itimerval timer;
int device_fd=0;
int axe=0;
//******************************************************************************
// Fonction appelée a chaque fin de timer
//******************************************************************************
//gboolean update_image(gpointer data){
void update_image(int signal){
GError *error=NULL;
GdkPixbuf *pixbuf=NULL;
GdkPixbuf *scaledpixbuf=NULL;
gchar *filename=NULL;
struct js_event js;
//lseek(device_fd,-sizeof(struct js_event),SEEK_END);
read(device_fd, &js, sizeof(struct js_event));
if((js.type & ~JS_EVENT_INIT)==JS_EVENT_AXIS && js.number==2){
axe=js.value;
}
if(axe>10){
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000*32767/axe;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
filename = g_list_nth_data(namelist, imagecpt);
if(filename == NULL){
gtk_main_quit();
return;
}
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(pixbuf==NULL){
printf("Error: %s: %s\n",filename,error->message);
exit(69);
}
scaledpixbuf=gdk_pixbuf_scale_simple(pixbuf, windowwidth, windowheight, GDK_INTERP_NEAREST);
gtk_image_clear(GTK_IMAGE(image));
gtk_image_set_from_pixbuf(GTK_IMAGE(image), scaledpixbuf);
g_object_unref(pixbuf);
g_object_unref(scaledpixbuf);
imagecpt = imagecpt+1;
return;
}
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
}
//******************************************************************************
// Actualisation de la taille de l'image à la taille de la fenetre
//******************************************************************************
gboolean size_updated(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data){
windowwidth = event->width;
windowheight = event->height;
printf("%d , %d\n",windowwidth, windowheight);
return FALSE;
}
//******************************************************************************
// Main
//******************************************************************************
int main(int argc,char **argv){
GtkWidget *mainwindow=NULL;
GDir *dir=NULL;
gchar *filename=NULL;
gchar *name=NULL;
//Ouverture du device et mode nonblocant
if((device_fd = open(DEVICE_FILE, O_RDONLY)) < 0) {
perror(DEVICE_FILE);
return 1;
}
fcntl(device_fd, F_SETFL, O_NONBLOCK);
//Recuperation des noms de fichier et tri
dir = g_dir_open(IMAGES_PATH,0,NULL);
while(1){
filename = g_strdup(g_dir_read_name(dir));
if(filename == NULL)
break;
name = g_malloc((strlen(IMAGES_PATH)+strlen(filename)+1)* sizeof(gchar));
g_sprintf(name,"%s/%s",IMAGES_PATH,filename);
g_free(filename);
namelist = g_list_append(namelist,name);
}
namelist = g_list_sort(namelist,(GCompareFunc)strcmp);
// Construction interface GTK
gtk_init(&argc,&argv);
mainwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(mainwindow),"destroy",G_CALLBACK(gtk_main_quit),NULL);
g_signal_connect(G_OBJECT(mainwindow),"configure-event",G_CALLBACK(size_updated),NULL);
gtk_window_resize(GTK_WINDOW(mainwindow),640, 480);
//gtk_window_fullscreen(GTK_WINDOW(mainwindow));
image = gtk_image_new();
gtk_container_add(GTK_CONTAINER(mainwindow),image);
gtk_widget_show_all(mainwindow);
// Timer
signal(SIGALRM,update_image);
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 40000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
setitimer (ITIMER_REAL, &timer, NULL);
// Départ de la boucle principale
gtk_main();
return (0);
}
Question subsidiaire: Pour afficher/redimensionner une image j'utilise gdk_pixbuf et gtk_image car je ne connais que gtk.
Y aurait-il une méthode plus simple et/ou plus rapide (sdl, opengl, ...)
# mutex
Posté par Cereal Killer . Évalué à 1.
[^] # Re: mutex
Posté par xavier thomas . Évalué à 1.
Je vais me documenter de ce coté, mais des 3 solutions c'est celle qui me plaisait le moins. (c'est celle qui va me demander le plus de travail!)
merci
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.