Automatically assign player indexes to game controllers, and allow changing the player index for game controllers and joysticks.
authorSam Lantinga
Fri, 20 Dec 2019 20:12:03 -0800
changeset 13369d73580c86f81
parent 13368 1219018fa220
child 13370 a67f6a4199a9
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
include/SDL_joystick.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/joystick/SDL_gamecontroller.c
src/joystick/SDL_joystick.c
src/joystick/SDL_joystick_c.h
src/joystick/SDL_sysjoystick.h
src/joystick/android/SDL_sysjoystick.c
src/joystick/bsd/SDL_sysjoystick.c
src/joystick/darwin/SDL_sysjoystick.c
src/joystick/dummy/SDL_sysjoystick.c
src/joystick/emscripten/SDL_sysjoystick.c
src/joystick/haiku/SDL_haikujoystick.cc
src/joystick/hidapi/SDL_hidapi_gamecube.c
src/joystick/hidapi/SDL_hidapi_ps4.c
src/joystick/hidapi/SDL_hidapi_switch.c
src/joystick/hidapi/SDL_hidapi_xbox360.c
src/joystick/hidapi/SDL_hidapi_xbox360w.c
src/joystick/hidapi/SDL_hidapi_xboxone.c
src/joystick/hidapi/SDL_hidapijoystick.c
src/joystick/hidapi/SDL_hidapijoystick_c.h
src/joystick/iphoneos/SDL_sysjoystick.m
src/joystick/linux/SDL_sysjoystick.c
src/joystick/windows/SDL_windowsjoystick.c
test/testgamecontroller.c
     1.1 --- a/include/SDL_gamecontroller.h	Fri Dec 20 15:58:59 2019 +0100
     1.2 +++ b/include/SDL_gamecontroller.h	Fri Dec 20 20:12:03 2019 -0800
     1.3 @@ -215,6 +215,11 @@
     1.4  extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid);
     1.5  
     1.6  /**
     1.7 + * Return the SDL_GameController associated with a player index.
     1.8 + */
     1.9 +extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index);
    1.10 +
    1.11 +/**
    1.12   *  Return the name for this currently opened controller
    1.13   */
    1.14  extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller);
    1.15 @@ -232,6 +237,11 @@
    1.16  extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);
    1.17  
    1.18  /**
    1.19 + *  Set the player index of an opened game controller
    1.20 + */
    1.21 +extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index);
    1.22 +
    1.23 +/**
    1.24   *  Get the USB vendor ID of an opened controller, if available.
    1.25   *  If the vendor ID isn't available this function returns 0.
    1.26   */
     2.1 --- a/include/SDL_joystick.h	Fri Dec 20 15:58:59 2019 +0100
     2.2 +++ b/include/SDL_joystick.h	Fri Dec 20 20:12:03 2019 -0800
     2.3 @@ -192,7 +192,12 @@
     2.4  /**
     2.5   * Return the SDL_Joystick associated with an instance id.
     2.6   */
     2.7 -extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID joyid);
     2.8 +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id);
     2.9 +
    2.10 +/**
    2.11 + * Return the SDL_Joystick associated with a player index.
    2.12 + */
    2.13 +extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);
    2.14  
    2.15  /**
    2.16   *  Return the name for this currently opened joystick.
    2.17 @@ -208,6 +213,11 @@
    2.18  extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick);
    2.19  
    2.20  /**
    2.21 + *  Set the player index of an opened joystick
    2.22 + */
    2.23 +extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index);
    2.24 +
    2.25 +/**
    2.26   *  Return the GUID for this opened joystick
    2.27   */
    2.28  extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick * joystick);
     3.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Fri Dec 20 15:58:59 2019 +0100
     3.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Fri Dec 20 20:12:03 2019 -0800
     3.3 @@ -733,3 +733,7 @@
     3.4  #define SDL_wcsncmp SDL_wcsncmp_REAL
     3.5  #define SDL_GameControllerTypeForIndex SDL_GameControllerTypeForIndex_REAL
     3.6  #define SDL_GameControllerGetType SDL_GameControllerGetType_REAL
     3.7 +#define SDL_GameControllerFromPlayerIndex SDL_GameControllerFromPlayerIndex_REAL
     3.8 +#define SDL_GameControllerSetPlayerIndex SDL_GameControllerSetPlayerIndex_REAL
     3.9 +#define SDL_JoystickFromPlayerIndex SDL_JoystickFromPlayerIndex_REAL
    3.10 +#define SDL_JoystickSetPlayerIndex SDL_JoystickSetPlayerIndex_REAL
     4.1 --- a/src/dynapi/SDL_dynapi_procs.h	Fri Dec 20 15:58:59 2019 +0100
     4.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Fri Dec 20 20:12:03 2019 -0800
     4.3 @@ -789,3 +789,7 @@
     4.4  SDL_DYNAPI_PROC(int,SDL_wcsncmp,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
     4.5  SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerTypeForIndex,(int a),(a),return)
     4.6  SDL_DYNAPI_PROC(SDL_GameControllerType,SDL_GameControllerGetType,(SDL_GameController *a),(a),return)
     4.7 +SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromPlayerIndex,(int a),(a),return)
     4.8 +SDL_DYNAPI_PROC(void,SDL_GameControllerSetPlayerIndex,(SDL_GameController *a, int b),(a,b),)
     4.9 +SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromPlayerIndex,(int a),(a),return)
    4.10 +SDL_DYNAPI_PROC(void,SDL_JoystickSetPlayerIndex,(SDL_Joystick *a, int b),(a,b),)
     5.1 --- a/src/joystick/SDL_gamecontroller.c	Fri Dec 20 15:58:59 2019 +0100
     5.2 +++ b/src/joystick/SDL_gamecontroller.c	Fri Dec 20 20:12:03 2019 -0800
     5.3 @@ -1765,6 +1765,15 @@
     5.4      return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller));
     5.5  }
     5.6  
     5.7 +/**
     5.8 + *  Set the player index of an opened game controller
     5.9 + */
    5.10 +void
    5.11 +SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index)
    5.12 +{
    5.13 +    SDL_JoystickSetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller), player_index);
    5.14 +}
    5.15 +
    5.16  Uint16
    5.17  SDL_GameControllerGetVendor(SDL_GameController * gamecontroller)
    5.18  {
    5.19 @@ -1809,7 +1818,7 @@
    5.20  
    5.21  
    5.22  /*
    5.23 - * Find the SDL_GameController that owns this instance id
    5.24 + * Return the SDL_GameController associated with an instance id.
    5.25   */
    5.26  SDL_GameController *
    5.27  SDL_GameControllerFromInstanceID(SDL_JoystickID joyid)
    5.28 @@ -1830,6 +1839,19 @@
    5.29  }
    5.30  
    5.31  
    5.32 +/**
    5.33 + * Return the SDL_GameController associated with a player index.
    5.34 + */
    5.35 +SDL_GameController *SDL_GameControllerFromPlayerIndex(int player_index)
    5.36 +{
    5.37 +    SDL_Joystick *joystick = SDL_JoystickFromPlayerIndex(player_index);
    5.38 +    if (joystick) {
    5.39 +        return SDL_GameControllerFromInstanceID(joystick->instance_id);
    5.40 +    }
    5.41 +    return NULL;
    5.42 +}
    5.43 +
    5.44 +
    5.45  /*
    5.46   * Get the SDL joystick layer binding for this controller axis mapping
    5.47   */
     6.1 --- a/src/joystick/SDL_joystick.c	Fri Dec 20 15:58:59 2019 +0100
     6.2 +++ b/src/joystick/SDL_joystick.c	Fri Dec 20 20:12:03 2019 -0800
     6.3 @@ -83,6 +83,8 @@
     6.4  static SDL_bool SDL_updating_joystick = SDL_FALSE;
     6.5  static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
     6.6  static SDL_atomic_t SDL_next_joystick_instance_id;
     6.7 +static int SDL_joystick_player_count = 0;
     6.8 +static SDL_JoystickID *SDL_joystick_players = NULL;
     6.9  
    6.10  void
    6.11  SDL_LockJoysticks(void)
    6.12 @@ -100,6 +102,81 @@
    6.13      }
    6.14  }
    6.15  
    6.16 +static int
    6.17 +SDL_FindFreePlayerIndex()
    6.18 +{
    6.19 +    int player_index;
    6.20 +
    6.21 +    for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
    6.22 +        if (SDL_joystick_players[player_index] == -1) {
    6.23 +            return player_index;
    6.24 +        }
    6.25 +    }
    6.26 +    return player_index;
    6.27 +}
    6.28 +
    6.29 +static int
    6.30 +SDL_GetPlayerIndexForJoystickID(SDL_JoystickID instance_id)
    6.31 +{
    6.32 +    int player_index;
    6.33 +
    6.34 +    for (player_index = 0; player_index < SDL_joystick_player_count; ++player_index) {
    6.35 +        if (instance_id == SDL_joystick_players[player_index]) {
    6.36 +            break;
    6.37 +        }
    6.38 +    }
    6.39 +    if (player_index == SDL_joystick_player_count) {
    6.40 +        player_index = -1;
    6.41 +    }
    6.42 +    return player_index;
    6.43 +}
    6.44 +
    6.45 +static SDL_JoystickID
    6.46 +SDL_GetJoystickIDForPlayerIndex(int player_index)
    6.47 +{
    6.48 +    if (player_index < 0 || player_index >= SDL_joystick_player_count) {
    6.49 +        return -1;
    6.50 +    }
    6.51 +    return SDL_joystick_players[player_index];
    6.52 +}
    6.53 +
    6.54 +static SDL_bool
    6.55 +SDL_SetJoystickIDForPlayerIndex(int player_index, SDL_JoystickID instance_id)
    6.56 +{
    6.57 +    SDL_JoystickID existing_instance = SDL_GetJoystickIDForPlayerIndex(player_index);
    6.58 +    SDL_JoystickDriver *driver;
    6.59 +    int device_index;
    6.60 +
    6.61 +    if (player_index < 0) {
    6.62 +        return SDL_FALSE;
    6.63 +    }
    6.64 +    if (player_index >= SDL_joystick_player_count) {
    6.65 +        SDL_JoystickID *new_players = (SDL_JoystickID *)SDL_realloc(SDL_joystick_players, (player_index + 1)*sizeof(*SDL_joystick_players));
    6.66 +        if (!new_players) {
    6.67 +            SDL_OutOfMemory();
    6.68 +            return SDL_FALSE;
    6.69 +        }
    6.70 +
    6.71 +        SDL_joystick_players = new_players;
    6.72 +        while (SDL_joystick_player_count <= player_index) {
    6.73 +            SDL_joystick_players[SDL_joystick_player_count++] = -1;
    6.74 +        }
    6.75 +    }
    6.76 +
    6.77 +    SDL_joystick_players[player_index] = instance_id;
    6.78 +
    6.79 +    /* Update the driver with the new index */
    6.80 +    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(instance_id);
    6.81 +    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
    6.82 +        driver->SetDevicePlayerIndex(device_index, player_index);
    6.83 +    }
    6.84 +
    6.85 +    /* Move any existing joystick to another slot */
    6.86 +    if (existing_instance >= 0) {
    6.87 +        SDL_SetJoystickIDForPlayerIndex(SDL_FindFreePlayerIndex(), existing_instance);
    6.88 +    }
    6.89 +    return SDL_TRUE;
    6.90 +}
    6.91  
    6.92  static void SDLCALL
    6.93  SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
    6.94 @@ -228,16 +305,16 @@
    6.95      return name;
    6.96  }
    6.97  
    6.98 +/*
    6.99 + *  Get the player index of a joystick, or -1 if it's not available
   6.100 + */
   6.101  int
   6.102  SDL_JoystickGetDevicePlayerIndex(int device_index)
   6.103  {
   6.104 -    SDL_JoystickDriver *driver;
   6.105 -    int player_index = -1;
   6.106 +    int player_index;
   6.107  
   6.108      SDL_LockJoysticks();
   6.109 -    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &device_index)) {
   6.110 -        player_index = driver->GetDevicePlayerIndex(device_index);
   6.111 -    }
   6.112 +    player_index = SDL_GetPlayerIndexForJoystickID(SDL_JoystickGetDeviceInstanceID(device_index));
   6.113      SDL_UnlockJoysticks();
   6.114  
   6.115      return player_index;
   6.116 @@ -323,7 +400,6 @@
   6.117      joystick->driver = driver;
   6.118      joystick->instance_id = instance_id;
   6.119      joystick->attached = SDL_TRUE;
   6.120 -    joystick->player_index = -1;
   6.121      joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN;
   6.122  
   6.123      if (driver->Open(joystick, device_index) < 0) {
   6.124 @@ -391,16 +467,16 @@
   6.125  /*
   6.126   * Checks to make sure the joystick is valid.
   6.127   */
   6.128 -int
   6.129 +SDL_bool
   6.130  SDL_PrivateJoystickValid(SDL_Joystick * joystick)
   6.131  {
   6.132 -    int valid;
   6.133 +    SDL_bool valid;
   6.134  
   6.135      if (joystick == NULL) {
   6.136          SDL_SetError("Joystick hasn't been opened yet");
   6.137 -        valid = 0;
   6.138 +        valid = SDL_FALSE;
   6.139      } else {
   6.140 -        valid = 1;
   6.141 +        valid = SDL_TRUE;
   6.142      }
   6.143  
   6.144      return valid;
   6.145 @@ -589,16 +665,36 @@
   6.146  }
   6.147  
   6.148  /*
   6.149 - * Find the SDL_Joystick that owns this instance id
   6.150 + * Return the SDL_Joystick associated with an instance id.
   6.151   */
   6.152  SDL_Joystick *
   6.153 -SDL_JoystickFromInstanceID(SDL_JoystickID joyid)
   6.154 +SDL_JoystickFromInstanceID(SDL_JoystickID instance_id)
   6.155  {
   6.156      SDL_Joystick *joystick;
   6.157  
   6.158      SDL_LockJoysticks();
   6.159      for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   6.160 -        if (joystick->instance_id == joyid) {
   6.161 +        if (joystick->instance_id == instance_id) {
   6.162 +            break;
   6.163 +        }
   6.164 +    }
   6.165 +    SDL_UnlockJoysticks();
   6.166 +    return joystick;
   6.167 +}
   6.168 +
   6.169 +/**
   6.170 + * Return the SDL_Joystick associated with a player index.
   6.171 + */
   6.172 +SDL_Joystick *
   6.173 +SDL_JoystickFromPlayerIndex(int player_index)
   6.174 +{
   6.175 +    SDL_JoystickID instance_id;
   6.176 +    SDL_Joystick *joystick;
   6.177 +
   6.178 +    SDL_LockJoysticks();
   6.179 +    instance_id = SDL_GetJoystickIDForPlayerIndex(player_index);
   6.180 +    for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
   6.181 +        if (joystick->instance_id == instance_id) {
   6.182              break;
   6.183          }
   6.184      }
   6.185 @@ -619,13 +715,38 @@
   6.186      return SDL_FixupJoystickName(joystick->name);
   6.187  }
   6.188  
   6.189 +/**
   6.190 + *  Get the player index of an opened joystick, or -1 if it's not available
   6.191 + */
   6.192  int
   6.193  SDL_JoystickGetPlayerIndex(SDL_Joystick * joystick)
   6.194  {
   6.195 +    int player_index;
   6.196 +
   6.197      if (!SDL_PrivateJoystickValid(joystick)) {
   6.198          return -1;
   6.199      }
   6.200 -    return joystick->player_index;
   6.201 +
   6.202 +    SDL_LockJoysticks();
   6.203 +    player_index = SDL_GetPlayerIndexForJoystickID(joystick->instance_id);
   6.204 +    SDL_UnlockJoysticks();
   6.205 +
   6.206 +    return player_index;
   6.207 +}
   6.208 +
   6.209 +/**
   6.210 + *  Set the player index of an opened joystick
   6.211 + */
   6.212 +void
   6.213 +SDL_JoystickSetPlayerIndex(SDL_Joystick * joystick, int player_index)
   6.214 +{
   6.215 +    if (!SDL_PrivateJoystickValid(joystick)) {
   6.216 +        return;
   6.217 +    }
   6.218 +
   6.219 +    SDL_LockJoysticks();
   6.220 +    SDL_SetJoystickIDForPlayerIndex(player_index, joystick->instance_id);
   6.221 +    SDL_UnlockJoysticks();
   6.222  }
   6.223  
   6.224  int
   6.225 @@ -718,6 +839,11 @@
   6.226         SDL_joystick_drivers[i]->Quit();
   6.227      }
   6.228  
   6.229 +    if (SDL_joystick_players) {
   6.230 +        SDL_free(SDL_joystick_players);
   6.231 +        SDL_joystick_players = NULL;
   6.232 +        SDL_joystick_player_count = 0;
   6.233 +    }
   6.234      SDL_UnlockJoysticks();
   6.235  
   6.236  #if !SDL_EVENTS_DISABLED
   6.237 @@ -755,20 +881,36 @@
   6.238  
   6.239  void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
   6.240  {
   6.241 -#if !SDL_EVENTS_DISABLED
   6.242 -    SDL_Event event;
   6.243 -    int device_index;
   6.244 -
   6.245 -    device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
   6.246 +    SDL_JoystickDriver *driver;
   6.247 +    int driver_device_index;
   6.248 +    int player_index = -1;
   6.249 +    int device_index = SDL_JoystickGetDeviceIndexFromInstanceID(device_instance);
   6.250      if (device_index < 0) {
   6.251          return;
   6.252      }
   6.253  
   6.254 -    event.type = SDL_JOYDEVICEADDED;
   6.255 +    SDL_LockJoysticks();
   6.256 +    if (SDL_GetDriverAndJoystickIndex(device_index, &driver, &driver_device_index)) {
   6.257 +        player_index = driver->GetDevicePlayerIndex(driver_device_index);
   6.258 +    }
   6.259 +    if (player_index < 0 && SDL_IsGameController(device_index)) {
   6.260 +        player_index = SDL_FindFreePlayerIndex();
   6.261 +    }
   6.262 +    if (player_index >= 0) {
   6.263 +        SDL_SetJoystickIDForPlayerIndex(player_index, device_instance);
   6.264 +    }
   6.265 +    SDL_UnlockJoysticks();
   6.266  
   6.267 -    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   6.268 -        event.jdevice.which = device_index;
   6.269 -        SDL_PushEvent(&event);
   6.270 +#if !SDL_EVENTS_DISABLED
   6.271 +    {
   6.272 +        SDL_Event event;
   6.273 +
   6.274 +        event.type = SDL_JOYDEVICEADDED;
   6.275 +
   6.276 +        if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   6.277 +            event.jdevice.which = device_index;
   6.278 +            SDL_PushEvent(&event);
   6.279 +        }
   6.280      }
   6.281  #endif /* !SDL_EVENTS_DISABLED */
   6.282  }
     7.1 --- a/src/joystick/SDL_joystick_c.h	Fri Dec 20 15:58:59 2019 +0100
     7.2 +++ b/src/joystick/SDL_joystick_c.h	Fri Dec 20 20:12:03 2019 -0800
     7.3 @@ -101,7 +101,7 @@
     7.4                                              SDL_JoystickPowerLevel ePowerLevel);
     7.5  
     7.6  /* Internal sanity checking functions */
     7.7 -extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
     7.8 +extern SDL_bool SDL_PrivateJoystickValid(SDL_Joystick * joystick);
     7.9  
    7.10  #endif /* SDL_joystick_c_h_ */
    7.11  
     8.1 --- a/src/joystick/SDL_sysjoystick.h	Fri Dec 20 15:58:59 2019 +0100
     8.2 +++ b/src/joystick/SDL_sysjoystick.h	Fri Dec 20 20:12:03 2019 -0800
     8.3 @@ -43,7 +43,6 @@
     8.4  {
     8.5      SDL_JoystickID instance_id; /* Device instance, monotonically increasing from 0 */
     8.6      char *name;                 /* Joystick name - system dependent */
     8.7 -    int player_index;           /* Joystick player index, or -1 if unavailable */
     8.8      SDL_JoystickGUID guid;      /* Joystick guid */
     8.9  
    8.10      int naxes;                  /* Number of axis controls on the joystick */
    8.11 @@ -110,6 +109,9 @@
    8.12      /* Function to get the player index of a joystick */
    8.13      int (*GetDevicePlayerIndex)(int device_index);
    8.14  
    8.15 +    /* Function to get the player index of a joystick */
    8.16 +    void (*SetDevicePlayerIndex)(int device_index, int player_index);
    8.17 +
    8.18      /* Function to return the stable GUID for a plugged in device */
    8.19      SDL_JoystickGUID (*GetDeviceGUID)(int device_index);
    8.20  
     9.1 --- a/src/joystick/android/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
     9.2 +++ b/src/joystick/android/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
     9.3 @@ -587,6 +587,11 @@
     9.4      return -1;
     9.5  }
     9.6  
     9.7 +static void
     9.8 +ANDROID_JoystickSetDevicePlayerIndex(int device_index, int player_index)
     9.9 +{
    9.10 +}
    9.11 +
    9.12  static SDL_JoystickGUID
    9.13  ANDROID_JoystickGetDeviceGUID(int device_index)
    9.14  {
    9.15 @@ -696,6 +701,7 @@
    9.16      ANDROID_JoystickDetect,
    9.17      ANDROID_JoystickGetDeviceName,
    9.18      ANDROID_JoystickGetDevicePlayerIndex,
    9.19 +    ANDROID_JoystickSetDevicePlayerIndex,
    9.20      ANDROID_JoystickGetDeviceGUID,
    9.21      ANDROID_JoystickGetDeviceInstanceID,
    9.22      ANDROID_JoystickOpen,
    10.1 --- a/src/joystick/bsd/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    10.2 +++ b/src/joystick/bsd/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    10.3 @@ -276,6 +276,11 @@
    10.4      return -1;
    10.5  }
    10.6  
    10.7 +static void
    10.8 +BSD_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    10.9 +{
   10.10 +}
   10.11 +
   10.12  /* Function to perform the mapping from device index to the instance id for this index */
   10.13  static SDL_JoystickID
   10.14  BSD_JoystickGetDeviceInstanceID(int device_index)
   10.15 @@ -764,6 +769,7 @@
   10.16      BSD_JoystickDetect,
   10.17      BSD_JoystickGetDeviceName,
   10.18      BSD_JoystickGetDevicePlayerIndex,
   10.19 +    BSD_JoystickSetDevicePlayerIndex,
   10.20      BSD_JoystickGetDeviceGUID,
   10.21      BSD_JoystickGetDeviceInstanceID,
   10.22      BSD_JoystickOpen,
    11.1 --- a/src/joystick/darwin/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    11.2 +++ b/src/joystick/darwin/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    11.3 @@ -734,6 +734,11 @@
    11.4      return -1;
    11.5  }
    11.6  
    11.7 +static void
    11.8 +DARWIN_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    11.9 +{
   11.10 +}
   11.11 +
   11.12  static SDL_JoystickGUID
   11.13  DARWIN_JoystickGetDeviceGUID( int device_index )
   11.14  {
   11.15 @@ -1033,6 +1038,7 @@
   11.16      DARWIN_JoystickDetect,
   11.17      DARWIN_JoystickGetDeviceName,
   11.18      DARWIN_JoystickGetDevicePlayerIndex,
   11.19 +    DARWIN_JoystickSetDevicePlayerIndex,
   11.20      DARWIN_JoystickGetDeviceGUID,
   11.21      DARWIN_JoystickGetDeviceInstanceID,
   11.22      DARWIN_JoystickOpen,
    12.1 --- a/src/joystick/dummy/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    12.2 +++ b/src/joystick/dummy/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    12.3 @@ -58,6 +58,11 @@
    12.4      return -1;
    12.5  }
    12.6  
    12.7 +static void
    12.8 +DUMMY_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    12.9 +{
   12.10 +}
   12.11 +
   12.12  static SDL_JoystickGUID
   12.13  DUMMY_JoystickGetDeviceGUID(int device_index)
   12.14  {
   12.15 @@ -106,6 +111,7 @@
   12.16      DUMMY_JoystickDetect,
   12.17      DUMMY_JoystickGetDeviceName,
   12.18      DUMMY_JoystickGetDevicePlayerIndex,
   12.19 +    DUMMY_JoystickSetDevicePlayerIndex,
   12.20      DUMMY_JoystickGetDeviceGUID,
   12.21      DUMMY_JoystickGetDeviceInstanceID,
   12.22      DUMMY_JoystickOpen,
    13.1 --- a/src/joystick/emscripten/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    13.2 +++ b/src/joystick/emscripten/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    13.3 @@ -288,6 +288,11 @@
    13.4      return -1;
    13.5  }
    13.6  
    13.7 +static void
    13.8 +EMSCRIPTEN_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    13.9 +{
   13.10 +}
   13.11 +
   13.12  static SDL_JoystickID
   13.13  EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index)
   13.14  {
   13.15 @@ -406,6 +411,7 @@
   13.16      EMSCRIPTEN_JoystickDetect,
   13.17      EMSCRIPTEN_JoystickGetDeviceName,
   13.18      EMSCRIPTEN_JoystickGetDevicePlayerIndex,
   13.19 +    EMSCRIPTEN_JoystickSetDevicePlayerIndex,
   13.20      EMSCRIPTEN_JoystickGetDeviceGUID,
   13.21      EMSCRIPTEN_JoystickGetDeviceInstanceID,
   13.22      EMSCRIPTEN_JoystickOpen,
    14.1 --- a/src/joystick/haiku/SDL_haikujoystick.cc	Fri Dec 20 15:58:59 2019 +0100
    14.2 +++ b/src/joystick/haiku/SDL_haikujoystick.cc	Fri Dec 20 20:12:03 2019 -0800
    14.3 @@ -104,6 +104,10 @@
    14.4          return -1;
    14.5      }
    14.6  
    14.7 +    static void HAIKU_JoystickGetDevicePlayerIndex(int device_index, int player_index)
    14.8 +    {
    14.9 +    }
   14.10 +
   14.11  /* Function to perform the mapping from device index to the instance id for this index */
   14.12      static SDL_JoystickID HAIKU_JoystickGetDeviceInstanceID(int device_index)
   14.13      {
   14.14 @@ -262,6 +266,7 @@
   14.15          HAIKU_JoystickDetect,
   14.16          HAIKU_JoystickGetDeviceName,
   14.17          HAIKU_JoystickGetDevicePlayerIndex,
   14.18 +        HAIKU_JoystickSetDevicePlayerIndex,
   14.19          HAIKU_JoystickGetDeviceGUID,
   14.20          HAIKU_JoystickGetDeviceInstanceID,
   14.21          HAIKU_JoystickOpen,
    15.1 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c	Fri Dec 20 15:58:59 2019 +0100
    15.2 +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c	Fri Dec 20 20:12:03 2019 -0800
    15.3 @@ -140,6 +140,25 @@
    15.4      return SDL_FALSE;
    15.5  }
    15.6  
    15.7 +static int
    15.8 +HIDAPI_DriverGameCube_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
    15.9 +{
   15.10 +    SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
   15.11 +    Uint8 i;
   15.12 +
   15.13 +    for (i = 0; i < 4; ++i) {
   15.14 +        if (instance_id == ctx->joysticks[i]) {
   15.15 +            return i;
   15.16 +        }
   15.17 +    }
   15.18 +    return -1;
   15.19 +}
   15.20 +
   15.21 +static void
   15.22 +HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   15.23 +{
   15.24 +}
   15.25 +
   15.26  static SDL_bool
   15.27  HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
   15.28  {
   15.29 @@ -253,7 +272,6 @@
   15.30              joystick->nbuttons = 12;
   15.31              joystick->naxes = 6;
   15.32              joystick->epowerlevel = ctx->wireless[i] ? SDL_JOYSTICK_POWER_UNKNOWN : SDL_JOYSTICK_POWER_WIRED;
   15.33 -            joystick->player_index = i;
   15.34              return SDL_TRUE;
   15.35          }
   15.36      }
   15.37 @@ -331,6 +349,8 @@
   15.38      HIDAPI_DriverGameCube_IsSupportedDevice,
   15.39      HIDAPI_DriverGameCube_GetDeviceName,
   15.40      HIDAPI_DriverGameCube_InitDevice,
   15.41 +    HIDAPI_DriverGameCube_GetDevicePlayerIndex,
   15.42 +    HIDAPI_DriverGameCube_SetDevicePlayerIndex,
   15.43      HIDAPI_DriverGameCube_UpdateDevice,
   15.44      HIDAPI_DriverGameCube_OpenJoystick,
   15.45      HIDAPI_DriverGameCube_RumbleJoystick,
    16.1 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c	Fri Dec 20 15:58:59 2019 +0100
    16.2 +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c	Fri Dec 20 20:12:03 2019 -0800
    16.3 @@ -199,6 +199,17 @@
    16.4      return HIDAPI_JoystickConnected(device, NULL);
    16.5  }
    16.6  
    16.7 +static int
    16.8 +HIDAPI_DriverPS4_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
    16.9 +{
   16.10 +    return -1;
   16.11 +}
   16.12 +
   16.13 +static void
   16.14 +HIDAPI_DriverPS4_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   16.15 +{
   16.16 +}
   16.17 +
   16.18  static int HIDAPI_DriverPS4_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
   16.19  
   16.20  static SDL_bool
   16.21 @@ -499,6 +510,8 @@
   16.22      HIDAPI_DriverPS4_IsSupportedDevice,
   16.23      HIDAPI_DriverPS4_GetDeviceName,
   16.24      HIDAPI_DriverPS4_InitDevice,
   16.25 +    HIDAPI_DriverPS4_GetDevicePlayerIndex,
   16.26 +    HIDAPI_DriverPS4_SetDevicePlayerIndex,
   16.27      HIDAPI_DriverPS4_UpdateDevice,
   16.28      HIDAPI_DriverPS4_OpenJoystick,
   16.29      HIDAPI_DriverPS4_RumbleJoystick,
    17.1 --- a/src/joystick/hidapi/SDL_hidapi_switch.c	Fri Dec 20 15:58:59 2019 +0100
    17.2 +++ b/src/joystick/hidapi/SDL_hidapi_switch.c	Fri Dec 20 20:12:03 2019 -0800
    17.3 @@ -628,6 +628,17 @@
    17.4      return HIDAPI_JoystickConnected(device, NULL);
    17.5  }
    17.6  
    17.7 +static int
    17.8 +HIDAPI_DriverSwitch_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
    17.9 +{
   17.10 +    return -1;
   17.11 +}
   17.12 +
   17.13 +static void
   17.14 +HIDAPI_DriverSwitch_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   17.15 +{
   17.16 +}
   17.17 +
   17.18  static SDL_bool
   17.19  HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   17.20  {
   17.21 @@ -1109,6 +1120,8 @@
   17.22      HIDAPI_DriverSwitch_IsSupportedDevice,
   17.23      HIDAPI_DriverSwitch_GetDeviceName,
   17.24      HIDAPI_DriverSwitch_InitDevice,
   17.25 +    HIDAPI_DriverSwitch_GetDevicePlayerIndex,
   17.26 +    HIDAPI_DriverSwitch_SetDevicePlayerIndex,
   17.27      HIDAPI_DriverSwitch_UpdateDevice,
   17.28      HIDAPI_DriverSwitch_OpenJoystick,
   17.29      HIDAPI_DriverSwitch_RumbleJoystick,
    18.1 --- a/src/joystick/hidapi/SDL_hidapi_xbox360.c	Fri Dec 20 15:58:59 2019 +0100
    18.2 +++ b/src/joystick/hidapi/SDL_hidapi_xbox360.c	Fri Dec 20 20:12:03 2019 -0800
    18.3 @@ -305,10 +305,25 @@
    18.4      return HIDAPI_JoystickConnected(device, NULL);
    18.5  }
    18.6  
    18.7 +static int
    18.8 +HIDAPI_DriverXbox360_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
    18.9 +{
   18.10 +    return -1;
   18.11 +}
   18.12 +
   18.13 +static void
   18.14 +HIDAPI_DriverXbox360_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   18.15 +{
   18.16 +    if (device->dev) {
   18.17 +        SetSlotLED(device->dev, (player_index % 4));
   18.18 +    }
   18.19 +}
   18.20 +
   18.21  static SDL_bool
   18.22  HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   18.23  {
   18.24      SDL_DriverXbox360_Context *ctx;
   18.25 +    int player_index;
   18.26  
   18.27      ctx = (SDL_DriverXbox360_Context *)SDL_calloc(1, sizeof(*ctx));
   18.28      if (!ctx) {
   18.29 @@ -336,7 +351,10 @@
   18.30  #endif
   18.31  
   18.32      /* Set the controller LED */
   18.33 -    SetSlotLED(device->dev, (joystick->instance_id % 4));
   18.34 +    player_index = SDL_JoystickGetPlayerIndex(joystick);
   18.35 +    if (player_index >= 0) {
   18.36 +        SetSlotLED(device->dev, (player_index % 4));
   18.37 +    }
   18.38  
   18.39      /* Initialize the joystick capabilities */
   18.40      joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
   18.41 @@ -837,6 +855,8 @@
   18.42      HIDAPI_DriverXbox360_IsSupportedDevice,
   18.43      HIDAPI_DriverXbox360_GetDeviceName,
   18.44      HIDAPI_DriverXbox360_InitDevice,
   18.45 +    HIDAPI_DriverXbox360_GetDevicePlayerIndex,
   18.46 +    HIDAPI_DriverXbox360_SetDevicePlayerIndex,
   18.47      HIDAPI_DriverXbox360_UpdateDevice,
   18.48      HIDAPI_DriverXbox360_OpenJoystick,
   18.49      HIDAPI_DriverXbox360_RumbleJoystick,
    19.1 --- a/src/joystick/hidapi/SDL_hidapi_xbox360w.c	Fri Dec 20 15:58:59 2019 +0100
    19.2 +++ b/src/joystick/hidapi/SDL_hidapi_xbox360w.c	Fri Dec 20 20:12:03 2019 -0800
    19.3 @@ -94,7 +94,7 @@
    19.4      SDL_DriverXbox360W_Context *ctx;
    19.5  
    19.6      /* Requests controller presence information from the wireless dongle */
    19.7 -	const Uint8 init_packet[] = { 0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    19.8 +    const Uint8 init_packet[] = { 0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    19.9  
   19.10      ctx = (SDL_DriverXbox360W_Context *)SDL_calloc(1, sizeof(*ctx));
   19.11      if (!ctx) {
   19.12 @@ -118,6 +118,18 @@
   19.13      return SDL_TRUE;
   19.14  }
   19.15  
   19.16 +static int
   19.17 +HIDAPI_DriverXbox360W_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
   19.18 +{
   19.19 +    return -1;
   19.20 +}
   19.21 +
   19.22 +static void
   19.23 +HIDAPI_DriverXbox360W_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   19.24 +{
   19.25 +    SetSlotLED(device->dev, (player_index % 4));
   19.26 +}
   19.27 +
   19.28  static SDL_bool
   19.29  HIDAPI_DriverXbox360W_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   19.30  {
   19.31 @@ -300,6 +312,8 @@
   19.32      HIDAPI_DriverXbox360W_IsSupportedDevice,
   19.33      HIDAPI_DriverXbox360W_GetDeviceName,
   19.34      HIDAPI_DriverXbox360W_InitDevice,
   19.35 +    HIDAPI_DriverXbox360W_GetDevicePlayerIndex,
   19.36 +    HIDAPI_DriverXbox360W_SetDevicePlayerIndex,
   19.37      HIDAPI_DriverXbox360W_UpdateDevice,
   19.38      HIDAPI_DriverXbox360W_OpenJoystick,
   19.39      HIDAPI_DriverXbox360W_RumbleJoystick,
    20.1 --- a/src/joystick/hidapi/SDL_hidapi_xboxone.c	Fri Dec 20 15:58:59 2019 +0100
    20.2 +++ b/src/joystick/hidapi/SDL_hidapi_xboxone.c	Fri Dec 20 20:12:03 2019 -0800
    20.3 @@ -260,6 +260,17 @@
    20.4      return HIDAPI_JoystickConnected(device, NULL);
    20.5  }
    20.6  
    20.7 +static int
    20.8 +HIDAPI_DriverXboxOne_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
    20.9 +{
   20.10 +    return -1;
   20.11 +}
   20.12 +
   20.13 +static void
   20.14 +HIDAPI_DriverXboxOne_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
   20.15 +{
   20.16 +}
   20.17 +
   20.18  static SDL_bool
   20.19  HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
   20.20  {
   20.21 @@ -468,6 +479,8 @@
   20.22      HIDAPI_DriverXboxOne_IsSupportedDevice,
   20.23      HIDAPI_DriverXboxOne_GetDeviceName,
   20.24      HIDAPI_DriverXboxOne_InitDevice,
   20.25 +    HIDAPI_DriverXboxOne_GetDevicePlayerIndex,
   20.26 +    HIDAPI_DriverXboxOne_SetDevicePlayerIndex,
   20.27      HIDAPI_DriverXboxOne_UpdateDevice,
   20.28      HIDAPI_DriverXboxOne_OpenJoystick,
   20.29      HIDAPI_DriverXboxOne_RumbleJoystick,
    21.1 --- a/src/joystick/hidapi/SDL_hidapijoystick.c	Fri Dec 20 15:58:59 2019 +0100
    21.2 +++ b/src/joystick/hidapi/SDL_hidapijoystick.c	Fri Dec 20 20:12:03 2019 -0800
    21.3 @@ -894,7 +894,32 @@
    21.4  static int
    21.5  HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
    21.6  {
    21.7 -    return -1;
    21.8 +    SDL_HIDAPI_Device *device;
    21.9 +    SDL_JoystickID instance_id;
   21.10 +    int player_index = -1;
   21.11 +
   21.12 +    SDL_LockMutex(SDL_HIDAPI_mutex);
   21.13 +    device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
   21.14 +    if (device) {
   21.15 +        player_index = device->driver->GetDevicePlayerIndex(device, instance_id);
   21.16 +    }
   21.17 +    SDL_UnlockMutex(SDL_HIDAPI_mutex);
   21.18 +
   21.19 +    return player_index;
   21.20 +}
   21.21 +
   21.22 +static void
   21.23 +HIDAPI_JoystickSetDevicePlayerIndex(int device_index, int player_index)
   21.24 +{
   21.25 +    SDL_HIDAPI_Device *device;
   21.26 +    SDL_JoystickID instance_id;
   21.27 +
   21.28 +    SDL_LockMutex(SDL_HIDAPI_mutex);
   21.29 +    device = HIDAPI_GetDeviceByIndex(device_index, &instance_id);
   21.30 +    if (device) {
   21.31 +        device->driver->SetDevicePlayerIndex(device, instance_id, player_index);
   21.32 +    }
   21.33 +    SDL_UnlockMutex(SDL_HIDAPI_mutex);
   21.34  }
   21.35  
   21.36  static SDL_JoystickGUID
   21.37 @@ -1023,6 +1048,7 @@
   21.38      HIDAPI_JoystickDetect,
   21.39      HIDAPI_JoystickGetDeviceName,
   21.40      HIDAPI_JoystickGetDevicePlayerIndex,
   21.41 +    HIDAPI_JoystickSetDevicePlayerIndex,
   21.42      HIDAPI_JoystickGetDeviceGUID,
   21.43      HIDAPI_JoystickGetDeviceInstanceID,
   21.44      HIDAPI_JoystickOpen,
    22.1 --- a/src/joystick/hidapi/SDL_hidapijoystick_c.h	Fri Dec 20 15:58:59 2019 +0100
    22.2 +++ b/src/joystick/hidapi/SDL_hidapijoystick_c.h	Fri Dec 20 20:12:03 2019 -0800
    22.3 @@ -81,6 +81,8 @@
    22.4      SDL_bool (*IsSupportedDevice)(Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, const char *name);
    22.5      const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
    22.6      SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
    22.7 +    int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id);
    22.8 +    void (*SetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index);
    22.9      SDL_bool (*UpdateDevice)(SDL_HIDAPI_Device *device);
   22.10      SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
   22.11      int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
    23.1 --- a/src/joystick/iphoneos/SDL_sysjoystick.m	Fri Dec 20 15:58:59 2019 +0100
    23.2 +++ b/src/joystick/iphoneos/SDL_sysjoystick.m	Fri Dec 20 20:12:03 2019 -0800
    23.3 @@ -469,6 +469,15 @@
    23.4      return device ? (int)device->controller.playerIndex : -1;
    23.5  }
    23.6  
    23.7 +static void
    23.8 +IOS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    23.9 +{
   23.10 +    SDL_JoystickDeviceItem *device = GetDeviceForIndex(device_index);
   23.11 +    if (device) {
   23.12 +        device->controller.playerIndex = player_index;
   23.13 +    }
   23.14 +}
   23.15 +
   23.16  static SDL_JoystickGUID
   23.17  IOS_JoystickGetDeviceGUID( int device_index )
   23.18  {
   23.19 @@ -616,7 +625,6 @@
   23.20          GCController *controller = joystick->hwdata->controller;
   23.21          Uint8 hatstate = SDL_HAT_CENTERED;
   23.22          int i;
   23.23 -        int updateplayerindex = 0;
   23.24          int pause_button_index = 0;
   23.25  
   23.26          if (controller.extendedGamepad) {
   23.27 @@ -670,17 +678,10 @@
   23.28              hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
   23.29  
   23.30              for (i = 0; i < SDL_arraysize(axes); i++) {
   23.31 -                /* The triggers (axes 2 and 5) are resting at -32768 but SDL
   23.32 -                 * initializes its values to 0. We only want to make sure the
   23.33 -                 * player index is up to date if the user actually moves an axis. */
   23.34 -                if ((i != 2 && i != 5) || axes[i] != -32768) {
   23.35 -                    updateplayerindex |= (joystick->axes[i].value != axes[i]);
   23.36 -                }
   23.37                  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
   23.38              }
   23.39  
   23.40              for (i = 0; i < button_count; i++) {
   23.41 -                updateplayerindex |= (joystick->buttons[i] != buttons[i]);
   23.42                  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
   23.43              }
   23.44          } else if (controller.gamepad) {
   23.45 @@ -701,7 +702,6 @@
   23.46              hatstate = IOS_MFIJoystickHatStateForDPad(gamepad.dpad);
   23.47  
   23.48              for (i = 0; i < button_count; i++) {
   23.49 -                updateplayerindex |= (joystick->buttons[i] != buttons[i]);
   23.50                  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
   23.51              }
   23.52          }
   23.53 @@ -715,7 +715,6 @@
   23.54              };
   23.55  
   23.56              for (i = 0; i < SDL_arraysize(axes); i++) {
   23.57 -                updateplayerindex |= (joystick->axes[i].value != axes[i]);
   23.58                  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
   23.59              }
   23.60  
   23.61 @@ -737,14 +736,12 @@
   23.62  #pragma clang diagnostic pop
   23.63  
   23.64              for (i = 0; i < button_count; i++) {
   23.65 -                updateplayerindex |= (joystick->buttons[i] != buttons[i]);
   23.66                  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
   23.67              }
   23.68          }
   23.69  #endif /* TARGET_OS_TV */
   23.70  
   23.71          if (joystick->nhats > 0) {
   23.72 -            updateplayerindex |= (joystick->hats[0] != hatstate);
   23.73              SDL_PrivateJoystickHat(joystick, 0, hatstate);
   23.74          }
   23.75  
   23.76 @@ -752,31 +749,9 @@
   23.77              for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
   23.78                  SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_PRESSED);
   23.79                  SDL_PrivateJoystickButton(joystick, pause_button_index, SDL_RELEASED);
   23.80 -                updateplayerindex = YES;
   23.81              }
   23.82              joystick->hwdata->num_pause_presses = 0;
   23.83          }
   23.84 -
   23.85 -        if (updateplayerindex && controller.playerIndex == -1) {
   23.86 -            BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
   23.87 -
   23.88 -            /* Find the player index of all other connected controllers. */
   23.89 -            for (GCController *c in [GCController controllers]) {
   23.90 -                if (c != controller && c.playerIndex >= 0) {
   23.91 -                    usedPlayerIndexSlots[c.playerIndex] = YES;
   23.92 -                }
   23.93 -            }
   23.94 -
   23.95 -            /* Set this controller's player index to the first unused index.
   23.96 -             * FIXME: This logic isn't great... but SDL doesn't expose this
   23.97 -             * concept in its external API, so we don't have much to go on. */
   23.98 -            for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) {
   23.99 -                if (!usedPlayerIndexSlots[i]) {
  23.100 -                    controller.playerIndex = i;
  23.101 -                    break;
  23.102 -                }
  23.103 -            }
  23.104 -        }
  23.105      }
  23.106  #endif /* SDL_JOYSTICK_MFI */
  23.107  }
  23.108 @@ -874,6 +849,7 @@
  23.109      IOS_JoystickDetect,
  23.110      IOS_JoystickGetDeviceName,
  23.111      IOS_JoystickGetDevicePlayerIndex,
  23.112 +    IOS_JoystickSetDevicePlayerIndex,
  23.113      IOS_JoystickGetDeviceGUID,
  23.114      IOS_JoystickGetDeviceInstanceID,
  23.115      IOS_JoystickOpen,
    24.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    24.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    24.3 @@ -569,6 +569,11 @@
    24.4      return -1;
    24.5  }
    24.6  
    24.7 +static void
    24.8 +LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    24.9 +{
   24.10 +}
   24.11 +
   24.12  static SDL_JoystickGUID
   24.13  LINUX_JoystickGetDeviceGUID( int device_index )
   24.14  {
   24.15 @@ -1086,6 +1091,7 @@
   24.16      LINUX_JoystickDetect,
   24.17      LINUX_JoystickGetDeviceName,
   24.18      LINUX_JoystickGetDevicePlayerIndex,
   24.19 +    LINUX_JoystickSetDevicePlayerIndex,
   24.20      LINUX_JoystickGetDeviceGUID,
   24.21      LINUX_JoystickGetDeviceInstanceID,
   24.22      LINUX_JoystickOpen,
    25.1 --- a/src/joystick/windows/SDL_windowsjoystick.c	Fri Dec 20 15:58:59 2019 +0100
    25.2 +++ b/src/joystick/windows/SDL_windowsjoystick.c	Fri Dec 20 20:12:03 2019 -0800
    25.3 @@ -419,6 +419,11 @@
    25.4      return device->bXInputDevice ? (int)device->XInputUserId : -1;
    25.5  }
    25.6  
    25.7 +static void
    25.8 +WINDOWS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
    25.9 +{
   25.10 +}
   25.11 +
   25.12  /* return the stable device guid for this device index */
   25.13  static SDL_JoystickGUID
   25.14  WINDOWS_JoystickGetDeviceGUID(int device_index)
   25.15 @@ -557,6 +562,7 @@
   25.16      WINDOWS_JoystickDetect,
   25.17      WINDOWS_JoystickGetDeviceName,
   25.18      WINDOWS_JoystickGetDevicePlayerIndex,
   25.19 +    WINDOWS_JoystickSetDevicePlayerIndex,
   25.20      WINDOWS_JoystickGetDeviceGUID,
   25.21      WINDOWS_JoystickGetDeviceInstanceID,
   25.22      WINDOWS_JoystickOpen,
    26.1 --- a/test/testgamecontroller.c	Fri Dec 20 15:58:59 2019 +0100
    26.2 +++ b/test/testgamecontroller.c	Fri Dec 20 20:12:03 2019 -0800
    26.3 @@ -316,9 +316,9 @@
    26.4              name = SDL_JoystickNameForIndex(i);
    26.5              description = "Joystick";
    26.6          }
    26.7 -        SDL_Log("%s %d: %s (guid %s, VID 0x%.4x, PID 0x%.4x)\n",
    26.8 +        SDL_Log("%s %d: %s (guid %s, VID 0x%.4x, PID 0x%.4x, player index = %d)\n",
    26.9              description, i, name ? name : "Unknown", guid,
   26.10 -            SDL_JoystickGetDeviceVendor(i), SDL_JoystickGetDeviceProduct(i));
   26.11 +            SDL_JoystickGetDeviceVendor(i), SDL_JoystickGetDeviceProduct(i), SDL_JoystickGetDevicePlayerIndex(i));
   26.12      }
   26.13      SDL_Log("There are %d game controller(s) attached (%d joystick(s))\n", nController, SDL_NumJoysticks());
   26.14