Joystick API behavior

The only reason that I’m not immediately accepting the patch is because
once you get the pointer, who owns it? Who should close it? What happens
if the code calling that isn’t aware of how many times that joystick has
been opened elsewhere?

It definitely serves a useful purpose for this, but I’d like to think
through some of the ramifications of adding this.

Ryan, other folks, what do you think?On Fri, Oct 11, 2013 at 1:25 PM, T. Joseph Carter < tjcarter at spiritsubstance.com> wrote:

On Fri, Oct 11, 2013 at 05:08:06PM -0300, Sik the hedgehog wrote:

Of course, if you’re using the event API the way it ought to be used,

you get that pointer from SDL_JoystickOpen, save off the instance id
from the SDL_Joystick if you need to know it later on, and you ought
to be able to promptly forget about it. After all, it’s a pointer to
a structure internal to (and managed by) SDL.

Actually, this is related to the above. Polling functions make use of
SDL_Joystick, but events make use of the instance IDs instead. Yeah,
API inconsistency, but sadly the ABI is frozen by now which means this
can’t be changed.

This patch is probably the best workaround for this :stuck_out_tongue:

Part of the reason why the polling functions work on structures is that if
you hand SDL a structure, it doesn’t have to look up which stick you’re
polling. That simplifies the code quite a lot, and it also would be very
slow to test for all the various buttons and controls. It’s not two axes
and two buttons anymore. :slight_smile:

Hopefully my improvements to testgamecontroller and eventually also
testjoystick will serve as good models for how to do both. I would like to
see this patch (perhaps with a renamed function if someone has a better
name) make it into 2.0.1, basically before too many people find themselves
inventing workarounds they don’t need to.

Joseph

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

There’s already a function to get the instance ID from the pointer,
and I’d imagine it has exactly the same issues.

In any case this is something that would be under the control of the
program anyway. If the joystick pointer is accessed in the same thread
as the events, this is a non-brainer. If it’s accessed in multiple
threads, you would be using mutexes for starters.

2013/10/12, Sam Lantinga :> The only reason that I’m not immediately accepting the patch is because

once you get the pointer, who owns it? Who should close it? What happens
if the code calling that isn’t aware of how many times that joystick has
been opened elsewhere?

It definitely serves a useful purpose for this, but I’d like to think
through some of the ramifications of adding this.

Ryan, other folks, what do you think?

On Fri, Oct 11, 2013 at 1:25 PM, T. Joseph Carter < tjcarter at spiritsubstance.com> wrote:

On Fri, Oct 11, 2013 at 05:08:06PM -0300, Sik the hedgehog wrote:

Of course, if you’re using the event API the way it ought to be used,

you get that pointer from SDL_JoystickOpen, save off the instance id
from the SDL_Joystick if you need to know it later on, and you ought
to be able to promptly forget about it. After all, it’s a pointer to
a structure internal to (and managed by) SDL.

Actually, this is related to the above. Polling functions make use of
SDL_Joystick, but events make use of the instance IDs instead. Yeah,
API inconsistency, but sadly the ABI is frozen by now which means this
can’t be changed.

This patch is probably the best workaround for this :stuck_out_tongue:

Part of the reason why the polling functions work on structures is that
if
you hand SDL a structure, it doesn’t have to look up which stick you’re
polling. That simplifies the code quite a lot, and it also would be very
slow to test for all the various buttons and controls. It’s not two axes
and two buttons anymore. :slight_smile:

Hopefully my improvements to testgamecontroller and eventually also
testjoystick will serve as good models for how to do both. I would like
to
see this patch (perhaps with a renamed function if someone has a better
name) make it into 2.0.1, basically before too many people find
themselves
inventing workarounds they don’t need to.

Joseph

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Wait, now that you mention it, I forgot it’s possible to open a
joystick multiple times… Huh, why is that even possible at all? :S
Doesn’t make much sense to me. Sounds like the problem is how the API
itself works.

What about making the function return the first open pointer with this
instance ID? Then one could just close all pointers to it with a loop
if one opened the joystick multiple times (you probably shouldn’t open
a joystick multiple times for starters, but whatever).

Opening a joystick multiple times just increments an internal reference counter and returns the original opened SDL_Joystick pointer. It’s useful.On 2013-10-12, at 6:19 AM, Sik the hedgehog <sik.the.hedgehog at gmail.com> wrote:

Wait, now that you mention it, I forgot it’s possible to open a
joystick multiple times… Huh, why is that even possible at all? :S
Doesn’t make much sense to me. Sounds like the problem is how the API
itself works.

What about making the function return the first open pointer with this
instance ID? Then one could just close all pointers to it with a loop
if one opened the joystick multiple times (you probably shouldn’t open
a joystick multiple times for starters, but whatever).


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Sam,

I do see your point, only because you can get a SDL_JOYDEVICEREMOVED
event for a joystick that isn’t opened yet. Of course if you do, you
ask for the joystick associated with that instance and get NULL back.
If you check SDL_Error, it’d tell you that’s why you got NULL.

