Add mouse emulation and bind all USB devices options

This commit is contained in:
Cameron Gutman 2018-02-24 20:17:14 -08:00
parent 3c2fd32d1e
commit 88f9b68db7
6 changed files with 51 additions and 20 deletions

View File

@ -367,7 +367,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Initialize the connection // Initialize the connection
conn = new NvConnection(host, uniqueId, config, PlatformBinding.getCryptoProvider(this)); conn = new NvConnection(host, uniqueId, config, PlatformBinding.getCryptoProvider(this));
controllerHandler = new ControllerHandler(this, conn, this, prefConfig.multiController, prefConfig.deadzonePercentage); controllerHandler = new ControllerHandler(this, conn, this, prefConfig);
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE); InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(controllerHandler, null); inputManager.registerInputDeviceListener(controllerHandler, null);

View File

@ -18,6 +18,7 @@ import com.limelight.binding.input.driver.UsbDriverService;
import com.limelight.nvstream.NvConnection; import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.ControllerPacket; import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.nvstream.input.MouseButtonPacket; import com.limelight.nvstream.input.MouseButtonPacket;
import com.limelight.preferences.PreferenceConfiguration;
import com.limelight.ui.GameGestures; import com.limelight.ui.GameGestures;
import com.limelight.utils.Vector2d; import com.limelight.utils.Vector2d;
@ -50,18 +51,18 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
private final GameGestures gestures; private final GameGestures gestures;
private boolean hasGameController; private boolean hasGameController;
private final boolean multiControllerEnabled; private final PreferenceConfiguration prefConfig;
private short currentControllers, initialControllers; private short currentControllers, initialControllers;
public ControllerHandler(Context activityContext, NvConnection conn, GameGestures gestures, boolean multiControllerEnabled, int deadzonePercentage) { public ControllerHandler(Context activityContext, NvConnection conn, GameGestures gestures, PreferenceConfiguration prefConfig) {
this.activityContext = activityContext; this.activityContext = activityContext;
this.conn = conn; this.conn = conn;
this.gestures = gestures; this.gestures = gestures;
this.multiControllerEnabled = multiControllerEnabled; this.prefConfig = prefConfig;
// HACK: For now we're hardcoding a 10% deadzone. Some deadzone // HACK: For now we're hardcoding a 10% deadzone. Some deadzone
// is required for controller batching support to work. // is required for controller batching support to work.
deadzonePercentage = 10; int deadzonePercentage = 10;
int[] ids = InputDevice.getDeviceIds(); int[] ids = InputDevice.getDeviceIds();
for (int id : ids) { for (int id : ids) {
@ -167,13 +168,17 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
} }
// Count all USB devices that match our drivers // Count all USB devices that match our drivers
if (PreferenceConfiguration.readPreferences(context).usbDriver) {
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (UsbDevice dev : usbManager.getDeviceList().values()) { for (UsbDevice dev : usbManager.getDeviceList().values()) {
if (UsbDriverService.shouldClaimDevice(dev)) { // We explicitly ask not to claim devices that appear as InputDevices
// otherwise we will double count them.
if (UsbDriverService.shouldClaimDevice(dev, false)) {
LimeLog.info("Counting UsbDevice: "+dev.getDeviceName()); LimeLog.info("Counting UsbDevice: "+dev.getDeviceName());
mask |= 1 << count++; mask |= 1 << count++;
} }
} }
}
LimeLog.info("Enumerated "+count+" gamepads"); LimeLog.info("Enumerated "+count+" gamepads");
return mask; return mask;
@ -215,7 +220,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
LimeLog.info("Built-in buttons hardcoded as controller 0"); LimeLog.info("Built-in buttons hardcoded as controller 0");
context.controllerNumber = 0; context.controllerNumber = 0;
} }
else if (multiControllerEnabled && devContext.hasJoystickAxes) { else if (prefConfig.multiController && devContext.hasJoystickAxes) {
context.controllerNumber = 0; context.controllerNumber = 0;
LimeLog.info("Reserving the next available controller number"); LimeLog.info("Reserving the next available controller number");
@ -239,7 +244,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
} }
} }
else { else {
if (multiControllerEnabled) { if (prefConfig.multiController) {
context.controllerNumber = 0; context.controllerNumber = 0;
LimeLog.info("Reserving the next available controller number"); LimeLog.info("Reserving the next available controller number");
@ -522,7 +527,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
} }
private short getActiveControllerMask() { private short getActiveControllerMask() {
if (multiControllerEnabled) { if (prefConfig.multiController) {
return (short)(currentControllers | initialControllers); return (short)(currentControllers | initialControllers);
} }
else { else {
@ -985,7 +990,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
// Make sure it's real by checking that the key is actually down before taking // Make sure it's real by checking that the key is actually down before taking
// any action. // any action.
if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 && if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 &&
SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS) { SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS &&
prefConfig.mouseEmulation) {
toggleMouseEmulation(context); toggleMouseEmulation(context);
} }
context.inputMap &= ~ControllerPacket.PLAY_FLAG; context.inputMap &= ~ControllerPacket.PLAY_FLAG;

View File

@ -18,6 +18,7 @@ import android.widget.Toast;
import com.limelight.LimeLog; import com.limelight.LimeLog;
import com.limelight.R; import com.limelight.R;
import com.limelight.preferences.PreferenceConfiguration;
import java.util.ArrayList; import java.util.ArrayList;
@ -27,6 +28,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
"com.limelight.USB_PERMISSION"; "com.limelight.USB_PERMISSION";
private UsbManager usbManager; private UsbManager usbManager;
private PreferenceConfiguration prefConfig;
private final UsbEventReceiver receiver = new UsbEventReceiver(); private final UsbEventReceiver receiver = new UsbEventReceiver();
private final UsbDriverBinder binder = new UsbDriverBinder(); private final UsbDriverBinder binder = new UsbDriverBinder();
@ -119,7 +121,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
private void handleUsbDeviceState(UsbDevice device) { private void handleUsbDeviceState(UsbDevice device) {
// Are we able to operate it? // Are we able to operate it?
if (shouldClaimDevice(device)) { if (shouldClaimDevice(device, prefConfig.bindAllUsb)) {
// Do we have permission yet? // Do we have permission yet?
if (!usbManager.hasPermission(device)) { if (!usbManager.hasPermission(device)) {
// Let's ask for permission // Let's ask for permission
@ -194,16 +196,17 @@ public class UsbDriverService extends Service implements UsbDriverListener {
} }
} }
public static boolean shouldClaimDevice(UsbDevice device) { public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
// We always bind to XB1 controllers but only bind to XB360 controllers // We always bind to XB1 controllers but only bind to XB360 controllers
// if we know the kernel isn't already driving this device. // if we know the kernel isn't already driving this device.
return XboxOneController.canClaimDevice(device) || return XboxOneController.canClaimDevice(device) ||
(!isRecognizedInputDevice(device) && Xbox360Controller.canClaimDevice(device)); ((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
} }
@Override @Override
public void onCreate() { public void onCreate() {
this.usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); this.usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
this.prefConfig = PreferenceConfiguration.readPreferences(this);
// Register for USB attach broadcasts and permission completions // Register for USB attach broadcasts and permission completions
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
@ -213,7 +216,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
// Enumerate existing devices // Enumerate existing devices
for (UsbDevice dev : usbManager.getDeviceList().values()) { for (UsbDevice dev : usbManager.getDeviceList().values()) {
if (shouldClaimDevice(dev)) { if (shouldClaimDevice(dev, prefConfig.bindAllUsb)) {
// Start the process of claiming this device // Start the process of claiming this device
handleUsbDeviceState(dev); handleUsbDeviceState(dev);
} }

View File

@ -27,6 +27,8 @@ public class PreferenceConfiguration {
private static final String DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop"; private static final String DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr"; private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip"; private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
private static final int BITRATE_DEFAULT_720_30 = 5; private static final int BITRATE_DEFAULT_720_30 = 5;
private static final int BITRATE_DEFAULT_720_60 = 10; private static final int BITRATE_DEFAULT_720_60 = 10;
@ -54,6 +56,8 @@ public class PreferenceConfiguration {
private static final boolean DEFAULT_DISABLE_FRAME_DROP = false; private static final boolean DEFAULT_DISABLE_FRAME_DROP = false;
private static final boolean DEFAULT_ENABLE_HDR = false; private static final boolean DEFAULT_ENABLE_HDR = false;
private static final boolean DEFAULT_ENABLE_PIP = false; private static final boolean DEFAULT_ENABLE_PIP = false;
private static final boolean DEFAULT_BIND_ALL_USB = false;
private static final boolean DEFAULT_MOUSE_EMULATION = true;
public static final int FORCE_H265_ON = -1; public static final int FORCE_H265_ON = -1;
public static final int AUTOSELECT_H265 = 0; public static final int AUTOSELECT_H265 = 0;
@ -72,6 +76,8 @@ public class PreferenceConfiguration {
public boolean disableFrameDrop; public boolean disableFrameDrop;
public boolean enableHdr; public boolean enableHdr;
public boolean enablePip; public boolean enablePip;
public boolean bindAllUsb;
public boolean mouseEmulation;
public static int getDefaultBitrate(String resFpsString) { public static int getDefaultBitrate(String resFpsString) {
if (resFpsString.equals("720p30")) { if (resFpsString.equals("720p30")) {
@ -218,6 +224,8 @@ public class PreferenceConfiguration {
config.disableFrameDrop = prefs.getBoolean(DISABLE_FRAME_DROP_PREF_STRING, DEFAULT_DISABLE_FRAME_DROP); config.disableFrameDrop = prefs.getBoolean(DISABLE_FRAME_DROP_PREF_STRING, DEFAULT_DISABLE_FRAME_DROP);
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR); config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR);
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP); config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
return config; return config;
} }

View File

@ -98,7 +98,7 @@
<string name="addpc_success">Successfully added computer</string> <string name="addpc_success">Successfully added computer</string>
<string name="addpc_unknown_host">Unable to resolve PC address. Make sure you didn\'t make a typo in the address.</string> <string name="addpc_unknown_host">Unable to resolve PC address. Make sure you didn\'t make a typo in the address.</string>
<string name="addpc_enter_ip">You must enter an IP address</string> <string name="addpc_enter_ip">You must enter an IP address</string>
<string name="addpc_wrong_sitelocal">That address doesn\'t look right. You must your router\'s public IP address for streaming over the Internet.</string> <string name="addpc_wrong_sitelocal">That address doesn\'t look right. You must use your router\'s public IP address for streaming over the Internet.</string>
<!-- Preferences --> <!-- Preferences -->
<string name="category_basic_settings">Basic Settings</string> <string name="category_basic_settings">Basic Settings</string>
@ -125,7 +125,11 @@
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string> <string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
<string name="suffix_seekbar_deadzone">%</string> <string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string> <string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string>
<string name="summary_checkbox_xb1_driver">Enables a built-in USB driver for devices without native Xbox controller support.</string> <string name="summary_checkbox_xb1_driver">Enables a built-in USB driver for devices without native Xbox controller support</string>
<string name="title_checkbox_usb_bind_all">Override Android controller support</string>
<string name="summary_checkbox_usb_bind_all">Forces Moonlight\'s USB driver to take over all supported Xbox gamepads</string>
<string name="title_checkbox_mouse_emulation">Mouse emulation via gamepad</string>
<string name="summary_checkbox_mouse_emulation">Long pressing the Start button will put the gamepad into mouse mode</string>
<string name="category_on_screen_controls_settings">On-screen Controls Settings</string> <string name="category_on_screen_controls_settings">On-screen Controls Settings</string>
<string name="title_checkbox_show_onscreen_controls">Show on-screen controls</string> <string name="title_checkbox_show_onscreen_controls">Show on-screen controls</string>

View File

@ -56,6 +56,16 @@
android:title="@string/title_checkbox_xb1_driver" android:title="@string/title_checkbox_xb1_driver"
android:summary="@string/summary_checkbox_xb1_driver" android:summary="@string/summary_checkbox_xb1_driver"
android:defaultValue="true" /> android:defaultValue="true" />
<CheckBoxPreference
android:key="checkbox_usb_bind_all"
android:title="@string/title_checkbox_usb_bind_all"
android:summary="@string/summary_checkbox_usb_bind_all"
android:defaultValue="false" />
<CheckBoxPreference
android:key="checkbox_mouse_emulation"
android:title="@string/title_checkbox_mouse_emulation"
android:summary="@string/summary_checkbox_mouse_emulation"
android:defaultValue="true" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/category_on_screen_controls_settings" <PreferenceCategory android:title="@string/category_on_screen_controls_settings"
android:key="category_onscreen_controls"> android:key="category_onscreen_controls">