Compare commits

..
10 Commits
14 changed files with 160 additions and 21 deletions

No files matched your search

+2 -2
View File
@@ -8,8 +8,8 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 28 targetSdkVersion 28
versionName "6.1.3" versionName "6.2"
versionCode = 185 versionCode = 186
} }
flavorDimensions "root" flavorDimensions "root"
+14 -2
View File
@@ -908,7 +908,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return false; return false;
} }
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event)); byte modifiers = getModifierState(event);
if (KeyboardTranslator.needsShift(event.getKeyCode())) {
modifiers |= KeyboardPacket.MODIFIER_SHIFT;
conn.sendKeyboardInput((short) 0x8010, KeyboardPacket.KEY_DOWN, modifiers);
}
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, modifiers);
} }
return true; return true;
@@ -959,7 +964,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return false; return false;
} }
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event)); byte modifiers = getModifierState(event);
if (KeyboardTranslator.needsShift(event.getKeyCode())) {
modifiers |= KeyboardPacket.MODIFIER_SHIFT;
}
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, modifiers);
if (KeyboardTranslator.needsShift(event.getKeyCode())) {
conn.sendKeyboardInput((short) 0x8010, KeyboardPacket.KEY_UP, getModifierState(event));
}
} }
return true; return true;
@@ -200,6 +200,14 @@ public class ShortcutTrampoline extends Activity {
protected boolean validateInput() { protected boolean validateInput() {
// Validate UUID // Validate UUID
if (uuidString == null) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
}
try { try {
UUID.fromString(uuidString); UUID.fromString(uuidString);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
@@ -47,7 +47,21 @@ public class KeyboardTranslator {
public static final int VK_BACK_QUOTE = 192; public static final int VK_BACK_QUOTE = 192;
public static final int VK_QUOTE = 222; public static final int VK_QUOTE = 222;
public static final int VK_PAUSE = 19; public static final int VK_PAUSE = 19;
public static boolean needsShift(int keycode) {
switch (keycode)
{
case KeyEvent.KEYCODE_AT:
case KeyEvent.KEYCODE_POUND:
case KeyEvent.KEYCODE_PLUS:
case KeyEvent.KEYCODE_STAR:
return true;
default:
return false;
}
}
/** /**
* Translates the given keycode and returns the GFE keycode * Translates the given keycode and returns the GFE keycode
* @param keycode the code to be translated * @param keycode the code to be translated
@@ -116,7 +130,8 @@ public class KeyboardTranslator {
case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_ENTER:
translated = 0x0d; translated = 0x0d;
break; break;
case KeyEvent.KEYCODE_PLUS:
case KeyEvent.KEYCODE_EQUALS: case KeyEvent.KEYCODE_EQUALS:
translated = 0xbb; translated = 0xbb;
break; break;
@@ -257,7 +272,19 @@ public class KeyboardTranslator {
case KeyEvent.KEYCODE_NUMPAD_DOT: case KeyEvent.KEYCODE_NUMPAD_DOT:
translated = 0x6E; translated = 0x6E;
break; break;
case KeyEvent.KEYCODE_AT:
translated = 2 + VK_0;
break;
case KeyEvent.KEYCODE_POUND:
translated = 3 + VK_0;
break;
case KeyEvent.KEYCODE_STAR:
translated = 8 + VK_0;
break;
default: default:
System.out.println("No key for "+keycode); System.out.println("No key for "+keycode);
return 0; return 0;
@@ -14,6 +14,7 @@ public class Xbox360Controller extends AbstractXboxController {
private static final int XB360_IFACE_PROTOCOL = 1; // Wired only private static final int XB360_IFACE_PROTOCOL = 1; // Wired only
private static final int[] SUPPORTED_VENDORS = { private static final int[] SUPPORTED_VENDORS = {
0x0079, // GPD Win 2
0x044f, // Thrustmaster 0x044f, // Thrustmaster
0x045e, // Microsoft 0x045e, // Microsoft
0x046d, // Logitech 0x046d, // Logitech
@@ -23,6 +24,7 @@ public class Xbox360Controller extends AbstractXboxController {
0x07ff, // Mad Catz 0x07ff, // Mad Catz
0x0e6f, // Unknown 0x0e6f, // Unknown
0x0f0d, // Hori 0x0f0d, // Hori
0x1038, // SteelSeries
0x11c9, // Nacon 0x11c9, // Nacon
0x12ab, // Unknown 0x12ab, // Unknown
0x1430, // RedOctane 0x1430, // RedOctane
@@ -8,6 +8,7 @@ import com.limelight.LimeLog;
import com.limelight.nvstream.input.ControllerPacket; import com.limelight.nvstream.input.ControllerPacket;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
public class XboxOneController extends AbstractXboxController { public class XboxOneController extends AbstractXboxController {
@@ -23,8 +24,30 @@ public class XboxOneController extends AbstractXboxController {
0x24c6, // PowerA 0x24c6, // PowerA
}; };
// FIXME: odata_serial private static final byte[] FW2015_INIT = {0x05, 0x20, 0x00, 0x01, 0x00};
private static final byte[] XB1_INIT_DATA = {0x05, 0x20, 0x00, 0x01, 0x00}; private static final byte[] HORI_INIT = {0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
0x00, 0x00, 0x00, (byte)0x80, 0x00};
private static final byte[] PDP_INIT1 = {0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14};
private static final byte[] PDP_INIT2 = {0x06, 0x20, 0x00, 0x02, 0x01, 0x00};
private static final byte[] RUMBLE_INIT1 = {0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x1D, 0x1D, (byte)0xFF, 0x00, 0x00};
private static final byte[] RUMBLE_INIT2 = {0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00};
private static InitPacket[] INIT_PKTS = {
new InitPacket(0x0e6f, 0x0165, HORI_INIT),
new InitPacket(0x0f0d, 0x0067, HORI_INIT),
new InitPacket(0x0000, 0x0000, FW2015_INIT),
new InitPacket(0x0e6f, 0x0000, PDP_INIT1),
new InitPacket(0x0e6f, 0x0000, PDP_INIT2),
new InitPacket(0x24c6, 0x541a, RUMBLE_INIT1),
new InitPacket(0x24c6, 0x542a, RUMBLE_INIT1),
new InitPacket(0x24c6, 0x543a, RUMBLE_INIT1),
new InitPacket(0x24c6, 0x541a, RUMBLE_INIT2),
new InitPacket(0x24c6, 0x542a, RUMBLE_INIT2),
new InitPacket(0x24c6, 0x543a, RUMBLE_INIT2),
};
public XboxOneController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) { public XboxOneController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
super(device, connection, deviceId, listener); super(device, connection, deviceId, listener);
@@ -111,13 +134,43 @@ public class XboxOneController extends AbstractXboxController {
@Override @Override
protected boolean doInit() { protected boolean doInit() {
// Send the initialization packet byte seqNum = 0;
int res = connection.bulkTransfer(outEndpt, XB1_INIT_DATA, XB1_INIT_DATA.length, 3000);
if (res != XB1_INIT_DATA.length) { // Send all applicable init packets
LimeLog.warning("Initialization transfer failed: "+res); for (InitPacket pkt : INIT_PKTS) {
return false; if (pkt.vendorId != 0 && device.getVendorId() != pkt.vendorId) {
continue;
}
if (pkt.productId != 0 && device.getProductId() != pkt.productId) {
continue;
}
byte[] data = Arrays.copyOf(pkt.data, pkt.data.length);
// Populate sequence number
data[2] = seqNum++;
// Send the initialization packet
int res = connection.bulkTransfer(outEndpt, data, data.length, 3000);
if (res != data.length) {
LimeLog.warning("Initialization transfer failed: "+res);
return false;
}
} }
return true; return true;
} }
private static class InitPacket {
final int vendorId;
final int productId;
final byte[] data;
InitPacket(int vendorId, int productId, byte[] data) {
this.vendorId = vendorId;
this.productId = productId;
this.data = data;
}
}
} }
@@ -9,6 +9,7 @@ import android.widget.TextView;
import com.limelight.PcView; import com.limelight.PcView;
import com.limelight.R; import com.limelight.R;
import com.limelight.nvstream.http.ComputerDetails; import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.PairingManager;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@@ -77,6 +78,14 @@ public class PcGridAdapter extends GenericGridAdapter<PcView.ComputerObject> {
overlayView.setAlpha(0.4f); overlayView.setAlpha(0.4f);
return true; return true;
} }
// We must check if the status is exactly online and unpaired
// to avoid colliding with the loading spinner when status is unknown
else if (obj.details.state == ComputerDetails.State.ONLINE &&
obj.details.pairState == PairingManager.PairState.NOT_PAIRED) {
overlayView.setImageResource(R.drawable.ic_lock);
overlayView.setAlpha(1.0f);
return true;
}
return false; return false;
} }
} }
@@ -91,14 +91,20 @@ public class AddComputerManually extends Activity {
} }
private void doAddPc(String host) { private void doAddPc(String host) {
String msg;
boolean wrongSiteLocal = false; boolean wrongSiteLocal = false;
boolean success; boolean success;
SpinnerDialog dialog = SpinnerDialog.displayDialog(this, getResources().getString(R.string.title_add_pc), SpinnerDialog dialog = SpinnerDialog.displayDialog(this, getResources().getString(R.string.title_add_pc),
getResources().getString(R.string.msg_add_pc), false); getResources().getString(R.string.msg_add_pc), false);
success = managerBinder.addComputerBlocking(host, true); try {
success = managerBinder.addComputerBlocking(host, true);
} catch (IllegalArgumentException e) {
// This can be thrown from OkHttp if the host fails to canonicalize to a valid name.
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
e.printStackTrace();
success = false;
}
if (!success){ if (!success){
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host); wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
} }
@@ -84,6 +84,9 @@ public class PreferenceConfiguration {
if (resString.equalsIgnoreCase("360p")) { if (resString.equalsIgnoreCase("360p")) {
return 360; return 360;
} }
else if (resString.equalsIgnoreCase("480p")) {
return 480;
}
else if (resString.equalsIgnoreCase("720p")) { else if (resString.equalsIgnoreCase("720p")) {
return 720; return 720;
} }
@@ -103,13 +106,22 @@ public class PreferenceConfiguration {
} }
private static int getWidthFromResolutionString(String resString) { private static int getWidthFromResolutionString(String resString) {
return (getHeightFromResolutionString(resString) * 16) / 9; int height = getHeightFromResolutionString(resString);
if (height == 480) {
// This isn't an exact 16:9 resolution
return 854;
}
else {
return (height * 16) / 9;
}
} }
private static String getResolutionString(int width, int height) { private static String getResolutionString(int width, int height) {
switch (height) { switch (height) {
case 360: case 360:
return "360p"; return "360p";
case 480:
return "480p";
default: default:
case 720: case 720:
return "720p"; return "720p";
@@ -139,6 +151,9 @@ public class PreferenceConfiguration {
if (width * height <= 640 * 360) { if (width * height <= 640 * 360) {
return (int)(1000 * (fps / 30.0)); return (int)(1000 * (fps / 30.0));
} }
else if (width * height <= 854 * 480) {
return (int)(1500 * (fps / 30.0));
}
// This covers 1280x720 and 1280x800 too // This covers 1280x720 and 1280x800 too
else if (width * height <= 1366 * 768) { else if (width * height <= 1366 * 768) {
return (int)(5000 * (fps / 30.0)); return (int)(5000 * (fps / 30.0));
+5
View File
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
</vector>
+2
View File
@@ -2,6 +2,7 @@
<resources> <resources>
<string-array name="resolution_names"> <string-array name="resolution_names">
<item>360p</item> <item>360p</item>
<item>480p</item>
<item>720p</item> <item>720p</item>
<item>1080p</item> <item>1080p</item>
<item>1440p</item> <item>1440p</item>
@@ -9,6 +10,7 @@
</string-array> </string-array>
<string-array name="resolution_values" translatable="false"> <string-array name="resolution_values" translatable="false">
<item>360p</item> <item>360p</item>
<item>480p</item>
<item>720p</item> <item>720p</item>
<item>1080p</item> <item>1080p</item>
<item>1440p</item> <item>1440p</item>
+1 -1
View File
@@ -5,7 +5,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.android.tools.build:gradle:3.3.1'
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
#Tue May 08 18:56:31 PDT 2018 #Tue Feb 05 20:54:22 PST 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip