Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48a9d3ac12 | |||
| efdd1e2046 | |||
| 8a40892865 | |||
| 20635a3012 | |||
| b908c5cec3 | |||
| 1cb0b723f6 | |||
| 3f3c573c79 | |||
| e1253bbb59 | |||
| b2eb953f45 |
+3
-3
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.limelight"
|
||||
android:versionCode="7"
|
||||
android:versionName="2.1.1" >
|
||||
android:versionCode="9"
|
||||
android:versionName="2.1.3" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="16"
|
||||
@@ -29,7 +29,7 @@
|
||||
<activity
|
||||
android:name="com.limelight.Game"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:label="@string/title_activity_game"
|
||||
android:parentActivityName="com.limelight.Connection"
|
||||
android:theme="@style/FullscreenTheme" >
|
||||
|
||||
+10
-207
@@ -1,12 +1,13 @@
|
||||
package com.limelight;
|
||||
|
||||
import com.limelight.binding.PlatformBinding;
|
||||
import com.limelight.binding.input.ControllerHandler;
|
||||
import com.limelight.binding.input.KeyboardTranslator;
|
||||
import com.limelight.binding.video.ConfigurableDecoderRenderer;
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.NvConnectionListener;
|
||||
import com.limelight.nvstream.StreamConfiguration;
|
||||
import com.limelight.nvstream.av.video.VideoDecoderRenderer;
|
||||
import com.limelight.nvstream.input.ControllerPacket;
|
||||
import com.limelight.nvstream.input.KeyboardPacket;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
@@ -34,13 +35,6 @@ import android.widget.Toast;
|
||||
|
||||
|
||||
public class Game extends Activity implements OnGenericMotionListener, OnTouchListener, NvConnectionListener {
|
||||
private short inputMap = 0x0000;
|
||||
private byte leftTrigger = 0x00;
|
||||
private byte rightTrigger = 0x00;
|
||||
private short rightStickX = 0x0000;
|
||||
private short rightStickY = 0x0000;
|
||||
private short leftStickX = 0x0000;
|
||||
private short leftStickY = 0x0000;
|
||||
private int lastMouseX = Integer.MIN_VALUE;
|
||||
private int lastMouseY = Integer.MIN_VALUE;
|
||||
private int lastButtonState = 0;
|
||||
@@ -48,6 +42,7 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
private int lastTouchY = 0;
|
||||
private boolean hasMoved = false;
|
||||
|
||||
private ControllerHandler controllerHandler;
|
||||
private KeyboardTranslator keybTranslator;
|
||||
|
||||
private int height;
|
||||
@@ -134,6 +129,7 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
conn = new NvConnection(Game.this.getIntent().getStringExtra("host"), Game.this,
|
||||
new StreamConfiguration(width, height, refreshRate));
|
||||
keybTranslator = new KeyboardTranslator(conn);
|
||||
controllerHandler = new ControllerHandler(conn);
|
||||
conn.start(PlatformBinding.getDeviceName(), sv.getHolder(), drFlags,
|
||||
PlatformBinding.getAudioRenderer(), new ConfigurableDecoderRenderer());
|
||||
}
|
||||
@@ -210,64 +206,9 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
getModifierState(event));
|
||||
}
|
||||
else {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
inputMap |= ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
inputMap |= ControllerPacket.BACK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
inputMap |= ControllerPacket.LEFT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
inputMap |= ControllerPacket.UP_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
inputMap |= ControllerPacket.DOWN_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
inputMap |= ControllerPacket.B_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
inputMap |= ControllerPacket.A_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
inputMap |= ControllerPacket.X_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
inputMap |= ControllerPacket.Y_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
inputMap |= ControllerPacket.LB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
inputMap |= ControllerPacket.RB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
inputMap |= ControllerPacket.LS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
inputMap |= ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
default:
|
||||
if (!controllerHandler.handleButtonDown(keyCode, event)) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
// We detect back+start as the special button combo
|
||||
if ((inputMap & ControllerPacket.BACK_FLAG) != 0 &&
|
||||
(inputMap & ControllerPacket.PLAY_FLAG) != 0)
|
||||
{
|
||||
inputMap &= ~(ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG);
|
||||
inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
}
|
||||
|
||||
sendControllerInputPacket();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -286,63 +227,9 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
getModifierState(event));
|
||||
}
|
||||
else {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
inputMap &= ~ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
inputMap &= ~ControllerPacket.BACK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
inputMap &= ~ControllerPacket.LEFT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
inputMap &= ~ControllerPacket.UP_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
inputMap &= ~ControllerPacket.DOWN_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
inputMap &= ~ControllerPacket.B_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
inputMap &= ~ControllerPacket.A_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
inputMap &= ~ControllerPacket.X_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
inputMap &= ~ControllerPacket.Y_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
inputMap &= ~ControllerPacket.LB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
inputMap &= ~ControllerPacket.RB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
inputMap &= ~ControllerPacket.LS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
default:
|
||||
if (!controllerHandler.handleButtonUp(keyCode, event)) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
// If one of the two is up, the special button comes up too
|
||||
if ((inputMap & ControllerPacket.BACK_FLAG) == 0 ||
|
||||
(inputMap & ControllerPacket.PLAY_FLAG) == 0)
|
||||
{
|
||||
inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
}
|
||||
|
||||
sendControllerInputPacket();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -460,92 +347,13 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||
InputDevice dev = event.getDevice();
|
||||
|
||||
if (dev == null) {
|
||||
System.err.println("Unknown device");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
||||
float LS_X = event.getAxisValue(MotionEvent.AXIS_X);
|
||||
float LS_Y = event.getAxisValue(MotionEvent.AXIS_Y);
|
||||
|
||||
float RS_X, RS_Y, L2, R2;
|
||||
|
||||
InputDevice.MotionRange leftTriggerRange = dev.getMotionRange(MotionEvent.AXIS_LTRIGGER);
|
||||
InputDevice.MotionRange rightTriggerRange = dev.getMotionRange(MotionEvent.AXIS_RTRIGGER);
|
||||
if (leftTriggerRange != null && rightTriggerRange != null)
|
||||
{
|
||||
// Ouya controller
|
||||
L2 = event.getAxisValue(MotionEvent.AXIS_LTRIGGER);
|
||||
R2 = event.getAxisValue(MotionEvent.AXIS_RTRIGGER);
|
||||
RS_X = event.getAxisValue(MotionEvent.AXIS_Z);
|
||||
RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputDevice.MotionRange brakeRange = dev.getMotionRange(MotionEvent.AXIS_BRAKE);
|
||||
InputDevice.MotionRange gasRange = dev.getMotionRange(MotionEvent.AXIS_GAS);
|
||||
if (brakeRange != null && gasRange != null)
|
||||
{
|
||||
// Moga controller
|
||||
RS_X = event.getAxisValue(MotionEvent.AXIS_Z);
|
||||
RS_Y = event.getAxisValue(MotionEvent.AXIS_RZ);
|
||||
L2 = event.getAxisValue(MotionEvent.AXIS_BRAKE);
|
||||
R2 = event.getAxisValue(MotionEvent.AXIS_GAS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Xbox controller
|
||||
RS_X = event.getAxisValue(MotionEvent.AXIS_RX);
|
||||
RS_Y = event.getAxisValue(MotionEvent.AXIS_RY);
|
||||
L2 = (event.getAxisValue(MotionEvent.AXIS_Z) + 1) / 2;
|
||||
R2 = (event.getAxisValue(MotionEvent.AXIS_RZ) + 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InputDevice.MotionRange hatXRange = dev.getMotionRange(MotionEvent.AXIS_HAT_X);
|
||||
InputDevice.MotionRange hatYRange = dev.getMotionRange(MotionEvent.AXIS_HAT_Y);
|
||||
if (hatXRange != null && hatYRange != null)
|
||||
{
|
||||
// Xbox controller D-pad
|
||||
float hatX, hatY;
|
||||
|
||||
hatX = event.getAxisValue(MotionEvent.AXIS_HAT_X);
|
||||
hatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y);
|
||||
|
||||
inputMap &= ~(ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG);
|
||||
inputMap &= ~(ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG);
|
||||
if (hatX < -0.5) {
|
||||
inputMap |= ControllerPacket.LEFT_FLAG;
|
||||
}
|
||||
if (hatX > 0.5) {
|
||||
inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||
}
|
||||
if (hatY < -0.5) {
|
||||
inputMap |= ControllerPacket.UP_FLAG;
|
||||
}
|
||||
if (hatY > 0.5) {
|
||||
inputMap |= ControllerPacket.DOWN_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
leftStickX = (short)Math.round(LS_X * 0x7FFF);
|
||||
leftStickY = (short)Math.round(-LS_Y * 0x7FFF);
|
||||
|
||||
rightStickX = (short)Math.round(RS_X * 0x7FFF);
|
||||
rightStickY = (short)Math.round(-RS_Y * 0x7FFF);
|
||||
|
||||
leftTrigger = (byte)Math.round(L2 * 0xFF);
|
||||
rightTrigger = (byte)Math.round(R2 * 0xFF);
|
||||
|
||||
sendControllerInputPacket();
|
||||
return true;
|
||||
if (controllerHandler.handleMotionEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
|
||||
{
|
||||
@@ -579,11 +387,6 @@ public class Game extends Activity implements OnGenericMotionListener, OnTouchLi
|
||||
lastMouseX = eventX;
|
||||
lastMouseY = eventY;
|
||||
}
|
||||
|
||||
private void sendControllerInputPacket() {
|
||||
conn.sendControllerInput(inputMap, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotion(View v, MotionEvent event) {
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
package com.limelight.binding.input;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.ControllerPacket;
|
||||
|
||||
public class ControllerHandler {
|
||||
private short inputMap = 0x0000;
|
||||
private byte leftTrigger = 0x00;
|
||||
private byte rightTrigger = 0x00;
|
||||
private short rightStickX = 0x0000;
|
||||
private short rightStickY = 0x0000;
|
||||
private short leftStickX = 0x0000;
|
||||
private short leftStickY = 0x0000;
|
||||
|
||||
private HashMap<String, ControllerMapping> mappings = new HashMap<String, ControllerMapping>();
|
||||
|
||||
private NvConnection conn;
|
||||
|
||||
public ControllerHandler(NvConnection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
private ControllerMapping createMappingForDevice(InputDevice dev) {
|
||||
ControllerMapping mapping = new ControllerMapping();
|
||||
|
||||
mapping.leftStickXAxis = MotionEvent.AXIS_X;
|
||||
mapping.leftStickYAxis = MotionEvent.AXIS_Y;
|
||||
|
||||
InputDevice.MotionRange leftTriggerRange = dev.getMotionRange(MotionEvent.AXIS_LTRIGGER);
|
||||
InputDevice.MotionRange rightTriggerRange = dev.getMotionRange(MotionEvent.AXIS_RTRIGGER);
|
||||
InputDevice.MotionRange brakeRange = dev.getMotionRange(MotionEvent.AXIS_BRAKE);
|
||||
InputDevice.MotionRange gasRange = dev.getMotionRange(MotionEvent.AXIS_GAS);
|
||||
if (leftTriggerRange != null && rightTriggerRange != null)
|
||||
{
|
||||
// Some controllers use LTRIGGER and RTRIGGER (like Ouya)
|
||||
mapping.leftTriggerAxis = MotionEvent.AXIS_LTRIGGER;
|
||||
mapping.rightTriggerAxis = MotionEvent.AXIS_RTRIGGER;
|
||||
}
|
||||
else if (brakeRange != null && gasRange != null)
|
||||
{
|
||||
// Others use GAS and BRAKE (like Moga)
|
||||
mapping.leftTriggerAxis = MotionEvent.AXIS_BRAKE;
|
||||
mapping.rightTriggerAxis = MotionEvent.AXIS_GAS;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputDevice.MotionRange rxRange = dev.getMotionRange(MotionEvent.AXIS_RX);
|
||||
InputDevice.MotionRange ryRange = dev.getMotionRange(MotionEvent.AXIS_RY);
|
||||
if (rxRange != null && ryRange != null) {
|
||||
String devName = dev.getName();
|
||||
if (devName.contains("Xbox") || devName.contains("XBox") || devName.contains("X-Box")) {
|
||||
// Xbox controllers use RX and RY for right stick
|
||||
mapping.rightStickXAxis = MotionEvent.AXIS_RX;
|
||||
mapping.rightStickYAxis = MotionEvent.AXIS_RY;
|
||||
|
||||
// Xbox controllers use Z and RZ for triggers
|
||||
mapping.leftTriggerAxis = MotionEvent.AXIS_Z;
|
||||
mapping.rightTriggerAxis = MotionEvent.AXIS_RZ;
|
||||
mapping.triggersIdleNegative = true;
|
||||
}
|
||||
else {
|
||||
// DS4 controller uses RX and RY for triggers
|
||||
mapping.leftTriggerAxis = MotionEvent.AXIS_RX;
|
||||
mapping.rightTriggerAxis = MotionEvent.AXIS_RY;
|
||||
mapping.triggersIdleNegative = true;
|
||||
|
||||
mapping.isDualShock4 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping.rightStickXAxis == -1 && mapping.rightStickYAxis == -1) {
|
||||
InputDevice.MotionRange zRange = dev.getMotionRange(MotionEvent.AXIS_Z);
|
||||
InputDevice.MotionRange rzRange = dev.getMotionRange(MotionEvent.AXIS_RZ);
|
||||
|
||||
// Most other controllers use Z and RZ for the right stick
|
||||
if (zRange != null && rzRange != null) {
|
||||
mapping.rightStickXAxis = MotionEvent.AXIS_Z;
|
||||
mapping.rightStickYAxis = MotionEvent.AXIS_RZ;
|
||||
}
|
||||
else {
|
||||
InputDevice.MotionRange rxRange = dev.getMotionRange(MotionEvent.AXIS_RX);
|
||||
InputDevice.MotionRange ryRange = dev.getMotionRange(MotionEvent.AXIS_RY);
|
||||
|
||||
// Try RX and RY now
|
||||
if (rxRange != null && ryRange != null) {
|
||||
mapping.rightStickXAxis = MotionEvent.AXIS_RX;
|
||||
mapping.rightStickYAxis = MotionEvent.AXIS_RY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some devices have "hats" for d-pads
|
||||
InputDevice.MotionRange hatXRange = dev.getMotionRange(MotionEvent.AXIS_HAT_X);
|
||||
InputDevice.MotionRange hatYRange = dev.getMotionRange(MotionEvent.AXIS_HAT_Y);
|
||||
if (hatXRange != null && hatYRange != null) {
|
||||
mapping.hatXAxis = MotionEvent.AXIS_HAT_X;
|
||||
mapping.hatYAxis = MotionEvent.AXIS_HAT_Y;
|
||||
|
||||
mapping.hatXDeadzone = hatXRange.getFlat();
|
||||
mapping.hatYDeadzone = hatYRange.getFlat();
|
||||
}
|
||||
|
||||
if (mapping.leftStickXAxis != -1 && mapping.leftStickYAxis != -1) {
|
||||
InputDevice.MotionRange lsXRange = dev.getMotionRange(mapping.leftStickXAxis);
|
||||
InputDevice.MotionRange lsYRange = dev.getMotionRange(mapping.leftStickYAxis);
|
||||
if (lsXRange != null) {
|
||||
mapping.leftStickXAxisDeadzone = lsXRange.getFlat();
|
||||
}
|
||||
if (lsYRange != null) {
|
||||
mapping.leftStickYAxisDeadzone = lsYRange.getFlat();
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping.rightStickXAxis != -1 && mapping.rightStickYAxis != -1) {
|
||||
InputDevice.MotionRange rsXRange = dev.getMotionRange(mapping.rightStickXAxis);
|
||||
InputDevice.MotionRange rsYRange = dev.getMotionRange(mapping.rightStickYAxis);
|
||||
if (rsXRange != null) {
|
||||
mapping.rightStickXAxisDeadzone = rsXRange.getFlat();
|
||||
}
|
||||
if (rsYRange != null) {
|
||||
mapping.rightStickYAxisDeadzone = rsYRange.getFlat();
|
||||
}
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private ControllerMapping getMappingForDevice(InputDevice dev) {
|
||||
// Unknown devices can't be handled
|
||||
if (dev == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String descriptor = dev.getDescriptor();
|
||||
|
||||
// Return the existing mapping if it exists
|
||||
ControllerMapping mapping = mappings.get(descriptor);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
// Otherwise create a new mapping
|
||||
mapping = createMappingForDevice(dev);
|
||||
mappings.put(descriptor, mapping);
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private void sendControllerInputPacket() {
|
||||
conn.sendControllerInput(inputMap, leftTrigger, rightTrigger,
|
||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
}
|
||||
|
||||
private int handleRemapping(ControllerMapping mapping, int keyCode) {
|
||||
if (mapping.isDualShock4) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
return KeyEvent.KEYCODE_BUTTON_L1;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_Z:
|
||||
return KeyEvent.KEYCODE_BUTTON_R1;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_C:
|
||||
return KeyEvent.KEYCODE_BUTTON_B;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
return KeyEvent.KEYCODE_BUTTON_Y;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
return KeyEvent.KEYCODE_BUTTON_A;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
return KeyEvent.KEYCODE_BUTTON_X;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
return KeyEvent.KEYCODE_BUTTON_THUMBL;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
return KeyEvent.KEYCODE_BUTTON_THUMBR;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
return KeyEvent.KEYCODE_BUTTON_SELECT;
|
||||
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
return KeyEvent.KEYCODE_BUTTON_START;
|
||||
|
||||
// These are duplicate trigger events
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping.hatXAxis != -1 && mapping.hatYAxis != -1) {
|
||||
switch (keyCode) {
|
||||
// These are duplicate dpad events for hat input
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return keyCode;
|
||||
}
|
||||
|
||||
public boolean handleMotionEvent(MotionEvent event) {
|
||||
ControllerMapping mapping = getMappingForDevice(event.getDevice());
|
||||
if (mapping == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle left stick events outside of the deadzone
|
||||
if (mapping.leftStickXAxis != -1 && mapping.leftStickYAxis != -1) {
|
||||
float LS_X = event.getAxisValue(mapping.leftStickXAxis);
|
||||
float LS_Y = event.getAxisValue(mapping.leftStickYAxis);
|
||||
if (LS_X >= -mapping.leftStickXAxisDeadzone && LS_X <= mapping.leftStickXAxisDeadzone) {
|
||||
LS_X = 0;
|
||||
}
|
||||
if (LS_Y >= -mapping.leftStickYAxisDeadzone && LS_Y <= mapping.leftStickYAxisDeadzone) {
|
||||
LS_Y = 0;
|
||||
}
|
||||
leftStickX = (short)Math.round(LS_X * 0x7FFF);
|
||||
leftStickY = (short)Math.round(-LS_Y * 0x7FFF);
|
||||
}
|
||||
|
||||
// Handle right stick events outside of the deadzone
|
||||
if (mapping.rightStickXAxis != -1 && mapping.rightStickYAxis != -1) {
|
||||
float RS_X = event.getAxisValue(mapping.rightStickXAxis);
|
||||
float RS_Y = event.getAxisValue(mapping.rightStickYAxis);
|
||||
if (RS_X >= -mapping.rightStickXAxisDeadzone && RS_X <= mapping.rightStickXAxisDeadzone) {
|
||||
RS_X = 0;
|
||||
}
|
||||
if (RS_Y >= -mapping.rightStickYAxisDeadzone && RS_Y <= mapping.rightStickYAxisDeadzone) {
|
||||
RS_Y = 0;
|
||||
}
|
||||
rightStickX = (short)Math.round(RS_X * 0x7FFF);
|
||||
rightStickY = (short)Math.round(-RS_Y * 0x7FFF);
|
||||
}
|
||||
|
||||
// Handle controllers with analog triggers
|
||||
if (mapping.leftTriggerAxis != -1 && mapping.rightTriggerAxis != -1) {
|
||||
float L2 = event.getAxisValue(mapping.leftTriggerAxis);
|
||||
float R2 = event.getAxisValue(mapping.rightTriggerAxis);
|
||||
|
||||
if (mapping.triggersIdleNegative) {
|
||||
L2 = (L2 + 1) / 2;
|
||||
R2 = (R2 + 1) / 2;
|
||||
}
|
||||
|
||||
leftTrigger = (byte)Math.round(L2 * 0xFF);
|
||||
rightTrigger = (byte)Math.round(R2 * 0xFF);
|
||||
}
|
||||
|
||||
// Hats emulate d-pad events
|
||||
if (mapping.hatXAxis != -1 && mapping.hatYAxis != -1) {
|
||||
float hatX = event.getAxisValue(MotionEvent.AXIS_HAT_X);
|
||||
float hatY = event.getAxisValue(MotionEvent.AXIS_HAT_Y);
|
||||
|
||||
inputMap &= ~(ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG);
|
||||
if (hatX < -(0.5 + mapping.hatXDeadzone)) {
|
||||
inputMap |= ControllerPacket.LEFT_FLAG;
|
||||
}
|
||||
else if (hatX > (0.5 + mapping.hatXDeadzone)) {
|
||||
inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||
}
|
||||
|
||||
inputMap &= ~(ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG);
|
||||
if (hatY < -(0.5 + mapping.hatYDeadzone)) {
|
||||
inputMap |= ControllerPacket.UP_FLAG;
|
||||
}
|
||||
else if (hatY > (0.5 + mapping.hatYDeadzone)) {
|
||||
inputMap |= ControllerPacket.DOWN_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
sendControllerInputPacket();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean handleButtonUp(int keyCode, KeyEvent event) {
|
||||
ControllerMapping mapping = getMappingForDevice(event.getDevice());
|
||||
if (mapping == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
keyCode = handleRemapping(mapping, keyCode);
|
||||
if (keyCode == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BUTTON_MODE:
|
||||
inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
inputMap &= ~ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
inputMap &= ~ControllerPacket.BACK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
inputMap &= ~ControllerPacket.LEFT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
inputMap &= ~ControllerPacket.RIGHT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
inputMap &= ~ControllerPacket.UP_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
inputMap &= ~ControllerPacket.DOWN_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
inputMap &= ~ControllerPacket.B_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
inputMap &= ~ControllerPacket.A_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
inputMap &= ~ControllerPacket.X_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
inputMap &= ~ControllerPacket.Y_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
inputMap &= ~ControllerPacket.LB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
inputMap &= ~ControllerPacket.RB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
inputMap &= ~ControllerPacket.LS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
leftTrigger = 0;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
rightTrigger = 0;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// If one of the two is up, the special button comes up too
|
||||
if ((inputMap & ControllerPacket.BACK_FLAG) == 0 ||
|
||||
(inputMap & ControllerPacket.PLAY_FLAG) == 0)
|
||||
{
|
||||
inputMap &= ~ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
}
|
||||
|
||||
sendControllerInputPacket();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean handleButtonDown(int keyCode, KeyEvent event) {
|
||||
ControllerMapping mapping = getMappingForDevice(event.getDevice());
|
||||
if (mapping == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
keyCode = handleRemapping(mapping, keyCode);
|
||||
if (keyCode == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BUTTON_MODE:
|
||||
inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_START:
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
inputMap |= ControllerPacket.PLAY_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
case KeyEvent.KEYCODE_BUTTON_SELECT:
|
||||
inputMap |= ControllerPacket.BACK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||
inputMap |= ControllerPacket.LEFT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||
inputMap |= ControllerPacket.RIGHT_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_UP:
|
||||
inputMap |= ControllerPacket.UP_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||
inputMap |= ControllerPacket.DOWN_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_B:
|
||||
inputMap |= ControllerPacket.B_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_A:
|
||||
inputMap |= ControllerPacket.A_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_X:
|
||||
inputMap |= ControllerPacket.X_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_Y:
|
||||
inputMap |= ControllerPacket.Y_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L1:
|
||||
inputMap |= ControllerPacket.LB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R1:
|
||||
inputMap |= ControllerPacket.RB_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBL:
|
||||
inputMap |= ControllerPacket.LS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_THUMBR:
|
||||
inputMap |= ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
leftTrigger = (byte)0xFF;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
rightTrigger = (byte)0xFF;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// We detect back+start as the special button combo
|
||||
if ((inputMap & ControllerPacket.BACK_FLAG) != 0 &&
|
||||
(inputMap & ControllerPacket.PLAY_FLAG) != 0)
|
||||
{
|
||||
inputMap &= ~(ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG);
|
||||
inputMap |= ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
}
|
||||
|
||||
sendControllerInputPacket();
|
||||
return true;
|
||||
}
|
||||
|
||||
class ControllerMapping {
|
||||
public int leftStickXAxis = -1;
|
||||
public float leftStickXAxisDeadzone;
|
||||
|
||||
public int leftStickYAxis = -1;
|
||||
public float leftStickYAxisDeadzone;
|
||||
|
||||
public int rightStickXAxis = -1;
|
||||
public float rightStickXAxisDeadzone;
|
||||
|
||||
public int rightStickYAxis = -1;
|
||||
public float rightStickYAxisDeadzone;
|
||||
|
||||
public int leftTriggerAxis = -1;
|
||||
public int rightTriggerAxis = -1;
|
||||
public boolean triggersIdleNegative;
|
||||
|
||||
public int hatXAxis = -1;
|
||||
public int hatYAxis = -1;
|
||||
public float hatXDeadzone;
|
||||
public float hatYDeadzone;
|
||||
|
||||
public boolean isDualShock4;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.limelight;
|
||||
package com.limelight.binding.input;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
@@ -123,7 +123,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
public void setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) {
|
||||
this.redrawRate = redrawRate;
|
||||
|
||||
dumpDecoders();
|
||||
//dumpDecoders();
|
||||
|
||||
MediaCodecInfo safeDecoder = findSafeDecoder();
|
||||
if (safeDecoder != null) {
|
||||
|
||||
Reference in New Issue
Block a user