I’m in the process of making my (Win/Linux) game detect add/remove events for
joysticks. The original code assumed that joysticks would be plugged in before
the game was launched and would stay connected. If you needed to swap out
controllers, you had to relaunch the game. This is antiquated.
Now that I bring device added/removed events into the mix, a few new "gotchas"
come into play:
If an SDL_Joystick pointer is opened, it keeps pointing to the same
structure even when the physical device is disconnected from the system. You
can keep making calls using the pointer and things like axis readings appear to
continue working but the SDL joystick basically “goes dead”. That’s a good
thing, IMHO… you don’t want to have to deal with “fatal error” handling for
every single call to do anything with an SDL_Joystick.
If you had an SDL_Joystick pointer opened, and the device got disconnected
and reconnected, the pointer would remain pointing to an old structure that is
"dead". If you call SDL_JoystickGetAttached, it will return SDL_FALSE but it
will never return SDL_TRUE even after the device gets reconnected. This was
suprising. SDL doesn’t “reacquire” a device that was temporarily lost (like
XINPUT would do for play #1 whose battery died or who got excited and pulled
their USB out).
If a device is disconnected and reconnected, the same joystick gets a new,
unique instance ID… so any events are for a “different” device now. I had
thought the “instance ID” was the solution to the problem of figuring out which
device is which, but it makes sense now… it’s just a auto-incremented number
for each device encountered (whether it was seen before or not).
The index numbers get shuffled around when devices are added/removed - which
is as expected according to the docs. However, this leads to the situation
where if you can’t use the same index number for the same device, and you can’t
use the same instance ID for the same device, then you can never tell
"definitively" that even a single device was disconnected and reconnected,
except by maybe using the GUID for a DINPUT device (not very good for 3 of the
same device type), or looking for “#1”, “#2”, etc., for an XINPUT device.
So given all that, I have to take a step back and ask, how are we supposed to
design our code to deal with devices coming and going?
So far, I’ve basically rewritten my code to close out all controllers and
reopen all controllers every time there is a device added/removed event (and
deal with matching the game code structures with the proper SDL_Joystick and
getting my game’s event mapping system re-setup properly, etc.). This certainly
works, but it somehow seems like the… “wrong way”.
Ed Phillips email@example.com University of Delaware (302) 831-6082
Systems Programmer IV, Network and Systems Services