Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 35fb96f9f4 | |||
| 37371906d5 | |||
| 83a9539f4b | |||
| b214fe5301 | |||
| 57779b4e89 | |||
| 547932f8b2 | |||
| 762fa0fe2f | |||
| 9cedc57df2 | |||
| ba81f8096a | |||
| c4fa654166 | |||
| 8ac440b68b | |||
| 165386b941 | |||
| 3a7398f321 | |||
| ebb1d0dfa2 | |||
| 1ca1ed5d20 | |||
| b416bafb78 | |||
| 3a301b74a6 | |||
| 71d463f063 | |||
| 1fae816223 | |||
| 989d6fc169 | |||
| 381509b3a6 | |||
| d8ae40376e | |||
| 4ea93f5e68 | |||
| cd84c8f30e | |||
| 8d4cdca7c3 | |||
| c0239c36fd | |||
| 9d9f729e42 | |||
| 6c5fe18b6e | |||
| 1994bf6522 | |||
| 31381e5664 | |||
| fac1b1d7e5 | |||
| 40c406051c | |||
| 8bac873e67 | |||
| a170e1efd7 | |||
| 17bffa8d78 | |||
| 289222749b | |||
| 81d84600d4 | |||
| 0b15fd582d | |||
| cbe4a1cde6 | |||
| 89ef16c02e | |||
| 58b6ed8d00 | |||
| 7d01e1a7a4 |
+1
-1
@@ -30,7 +30,7 @@ Thumbs.db
|
|||||||
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
|
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
|
||||||
.gradle
|
.gradle
|
||||||
build/
|
build/
|
||||||
app/app.iml
|
*.iml
|
||||||
|
|
||||||
# Compiled JNI libraries folder
|
# Compiled JNI libraries folder
|
||||||
**/jniLibs
|
**/jniLibs
|
||||||
|
|||||||
+16
-4
@@ -7,8 +7,8 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
|
|
||||||
versionName "5.7.2"
|
versionName "5.8"
|
||||||
versionCode = 150
|
versionCode = 161
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "root"
|
flavorDimensions "root"
|
||||||
@@ -45,9 +45,21 @@ android {
|
|||||||
disable 'MissingTranslation'
|
disable 'MissingTranslation'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bundle {
|
||||||
|
language {
|
||||||
|
// Avoid splitting by language, since we allow users
|
||||||
|
// to manually switch language in settings.
|
||||||
|
enableSplit = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
|
|
||||||
|
minifyEnabled true
|
||||||
|
useProguard false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
// To whomever is releasing/using an APK in release mode with
|
// To whomever is releasing/using an APK in release mode with
|
||||||
@@ -82,8 +94,8 @@ android {
|
|||||||
// TL;DR: Leave the following line alone!
|
// TL;DR: Leave the following line alone!
|
||||||
applicationIdSuffix ".unofficial"
|
applicationIdSuffix ".unofficial"
|
||||||
|
|
||||||
minifyEnabled false
|
minifyEnabled true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt')
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+27
@@ -0,0 +1,27 @@
|
|||||||
|
# Don't obfuscate code
|
||||||
|
-dontobfuscate
|
||||||
|
|
||||||
|
# Our code
|
||||||
|
-keep class com.limelight.binding.input.evdev.* {*;}
|
||||||
|
|
||||||
|
# Moonlight common
|
||||||
|
-keep class com.limelight.nvstream.jni.* {*;}
|
||||||
|
|
||||||
|
# Okio
|
||||||
|
-keep class sun.misc.Unsafe {*;}
|
||||||
|
-dontwarn java.nio.file.*
|
||||||
|
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||||
|
-dontwarn okio.**
|
||||||
|
|
||||||
|
# BouncyCastle
|
||||||
|
-keep class org.bouncycastle.jcajce.provider.asymmetric.* {*;}
|
||||||
|
-keep class org.bouncycastle.jcajce.provider.asymmetric.util.* {*;}
|
||||||
|
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.* {*;}
|
||||||
|
-keep class org.bouncycastle.jcajce.provider.digest.** {*;}
|
||||||
|
-keep class org.bouncycastle.jcajce.provider.symmetric.** {*;}
|
||||||
|
-keep class org.bouncycastle.jcajce.spec.* {*;}
|
||||||
|
-keep class org.bouncycastle.jce.** {*;}
|
||||||
|
-dontwarn javax.naming.**
|
||||||
|
|
||||||
|
# jMDNS
|
||||||
|
-dontwarn javax.jmdns.impl.DNSCache
|
||||||
@@ -99,10 +99,11 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="com.limelight.PcView" />
|
android:value="com.limelight.PcView" />
|
||||||
</activity>
|
</activity>
|
||||||
|
<!-- This will fall back to sensorLandscape at runtime on Android 4.2 and below -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".Game"
|
android:name=".Game"
|
||||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||||
android:screenOrientation="sensorLandscape"
|
android:screenOrientation="userLandscape"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:supportsPictureInPicture="true"
|
android:supportsPictureInPicture="true"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ public class AppViewShortcutTrampoline extends Activity {
|
|||||||
blockingLoadSpinner = null;
|
blockingLoadSpinner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the managerBinder was destroyed before this callback,
|
||||||
|
// just finish the activity.
|
||||||
|
if (managerBinder == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (details.state == ComputerDetails.State.ONLINE) {
|
if (details.state == ComputerDetails.State.ONLINE) {
|
||||||
// Close this activity
|
// Close this activity
|
||||||
finish();
|
finish();
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
@@ -69,7 +71,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
public class Game extends Activity implements SurfaceHolder.Callback,
|
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||||
OnSystemUiVisibilityChangeListener, GameGestures
|
OnSystemUiVisibilityChangeListener, GameGestures, StreamView.InputCallbacks
|
||||||
{
|
{
|
||||||
private int lastMouseX = Integer.MIN_VALUE;
|
private int lastMouseX = Integer.MIN_VALUE;
|
||||||
private int lastMouseY = Integer.MIN_VALUE;
|
private int lastMouseY = Integer.MIN_VALUE;
|
||||||
@@ -95,6 +97,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
private boolean displayedFailureDialog = false;
|
private boolean displayedFailureDialog = false;
|
||||||
private boolean connecting = false;
|
private boolean connecting = false;
|
||||||
private boolean connected = false;
|
private boolean connected = false;
|
||||||
|
private boolean surfaceCreated = false;
|
||||||
|
private boolean attemptedConnection = false;
|
||||||
|
|
||||||
private InputCaptureProvider inputCaptureProvider;
|
private InputCaptureProvider inputCaptureProvider;
|
||||||
private int modifierFlags = 0;
|
private int modifierFlags = 0;
|
||||||
@@ -158,6 +162,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We specified userLandscape in the manifest which isn't supported until 4.3,
|
||||||
|
// so we must fall back at runtime to sensorLandscape.
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||||
|
}
|
||||||
|
|
||||||
// Listen for UI visibility events
|
// Listen for UI visibility events
|
||||||
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
|
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
|
||||||
|
|
||||||
@@ -180,6 +190,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
streamView = findViewById(R.id.surfaceView);
|
streamView = findViewById(R.id.surfaceView);
|
||||||
streamView.setOnGenericMotionListener(this);
|
streamView.setOnGenericMotionListener(this);
|
||||||
streamView.setOnTouchListener(this);
|
streamView.setOnTouchListener(this);
|
||||||
|
streamView.setInputCallbacks(this);
|
||||||
|
|
||||||
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
||||||
|
|
||||||
@@ -296,8 +307,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int gamepadMask = ControllerHandler.getAttachedControllerMask(this);
|
int gamepadMask = ControllerHandler.getAttachedControllerMask(this);
|
||||||
if (!prefConfig.multiController && gamepadMask != 0) {
|
if (!prefConfig.multiController) {
|
||||||
// If any gamepads are present in non-MC mode, set only gamepad 1.
|
// Always set gamepad 1 present for when multi-controller is
|
||||||
|
// disabled for games that don't properly support detection
|
||||||
|
// of gamepads removed and replugged at runtime.
|
||||||
gamepadMask = 1;
|
gamepadMask = 1;
|
||||||
}
|
}
|
||||||
if (prefConfig.onscreenController) {
|
if (prefConfig.onscreenController) {
|
||||||
@@ -415,19 +428,46 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
streamView.getHolder().addCallback(this);
|
streamView.getHolder().addCallback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
|
||||||
|
if (virtualController != null) {
|
||||||
|
// Refresh layout of OSC for possible new screen size
|
||||||
|
virtualController.refreshLayout();
|
||||||
|
|
||||||
|
// Hide OSC in PiP
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
if (isInPictureInPictureMode()) {
|
||||||
|
virtualController.hide();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
virtualController.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUserLeaveHint() {
|
public void onUserLeaveHint() {
|
||||||
super.onUserLeaveHint();
|
super.onUserLeaveHint();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
if (prefConfig.enablePip && connected) {
|
if (prefConfig.enablePip && connected) {
|
||||||
enterPictureInPictureMode(
|
try {
|
||||||
new PictureInPictureParams.Builder()
|
// This has thrown all sorts of weird exceptions on Samsung devices
|
||||||
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
// running Oreo. Just eat them and close gracefully on leave, rather
|
||||||
.setSourceRectHint(new Rect(
|
// than crashing.
|
||||||
streamView.getLeft(), streamView.getTop(),
|
enterPictureInPictureMode(
|
||||||
streamView.getRight(), streamView.getBottom()))
|
new PictureInPictureParams.Builder()
|
||||||
.build());
|
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
||||||
|
.setSourceRectHint(new Rect(
|
||||||
|
streamView.getLeft(), streamView.getTop(),
|
||||||
|
streamView.getRight(), streamView.getBottom()))
|
||||||
|
.build());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,9 +819,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
|
return handleKeyDown(event) || super.onKeyDown(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyDown(KeyEvent event) {
|
||||||
// Pass-through virtual navigation keys
|
// Pass-through virtual navigation keys
|
||||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
@@ -793,11 +838,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
boolean handled = false;
|
boolean handled = false;
|
||||||
|
|
||||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
|
||||||
if (detectedGamepad || (event.getDevice() == null ||
|
|
||||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
|
||||||
)) {
|
|
||||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||||
handled = controllerHandler.handleButtonDown(event);
|
handled = controllerHandler.handleButtonDown(event);
|
||||||
@@ -807,17 +848,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Try the keyboard handler
|
// Try the keyboard handler
|
||||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||||
if (translated == 0) {
|
if (translated == 0) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let this method take duplicate key down events
|
// Let this method take duplicate key down events
|
||||||
if (handleSpecialKeys(keyCode, true)) {
|
if (handleSpecialKeys(event.getKeyCode(), true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass through keyboard input if we're not grabbing
|
// Pass through keyboard input if we're not grabbing
|
||||||
if (!grabbedInput) {
|
if (!grabbedInput) {
|
||||||
return super.onKeyDown(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
||||||
@@ -828,9 +869,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
|
return handleKeyUp(event) || super.onKeyUp(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handleKeyUp(KeyEvent event) {
|
||||||
// Pass-through virtual navigation keys
|
// Pass-through virtual navigation keys
|
||||||
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
if ((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
@@ -841,11 +887,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean handled = false;
|
boolean handled = false;
|
||||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
|
||||||
if (detectedGamepad || (event.getDevice() == null ||
|
|
||||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
|
||||||
)) {
|
|
||||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||||
handled = controllerHandler.handleButtonUp(event);
|
handled = controllerHandler.handleButtonUp(event);
|
||||||
@@ -855,16 +897,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Try the keyboard handler
|
// Try the keyboard handler
|
||||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||||
if (translated == 0) {
|
if (translated == 0) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handleSpecialKeys(keyCode, false)) {
|
if (handleSpecialKeys(event.getKeyCode(), false)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass through keyboard input if we're not grabbing
|
// Pass through keyboard input if we're not grabbing
|
||||||
if (!grabbedInput) {
|
if (!grabbedInput) {
|
||||||
return super.onKeyUp(keyCode, event);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
||||||
@@ -961,6 +1003,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
lastMouseX = (int)event.getX();
|
lastMouseX = (int)event.getX();
|
||||||
lastMouseY = (int)event.getY();
|
lastMouseY = (int)event.getY();
|
||||||
}
|
}
|
||||||
|
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
// We get a normal (non-relative) MotionEvent when starting pointer capture to synchronize the
|
||||||
|
// location of the cursor with our app. We don't want this, so we must discard this event.
|
||||||
|
lastMouseX = (int)event.getX();
|
||||||
|
lastMouseY = (int)event.getY();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// First process the history
|
// First process the history
|
||||||
for (int i = 0; i < event.getHistorySize(); i++) {
|
for (int i = 0; i < event.getHistorySize(); i++) {
|
||||||
@@ -1193,8 +1241,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
spinner = null;
|
spinner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
connecting = false;
|
|
||||||
connected = true;
|
connected = true;
|
||||||
|
connecting = false;
|
||||||
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1233,12 +1281,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||||
}
|
if (!surfaceCreated) {
|
||||||
|
throw new IllegalStateException("Surface changed before creation!");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
if (!attemptedConnection) {
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
attemptedConnection = true;
|
||||||
if (!connected && !connecting) {
|
|
||||||
connecting = true;
|
|
||||||
|
|
||||||
decoderRenderer.setRenderTarget(holder);
|
decoderRenderer.setRenderTarget(holder);
|
||||||
conn.start(PlatformBinding.getAudioRenderer(), decoderRenderer, Game.this);
|
conn.start(PlatformBinding.getAudioRenderer(), decoderRenderer, Game.this);
|
||||||
@@ -1246,12 +1294,23 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
// Let the decoder know immediately that the surface is gone
|
surfaceCreated = true;
|
||||||
decoderRenderer.prepareForStop();
|
}
|
||||||
|
|
||||||
if (connected) {
|
@Override
|
||||||
stopConnection();
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
|
if (!surfaceCreated) {
|
||||||
|
throw new IllegalStateException("Surface destroyed before creation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attemptedConnection) {
|
||||||
|
// Let the decoder know immediately that the surface is gone
|
||||||
|
decoderRenderer.prepareForStop();
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
stopConnection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,30 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
onInputDeviceAdded(deviceId);
|
onInputDeviceAdded(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasJoystickAxes(InputDevice device) {
|
||||||
|
return (device.getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK &&
|
||||||
|
getMotionRangeForJoystickAxis(device, MotionEvent.AXIS_X) != null &&
|
||||||
|
getMotionRangeForJoystickAxis(device, MotionEvent.AXIS_Y) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasGamepadButtons(InputDevice device) {
|
||||||
|
return (device.getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isGameControllerDevice(InputDevice device) {
|
||||||
|
if (device == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasJoystickAxes(device) || hasGamepadButtons(device)) {
|
||||||
|
// Has real joystick axes or gamepad buttons
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we'll try anything that claims to be a non-alphabetic keyboard
|
||||||
|
return device.getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC;
|
||||||
|
}
|
||||||
|
|
||||||
public static short getAttachedControllerMask(Context context) {
|
public static short getAttachedControllerMask(Context context) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
short mask = 0;
|
short mask = 0;
|
||||||
@@ -161,7 +185,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0) {
|
if (hasJoystickAxes(dev)) {
|
||||||
LimeLog.info("Counting InputDevice: "+dev.getName());
|
LimeLog.info("Counting InputDevice: "+dev.getName());
|
||||||
mask |= 1 << count++;
|
mask |= 1 << count++;
|
||||||
}
|
}
|
||||||
@@ -835,16 +859,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
// to normal behavior, so ignore triggersIdleNegative for each trigger until
|
// to normal behavior, so ignore triggersIdleNegative for each trigger until
|
||||||
// first touch.
|
// first touch.
|
||||||
if (lt != 0) {
|
if (lt != 0) {
|
||||||
context.leftTriggerUsed = true;
|
context.leftTriggerAxisUsed = true;
|
||||||
}
|
}
|
||||||
if (rt != 0) {
|
if (rt != 0) {
|
||||||
context.rightTriggerUsed = true;
|
context.rightTriggerAxisUsed = true;
|
||||||
}
|
}
|
||||||
if (context.triggersIdleNegative) {
|
if (context.triggersIdleNegative) {
|
||||||
if (context.leftTriggerUsed) {
|
if (context.leftTriggerAxisUsed) {
|
||||||
lt = (lt + 1) / 2;
|
lt = (lt + 1) / 2;
|
||||||
}
|
}
|
||||||
if (context.rightTriggerUsed) {
|
if (context.rightTriggerAxisUsed) {
|
||||||
rt = (rt + 1) / 2;
|
rt = (rt + 1) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1040,15 +1064,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
context.inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
context.inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||||
if (context.leftTriggerAxis >= 0) {
|
if (context.leftTriggerAxisUsed) {
|
||||||
// Suppress this digital event if an analog trigger is present
|
// Suppress this digital event if an analog trigger is active
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
context.leftTrigger = 0;
|
context.leftTrigger = 0;
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||||
if (context.rightTriggerAxis >= 0) {
|
if (context.rightTriggerAxisUsed) {
|
||||||
// Suppress this digital event if an analog trigger is present
|
// Suppress this digital event if an analog trigger is active
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
context.rightTrigger = 0;
|
context.rightTrigger = 0;
|
||||||
@@ -1160,15 +1184,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
context.inputMap |= ControllerPacket.RS_CLK_FLAG;
|
context.inputMap |= ControllerPacket.RS_CLK_FLAG;
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||||
if (context.leftTriggerAxis >= 0) {
|
if (context.leftTriggerAxisUsed) {
|
||||||
// Suppress this digital event if an analog trigger is present
|
// Suppress this digital event if an analog trigger is active
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
context.leftTrigger = (byte)0xFF;
|
context.leftTrigger = (byte)0xFF;
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||||
if (context.rightTriggerAxis >= 0) {
|
if (context.rightTriggerAxisUsed) {
|
||||||
// Suppress this digital event if an analog trigger is present
|
// Suppress this digital event if an analog trigger is active
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
context.rightTrigger = (byte)0xFF;
|
context.rightTrigger = (byte)0xFF;
|
||||||
@@ -1299,7 +1323,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
|||||||
public int leftTriggerAxis = -1;
|
public int leftTriggerAxis = -1;
|
||||||
public int rightTriggerAxis = -1;
|
public int rightTriggerAxis = -1;
|
||||||
public boolean triggersIdleNegative;
|
public boolean triggersIdleNegative;
|
||||||
public boolean leftTriggerUsed, rightTriggerUsed;
|
public boolean leftTriggerAxisUsed, rightTriggerAxisUsed;
|
||||||
|
|
||||||
public int hatXAxis = -1;
|
public int hatXAxis = -1;
|
||||||
public int hatYAxis = -1;
|
public int hatYAxis = -1;
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public class AnalogStick extends VirtualControllerElement {
|
|||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
// calculate new radius sizes depending
|
// calculate new radius sizes depending
|
||||||
radius_complete = getPercent(getCorrectWidth() / 2, 90);
|
radius_complete = getPercent(getCorrectWidth() / 2, 100);
|
||||||
radius_dead_zone = getPercent(getCorrectWidth() / 2, 30);
|
radius_dead_zone = getPercent(getCorrectWidth() / 2, 30);
|
||||||
radius_analog_stick = getPercent(getCorrectWidth() / 2, 20);
|
radius_analog_stick = getPercent(getCorrectWidth() / 2, 20);
|
||||||
|
|
||||||
|
|||||||
+8
@@ -86,6 +86,14 @@ public class VirtualController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
relative_layout.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
relative_layout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
public void removeElements() {
|
public void removeElements() {
|
||||||
for (VirtualControllerElement element : elements) {
|
for (VirtualControllerElement element : elements) {
|
||||||
relative_layout.removeView(element);
|
relative_layout.removeView(element);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.limelight.binding.video;
|
package com.limelight.binding.video;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.jcodec.codecs.h264.H264Utils;
|
import org.jcodec.codecs.h264.H264Utils;
|
||||||
@@ -41,7 +40,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
|
|
||||||
private MediaCodec videoDecoder;
|
private MediaCodec videoDecoder;
|
||||||
private Thread rendererThread;
|
private Thread rendererThread;
|
||||||
private Thread[] spinnerThreads;
|
|
||||||
private boolean needsSpsBitstreamFixup, isExynos4;
|
private boolean needsSpsBitstreamFixup, isExynos4;
|
||||||
private boolean adaptivePlayback, directSubmit;
|
private boolean adaptivePlayback, directSubmit;
|
||||||
private boolean constrainedHighProfile;
|
private boolean constrainedHighProfile;
|
||||||
@@ -132,14 +130,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
this.consecutiveCrashCount = consecutiveCrashCount;
|
this.consecutiveCrashCount = consecutiveCrashCount;
|
||||||
this.glRenderer = glRenderer;
|
this.glRenderer = glRenderer;
|
||||||
|
|
||||||
// Disable spinner threads in battery saver mode or 4K
|
|
||||||
if (prefs.batterySaver || prefs.height >= 2160) {
|
|
||||||
spinnerThreads = new Thread[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
spinnerThreads = new Thread[Runtime.getRuntime().availableProcessors()];
|
|
||||||
}
|
|
||||||
|
|
||||||
avcDecoder = findAvcDecoder();
|
avcDecoder = findAvcDecoder();
|
||||||
if (avcDecoder != null) {
|
if (avcDecoder != null) {
|
||||||
LimeLog.info("Selected AVC decoder: "+avcDecoder.getName());
|
LimeLog.info("Selected AVC decoder: "+avcDecoder.getName());
|
||||||
@@ -217,15 +207,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyVideoForeground() {
|
public void notifyVideoForeground() {
|
||||||
startSpinnerThreads();
|
|
||||||
foreground = true;
|
foreground = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyVideoBackground() {
|
public void notifyVideoBackground() {
|
||||||
// Signal the spinner threads to stop but
|
|
||||||
// don't wait for them to terminate to avoid
|
|
||||||
// delaying the state transition
|
|
||||||
signalSpinnerStop();
|
|
||||||
foreground = false;
|
foreground = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,73 +447,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
rendererThread.start();
|
rendererThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startSpinnerThread(final int i) {
|
|
||||||
spinnerThreads[i] = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// This thread exists to keep the CPU at a higher DVFS state on devices
|
|
||||||
// where the governor scales clock speed sporadically, causing dropped frames.
|
|
||||||
//
|
|
||||||
// Run until we notice our thread has been removed from the spinner threads
|
|
||||||
// array. Even if we don't notice immediately, we'll notice soon enough.
|
|
||||||
// This will also ensure we terminate even if someone has restarted spinning
|
|
||||||
// before we realized we should stop.
|
|
||||||
while (this == spinnerThreads[i]) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(0, 1);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spinnerThreads[i].setName("Spinner-"+i);
|
|
||||||
spinnerThreads[i].setPriority(Thread.MIN_PRIORITY);
|
|
||||||
spinnerThreads[i].start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startSpinnerThreads() {
|
|
||||||
LimeLog.info("Using "+spinnerThreads.length+" spinner threads");
|
|
||||||
for (int i = 0; i < spinnerThreads.length; i++) {
|
|
||||||
if (spinnerThreads[i] != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
startSpinnerThread(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Thread[] signalSpinnerStop() {
|
|
||||||
// Capture current running threads
|
|
||||||
Thread[] runningThreads = Arrays.copyOf(spinnerThreads, spinnerThreads.length);
|
|
||||||
|
|
||||||
// Clear the spinner threads to signal their termination
|
|
||||||
for (int i = 0; i < spinnerThreads.length; i++) {
|
|
||||||
spinnerThreads[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interrupt the threads
|
|
||||||
for (int i = 0; i < runningThreads.length; i++) {
|
|
||||||
if (runningThreads[i] != null) {
|
|
||||||
runningThreads[i].interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return runningThreads;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopSpinnerThreads() {
|
|
||||||
// Signal and wait for the threads to stop
|
|
||||||
Thread[] runningThreads = signalSpinnerStop();
|
|
||||||
for (int i = 0; i < runningThreads.length; i++) {
|
|
||||||
if (runningThreads[i] != null) {
|
|
||||||
try {
|
|
||||||
runningThreads[i].join();
|
|
||||||
} catch (InterruptedException ignored) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int dequeueInputBuffer() {
|
private int dequeueInputBuffer() {
|
||||||
int index = -1;
|
int index = -1;
|
||||||
long startTime;
|
long startTime;
|
||||||
@@ -570,7 +488,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
startRendererThread();
|
startRendererThread();
|
||||||
startSpinnerThreads();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// !!! May be called even if setup()/start() fails !!!
|
// !!! May be called even if setup()/start() fails !!!
|
||||||
@@ -593,9 +510,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
try {
|
try {
|
||||||
rendererThread.join();
|
rendererThread.join();
|
||||||
} catch (InterruptedException ignored) { }
|
} catch (InterruptedException ignored) { }
|
||||||
|
|
||||||
// Halt the spinner threads
|
|
||||||
stopSpinnerThreads();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -718,7 +632,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
LimeLog.info("Patching level_idc to 31");
|
LimeLog.info("Patching level_idc to 31");
|
||||||
sps.levelIdc = 31;
|
sps.levelIdc = 31;
|
||||||
}
|
}
|
||||||
if (initialWidth <= 1280 && initialHeight <= 720) {
|
else if (initialWidth <= 1280 && initialHeight <= 720) {
|
||||||
// Max 5 buffered frames at 1280x720x60
|
// Max 5 buffered frames at 1280x720x60
|
||||||
LimeLog.info("Patching level_idc to 32");
|
LimeLog.info("Patching level_idc to 32");
|
||||||
sps.levelIdc = 32;
|
sps.levelIdc = 32;
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ public class MediaCodecHelper {
|
|||||||
blacklistedDecoderPrefixes = new LinkedList<>();
|
blacklistedDecoderPrefixes = new LinkedList<>();
|
||||||
|
|
||||||
// Blacklist software decoders that don't support H264 high profile,
|
// Blacklist software decoders that don't support H264 high profile,
|
||||||
// but exclude the official AOSP emulator from this restriction.
|
// but exclude the official AOSP and CrOS emulator from this restriction.
|
||||||
if (!Build.HARDWARE.equals("ranchu") || !Build.BRAND.equals("google")) {
|
if (!Build.HARDWARE.equals("ranchu") && !Build.HARDWARE.equals("cheets")) {
|
||||||
blacklistedDecoderPrefixes.add("omx.google");
|
blacklistedDecoderPrefixes.add("omx.google");
|
||||||
blacklistedDecoderPrefixes.add("AVCDecoder");
|
blacklistedDecoderPrefixes.add("AVCDecoder");
|
||||||
}
|
}
|
||||||
@@ -135,6 +135,7 @@ public class MediaCodecHelper {
|
|||||||
// to actually be tested. Ugh...
|
// to actually be tested. Ugh...
|
||||||
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
||||||
whitelistedHevcDecoders.add("omx.mtk");
|
whitelistedHevcDecoders.add("omx.mtk");
|
||||||
|
whitelistedHevcDecoders.add("omx.amlogic");
|
||||||
}
|
}
|
||||||
|
|
||||||
// These theoretically have good HEVC decoding capabilities (potentially better than
|
// These theoretically have good HEVC decoding capabilities (potentially better than
|
||||||
@@ -336,7 +337,7 @@ public class MediaCodecHelper {
|
|||||||
|
|
||||||
// This device seems to crash constantly at 720p, so try disabling
|
// This device seems to crash constantly at 720p, so try disabling
|
||||||
// RFI to see if we can get that under control.
|
// RFI to see if we can get that under control.
|
||||||
if (Build.PRODUCT.equalsIgnoreCase("b3_att_us")) {
|
if (Build.DEVICE.equals("b3") || Build.DEVICE.equals("b5")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ public class PreferenceConfiguration {
|
|||||||
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
|
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
|
||||||
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
||||||
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
|
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
|
||||||
private static final String BATTERY_SAVER_PREF_STRING = "checkbox_battery_saver";
|
|
||||||
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";
|
||||||
@@ -75,7 +74,6 @@ public class PreferenceConfiguration {
|
|||||||
public boolean listMode, smallIconMode, multiController, enable51Surround, usbDriver;
|
public boolean listMode, smallIconMode, multiController, enable51Surround, usbDriver;
|
||||||
public boolean onscreenController;
|
public boolean onscreenController;
|
||||||
public boolean onlyL3R3;
|
public boolean onlyL3R3;
|
||||||
public boolean batterySaver;
|
|
||||||
public boolean disableFrameDrop;
|
public boolean disableFrameDrop;
|
||||||
public boolean enableHdr;
|
public boolean enableHdr;
|
||||||
public boolean enablePip;
|
public boolean enablePip;
|
||||||
@@ -244,7 +242,6 @@ public class PreferenceConfiguration {
|
|||||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||||
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
|
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
|
||||||
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
|
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
|
||||||
config.batterySaver = prefs.getBoolean(BATTERY_SAVER_PREF_STRING, DEFAULT_BATTERY_SAVER);
|
|
||||||
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);
|
||||||
|
|||||||
@@ -3,15 +3,21 @@ package com.limelight.ui;
|
|||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
public class StreamView extends SurfaceView {
|
public class StreamView extends SurfaceView {
|
||||||
private double desiredAspectRatio;
|
private double desiredAspectRatio;
|
||||||
|
private InputCallbacks inputCallbacks;
|
||||||
|
|
||||||
public void setDesiredAspectRatio(double aspectRatio) {
|
public void setDesiredAspectRatio(double aspectRatio) {
|
||||||
this.desiredAspectRatio = aspectRatio;
|
this.desiredAspectRatio = aspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInputCallbacks(InputCallbacks callbacks) {
|
||||||
|
this.inputCallbacks = callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
public StreamView(Context context) {
|
public StreamView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
@@ -52,4 +58,30 @@ public class StreamView extends SurfaceView {
|
|||||||
|
|
||||||
setMeasuredDimension(measuredWidth, measuredHeight);
|
setMeasuredDimension(measuredWidth, measuredHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||||
|
// This callbacks allows us to override dumb IME behavior like when
|
||||||
|
// Samsung's default keyboard consumes Shift+Space. We'll process
|
||||||
|
// the input event directly if any modifier keys are down.
|
||||||
|
if (inputCallbacks != null && event.getModifiers() != 0) {
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
if (inputCallbacks.handleKeyDown(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
if (inputCallbacks.handleKeyUp(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onKeyPreIme(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface InputCallbacks {
|
||||||
|
boolean handleKeyUp(KeyEvent event);
|
||||||
|
boolean handleKeyDown(KeyEvent event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
<!-- Portrait orientation only -->
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -110,8 +110,6 @@
|
|||||||
<string name="title_checkbox_stretch_video">Forza video a schermo intero</string>
|
<string name="title_checkbox_stretch_video">Forza video a schermo intero</string>
|
||||||
<string name="title_checkbox_disable_warnings">Disabilita messaggi di warning</string>
|
<string name="title_checkbox_disable_warnings">Disabilita messaggi di warning</string>
|
||||||
<string name="summary_checkbox_disable_warnings">Disabilita i messaggi di warning sullo schermo durante lo streaming</string>
|
<string name="summary_checkbox_disable_warnings">Disabilita i messaggi di warning sullo schermo durante lo streaming</string>
|
||||||
<string name="title_checkbox_battery_saver">Risparmio batteria</string>
|
|
||||||
<string name="summary_checkbox_battery_saver">Usa meno batteria, ma può aumentare lo stuttering</string>
|
|
||||||
<string name="title_checkbox_enable_pip">Abilita modalità spettatore Picture-in-Picture</string>
|
<string name="title_checkbox_enable_pip">Abilita modalità spettatore Picture-in-Picture</string>
|
||||||
<string name="summary_checkbox_enable_pip">Permette di osservare (ma non di controllare) la stream in multitasking</string>
|
<string name="summary_checkbox_enable_pip">Permette di osservare (ma non di controllare) la stream in multitasking</string>
|
||||||
|
|
||||||
|
|||||||
@@ -142,8 +142,6 @@
|
|||||||
<string name="message_decoding_reset">Видео декодер Вашего устройства давал сбои с выбранными настройками. Настройки трансляции были сброшены до значений по умолчанию.</string>
|
<string name="message_decoding_reset">Видео декодер Вашего устройства давал сбои с выбранными настройками. Настройки трансляции были сброшены до значений по умолчанию.</string>
|
||||||
<string name="error_usb_prohibited">USB доступ запрещен администратором устройства. Проверьте настройки Knox или MDM.</string>
|
<string name="error_usb_prohibited">USB доступ запрещен администратором устройства. Проверьте настройки Knox или MDM.</string>
|
||||||
<string name="addpc_wrong_sitelocal">Адрес указан неверно. Вы должны ввести публичный IP-адрес Вашего роутера для передачи через интернет.</string>
|
<string name="addpc_wrong_sitelocal">Адрес указан неверно. Вы должны ввести публичный IP-адрес Вашего роутера для передачи через интернет.</string>
|
||||||
<string name="title_checkbox_battery_saver">Экономия батареи</string>
|
|
||||||
<string name="summary_checkbox_battery_saver">Использует меньше заряда батареи, но может увеличить зависания</string>
|
|
||||||
<string name="title_checkbox_enable_pip">Включить просмотр в режиме \"Картинка в картинке\"</string>
|
<string name="title_checkbox_enable_pip">Включить просмотр в режиме \"Картинка в картинке\"</string>
|
||||||
<string name="summary_checkbox_enable_pip">Позволяет просматривать трансляцию (но не управлять ей) во время работы в других приложениях</string>
|
<string name="summary_checkbox_enable_pip">Позволяет просматривать трансляцию (но не управлять ей) во время работы в других приложениях</string>
|
||||||
<string name="title_checkbox_usb_bind_all">Переопределить поддержку контроллеров Android</string>
|
<string name="title_checkbox_usb_bind_all">Переопределить поддержку контроллеров Android</string>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
Using remote desktop software can also cause this error. Try rebooting your machine or reinstalling GFE.
|
Using remote desktop software can also cause this error. Try rebooting your machine or reinstalling GFE.
|
||||||
</string>
|
</string>
|
||||||
<string name="title_decoding_error">Video Decoder Crashed</string>
|
<string name="title_decoding_error">Video Decoder Crashed</string>
|
||||||
<string name="message_decoding_error">Moonlight has crashed due to a problem with this device\'s video decoder. Try adjusting the streaming settings if the crashes continue.</string>
|
<string name="message_decoding_error">Moonlight has crashed due to an incompatibility with this device\'s video decoder. Ensure GeForce Experience is updated to the latest version on your PC. Try adjusting the streaming settings if the crashes continue.</string>
|
||||||
<string name="title_decoding_reset">Video Settings Reset</string>
|
<string name="title_decoding_reset">Video Settings Reset</string>
|
||||||
<string name="message_decoding_reset">Your device\'s video decoder continues to crash at your selected streaming settings. Your streaming settings have been reset to default.</string>
|
<string name="message_decoding_reset">Your device\'s video decoder continues to crash at your selected streaming settings. Your streaming settings have been reset to default.</string>
|
||||||
<string name="error_usb_prohibited">USB access is prohibited by your device administrator. Check your Knox or MDM settings.</string>
|
<string name="error_usb_prohibited">USB access is prohibited by your device administrator. Check your Knox or MDM settings.</string>
|
||||||
@@ -113,8 +113,6 @@
|
|||||||
<string name="title_checkbox_stretch_video">Stretch video to full-screen</string>
|
<string name="title_checkbox_stretch_video">Stretch video to full-screen</string>
|
||||||
<string name="title_checkbox_disable_warnings">Disable warning messages</string>
|
<string name="title_checkbox_disable_warnings">Disable warning messages</string>
|
||||||
<string name="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
|
<string name="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
|
||||||
<string name="title_checkbox_battery_saver">Battery saver</string>
|
|
||||||
<string name="summary_checkbox_battery_saver">Uses less battery, but may increase stuttering</string>
|
|
||||||
<string name="title_checkbox_enable_pip">Enable Picture-in-Picture observer mode</string>
|
<string name="title_checkbox_enable_pip">Enable Picture-in-Picture observer mode</string>
|
||||||
<string name="summary_checkbox_enable_pip">Allows the stream to be viewed (but not controlled) while multitasking</string>
|
<string name="summary_checkbox_enable_pip">Allows the stream to be viewed (but not controlled) while multitasking</string>
|
||||||
|
|
||||||
@@ -124,7 +122,7 @@
|
|||||||
|
|
||||||
<string name="category_gamepad_settings">Gamepad Settings</string>
|
<string name="category_gamepad_settings">Gamepad Settings</string>
|
||||||
<string name="title_checkbox_multi_controller">Multiple controller support</string>
|
<string name="title_checkbox_multi_controller">Multiple controller support</string>
|
||||||
<string name="summary_checkbox_multi_controller">When unchecked, all controllers appear as one</string>
|
<string name="summary_checkbox_multi_controller">Uncheck for games with controller detection issues</string>
|
||||||
<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>
|
||||||
|
|||||||
@@ -24,11 +24,6 @@
|
|||||||
android:key="checkbox_stretch_video"
|
android:key="checkbox_stretch_video"
|
||||||
android:title="@string/title_checkbox_stretch_video"
|
android:title="@string/title_checkbox_stretch_video"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="checkbox_battery_saver"
|
|
||||||
android:title="@string/title_checkbox_battery_saver"
|
|
||||||
android:summary="@string/summary_checkbox_battery_saver"
|
|
||||||
android:defaultValue="false" />
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="checkbox_enable_pip"
|
android:key="checkbox_enable_pip"
|
||||||
android:title="@string/title_checkbox_enable_pip"
|
android:title="@string/title_checkbox_enable_pip"
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
classpath "com.android.tools:r8:1.0.25"
|
||||||
|
classpath 'com.android.tools.build:gradle:3.2.0-alpha15'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
#Sun Sep 03 12:51:12 PDT 2017
|
#Tue May 08 18:56:31 PDT 2018
|
||||||
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.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module external.linked.project.id="moonlight-android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="java-gradle" name="Java-Gradle">
|
|
||||||
<configuration>
|
|
||||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
|
||||||
<option name="BUILDABLE" value="false" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
+1
-1
Submodule moonlight-common updated: 9ef3a4a6b7...d87f24c617
Reference in New Issue
Block a user