Compare commits

...

9 Commits

8 changed files with 86 additions and 22 deletions
+3 -3
View File
@@ -5,14 +5,14 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '27.0.2'
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionName "5.6.2"
versionCode = 140
versionName "5.6.4"
versionCode = 143
}
flavorDimensions "root"
+12 -1
View File
@@ -294,6 +294,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (prefConfig.videoFormat == PreferenceConfiguration.FORCE_H265_ON && !decoderRenderer.isHevcSupported()) {
Toast.makeText(this, "No H.265 decoder found.\nFalling back to H.264.", Toast.LENGTH_LONG).show();
}
int gamepadMask = ControllerHandler.getAttachedControllerMask(this);
if (!prefConfig.multiController && gamepadMask != 0) {
// If any gamepads are present in non-MC mode, set only gamepad 1.
gamepadMask = 1;
}
if (prefConfig.onscreenController) {
// If we're using OSC, always set at least gamepad 1.
gamepadMask |= 1;
}
StreamConfiguration config = new StreamConfiguration.Builder()
.setResolution(prefConfig.width, prefConfig.height)
@@ -302,11 +312,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
.setBitrate(prefConfig.bitrate * 1000)
.setEnableSops(prefConfig.enableSops)
.enableLocalAudioPlayback(prefConfig.playHostAudio)
.setMaxPacketSize(remote ? 1024 : 1292)
.setMaxPacketSize((remote || prefConfig.width <= 1920) ? 1024 : 1292)
.setRemote(remote)
.setHevcBitratePercentageMultiplier(75)
.setHevcSupported(decoderRenderer.isHevcSupported())
.setEnableHdr(willStreamHdr)
.setAttachedGamepadMask(gamepadMask)
.setAudioConfiguration(prefConfig.enable51Surround ?
MoonBridge.AUDIO_CONFIGURATION_51_SURROUND :
MoonBridge.AUDIO_CONFIGURATION_STEREO)
@@ -2,6 +2,8 @@ package com.limelight.binding.input;
import android.content.Context;
import android.hardware.input.InputManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;
import android.util.SparseArray;
import android.view.InputDevice;
@@ -12,6 +14,7 @@ import android.widget.Toast;
import com.limelight.LimeLog;
import com.limelight.binding.input.driver.UsbDriverListener;
import com.limelight.binding.input.driver.UsbDriverService;
import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.nvstream.input.MouseButtonPacket;
@@ -48,7 +51,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
private boolean hasGameController;
private final boolean multiControllerEnabled;
private short currentControllers;
private short currentControllers, initialControllers;
public ControllerHandler(Context activityContext, NvConnection conn, GameGestures gestures, boolean multiControllerEnabled, int deadzonePercentage) {
this.activityContext = activityContext;
@@ -102,6 +105,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
// consume these. Instead, let's ignore them since that's probably the
// most likely case.
defaultContext.ignoreBack = true;
// Get the initially attached set of gamepads. As each gamepad receives
// its initial InputEvent, we will move these from this set onto the
// currentControllers set which will allow them to properly unplug
// if they are removed.
initialControllers = getAttachedControllerMask(activityContext);
}
private static InputDevice.MotionRange getMotionRangeForJoystickAxis(InputDevice dev, int axis) {
@@ -139,8 +148,47 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
onInputDeviceAdded(deviceId);
}
public static short getAttachedControllerMask(Context context) {
int count = 0;
short mask = 0;
// Count all input devices that are gamepads
InputManager im = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
for (int id : im.getInputDeviceIds()) {
InputDevice dev = im.getInputDevice(id);
if (dev == null) {
continue;
}
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0) {
LimeLog.info("Counting InputDevice: "+dev.getName());
mask |= 1 << count++;
}
}
// Count all USB devices that match our drivers
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (UsbDevice dev : usbManager.getDeviceList().values()) {
if (UsbDriverService.shouldClaimDevice(dev)) {
LimeLog.info("Counting UsbDevice: "+dev.getDeviceName());
mask |= 1 << count++;
}
}
LimeLog.info("Enumerated "+count+" gamepads");
return mask;
}
private void releaseControllerNumber(GenericControllerContext context) {
// If this device sent data as a gamepad, zero the values before removing
// If we reserved a controller number, remove that reservation
if (context.reservedControllerNumber) {
LimeLog.info("Controller number "+context.controllerNumber+" is now available");
currentControllers &= ~(1 << context.controllerNumber);
}
// If this device sent data as a gamepad, zero the values before removing.
// We must do this after clearing the currentControllers entry so this
// causes the device to be removed on the server PC.
if (context.assignedControllerNumber) {
conn.sendControllerInput(context.controllerNumber, getActiveControllerMask(),
(short) 0,
@@ -148,12 +196,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
(short) 0, (short) 0,
(short) 0, (short) 0);
}
// If we reserved a controller number, remove that reservation
if (context.reservedControllerNumber) {
LimeLog.info("Controller number "+context.controllerNumber+" is now available");
currentControllers &= ~(1 << context.controllerNumber);
}
}
// Called before sending input but after we've determined that this
@@ -181,6 +223,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
if ((currentControllers & (1 << i)) == 0) {
// Found an unused controller value
currentControllers |= (1 << i);
// Take this value out of the initial gamepad set
initialControllers &= ~(1 << i);
context.controllerNumber = i;
context.reservedControllerNumber = true;
break;
@@ -201,6 +247,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
if ((currentControllers & (1 << i)) == 0) {
// Found an unused controller value
currentControllers |= (1 << i);
// Take this value out of the initial gamepad set
initialControllers &= ~(1 << i);
context.controllerNumber = i;
context.reservedControllerNumber = true;
break;
@@ -473,7 +523,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
private short getActiveControllerMask() {
if (multiControllerEnabled) {
return currentControllers;
return (short)(currentControllers | initialControllers);
}
else {
// Only Player 1 is active with multi-controller disabled
@@ -3,6 +3,7 @@ package com.limelight.binding.input.capture;
import android.app.Activity;
import com.limelight.LimeLog;
import com.limelight.LimelightBuildProps;
import com.limelight.R;
import com.limelight.binding.input.evdev.EvdevCaptureProviderShim;
import com.limelight.binding.input.evdev.EvdevListener;
@@ -13,7 +14,9 @@ public class InputCaptureManager {
LimeLog.info("Using Android O+ native mouse capture");
return new AndroidNativePointerCaptureProvider(activity.findViewById(R.id.surfaceView));
}
else if (ShieldCaptureProvider.isCaptureProviderSupported()) {
// LineageOS implemented broken NVIDIA capture extensions, so avoid using them on root builds.
// See https://github.com/LineageOS/android_frameworks_base/commit/d304f478a023430f4712dbdc3ee69d9ad02cebd3
else if (!LimelightBuildProps.ROOT_BUILD && ShieldCaptureProvider.isCaptureProviderSupported()) {
LimeLog.info("Using NVIDIA mouse capture extension");
return new ShieldCaptureProvider(activity);
}
@@ -157,7 +157,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
}
private boolean isRecognizedInputDevice(UsbDevice device) {
private static boolean isRecognizedInputDevice(UsbDevice device) {
// On KitKat and later, we can determine if this VID and PID combo
// matches an existing input device and defer to the built-in controller
// support in that case. Prior to KitKat, we'll always return true to be safe.
@@ -182,7 +182,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
}
private boolean shouldClaimDevice(UsbDevice device) {
public static boolean shouldClaimDevice(UsbDevice device) {
// We always bind to XB1 controllers but only bind to XB360 controllers
// if we know the kernel isn't already driving this device.
return XboxOneController.canClaimDevice(device) ||
@@ -134,7 +134,7 @@ public class ComputerManagerService extends Service {
public void run() {
int offlineCount = 0;
while (!isInterrupted() && pollingActive) {
while (!isInterrupted() && pollingActive && tuple.thread == this) {
try {
// Only allow one request to the machine at a time
synchronized (tuple.networkLock) {
@@ -392,6 +392,7 @@ public class ComputerManagerService extends Service {
if (tuple.thread != null) {
// Interrupt the thread on this entry
tuple.thread.interrupt();
tuple.thread = null;
}
pollingTuples.remove(tuple);
break;
@@ -840,6 +841,7 @@ public class ComputerManagerService extends Service {
} while (waitPollingDelay());
}
};
thread.setName("App list polling thread for " + computer.localAddress);
thread.start();
}
+2 -4
View File
@@ -2,8 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Non-root application name -->
<!-- No need to extract libraries for the non-root version -->
<application
android:label="Moonlight"
android:extractNativeLibs="false" />
<!-- FIXME: We should set extractNativeLibs=false but this breaks installation on the Fire TV 3 -->
<application android:label="Moonlight" />
</manifest>