src/joystick/SDL_joystick.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 08 Feb 2011 16:50:51 -0800
changeset 5229 c015d3e63631
parent 5123 dc0dfdd58f27
child 5262 b530ef003506
permissions -rw-r--r--
Fixed setting the texture unit, still doesn't work.
     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 
    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"
    31 #endif
    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     for (i = 0; SDL_joysticks[i]; ++i)
   163         /* Skip to next joystick */ ;
   164     SDL_joysticks[i] = joystick;
   165 
   166     return (joystick);
   167 }
   168 
   169 /*
   170  * Returns 1 if the joystick has been opened, or 0 if it has not.
   171  */
   172 int
   173 SDL_JoystickOpened(int device_index)
   174 {
   175     int i, opened;
   176 
   177     opened = 0;
   178     for (i = 0; SDL_joysticks[i]; ++i) {
   179         if (SDL_joysticks[i]->index == (Uint8) device_index) {
   180             opened = 1;
   181             break;
   182         }
   183     }
   184     return (opened);
   185 }
   186 
   187 
   188 /*
   189  * Checks to make sure the joystick is valid.
   190  */
   191 int
   192 SDL_PrivateJoystickValid(SDL_Joystick ** joystick)
   193 {
   194     int valid;
   195 
   196     if (*joystick == NULL) {
   197         *joystick = default_joystick;
   198     }
   199     if (*joystick == NULL) {
   200         SDL_SetError("Joystick hasn't been opened yet");
   201         valid = 0;
   202     } else {
   203         valid = 1;
   204     }
   205     return valid;
   206 }
   207 
   208 /*
   209  * Get the device index of an opened joystick.
   210  */
   211 int
   212 SDL_JoystickIndex(SDL_Joystick * joystick)
   213 {
   214     if (!SDL_PrivateJoystickValid(&joystick)) {
   215         return (-1);
   216     }
   217     return (joystick->index);
   218 }
   219 
   220 /*
   221  * Get the number of multi-dimensional axis controls on a joystick
   222  */
   223 int
   224 SDL_JoystickNumAxes(SDL_Joystick * joystick)
   225 {
   226     if (!SDL_PrivateJoystickValid(&joystick)) {
   227         return (-1);
   228     }
   229     return (joystick->naxes);
   230 }
   231 
   232 /*
   233  * Get the number of hats on a joystick
   234  */
   235 int
   236 SDL_JoystickNumHats(SDL_Joystick * joystick)
   237 {
   238     if (!SDL_PrivateJoystickValid(&joystick)) {
   239         return (-1);
   240     }
   241     return (joystick->nhats);
   242 }
   243 
   244 /*
   245  * Get the number of trackballs on a joystick
   246  */
   247 int
   248 SDL_JoystickNumBalls(SDL_Joystick * joystick)
   249 {
   250     if (!SDL_PrivateJoystickValid(&joystick)) {
   251         return (-1);
   252     }
   253     return (joystick->nballs);
   254 }
   255 
   256 /*
   257  * Get the number of buttons on a joystick
   258  */
   259 int
   260 SDL_JoystickNumButtons(SDL_Joystick * joystick)
   261 {
   262     if (!SDL_PrivateJoystickValid(&joystick)) {
   263         return (-1);
   264     }
   265     return (joystick->nbuttons);
   266 }
   267 
   268 /*
   269  * Get the current state of an axis control on a joystick
   270  */
   271 Sint16
   272 SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis)
   273 {
   274     Sint16 state;
   275 
   276     if (!SDL_PrivateJoystickValid(&joystick)) {
   277         return (0);
   278     }
   279     if (axis < joystick->naxes) {
   280         state = joystick->axes[axis];
   281     } else {
   282         SDL_SetError("Joystick only has %d axes", joystick->naxes);
   283         state = 0;
   284     }
   285     return (state);
   286 }
   287 
   288 /*
   289  * Get the current state of a hat on a joystick
   290  */
   291 Uint8
   292 SDL_JoystickGetHat(SDL_Joystick * joystick, int hat)
   293 {
   294     Uint8 state;
   295 
   296     if (!SDL_PrivateJoystickValid(&joystick)) {
   297         return (0);
   298     }
   299     if (hat < joystick->nhats) {
   300         state = joystick->hats[hat];
   301     } else {
   302         SDL_SetError("Joystick only has %d hats", joystick->nhats);
   303         state = 0;
   304     }
   305     return (state);
   306 }
   307 
   308 /*
   309  * Get the ball axis change since the last poll
   310  */
   311 int
   312 SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy)
   313 {
   314     int retval;
   315 
   316     if (!SDL_PrivateJoystickValid(&joystick)) {
   317         return (-1);
   318     }
   319 
   320     retval = 0;
   321     if (ball < joystick->nballs) {
   322         if (dx) {
   323             *dx = joystick->balls[ball].dx;
   324         }
   325         if (dy) {
   326             *dy = joystick->balls[ball].dy;
   327         }
   328         joystick->balls[ball].dx = 0;
   329         joystick->balls[ball].dy = 0;
   330     } else {
   331         SDL_SetError("Joystick only has %d balls", joystick->nballs);
   332         retval = -1;
   333     }
   334     return (retval);
   335 }
   336 
   337 /*
   338  * Get the current state of a button on a joystick
   339  */
   340 Uint8
   341 SDL_JoystickGetButton(SDL_Joystick * joystick, int button)
   342 {
   343     Uint8 state;
   344 
   345     if (!SDL_PrivateJoystickValid(&joystick)) {
   346         return (0);
   347     }
   348     if (button < joystick->nbuttons) {
   349         state = joystick->buttons[button];
   350     } else {
   351         SDL_SetError("Joystick only has %d buttons", joystick->nbuttons);
   352         state = 0;
   353     }
   354     return (state);
   355 }
   356 
   357 /*
   358  * Close a joystick previously opened with SDL_JoystickOpen()
   359  */
   360 void
   361 SDL_JoystickClose(SDL_Joystick * joystick)
   362 {
   363     int i;
   364 
   365     if (!SDL_PrivateJoystickValid(&joystick)) {
   366         return;
   367     }
   368 
   369     /* First decrement ref count */
   370     if (--joystick->ref_count > 0) {
   371         return;
   372     }
   373 
   374     if (joystick == default_joystick) {
   375         default_joystick = NULL;
   376     }
   377     SDL_SYS_JoystickClose(joystick);
   378 
   379     /* Remove joystick from list */
   380     for (i = 0; SDL_joysticks[i]; ++i) {
   381         if (joystick == SDL_joysticks[i]) {
   382             SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i + 1],
   383                         (SDL_numjoysticks - i) * sizeof(joystick));
   384             break;
   385         }
   386     }
   387 
   388     /* Free the data associated with this joystick */
   389     if (joystick->axes) {
   390         SDL_free(joystick->axes);
   391     }
   392     if (joystick->hats) {
   393         SDL_free(joystick->hats);
   394     }
   395     if (joystick->balls) {
   396         SDL_free(joystick->balls);
   397     }
   398     if (joystick->buttons) {
   399         SDL_free(joystick->buttons);
   400     }
   401     SDL_free(joystick);
   402 }
   403 
   404 void
   405 SDL_JoystickQuit(void)
   406 {
   407     /* Stop the event polling */
   408     SDL_numjoysticks = 0;
   409 
   410     /* Quit the joystick setup */
   411     SDL_SYS_JoystickQuit();
   412     if (SDL_joysticks) {
   413         SDL_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
   422 SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
   423 {
   424     int posted;
   425 
   426     /* Update internal joystick state */
   427     joystick->axes[axis] = value;
   428 
   429     /* Post the event, if desired */
   430     posted = 0;
   431 #if !SDL_EVENTS_DISABLED
   432     if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
   433         SDL_Event event;
   434         event.type = SDL_JOYAXISMOTION;
   435         event.jaxis.which = joystick->index;
   436         event.jaxis.axis = axis;
   437         event.jaxis.value = value;
   438         if ((SDL_EventOK == NULL)
   439             || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
   440             posted = 1;
   441             SDL_PushEvent(&event);
   442         }
   443     }
   444 #endif /* !SDL_EVENTS_DISABLED */
   445     return (posted);
   446 }
   447 
   448 int
   449 SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
   450 {
   451     int posted;
   452 
   453     /* Update internal joystick state */
   454     joystick->hats[hat] = value;
   455 
   456     /* Post the event, if desired */
   457     posted = 0;
   458 #if !SDL_EVENTS_DISABLED
   459     if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) {
   460         SDL_Event event;
   461         event.jhat.type = SDL_JOYHATMOTION;
   462         event.jhat.which = joystick->index;
   463         event.jhat.hat = hat;
   464         event.jhat.value = value;
   465         if ((SDL_EventOK == NULL)
   466             || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
   467             posted = 1;
   468             SDL_PushEvent(&event);
   469         }
   470     }
   471 #endif /* !SDL_EVENTS_DISABLED */
   472     return (posted);
   473 }
   474 
   475 int
   476 SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball,
   477                         Sint16 xrel, Sint16 yrel)
   478 {
   479     int posted;
   480 
   481     /* Update internal mouse state */
   482     joystick->balls[ball].dx += xrel;
   483     joystick->balls[ball].dy += yrel;
   484 
   485     /* Post the event, if desired */
   486     posted = 0;
   487 #if !SDL_EVENTS_DISABLED
   488     if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) {
   489         SDL_Event event;
   490         event.jball.type = SDL_JOYBALLMOTION;
   491         event.jball.which = joystick->index;
   492         event.jball.ball = ball;
   493         event.jball.xrel = xrel;
   494         event.jball.yrel = yrel;
   495         if ((SDL_EventOK == NULL)
   496             || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
   497             posted = 1;
   498             SDL_PushEvent(&event);
   499         }
   500     }
   501 #endif /* !SDL_EVENTS_DISABLED */
   502     return (posted);
   503 }
   504 
   505 int
   506 SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
   507 {
   508     int posted;
   509 #if !SDL_EVENTS_DISABLED
   510     SDL_Event event;
   511 
   512     switch (state) {
   513     case SDL_PRESSED:
   514         event.type = SDL_JOYBUTTONDOWN;
   515         break;
   516     case SDL_RELEASED:
   517         event.type = SDL_JOYBUTTONUP;
   518         break;
   519     default:
   520         /* Invalid state -- bail */
   521         return (0);
   522     }
   523 #endif /* !SDL_EVENTS_DISABLED */
   524 
   525     /* Update internal joystick state */
   526     joystick->buttons[button] = state;
   527 
   528     /* Post the event, if desired */
   529     posted = 0;
   530 #if !SDL_EVENTS_DISABLED
   531     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   532         event.jbutton.which = joystick->index;
   533         event.jbutton.button = button;
   534         event.jbutton.state = state;
   535         if ((SDL_EventOK == NULL)
   536             || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
   537             posted = 1;
   538             SDL_PushEvent(&event);
   539         }
   540     }
   541 #endif /* !SDL_EVENTS_DISABLED */
   542     return (posted);
   543 }
   544 
   545 void
   546 SDL_JoystickUpdate(void)
   547 {
   548     int i;
   549 
   550     for (i = 0; SDL_joysticks[i]; ++i) {
   551         SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
   552     }
   553 }
   554 
   555 int
   556 SDL_JoystickEventState(int state)
   557 {
   558 #if SDL_EVENTS_DISABLED
   559     return SDL_IGNORE;
   560 #else
   561     const Uint32 event_list[] = {
   562         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
   563         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP,
   564     };
   565     unsigned int i;
   566 
   567     switch (state) {
   568     case SDL_QUERY:
   569         state = SDL_IGNORE;
   570         for (i = 0; i < SDL_arraysize(event_list); ++i) {
   571             state = SDL_EventState(event_list[i], SDL_QUERY);
   572             if (state == SDL_ENABLE) {
   573                 break;
   574             }
   575         }
   576         break;
   577     default:
   578         for (i = 0; i < SDL_arraysize(event_list); ++i) {
   579             SDL_EventState(event_list[i], state);
   580         }
   581         break;
   582     }
   583     return (state);
   584 #endif /* SDL_EVENTS_DISABLED */
   585 }
   586 
   587 /* vi: set ts=4 sw=4 expandtab: */