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