Atlas - SDL_sysjoystick.c

Home / ext / SDL2 / src / joystick / emscripten Lines: 1 | Size: 11371 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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#include "SDL_joystick.h" 31#include "SDL_assert.h" 32#include "SDL_timer.h" 33#include "SDL_log.h" 34#include "SDL_sysjoystick_c.h" 35#include "../SDL_joystick_c.h" 36 37static SDL_joylist_item * JoystickByIndex(int index); 38 39static SDL_joylist_item *SDL_joylist = NULL; 40static SDL_joylist_item *SDL_joylist_tail = NULL; 41static int numjoysticks = 0; 42static int instance_counter = 0; 43 44static EM_BOOL 45Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) 46{ 47 int i; 48 49 SDL_joylist_item *item; 50 51 if (JoystickByIndex(gamepadEvent->index) != NULL) { 52 return 1; 53 } 54 55 item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item)); 56 if (item == NULL) { 57 return 1; 58 } 59 60 SDL_zerop(item); 61 item->index = gamepadEvent->index; 62 63 item->name = SDL_strdup(gamepadEvent->id); 64 if ( item->name == NULL ) { 65 SDL_free(item); 66 return 1; 67 } 68 69 item->mapping = SDL_strdup(gamepadEvent->mapping); 70 if ( item->mapping == NULL ) { 71 SDL_free(item->name); 72 SDL_free(item); 73 return 1; 74 } 75 76 item->naxes = gamepadEvent->numAxes; 77 item->nbuttons = gamepadEvent->numButtons; 78 item->device_instance = instance_counter++; 79 80 item->timestamp = gamepadEvent->timestamp; 81 82 for( i = 0; i < item->naxes; i++) { 83 item->axis[i] = gamepadEvent->axis[i]; 84 } 85 86 for( i = 0; i < item->nbuttons; i++) { 87 item->analogButton[i] = gamepadEvent->analogButton[i]; 88 item->digitalButton[i] = gamepadEvent->digitalButton[i]; 89 } 90 91 if (SDL_joylist_tail == NULL) { 92 SDL_joylist = SDL_joylist_tail = item; 93 } else { 94 SDL_joylist_tail->next = item; 95 SDL_joylist_tail = item; 96 } 97 98 ++numjoysticks; 99 100 SDL_PrivateJoystickAdded(numjoysticks - 1); 101 102#ifdef DEBUG_JOYSTICK 103 SDL_Log("Number of joysticks is %d", numjoysticks); 104#endif 105 106#ifdef DEBUG_JOYSTICK 107 SDL_Log("Added joystick with index %d", item->index); 108#endif 109 110 return 1; 111} 112 113static EM_BOOL 114Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) 115{ 116 SDL_joylist_item *item = SDL_joylist; 117 SDL_joylist_item *prev = NULL; 118 119 while (item != NULL) { 120 if (item->index == gamepadEvent->index) { 121 break; 122 } 123 prev = item; 124 item = item->next; 125 } 126 127 if (item == NULL) { 128 return 1; 129 } 130 131 if (item->joystick) { 132 item->joystick->hwdata = NULL; 133 } 134 135 if (prev != NULL) { 136 prev->next = item->next; 137 } else { 138 SDL_assert(SDL_joylist == item); 139 SDL_joylist = item->next; 140 } 141 if (item == SDL_joylist_tail) { 142 SDL_joylist_tail = prev; 143 } 144 145 /* Need to decrement the joystick count before we post the event */ 146 --numjoysticks; 147 148 SDL_PrivateJoystickRemoved(item->device_instance); 149 150#ifdef DEBUG_JOYSTICK 151 SDL_Log("Removed joystick with id %d", item->device_instance); 152#endif 153 SDL_free(item->name); 154 SDL_free(item->mapping); 155 SDL_free(item); 156 return 1; 157} 158 159/* Function to perform any system-specific joystick related cleanup */ 160static void 161EMSCRIPTEN_JoystickQuit(void) 162{ 163 SDL_joylist_item *item = NULL; 164 SDL_joylist_item *next = NULL; 165 166 for (item = SDL_joylist; item; item = next) { 167 next = item->next; 168 SDL_free(item->mapping); 169 SDL_free(item->name); 170 SDL_free(item); 171 } 172 173 SDL_joylist = SDL_joylist_tail = NULL; 174 175 numjoysticks = 0; 176 instance_counter = 0; 177 178 emscripten_set_gamepadconnected_callback(NULL, 0, NULL); 179 emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL); 180} 181 182/* Function to scan the system for joysticks. 183 * It should return 0, or -1 on an unrecoverable fatal error. 184 */ 185static int 186EMSCRIPTEN_JoystickInit(void) 187{ 188 int retval, i, numjs; 189 EmscriptenGamepadEvent gamepadState; 190 191 numjoysticks = 0; 192 numjs = emscripten_get_num_gamepads(); 193 194 /* Check if gamepad is supported by browser */ 195 if (numjs == EMSCRIPTEN_RESULT_NOT_SUPPORTED) { 196 return SDL_SetError("Gamepads not supported"); 197 } 198 199 /* handle already connected gamepads */ 200 if (numjs > 0) { 201 for(i = 0; i < numjs; i++) { 202 retval = emscripten_get_gamepad_status(i, &gamepadState); 203 if (retval == EMSCRIPTEN_RESULT_SUCCESS) { 204 Emscripten_JoyStickConnected(EMSCRIPTEN_EVENT_GAMEPADCONNECTED, 205 &gamepadState, 206 NULL); 207 } 208 } 209 } 210 211 retval = emscripten_set_gamepadconnected_callback(NULL, 212 0, 213 Emscripten_JoyStickConnected); 214 215 if(retval != EMSCRIPTEN_RESULT_SUCCESS) { 216 EMSCRIPTEN_JoystickQuit(); 217 return SDL_SetError("Could not set gamepad connect callback"); 218 } 219 220 retval = emscripten_set_gamepaddisconnected_callback(NULL, 221 0, 222 Emscripten_JoyStickDisconnected); 223 if(retval != EMSCRIPTEN_RESULT_SUCCESS) { 224 EMSCRIPTEN_JoystickQuit(); 225 return SDL_SetError("Could not set gamepad disconnect callback"); 226 } 227 228 return 0; 229} 230 231/* Returns item matching given SDL device index. */ 232static SDL_joylist_item * 233JoystickByDeviceIndex(int device_index) 234{ 235 SDL_joylist_item *item = SDL_joylist; 236 237 while (0 < device_index) { 238 --device_index; 239 item = item->next; 240 } 241 242 return item; 243} 244 245/* Returns item matching given HTML gamepad index. */ 246static SDL_joylist_item * 247JoystickByIndex(int index) 248{ 249 SDL_joylist_item *item = SDL_joylist; 250 251 if (index < 0) { 252 return NULL; 253 } 254 255 while (item != NULL) { 256 if (item->index == index) { 257 break; 258 } 259 item = item->next; 260 } 261 262 return item; 263} 264 265static int 266EMSCRIPTEN_JoystickGetCount(void) 267{ 268 return numjoysticks; 269} 270 271static void 272EMSCRIPTEN_JoystickDetect(void) 273{ 274} 275 276static const char * 277EMSCRIPTEN_JoystickGetDeviceName(int device_index) 278{ 279 return JoystickByDeviceIndex(device_index)->name; 280} 281 282static SDL_JoystickID 283EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index) 284{ 285 return JoystickByDeviceIndex(device_index)->device_instance; 286} 287 288/* Function to open a joystick for use. 289 The joystick to open is specified by the device index. 290 This should fill the nbuttons and naxes fields of the joystick structure. 291 It returns 0, or -1 if there is an error. 292 */ 293static int 294EMSCRIPTEN_JoystickOpen(SDL_Joystick * joystick, int device_index) 295{ 296 SDL_joylist_item *item = JoystickByDeviceIndex(device_index); 297 298 if (item == NULL ) { 299 return SDL_SetError("No such device"); 300 } 301 302 if (item->joystick != NULL) { 303 return SDL_SetError("Joystick already opened"); 304 } 305 306 joystick->instance_id = item->device_instance; 307 joystick->hwdata = (struct joystick_hwdata *) item; 308 item->joystick = joystick; 309 310 /* HTML5 Gamepad API doesn't say anything about these */ 311 joystick->nhats = 0; 312 joystick->nballs = 0; 313 314 joystick->nbuttons = item->nbuttons; 315 joystick->naxes = item->naxes; 316 317 return (0); 318} 319 320/* Function to update the state of a joystick - called as a device poll. 321 * This function shouldn't update the joystick structure directly, 322 * but instead should call SDL_PrivateJoystick*() to deliver events 323 * and update joystick device state. 324 */ 325static void 326EMSCRIPTEN_JoystickUpdate(SDL_Joystick * joystick) 327{ 328 EmscriptenGamepadEvent gamepadState; 329 SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata; 330 int i, result, buttonState; 331 332 if (item) { 333 result = emscripten_get_gamepad_status(item->index, &gamepadState); 334 if( result == EMSCRIPTEN_RESULT_SUCCESS) { 335 if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) { 336 for(i = 0; i < item->nbuttons; i++) { 337 if(item->digitalButton[i] != gamepadState.digitalButton[i]) { 338 buttonState = gamepadState.digitalButton[i]? SDL_PRESSED: SDL_RELEASED; 339 SDL_PrivateJoystickButton(item->joystick, i, buttonState); 340 } 341 342 /* store values to compare them in the next update */ 343 item->analogButton[i] = gamepadState.analogButton[i]; 344 item->digitalButton[i] = gamepadState.digitalButton[i]; 345 } 346 347 for(i = 0; i < item->naxes; i++) { 348 if(item->axis[i] != gamepadState.axis[i]) { 349 /* do we need to do conversion? */ 350 SDL_PrivateJoystickAxis(item->joystick, i, 351 (Sint16) (32767.*gamepadState.axis[i])); 352 } 353 354 /* store to compare in next update */ 355 item->axis[i] = gamepadState.axis[i]; 356 } 357 358 item->timestamp = gamepadState.timestamp; 359 } 360 } 361 } 362} 363 364/* Function to close a joystick after use */ 365static void 366EMSCRIPTEN_JoystickClose(SDL_Joystick * joystick) 367{ 368 SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata; 369 if (item) { 370 item->joystick = NULL; 371 } 372} 373 374static SDL_JoystickGUID 375EMSCRIPTEN_JoystickGetDeviceGUID(int device_index) 376{ 377 SDL_JoystickGUID guid; 378 /* the GUID is just the first 16 chars of the name for now */ 379 const char *name = EMSCRIPTEN_JoystickGetDeviceName(device_index); 380 SDL_zero(guid); 381 SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); 382 return guid; 383} 384 385static int 386EMSCRIPTEN_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) 387{ 388 return SDL_Unsupported(); 389} 390 391SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = 392{ 393 EMSCRIPTEN_JoystickInit, 394 EMSCRIPTEN_JoystickGetCount, 395 EMSCRIPTEN_JoystickDetect, 396 EMSCRIPTEN_JoystickGetDeviceName, 397 EMSCRIPTEN_JoystickGetDeviceGUID, 398 EMSCRIPTEN_JoystickGetDeviceInstanceID, 399 EMSCRIPTEN_JoystickOpen, 400 EMSCRIPTEN_JoystickRumble, 401 EMSCRIPTEN_JoystickUpdate, 402 EMSCRIPTEN_JoystickClose, 403 EMSCRIPTEN_JoystickQuit, 404}; 405 406#endif /* SDL_JOYSTICK_EMSCRIPTEN */ 407
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.