But what if you use raw joysticks and game controllers in the same
program? Eventually I’m going to write a GameController mapper that
obviously must do exactly that. If the GameController opens the
joystick, but the program didn’t, the program shouldn’t go closing
the joystick when it receives the event. The program could track the
instance ids it has opened, and probably be wise to do so. But if
it’s gonna do that, it might as well track SDL_Joystick pointers
instead.

I guess the one advantage of the current API is that you can’t call
SDL_JoystickClose unless you have that pointer. And you don’t have
the pointer unless you opened it.

Plus, in C++, you’d be using a Vector most likely, so the issue of
managing a linked list is solved for you. If you’re using C, I
suppose you should already expect to be doing things a bit closer to
bare metal.

So maybe I’m suggesting a brittle solution to the problem of
programmer laziness? :slight_smile: Or perhaps, it really would’ve been much
easier if SDL 2.0 had moved to using instance ids throughout?

JosephOn Fri, Oct 11, 2013 at 09:48:13PM -0700, Sam Lantinga wrote:

The only reason that I’m not immediately accepting the patch is because
once you get the pointer, who owns it? Who should close it? What happens
if the code calling that isn’t aware of how many times that joystick has
been opened elsewhere?

It definitely serves a useful purpose for this, but I’d like to think
through some of the ramifications of adding this.

Ryan, other folks, what do you think?

On Fri, Oct 11, 2013 at 1:25 PM, T. Joseph Carter < @T_Joseph_Carter> wrote:

On Fri, Oct 11, 2013 at 05:08:06PM -0300, Sik the hedgehog wrote:

Of course, if you’re using the event API the way it ought to be used,

you get that pointer from SDL_JoystickOpen, save off the instance id
from the SDL_Joystick if you need to know it later on, and you ought
to be able to promptly forget about it. After all, it’s a pointer to
a structure internal to (and managed by) SDL.

Actually, this is related to the above. Polling functions make use of
SDL_Joystick, but events make use of the instance IDs instead. Yeah,
API inconsistency, but sadly the ABI is frozen by now which means this
can’t be changed.

This patch is probably the best workaround for this :stuck_out_tongue:

Part of the reason why the polling functions work on structures is that if
you hand SDL a structure, it doesn’t have to look up which stick you’re
polling. That simplifies the code quite a lot, and it also would be very
slow to test for all the various buttons and controls. It’s not two axes
and two buttons anymore. :slight_smile:

Hopefully my improvements to testgamecontroller and eventually also
testjoystick will serve as good models for how to do both. I would like to
see this patch (perhaps with a renamed function if someone has a better
name) make it into 2.0.1, basically before too many people find themselves
inventing workarounds they don’t need to.

Joseph

_____________**
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.orghttp://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I guess the conclusion of all this is that the entire joystick support
is a horrible mess.

2013/10/12, T. Joseph Carter :

But what if you use raw joysticks and game controllers in the same
program? Eventually I’m going to write a GameController mapper that
obviously must do exactly that. If the GameController opens the
joystick, but the program didn’t, the program shouldn’t go closing
the joystick when it receives the event. The program could track the
instance ids it has opened, and probably be wise to do so. But if
it’s gonna do that, it might as well track SDL_Joystick pointers
instead.

I guess the one advantage of the current API is that you can’t call
SDL_JoystickClose unless you have that pointer. And you don’t have
the pointer unless you opened it.

I guess the biggest problem is if you’re handling things like in my
game, where the input and the events are handled in completely
separate sections, then you have lots of glue code just to be able to
pass the relevant events to the input system, and the more thing one
has to care about, the more glue code is needed.

…or maybe I should be kicked and be demanded to do all the glue work :stuck_out_tongue:

Plus, in C++, you’d be using a Vector most likely, so the issue of
managing a linked list is solved for you. If you’re using C, I
suppose you should already expect to be doing things a bit closer to
bare metal.

To be fair, linked lists are overkill… I mean, you’re never going to
have more than a handful of joysticks connected to the same machine
(heck, I bet you could hardcode the maximum count to 4 and nobody
would notice), and adding and removing are extremely uncommon events,
to the point they may not even happen, and with such a small array, it
isn’t worth the complexity of a full blown list… yeah

So maybe I’m suggesting a brittle solution to the problem of
programmer laziness? :slight_smile: Or perhaps, it really would’ve been much
easier if SDL 2.0 had moved to using instance ids throughout?

Honestly IDs would have been better… except for the fact that an ID
can change its joystick at any moment, and a naively written program
(or worse, a cleverly written one with events being processed in a
separate thread) may end up not noticing that, and we’re back to
square one -_-’

If instance IDs weren’t reusable this may have been a non-problem I guess.

I guess the conclusion of all this is that the entire joystick support
is a horrible mess.

I wouldn’t call it that. The interface is actually pretty clean and
simple for the most part. It just didn’t get as profound a makeover
for 2.0 as some subsystems, aside from some under the hood support
for devices appearing and disappearing. That’s actually a rather big
change internally, but you don’t see much of it because the decision
was made not to change the API if it didn’t need changing.

