From aaa1ca7079efa409d0086949b1fb75e6c4b7f13a Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 20 Oct 2022 06:52:28 +0000 Subject: [PATCH] Added controller rumble support. Pepper SDK and NaCl in general is EOL for Chrome, although still supported for Chrome Apps. This means that the Pepper Gamepad API was never updated with rumble support so in order to add rumble support, rumble messages from Gamestream have to be forwarded to JavaScript and handled with gamepad.vibrationActuator.playEffect(). Side note, Chrome limits the duration of playEffect to 5 seconds and requesting more than that causes the vibration request to be rejected. --- connectionlistener.cpp | 1 + gamepad.cpp | 13 +++++++++++++ manifest.json | 2 +- moonlight.hpp | 1 + static/js/messages.js | 12 ++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/connectionlistener.cpp b/connectionlistener.cpp index 37c84e2..3174a18 100644 --- a/connectionlistener.cpp +++ b/connectionlistener.cpp @@ -61,4 +61,5 @@ CONNECTION_LISTENER_CALLBACKS MoonlightInstance::s_ClCallbacks = { .connectionStarted = MoonlightInstance::ClConnectionStarted, .connectionTerminated = MoonlightInstance::ClConnectionTerminated, .logMessage = MoonlightInstance::ClLogMessage, + .rumble = MoonlightInstance::ClControllerRumble, }; diff --git a/gamepad.cpp b/gamepad.cpp index 93df0fc..eac6979 100644 --- a/gamepad.cpp +++ b/gamepad.cpp @@ -4,6 +4,8 @@ #include +#include + static const unsigned short k_StandardGamepadButtonMapping[] = { A_FLAG, B_FLAG, X_FLAG, Y_FLAG, LB_FLAG, RB_FLAG, @@ -127,3 +129,14 @@ void MoonlightInstance::PollGamepads() { controllerIndex++; } } + +void MoonlightInstance::ClControllerRumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor) +{ + const float weakMagnitude = static_cast(highFreqMotor) / static_cast(UINT16_MAX); + const float strongMagnitude = static_cast(lowFreqMotor) / static_cast(UINT16_MAX); + + std::ostringstream ss; + ss << controllerNumber << "," << weakMagnitude << "," << strongMagnitude; + pp::Var response(std::string("controllerRumble: ") + ss.str()); + g_Instance->PostMessage(response); +} \ No newline at end of file diff --git a/manifest.json b/manifest.json index ac1aef2..2a509bb 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Moonlight Game Streaming", "short_name": "Moonlight", - "version": "0.10.21", + "version": "0.10.22", "description": "Open-source client for NVIDIA GameStream", "icons": { "128": "icons/icon128.png", diff --git a/moonlight.hpp b/moonlight.hpp index 656b0c0..8af689b 100644 --- a/moonlight.hpp +++ b/moonlight.hpp @@ -137,6 +137,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { static void ClDisplayMessage(const char* message); static void ClDisplayTransientMessage(const char* message); static void ClLogMessage(const char* format, ...); + static void ClControllerRumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor); static Shader CreateProgram(const char* vertexShader, const char* fragmentShader); static void CreateShader(GLuint program, GLenum type, const char* source, int size); diff --git a/static/js/messages.js b/static/js/messages.js index d8ab820..3a0970d 100644 --- a/static/js/messages.js +++ b/static/js/messages.js @@ -81,6 +81,18 @@ function handleMessage(msg) { snackbarLogLong(msg.data.replace('DialogMsg: ', '')); } else if (msg.data === 'displayVideo') { $("#listener").addClass("fullscreen"); + } else if (msg.data.indexOf('controllerRumble: ' ) === 0) { + const eventData = msg.data.split( ' ' )[1].split(','); + const gamepadIdx = parseInt(eventData[0]); + const weakMagnitude = parseFloat(eventData[1]); + const strongMagnitude = parseFloat(eventData[2]); + console.log("Playing rumble on gamepad " + gamepadIdx + " with weakMagnitude " + weakMagnitude + " and strongMagnitude " + strongMagnitude); + navigator.getGamepads()[gamepadIdx].vibrationActuator.playEffect('dual-rumble', { + startDelay: 0, + duration: 5000, // Moonlight should be sending another rumble event when stopping. + weakMagnitude: weakMagnitude, + strongMagnitude: strongMagnitude, + }); } } }