Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b238ab6c3 | |||
| f82ee97c05 | |||
| 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 |
+16
-4
@@ -7,8 +7,8 @@ android {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
|
||||
versionName "5.7.3"
|
||||
versionCode = 151
|
||||
versionName "5.8"
|
||||
versionCode = 162
|
||||
}
|
||||
|
||||
flavorDimensions "root"
|
||||
@@ -45,9 +45,21 @@ android {
|
||||
disable 'MissingTranslation'
|
||||
}
|
||||
|
||||
bundle {
|
||||
language {
|
||||
// Avoid splitting by language, since we allow users
|
||||
// to manually switch language in settings.
|
||||
enableSplit = false
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
|
||||
minifyEnabled true
|
||||
useProguard false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
// To whomever is releasing/using an APK in release mode with
|
||||
@@ -82,8 +94,8 @@ android {
|
||||
// TL;DR: Leave the following line alone!
|
||||
applicationIdSuffix ".unofficial"
|
||||
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt')
|
||||
minifyEnabled true
|
||||
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
|
||||
@@ -40,6 +40,7 @@ import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.input.InputManager;
|
||||
@@ -70,7 +71,7 @@ import android.widget.Toast;
|
||||
|
||||
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||
OnSystemUiVisibilityChangeListener, GameGestures
|
||||
OnSystemUiVisibilityChangeListener, GameGestures, StreamView.InputCallbacks
|
||||
{
|
||||
private int lastMouseX = Integer.MIN_VALUE;
|
||||
private int lastMouseY = Integer.MIN_VALUE;
|
||||
@@ -189,6 +190,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
streamView = findViewById(R.id.surfaceView);
|
||||
streamView.setOnGenericMotionListener(this);
|
||||
streamView.setOnTouchListener(this);
|
||||
streamView.setInputCallbacks(this);
|
||||
|
||||
inputCaptureProvider = InputCaptureManager.getInputCaptureProvider(this, this);
|
||||
|
||||
@@ -305,8 +307,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
int gamepadMask = ControllerHandler.getAttachedControllerMask(this);
|
||||
if (!prefConfig.multiController && gamepadMask != 0) {
|
||||
// If any gamepads are present in non-MC mode, set only gamepad 1.
|
||||
if (!prefConfig.multiController) {
|
||||
// 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;
|
||||
}
|
||||
if (prefConfig.onscreenController) {
|
||||
@@ -424,19 +428,46 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
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
|
||||
public void onUserLeaveHint() {
|
||||
super.onUserLeaveHint();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (prefConfig.enablePip && connected) {
|
||||
enterPictureInPictureMode(
|
||||
new PictureInPictureParams.Builder()
|
||||
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
||||
.setSourceRectHint(new Rect(
|
||||
streamView.getLeft(), streamView.getTop(),
|
||||
streamView.getRight(), streamView.getBottom()))
|
||||
.build());
|
||||
try {
|
||||
// This has thrown all sorts of weird exceptions on Samsung devices
|
||||
// running Oreo. Just eat them and close gracefully on leave, rather
|
||||
// than crashing.
|
||||
enterPictureInPictureMode(
|
||||
new PictureInPictureParams.Builder()
|
||||
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
||||
.setSourceRectHint(new Rect(
|
||||
streamView.getLeft(), streamView.getTop(),
|
||||
streamView.getRight(), streamView.getBottom()))
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -788,9 +819,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
@@ -802,11 +838,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
boolean handled = false;
|
||||
|
||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
||||
if (detectedGamepad || (event.getDevice() == null ||
|
||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
||||
)) {
|
||||
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||
handled = controllerHandler.handleButtonDown(event);
|
||||
@@ -816,17 +848,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Try the keyboard handler
|
||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||
if (translated == 0) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let this method take duplicate key down events
|
||||
if (handleSpecialKeys(keyCode, true)) {
|
||||
if (handleSpecialKeys(event.getKeyCode(), true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass through keyboard input if we're not grabbing
|
||||
if (!grabbedInput) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_DOWN, getModifierState(event));
|
||||
@@ -837,9 +869,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
@@ -850,11 +887,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
boolean handled = false;
|
||||
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
|
||||
(event.getDevice().getSources() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD);
|
||||
if (detectedGamepad || (event.getDevice() == null ||
|
||||
event.getDevice().getKeyboardType() != InputDevice.KEYBOARD_TYPE_ALPHABETIC
|
||||
)) {
|
||||
if (ControllerHandler.isGameControllerDevice(event.getDevice())) {
|
||||
// Always try the controller handler first, unless it's an alphanumeric keyboard device.
|
||||
// Otherwise, controller handler will eat keyboard d-pad events.
|
||||
handled = controllerHandler.handleButtonUp(event);
|
||||
@@ -864,16 +897,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Try the keyboard handler
|
||||
short translated = KeyboardTranslator.translate(event.getKeyCode());
|
||||
if (translated == 0) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (handleSpecialKeys(keyCode, false)) {
|
||||
if (handleSpecialKeys(event.getKeyCode(), false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass through keyboard input if we're not grabbing
|
||||
if (!grabbedInput) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
conn.sendKeyboardInput(translated, KeyboardPacket.KEY_UP, getModifierState(event));
|
||||
|
||||
@@ -149,6 +149,30 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
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) {
|
||||
int count = 0;
|
||||
short mask = 0;
|
||||
@@ -161,9 +185,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0 &&
|
||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) != null &&
|
||||
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) != null) {
|
||||
if (hasJoystickAxes(dev)) {
|
||||
LimeLog.info("Counting InputDevice: "+dev.getName());
|
||||
mask |= 1 << count++;
|
||||
}
|
||||
@@ -837,16 +859,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// to normal behavior, so ignore triggersIdleNegative for each trigger until
|
||||
// first touch.
|
||||
if (lt != 0) {
|
||||
context.leftTriggerUsed = true;
|
||||
context.leftTriggerAxisUsed = true;
|
||||
}
|
||||
if (rt != 0) {
|
||||
context.rightTriggerUsed = true;
|
||||
context.rightTriggerAxisUsed = true;
|
||||
}
|
||||
if (context.triggersIdleNegative) {
|
||||
if (context.leftTriggerUsed) {
|
||||
if (context.leftTriggerAxisUsed) {
|
||||
lt = (lt + 1) / 2;
|
||||
}
|
||||
if (context.rightTriggerUsed) {
|
||||
if (context.rightTriggerAxisUsed) {
|
||||
rt = (rt + 1) / 2;
|
||||
}
|
||||
}
|
||||
@@ -1042,15 +1064,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.inputMap &= ~ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
if (context.leftTriggerAxis >= 0) {
|
||||
// Suppress this digital event if an analog trigger is present
|
||||
if (context.leftTriggerAxisUsed) {
|
||||
// Suppress this digital event if an analog trigger is active
|
||||
return true;
|
||||
}
|
||||
context.leftTrigger = 0;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
if (context.rightTriggerAxis >= 0) {
|
||||
// Suppress this digital event if an analog trigger is present
|
||||
if (context.rightTriggerAxisUsed) {
|
||||
// Suppress this digital event if an analog trigger is active
|
||||
return true;
|
||||
}
|
||||
context.rightTrigger = 0;
|
||||
@@ -1162,15 +1184,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.inputMap |= ControllerPacket.RS_CLK_FLAG;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_L2:
|
||||
if (context.leftTriggerAxis >= 0) {
|
||||
// Suppress this digital event if an analog trigger is present
|
||||
if (context.leftTriggerAxisUsed) {
|
||||
// Suppress this digital event if an analog trigger is active
|
||||
return true;
|
||||
}
|
||||
context.leftTrigger = (byte)0xFF;
|
||||
break;
|
||||
case KeyEvent.KEYCODE_BUTTON_R2:
|
||||
if (context.rightTriggerAxis >= 0) {
|
||||
// Suppress this digital event if an analog trigger is present
|
||||
if (context.rightTriggerAxisUsed) {
|
||||
// Suppress this digital event if an analog trigger is active
|
||||
return true;
|
||||
}
|
||||
context.rightTrigger = (byte)0xFF;
|
||||
@@ -1301,7 +1323,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
public int leftTriggerAxis = -1;
|
||||
public int rightTriggerAxis = -1;
|
||||
public boolean triggersIdleNegative;
|
||||
public boolean leftTriggerUsed, rightTriggerUsed;
|
||||
public boolean leftTriggerAxisUsed, rightTriggerAxisUsed;
|
||||
|
||||
public int hatXAxis = -1;
|
||||
public int hatYAxis = -1;
|
||||
|
||||
@@ -210,7 +210,7 @@ public class AnalogStick extends VirtualControllerElement {
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
// 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_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() {
|
||||
for (VirtualControllerElement element : elements) {
|
||||
relative_layout.removeView(element);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.limelight.binding.video;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jcodec.codecs.h264.H264Utils;
|
||||
@@ -41,7 +40,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
|
||||
private MediaCodec videoDecoder;
|
||||
private Thread rendererThread;
|
||||
private Thread[] spinnerThreads;
|
||||
private boolean needsSpsBitstreamFixup, isExynos4;
|
||||
private boolean adaptivePlayback, directSubmit;
|
||||
private boolean constrainedHighProfile;
|
||||
@@ -132,14 +130,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
this.consecutiveCrashCount = consecutiveCrashCount;
|
||||
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();
|
||||
if (avcDecoder != null) {
|
||||
LimeLog.info("Selected AVC decoder: "+avcDecoder.getName());
|
||||
@@ -217,15 +207,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
}
|
||||
|
||||
public void notifyVideoForeground() {
|
||||
startSpinnerThreads();
|
||||
foreground = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -462,73 +447,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
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() {
|
||||
int index = -1;
|
||||
long startTime;
|
||||
@@ -570,7 +488,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
@Override
|
||||
public void start() {
|
||||
startRendererThread();
|
||||
startSpinnerThreads();
|
||||
}
|
||||
|
||||
// !!! May be called even if setup()/start() fails !!!
|
||||
@@ -593,9 +510,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
||||
try {
|
||||
rendererThread.join();
|
||||
} catch (InterruptedException ignored) { }
|
||||
|
||||
// Halt the spinner threads
|
||||
stopSpinnerThreads();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -71,8 +71,8 @@ public class MediaCodecHelper {
|
||||
blacklistedDecoderPrefixes = new LinkedList<>();
|
||||
|
||||
// Blacklist software decoders that don't support H264 high profile,
|
||||
// but exclude the official AOSP emulator from this restriction.
|
||||
if (!Build.HARDWARE.equals("ranchu") || !Build.BRAND.equals("google")) {
|
||||
// but exclude the official AOSP and CrOS emulator from this restriction.
|
||||
if (!Build.HARDWARE.equals("ranchu") && !Build.HARDWARE.equals("cheets")) {
|
||||
blacklistedDecoderPrefixes.add("omx.google");
|
||||
blacklistedDecoderPrefixes.add("AVCDecoder");
|
||||
}
|
||||
@@ -135,6 +135,7 @@ public class MediaCodecHelper {
|
||||
// to actually be tested. Ugh...
|
||||
if (Build.MANUFACTURER.equalsIgnoreCase("Amazon")) {
|
||||
whitelistedHevcDecoders.add("omx.mtk");
|
||||
whitelistedHevcDecoders.add("omx.amlogic");
|
||||
}
|
||||
|
||||
// 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
|
||||
// RFI to see if we can get that under control.
|
||||
if (Build.BRAND.toLowerCase().equals("lge") && Build.PRODUCT.toLowerCase().startsWith("b3_")) {
|
||||
if (Build.DEVICE.equals("b3") || Build.DEVICE.equals("b5")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ public class PreferenceConfiguration {
|
||||
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 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 ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
|
||||
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 onscreenController;
|
||||
public boolean onlyL3R3;
|
||||
public boolean batterySaver;
|
||||
public boolean disableFrameDrop;
|
||||
public boolean enableHdr;
|
||||
public boolean enablePip;
|
||||
@@ -244,7 +242,6 @@ public class PreferenceConfiguration {
|
||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||
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.batterySaver = prefs.getBoolean(BATTERY_SAVER_PREF_STRING, DEFAULT_BATTERY_SAVER);
|
||||
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.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
||||
|
||||
@@ -3,15 +3,21 @@ package com.limelight.ui;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public class StreamView extends SurfaceView {
|
||||
private double desiredAspectRatio;
|
||||
private InputCallbacks inputCallbacks;
|
||||
|
||||
public void setDesiredAspectRatio(double aspectRatio) {
|
||||
this.desiredAspectRatio = aspectRatio;
|
||||
}
|
||||
|
||||
public void setInputCallbacks(InputCallbacks callbacks) {
|
||||
this.inputCallbacks = callbacks;
|
||||
}
|
||||
|
||||
public StreamView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@@ -52,4 +58,30 @@ public class StreamView extends SurfaceView {
|
||||
|
||||
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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
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_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="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="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="error_usb_prohibited">USB доступ запрещен администратором устройства. Проверьте настройки Knox или MDM.</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="summary_checkbox_enable_pip">Позволяет просматривать трансляцию (но не управлять ей) во время работы в других приложениях</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.
|
||||
</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="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>
|
||||
@@ -113,8 +113,6 @@
|
||||
<string name="title_checkbox_stretch_video">Stretch video to full-screen</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="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="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="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="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string>
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
android:key="checkbox_stretch_video"
|
||||
android:title="@string/title_checkbox_stretch_video"
|
||||
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
|
||||
android:key="checkbox_enable_pip"
|
||||
android:title="@string/title_checkbox_enable_pip"
|
||||
|
||||
+2
-1
@@ -5,7 +5,8 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.0-rc03'
|
||||
classpath "com.android.tools:r8:1.0.25"
|
||||
classpath 'com.android.tools.build:gradle:3.2.0-alpha15'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Tue Mar 20 18:12:28 PDT 2018
|
||||
#Tue May 08 18:56:31 PDT 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
|
||||
+1
-1
Submodule moonlight-common updated: 7f95544a0d...f605589454
Reference in New Issue
Block a user