Plumb new Sunshine protocol extensions

This commit is contained in:
Cameron Gutman
2023-06-24 15:19:50 -05:00
parent 7f15f45beb
commit ddefda3afa
11 changed files with 228 additions and 48 deletions

View File

@@ -2104,12 +2104,24 @@ public class Game extends Activity implements SurfaceHolder.Callback,
controllerHandler.handleRumble(controllerNumber, lowFreqMotor, highFreqMotor);
}
@Override
public void rumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
LimeLog.info(String.format((Locale)null, "Rumble on gamepad triggers %d: %04x %04x", controllerNumber, leftTrigger, rightTrigger));
controllerHandler.handleRumbleTriggers(controllerNumber, leftTrigger, rightTrigger);
}
@Override
public void setHdrMode(boolean enabled, byte[] hdrMetadata) {
LimeLog.info("Display HDR mode: " + (enabled ? "enabled" : "disabled"));
decoderRenderer.setHdrMode(enabled, hdrMetadata);
}
@Override
public void setMotionEventState(short controllerNumber, byte motionType, short reportRateHz) {
controllerHandler.handleSetMotionEventState(controllerNumber, motionType, reportRateHz);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (!surfaceCreated) {

View File

@@ -817,7 +817,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
// Take the context's controller number and fuse all inputs with the same number
short controllerNumber = originalContext.controllerNumber;
short inputMap = 0;
int inputMap = 0;
byte leftTrigger = 0;
byte rightTrigger = 0;
short leftStickX = 0;
@@ -1473,6 +1473,14 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
}
public void handleRumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
// TODO
}
public void handleSetMotionEventState(short controllerNumber, byte motionType, short reportRateHz) {
// TODO
}
public boolean handleButtonUp(KeyEvent event) {
InputDeviceContext context = getContextForEvent(event);
if (context == null) {
@@ -1794,7 +1802,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
return true;
}
public void reportOscState(short buttonFlags,
public void reportOscState(int buttonFlags,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY,
byte leftTrigger, byte rightTrigger) {
@@ -1813,7 +1821,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
@Override
public void reportControllerState(int controllerId, short buttonFlags,
public void reportControllerState(int controllerId, int buttonFlags,
float leftStickX, float leftStickY,
float rightStickX, float rightStickY,
float leftTrigger, float rightTrigger) {
@@ -1883,7 +1891,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
public boolean reservedControllerNumber;
public short controllerNumber;
public short inputMap = 0x0000;
public int inputMap = 0;
public byte leftTrigger = 0x00;
public byte rightTrigger = 0x00;
public short rightStickX = 0x0000;
@@ -1892,7 +1900,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
public short leftStickY = 0x0000;
public boolean mouseEmulationActive;
public short mouseEmulationLastInputMap;
public int mouseEmulationLastInputMap;
public final int mouseEmulationReportPeriod = 50;
public final Runnable mouseEmulationRunnable = new Runnable() {

View File

@@ -1,7 +1,7 @@
package com.limelight.binding.input.driver;
public interface UsbDriverListener {
void reportControllerState(int controllerId, short buttonFlags,
void reportControllerState(int controllerId, int buttonFlags,
float leftStickX, float leftStickY,
float rightStickX, float rightStickY,
float leftTrigger, float rightTrigger);

View File

@@ -42,7 +42,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
private int nextDeviceId;
@Override
public void reportControllerState(int controllerId, short buttonFlags, float leftStickX, float leftStickY, float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
public void reportControllerState(int controllerId, int buttonFlags, float leftStickX, float leftStickY,
float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
// Call through to the client's listener
if (listener != null) {
listener.reportControllerState(controllerId, buttonFlags, leftStickX, leftStickY, rightStickX, rightStickY, leftTrigger, rightTrigger);

View File

@@ -486,7 +486,7 @@ public class NvConnection {
}
public void sendControllerInput(final short controllerNumber,
final short activeGamepadMask, final short buttonFlags,
final short activeGamepadMask, final int buttonFlags,
final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY,
final short rightStickX, final short rightStickY)
@@ -496,18 +496,7 @@ public class NvConnection {
leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
}
}
public void sendControllerInput(final short buttonFlags,
final byte leftTrigger, final byte rightTrigger,
final short leftStickX, final short leftStickY,
final short rightStickX, final short rightStickY)
{
if (!isMonkey) {
MoonBridge.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX,
leftStickY, rightStickX, rightStickY);
}
}
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier, final byte flags) {
if (!isMonkey) {
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier, flags);
@@ -538,6 +527,50 @@ public class NvConnection {
}
}
public int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressure) {
if (!isMonkey) {
return MoonBridge.sendTouchEvent(eventType, pointerId, x, y, pressure);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
float pressure, short rotation, byte tiltX, byte tiltY) {
if (!isMonkey) {
return MoonBridge.sendPenEvent(eventType, toolType, penButtons, x, y, pressure, rotation, tiltX, tiltY);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type,
int supportedButtonFlags, short capabilities) {
return MoonBridge.sendControllerArrivalEvent(controllerNumber, activeGamepadMask, type, supportedButtonFlags, capabilities);
}
public int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId,
float x, float y, float pressure) {
if (!isMonkey) {
return MoonBridge.sendControllerTouchEvent(controllerNumber, eventType, pointerId, x, y, pressure);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public int sendControllerMotionEvent(byte controllerNumber, byte motionType,
float x, float y, float z) {
if (!isMonkey) {
return MoonBridge.sendControllerMotionEvent(controllerNumber, motionType, x, y, z);
}
else {
return MoonBridge.LI_ERR_UNSUPPORTED;
}
}
public void sendUtf8Text(final String text) {
if (!isMonkey) {
MoonBridge.sendUtf8Text(text);

View File

@@ -13,6 +13,9 @@ public interface NvConnectionListener {
void displayTransientMessage(String message);
void rumble(short controllerNumber, short lowFreqMotor, short highFreqMotor);
void rumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger);
void setHdrMode(boolean enabled, byte[] hdrMetadata);
void setMotionEventState(short controllerNumber, byte motionType, short reportRateHz);
}

View File

@@ -1,19 +1,27 @@
package com.limelight.nvstream.input;
public class ControllerPacket {
public static final short A_FLAG = 0x1000;
public static final short B_FLAG = 0x2000;
public static final short X_FLAG = 0x4000;
public static final short Y_FLAG = (short)0x8000;
public static final short UP_FLAG = 0x0001;
public static final short DOWN_FLAG = 0x0002;
public static final short LEFT_FLAG = 0x0004;
public static final short RIGHT_FLAG = 0x0008;
public static final short LB_FLAG = 0x0100;
public static final short RB_FLAG = 0x0200;
public static final short PLAY_FLAG = 0x0010;
public static final short BACK_FLAG = 0x0020;
public static final short LS_CLK_FLAG = 0x0040;
public static final short RS_CLK_FLAG = 0x0080;
public static final short SPECIAL_BUTTON_FLAG = 0x0400;
public static final int A_FLAG = 0x1000;
public static final int B_FLAG = 0x2000;
public static final int X_FLAG = 0x4000;
public static final int Y_FLAG = 0x8000;
public static final int UP_FLAG = 0x0001;
public static final int DOWN_FLAG = 0x0002;
public static final int LEFT_FLAG = 0x0004;
public static final int RIGHT_FLAG = 0x0008;
public static final int LB_FLAG = 0x0100;
public static final int RB_FLAG = 0x0200;
public static final int PLAY_FLAG = 0x0010;
public static final int BACK_FLAG = 0x0020;
public static final int LS_CLK_FLAG = 0x0040;
public static final int RS_CLK_FLAG = 0x0080;
public static final int SPECIAL_BUTTON_FLAG = 0x0400;
// Extended buttons (Sunshine only)
public static final int PADDLE1_FLAG = 0x010000;
public static final int PADDLE2_FLAG = 0x020000;
public static final int PADDLE3_FLAG = 0x040000;
public static final int PADDLE4_FLAG = 0x080000;
public static final int TOUCHPAD_FLAG = 0x100000; // Touchpad buttons on Sony controllers
public static final int MISC_FLAG = 0x200000; // Share/Mic/Capture/Mute buttons on various controllers
}

View File

@@ -75,6 +75,39 @@ public class MoonBridge {
public static final byte SS_KBE_FLAG_NON_NORMALIZED = 0x01;
public static final int LI_ERR_UNSUPPORTED = -5501;
public static final byte LI_TOUCH_EVENT_HOVER = 0x00;
public static final byte LI_TOUCH_EVENT_DOWN = 0x01;
public static final byte LI_TOUCH_EVENT_UP = 0x02;
public static final byte LI_TOUCH_EVENT_MOVE = 0x03;
public static final byte LI_TOUCH_EVENT_CANCEL = 0x04;
public static final byte LI_TOOL_TYPE_PEN = 0x01;
public static final byte LI_TOOL_TYPE_ERASER = 0x02;
public static final byte LI_PEN_BUTTON_PRIMARY = 0x01;
public static final byte LI_PEN_BUTTON_SECONDARY = 0x02;
public static final byte LI_PEN_BUTTON_TERTIARY = 0x04;
public static final byte LI_TILT_UNKNOWN = (byte)0xFF;
public static final byte LI_ROT_UNKNOWN = (byte)0xFF;
public static final byte LI_CTYPE_UNKNOWN = 0x00;
public static final byte LI_CTYPE_XBOX = 0x01;
public static final byte LI_CTYPE_PS = 0x02;
public static final byte LI_CTYPE_NINTENDO = 0x03;
public static final short LI_CCAP_ANALOG_TRIGGERS = 0x01;
public static final short LI_CCAP_RUMBLE = 0x02;
public static final short LI_CCAP_TRIGGER_RUMBLE = 0x04;
public static final short LI_CCAP_TOUCHPAD = 0x08;
public static final short LI_CCAP_ACCEL = 0x10;
public static final short LI_CCAP_GYRO = 0x20;
public static final byte LI_MOTION_TYPE_ACCEL = 0x01;
public static final byte LI_MOTION_TYPE_GYRO = 0x02;
private static AudioRenderer audioRenderer;
private static VideoDecoderRenderer videoRenderer;
private static NvConnectionListener connectionListener;
@@ -259,6 +292,18 @@ public class MoonBridge {
}
}
public static void bridgeClRumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
if (connectionListener != null) {
connectionListener.rumbleTriggers(controllerNumber, leftTrigger, rightTrigger);
}
}
public static void bridgeClSetMotionEventState(short controllerNumber, byte eventType, short sampleRateHz) {
if (connectionListener != null) {
connectionListener.setMotionEventState(controllerNumber, eventType, sampleRateHz);
}
}
public static void setupBridge(VideoDecoderRenderer videoRenderer, AudioRenderer audioRenderer, NvConnectionListener connectionListener) {
MoonBridge.videoRenderer = videoRenderer;
MoonBridge.audioRenderer = audioRenderer;
@@ -297,15 +342,21 @@ public class MoonBridge {
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
public static native void sendMultiControllerInput(short controllerNumber,
short activeGamepadMask, short buttonFlags,
short activeGamepadMask, int buttonFlags,
byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY);
public static native void sendControllerInput(short buttonFlags,
byte leftTrigger, byte rightTrigger,
short leftStickX, short leftStickY,
short rightStickX, short rightStickY);
public static native int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressure);
public static native int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
float pressure, short rotation, byte tiltX, byte tiltY);
public static native int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type, int supportedButtonFlags, short capabilities);
public static native int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId, float x, float y, float pressure);
public static native int sendControllerMotionEvent(byte controllerNumber, byte motionType, float x, float y, float z);
public static native void sendKeyboardInput(short keyMap, byte keyDirection, byte modifier, byte flags);

View File

@@ -33,6 +33,8 @@ static jmethodID BridgeClConnectionTerminatedMethod;
static jmethodID BridgeClRumbleMethod;
static jmethodID BridgeClConnectionStatusUpdateMethod;
static jmethodID BridgeClSetHdrModeMethod;
static jmethodID BridgeClRumbleTriggersMethod;
static jmethodID BridgeClSetMotionEventStateMethod;
static jbyteArray DecodedFrameBuffer;
static jshortArray DecodedAudioBuffer;
@@ -94,6 +96,8 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
BridgeClConnectionStatusUpdateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionStatusUpdate", "(I)V");
BridgeClSetHdrModeMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetHdrMode", "(Z[B)V");
BridgeClRumbleTriggersMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumbleTriggers", "(SSS)V");
BridgeClSetMotionEventStateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetMotionEventState", "(SBS)V");
}
int BridgeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
@@ -347,6 +351,29 @@ void BridgeClSetHdrMode(bool enabled) {
}
}
void BridgeClRumbleTriggers(unsigned short controllerNumber, unsigned short leftTrigger, unsigned short rightTrigger) {
JNIEnv* env = GetThreadEnv();
// The seemingly redundant short casts are required in order to convert the unsigned short to a signed short.
// If we leave it as an unsigned short, CheckJNI will fail when the value exceeds 32767. The cast itself is
// fine because the Java code treats the value as unsigned even though it's stored in a signed type.
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClRumbleTriggersMethod, controllerNumber, (short)leftTrigger, (short)rightTrigger);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
}
}
void BridgeClSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz) {
JNIEnv* env = GetThreadEnv();
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetMotionEventStateMethod, controllerNumber, motionType, reportRateHz);
if ((*env)->ExceptionCheck(env)) {
// We will crash here
(*JVM)->DetachCurrentThread(JVM);
}
}
void BridgeClLogMessage(const char* format, ...) {
va_list va;
va_start(va, format);
@@ -381,6 +408,8 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
.rumble = BridgeClRumble,
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
.setHdrMode = BridgeClSetHdrMode,
.rumbleTriggers = BridgeClRumbleTriggers,
.setMotionEventState = BridgeClSetMotionEventState,
};
JNIEXPORT jint JNICALL

View File

@@ -30,7 +30,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_sendMouseButton(JNIEnv *env, jclass c
JNIEXPORT void JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendMultiControllerInput(JNIEnv *env, jclass clazz, jshort controllerNumber,
jshort activeGamepadMask, jshort buttonFlags,
jshort activeGamepadMask, jint buttonFlags,
jbyte leftTrigger, jbyte rightTrigger,
jshort leftStickX, jshort leftStickY,
jshort rightStickX, jshort rightStickY) {
@@ -38,12 +38,47 @@ Java_com_limelight_nvstream_jni_MoonBridge_sendMultiControllerInput(JNIEnv *env,
leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
}
JNIEXPORT void JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerInput(JNIEnv *env, jclass clazz, jshort buttonFlags,
jbyte leftTrigger, jbyte rightTrigger,
jshort leftStickX, jshort leftStickY,
jshort rightStickX, jshort rightStickY) {
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendTouchEvent(JNIEnv *env, jclass clazz,
jbyte eventType, jint pointerId,
jfloat x, jfloat y, jfloat pressure) {
return LiSendTouchEvent(eventType, pointerId, x, y, pressure);
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendPenEvent(JNIEnv *env, jclass clazz, jbyte eventType,
jbyte toolType, jbyte penButtons,
jfloat x, jfloat y, jfloat pressure,
jshort rotation, jbyte tiltX,
jbyte tiltY) {
return LiSendPenEvent(eventType, toolType, penButtons, x, y, pressure, rotation, tiltX, tiltY);
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerArrivalEvent(JNIEnv *env, jclass clazz,
jbyte controllerNumber,
jshort activeGamepadMask,
jbyte type,
jint supportedButtonFlags,
jshort capabilities) {
return LiSendControllerArrivalEvent(controllerNumber, activeGamepadMask, type, supportedButtonFlags, capabilities);
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerTouchEvent(JNIEnv *env, jclass clazz,
jbyte controllerNumber,
jbyte eventType,
jint pointerId, jfloat x,
jfloat y, jfloat pressure) {
return LiSendControllerTouchEvent(controllerNumber, eventType, pointerId, x, y, pressure);
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerMotionEvent(JNIEnv *env, jclass clazz,
jbyte controllerNumber,
jbyte motionType, jfloat x,
jfloat y, jfloat z) {
return LiSendControllerMotionEvent(controllerNumber, motionType, x, y, z);
}
JNIEXPORT void JNICALL