[conversion d'une lib windows en linux]

Résolu/Fermé
Danny - 23 août 2007 à 10:23
 danny - 24 août 2007 à 13:26
Bonjour

Voici une lib qui fonctionne sous windows. Je voudrais la faire fonctionner sous Linux. Je n'y connais pas grand chose en programmation, mais je pense que le problème de compatibilité viens des headers qui sont différents selon le système d'exploitation. Les fonctions liées aux .h de windows ne sont pas nombreuses, donc je crois que ca ne ne devrait pas être très difficile pour des expérimentés (la lib "ne fait que" 500 lignes). Cela permettrait de faire avancer considérablement mon projet.

A tous ceux qui aiment les défis, ou qui voudrait me donner un coup de main je vous remercie.

Danny



------------------------------------------------------------------------------------------------------------------------------------------------

/***************************************************************************
This library is a test for the version 3.0 input device API for
CVF-based products
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*#include <windows.h>*/ /* <-- header windows */
/*#include <mmsystem.h>*/ /* <-- header windows */

#include <string.h>

#include <cvf_dl_init.h>
#include <cvf_udi_dso.h>

/* Boilerplate */
char *
udi_name(void)
{
return("WinJoy");
}

char *
udi_desc(void)
{
return("Windows Joystick UDI");
}

char *
udi_api_version(void)
{
return("3.0");
}

/* device "status" */
static int _debug = 0;

/* current device info... */
static int _which;
static JOYCAPS _dev;
static JOYINFOEX _info;
char* _dev="attention _dev";
/* current position... */
static float _pos[3];
static float _up[3];
static float _dir[3];

/* cursor axis and masks */
static int _axismap[6];
static int _axismask[6];
static int _axisbtn[6];
static float _axisscale[6];

/* output domain */
static float _dx[2];
static float _dy[2];
static float _dz[2];

/* buttons */
static int _nbuttons;
static int _btnmask[32];

/* valuators */
static int _nvaluators;
static int _valmap[6];
static int _valmask[6];
static int _valbtn[6];

/* reset button masks */
static int _reset[3]; /* all, pos, rot */

/* private fowrads */
static int parse_config(void);
static void update_tracker(void);
static void init_transpos(int which);
static float check_axis(int axis, int btnmask, int btnvalue, float scale);
static float get_info_axis(int axis);
static void norm(float *v);
static void n3m44f_mult(float *v, float m[4][4]);
static void m44f_rotate(float mat[4][4], float angle, float *vec);

/***************************************************************************
this routine is used to initialize the input device - it is called each time
the user toggles the "Use 6D input device" toggle.
**************************************************************************/

int
udi_device_initialize(void)
{
init_transpos(3);

_dx[0] = -1.0; _dx[1] = 1.0;
memcpy(_dy,_dx,sizeof(_dx));
memcpy(_dz,_dx,sizeof(_dx));

_which = JOYSTICKID1;
_nbuttons = 0;
_nvaluators = 0;
_axismap[0] = -1; _axismap[1] = -1; _axismap[2] = -1;
_axismap[3] = -1; _axismap[4] = -1; _axismap[5] = -1;
_reset[0] = -1; _reset[1] = -1; _reset[2] = -1;

parse_config();

if (joyGetDevCaps(_which,&_dev,sizeof(_dev)) != JOYERR_NOERROR) _which = -1;

if (_debug) {
int i;
fprintf(stderr,"Using physical joystick: %d\n",_which);
fprintf(stderr,"Device: %s %s\n",_dev.szPname,_dev.szOEMVxD);
fprintf(stderr,"%d buttons, %d axes\n",_dev.wNumButtons,_dev.wNumAxes);
fprintf(stderr,"Configuration:\n");
fprintf(stderr,"Domain: %.3f %.3f : %.3f %.3f : %.3f %.3f:\n",
_dx[0],_dx[1],_dy[0],_dy[1],_dz[0],_dz[1]);
fprintf(stderr,"Reset buttons: %X %X %X\n",_reset[0],_reset[1],_reset[2]);
fprintf(stderr,"Position:\n");
fprintf(stderr,"X:%d msk:%X:%X scl:%.3f\n",_axismap[0],_axismask[0],_axisbtn[0],_axisscale[0]);
fprintf(stderr,"Y:%d msk:%X:%X scl:%.3f\n",_axismap[1],_axismask[1],_axisbtn[1],_axisscale[1]);
fprintf(stderr,"Z:%d msk:%X:%X scl:%.3f\n",_axismap[2],_axismask[2],_axisbtn[2],_axisscale[2]);
fprintf(stderr,"Rotation:\n");
fprintf(stderr,"X:%d msk:%X:%X scl:%.3f\n",_axismap[3],_axismask[3],_axisbtn[3],_axisscale[3]);
fprintf(stderr,"Y:%d msk:%X:%X scl:%.3f\n",_axismap[4],_axismask[4],_axisbtn[4],_axisscale[4]);
fprintf(stderr,"Z:%d msk:%X:%X scl:%.3f\n",_axismap[5],_axismask[5],_axisbtn[5],_axisscale[5]);
fprintf(stderr,"Buttons:\n");
for(i=0;i<_nbuttons;i++) fprintf(stderr,"%d - %X\n",i,_btnmask[i]);
fprintf(stderr,"Valuators:\n");
for(i=0;i<_nvaluators;i++) fprintf(stderr,"%d - %d %X\n",i,_valmap[i],_valmask[i],_valbtn[i]);
}

return(CVF_ERROR_OK);
}

/* we only have one "tracker" */
int
udi_num_trackers(void)
{
return(1);
}

/***************************************************************************
return the direction and 'up' vectors for a tracker
**************************************************************************/
int
udi_tracker_pos(int tracker, float pos[3])
{
update_tracker();
memcpy(pos,_pos,sizeof(_pos));
return(1);
}

int
udi_tracker_orient(int tracker, float dir[3], float up[3])
{
memcpy(dir,_dir,sizeof(_dir));
memcpy(up,_up,sizeof(_up));
return(1);
}

/* Button interface */
int
udi_num_buttons(void)
{
if (_which == -1) return(0);
return(_nbuttons);
}

int
udi_button_status(int button, int *status)
{
*status = 0;
if (_which == -1) return(1);
if (button >= _nbuttons) return(1);
if ((_info.dwButtons & _btnmask[button]) == _btnmask[button]) *status = 1;
return(1);
}

int
udi_num_valuators(void)
{
if (_which == -1) return(0);
return(_nvaluators);
}

int
udi_valuator_value(int valuator, float *val)
{
*val = 0.0;
if (valuator >= _nvaluators) return(1);
/* if there is a btnmask, then the btn bits must match */
if (_valmask[valuator]) {
if ((_info.dwButtons & _valmask[valuator]) != _valbtn[valuator])
{
return(1);
}
}
*val = get_info_axis(_valmap[valuator]);
return(1);
}

/*******************************************************************/

/*
* Call this routine periodically to update the output values...
* In the future, this could be called by a thread...
*/
static void
update_tracker(void)
{
float rot[3] = {0.,0.,0.};
float trans[3] = {0.,0.,0.};
float mat[4][4];
float xv[3] = {1.,0.,0.};
float yv[3] = {0.,1.,0.};
float p[3];
int i;

if (_which == -1) return;

/* update the cache */
_info.dwSize = sizeof(_info);
_info.dwFlags = JOY_RETURNALL;
if (joyGetPosEx(_which, &_info) != JOYERR_NOERROR ) return;

if (_debug > 3) {
fprintf(stderr,"Raw data: %d %d %d %d %d %d : %X %X \n",
_info.dwXpos,_info.dwYpos,_info.dwZpos,
_info.dwRpos,_info.dwUpos,_info.dwVpos,
_info.dwButtons,_info.dwPOV);
}

/* check for "reset" */
i = 0;
if (_info.dwButtons == _reset[0]) i |= 3;
if (_info.dwButtons == _reset[1]) i |= 1;
if (_info.dwButtons == _reset[2]) i |= 2;
init_transpos(i);

/* compute rot, trans based on cursor axes */
trans[0] = check_axis(_axismap[0],_axismask[0],_axisbtn[0],_axisscale[0]);
trans[1] = check_axis(_axismap[1],_axismask[1],_axisbtn[1],_axisscale[1]);
trans[2] = check_axis(_axismap[2],_axismask[2],_axisbtn[2],_axisscale[2]);
rot[0] = check_axis(_axismap[3],_axismask[3],_axisbtn[3],_axisscale[3]);
rot[1] = check_axis(_axismap[4],_axismask[4],_axisbtn[4],_axisscale[4]);
rot[2] = check_axis(_axismap[5],_axismask[5],_axisbtn[5],_axisscale[5]);
if (_debug > 2) {
fprintf(stderr,"Core values: %.3f %.3f %.3f : %.3f %.3f %.3f\n",
rot[0],rot[1],rot[2],trans[0],trans[1],trans[2]);
}

/* update the vector */
m44f_rotate(mat,rot[0],xv);
n3m44f_mult(_dir,mat);
n3m44f_mult(_up,mat);
m44f_rotate(mat,rot[1],yv);
n3m44f_mult(_dir,mat);
n3m44f_mult(_up,mat);
m44f_rotate(mat,rot[2],_dir);
n3m44f_mult(_up,mat);
norm(_up);
norm(_dir);

/* update the position */
_pos[0] += trans[0]; _pos[1] += trans[1]; _pos[2] += trans[2];

/* clamp to the domain */
if (_pos[0] < _dx[0]) _pos[0] = _dx[0];
if (_pos[0] > _dx[1]) _pos[0] = _dx[1];
if (_pos[1] < _dy[0]) _pos[1] = _dy[0];
if (_pos[1] > _dy[1]) _pos[1] = _dy[1];
if (_pos[2] < _dz[0]) _pos[2] = _dz[0];
if (_pos[2] > _dz[1]) _pos[2] = _dz[1];

if (_debug > 1) {
fprintf(stderr,"Pos: %.3f %.3f %.3f Dir: %.3f %.3f %.3f Up: %.3f %.3f %.3f\n",
_pos[0],_pos[1],_pos[2],_dir[0],_dir[1],_dir[2],_up[0],_up[1],_up[2]);
}

return;
}

/* Borrowed from cvf_linear.c */
static void
m44f_rotate(float mat[4][4], float angle, float *vec)
{
double c, s;
float v[3];

if (angle == 0.0) {
mat[0][0] = 1.0;
mat[0][1] = 0.0;
mat[0][2] = 0.0;
mat[0][3] = 0.0;

mat[1][0] = 0.0;
mat[1][1] = 1.0;
mat[1][2] = 0.0;
mat[1][3] = 0.0;

mat[2][0] = 0.0;
mat[2][1] = 0.0;
mat[2][2] = 1.0;
mat[2][3] = 0.0;

mat[3][0] = 0.0;
mat[3][1] = 0.0;
mat[3][2] = 0.0;
mat[3][3] = 1.0;
return;
}

c=cos(angle);
s=sin(angle);

memcpy(v, vec, sizeof(v));
norm(v);

mat[0][0] = v[0]*v[0]*(1-c) + c;
mat[1][0] = v[0]*v[1]*(1-c) - v[2]*s;
mat[2][0] = v[0]*v[2]*(1-c) + v[1]*s;
mat[3][0] = 0;

mat[0][1] = v[1]*v[0]*(1-c) + v[2]*s;
mat[1][1] = v[1]*v[1]*(1-c) + c;
mat[2][1] = v[1]*v[2]*(1-c) - v[0]*s;
mat[3][1] = 0;

mat[0][2] = v[2]*v[0]*(1-c) - v[1]*s;
mat[1][2] = v[2]*v[1]*(1-c) + v[0]*s;
mat[2][2] = v[2]*v[2]*(1-c) + c;
mat[3][2] = 0;

mat[0][3] = 0;
mat[1][3] = 0;
mat[2][3] = 0;
mat[3][3] = 1;

return;
}

static void
n3m44f_mult(float *v, float m[4][4])
{
float result[3];
result[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0];
result[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1];
result[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2];
memcpy(v,result,sizeof(result));
return;
}

static void
norm(float *v)
{
double len;
len = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
if (len == 0.0) len = 1.0;
v[0] /= len; v[1] /= len; v[2] /= len;
return;
}

/* convert cursor axes to -scale,scale */
static float
check_axis(int axis, int btnmask, int btnvalue, float scale)
{
float v = 0.0;

if (axis < 0) return(v);
/* if there is a btnmask, then all the btn bits must be set */
if (btnmask) {
if ((_info.dwButtons & btnmask) != btnvalue) return(v);
}
/* grab the axis (-1,1) and rescale */
v = get_info_axis(axis)*scale;
return(v);
}

static float
get_info_axis(int axis)
{
float f,d,min,max,val;

/* pick the value and the bounds */
switch(axis) {
case 0:
val = _info.dwXpos; min = _dev.wXmin; max = _dev.wXmax;
break;
case 1:
val = _info.dwYpos; min = _dev.wYmin; max = _dev.wYmax;
break;
case 2:
val = _info.dwZpos; min = _dev.wZmin; max = _dev.wZmax;
break;
case 3:
val = _info.dwRpos; min = _dev.wRmin; max = _dev.wRmax;
break;
case 4:
val = _info.dwUpos; min = _dev.wUmin; max = _dev.wUmax;
break;
case 5:
val = _info.dwVpos; min = _dev.wVmin; max = _dev.wVmax;
break;
default:
val = 0.0; min = -1.0; max = 1.0;
break;
}
/* normalize */
d = max - min;
if (d == 0.0) d = 1.0;
f = (val - min)/(d);
val = f*2.0 - 1.0;
return -1 to 1
return(val);
}

static void
init_transpos(int which)
{
if (which & 1) {
memset(_pos,0,sizeof(_pos));
}
if (which & 2) {
memset(_up,0,sizeof(_up));
_up[1] = 1.0;
memset(_dir,0,sizeof(_dir));
_dir[2] = -1.0;
}
return;
}


/* config file:
*
* #WINJOY 1.0
* VALUATOR (0-6) (btnmask) (btnvalue)
* DOMAIN xmin xmax ymin ymax zmin zmax
* POSITIONX (0-6) (btnmask) (btnvalue) (scale)
* POSITIONY (0-6) (btnmask) (btnvalue) (scale)
* POSITIONZ (0-6) (btnmask) (btnvalue) (scale)
* ROTATIONX (0-6) (btnmask) (btnvalue) (scale)
* ROTATIONY (0-6) (btnmask) (btnvalue) (scale)
* ROTATIONZ (0-6) (btnmask) (btnvalue) (scale)
* BUTTON (b#)
* RESET (all b#) (pos b#) (rot b#)
* JOYSTICK #
* DEBUG (0-3)
*
*/
static int
parse_config(void)
{
FILE *fp;
char tmp[256];
char *path = "winjoy.cfg";

if (getenv("CEI_WINJOY_CONFIG")) path=getenv("CEI_WINJOY_CONFIG");

fp = fopen(path,"rb");
if (!fp) {
fprintf(stderr,"Unable to open joystick configuration file:%s\n",path);
return(-1);
}
while(fgets(tmp,sizeof(tmp),fp)) {
int i,axis,mask,val;
float scale;
char *s = strchr(tmp,'#');
if (s) *s = '\0';
s = strchr(tmp,';');
if (s) *s = '\0';
if (!_strnicmp(tmp,"VALUATOR", 8)) {
if (_nvaluators < 6) {
sscanf(tmp+8,"%d %d %d",_valmap+_nvaluators,
_valmask+_nvaluators,_valbtn+_nvaluators);
_nvaluators++;
} else {
fprintf(stderr,"Valuator skipped:%s\n",tmp);
}
} else if (!_strnicmp(tmp,"BUTTON", 6)) {
if (_nbuttons < 32) {
sscanf(tmp+6,"%d",&i);
_btnmask[_nbuttons] = 1 << i;
_nbuttons++;
} else {
fprintf(stderr,"Button skipped:%s\n",tmp);
}
} else if (!_strnicmp(tmp,"POSITION", 8)) {
sscanf(tmp+9,"%d %d %d %f",&axis,&mask,&val,&scale);
i = -1;
if (tmp[8] == 'X') i = 0;
if (tmp[8] == 'Y') i = 1;
if (tmp[8] == 'Z') i = 2;
if (i > -1) {
_axismap[i] = axis; _axismask[i] = mask; _axisbtn[i] = val;
_axisscale[i] = scale;
}
} else if (!_strnicmp(tmp,"ROTATION", 8)) {
sscanf(tmp+9,"%d %d %d %f",&axis,&mask,&val,&scale);
i = -1;
if (tmp[8] == 'X') i = 3;
if (tmp[8] == 'Y') i = 4;
if (tmp[8] == 'Z') i = 5;
if (i > -1) {
_axismap[i] = axis; _axismask[i] = mask; _axisbtn[i] = val;
_axisscale[i] = scale;
}
} else if (!_strnicmp(tmp,"JOYSTICK", 8)) {
sscanf(tmp+8,"%d",&_which);
} else if (!_strnicmp(tmp,"RESET", 5)) {
sscanf(tmp+5,"%d %d %d",_reset+0,_reset+1,_reset+2);
_reset[0] = 1 << _reset[0];
_reset[1] = 1 << _reset[1];
_reset[2] = 1 << _reset[2];
} else if (!_strnicmp(tmp,"DOMAIN", 6)) {
sscanf(tmp+6,"%f %f %f %f %f %f",_dx+0,_dx+1,_dy+0,_dy+1,_dz+0,_dz+1);
} else if (!_strnicmp(tmp,"DEBUG", 5)) {
sscanf(tmp+5,"%d",&_debug);
}
}
fclose(fp);
return(0);
}
A voir également:

2 réponses

mamiemando Messages postés 33591 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 mars 2025 7 834
23 août 2007 à 19:55
Oui c'est la bonne démarche.
Les headers suivants ne sont pas standards non plus :
#include <cvf_dl_init.h>
#include <cvf_udi_dso.h>

A moins que ce soit des headers développés par tes soins, il faudrait que tu commentes ces headers en plus des headers windowsiens et que tu regardes quels fonctions vont te manquer sous linux. Ensuite il faudra soit trouver un équivalent sous linux, soit les adapter sous linux.

Tu peux spécifier dans ton code des sections spécifiques à windows et spécifiques à linux (cf #define), en particulier pour les #include.
Exemple
#ifdef WIN32
//... code windows
#endif

#ifdef LINUX
// ... code linux
#endif

Pour compiler sous linux il faudra rajouter l'option -DLINUX. Exemple :
g++ -W -Wall -DLINUX plop.cpp

Bonne chance
0
ok merci pour l'info, je vais me mettre au boulot!
0