src/joystick/emscripten/SDL_sysjoystick.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Thu, 25 Dec 2014 22:03:07 +0100
changeset 9291 02b47b8164da
parent 9278 8900afb78a19
child 9300 0293f45e4814
permissions -rw-r--r--
Fixed compile warnings about unused variables.

Found by buildbot.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     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.
     8 
     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:
    12 
    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.
    20 */
    21 
    22 #include "../../SDL_internal.h"
    23 
    24 #ifdef SDL_JOYSTICK_EMSCRIPTEN
    25 
    26 #include <stdio.h>              /* For the definition of NULL */
    27 #include "SDL_error.h"
    28 #include "SDL_events.h"
    29 
    30 #if !SDL_EVENTS_DISABLED
    31 #include "../../events/SDL_events_c.h"
    32 #endif
    33 
    34 #include "SDL_joystick.h"
    35 #include "SDL_hints.h"
    36 #include "SDL_assert.h"
    37 #include "SDL_timer.h"
    38 #include "SDL_log.h"
    39 #include "SDL_sysjoystick_c.h"
    40 #include "../SDL_joystick_c.h"
    41 
    42 static SDL_joylist_item * JoystickByIndex(int index);
    43 
    44 static SDL_joylist_item *SDL_joylist = NULL;
    45 static SDL_joylist_item *SDL_joylist_tail = NULL;
    46 static int numjoysticks = 0;
    47 static int instance_counter = 0;
    48 
    49 int
    50 Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
    51 {
    52     int i;
    53 
    54     SDL_joylist_item *item;
    55 
    56     if (JoystickByIndex(gamepadEvent->index) != NULL) {
    57       return 1;
    58     }
    59 
    60 #if !SDL_EVENTS_DISABLED
    61     SDL_Event event;
    62 #endif
    63 
    64     item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
    65     if (item == NULL) {
    66         return 1;
    67     }
    68 
    69     SDL_zerop(item);
    70     item->index = gamepadEvent->index;
    71 
    72     item->name = SDL_strdup(gamepadEvent->id);
    73     if ( item->name == NULL ) {
    74         SDL_free(item);
    75         return 1;
    76     }
    77 
    78     item->mapping = SDL_strdup(gamepadEvent->mapping);
    79     if ( item->mapping == NULL ) {
    80         SDL_free(item->name);
    81         SDL_free(item);
    82         return 1;
    83     }
    84 
    85     item->naxes = gamepadEvent->numAxes;
    86     item->nbuttons = gamepadEvent->numButtons;
    87     item->device_instance = instance_counter++;
    88 
    89     item->timestamp = gamepadEvent->timestamp;
    90 
    91     for( i = 0; i < item->naxes; i++) {
    92         item->axis[i] = gamepadEvent->axis[i];
    93     }
    94 
    95     for( i = 0; i < item->nbuttons; i++) {
    96         item->analogButton[i] = gamepadEvent->analogButton[i];
    97         item->digitalButton[i] = gamepadEvent->digitalButton[i];
    98     }
    99 
   100     if (SDL_joylist_tail == NULL) {
   101         SDL_joylist = SDL_joylist_tail = item;
   102     } else {
   103         SDL_joylist_tail->next = item;
   104         SDL_joylist_tail = item;
   105     }
   106 
   107     ++numjoysticks;
   108     SDL_Log("%d",numjoysticks);
   109 #if !SDL_EVENTS_DISABLED
   110     event.type = SDL_JOYDEVICEADDED;
   111 
   112     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   113         event.jdevice.which = item->device_instance - 1;
   114         if ( (SDL_EventOK == NULL) ||
   115              (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
   116             SDL_PushEvent(&event);
   117         }
   118     }
   119 #endif /* !SDL_EVENTS_DISABLED */
   120 
   121     SDL_Log("Added joystick with index %d", item->index);
   122 
   123     return 1;
   124 }
   125 
   126 int
   127 Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
   128 {
   129     SDL_joylist_item *item = SDL_joylist;
   130     SDL_joylist_item *prev = NULL;
   131 #if !SDL_EVENTS_DISABLED
   132     SDL_Event event;
   133 #endif
   134 
   135     while (item != NULL) {
   136         if (item->index == gamepadEvent->index) {
   137             break;
   138         }
   139         prev = item;
   140         item = item->next;
   141     }
   142 
   143     if (item == NULL) {
   144         return 1;
   145     }
   146 
   147     const int retval = item->device_instance;
   148     if (item->joystick) {
   149         item->joystick->hwdata = NULL;
   150     }
   151 
   152     if (prev != NULL) {
   153         prev->next = item->next;
   154     } else {
   155         SDL_assert(SDL_joylist == item);
   156         SDL_joylist = item->next;
   157     }
   158     if (item == SDL_joylist_tail) {
   159         SDL_joylist_tail = prev;
   160     }
   161 
   162     /* Need to decrement the joystick count before we post the event */
   163     --numjoysticks;
   164 
   165 #if !SDL_EVENTS_DISABLED
   166     event.type = SDL_JOYDEVICEREMOVED;
   167 
   168     if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   169         event.jdevice.which = item->device_instance;
   170         if ( (SDL_EventOK == NULL) ||
   171              (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
   172             SDL_PushEvent(&event);
   173         }
   174     }
   175 #endif /* !SDL_EVENTS_DISABLED */
   176 
   177     SDL_Log("Removed joystick with index %d", retval);
   178     SDL_free(item->name);
   179     SDL_free(item->mapping);
   180     SDL_free(item);
   181     return 1;
   182 }
   183 
   184 /* Function to scan the system for joysticks.
   185  * It should return 0, or -1 on an unrecoverable fatal error.
   186  */
   187 int
   188 SDL_SYS_JoystickInit(void)
   189 {
   190     int retval, i, numjs;
   191     EmscriptenGamepadEvent gamepadState;
   192 
   193     numjoysticks = 0;
   194     numjs = emscripten_get_num_gamepads();
   195 
   196     /* Check if gamepad is supported by browser */
   197     if (numjs == EMSCRIPTEN_RESULT_NOT_SUPPORTED) {
   198         return -1;
   199     }
   200 
   201     /* handle already connected gamepads */
   202     if (numjs > 0) {
   203         for(i = 0; i < numjs; i++) {
   204             retval = emscripten_get_gamepad_status(i, &gamepadState);
   205             if (retval == EMSCRIPTEN_RESULT_SUCCESS) {
   206                 Emscripten_JoyStickConnected(EMSCRIPTEN_EVENT_GAMEPADCONNECTED,
   207                                              &gamepadState,
   208                                              NULL);
   209             }
   210         }
   211     }
   212 
   213     retval = emscripten_set_gamepadconnected_callback(NULL,
   214                                                       0,
   215                                                       Emscripten_JoyStickConnected);
   216 
   217     if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
   218         return -1;
   219     }
   220 
   221     retval = emscripten_set_gamepaddisconnected_callback(NULL,
   222                                                          0,
   223                                                          Emscripten_JoyStickDisconnected);
   224     if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
   225         return -1;
   226     }
   227 
   228     return 0;
   229 }
   230 
   231 static SDL_joylist_item *
   232 JoystickByIndex(int index)
   233 {
   234     SDL_joylist_item *item = SDL_joylist;
   235 
   236     if (index < 0) {
   237         return NULL;
   238     }
   239 
   240     while (item != NULL) {
   241         if (item->index == index) {
   242             break;
   243         }
   244         item = item->next;
   245     }
   246 
   247     return item;
   248 }
   249 
   250 int SDL_SYS_NumJoysticks()
   251 {
   252     return numjoysticks;
   253 }
   254 
   255 void SDL_SYS_JoystickDetect()
   256 {
   257 }
   258 
   259 // we need to poll to see if the gamepad state has changed
   260 SDL_bool SDL_SYS_JoystickNeedsPolling()
   261 {
   262     return SDL_TRUE;
   263 }
   264 
   265 /* Function to get the device-dependent name of a joystick */
   266 const char *
   267 SDL_SYS_JoystickNameForDeviceIndex(int index)
   268 {
   269     SDL_joylist_item *item = JoystickByIndex(index);
   270     if (item == NULL) {
   271         SDL_SetError("Joystick with index %d not found", index);
   272         return NULL;
   273     }
   274 
   275     return item->name;
   276 }
   277 
   278 /* Function to perform the mapping from device index to the instance id for this index */
   279 SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
   280 {
   281     SDL_joylist_item *item = JoystickByIndex(index);
   282     if (item == NULL) {
   283         SDL_SetError("Joystick with index %d not found", index);
   284         return NULL;
   285     }
   286 
   287     return item->device_instance;
   288 }
   289 
   290 /* Function to open a joystick for use.
   291    The joystick to open is specified by the index field of the joystick.
   292    This should fill the nbuttons and naxes fields of the joystick structure.
   293    It returns 0, or -1 if there is an error.
   294  */
   295 int
   296 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index)
   297 {
   298     SDL_joylist_item *item = JoystickByIndex(index);
   299 
   300     if (item == NULL ) {
   301         return SDL_SetError("No such device");
   302     }
   303 
   304     if (item->joystick != NULL) {
   305         return SDL_SetError("Joystick already opened");
   306     }
   307 
   308     joystick->instance_id = item->device_instance;
   309     joystick->hwdata = (struct joystick_hwdata *) item;
   310     item->joystick = joystick;
   311 
   312     /* HTML5 Gamepad API doesn't say anything about these */
   313     joystick->nhats = 0;
   314     joystick->nballs = 0;
   315 
   316     joystick->nbuttons = item->nbuttons;
   317     joystick->naxes = item->naxes;
   318 
   319     return (0);
   320 }
   321 
   322 /* Function to determine is this joystick is attached to the system right now */
   323 SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   324 {
   325     return !joystick->closed && (joystick->hwdata != NULL);
   326 }
   327 
   328 /* Function to update the state of a joystick - called as a device poll.
   329  * This function shouldn't update the joystick structure directly,
   330  * but instead should call SDL_PrivateJoystick*() to deliver events
   331  * and update joystick device state.
   332  */
   333 void
   334 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   335 {
   336     EmscriptenGamepadEvent gamepadState;
   337     SDL_joylist_item *item = SDL_joylist;
   338     int i, result, buttonState;
   339 
   340     while (item != NULL) {
   341         result = emscripten_get_gamepad_status(item->index, &gamepadState);
   342         if( result == EMSCRIPTEN_RESULT_SUCCESS) {
   343             if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
   344                 for(i = 0; i < item->nbuttons; i++) {
   345                     if(item->digitalButton[i] != gamepadState.digitalButton[i]) {
   346                         buttonState = gamepadState.digitalButton[i]? SDL_PRESSED: SDL_RELEASED;
   347                         SDL_PrivateJoystickButton(item->joystick, i, buttonState);
   348                     }
   349                 }
   350 
   351                 for(i = 0; i < item->naxes; i++) {
   352                     if(item->axis[i] != gamepadState.axis[i]) {
   353                         // do we need to do conversion?
   354                         SDL_PrivateJoystickAxis(item->joystick, i,
   355                                                   (Sint16) (32767.*gamepadState.axis[i]));
   356                     }
   357                 }
   358 
   359                 item->timestamp = gamepadState.timestamp;
   360                 for( i = 0; i < item->naxes; i++) {
   361                     item->axis[i] = gamepadState.axis[i];
   362                 }
   363 
   364                 for( i = 0; i < item->nbuttons; i++) {
   365                     item->analogButton[i] = gamepadState.analogButton[i];
   366                     item->digitalButton[i] = gamepadState.digitalButton[i];
   367                 }
   368             }
   369         }
   370         item = item->next;
   371     }
   372 }
   373 
   374 /* Function to close a joystick after use */
   375 void
   376 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   377 {
   378     if (joystick->hwdata) {
   379         ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
   380         joystick->hwdata = NULL;
   381     }
   382     joystick->closed = 1;
   383 }
   384 
   385 /* Function to perform any system-specific joystick related cleanup */
   386 void
   387 SDL_SYS_JoystickQuit(void)
   388 {
   389     SDL_joylist_item *item = NULL;
   390     SDL_joylist_item *next = NULL;
   391 
   392     for (item = SDL_joylist; item; item = next) {
   393         next = item->next;
   394         SDL_free(item->mapping);
   395         SDL_free(item->name);
   396         SDL_free(item);
   397     }
   398 
   399     SDL_joylist = SDL_joylist_tail = NULL;
   400 
   401     numjoysticks = 0;
   402     instance_counter = 0;
   403 }
   404 
   405 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index)
   406 {
   407     SDL_JoystickGUID guid;
   408     /* the GUID is just the first 16 chars of the name for now */
   409     const char *name = SDL_SYS_JoystickNameForDeviceIndex(index);
   410     SDL_zero(guid);
   411     SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
   412     return guid;
   413 }
   414 
   415 
   416 SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
   417 {
   418     SDL_JoystickGUID guid;
   419     /* the GUID is just the first 16 chars of the name for now */
   420     const char *name = joystick->name;
   421     SDL_zero(guid);
   422     SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
   423     return guid;
   424 }
   425 
   426 #endif /* SDL_JOYSTICK_EMSCRIPTEN */