Mercurial > sdl-ios-xcode
annotate src/joystick/SDL_joystick.c @ 1330:450721ad5436
It's now possible to build SDL without any C runtime at all on Windows,
using Visual C++ 2005
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 06 Feb 2006 08:28:51 +0000 |
parents | c9b51268668f |
children | 3692456e7b0f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 /* This is the joystick API for Simple DirectMedia Layer */ | |
24 | |
25 #include "SDL_error.h" | |
26 #include "SDL_events.h" | |
1330
450721ad5436
It's now possible to build SDL without any C runtime at all on Windows,
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
27 #include "SDL_stdlib.h" |
450721ad5436
It's now possible to build SDL without any C runtime at all on Windows,
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
28 #include "SDL_string.h" |
0 | 29 #ifndef DISABLE_EVENTS |
30 #include "SDL_events_c.h" | |
31 #endif | |
32 #include "SDL_joystick_c.h" | |
33 #include "SDL_sysjoystick.h" | |
34 | |
35 /* This is used for Quake III Arena */ | |
36 #ifdef DISABLE_EVENTS | |
37 #define SDL_Lock_EventThread() | |
38 #define SDL_Unlock_EventThread() | |
39 #endif | |
40 | |
41 Uint8 SDL_numjoysticks = 0; | |
42 SDL_Joystick **SDL_joysticks = NULL; | |
43 static SDL_Joystick *default_joystick = NULL; | |
44 | |
45 int SDL_JoystickInit(void) | |
46 { | |
47 int arraylen; | |
48 int status; | |
49 | |
50 SDL_numjoysticks = 0; | |
51 status = SDL_SYS_JoystickInit(); | |
52 if ( status >= 0 ) { | |
53 arraylen = (status+1)*sizeof(*SDL_joysticks); | |
54 SDL_joysticks = (SDL_Joystick **)malloc(arraylen); | |
55 if ( SDL_joysticks == NULL ) { | |
56 SDL_numjoysticks = 0; | |
57 } else { | |
58 memset(SDL_joysticks, 0, arraylen); | |
716
f25e3334d583
SDL_JoystickInit: If malloc() fails, pretend no joysticks were detected.
Ryan C. Gordon <icculus@icculus.org>
parents:
297
diff
changeset
|
59 SDL_numjoysticks = status; |
0 | 60 } |
61 status = 0; | |
62 } | |
63 default_joystick = NULL; | |
64 return(status); | |
65 } | |
66 | |
67 /* | |
68 * Count the number of joysticks attached to the system | |
69 */ | |
70 int SDL_NumJoysticks(void) | |
71 { | |
72 return SDL_numjoysticks; | |
73 } | |
74 | |
75 /* | |
76 * Get the implementation dependent name of a joystick | |
77 */ | |
78 const char *SDL_JoystickName(int device_index) | |
79 { | |
80 if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { | |
81 SDL_SetError("There are %d joysticks available", | |
82 SDL_numjoysticks); | |
83 return(NULL); | |
84 } | |
85 return(SDL_SYS_JoystickName(device_index)); | |
86 } | |
87 | |
88 /* | |
89 * Open a joystick for use - the index passed as an argument refers to | |
90 * the N'th joystick on the system. This index is the value which will | |
91 * identify this joystick in future joystick events. | |
92 * | |
93 * This function returns a joystick identifier, or NULL if an error occurred. | |
94 */ | |
95 SDL_Joystick *SDL_JoystickOpen(int device_index) | |
96 { | |
97 int i; | |
98 SDL_Joystick *joystick; | |
99 | |
100 if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { | |
101 SDL_SetError("There are %d joysticks available", | |
102 SDL_numjoysticks); | |
103 return(NULL); | |
104 } | |
105 | |
106 /* If the joystick is already open, return it */ | |
107 for ( i=0; SDL_joysticks[i]; ++i ) { | |
108 if ( device_index == SDL_joysticks[i]->index ) { | |
109 joystick = SDL_joysticks[i]; | |
110 ++joystick->ref_count; | |
111 return(joystick); | |
112 } | |
113 } | |
114 | |
115 /* Create and initialize the joystick */ | |
116 joystick = (SDL_Joystick *)malloc((sizeof *joystick)); | |
117 if ( joystick != NULL ) { | |
118 memset(joystick, 0, (sizeof *joystick)); | |
119 joystick->index = device_index; | |
120 if ( SDL_SYS_JoystickOpen(joystick) < 0 ) { | |
121 free(joystick); | |
122 joystick = NULL; | |
123 } else { | |
124 if ( joystick->naxes > 0 ) { | |
125 joystick->axes = (Sint16 *)malloc | |
126 (joystick->naxes*sizeof(Sint16)); | |
127 } | |
128 if ( joystick->nhats > 0 ) { | |
129 joystick->hats = (Uint8 *)malloc | |
130 (joystick->nhats*sizeof(Uint8)); | |
131 } | |
132 if ( joystick->nballs > 0 ) { | |
133 joystick->balls = (struct balldelta *)malloc | |
134 (joystick->nballs*sizeof(*joystick->balls)); | |
135 } | |
136 if ( joystick->nbuttons > 0 ) { | |
137 joystick->buttons = (Uint8 *)malloc | |
138 (joystick->nbuttons*sizeof(Uint8)); | |
139 } | |
140 if ( ((joystick->naxes > 0) && !joystick->axes) | |
141 || ((joystick->nhats > 0) && !joystick->hats) | |
142 || ((joystick->nballs > 0) && !joystick->balls) | |
143 || ((joystick->nbuttons > 0) && !joystick->buttons)) { | |
144 SDL_OutOfMemory(); | |
145 SDL_JoystickClose(joystick); | |
146 joystick = NULL; | |
147 } | |
148 if ( joystick->axes ) { | |
149 memset(joystick->axes, 0, | |
150 joystick->naxes*sizeof(Sint16)); | |
151 } | |
152 if ( joystick->hats ) { | |
153 memset(joystick->hats, 0, | |
154 joystick->nhats*sizeof(Uint8)); | |
155 } | |
156 if ( joystick->balls ) { | |
157 memset(joystick->balls, 0, | |
158 joystick->nballs*sizeof(*joystick->balls)); | |
159 } | |
160 if ( joystick->buttons ) { | |
161 memset(joystick->buttons, 0, | |
162 joystick->nbuttons*sizeof(Uint8)); | |
163 } | |
164 } | |
165 } | |
166 if ( joystick ) { | |
167 /* Add joystick to list */ | |
168 ++joystick->ref_count; | |
169 SDL_Lock_EventThread(); | |
170 for ( i=0; SDL_joysticks[i]; ++i ) | |
171 /* Skip to next joystick */; | |
172 SDL_joysticks[i] = joystick; | |
173 SDL_Unlock_EventThread(); | |
174 } | |
175 return(joystick); | |
176 } | |
177 | |
178 /* | |
179 * Returns 1 if the joystick has been opened, or 0 if it has not. | |
180 */ | |
181 int SDL_JoystickOpened(int device_index) | |
182 { | |
183 int i, opened; | |
184 | |
185 opened = 0; | |
186 for ( i=0; SDL_joysticks[i]; ++i ) { | |
187 if ( SDL_joysticks[i]->index == (Uint8)device_index ) { | |
188 opened = 1; | |
189 break; | |
190 } | |
191 } | |
192 return(opened); | |
193 } | |
194 | |
195 static int ValidJoystick(SDL_Joystick **joystick) | |
196 { | |
197 int valid; | |
198 | |
199 if ( *joystick == NULL ) { | |
200 *joystick = default_joystick; | |
201 } | |
202 if ( *joystick == NULL ) { | |
203 SDL_SetError("Joystick hasn't been opened yet"); | |
204 valid = 0; | |
205 } else { | |
206 valid = 1; | |
207 } | |
208 return valid; | |
209 } | |
210 | |
211 /* | |
212 * Get the device index of an opened joystick. | |
213 */ | |
214 int SDL_JoystickIndex(SDL_Joystick *joystick) | |
215 { | |
216 if ( ! ValidJoystick(&joystick) ) { | |
217 return(-1); | |
218 } | |
219 return(joystick->index); | |
220 } | |
221 | |
222 /* | |
223 * Get the number of multi-dimensional axis controls on a joystick | |
224 */ | |
225 int SDL_JoystickNumAxes(SDL_Joystick *joystick) | |
226 { | |
227 if ( ! ValidJoystick(&joystick) ) { | |
228 return(-1); | |
229 } | |
230 return(joystick->naxes); | |
231 } | |
232 | |
233 /* | |
234 * Get the number of hats on a joystick | |
235 */ | |
236 int SDL_JoystickNumHats(SDL_Joystick *joystick) | |
237 { | |
238 if ( ! ValidJoystick(&joystick) ) { | |
239 return(-1); | |
240 } | |
241 return(joystick->nhats); | |
242 } | |
243 | |
244 /* | |
245 * Get the number of trackballs on a joystick | |
246 */ | |
247 int SDL_JoystickNumBalls(SDL_Joystick *joystick) | |
248 { | |
249 if ( ! ValidJoystick(&joystick) ) { | |
250 return(-1); | |
251 } | |
252 return(joystick->nballs); | |
253 } | |
254 | |
255 /* | |
256 * Get the number of buttons on a joystick | |
257 */ | |
258 int SDL_JoystickNumButtons(SDL_Joystick *joystick) | |
259 { | |
260 if ( ! ValidJoystick(&joystick) ) { | |
261 return(-1); | |
262 } | |
263 return(joystick->nbuttons); | |
264 } | |
265 | |
266 /* | |
267 * Get the current state of an axis control on a joystick | |
268 */ | |
269 Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) | |
270 { | |
271 Sint16 state; | |
272 | |
273 if ( ! ValidJoystick(&joystick) ) { | |
274 return(0); | |
275 } | |
276 if ( axis < joystick->naxes ) { | |
277 state = joystick->axes[axis]; | |
278 } else { | |
279 SDL_SetError("Joystick only has %d axes", joystick->naxes); | |
280 state = 0; | |
281 } | |
282 return(state); | |
283 } | |
284 | |
285 /* | |
286 * Get the current state of a hat on a joystick | |
287 */ | |
288 Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) | |
289 { | |
290 Uint8 state; | |
291 | |
292 if ( ! ValidJoystick(&joystick) ) { | |
293 return(0); | |
294 } | |
295 if ( hat < joystick->nhats ) { | |
296 state = joystick->hats[hat]; | |
297 } else { | |
298 SDL_SetError("Joystick only has %d hats", joystick->nhats); | |
299 state = 0; | |
300 } | |
301 return(state); | |
302 } | |
303 | |
304 /* | |
305 * Get the ball axis change since the last poll | |
306 */ | |
307 int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) | |
308 { | |
309 int retval; | |
310 | |
311 if ( ! ValidJoystick(&joystick) ) { | |
312 return(-1); | |
313 } | |
314 | |
315 retval = 0; | |
316 if ( ball < joystick->nballs ) { | |
317 if ( dx ) { | |
318 *dx = joystick->balls[ball].dx; | |
319 } | |
320 if ( dy ) { | |
321 *dy = joystick->balls[ball].dy; | |
322 } | |
323 joystick->balls[ball].dx = 0; | |
324 joystick->balls[ball].dy = 0; | |
325 } else { | |
326 SDL_SetError("Joystick only has %d balls", joystick->nballs); | |
327 retval = -1; | |
328 } | |
329 return(retval); | |
330 } | |
331 | |
332 /* | |
333 * Get the current state of a button on a joystick | |
334 */ | |
335 Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) | |
336 { | |
337 Uint8 state; | |
338 | |
339 if ( ! ValidJoystick(&joystick) ) { | |
340 return(0); | |
341 } | |
342 if ( button < joystick->nbuttons ) { | |
343 state = joystick->buttons[button]; | |
344 } else { | |
345 SDL_SetError("Joystick only has %d buttons",joystick->nbuttons); | |
346 state = 0; | |
347 } | |
348 return(state); | |
349 } | |
350 | |
351 /* | |
352 * Close a joystick previously opened with SDL_JoystickOpen() | |
353 */ | |
354 void SDL_JoystickClose(SDL_Joystick *joystick) | |
355 { | |
356 int i; | |
357 | |
358 if ( ! ValidJoystick(&joystick) ) { | |
359 return; | |
360 } | |
361 | |
362 /* First decrement ref count */ | |
363 if ( --joystick->ref_count > 0 ) { | |
364 return; | |
365 } | |
366 | |
367 /* Lock the event queue - prevent joystick polling */ | |
368 SDL_Lock_EventThread(); | |
369 | |
370 if ( joystick == default_joystick ) { | |
371 default_joystick = NULL; | |
372 } | |
373 SDL_SYS_JoystickClose(joystick); | |
374 | |
375 /* Remove joystick from list */ | |
376 for ( i=0; SDL_joysticks[i]; ++i ) { | |
377 if ( joystick == SDL_joysticks[i] ) { | |
378 memcpy(&SDL_joysticks[i], &SDL_joysticks[i+1], | |
379 (SDL_numjoysticks-i)*sizeof(joystick)); | |
380 break; | |
381 } | |
382 } | |
383 | |
384 /* Let the event thread keep running */ | |
385 SDL_Unlock_EventThread(); | |
386 | |
387 /* Free the data associated with this joystick */ | |
388 if ( joystick->axes ) { | |
389 free(joystick->axes); | |
390 } | |
391 if ( joystick->hats ) { | |
392 free(joystick->hats); | |
393 } | |
394 if ( joystick->balls ) { | |
395 free(joystick->balls); | |
396 } | |
397 if ( joystick->buttons ) { | |
398 free(joystick->buttons); | |
399 } | |
400 free(joystick); | |
401 } | |
402 | |
403 void SDL_JoystickQuit(void) | |
404 { | |
405 /* Stop the event polling */ | |
406 SDL_Lock_EventThread(); | |
407 SDL_numjoysticks = 0; | |
408 SDL_Unlock_EventThread(); | |
409 | |
410 /* Quit the joystick setup */ | |
411 SDL_SYS_JoystickQuit(); | |
412 if ( SDL_joysticks ) { | |
413 free(SDL_joysticks); | |
414 SDL_joysticks = NULL; | |
415 } | |
416 } | |
417 | |
418 | |
419 /* These are global for SDL_sysjoystick.c and SDL_events.c */ | |
420 | |
421 int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value) | |
422 { | |
423 int posted; | |
424 | |
425 /* Update internal joystick state */ | |
426 joystick->axes[axis] = value; | |
427 | |
428 /* Post the event, if desired */ | |
429 posted = 0; | |
430 #ifndef DISABLE_EVENTS | |
431 if ( SDL_ProcessEvents[SDL_JOYAXISMOTION] == SDL_ENABLE ) { | |
432 SDL_Event event; | |
433 event.type = SDL_JOYAXISMOTION; | |
434 event.jaxis.which = joystick->index; | |
435 event.jaxis.axis = axis; | |
436 event.jaxis.value = value; | |
437 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | |
438 posted = 1; | |
439 SDL_PushEvent(&event); | |
440 } | |
441 } | |
442 #endif /* !DISABLE_EVENTS */ | |
443 return(posted); | |
444 } | |
445 | |
446 int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) | |
447 { | |
448 int posted; | |
449 | |
450 /* Update internal joystick state */ | |
451 joystick->hats[hat] = value; | |
452 | |
453 /* Post the event, if desired */ | |
454 posted = 0; | |
455 #ifndef DISABLE_EVENTS | |
456 if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) { | |
457 SDL_Event event; | |
458 event.jhat.type = SDL_JOYHATMOTION; | |
459 event.jhat.which = joystick->index; | |
460 event.jhat.hat = hat; | |
461 event.jhat.value = value; | |
462 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | |
463 posted = 1; | |
464 SDL_PushEvent(&event); | |
465 } | |
466 } | |
467 #endif /* !DISABLE_EVENTS */ | |
468 return(posted); | |
469 } | |
470 | |
471 int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, | |
472 Sint16 xrel, Sint16 yrel) | |
473 { | |
474 int posted; | |
475 | |
476 /* Update internal mouse state */ | |
477 joystick->balls[ball].dx += xrel; | |
478 joystick->balls[ball].dy += yrel; | |
479 | |
480 /* Post the event, if desired */ | |
481 posted = 0; | |
482 #ifndef DISABLE_EVENTS | |
483 if ( SDL_ProcessEvents[SDL_JOYBALLMOTION] == SDL_ENABLE ) { | |
484 SDL_Event event; | |
485 event.jball.type = SDL_JOYBALLMOTION; | |
486 event.jball.which = joystick->index; | |
487 event.jball.ball = ball; | |
488 event.jball.xrel = xrel; | |
489 event.jball.yrel = yrel; | |
490 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | |
491 posted = 1; | |
492 SDL_PushEvent(&event); | |
493 } | |
494 } | |
495 #endif /* !DISABLE_EVENTS */ | |
496 return(posted); | |
497 } | |
498 | |
499 int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) | |
500 { | |
501 int posted; | |
502 #ifndef DISABLE_EVENTS | |
503 SDL_Event event; | |
504 | |
505 switch ( state ) { | |
506 case SDL_PRESSED: | |
507 event.type = SDL_JOYBUTTONDOWN; | |
508 break; | |
509 case SDL_RELEASED: | |
510 event.type = SDL_JOYBUTTONUP; | |
511 break; | |
512 default: | |
513 /* Invalid state -- bail */ | |
514 return(0); | |
515 } | |
516 #endif /* !DISABLE_EVENTS */ | |
517 | |
518 /* Update internal joystick state */ | |
519 joystick->buttons[button] = state; | |
520 | |
521 /* Post the event, if desired */ | |
522 posted = 0; | |
523 #ifndef DISABLE_EVENTS | |
524 if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { | |
525 event.jbutton.which = joystick->index; | |
526 event.jbutton.button = button; | |
527 event.jbutton.state = state; | |
528 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | |
529 posted = 1; | |
530 SDL_PushEvent(&event); | |
531 } | |
532 } | |
533 #endif /* !DISABLE_EVENTS */ | |
534 return(posted); | |
535 } | |
536 | |
537 void SDL_JoystickUpdate(void) | |
538 { | |
539 int i; | |
540 | |
541 for ( i=0; SDL_joysticks[i]; ++i ) { | |
542 SDL_SYS_JoystickUpdate(SDL_joysticks[i]); | |
543 } | |
544 } | |
545 | |
546 int SDL_JoystickEventState(int state) | |
547 { | |
548 #ifdef DISABLE_EVENTS | |
549 return SDL_IGNORE; | |
550 #else | |
551 const Uint8 event_list[] = { | |
552 SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, | |
553 SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, | |
554 }; | |
555 int i; | |
556 | |
557 switch (state) { | |
558 case SDL_QUERY: | |
559 state = SDL_IGNORE; | |
560 for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) { | |
561 state = SDL_EventState(event_list[i],SDL_QUERY); | |
562 if ( state == SDL_ENABLE ) { | |
563 break; | |
564 } | |
565 } | |
566 break; | |
567 default: | |
568 for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) { | |
569 SDL_EventState(event_list[i], state); | |
570 } | |
571 break; | |
572 } | |
573 return(state); | |
574 #endif /* DISABLE_EVENTS */ | |
575 } |