mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-10 05:34:17 +00:00
Implement controller LED and battery protocol extensions
This commit is contained in:
parent
b6d203b6dd
commit
df283d80c6
5 changed files with 120 additions and 1 deletions
|
@ -64,6 +64,47 @@ void SdlInputHandler::sendGamepadState(GamepadState* state)
|
|||
state->rsY);
|
||||
}
|
||||
|
||||
void SdlInputHandler::sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level)
|
||||
{
|
||||
uint8_t batteryPercentage;
|
||||
uint8_t batteryState;
|
||||
|
||||
// SDL's battery reporting capabilities are quite limited. Notably, we cannot
|
||||
// tell the battery level while charging (or even if a battery is present).
|
||||
// We also cannot tell the percentage of charge exactly in any case.
|
||||
switch (level)
|
||||
{
|
||||
case SDL_JOYSTICK_POWER_UNKNOWN:
|
||||
batteryState = LI_BATTERY_STATE_UNKNOWN;
|
||||
batteryPercentage = LI_BATTERY_PERCENTAGE_UNKNOWN;
|
||||
break;
|
||||
case SDL_JOYSTICK_POWER_WIRED:
|
||||
batteryState = LI_BATTERY_STATE_CHARGING;
|
||||
batteryPercentage = LI_BATTERY_PERCENTAGE_UNKNOWN;
|
||||
break;
|
||||
case SDL_JOYSTICK_POWER_EMPTY:
|
||||
batteryState = LI_BATTERY_STATE_DISCHARGING;
|
||||
batteryPercentage = 5;
|
||||
break;
|
||||
case SDL_JOYSTICK_POWER_LOW:
|
||||
batteryState = LI_BATTERY_STATE_DISCHARGING;
|
||||
batteryPercentage = 20;
|
||||
break;
|
||||
case SDL_JOYSTICK_POWER_MEDIUM:
|
||||
batteryState = LI_BATTERY_STATE_DISCHARGING;
|
||||
batteryPercentage = 50;
|
||||
break;
|
||||
case SDL_JOYSTICK_POWER_FULL:
|
||||
batteryState = LI_BATTERY_STATE_DISCHARGING;
|
||||
batteryPercentage = 90;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
LiSendControllerBatteryEvent(state->index, batteryState, batteryPercentage);
|
||||
}
|
||||
|
||||
Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param)
|
||||
{
|
||||
auto gamepad = reinterpret_cast<GamepadState*>(param);
|
||||
|
@ -364,6 +405,20 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent*
|
|||
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
|
||||
void SdlInputHandler::handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendGamepadBatteryState(state, event->level);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event)
|
||||
{
|
||||
GamepadState* state;
|
||||
|
@ -489,6 +544,8 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
|||
SDL_assert(m_GamepadMask == 0x1);
|
||||
}
|
||||
|
||||
SDL_JoystickPowerLevel powerLevel = SDL_JoystickCurrentPowerLevel(SDL_GameControllerGetJoystick(state->controller));
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
// On SDL 2.0.14 and later, we can provide enhanced controller information to the host PC
|
||||
// for it to use as a hint for the type of controller to emulate.
|
||||
|
@ -520,6 +577,12 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
|||
if (SDL_GameControllerHasSensor(state->controller, SDL_SENSOR_GYRO)) {
|
||||
capabilities |= LI_CCAP_GYRO;
|
||||
}
|
||||
if (powerLevel != SDL_JOYSTICK_POWER_UNKNOWN || SDL_VERSION_ATLEAST(2, 24, 0)) {
|
||||
capabilities |= LI_CCAP_BATTERY_STATE;
|
||||
}
|
||||
if (SDL_GameControllerHasLED(state->controller)) {
|
||||
capabilities |= LI_CCAP_RGB_LED;
|
||||
}
|
||||
|
||||
uint8_t type;
|
||||
switch (SDL_GameControllerGetType(state->controller)) {
|
||||
|
@ -549,6 +612,11 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
|||
// Send an empty event to tell the PC we've arrived
|
||||
sendGamepadState(state);
|
||||
#endif
|
||||
|
||||
// Send a power level if it's known at this time
|
||||
if (powerLevel != SDL_JOYSTICK_POWER_UNKNOWN) {
|
||||
sendGamepadBatteryState(state, powerLevel);
|
||||
}
|
||||
}
|
||||
else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||
state = findStateForGamepad(event->which);
|
||||
|
@ -716,6 +784,20 @@ void SdlInputHandler::setMotionEventState(uint16_t controllerNumber, uint8_t mot
|
|||
#endif
|
||||
}
|
||||
|
||||
void SdlInputHandler::setControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// Make sure the controller number is within our supported count
|
||||
if (controllerNumber >= MAX_GAMEPADS) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
if (m_GamepadState[controllerNumber].controller != nullptr) {
|
||||
SDL_GameControllerSetLED(m_GamepadState[controllerNumber].controller, r, g, b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString SdlInputHandler::getUnmappedGamepads()
|
||||
{
|
||||
QString ret;
|
||||
|
|
|
@ -72,6 +72,10 @@ public:
|
|||
void handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event);
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
void handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event);
|
||||
#endif
|
||||
|
||||
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
|
||||
|
||||
void sendText(QString& string);
|
||||
|
@ -82,6 +86,8 @@ public:
|
|||
|
||||
void setMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
|
||||
|
||||
void setControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
void handleTouchFingerEvent(SDL_TouchFingerEvent* event);
|
||||
|
||||
int getAttachedGamepadMask();
|
||||
|
@ -126,6 +132,8 @@ private:
|
|||
|
||||
void sendGamepadState(GamepadState* state);
|
||||
|
||||
void sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level);
|
||||
|
||||
void handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event);
|
||||
|
||||
void emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define SDL_CODE_GAMECONTROLLER_RUMBLE 101
|
||||
#define SDL_CODE_GAMECONTROLLER_RUMBLE_TRIGGERS 102
|
||||
#define SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE 103
|
||||
#define SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED 104
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
@ -66,6 +67,7 @@ CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
|
|||
Session::clSetHdrMode,
|
||||
Session::clRumbleTriggers,
|
||||
Session::clSetMotionEventState,
|
||||
Session::clSetControllerLED,
|
||||
};
|
||||
|
||||
Session* Session::s_ActiveSession;
|
||||
|
@ -243,6 +245,19 @@ void Session::clSetMotionEventState(uint16_t controllerNumber, uint8_t motionTyp
|
|||
SDL_PushEvent(&setMotionEventStateEvent);
|
||||
}
|
||||
|
||||
void Session::clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// 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_CONTROLLER_LED;
|
||||
setControllerLEDEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
setControllerLEDEvent.user.data2 = (void*)(uintptr_t)(r << 16 | g << 8 | b);
|
||||
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)
|
||||
|
@ -1679,6 +1694,12 @@ void Session::execInternal()
|
|||
(uint8_t)((uintptr_t)event.user.data2 >> 16),
|
||||
(uint16_t)((uintptr_t)event.user.data2 & 0xFFFF));
|
||||
break;
|
||||
case SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED:
|
||||
m_InputHandler->setControllerLED((uint16_t)(uintptr_t)event.user.data1,
|
||||
(uint8_t)((uintptr_t)event.user.data2 >> 16),
|
||||
(uint8_t)((uintptr_t)event.user.data2 >> 8),
|
||||
(uint8_t)((uintptr_t)event.user.data2));
|
||||
break;
|
||||
default:
|
||||
SDL_assert(false);
|
||||
}
|
||||
|
@ -1874,6 +1895,11 @@ void Session::execInternal()
|
|||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
m_InputHandler->handleControllerTouchpadEvent(&event.ctouchpad);
|
||||
break;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
case SDL_JOYBATTERYUPDATED:
|
||||
m_InputHandler->handleJoystickBatteryEvent(&event.jbattery);
|
||||
break;
|
||||
#endif
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
|
|
|
@ -130,6 +130,9 @@ private:
|
|||
static
|
||||
void clSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
|
||||
|
||||
static
|
||||
void clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
static
|
||||
int arInit(int audioConfiguration,
|
||||
const POPUS_MULTISTREAM_CONFIGURATION opusConfig,
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 28d63b11ddb808662f0a7d90674a1376d99059c4
|
||||
Subproject commit c0792168f5a7ed48fc6feeb7fce01b83df405df2
|
Loading…
Reference in a new issue