2 Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "SDL_config.h"
23 /* This is the joystick API for Simple DirectMedia Layer */
25 #include "SDL_events.h"
26 #include "SDL_sysjoystick.h"
27 #include "SDL_joystick_c.h"
28 #include "SDL_assert.h"
30 #if !SDL_EVENTS_DISABLED
31 #include "../events/SDL_events_c.h"
34 Uint8 SDL_numjoysticks = 0;
35 SDL_Joystick **SDL_joysticks = NULL;
38 SDL_JoystickInit(void)
44 status = SDL_SYS_JoystickInit();
46 arraylen = (status + 1) * sizeof(*SDL_joysticks);
47 SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen);
48 if (SDL_joysticks == NULL) {
51 SDL_memset(SDL_joysticks, 0, arraylen);
52 SDL_numjoysticks = status;
60 * Count the number of joysticks attached to the system
63 SDL_NumJoysticks(void)
65 return SDL_numjoysticks;
69 * Get the implementation dependent name of a joystick
72 SDL_JoystickName(int device_index)
74 if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
75 SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
78 return (SDL_SYS_JoystickName(device_index));
82 * Open a joystick for use - the index passed as an argument refers to
83 * the N'th joystick on the system. This index is the value which will
84 * identify this joystick in future joystick events.
86 * This function returns a joystick identifier, or NULL if an error occurred.
89 SDL_JoystickOpen(int device_index)
92 SDL_Joystick *joystick;
94 if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
95 SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
99 /* If the joystick is already open, return it */
100 for (i = 0; SDL_joysticks[i]; ++i) {
101 if (device_index == SDL_joysticks[i]->index) {
102 joystick = SDL_joysticks[i];
103 ++joystick->ref_count;
108 /* Create and initialize the joystick */
109 joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
110 if (joystick == NULL) {
115 SDL_memset(joystick, 0, (sizeof *joystick));
116 joystick->index = device_index;
117 if (SDL_SYS_JoystickOpen(joystick) < 0) {
121 if (joystick->naxes > 0) {
122 joystick->axes = (Sint16 *) SDL_malloc
123 (joystick->naxes * sizeof(Sint16));
125 if (joystick->nhats > 0) {
126 joystick->hats = (Uint8 *) SDL_malloc
127 (joystick->nhats * sizeof(Uint8));
129 if (joystick->nballs > 0) {
130 joystick->balls = (struct balldelta *) SDL_malloc
131 (joystick->nballs * sizeof(*joystick->balls));
133 if (joystick->nbuttons > 0) {
134 joystick->buttons = (Uint8 *) SDL_malloc
135 (joystick->nbuttons * sizeof(Uint8));
137 if (((joystick->naxes > 0) && !joystick->axes)
138 || ((joystick->nhats > 0) && !joystick->hats)
139 || ((joystick->nballs > 0) && !joystick->balls)
140 || ((joystick->nbuttons > 0) && !joystick->buttons)) {
142 SDL_JoystickClose(joystick);
145 if (joystick->axes) {
146 SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
148 if (joystick->hats) {
149 SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
151 if (joystick->balls) {
152 SDL_memset(joystick->balls, 0,
153 joystick->nballs * sizeof(*joystick->balls));
155 if (joystick->buttons) {
156 SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
159 /* Add joystick to list */
160 ++joystick->ref_count;
161 for (i = 0; SDL_joysticks[i]; ++i)
162 /* Skip to next joystick */ ;
163 SDL_joysticks[i] = joystick;
169 * Returns 1 if the joystick has been opened, or 0 if it has not.
172 SDL_JoystickOpened(int device_index)
177 for (i = 0; SDL_joysticks[i]; ++i) {
178 if (SDL_joysticks[i]->index == (Uint8) device_index) {
188 * Checks to make sure the joystick is valid.
191 SDL_PrivateJoystickValid(SDL_Joystick ** joystick)
195 if (*joystick == NULL) {
196 SDL_SetError("Joystick hasn't been opened yet");
205 * Get the device index of an opened joystick.
208 SDL_JoystickIndex(SDL_Joystick * joystick)
210 if (!SDL_PrivateJoystickValid(&joystick)) {
213 return (joystick->index);
217 * Get the number of multi-dimensional axis controls on a joystick
220 SDL_JoystickNumAxes(SDL_Joystick * joystick)
222 if (!SDL_PrivateJoystickValid(&joystick)) {
225 return (joystick->naxes);
229 * Get the number of hats on a joystick
232 SDL_JoystickNumHats(SDL_Joystick * joystick)
234 if (!SDL_PrivateJoystickValid(&joystick)) {
237 return (joystick->nhats);
241 * Get the number of trackballs on a joystick
244 SDL_JoystickNumBalls(SDL_Joystick * joystick)
246 if (!SDL_PrivateJoystickValid(&joystick)) {
249 return (joystick->nballs);
253 * Get the number of buttons on a joystick
256 SDL_JoystickNumButtons(SDL_Joystick * joystick)
258 if (!SDL_PrivateJoystickValid(&joystick)) {
261 return (joystick->nbuttons);
265 * Get the current state of an axis control on a joystick
268 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
272 if (!SDL_PrivateJoystickValid(&joystick)) {
275 if (axis < joystick->naxes) {
276 state = joystick->axes[axis];
278 SDL_SetError("Joystick only has %d axes", joystick->naxes);
285 * Get the current state of a hat on a joystick
288 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
292 if (!SDL_PrivateJoystickValid(&joystick)) {
295 if (hat < joystick->nhats) {
296 state = joystick->hats[hat];
298 SDL_SetError("Joystick only has %d hats", joystick->nhats);
305 * Get the ball axis change since the last poll
308 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
312 if (!SDL_PrivateJoystickValid(&joystick)) {
317 if (ball < joystick->nballs) {
319 *dx = joystick->balls[ball].dx;
322 *dy = joystick->balls[ball].dy;
324 joystick->balls[ball].dx = 0;
325 joystick->balls[ball].dy = 0;
327 SDL_SetError("Joystick only has %d balls", joystick->nballs);
334 * Get the current state of a button on a joystick
337 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
341 if (!SDL_PrivateJoystickValid(&joystick)) {
344 if (button < joystick->nbuttons) {
345 state = joystick->buttons[button];
347 SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
354 * Close a joystick previously opened with SDL_JoystickOpen()
357 SDL_JoystickClose(SDL_Joystick * joystick)
361 if (!SDL_PrivateJoystickValid(&joystick)) {
365 /* First decrement ref count */
366 if (--joystick->ref_count > 0) {
370 SDL_SYS_JoystickClose(joystick);
372 /* Remove joystick from list */
373 for (i = 0; SDL_joysticks[i]; ++i) {
374 if (joystick == SDL_joysticks[i]) {
375 SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1],
376 (SDL_numjoysticks - i) * sizeof(joystick));
381 /* Free the data associated with this joystick */
382 if (joystick->axes) {
383 SDL_free(joystick->axes);
385 if (joystick->hats) {
386 SDL_free(joystick->hats);
388 if (joystick->balls) {
389 SDL_free(joystick->balls);
391 if (joystick->buttons) {
392 SDL_free(joystick->buttons);
398 SDL_JoystickQuit(void)
400 const int numsticks = SDL_numjoysticks;
403 /* Stop the event polling */
404 SDL_numjoysticks = 0;
406 for (i = numsticks; i--; ) {
407 SDL_Joystick *stick = SDL_joysticks[i];
408 if (stick && (stick->ref_count >= 1)) {
409 stick->ref_count = 1;
410 SDL_JoystickClose(stick);
414 /* Quit the joystick setup */
415 SDL_SYS_JoystickQuit();
417 SDL_free(SDL_joysticks);
418 SDL_joysticks = NULL;
423 /* These are global for SDL_sysjoystick.c and SDL_events.c */
426 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
430 /* Make sure we're not getting garbage events */
431 if (axis >= joystick->naxes) {
435 /* Update internal joystick state */
436 joystick->axes[axis] = value;
438 /* Post the event, if desired */
440 #if !SDL_EVENTS_DISABLED
441 if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
443 event.type = SDL_JOYAXISMOTION;
444 event.jaxis.which = joystick->index;
445 event.jaxis.axis = axis;
446 event.jaxis.value = value;
447 if ((SDL_EventOK == NULL)
448 || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
450 SDL_PushEvent(&event);
453 #endif /* !SDL_EVENTS_DISABLED */
458 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
462 /* Make sure we're not getting garbage events */
463 if (hat >= joystick->nhats) {
467 /* Update internal joystick state */
468 joystick->hats[hat] = value;
470 /* Post the event, if desired */
472 #if !SDL_EVENTS_DISABLED
473 if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
475 event.jhat.type = SDL_JOYHATMOTION;
476 event.jhat.which = joystick->index;
477 event.jhat.hat = hat;
478 event.jhat.value = value;
479 if ((SDL_EventOK == NULL)
480 || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
482 SDL_PushEvent(&event);
485 #endif /* !SDL_EVENTS_DISABLED */
490 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
491 Sint16 xrel, Sint16 yrel)
495 /* Make sure we're not getting garbage events */
496 if (ball >= joystick->nballs) {
500 /* Update internal mouse state */
501 joystick->balls[ball].dx += xrel;
502 joystick->balls[ball].dy += yrel;
504 /* Post the event, if desired */
506 #if !SDL_EVENTS_DISABLED
507 if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
509 event.jball.type = SDL_JOYBALLMOTION;
510 event.jball.which = joystick->index;
511 event.jball.ball = ball;
512 event.jball.xrel = xrel;
513 event.jball.yrel = yrel;
514 if ((SDL_EventOK == NULL)
515 || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
517 SDL_PushEvent(&event);
520 #endif /* !SDL_EVENTS_DISABLED */
525 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
528 #if !SDL_EVENTS_DISABLED
533 event.type = SDL_JOYBUTTONDOWN;
536 event.type = SDL_JOYBUTTONUP;
539 /* Invalid state -- bail */
542 #endif /* !SDL_EVENTS_DISABLED */
544 /* Make sure we're not getting garbage events */
545 if (button >= joystick->nbuttons) {
549 /* Update internal joystick state */
550 joystick->buttons[button] = state;
552 /* Post the event, if desired */
554 #if !SDL_EVENTS_DISABLED
555 if (SDL_GetEventState(event.type) == SDL_ENABLE) {
556 event.jbutton.which = joystick->index;
557 event.jbutton.button = button;
558 event.jbutton.state = state;
559 if ((SDL_EventOK == NULL)
560 || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
562 SDL_PushEvent(&event);
565 #endif /* !SDL_EVENTS_DISABLED */
570 SDL_JoystickUpdate(void)
574 for (i = 0; SDL_joysticks[i]; ++i) {
575 SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
580 SDL_JoystickEventState(int state)
582 #if SDL_EVENTS_DISABLED
585 const Uint32 event_list[] = {
586 SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
587 SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP,
594 for (i = 0; i < SDL_arraysize(event_list); ++i) {
595 state = SDL_EventState(event_list[i], SDL_QUERY);
596 if (state == SDL_ENABLE) {
602 for (i = 0; i < SDL_arraysize(event_list); ++i) {
603 SDL_EventState(event_list[i], state);
608 #endif /* SDL_EVENTS_DISABLED */
611 /* vi: set ts=4 sw=4 expandtab: */