pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / plugins / DFInput / SDL / src / joystick / SDL_joystick.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2010 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 /* This is the joystick API for Simple DirectMedia Layer */
25 #include "SDL.h"
26 #include "SDL_sysjoystick.h"
27 #include "SDL_joystick_c.h"
28
29 /* This is used for Quake III Arena */
30 #define SDL_Lock_EventThread()
31 #define SDL_Unlock_EventThread()
32
33 Uint8 SDL_numjoysticks = 0;
34 SDL_Joystick **SDL_joysticks = NULL;
35 static SDL_Joystick *default_joystick = NULL;
36
37 int
38 SDL_JoystickInit(void)
39 {
40     int arraylen;
41     int status;
42
43     SDL_numjoysticks = 0;
44     status = SDL_SYS_JoystickInit();
45     if (status >= 0) {
46         arraylen = (status + 1) * sizeof(*SDL_joysticks);
47         SDL_joysticks = (SDL_Joystick **) SDL_malloc(arraylen);
48         if (SDL_joysticks == NULL) {
49             SDL_numjoysticks = 0;
50         } else {
51             SDL_memset(SDL_joysticks, 0, arraylen);
52             SDL_numjoysticks = status;
53         }
54         status = 0;
55     }
56     default_joystick = NULL;
57     return (status);
58 }
59
60 /*
61  * Count the number of joysticks attached to the system
62  */
63 int
64 SDL_NumJoysticks(void)
65 {
66     return SDL_numjoysticks;
67 }
68
69 /*
70  * Get the implementation dependent name of a joystick
71  */
72 const char *
73 SDL_JoystickName(int device_index)
74 {
75     if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
76         SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
77         return (NULL);
78     }
79     return (SDL_SYS_JoystickName(device_index));
80 }
81
82 /*
83  * Open a joystick for use - the index passed as an argument refers to
84  * the N'th joystick on the system.  This index is the value which will
85  * identify this joystick in future joystick events.
86  *
87  * This function returns a joystick identifier, or NULL if an error occurred.
88  */
89 SDL_Joystick *
90 SDL_JoystickOpen(int device_index)
91 {
92     int i;
93     SDL_Joystick *joystick;
94
95     if ((device_index < 0) || (device_index >= SDL_numjoysticks)) {
96         SDL_SetError("There are %d joysticks available", SDL_numjoysticks);
97         return (NULL);
98     }
99
100     /* If the joystick is already open, return it */
101     for (i = 0; SDL_joysticks[i]; ++i) {
102         if (device_index == SDL_joysticks[i]->index) {
103             joystick = SDL_joysticks[i];
104             ++joystick->ref_count;
105             return (joystick);
106         }
107     }
108
109     /* Create and initialize the joystick */
110     joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick));
111     if (joystick == NULL) {
112         SDL_OutOfMemory();
113         return NULL;
114     }
115
116     SDL_memset(joystick, 0, (sizeof *joystick));
117     joystick->index = device_index;
118     if (SDL_SYS_JoystickOpen(joystick) < 0) {
119         SDL_free(joystick);
120         return NULL;
121     }
122     if (joystick->naxes > 0) {
123         joystick->axes = (Sint16 *) SDL_malloc
124             (joystick->naxes * sizeof(Sint16));
125     }
126     if (joystick->nhats > 0) {
127         joystick->hats = (Uint8 *) SDL_malloc
128             (joystick->nhats * sizeof(Uint8));
129     }
130     if (joystick->nballs > 0) {
131         joystick->balls = (struct balldelta *) SDL_malloc
132             (joystick->nballs * sizeof(*joystick->balls));
133     }
134     if (joystick->nbuttons > 0) {
135         joystick->buttons = (Uint8 *) SDL_malloc
136             (joystick->nbuttons * sizeof(Uint8));
137     }
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)) {
142         SDL_OutOfMemory();
143         SDL_JoystickClose(joystick);
144         return NULL;
145     }
146     if (joystick->axes) {
147         SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
148     }
149     if (joystick->hats) {
150         SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
151     }
152     if (joystick->balls) {
153         SDL_memset(joystick->balls, 0,
154             joystick->nballs * sizeof(*joystick->balls));
155     }
156     if (joystick->buttons) {
157         SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8));
158     }
159
160     /* Add joystick to list */
161     ++joystick->ref_count;
162     SDL_Lock_EventThread();
163     for (i = 0; SDL_joysticks[i]; ++i)
164         /* Skip to next joystick */ ;
165     SDL_joysticks[i] = joystick;
166     SDL_Unlock_EventThread();
167
168     return (joystick);
169 }
170
171 /*
172  * Returns 1 if the joystick has been opened, or 0 if it has not.
173  */
174 int
175 SDL_JoystickOpened(int device_index)
176 {
177     int i, opened;
178
179     opened = 0;
180     for (i = 0; SDL_joysticks[i]; ++i) {
181         if (SDL_joysticks[i]->index == (Uint8) device_index) {
182             opened = 1;
183             break;
184         }
185     }
186     return (opened);
187 }
188
189
190 /*
191  * Checks to make sure the joystick is valid.
192  */
193 int
194 SDL_PrivateJoystickValid(SDL_Joystick ** joystick)
195 {
196     int valid;
197
198     if (*joystick == NULL) {
199         *joystick = default_joystick;
200     }
201     if (*joystick == NULL) {
202         SDL_SetError("Joystick hasn't been opened yet");
203         valid = 0;
204     } else {
205         valid = 1;
206     }
207     return valid;
208 }
209
210 /*
211  * Get the device index of an opened joystick.
212  */
213 int
214 SDL_JoystickIndex(SDL_Joystick * joystick)
215 {
216     if (!SDL_PrivateJoystickValid(&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
226 SDL_JoystickNumAxes(SDL_Joystick * joystick)
227 {
228     if (!SDL_PrivateJoystickValid(&joystick)) {
229         return (-1);
230     }
231     return (joystick->naxes);
232 }
233
234 /*
235  * Get the number of hats on a joystick
236  */
237 int
238 SDL_JoystickNumHats(SDL_Joystick * joystick)
239 {
240     if (!SDL_PrivateJoystickValid(&joystick)) {
241         return (-1);
242     }
243     return (joystick->nhats);
244 }
245
246 /*
247  * Get the number of trackballs on a joystick
248  */
249 int
250 SDL_JoystickNumBalls(SDL_Joystick * joystick)
251 {
252     if (!SDL_PrivateJoystickValid(&joystick)) {
253         return (-1);
254     }
255     return (joystick->nballs);
256 }
257
258 /*
259  * Get the number of buttons on a joystick
260  */
261 int
262 SDL_JoystickNumButtons(SDL_Joystick * joystick)
263 {
264     if (!SDL_PrivateJoystickValid(&joystick)) {
265         return (-1);
266     }
267     return (joystick->nbuttons);
268 }
269
270 /*
271  * Get the current state of an axis control on a joystick
272  */
273 Sint16
274 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
275 {
276     Sint16 state;
277
278     if (!SDL_PrivateJoystickValid(&joystick)) {
279         return (0);
280     }
281     if (axis < joystick->naxes) {
282         state = joystick->axes[axis];
283     } else {
284         SDL_SetError("Joystick only has %d axes", joystick->naxes);
285         state = 0;
286     }
287     return (state);
288 }
289
290 /*
291  * Get the current state of a hat on a joystick
292  */
293 Uint8
294 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
295 {
296     Uint8 state;
297
298     if (!SDL_PrivateJoystickValid(&joystick)) {
299         return (0);
300     }
301     if (hat < joystick->nhats) {
302         state = joystick->hats[hat];
303     } else {
304         SDL_SetError("Joystick only has %d hats", joystick->nhats);
305         state = 0;
306     }
307     return (state);
308 }
309
310 /*
311  * Get the ball axis change since the last poll
312  */
313 int
314 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
315 {
316     int retval;
317
318     if (!SDL_PrivateJoystickValid(&joystick)) {
319         return (-1);
320     }
321
322     retval = 0;
323     if (ball < joystick->nballs) {
324         if (dx) {
325             *dx = joystick->balls[ball].dx;
326         }
327         if (dy) {
328             *dy = joystick->balls[ball].dy;
329         }
330         joystick->balls[ball].dx = 0;
331         joystick->balls[ball].dy = 0;
332     } else {
333         SDL_SetError("Joystick only has %d balls", joystick->nballs);
334         retval = -1;
335     }
336     return (retval);
337 }
338
339 /*
340  * Get the current state of a button on a joystick
341  */
342 Uint8
343 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
344 {
345     Uint8 state;
346
347     if (!SDL_PrivateJoystickValid(&joystick)) {
348         return (0);
349     }
350     if (button < joystick->nbuttons) {
351         state = joystick->buttons[button];
352     } else {
353         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
354         state = 0;
355     }
356     return (state);
357 }
358
359 /*
360  * Close a joystick previously opened with SDL_JoystickOpen()
361  */
362 void
363 SDL_JoystickClose(SDL_Joystick * joystick)
364 {
365     int i;
366
367     if (!SDL_PrivateJoystickValid(&joystick)) {
368         return;
369     }
370
371     /* First decrement ref count */
372     if (--joystick->ref_count > 0) {
373         return;
374     }
375
376     /* Lock the event queue - prevent joystick polling */
377     SDL_Lock_EventThread();
378
379     if (joystick == default_joystick) {
380         default_joystick = NULL;
381     }
382     SDL_SYS_JoystickClose(joystick);
383
384     /* Remove joystick from list */
385     for (i = 0; SDL_joysticks[i]; ++i) {
386         if (joystick == SDL_joysticks[i]) {
387             SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1],
388                         (SDL_numjoysticks - i) * sizeof(joystick));
389             break;
390         }
391     }
392
393     /* Let the event thread keep running */
394     SDL_Unlock_EventThread();
395
396     /* Free the data associated with this joystick */
397     if (joystick->axes) {
398         SDL_free(joystick->axes);
399     }
400     if (joystick->hats) {
401         SDL_free(joystick->hats);
402     }
403     if (joystick->balls) {
404         SDL_free(joystick->balls);
405     }
406     if (joystick->buttons) {
407         SDL_free(joystick->buttons);
408     }
409     SDL_free(joystick);
410 }
411
412 void
413 SDL_JoystickQuit(void)
414 {
415     /* Stop the event polling */
416     SDL_Lock_EventThread();
417     SDL_numjoysticks = 0;
418     SDL_Unlock_EventThread();
419
420     /* Quit the joystick setup */
421     SDL_SYS_JoystickQuit();
422     if (SDL_joysticks) {
423         SDL_free(SDL_joysticks);
424         SDL_joysticks = NULL;
425     }
426 }
427
428
429 /* These are global for SDL_sysjoystick.c and SDL_events.c */
430
431 int
432 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
433 {
434     int posted;
435
436     /* Update internal joystick state */
437     joystick->axes[axis] = value;
438
439     /* Post the event, if desired */
440     posted = 0;
441
442     return (posted);
443 }
444
445 int
446 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
456     return (posted);
457 }
458
459 int
460 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
461                         Sint16 xrel, Sint16 yrel)
462 {
463     int posted;
464
465     /* Update internal mouse state */
466     joystick->balls[ball].dx += xrel;
467     joystick->balls[ball].dy += yrel;
468
469     /* Post the event, if desired */
470     posted = 0;
471
472     return (posted);
473 }
474
475 int
476 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
477 {
478     int posted;
479
480     /* Update internal joystick state */
481     joystick->buttons[button] = state;
482
483     /* Post the event, if desired */
484     posted = 0;
485
486     return (posted);
487 }
488
489 void
490 SDL_JoystickUpdate(void)
491 {
492     int i;
493
494     for (i = 0; SDL_joysticks[i]; ++i) {
495         SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
496     }
497 }
498
499 int
500 SDL_JoystickEventState(int state)
501 {
502     return SDL_IGNORE;
503 }