Port rumble support for SDL from moonlight-qt

This commit is contained in:
Iwan Timmer
2019-02-16 15:37:09 +01:00
parent 2adf943980
commit 0868f0295e
5 changed files with 76 additions and 16 deletions

View File

@@ -25,6 +25,7 @@
pthread_t main_thread_id = 0;
bool connection_debug;
ConnListenerRumble rumble_handler = NULL;
static void connection_terminated() {
if (main_thread_id != 0)
@@ -46,6 +47,11 @@ static void connection_log_message(const char* format, ...) {
va_end(arglist);
}
static void rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor) {
if (rumble_handler)
rumble_handler(controllerNumber, lowFreqMotor, highFreqMotor);
}
CONNECTION_LISTENER_CALLBACKS connection_callbacks = {
.stageStarting = NULL,
.stageComplete = NULL,
@@ -55,4 +61,5 @@ CONNECTION_LISTENER_CALLBACKS connection_callbacks = {
.displayMessage = connection_display_message,
.displayTransientMessage = connection_display_transient_message,
.logMessage = connection_log_message,
.rumble = rumble,
};

View File

@@ -25,3 +25,4 @@
extern CONNECTION_LISTENER_CALLBACKS connection_callbacks;
extern pthread_t main_thread_id;
extern bool connection_debug;
extern ConnListenerRumble rumble_handler;

View File

@@ -33,6 +33,8 @@ typedef struct _GAMEPAD_STATE {
short rightStickX, rightStickY;
int buttons;
SDL_JoystickID sdl_id;
SDL_Haptic* haptic;
int haptic_effect_id;
short id;
bool initialized;
} GAMEPAD_STATE, *PGAMEPAD_STATE;
@@ -44,22 +46,6 @@ static int activeGamepadMask = 0;
int sdl_gamepads = 0;
void sdlinput_init(char* mappings) {
memset(gamepads, 0, sizeof(gamepads));
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
SDL_GameControllerAddMappingsFromFile(mappings);
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
if (SDL_IsGameController(i)) {
sdl_gamepads++;
if (!SDL_GameControllerOpen(i)) {
fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
}
}
}
}
static PGAMEPAD_STATE get_gamepad(SDL_JoystickID sdl_id) {
for (int i = 0;i<4;i++) {
if (!gamepads[i].initialized) {
@@ -74,6 +60,40 @@ static PGAMEPAD_STATE get_gamepad(SDL_JoystickID sdl_id) {
return &gamepads[0];
}
static void init_gamepad(int joystick_index) {
if (SDL_IsGameController(joystick_index)) {
sdl_gamepads++;
SDL_GameController* controller = SDL_GameControllerOpen(joystick_index);
if (!controller) {
fprintf(stderr, "Could not open gamecontroller %i: %s\n", joystick_index, SDL_GetError());
return;
}
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
SDL_Haptic* haptic = SDL_HapticOpenFromJoystick(joystick);
if (haptic && (SDL_HapticQuery(haptic) & SDL_HAPTIC_LEFTRIGHT) == 0) {
SDL_HapticClose(haptic);
haptic = NULL;
}
SDL_JoystickID sdl_id = SDL_JoystickInstanceID(joystick);
PGAMEPAD_STATE state = get_gamepad(joystick_index);
state->haptic = haptic;
state->haptic_effect_id = -1;
}
}
void sdlinput_init(char* mappings) {
memset(gamepads, 0, sizeof(gamepads));
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
SDL_InitSubSystem(SDL_INIT_HAPTIC);
SDL_GameControllerAddMappingsFromFile(mappings);
for (int i = 0; i < SDL_NumJoysticks(); ++i)
init_gamepad(i);
}
int sdlinput_handle_event(SDL_Event* event) {
int button = 0;
PGAMEPAD_STATE gamepad;
@@ -250,3 +270,33 @@ int sdlinput_handle_event(SDL_Event* event) {
}
return SDL_NOTHING;
}
void sdlinput_rumble(unsigned short controller_id, unsigned short low_freq_motor, unsigned short high_freq_motor) {
if (controller_id >= 4)
return;
PGAMEPAD_STATE state = &gamepads[controller_id];
SDL_Haptic* haptic = state->haptic;
if (!haptic)
return;
if (state->haptic_effect_id >= 0)
SDL_HapticDestroyEffect(haptic, state->haptic_effect_id);
if (low_freq_motor == 0 && high_freq_motor == 0)
return;
SDL_HapticEffect effect;
SDL_memset(&effect, 0, sizeof(effect));
effect.type = SDL_HAPTIC_LEFTRIGHT;
effect.leftright.length = SDL_HAPTIC_INFINITY;
// SDL haptics range from 0-32767 but XInput uses 0-65535, so divide by 2 to correct for SDL's scaling
effect.leftright.large_magnitude = low_freq_motor / 2;
effect.leftright.small_magnitude = high_freq_motor / 2;
state->haptic_effect_id = SDL_HapticNewEffect(haptic, &effect);
if (state->haptic_effect_id >= 0)
SDL_HapticRunEffect(haptic, state->haptic_effect_id, 1);
}

View File

@@ -101,3 +101,4 @@ static const short keyCodes5[] = {
void sdlinput_init(char* mappings);
int sdlinput_handle_event(SDL_Event* event);
void sdlinput_rumble(unsigned short controller_id, unsigned short low_freq_motor, unsigned short high_freq_motor);

View File

@@ -324,6 +324,7 @@ int main(int argc, char* argv[]) {
sdl_init(config.stream.width, config.stream.height, config.fullscreen);
sdlinput_init(config.mapping);
rumble_handler = sdlinput_rumble;
}
#endif