libgdx / Jamepad

A better way to use gamepads in Java
Apache License 2.0
20 stars 13 forks source link

Doesn't react to controller being turned on #5

Closed morvael closed 2 years ago

morvael commented 3 years ago

When the app is turned on before the controller, it will never start working (unless perhaps quitSDLGamepad and initSDLGamepad will be called). Calling ControllerManager.update does nothing.

MrStahlfelge commented 3 years ago

It is working for gdx-controllers desktop (which uses this lib), please check the implementation: https://github.com/libgdx/gdx-controllers/tree/master/gdx-controllers-desktop/src/main/java/com/badlogic/gdx/controllers/desktop

morvael commented 3 years ago

In my case getNumControllers always returns 0, and checking ControllerIndex like JamepadControllerMonitor (used by JamepadControllerManager) to maxNumControllers shows all are always disconnected. I have a wireless Xbox pad with adapter.

morvael commented 3 years ago

I'm trying to use this in a non-gdx project.

Issue number 1: had to manually specify gdx-jnigen-loader version in my pom, because the pom for Jamepad 2.0.14.1 wants gdx-jnigen-loader 2.0.0-SNAPSHOT, and by default SNAPSHOTs are not downloaded by Maven.

Issue number 2: had to extend ControllerManager and provide gamecontrollerdb.txt inside my jar for the mappings to load correctly (I think jamepad relies on the file from gdx-controllers-desktop). Luckily it uses getClass() do get the resource, so a workaround is possible.

Issue number 3: getLastNativeError from initSDLGamepad returns Couldn't find mapping for device (3), but I think it's a minor problem for some device that can be ignored. It exists whether the gamepad works (turned before app is started) or not (turned after the app is started).

Tried to find if the issue is in nativeControllerConnectedOrDisconnected, by manually calling reconnectController for all ControllerIndex objects, but it doesn't help. Simply put, when the pad is turned on after the app starts, getNumControllers will always return 0, and all ControllerIndex will return false from isConnected, even after calling reconnectController. When the pad is turned on before the app starts, getNumControllers returns 1, and ControllerIndex at index 0 is connected.

morvael commented 3 years ago

Likewise, turning the controller off when it works in the app will make no effect on the app - it will still show it as connected.

morvael commented 3 years ago

It makes no difference whether it's the actual pad that is turned on or off, or the wireless dongle that is plugged in or out of an USB port. It seems like the library recognizes only the at-app-start status of the controller(s), and nothing can change this later.

MrStahlfelge commented 3 years ago

I can safely say this is not a general problem as hot plugging is possible with this lib on Mac, Windows and Linux. Either there is a device problem or an implementation problem. I get that you don't want to use the lib with gdx, but using the test application gdx-controllers provides can give you a hint if you have a device problem or implementation problem.

morvael commented 3 years ago

Issue number 4: after using quitSDLGamepad it's impossible to reuse the object by calling initSDLGamepad, because controllers array will stay at 0 length.

I got it working by destroying the controller manager object in every loop.

          cm.quitSDLGamepad();
          cm = new GamePadControllerManager(configuration);
          cm.initSDLGamepad();
          cm.update();

Only in this case will it detect connected/disconnected controller. So somehow the SDL is not refreshing correctly.

morvael commented 3 years ago

The API is simple so it's not an implementation problem. The device is working.

Hotplugging works for me when using the https://github.com/electronstudio/sdl2gdx library, but it has its own set of problems.

IMHO somethings wrong with the SDL layer when this library is used without GDX.

morvael commented 3 years ago

Perhaps GDX does some SDL_refresh (if there is such a thing, I'm just imaginig this), while this app when standalone doesn't.

morvael commented 3 years ago

Maybe it's about SDL_PumpEvents?

morvael commented 3 years ago

It seems sdl2gdx uses SDL_PumpEvents instead of SDL_JoystickUpdate (though documentation says SDL_PollEvent uses SDL_PumpEvents internally).

morvael commented 3 years ago

It also adds some more hints to SDL: https://wiki.libsdl.org/SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS https://wiki.libsdl.org/SDL_HINT_MAC_BACKGROUND_APP

MrStahlfelge commented 3 years ago

Perhaps GDX does some SDL_refresh (if there is such a thing, I'm just imaginig this), while this app when standalone doesn't.

I would suggest you to check the code, it is open source in the linked repo :)

morvael commented 3 years ago

This library is advertised as being able to work without gdx ("The following information is only needed for non-gdx Java projects"), but it doesn't. Refering to gdx and their examples is not helpful in that case, I think there is place for a Jamepad-only example. The core way to use the API is:

ControllerManager cm = new ControllerManager();
cm.initSDLGamepad();
while (doWork) {
  cm.update();
  ...
}
cm.quitSDLGamepad();

and it doesn't work when it comes to detecting connected/disconnected controllers while the app is running. It only works when used this way:

ControllerManager cm = new ControllerManager();
cm.initSDLGamepad();
while (doWork) {
  cm.quitSDLGamepad();
  cm = new ControllerManager();
  cm.initSDLGamepad();
  cm.update();
  ...
}
cm.quitSDLGamepad();

which means full SDL re-init is needed to get a snapshot of the controllers connected to the system. Something doesn't work correcty in the cm.update(); (at least when not using GDX).

MrStahlfelge commented 2 years ago

The library does as it should when used within the libgdx convinience wrapper gdx-controllers. If it does not work for you, compare where your code differs from that wrapper and track down what's the problem. If you find that there's a problem in Jamepad that needs to be fixed, feel free to open a PR with the changes.