symbian-qemu-0.9.1-12/libsdl-trunk/src/joystick/win32/SDL_mmjoystick.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2006 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Lesser General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2.1 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Lesser General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Lesser General Public
       
    16     License along with this library; if not, write to the Free Software
       
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 #include "SDL_config.h"
       
    23 
       
    24 #ifdef SDL_JOYSTICK_WINMM
       
    25 
       
    26 /* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */
       
    27 
       
    28 #define WIN32_LEAN_AND_MEAN
       
    29 #include <windows.h>
       
    30 #include <mmsystem.h>
       
    31 #include <regstr.h>
       
    32 
       
    33 #include "SDL_events.h"
       
    34 #include "SDL_joystick.h"
       
    35 #include "../SDL_sysjoystick.h"
       
    36 #include "../SDL_joystick_c.h"
       
    37 
       
    38 #define MAX_JOYSTICKS	16
       
    39 #define MAX_AXES	6	/* each joystick can have up to 6 axes */
       
    40 #define MAX_BUTTONS	32	/* and 32 buttons                      */
       
    41 #define AXIS_MIN	-32768  /* minimum value for axis coordinate */
       
    42 #define AXIS_MAX	32767   /* maximum value for axis coordinate */
       
    43 /* limit axis to 256 possible positions to filter out noise */
       
    44 #define JOY_AXIS_THRESHOLD      (((AXIS_MAX)-(AXIS_MIN))/256)
       
    45 #define JOY_BUTTON_FLAG(n)	(1<<n)
       
    46 
       
    47 
       
    48 /* array to hold joystick ID values */
       
    49 static UINT	SYS_JoystickID[MAX_JOYSTICKS];
       
    50 static JOYCAPS	SYS_Joystick[MAX_JOYSTICKS];
       
    51 static char	*SYS_JoystickName[MAX_JOYSTICKS];
       
    52 
       
    53 /* The private structure used to keep track of a joystick */
       
    54 struct joystick_hwdata
       
    55 {
       
    56 	/* joystick ID */
       
    57 	UINT	id;
       
    58 
       
    59 	/* values used to translate device-specific coordinates into
       
    60 	   SDL-standard ranges */
       
    61 	struct _transaxis {
       
    62 		int offset;
       
    63 		float scale;
       
    64 	} transaxis[6];
       
    65 };
       
    66 
       
    67 /* Convert a win32 Multimedia API return code to a text message */
       
    68 static void SetMMerror(char *function, int code);
       
    69 
       
    70 
       
    71 static char *GetJoystickName(int index, const char *szRegKey)
       
    72 {
       
    73 	/* added 7/24/2004 by Eckhard Stolberg */
       
    74 	/*
       
    75 		see if there is a joystick for the current
       
    76 		index (1-16) listed in the registry
       
    77 	*/
       
    78 	char *name = NULL;
       
    79 	HKEY hTopKey;
       
    80 	HKEY hKey;
       
    81 	DWORD regsize;
       
    82 	LONG regresult;
       
    83 	char regkey[256];
       
    84 	char regvalue[256];
       
    85 	char regname[256];
       
    86 
       
    87 	SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s\\%s",
       
    88 		REGSTR_PATH_JOYCONFIG, szRegKey, REGSTR_KEY_JOYCURR);
       
    89 	hTopKey = HKEY_LOCAL_MACHINE;
       
    90 	regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
       
    91 	if (regresult != ERROR_SUCCESS) {
       
    92 		hTopKey = HKEY_CURRENT_USER;
       
    93 		regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
       
    94 	}
       
    95 	if (regresult != ERROR_SUCCESS) {
       
    96 		return NULL;
       
    97 	}
       
    98 
       
    99 	/* find the registry key name for the joystick's properties */
       
   100 	regsize = sizeof(regname);
       
   101 	SDL_snprintf(regvalue, SDL_arraysize(regvalue), "Joystick%d%s", index+1, REGSTR_VAL_JOYOEMNAME);
       
   102 	regresult = RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE)regname, &regsize);
       
   103 	RegCloseKey(hKey);
       
   104 
       
   105 	if (regresult != ERROR_SUCCESS) {
       
   106 		return NULL;
       
   107 	}
       
   108 
       
   109 	/* open that registry key */
       
   110 	SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM, regname);
       
   111 	regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey);
       
   112 	if (regresult != ERROR_SUCCESS) {
       
   113 		return NULL;
       
   114 	}
       
   115 
       
   116 	/* find the size for the OEM name text */
       
   117 	regsize = sizeof(regvalue);
       
   118 	regresult = RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, &regsize);
       
   119 	if (regresult == ERROR_SUCCESS) {
       
   120 		/* allocate enough memory for the OEM name text ... */
       
   121 		name = (char *) SDL_malloc(regsize);
       
   122 		if ( name ) {
       
   123 			/* ... and read it from the registry */
       
   124 			regresult = RegQueryValueExA(hKey,
       
   125 				REGSTR_VAL_JOYOEMNAME, 0, 0,
       
   126 				(LPBYTE) name, &regsize);
       
   127 		}
       
   128 	}
       
   129 	RegCloseKey(hKey);
       
   130 
       
   131 	return(name);
       
   132 }
       
   133 
       
   134 /* Function to scan the system for joysticks.
       
   135  * This function should set SDL_numjoysticks to the number of available
       
   136  * joysticks.  Joystick 0 should be the system default joystick.
       
   137  * It should return 0, or -1 on an unrecoverable fatal error.
       
   138  */
       
   139 int SDL_SYS_JoystickInit(void)
       
   140 {
       
   141 	int	i;
       
   142 	int maxdevs;
       
   143 	int numdevs;
       
   144 	JOYINFOEX joyinfo;
       
   145 	JOYCAPS	joycaps;
       
   146 	MMRESULT result;
       
   147 
       
   148 	/* Reset the joystick ID & name mapping tables */
       
   149 	for ( i = 0; i < MAX_JOYSTICKS; ++i ) {
       
   150 		SYS_JoystickID[i] = 0;
       
   151 		SYS_JoystickName[i] = NULL;
       
   152 	}
       
   153 
       
   154 	/* Loop over all potential joystick devices */
       
   155 	numdevs = 0;
       
   156 	maxdevs = joyGetNumDevs();
       
   157 	for ( i = JOYSTICKID1; i < maxdevs && numdevs < MAX_JOYSTICKS; ++i ) {
       
   158 		
       
   159 		joyinfo.dwSize = sizeof(joyinfo);
       
   160 		joyinfo.dwFlags = JOY_RETURNALL;
       
   161 		result = joyGetPosEx(i, &joyinfo);
       
   162 		if ( result == JOYERR_NOERROR ) {
       
   163 			result = joyGetDevCaps(i, &joycaps, sizeof(joycaps));
       
   164 			if ( result == JOYERR_NOERROR ) {
       
   165 				SYS_JoystickID[numdevs] = i;
       
   166 				SYS_Joystick[numdevs] = joycaps;
       
   167 				SYS_JoystickName[numdevs] = GetJoystickName(i, joycaps.szRegKey);
       
   168 				numdevs++;
       
   169 			}
       
   170 		}
       
   171 	}
       
   172 	return(numdevs);
       
   173 }
       
   174 
       
   175 /* Function to get the device-dependent name of a joystick */
       
   176 const char *SDL_SYS_JoystickName(int index)
       
   177 {
       
   178 	if ( SYS_JoystickName[index] != NULL ) {
       
   179 		return(SYS_JoystickName[index]);
       
   180 	} else {
       
   181 		return(SYS_Joystick[index].szPname);
       
   182 	}
       
   183 }
       
   184 
       
   185 /* Function to open a joystick for use.
       
   186    The joystick to open is specified by the index field of the joystick.
       
   187    This should fill the nbuttons and naxes fields of the joystick structure.
       
   188    It returns 0, or -1 if there is an error.
       
   189  */
       
   190 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
       
   191 {
       
   192 	int index, i;
       
   193 	int caps_flags[MAX_AXES-2] =
       
   194 		{ JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV };
       
   195 	int axis_min[MAX_AXES], axis_max[MAX_AXES];
       
   196 
       
   197 
       
   198 	/* shortcut */
       
   199 	index = joystick->index;
       
   200 	axis_min[0] = SYS_Joystick[index].wXmin;
       
   201 	axis_max[0] = SYS_Joystick[index].wXmax;
       
   202 	axis_min[1] = SYS_Joystick[index].wYmin;
       
   203 	axis_max[1] = SYS_Joystick[index].wYmax;
       
   204 	axis_min[2] = SYS_Joystick[index].wZmin;
       
   205 	axis_max[2] = SYS_Joystick[index].wZmax;
       
   206 	axis_min[3] = SYS_Joystick[index].wRmin;
       
   207 	axis_max[3] = SYS_Joystick[index].wRmax;
       
   208 	axis_min[4] = SYS_Joystick[index].wUmin;
       
   209 	axis_max[4] = SYS_Joystick[index].wUmax;
       
   210 	axis_min[5] = SYS_Joystick[index].wVmin;
       
   211 	axis_max[5] = SYS_Joystick[index].wVmax;
       
   212 
       
   213 	/* allocate memory for system specific hardware data */
       
   214 	joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata));
       
   215 	if (joystick->hwdata == NULL)
       
   216 	{
       
   217 		SDL_OutOfMemory();
       
   218 		return(-1);
       
   219 	}
       
   220 	SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
       
   221 
       
   222 	/* set hardware data */
       
   223 	joystick->hwdata->id = SYS_JoystickID[index];
       
   224 	for ( i = 0; i < MAX_AXES; ++i ) {
       
   225 		if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) {
       
   226 			joystick->hwdata->transaxis[i].offset =
       
   227 				AXIS_MIN - axis_min[i];
       
   228 			joystick->hwdata->transaxis[i].scale =
       
   229 				(float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]);
       
   230 		} else {
       
   231 			joystick->hwdata->transaxis[i].offset = 0;
       
   232 			joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */
       
   233 		}
       
   234 	}
       
   235 
       
   236 	/* fill nbuttons, naxes, and nhats fields */
       
   237 	joystick->nbuttons = SYS_Joystick[index].wNumButtons;
       
   238 	joystick->naxes = SYS_Joystick[index].wNumAxes;
       
   239 	if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) {
       
   240 		joystick->nhats = 1;
       
   241 	} else {
       
   242 		joystick->nhats = 0;
       
   243 	}
       
   244 	return(0);
       
   245 }
       
   246 
       
   247 static Uint8 TranslatePOV(DWORD value)
       
   248 {
       
   249 	Uint8 pos;
       
   250 
       
   251 	pos = SDL_HAT_CENTERED;
       
   252 	if ( value != JOY_POVCENTERED ) {
       
   253 		if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) {
       
   254 			pos |= SDL_HAT_UP;
       
   255 		}
       
   256 		if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) {
       
   257 			pos |= SDL_HAT_RIGHT;
       
   258 		}
       
   259 		if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) {
       
   260 			pos |= SDL_HAT_DOWN;
       
   261 		}
       
   262 		if ( value > JOY_POVBACKWARD ) {
       
   263 			pos |= SDL_HAT_LEFT;
       
   264 		}
       
   265 	}
       
   266 	return(pos);
       
   267 }
       
   268 
       
   269 /* Function to update the state of a joystick - called as a device poll.
       
   270  * This function shouldn't update the joystick structure directly,
       
   271  * but instead should call SDL_PrivateJoystick*() to deliver events
       
   272  * and update joystick device state.
       
   273  */
       
   274 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
       
   275 {
       
   276 	MMRESULT result;
       
   277 	int i;
       
   278 	DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, 
       
   279 				  JOY_RETURNR, JOY_RETURNU, JOY_RETURNV };
       
   280 	DWORD pos[MAX_AXES];
       
   281 	struct _transaxis *transaxis;
       
   282 	int value, change;
       
   283 	JOYINFOEX joyinfo;
       
   284 
       
   285 	joyinfo.dwSize = sizeof(joyinfo);
       
   286 	joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS;
       
   287 	if ( ! joystick->hats ) {
       
   288 		joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS);
       
   289 	}
       
   290 	result = joyGetPosEx(joystick->hwdata->id, &joyinfo);
       
   291 	if ( result != JOYERR_NOERROR ) {
       
   292 		SetMMerror("joyGetPosEx", result);
       
   293 		return;
       
   294 	}
       
   295 
       
   296 	/* joystick motion events */
       
   297 	pos[0] = joyinfo.dwXpos;
       
   298 	pos[1] = joyinfo.dwYpos;
       
   299 	pos[2] = joyinfo.dwZpos;
       
   300 	pos[3] = joyinfo.dwRpos;
       
   301 	pos[4] = joyinfo.dwUpos;
       
   302 	pos[5] = joyinfo.dwVpos;
       
   303 
       
   304 	transaxis = joystick->hwdata->transaxis;
       
   305 	for (i = 0; i < joystick->naxes; i++) {
       
   306 		if (joyinfo.dwFlags & flags[i]) {
       
   307 			value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale);
       
   308 			change = (value - joystick->axes[i]);
       
   309 			if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) {
       
   310 				SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value);
       
   311 			}
       
   312 		}
       
   313 	}
       
   314 
       
   315 	/* joystick button events */
       
   316 	if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) {
       
   317 		for ( i = 0; i < joystick->nbuttons; ++i ) {
       
   318 			if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) {
       
   319 				if ( ! joystick->buttons[i] ) {
       
   320 					SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED);
       
   321 				}
       
   322 			} else {
       
   323 				if ( joystick->buttons[i] ) {
       
   324 					SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED);
       
   325 				}
       
   326 			}
       
   327 		}
       
   328 	}
       
   329 
       
   330 	/* joystick hat events */
       
   331 	if ( joyinfo.dwFlags & JOY_RETURNPOV ) {
       
   332 		Uint8 pos;
       
   333 
       
   334 		pos = TranslatePOV(joyinfo.dwPOV);
       
   335 		if ( pos != joystick->hats[0] ) {
       
   336 			SDL_PrivateJoystickHat(joystick, 0, pos);
       
   337 		}
       
   338 	}
       
   339 }
       
   340 
       
   341 /* Function to close a joystick after use */
       
   342 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
       
   343 {
       
   344 	if (joystick->hwdata != NULL) {
       
   345 		/* free system specific hardware data */
       
   346 		SDL_free(joystick->hwdata);
       
   347 	}
       
   348 }
       
   349 
       
   350 /* Function to perform any system-specific joystick related cleanup */
       
   351 void SDL_SYS_JoystickQuit(void)
       
   352 {
       
   353 	int i;
       
   354 	for (i = 0; i < MAX_JOYSTICKS; i++) {
       
   355 		if ( SYS_JoystickName[i] != NULL ) {
       
   356 			SDL_free(SYS_JoystickName[i]);
       
   357 		}
       
   358 	}
       
   359 }
       
   360 
       
   361 
       
   362 /* implementation functions */
       
   363 void SetMMerror(char *function, int code)
       
   364 {
       
   365 	static char *error;
       
   366 	static char  errbuf[1024];
       
   367 
       
   368 	errbuf[0] = 0;
       
   369 	switch (code) 
       
   370 	{
       
   371 		case MMSYSERR_NODRIVER:
       
   372 			error = "Joystick driver not present";
       
   373 		break;
       
   374 
       
   375 		case MMSYSERR_INVALPARAM:
       
   376 		case JOYERR_PARMS:
       
   377 			error = "Invalid parameter(s)";
       
   378 		break;
       
   379 		
       
   380 		case MMSYSERR_BADDEVICEID:
       
   381 			error = "Bad device ID";
       
   382 		break;
       
   383 
       
   384 		case JOYERR_UNPLUGGED:
       
   385 			error = "Joystick not attached";
       
   386 		break;
       
   387 
       
   388 		case JOYERR_NOCANDO:
       
   389 			error = "Can't capture joystick input";
       
   390 		break;
       
   391 
       
   392 		default:
       
   393 			SDL_snprintf(errbuf, SDL_arraysize(errbuf),
       
   394 			         "%s: Unknown Multimedia system error: 0x%x",
       
   395 								function, code);
       
   396 		break;
       
   397 	}
       
   398 
       
   399 	if ( ! errbuf[0] ) {
       
   400 		SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error);
       
   401 	}
       
   402 	SDL_SetError("%s", errbuf);
       
   403 }
       
   404 
       
   405 #endif /* SDL_JOYSTICK_WINMM */