The event interface returns an instance id mainly because that’s what
the event.which field can hold. That’s annoying in C because the
structure is private and you have to call a getter function to access
it. Call it good OO design or call it keeping some idiot from making
changes to a read-only structure. :wink:

I guess the one advantage of the current API is that you can’t call
SDL_JoystickClose unless you have that pointer. And you don’t have
the pointer unless you opened it.

I guess the biggest problem is if you’re handling things like in my
game, where the input and the events are handled in completely
separate sections, then you have lots of glue code just to be able to
pass the relevant events to the input system, and the more thing one
has to care about, the more glue code is needed.

…or maybe I should be kicked and be demanded to do all the glue work :stuck_out_tongue:

You can now have multiple event processors. That’s one of the neat
things about SDL 2.0’s event API. You can watch for input events in
your input code now.

Plus, in C++, you’d be using a Vector most likely, so the issue of
managing a linked list is solved for you. If you’re using C, I
suppose you should already expect to be doing things a bit closer to
bare metal.

To be fair, linked lists are overkill… I mean, you’re never going to
have more than a handful of joysticks connected to the same machine
(heck, I bet you could hardcode the maximum count to 4 and nobody
would notice), and adding and removing are extremely uncommon events,
to the point they may not even happen, and with such a small array, it
isn’t worth the complexity of a full blown list… yeah

I don’t use a list for GameControllers. I use an array. More than 4
will not be in use, so ? why bother?

Joysticks are a little more arbitrary. Think about flight simulator
stuff for people who are serious about it. Separate stick or yoke,
throttle control, pedals? And often these things are sold as
separate USB devices that are all vaguely “joysticks”. Throw in a
wiimote and maybe a couple of gamepads and you’ve got a lot of random
sticks to handle.

So maybe I’m suggesting a brittle solution to the problem of
programmer laziness? :slight_smile: Or perhaps, it really would’ve been much
easier if SDL 2.0 had moved to using instance ids throughout?

Honestly IDs would have been better… except for the fact that an ID
can change its joystick at any moment, and a naively written program
(or worse, a cleverly written one with events being processed in a
separate thread) may end up not noticing that, and we’re back to
square one -_-’

If instance IDs weren’t reusable this may have been a non-problem I guess.

Ah, but instance IDs are NOT reusable. :slight_smile: That you didn’t realize
that explains why you’d think the API is such a mess. It really
isn’t. In SDL 2.0, there are three ways a joystick is identified,
based on what you’re doing with it. They’re all related:

SDL’s internal representation is the instance id. As new joysticks
are found (at startup or while SDL is running), it’s given the next
instance ID. On the Mac, my first joystick was given instance ID 4
until Sam committed a patch that didn’t allow anything but a joystick
to increment the instance ID counter on Darwin systems. Instance IDs
are never reused, and since they’re not guaranteed to start at 0,
they’re useless for loop iteration.

Once a joystick is opened, SDL wants more info about the joystick,
and that goes in the SDL_Joystick structure. Its contents should not
be modified, so as noted you have to call getters if you want the
info contained within.

That leaves opening the joystick. In 1.2, joysticks didn’t use
instance IDs like they do now. They used a device index guaranteed
to be in the range 0 to SDL_NumJoysticks(). Sound familiar? If you
could name anything in the joystick API as “legacy code”, it’s the
device index. It was clearly kept for two reasons:

  1. You cannot iterate over instance IDs for all connected joysticks.

  2. The alternative would be to have a loop, but then call a function
    to get the instance ID for the current loop count so you could open
    or query the joystick’s basic info. If you did that, code written
    for 1.2’s device indices would compile and then break quietly,
    leading to frustrating bugs (probably for users, not developers) and
    create all kinds of headaches.

So SDL still uses device indices and they are guaranteed to be
something you can loop over. Because of that, SDL_JOYDEVICEADDED is
the one joystick event that does NOT contain an instance ID. It
comes with a device index. This is documented in SDL_joystick.h but
not yet on the wiki.

JosephOn Sat, Oct 12, 2013 at 10:47:50AM -0300, Sik the hedgehog wrote:

2013/10/12, T. Joseph Carter :

The event interface returns an instance id mainly because that’s what
the event.which field can hold.

Technically, the events used for adding or removing joysticks have its
own set of fields, so really there wasn’t any reason to not just
modify it to have a pointer instead. Now the ABI is frozen and that
can’t be done, sadly.

The biggest problem is that events seem to want instances while
polling seems to want the structure. Which wouldn’t be much of an
issue if it wasn’t because both rely on SDL_JoystickClose, and that
one needs the structure (good if you’re polling, not good
otherwise…).

Ah, but instance IDs are NOT reusable. :slight_smile: That you didn’t realize
that explains why you’d think the API is such a mess.

Screw that, it seems it’s the device indexes that are reused. The fact
that there are both indexes and instances is just ridiculous -_-’