Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/streaming/input/gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,22 @@ void SdlInputHandler::setControllerLED(uint16_t controllerNumber, uint8_t r, uin
#endif
}

void SdlInputHandler::setAdaptiveTriggers(uint16_t controllerNumber, DualSenseOutputReport *report){

#if SDL_VERSION_ATLEAST(2, 0, 16)
// Make sure the controller number is within our supported count
if (controllerNumber <= MAX_GAMEPADS &&
// and we have a valid controller
m_GamepadState[controllerNumber].controller != nullptr &&
// and it's a PS5 controller
SDL_GameControllerGetType(m_GamepadState[controllerNumber].controller) == SDL_CONTROLLER_TYPE_PS5) {
SDL_GameControllerSendEffect(m_GamepadState[controllerNumber].controller, report, sizeof(*report));
}
#endif

SDL_free(report);
}

QString SdlInputHandler::getUnmappedGamepads()
{
QString ret;
Expand Down
33 changes: 33 additions & 0 deletions app/streaming/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,37 @@ struct GamepadState {
unsigned char lt, rt;
};


struct DualSenseOutputReport{
uint8_t validFlag0;
uint8_t validFlag1;

/* For DualShock 4 compatibility mode. */
uint8_t motorRight;
uint8_t motorLeft;

/* Audio controls */
uint8_t reserved[4];
uint8_t muteButtonLed;

uint8_t powerSaveControl;
uint8_t rightTriggerEffectType;
uint8_t rightTriggerEffect[DS_EFFECT_PAYLOAD_SIZE];
uint8_t leftTriggerEffectType;
uint8_t leftTriggerEffect[DS_EFFECT_PAYLOAD_SIZE];
uint8_t reserved2[6];

/* LEDs and lightbar */
uint8_t validFlag2;
uint8_t reserved3[2];
uint8_t lightbarSetup;
uint8_t ledBrightness;
uint8_t playerLeds;
uint8_t lightbarRed;
uint8_t lightbarGreen;
uint8_t lightbarBlue;
};

// activeGamepadMask is a short, so we're bounded by the number of mask bits
#define MAX_GAMEPADS 16

Expand Down Expand Up @@ -95,6 +126,8 @@ class SdlInputHandler

void setControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);

void setAdaptiveTriggers(uint16_t controllerNumber, DualSenseOutputReport *report);

void handleTouchFingerEvent(SDL_TouchFingerEvent* event);

int getAttachedGamepadMask();
Expand Down
30 changes: 30 additions & 0 deletions app/streaming/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#define SDL_CODE_GAMECONTROLLER_RUMBLE_TRIGGERS 102
#define SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE 103
#define SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED 104
#define SDL_CODE_GAMECONTROLLER_SET_ADAPTIVE_TRIGGERS 105

#include <openssl/rand.h>

Expand Down Expand Up @@ -69,6 +70,7 @@ CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
Session::clRumbleTriggers,
Session::clSetMotionEventState,
Session::clSetControllerLED,
Session::clSetAdaptiveTriggers
};

Session* Session::s_ActiveSession;
Expand Down Expand Up @@ -259,6 +261,30 @@ void Session::clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g
SDL_PushEvent(&setControllerLEDEvent);
}

void Session::clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlags, uint8_t typeLeft, uint8_t typeRight, uint8_t *left, uint8_t *right){
// We push an event for the main thread to handle in order to properly synchronize
// with the removal of game controllers that could result in our game controller
// going away during this callback.
SDL_Event setControllerLEDEvent = {};
setControllerLEDEvent.type = SDL_USEREVENT;
setControllerLEDEvent.user.code = SDL_CODE_GAMECONTROLLER_SET_ADAPTIVE_TRIGGERS;
setControllerLEDEvent.user.data1 = (void*)(uintptr_t)controllerNumber;

// Based on the following SDL code:
// https://github.com/libsdl-org/SDL/blob/120c76c84bbce4c1bfed4e9eb74e10678bd83120/test/testgamecontroller.c#L286-L307
DualSenseOutputReport *state = (DualSenseOutputReport *) SDL_malloc(sizeof(DualSenseOutputReport));
SDL_zero(*state);
state->validFlag0 = (eventFlags & DS_EFFECT_RIGHT_TRIGGER) | (eventFlags & DS_EFFECT_LEFT_TRIGGER);
state->rightTriggerEffectType = typeRight;
SDL_memcpy(state->rightTriggerEffect, right, sizeof(state->rightTriggerEffect));
state->leftTriggerEffectType = typeLeft;
SDL_memcpy(state->leftTriggerEffect, left, sizeof(state->leftTriggerEffect));

setControllerLEDEvent.user.data2 = (void *) state;
SDL_PushEvent(&setControllerLEDEvent);
}


bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
SDL_Window* window, int videoFormat, int width, int height,
int frameRate, bool enableVsync, bool enableFramePacing, bool testOnly, IVideoDecoder*& chosenDecoder)
Expand Down Expand Up @@ -2041,6 +2067,10 @@ void Session::execInternal()
(uint8_t)((uintptr_t)event.user.data2 >> 8),
(uint8_t)((uintptr_t)event.user.data2));
break;
case SDL_CODE_GAMECONTROLLER_SET_ADAPTIVE_TRIGGERS:
m_InputHandler->setAdaptiveTriggers((uint16_t)(uintptr_t)event.user.data1,
(DualSenseOutputReport *)event.user.data2);
break;
default:
SDL_assert(false);
}
Expand Down
3 changes: 3 additions & 0 deletions app/streaming/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ class Session : public QObject
static
void clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);

static
void clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlags, uint8_t typeLeft, uint8_t typeRight, uint8_t *left, uint8_t *right);

static
int arInit(int audioConfiguration,
const POPUS_MULTISTREAM_CONFIGURATION opusConfig,
Expand Down