2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
24 /* This is the joystick API for Simple DirectMedia Layer */
26 #include "SDL_events.h"
27 #include "SDL_sysjoystick.h"
28 #include "SDL_joystick_c.h"
29 #if !SDL_EVENTS_DISABLED
30 #include "../events/SDL_events_c.h"
33 /* This is used for Quake III Arena */
34 #if SDL_EVENTS_DISABLED
35 #define SDL_Lock_EventThread()
36 #define SDL_Unlock_EventThread()
39 Uint8 SDL_numjoysticks
= 0;
40 SDL_Joystick
**SDL_joysticks
= NULL
;
41 static SDL_Joystick
*default_joystick
= NULL
;
43 int SDL_JoystickInit(void)
49 status
= SDL_SYS_JoystickInit();
51 arraylen
= (status
+1)*sizeof(*SDL_joysticks
);
52 SDL_joysticks
= (SDL_Joystick
**)SDL_malloc(arraylen
);
53 if ( SDL_joysticks
== NULL
) {
56 SDL_memset(SDL_joysticks
, 0, arraylen
);
57 SDL_numjoysticks
= status
;
61 default_joystick
= NULL
;
66 * Count the number of joysticks attached to the system
68 int SDL_NumJoysticks(void)
70 return SDL_numjoysticks
;
74 * Get the implementation dependent name of a joystick
76 const char *SDL_JoystickName(int device_index
)
78 if ( (device_index
< 0) || (device_index
>= SDL_numjoysticks
) ) {
79 SDL_SetError("There are %d joysticks available",
83 return(SDL_SYS_JoystickName(device_index
));
87 * Open a joystick for use - the index passed as an argument refers to
88 * the N'th joystick on the system. This index is the value which will
89 * identify this joystick in future joystick events.
91 * This function returns a joystick identifier, or NULL if an error occurred.
93 SDL_Joystick
*SDL_JoystickOpen(int device_index
)
96 SDL_Joystick
*joystick
;
98 if ( (device_index
< 0) || (device_index
>= SDL_numjoysticks
) ) {
99 SDL_SetError("There are %d joysticks available",
104 /* If the joystick is already open, return it */
105 for ( i
=0; SDL_joysticks
[i
]; ++i
) {
106 if ( device_index
== SDL_joysticks
[i
]->index
) {
107 joystick
= SDL_joysticks
[i
];
108 ++joystick
->ref_count
;
113 /* Create and initialize the joystick */
114 joystick
= (SDL_Joystick
*)SDL_malloc((sizeof *joystick
));
115 if ( joystick
!= NULL
) {
116 SDL_memset(joystick
, 0, (sizeof *joystick
));
117 joystick
->index
= device_index
;
118 if ( SDL_SYS_JoystickOpen(joystick
) < 0 ) {
122 if ( joystick
->naxes
> 0 ) {
123 joystick
->axes
= (Sint16
*)SDL_malloc
124 (joystick
->naxes
*sizeof(Sint16
));
126 if ( joystick
->nhats
> 0 ) {
127 joystick
->hats
= (Uint8
*)SDL_malloc
128 (joystick
->nhats
*sizeof(Uint8
));
130 if ( joystick
->nballs
> 0 ) {
131 joystick
->balls
= (struct balldelta
*)SDL_malloc
132 (joystick
->nballs
*sizeof(*joystick
->balls
));
134 if ( joystick
->nbuttons
> 0 ) {
135 joystick
->buttons
= (Uint8
*)SDL_malloc
136 (joystick
->nbuttons
*sizeof(Uint8
));
138 if ( ((joystick
->naxes
> 0) && !joystick
->axes
)
139 || ((joystick
->nhats
> 0) && !joystick
->hats
)
140 || ((joystick
->nballs
> 0) && !joystick
->balls
)
141 || ((joystick
->nbuttons
> 0) && !joystick
->buttons
)) {
143 SDL_JoystickClose(joystick
);
146 if ( joystick
->axes
) {
147 SDL_memset(joystick
->axes
, 0,
148 joystick
->naxes
*sizeof(Sint16
));
150 if ( joystick
->hats
) {
151 SDL_memset(joystick
->hats
, 0,
152 joystick
->nhats
*sizeof(Uint8
));
154 if ( joystick
->balls
) {
155 SDL_memset(joystick
->balls
, 0,
156 joystick
->nballs
*sizeof(*joystick
->balls
));
158 if ( joystick
->buttons
) {
159 SDL_memset(joystick
->buttons
, 0,
160 joystick
->nbuttons
*sizeof(Uint8
));
165 /* Add joystick to list */
166 ++joystick
->ref_count
;
167 SDL_Lock_EventThread();
168 for ( i
=0; SDL_joysticks
[i
]; ++i
)
169 /* Skip to next joystick */;
170 SDL_joysticks
[i
] = joystick
;
171 SDL_Unlock_EventThread();
177 * Returns 1 if the joystick has been opened, or 0 if it has not.
179 int SDL_JoystickOpened(int device_index
)
184 for ( i
=0; SDL_joysticks
[i
]; ++i
) {
185 if ( SDL_joysticks
[i
]->index
== (Uint8
)device_index
) {
193 static int ValidJoystick(SDL_Joystick
**joystick
)
197 if ( *joystick
== NULL
) {
198 *joystick
= default_joystick
;
200 if ( *joystick
== NULL
) {
201 SDL_SetError("Joystick hasn't been opened yet");
210 * Get the device index of an opened joystick.
212 int SDL_JoystickIndex(SDL_Joystick
*joystick
)
214 if ( ! ValidJoystick(&joystick
) ) {
217 return(joystick
->index
);
221 * Get the number of multi-dimensional axis controls on a joystick
223 int SDL_JoystickNumAxes(SDL_Joystick
*joystick
)
225 if ( ! ValidJoystick(&joystick
) ) {
228 return(joystick
->naxes
);
232 * Get the number of hats on a joystick
234 int SDL_JoystickNumHats(SDL_Joystick
*joystick
)
236 if ( ! ValidJoystick(&joystick
) ) {
239 return(joystick
->nhats
);
243 * Get the number of trackballs on a joystick
245 int SDL_JoystickNumBalls(SDL_Joystick
*joystick
)
247 if ( ! ValidJoystick(&joystick
) ) {
250 return(joystick
->nballs
);
254 * Get the number of buttons on a joystick
256 int SDL_JoystickNumButtons(SDL_Joystick
*joystick
)
258 if ( ! ValidJoystick(&joystick
) ) {
261 return(joystick
->nbuttons
);
265 * Get the current state of an axis control on a joystick
267 Sint16
SDL_JoystickGetAxis(SDL_Joystick
*joystick
, int axis
)
271 if ( ! ValidJoystick(&joystick
) ) {
274 if ( axis
< joystick
->naxes
) {
275 state
= joystick
->axes
[axis
];
277 SDL_SetError("Joystick only has %d axes", joystick
->naxes
);
284 * Get the current state of a hat on a joystick
286 Uint8
SDL_JoystickGetHat(SDL_Joystick
*joystick
, int hat
)
290 if ( ! ValidJoystick(&joystick
) ) {
293 if ( hat
< joystick
->nhats
) {
294 state
= joystick
->hats
[hat
];
296 SDL_SetError("Joystick only has %d hats", joystick
->nhats
);
303 * Get the ball axis change since the last poll
305 int SDL_JoystickGetBall(SDL_Joystick
*joystick
, int ball
, int *dx
, int *dy
)
309 if ( ! ValidJoystick(&joystick
) ) {
314 if ( ball
< joystick
->nballs
) {
316 *dx
= joystick
->balls
[ball
].dx
;
319 *dy
= joystick
->balls
[ball
].dy
;
321 joystick
->balls
[ball
].dx
= 0;
322 joystick
->balls
[ball
].dy
= 0;
324 SDL_SetError("Joystick only has %d balls", joystick
->nballs
);
331 * Get the current state of a button on a joystick
333 Uint8
SDL_JoystickGetButton(SDL_Joystick
*joystick
, int button
)
337 if ( ! ValidJoystick(&joystick
) ) {
340 if ( button
< joystick
->nbuttons
) {
341 state
= joystick
->buttons
[button
];
343 SDL_SetError("Joystick only has %d buttons",joystick
->nbuttons
);
350 * Close a joystick previously opened with SDL_JoystickOpen()
352 void SDL_JoystickClose(SDL_Joystick
*joystick
)
356 if ( ! ValidJoystick(&joystick
) ) {
360 /* First decrement ref count */
361 if ( --joystick
->ref_count
> 0 ) {
365 /* Lock the event queue - prevent joystick polling */
366 SDL_Lock_EventThread();
368 if ( joystick
== default_joystick
) {
369 default_joystick
= NULL
;
371 SDL_SYS_JoystickClose(joystick
);
373 /* Remove joystick from list */
374 for ( i
=0; SDL_joysticks
[i
]; ++i
) {
375 if ( joystick
== SDL_joysticks
[i
] ) {
376 SDL_memcpy(&SDL_joysticks
[i
], &SDL_joysticks
[i
+1],
377 (SDL_numjoysticks
-i
)*sizeof(joystick
));
382 /* Let the event thread keep running */
383 SDL_Unlock_EventThread();
385 /* Free the data associated with this joystick */
386 if ( joystick
->axes
) {
387 SDL_free(joystick
->axes
);
389 if ( joystick
->hats
) {
390 SDL_free(joystick
->hats
);
392 if ( joystick
->balls
) {
393 SDL_free(joystick
->balls
);
395 if ( joystick
->buttons
) {
396 SDL_free(joystick
->buttons
);
401 void SDL_JoystickQuit(void)
403 /* Stop the event polling */
404 SDL_Lock_EventThread();
405 SDL_numjoysticks
= 0;
406 SDL_Unlock_EventThread();
408 /* Quit the joystick setup */
409 SDL_SYS_JoystickQuit();
410 if ( SDL_joysticks
) {
411 SDL_free(SDL_joysticks
);
412 SDL_joysticks
= NULL
;
417 /* These are global for SDL_sysjoystick.c and SDL_events.c */
419 int SDL_PrivateJoystickAxis(SDL_Joystick
*joystick
, Uint8 axis
, Sint16 value
)
423 /* Update internal joystick state */
424 joystick
->axes
[axis
] = value
;
426 /* Post the event, if desired */
428 #if !SDL_EVENTS_DISABLED
429 if ( SDL_ProcessEvents
[SDL_JOYAXISMOTION
] == SDL_ENABLE
) {
431 event
.type
= SDL_JOYAXISMOTION
;
432 event
.jaxis
.which
= joystick
->index
;
433 event
.jaxis
.axis
= axis
;
434 event
.jaxis
.value
= value
;
435 if ( (SDL_EventOK
== NULL
) || (*SDL_EventOK
)(&event
) ) {
437 SDL_PushEvent(&event
);
440 #endif /* !SDL_EVENTS_DISABLED */
444 int SDL_PrivateJoystickHat(SDL_Joystick
*joystick
, Uint8 hat
, Uint8 value
)
448 /* Update internal joystick state */
449 joystick
->hats
[hat
] = value
;
451 /* Post the event, if desired */
453 #if !SDL_EVENTS_DISABLED
454 if ( SDL_ProcessEvents
[SDL_JOYHATMOTION
] == SDL_ENABLE
) {
456 event
.jhat
.type
= SDL_JOYHATMOTION
;
457 event
.jhat
.which
= joystick
->index
;
458 event
.jhat
.hat
= hat
;
459 event
.jhat
.value
= value
;
460 if ( (SDL_EventOK
== NULL
) || (*SDL_EventOK
)(&event
) ) {
462 SDL_PushEvent(&event
);
465 #endif /* !SDL_EVENTS_DISABLED */
469 int SDL_PrivateJoystickBall(SDL_Joystick
*joystick
, Uint8 ball
,
470 Sint16 xrel
, Sint16 yrel
)
474 /* Update internal mouse state */
475 joystick
->balls
[ball
].dx
+= xrel
;
476 joystick
->balls
[ball
].dy
+= yrel
;
478 /* Post the event, if desired */
480 #if !SDL_EVENTS_DISABLED
481 if ( SDL_ProcessEvents
[SDL_JOYBALLMOTION
] == SDL_ENABLE
) {
483 event
.jball
.type
= SDL_JOYBALLMOTION
;
484 event
.jball
.which
= joystick
->index
;
485 event
.jball
.ball
= ball
;
486 event
.jball
.xrel
= xrel
;
487 event
.jball
.yrel
= yrel
;
488 if ( (SDL_EventOK
== NULL
) || (*SDL_EventOK
)(&event
) ) {
490 SDL_PushEvent(&event
);
493 #endif /* !SDL_EVENTS_DISABLED */
497 int SDL_PrivateJoystickButton(SDL_Joystick
*joystick
, Uint8 button
, Uint8 state
)
500 #if !SDL_EVENTS_DISABLED
505 event
.type
= SDL_JOYBUTTONDOWN
;
508 event
.type
= SDL_JOYBUTTONUP
;
511 /* Invalid state -- bail */
514 #endif /* !SDL_EVENTS_DISABLED */
516 /* Update internal joystick state */
517 joystick
->buttons
[button
] = state
;
519 /* Post the event, if desired */
521 #if !SDL_EVENTS_DISABLED
522 if ( SDL_ProcessEvents
[event
.type
] == SDL_ENABLE
) {
523 event
.jbutton
.which
= joystick
->index
;
524 event
.jbutton
.button
= button
;
525 event
.jbutton
.state
= state
;
526 if ( (SDL_EventOK
== NULL
) || (*SDL_EventOK
)(&event
) ) {
528 SDL_PushEvent(&event
);
531 #endif /* !SDL_EVENTS_DISABLED */
535 void SDL_JoystickUpdate(void)
539 for ( i
=0; SDL_joysticks
[i
]; ++i
) {
540 SDL_SYS_JoystickUpdate(SDL_joysticks
[i
]);
544 int SDL_JoystickEventState(int state
)
546 #if SDL_EVENTS_DISABLED
549 const Uint8 event_list
[] = {
550 SDL_JOYAXISMOTION
, SDL_JOYBALLMOTION
, SDL_JOYHATMOTION
,
551 SDL_JOYBUTTONDOWN
, SDL_JOYBUTTONUP
,
558 for ( i
=0; i
<SDL_arraysize(event_list
); ++i
) {
559 state
= SDL_EventState(event_list
[i
],SDL_QUERY
);
560 if ( state
== SDL_ENABLE
) {
566 for ( i
=0; i
<SDL_arraysize(event_list
); ++i
) {
567 SDL_EventState(event_list
[i
], state
);
572 #endif /* SDL_EVENTS_DISABLED */