Mercurial > sdl-ios-xcode
annotate src/joystick/win32/SDL_mmjoystick.c @ 765:4c2ba6161939
Editors Note: The original patch was modified to use SDL_Delay() instead of
nanosleep because nanosleep may not be portable to all systems
using SDL with the ALSA backend. This may be a moot point with
the switch to blocking writes anyway...
Date: Sat, 27 Dec 2003 21:47:36 +0100
From: Michel Daenzer
To: Debian Bug Tracking System
Subject: [SDL] Bug#225252: [PATCH] ALSA fixes
Package: libsdl1.2debian-all
Version: 1.2.6-2
Severity: normal
Tags: patch
For SDL 1.2.6, the ALSA backend was changed to call snd_pcm_open() with
SND_PCM_NONBLOCK. That's a good idea per se, however, it causes high CPU
usage, interrupted sound and stuttering in some games here. Taking a nanosleep
whenever snd_pcm_writei() returns -EAGAIN fixes this, but I think it's more
efficient to use blocking mode for the actual sound playback. Feedback from the
SDL and ALSA lists appreciated.
The patch also fixes the default ALSA device to be used.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 04 Jan 2004 15:40:50 +0000 |
parents | 8450e66651ea |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
165
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */ | |
29 | |
30 #include <stdlib.h> | |
31 #include <stdio.h> /* For the definition of NULL */ | |
32 | |
33 #include "SDL_error.h" | |
34 #include "SDL_joystick.h" | |
35 #include "SDL_sysjoystick.h" | |
36 #include "SDL_joystick_c.h" | |
37 | |
38 #include <windows.h> | |
39 #include <mmsystem.h> | |
40 | |
531
8450e66651ea
Fixed joystick detection problem on Windows XP (thanks Maciej!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
41 #define MAX_JOYSTICKS 16 |
0 | 42 #define MAX_AXES 6 /* each joystick can have up to 6 axes */ |
43 #define MAX_BUTTONS 32 /* and 32 buttons */ | |
44 #define AXIS_MIN -32768 /* minimum value for axis coordinate */ | |
45 #define AXIS_MAX 32767 /* maximum value for axis coordinate */ | |
46 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/100) /* 1% motion */ | |
47 #define JOY_BUTTON_FLAG(n) (1<<n) | |
48 | |
49 | |
50 /* array to hold joystick ID values */ | |
51 static UINT SYS_JoystickID[MAX_JOYSTICKS]; | |
52 static JOYCAPS SYS_Joystick[MAX_JOYSTICKS]; | |
53 | |
54 /* The private structure used to keep track of a joystick */ | |
55 struct joystick_hwdata | |
56 { | |
57 /* joystick ID */ | |
58 UINT id; | |
59 | |
60 /* values used to translate device-specific coordinates into | |
61 SDL-standard ranges */ | |
62 struct _transaxis { | |
63 int offset; | |
64 float scale; | |
65 } transaxis[6]; | |
66 }; | |
67 | |
68 /* Convert a win32 Multimedia API return code to a text message */ | |
69 static void SetMMerror(char *function, int code); | |
70 | |
71 | |
72 /* Function to scan the system for joysticks. | |
73 * This function should set SDL_numjoysticks to the number of available | |
74 * joysticks. Joystick 0 should be the system default joystick. | |
75 * It should return 0, or -1 on an unrecoverable fatal error. | |
76 */ | |
77 int SDL_SYS_JoystickInit(void) | |
78 { | |
79 int i; | |
80 int maxdevs; | |
81 int numdevs; | |
82 JOYINFOEX joyinfo; | |
83 JOYCAPS joycaps; | |
84 MMRESULT result; | |
85 | |
86 numdevs = 0; | |
87 maxdevs = joyGetNumDevs(); | |
165
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
88 |
0 | 89 if ( maxdevs > MAX_JOYSTICKS ) { |
90 maxdevs = MAX_JOYSTICKS; | |
91 } | |
92 | |
165
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
93 |
531
8450e66651ea
Fixed joystick detection problem on Windows XP (thanks Maciej!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
94 for ( i = 0; i < MAX_JOYSTICKS; i++ ) { |
8450e66651ea
Fixed joystick detection problem on Windows XP (thanks Maciej!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
95 SYS_JoystickID[i] = JOYSTICKID1 + i; |
8450e66651ea
Fixed joystick detection problem on Windows XP (thanks Maciej!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
96 } |
8450e66651ea
Fixed joystick detection problem on Windows XP (thanks Maciej!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
97 |
0 | 98 |
99 for ( i = 0; (i < maxdevs); ++i ) { | |
165
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
100 |
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
101 /* added 8/31/2001 By Vitaliy Mikitchenko */ |
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
102 joyinfo.dwSize = sizeof(joyinfo); |
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
103 joyinfo.dwFlags = JOY_RETURNALL; |
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
104 /* end addition */ |
6a4e09bbbbc0
Joystick initialization fix submitted by Vitaliy Mikitchenko
Sam Lantinga <slouken@libsdl.org>
parents:
49
diff
changeset
|
105 |
0 | 106 result = joyGetPosEx(SYS_JoystickID[i], &joyinfo); |
107 if ( result == JOYERR_NOERROR ) { | |
108 result = joyGetDevCaps(SYS_JoystickID[i], &joycaps, sizeof(joycaps)); | |
109 if ( result == JOYERR_NOERROR ) { | |
110 SYS_JoystickID[numdevs] = SYS_JoystickID[i]; | |
111 SYS_Joystick[numdevs] = joycaps; | |
112 numdevs++; | |
113 } | |
114 } | |
115 } | |
116 return(numdevs); | |
117 } | |
118 | |
119 /* Function to get the device-dependent name of a joystick */ | |
120 const char *SDL_SYS_JoystickName(int index) | |
121 { | |
122 /***-> test for invalid index ? */ | |
123 return(SYS_Joystick[index].szPname); | |
124 } | |
125 | |
126 /* Function to open a joystick for use. | |
127 The joystick to open is specified by the index field of the joystick. | |
128 This should fill the nbuttons and naxes fields of the joystick structure. | |
129 It returns 0, or -1 if there is an error. | |
130 */ | |
131 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | |
132 { | |
133 int index, i; | |
134 int caps_flags[MAX_AXES-2] = | |
135 { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; | |
136 int axis_min[MAX_AXES], axis_max[MAX_AXES]; | |
137 | |
138 | |
139 /* shortcut */ | |
140 index = joystick->index; | |
141 axis_min[0] = SYS_Joystick[index].wXmin; | |
142 axis_max[0] = SYS_Joystick[index].wXmax; | |
143 axis_min[1] = SYS_Joystick[index].wYmin; | |
144 axis_max[1] = SYS_Joystick[index].wYmax; | |
145 axis_min[2] = SYS_Joystick[index].wZmin; | |
146 axis_max[2] = SYS_Joystick[index].wZmax; | |
147 axis_min[3] = SYS_Joystick[index].wRmin; | |
148 axis_max[3] = SYS_Joystick[index].wRmax; | |
149 axis_min[4] = SYS_Joystick[index].wUmin; | |
150 axis_max[4] = SYS_Joystick[index].wUmax; | |
151 axis_min[5] = SYS_Joystick[index].wVmin; | |
152 axis_max[5] = SYS_Joystick[index].wVmax; | |
153 | |
154 /* allocate memory for system specific hardware data */ | |
155 joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata)); | |
156 if (joystick->hwdata == NULL) | |
157 { | |
158 SDL_OutOfMemory(); | |
159 return(-1); | |
160 } | |
161 memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); | |
162 | |
163 /* set hardware data */ | |
164 joystick->hwdata->id = SYS_JoystickID[index]; | |
165 for ( i = 0; i < MAX_AXES; ++i ) { | |
166 if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { | |
167 joystick->hwdata->transaxis[i].offset = | |
168 AXIS_MIN - axis_min[i]; | |
169 joystick->hwdata->transaxis[i].scale = | |
170 (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); | |
171 } else { | |
172 joystick->hwdata->transaxis[i].offset = 0; | |
173 joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ | |
174 } | |
175 } | |
176 | |
177 /* fill nbuttons, naxes, and nhats fields */ | |
178 joystick->nbuttons = SYS_Joystick[index].wNumButtons; | |
179 joystick->naxes = SYS_Joystick[index].wNumAxes; | |
180 if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { | |
181 joystick->nhats = 1; | |
182 } else { | |
183 joystick->nhats = 0; | |
184 } | |
185 return(0); | |
186 } | |
187 | |
188 static Uint8 TranslatePOV(DWORD value) | |
189 { | |
190 Uint8 pos; | |
191 | |
192 pos = SDL_HAT_CENTERED; | |
193 if ( value != JOY_POVCENTERED ) { | |
194 if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { | |
195 pos |= SDL_HAT_UP; | |
196 } | |
197 if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { | |
198 pos |= SDL_HAT_RIGHT; | |
199 } | |
200 if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { | |
201 pos |= SDL_HAT_DOWN; | |
202 } | |
203 if ( value > JOY_POVBACKWARD ) { | |
204 pos |= SDL_HAT_LEFT; | |
205 } | |
206 } | |
207 return(pos); | |
208 } | |
209 | |
210 /* Function to update the state of a joystick - called as a device poll. | |
211 * This function shouldn't update the joystick structure directly, | |
212 * but instead should call SDL_PrivateJoystick*() to deliver events | |
213 * and update joystick device state. | |
214 */ | |
215 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | |
216 { | |
217 MMRESULT result; | |
218 int i; | |
219 DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, | |
220 JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; | |
221 DWORD pos[MAX_AXES]; | |
222 struct _transaxis *transaxis; | |
223 int value, change; | |
224 JOYINFOEX joyinfo; | |
225 | |
226 joyinfo.dwSize = sizeof(joyinfo); | |
227 joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; | |
228 if ( ! joystick->hats ) { | |
229 joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); | |
230 } | |
231 result = joyGetPosEx(joystick->hwdata->id, &joyinfo); | |
232 if ( result != JOYERR_NOERROR ) { | |
233 SetMMerror("joyGetPosEx", result); | |
234 return; | |
235 } | |
236 | |
237 /* joystick motion events */ | |
238 pos[0] = joyinfo.dwXpos; | |
239 pos[1] = joyinfo.dwYpos; | |
240 pos[2] = joyinfo.dwZpos; | |
241 pos[3] = joyinfo.dwRpos; | |
242 pos[4] = joyinfo.dwUpos; | |
243 pos[5] = joyinfo.dwVpos; | |
244 | |
245 transaxis = joystick->hwdata->transaxis; | |
246 for (i = 0; i < joystick->naxes; i++) { | |
247 if (joyinfo.dwFlags & flags[i]) { | |
49
6f3c474f9abd
Fixed bug in joystick motion, thanks to Alexandre Duret-Lutz
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
248 value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); |
0 | 249 change = (value - joystick->axes[i]); |
250 if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { | |
251 SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); | |
252 } | |
253 } | |
254 } | |
255 | |
256 /* joystick button events */ | |
257 if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { | |
258 for ( i = 0; i < joystick->nbuttons; ++i ) { | |
259 if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { | |
260 if ( ! joystick->buttons[i] ) { | |
261 SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); | |
262 } | |
263 } else { | |
264 if ( joystick->buttons[i] ) { | |
265 SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); | |
266 } | |
267 } | |
268 } | |
269 } | |
270 | |
271 /* joystick hat events */ | |
272 if ( joyinfo.dwFlags & JOY_RETURNPOV ) { | |
273 Uint8 pos; | |
274 | |
275 pos = TranslatePOV(joyinfo.dwPOV); | |
276 if ( pos != joystick->hats[0] ) { | |
277 SDL_PrivateJoystickHat(joystick, 0, pos); | |
278 } | |
279 } | |
280 } | |
281 | |
282 /* Function to close a joystick after use */ | |
283 void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | |
284 { | |
285 if (joystick->hwdata != NULL) { | |
286 /* free system specific hardware data */ | |
287 free(joystick->hwdata); | |
288 } | |
289 } | |
290 | |
291 /* Function to perform any system-specific joystick related cleanup */ | |
292 void SDL_SYS_JoystickQuit(void) | |
293 { | |
294 return; | |
295 } | |
296 | |
297 | |
298 /* implementation functions */ | |
299 void SetMMerror(char *function, int code) | |
300 { | |
301 static char *error; | |
302 static char errbuf[BUFSIZ]; | |
303 | |
304 errbuf[0] = 0; | |
305 switch (code) | |
306 { | |
307 case MMSYSERR_NODRIVER: | |
308 error = "Joystick driver not present"; | |
309 break; | |
310 | |
311 case MMSYSERR_INVALPARAM: | |
312 case JOYERR_PARMS: | |
313 error = "Invalid parameter(s)"; | |
314 break; | |
315 | |
316 case MMSYSERR_BADDEVICEID: | |
317 error = "Bad device ID"; | |
318 break; | |
319 | |
320 case JOYERR_UNPLUGGED: | |
321 error = "Joystick not attached"; | |
322 break; | |
323 | |
324 case JOYERR_NOCANDO: | |
325 error = "Can't capture joystick input"; | |
326 break; | |
327 | |
328 default: | |
329 sprintf(errbuf, "%s: Unknown Multimedia system error: 0x%x", | |
330 function, code); | |
331 break; | |
332 } | |
333 | |
334 if ( ! errbuf[0] ) { | |
335 sprintf(errbuf, "%s: %s", function, error); | |
336 } | |
337 SDL_SetError("%s", errbuf); | |
338 } |