From 46e1377d49ddd2d25b3c2b2c23b91788093f2392 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 20 Dec 2019 20:12:03 -0800 Subject: [PATCH] Automatically assign player indexes to game controllers, and allow changing the player index for game controllers and joysticks. Added the functions SDL_JoystickFromPlayerIndex(), SDL_JoystickSetPlayerIndex(), SDL_GameControllerFromPlayerIndex(), and SDL_GameControllerSetPlayerIndex() --- include/SDL_gamecontroller.h | 10 ++ include/SDL_joystick.h | 12 +- src/dynapi/SDL_dynapi_overrides.h | 4 + src/dynapi/SDL_dynapi_procs.h | 4 + src/joystick/SDL_gamecontroller.c | 24 ++- src/joystick/SDL_joystick.c | 188 ++++++++++++++++++--- src/joystick/SDL_joystick_c.h | 2 +- src/joystick/SDL_sysjoystick.h | 4 +- src/joystick/android/SDL_sysjoystick.c | 6 + src/joystick/bsd/SDL_sysjoystick.c | 6 + src/joystick/darwin/SDL_sysjoystick.c | 6 + src/joystick/dummy/SDL_sysjoystick.c | 6 + src/joystick/emscripten/SDL_sysjoystick.c | 6 + src/joystick/haiku/SDL_haikujoystick.cc | 5 + src/joystick/hidapi/SDL_hidapi_gamecube.c | 22 ++- src/joystick/hidapi/SDL_hidapi_ps4.c | 13 ++ src/joystick/hidapi/SDL_hidapi_switch.c | 13 ++ src/joystick/hidapi/SDL_hidapi_xbox360.c | 22 ++- src/joystick/hidapi/SDL_hidapi_xbox360w.c | 16 +- src/joystick/hidapi/SDL_hidapi_xboxone.c | 13 ++ src/joystick/hidapi/SDL_hidapijoystick.c | 28 ++- src/joystick/hidapi/SDL_hidapijoystick_c.h | 2 + src/joystick/iphoneos/SDL_sysjoystick.m | 44 ++--- src/joystick/linux/SDL_sysjoystick.c | 6 + src/joystick/windows/SDL_windowsjoystick.c | 6 + test/testgamecontroller.c | 4 +- 26 files changed, 405 insertions(+), 67 deletions(-) diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index 4b738b2f4..5ee8e8e95 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -214,6 +214,11 @@ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_ */ extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid); +/** + * Return the SDL_GameController associated with a player index. + */ +extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index); + /** * Return the name for this currently opened controller */ @@ -231,6 +236,11 @@ extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_Gam */ extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller); +/** + * Set the player index of an opened game controller + */ +extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index); + /** * Get the USB vendor ID of an opened controller, if available. * If the vendor ID isn't available this function returns 0. diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 3a4c5d177..3c099decd 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -192,7 +192,12 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index); /** * Return the SDL_Joystick associated with an instance id. */ -extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID joyid); +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id); + +/** + * Return the SDL_Joystick associated with a player index. + */ +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index); /** * Return the name for this currently opened joystick. @@ -207,6 +212,11 @@ extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick * joystick); */ extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick); +/** + * Set the player index of an opened joystick + */ +extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index); + /** * Return the GUID for this opened joystick */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 56e461ad9..c391ecf56 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -733,3 +733,7 @@ #define SDL_wcsncmp SDL_wcsncmp_REAL #define SDL_GameControllerTypeForIndex SDL_GameControllerTypeForIndex_REAL #define SDL_GameControllerGetType SDL_GameControllerGetType_REAL +#define SDL_GameControllerFromPlayerIndex SDL_GameControllerFromPlayerIndex_REAL +#define SDL_GameControllerSetPlayerIndex SDL_GameControllerSetPlayerIndex_REAL +#define SDL_JoystickFromPlayerIndex SDL_JoystickFromPlayerIndex_REAL +#define SDL_JoystickSetPlayerIndex SDL_JoystickSetPlayerIndex_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index d7b8f04dd..2aa438d6c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -789,3 +789,7 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),r SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerTypeForIndex,(int a),(a),return) SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerGetType,(SDL_GameController *a),(a),return) +SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromPlayerIndex,(int a),(a),return) +SDL_DYNAPI_PROC(void,SDL_GameControllerSetPlayerIndex,(SDL_GameController *a, int b),(a,b),) +SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromPlayerIndex,(int a),(a),return) +SDL_DYNAPI_PROC(void,SDL_JoystickSetPlayerIndex,(SDL_Joystick *a, int b),(a,b),) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 8c898fdfe..51c482e9f 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -1765,6 +1765,15 @@ SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller)); } +/** + * Set the player index of an opened game controller + */ +void +SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index) +{ + SDL_JoystickSetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller), player_index); +} + Uint16 SDL_GameControllerGetVendor(SDL_GameController * gamecontroller) { @@ -1809,7 +1818,7 @@ SDL_Joystick *SDL_GameControllerGetJoystick(SDL_GameController * gamecontroller) /* - * Find the SDL_GameController that owns this instance id + * Return the SDL_GameController associated with an instance id. */ SDL_GameController * SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) @@ -1830,6 +1839,19 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) } +/** + * Return the SDL_GameController associated with a player index. + */ +SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index) +{ + SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index); + if (joystick) { + return SDL_GameControllerFromInstanceID(joystick->instance_id); + } + return NULL; +} + + /* * Get the SDL joystick layer binding for this controller axis mapping */ diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 3990c8f17..56d8fe2d6 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -83,6 +83,8 @@ static SDL_Joystick *SDL_joysticks = NULL; static SDL_bool SDL_updating_joystick = SDL_FALSE; static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ static SDL_atomic_t SDL_next_joystick_instance_id; +static int SDL_joystick_player_count = 0; +static SDL_JoystickID *SDL_joystick_players = NULL; void SDL_LockJoysticks(void) @@ -100,6 +102,81 @@ SDL_UnlockJoysticks(void) } } +static int +SDL_FindFreePlayerIndex() +{ + int player_index; + + for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) { + if (SDL_joystick_players[player_index] == -1) { + return player_index; + } + } + return player_index; +} + +static int +SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id) +{ + int player_index; + + for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) { + if (instance_id == SDL_joystick_players[player_index]) { + break; + } + } + if (player_index == SDL_joystick_player_count) { + player_index = -1; + } + return player_index; +} + +static SDL_JoystickID +SDL_GetJoystickIDForPlayerIndex(int player_index) +{ + if (player_index < 0 || player_index >= SDL_joystick_player_count) { + return -1; + } + return SDL_joystick_players[player_index]; +} + +static SDL_bool +SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id) +{ + SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index); + SDL_JoystickDriver *driver; + int device_index; + + if (player_index < 0) { + return SDL_FALSE; + } + if (player_index >= SDL_joystick_player_count) { + SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players)); + if (!new_players) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + + SDL_joystick_players = new_players; + while (SDL_joystick_player_count <= player_index) { + SDL_joystick_players[SDL_joystick_player_count++] = -1; + } + } + + SDL_joystick_players[player_index] = instance_id; + + /* Update the driver with the new index */ + device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id); + if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { + driver->SetDevicePlayerIndex(device_index, player_index); + } + + /* Move any existing joystick to another slot */ + if (existing_instance >= 0) { + SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance); + } + return SDL_TRUE; +} static void SDLCALL SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) @@ -228,16 +305,16 @@ SDL_JoystickNameForIndex(int device_index) return name; } +/* + * Get the player index of a joystick, or -1 if it's not available + */ int SDL_JoystickGetDevicePlayerIndex(int device_index) { - SDL_JoystickDriver *driver; - int player_index = -1; + int player_index; SDL_LockJoysticks(); - if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) { - player_index = driver->GetDevicePlayerIndex(device_index); - } + player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index)); SDL_UnlockJoysticks(); return player_index; @@ -323,7 +400,6 @@ SDL_JoystickOpen(int device_index) joystick->driver = driver; joystick->instance_id = instance_id; joystick->attached = SDL_TRUE; - joystick->player_index = -1; joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; if (driver->Open(joystick, device_index) < 0) { @@ -391,16 +467,16 @@ SDL_JoystickOpen(int device_index) /* * Checks to make sure the joystick is valid. */ -int +SDL_bool SDL_PrivateJoystickValid(SDL_Joystick * joystick) { - int valid; + SDL_bool valid; if (joystick == NULL) { SDL_SetError("Joystick hasn't been opened yet"); - valid = 0; + valid = SDL_FALSE; } else { - valid = 1; + valid = SDL_TRUE; } return valid; @@ -589,16 +665,36 @@ SDL_JoystickInstanceID(SDL_Joystick * joystick) } /* - * Find the SDL_Joystick that owns this instance id + * Return the SDL_Joystick associated with an instance id. */ SDL_Joystick * -SDL_JoystickFromInstanceID(SDL_JoystickID joyid) +SDL_JoystickFromInstanceID(SDL_JoystickID instance_id) { SDL_Joystick *joystick; SDL_LockJoysticks(); for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { - if (joystick->instance_id == joyid) { + if (joystick->instance_id == instance_id) { + break; + } + } + SDL_UnlockJoysticks(); + return joystick; +} + +/** + * Return the SDL_Joystick associated with a player index. + */ +SDL_Joystick * +SDL_JoystickFromPlayerIndex(int player_index) +{ + SDL_JoystickID instance_id; + SDL_Joystick *joystick; + + SDL_LockJoysticks(); + instance_id = SDL_GetJoystickIDForPlayerIndex(player_index); + for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { + if (joystick->instance_id == instance_id) { break; } } @@ -619,13 +715,38 @@ SDL_JoystickName(SDL_Joystick * joystick) return SDL_FixupJoystickName(joystick->name); } +/** + * Get the player index of an opened joystick, or -1 if it's not available + */ int SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick) { + int player_index; + if (!SDL_PrivateJoystickValid(joystick)) { return -1; } - return joystick->player_index; + + SDL_LockJoysticks(); + player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id); + SDL_UnlockJoysticks(); + + return player_index; +} + +/** + * Set the player index of an opened joystick + */ +void +SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index) +{ + if (!SDL_PrivateJoystickValid(joystick)) { + return; + } + + SDL_LockJoysticks(); + SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id); + SDL_UnlockJoysticks(); } int @@ -718,6 +839,11 @@ SDL_JoystickQuit(void) SDL_joystick_drivers[i]->Quit(); } + if (SDL_joystick_players) { + SDL_free(SDL_joystick_players); + SDL_joystick_players = NULL; + SDL_joystick_player_count = 0; + } SDL_UnlockJoysticks(); #if !SDL_EVENTS_DISABLED @@ -755,20 +881,36 @@ SDL_PrivateJoystickShouldIgnoreEvent() void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance) { -#if !SDL_EVENTS_DISABLED - SDL_Event event; - int device_index; - - device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance); + SDL_JoystickDriver *driver; + int driver_device_index; + int player_index = -1; + int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance); if (device_index < 0) { return; } - event.type = SDL_JOYDEVICEADDED; + SDL_LockJoysticks(); + if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) { + player_index = driver->GetDevicePlayerIndex(driver_device_index); + } + if (player_index < 0 && SDL_IsGameController(device_index)) { + player_index = SDL_FindFreePlayerIndex(); + } + if (player_index >= 0) { + SDL_SetJoystickIDForPlayerIndex(player_index, device_instance); + } + SDL_UnlockJoysticks(); - if (SDL_GetEventState(event.type) == SDL_ENABLE) { - event.jdevice.which = device_index; - SDL_PushEvent(&event); +#if !SDL_EVENTS_DISABLED + { + SDL_Event event; + + event.type = SDL_JOYDEVICEADDED; + + if (SDL_GetEventState(event.type) == SDL_ENABLE) { + event.jdevice.which = device_index; + SDL_PushEvent(&event); + } } #endif /* !SDL_EVENTS_DISABLED */ } diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index cf3dece24..a59eaeba5 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -101,7 +101,7 @@ extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick, SDL_JoystickPowerLevel ePowerLevel); /* Internal sanity checking functions */ -extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick); +extern SDL_bool SDL_PrivateJoystickValid(SDL_Joystick * joystick); #endif /* SDL_joystick_c_h_ */ diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 4ea0c80fd..0c7461d09 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -43,7 +43,6 @@ struct _SDL_Joystick { SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */ char *name; /* Joystick name - system dependent */ - int player_index; /* Joystick player index, or -1 if unavailable */ SDL_JoystickGUID guid; /* Joystick guid */ int naxes; /* Number of axis controls on the joystick */ @@ -110,6 +109,9 @@ typedef struct _SDL_JoystickDriver /* Function to get the player index of a joystick */ int (*GetDevicePlayerIndex)(int device_index); + /* Function to get the player index of a joystick */ + void (*SetDevicePlayerIndex)(int device_index, int player_index); + /* Function to return the stable GUID for a plugged in device */ SDL_JoystickGUID (*GetDeviceGUID)(int device_index); diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 158c38a4c..1e4607759 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -587,6 +587,11 @@ ANDROID_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +ANDROID_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + static SDL_JoystickGUID ANDROID_JoystickGetDeviceGUID(int device_index) { @@ -696,6 +701,7 @@ SDL_JoystickDriver SDL_ANDROID_JoystickDriver = ANDROID_JoystickDetect, ANDROID_JoystickGetDeviceName, ANDROID_JoystickGetDevicePlayerIndex, + ANDROID_JoystickSetDevicePlayerIndex, ANDROID_JoystickGetDeviceGUID, ANDROID_JoystickGetDeviceInstanceID, ANDROID_JoystickOpen, diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c index 4a2e887e3..db4976cd7 100644 --- a/src/joystick/bsd/SDL_sysjoystick.c +++ b/src/joystick/bsd/SDL_sysjoystick.c @@ -276,6 +276,11 @@ BSD_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +BSD_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + /* Function to perform the mapping from device index to the instance id for this index */ static SDL_JoystickID BSD_JoystickGetDeviceInstanceID(int device_index) @@ -764,6 +769,7 @@ SDL_JoystickDriver SDL_BSD_JoystickDriver = BSD_JoystickDetect, BSD_JoystickGetDeviceName, BSD_JoystickGetDevicePlayerIndex, + BSD_JoystickSetDevicePlayerIndex, BSD_JoystickGetDeviceGUID, BSD_JoystickGetDeviceInstanceID, BSD_JoystickOpen, diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 9208127c3..d17d8c1e6 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -734,6 +734,11 @@ DARWIN_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +DARWIN_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + static SDL_JoystickGUID DARWIN_JoystickGetDeviceGUID( int device_index ) { @@ -1033,6 +1038,7 @@ SDL_JoystickDriver SDL_DARWIN_JoystickDriver = DARWIN_JoystickDetect, DARWIN_JoystickGetDeviceName, DARWIN_JoystickGetDevicePlayerIndex, + DARWIN_JoystickSetDevicePlayerIndex, DARWIN_JoystickGetDeviceGUID, DARWIN_JoystickGetDeviceInstanceID, DARWIN_JoystickOpen, diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 482137b2a..a8fb757c0 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -58,6 +58,11 @@ DUMMY_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +DUMMY_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + static SDL_JoystickGUID DUMMY_JoystickGetDeviceGUID(int device_index) { @@ -106,6 +111,7 @@ SDL_JoystickDriver SDL_DUMMY_JoystickDriver = DUMMY_JoystickDetect, DUMMY_JoystickGetDeviceName, DUMMY_JoystickGetDevicePlayerIndex, + DUMMY_JoystickSetDevicePlayerIndex, DUMMY_JoystickGetDeviceGUID, DUMMY_JoystickGetDeviceInstanceID, DUMMY_JoystickOpen, diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 92b831a05..fca04bf68 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -288,6 +288,11 @@ EMSCRIPTEN_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +EMSCRIPTEN_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + static SDL_JoystickID EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index) { @@ -406,6 +411,7 @@ SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver = EMSCRIPTEN_JoystickDetect, EMSCRIPTEN_JoystickGetDeviceName, EMSCRIPTEN_JoystickGetDevicePlayerIndex, + EMSCRIPTEN_JoystickSetDevicePlayerIndex, EMSCRIPTEN_JoystickGetDeviceGUID, EMSCRIPTEN_JoystickGetDeviceInstanceID, EMSCRIPTEN_JoystickOpen, diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 1b18a51e0..604ef3869 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -104,6 +104,10 @@ extern "C" return -1; } + static void HAIKU_JoystickGetDevicePlayerIndex(int device_index, int player_index) + { + } + /* Function to perform the mapping from device index to the instance id for this index */ static SDL_JoystickID HAIKU_JoystickGetDeviceInstanceID(int device_index) { @@ -262,6 +266,7 @@ extern "C" HAIKU_JoystickDetect, HAIKU_JoystickGetDeviceName, HAIKU_JoystickGetDevicePlayerIndex, + HAIKU_JoystickSetDevicePlayerIndex, HAIKU_JoystickGetDeviceGUID, HAIKU_JoystickGetDeviceInstanceID, HAIKU_JoystickOpen, diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 6a88fe322..34648f929 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -140,6 +140,25 @@ error: return SDL_FALSE; } +static int +HIDAPI_DriverGameCube_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context; + Uint8 i; + + for (i = 0; i < 4; ++i) { + if (instance_id == ctx->joysticks[i]) { + return i; + } + } + return -1; +} + +static void +HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + static SDL_bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device) { @@ -253,7 +272,6 @@ HIDAPI_DriverGameCube_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys joystick->nbuttons = 12; joystick->naxes = 6; joystick->epowerlevel = ctx->wireless[i] ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED; - joystick->player_index = i; return SDL_TRUE; } } @@ -331,6 +349,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube = HIDAPI_DriverGameCube_IsSupportedDevice, HIDAPI_DriverGameCube_GetDeviceName, HIDAPI_DriverGameCube_InitDevice, + HIDAPI_DriverGameCube_GetDevicePlayerIndex, + HIDAPI_DriverGameCube_SetDevicePlayerIndex, HIDAPI_DriverGameCube_UpdateDevice, HIDAPI_DriverGameCube_OpenJoystick, HIDAPI_DriverGameCube_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 7a1af84ee..2b2459bb3 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -199,6 +199,17 @@ HIDAPI_DriverPS4_InitDevice(SDL_HIDAPI_Device *device) return HIDAPI_JoystickConnected(device, NULL); } +static int +HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + static int HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); static SDL_bool @@ -499,6 +510,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 = HIDAPI_DriverPS4_IsSupportedDevice, HIDAPI_DriverPS4_GetDeviceName, HIDAPI_DriverPS4_InitDevice, + HIDAPI_DriverPS4_GetDevicePlayerIndex, + HIDAPI_DriverPS4_SetDevicePlayerIndex, HIDAPI_DriverPS4_UpdateDevice, HIDAPI_DriverPS4_OpenJoystick, HIDAPI_DriverPS4_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index f5a8f1d0f..b49182595 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -628,6 +628,17 @@ HIDAPI_DriverSwitch_InitDevice(SDL_HIDAPI_Device *device) return HIDAPI_JoystickConnected(device, NULL); } +static int +HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + static SDL_bool HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { @@ -1109,6 +1120,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch = HIDAPI_DriverSwitch_IsSupportedDevice, HIDAPI_DriverSwitch_GetDeviceName, HIDAPI_DriverSwitch_InitDevice, + HIDAPI_DriverSwitch_GetDevicePlayerIndex, + HIDAPI_DriverSwitch_SetDevicePlayerIndex, HIDAPI_DriverSwitch_UpdateDevice, HIDAPI_DriverSwitch_OpenJoystick, HIDAPI_DriverSwitch_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360.c b/src/joystick/hidapi/SDL_hidapi_xbox360.c index 2fb565877..cd7e12380 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c @@ -305,10 +305,25 @@ HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device) return HIDAPI_JoystickConnected(device, NULL); } +static int +HIDAPI_DriverXbox360_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ + if (device->dev) { + SetSlotLED(device->dev, (player_index % 4)); + } +} + static SDL_bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { SDL_DriverXbox360_Context *ctx; + int player_index; ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { @@ -336,7 +351,10 @@ HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst #endif /* Set the controller LED */ - SetSlotLED(device->dev, (joystick->instance_id % 4)); + player_index = SDL_JoystickGetPlayerIndex(joystick); + if (player_index >= 0) { + SetSlotLED(device->dev, (player_index % 4)); + } /* Initialize the joystick capabilities */ joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX; @@ -837,6 +855,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 = HIDAPI_DriverXbox360_IsSupportedDevice, HIDAPI_DriverXbox360_GetDeviceName, HIDAPI_DriverXbox360_InitDevice, + HIDAPI_DriverXbox360_GetDevicePlayerIndex, + HIDAPI_DriverXbox360_SetDevicePlayerIndex, HIDAPI_DriverXbox360_UpdateDevice, HIDAPI_DriverXbox360_OpenJoystick, HIDAPI_DriverXbox360_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapi_xbox360w.c b/src/joystick/hidapi/SDL_hidapi_xbox360w.c index 562542033..a87ff9d92 100644 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c @@ -94,7 +94,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) SDL_DriverXbox360W_Context *ctx; /* Requests controller presence information from the wireless dongle */ - const Uint8 init_packet[] = { 0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const Uint8 init_packet[] = { 0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx)); if (!ctx) { @@ -118,6 +118,18 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device) return SDL_TRUE; } +static int +HIDAPI_DriverXbox360W_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ + SetSlotLED(device->dev, (player_index % 4)); +} + static SDL_bool HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { @@ -300,6 +312,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W = HIDAPI_DriverXbox360W_IsSupportedDevice, HIDAPI_DriverXbox360W_GetDeviceName, HIDAPI_DriverXbox360W_InitDevice, + HIDAPI_DriverXbox360W_GetDevicePlayerIndex, + HIDAPI_DriverXbox360W_SetDevicePlayerIndex, HIDAPI_DriverXbox360W_UpdateDevice, HIDAPI_DriverXbox360W_OpenJoystick, HIDAPI_DriverXbox360W_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapi_xboxone.c b/src/joystick/hidapi/SDL_hidapi_xboxone.c index 9c03142fb..f606f75d6 100644 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c @@ -260,6 +260,17 @@ HIDAPI_DriverXboxOne_InitDevice(SDL_HIDAPI_Device *device) return HIDAPI_JoystickConnected(device, NULL); } +static int +HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) +{ + return -1; +} + +static void +HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index) +{ +} + static SDL_bool HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { @@ -468,6 +479,8 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne = HIDAPI_DriverXboxOne_IsSupportedDevice, HIDAPI_DriverXboxOne_GetDeviceName, HIDAPI_DriverXboxOne_InitDevice, + HIDAPI_DriverXboxOne_GetDevicePlayerIndex, + HIDAPI_DriverXboxOne_SetDevicePlayerIndex, HIDAPI_DriverXboxOne_UpdateDevice, HIDAPI_DriverXboxOne_OpenJoystick, HIDAPI_DriverXboxOne_RumbleJoystick, diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index e7f77644e..ef9ee08f0 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -894,7 +894,32 @@ HIDAPI_JoystickGetDeviceName(int device_index) static int HIDAPI_JoystickGetDevicePlayerIndex(int device_index) { - return -1; + SDL_HIDAPI_Device *device; + SDL_JoystickID instance_id; + int player_index = -1; + + SDL_LockMutex(SDL_HIDAPI_mutex); + device = HIDAPI_GetDeviceByIndex(device_index, &instance_id); + if (device) { + player_index = device->driver->GetDevicePlayerIndex(device, instance_id); + } + SDL_UnlockMutex(SDL_HIDAPI_mutex); + + return player_index; +} + +static void +HIDAPI_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ + SDL_HIDAPI_Device *device; + SDL_JoystickID instance_id; + + SDL_LockMutex(SDL_HIDAPI_mutex); + device = HIDAPI_GetDeviceByIndex(device_index, &instance_id); + if (device) { + device->driver->SetDevicePlayerIndex(device, instance_id, player_index); + } + SDL_UnlockMutex(SDL_HIDAPI_mutex); } static SDL_JoystickGUID @@ -1023,6 +1048,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver = HIDAPI_JoystickDetect, HIDAPI_JoystickGetDeviceName, HIDAPI_JoystickGetDevicePlayerIndex, + HIDAPI_JoystickSetDevicePlayerIndex, HIDAPI_JoystickGetDeviceGUID, HIDAPI_JoystickGetDeviceInstanceID, HIDAPI_JoystickOpen, diff --git a/src/joystick/hidapi/SDL_hidapijoystick_c.h b/src/joystick/hidapi/SDL_hidapijoystick_c.h index 1a09df397..75691559e 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h @@ -81,6 +81,8 @@ typedef struct _SDL_HIDAPI_DeviceDriver SDL_bool (*IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name); const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id); SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device); + int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id); + void (*SetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index); SDL_bool (*UpdateDevice)(SDL_HIDAPI_Device *device); SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick); int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index daaf6a73d..3d7b4e9e5 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -469,6 +469,15 @@ IOS_JoystickGetDevicePlayerIndex(int device_index) return device ? (int)device->controller.playerIndex : -1; } +static void +IOS_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ + SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index); + if (device) { + device->controller.playerIndex = player_index; + } +} + static SDL_JoystickGUID IOS_JoystickGetDeviceGUID( int device_index ) { @@ -616,7 +625,6 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) GCController *controller = joystick->hwdata->controller; Uint8 hatstate = SDL_HAT_CENTERED; int i; - int updateplayerindex = 0; int pause_button_index = 0; if (controller.extendedGamepad) { @@ -670,17 +678,10 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad); for (i = 0; i < SDL_arraysize(axes); i++) { - /* The triggers (axes 2 and 5) are resting at -32768 but SDL - * initializes its values to 0. We only want to make sure the - * player index is up to date if the user actually moves an axis. */ - if ((i != 2 && i != 5) || axes[i] != -32768) { - updateplayerindex |= (joystick->axes[i].value != axes[i]); - } SDL_PrivateJoystickAxis(joystick, i, axes[i]); } for (i = 0; i < button_count; i++) { - updateplayerindex |= (joystick->buttons[i] != buttons[i]); SDL_PrivateJoystickButton(joystick, i, buttons[i]); } } else if (controller.gamepad) { @@ -701,7 +702,6 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad); for (i = 0; i < button_count; i++) { - updateplayerindex |= (joystick->buttons[i] != buttons[i]); SDL_PrivateJoystickButton(joystick, i, buttons[i]); } } @@ -715,7 +715,6 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) }; for (i = 0; i < SDL_arraysize(axes); i++) { - updateplayerindex |= (joystick->axes[i].value != axes[i]); SDL_PrivateJoystickAxis(joystick, i, axes[i]); } @@ -737,14 +736,12 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) #pragma clang diagnostic pop for (i = 0; i < button_count; i++) { - updateplayerindex |= (joystick->buttons[i] != buttons[i]); SDL_PrivateJoystickButton(joystick, i, buttons[i]); } } #endif /* TARGET_OS_TV */ if (joystick->nhats > 0) { - updateplayerindex |= (joystick->hats[0] != hatstate); SDL_PrivateJoystickHat(joystick, 0, hatstate); } @@ -752,31 +749,9 @@ IOS_MFIJoystickUpdate(SDL_Joystick * joystick) for (i = 0; i < joystick->hwdata->num_pause_presses; i++) { SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_PRESSED); SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_RELEASED); - updateplayerindex = YES; } joystick->hwdata->num_pause_presses = 0; } - - if (updateplayerindex && controller.playerIndex == -1) { - BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO}; - - /* Find the player index of all other connected controllers. */ - for (GCController *c in [GCController controllers]) { - if (c != controller && c.playerIndex >= 0) { - usedPlayerIndexSlots[c.playerIndex] = YES; - } - } - - /* Set this controller's player index to the first unused index. - * FIXME: This logic isn't great... but SDL doesn't expose this - * concept in its external API, so we don't have much to go on. */ - for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) { - if (!usedPlayerIndexSlots[i]) { - controller.playerIndex = i; - break; - } - } - } } #endif /* SDL_JOYSTICK_MFI */ } @@ -874,6 +849,7 @@ SDL_JoystickDriver SDL_IOS_JoystickDriver = IOS_JoystickDetect, IOS_JoystickGetDeviceName, IOS_JoystickGetDevicePlayerIndex, + IOS_JoystickSetDevicePlayerIndex, IOS_JoystickGetDeviceGUID, IOS_JoystickGetDeviceInstanceID, IOS_JoystickOpen, diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 2b9b1e9c3..f56979362 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -569,6 +569,11 @@ LINUX_JoystickGetDevicePlayerIndex(int device_index) return -1; } +static void +LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + static SDL_JoystickGUID LINUX_JoystickGetDeviceGUID( int device_index ) { @@ -1086,6 +1091,7 @@ SDL_JoystickDriver SDL_LINUX_JoystickDriver = LINUX_JoystickDetect, LINUX_JoystickGetDeviceName, LINUX_JoystickGetDevicePlayerIndex, + LINUX_JoystickSetDevicePlayerIndex, LINUX_JoystickGetDeviceGUID, LINUX_JoystickGetDeviceInstanceID, LINUX_JoystickOpen, diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 2d2db153d..2559faf5f 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -419,6 +419,11 @@ WINDOWS_JoystickGetDevicePlayerIndex(int device_index) return device->bXInputDevice ? (int)device->XInputUserId : -1; } +static void +WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index) +{ +} + /* return the stable device guid for this device index */ static SDL_JoystickGUID WINDOWS_JoystickGetDeviceGUID(int device_index) @@ -557,6 +562,7 @@ SDL_JoystickDriver SDL_WINDOWS_JoystickDriver = WINDOWS_JoystickDetect, WINDOWS_JoystickGetDeviceName, WINDOWS_JoystickGetDevicePlayerIndex, + WINDOWS_JoystickSetDevicePlayerIndex, WINDOWS_JoystickGetDeviceGUID, WINDOWS_JoystickGetDeviceInstanceID, WINDOWS_JoystickOpen, diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 1bcf44086..80d0e0759 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -316,9 +316,9 @@ main(int argc, char *argv[]) name = SDL_JoystickNameForIndex(i); description = "Joystick"; } - SDL_Log("%s %d: %s (guid %s, VID 0x%.4x, PID 0x%.4x)\n", + SDL_Log("%s %d: %s (guid %s, VID 0x%.4x, PID 0x%.4x, player index = %d)\n", description, i, name ? name : "Unknown", guid, - SDL_JoystickGetDeviceVendor(i), SDL_JoystickGetDeviceProduct(i)); + SDL_JoystickGetDeviceVendor(i), SDL_JoystickGetDeviceProduct(i), SDL_JoystickGetDevicePlayerIndex(i)); } SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());