libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.72k stars 1.8k forks source link

SDL_GameControllerRumble() not working despite SDL_GameControllerHasRumble() returning true? #7080

Closed SuperFromND closed 1 year ago

SuperFromND commented 1 year ago

SDL Version: 2.0.22 Operating System: Windows 7 Professional SP1 x64 Compiler: g++ (MinGW-W64 x86_64) 11.2.0 Compile Command: g++ src/rumble.cpp -o bin/rumble.exe -lmingw32 -lSDL2main -lSDL2 -lopengl32

I'm trying to make a simple SDL2 program that, when the user presses a keyboard key, it rumbles whatever controller they have plugged in. However, for some reason, SDL2's not actually able to rumble the controller despite claiming the controller supports rumble.

According to the docs, "SDL_GameControllerRumble()" returns a 0 on success, and -1 "if rumble isn't supported on this controller". "SDL_GameControllerHasRumble()" is similar, returning either TRUE or FALSE depending on whether the controller in question supports rumble.

Indeed, "SDL_GameControllerHasRumble()" returns true for the controller I'm using to test (a PowerA Xbox Series X controller), and I can confirm using this site the controller has fully functioning rumble. Yet despite this "SDL_GameControllerRumble()" returns -1! Somehow, SDL2 both claims my controller supports rumble, but the actual rumble function fails anyways seemingly due to NOT supporting rumble.

The code I'm using:

#include <SDL2/SDL.h>
#include <cstdio>

int width = 640;
int height = 480;

int main(int argc, char **argv) {
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window *window = SDL_CreateWindow("Rumble Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_RESIZABLE);
    SDL_GameController *cont = SDL_GameControllerOpen(0);

    if (SDL_GameControllerHasRumble(cont) == SDL_FALSE) {
        printf("No rumble support?\n");
    } else {
        printf("There's rumble support!\n");
    }

    bool running = 1;
    while (running) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                running = false;
            }

            if (event.type == SDL_WINDOWEVENT) {
                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    SDL_GetWindowSize(window, &width, &height);
                    printf("Window resized! %i %i\n", width, height);
                }
            }

            if (event.type == SDL_KEYDOWN) {
                if (SDL_GameControllerRumble(cont, 0xffff, 0xffff, 2000) == -1) {
                    printf("Rumble failed...?\n");
                } else {
                    printf("Rumble success!\n");
                }
            }
        }
    }

    return 0;
}

Is SDL2 at fault here, or am I missing something?

slouken commented 1 year ago

SDL doesn't know which XInput slot the controller is in until there's input on the controller. Do you still have an issue after you press a button on the controller?

SuperFromND commented 1 year ago

Pressing buttons on the controller on its own didn't seem to help at all. However, once I changed this line:

-           if (event.type == SDL_KEYDOWN) {
+           if (event.type == SDL_CONTROLLERBUTTONDOWN) {

After pressing a few buttons, it started to worked as intended, so that solves that! Thank you!