Compare commits

..
22 Commits
Author SHA1 Message Date
Cameron Gutman 35fb96f9f4 Version 5.8 2018-05-27 18:56:03 -07:00
Cameron Gutman 37371906d5 Update common for audio and JNI library size improvements 2018-05-27 18:51:28 -07:00
Cameron Gutman 83a9539f4b Version 5.7.7 2018-05-21 19:24:26 -07:00
Cameron Gutman b214fe5301 Update to AGP 3.2-alpha15 2018-05-21 18:55:36 -07:00
Cameron Gutman 57779b4e89 Always expose gamepad 1 in single controller mode 2018-05-21 18:55:02 -07:00
Cameron Gutman 547932f8b2 Version 5.7.6 2018-05-13 22:23:22 -07:00
Cameron Gutman 762fa0fe2f Tighten ProGuard rules for BC 2018-05-12 21:25:41 -07:00
Cameron Gutman 9cedc57df2 Move the portrait activity_pc_view.xml to the default directory 2018-05-12 18:33:47 -07:00
Cameron Gutman ba81f8096a Allow software decoding in CrOS emulator 2018-05-11 19:28:30 -07:00
Cameron Gutman c4fa654166 Fix split breaking language chooser 2018-05-08 21:24:49 -07:00
Cameron Gutman 8ac440b68b Update AGP for AS 3.2 and app bundles 2018-05-08 21:22:10 -07:00
Cameron Gutman 165386b941 Update AGP and D8 2018-05-08 18:43:49 -07:00
Cameron Gutman 3a7398f321 Use ProGuard for minification 2018-05-08 18:43:23 -07:00
Cameron Gutman ebb1d0dfa2 Version 5.7.5 2018-04-21 23:48:04 -07:00
Cameron Gutman 1ca1ed5d20 Increase OSC analog stick size 2018-04-21 23:46:55 -07:00
Cameron Gutman b416bafb78 Hide OSC in PiP and scale properly in multi-window 2018-04-21 23:37:38 -07:00
Cameron Gutman 3a301b74a6 Update to D8 v1.0.23 2018-04-21 23:17:04 -07:00
Cameron Gutman 71d463f063 Avoid crashing from unexpected enterPictureInPictureMode() exceptions 2018-04-21 21:32:59 -07:00
Cameron Gutman 1fae816223 Remove the spinner threads (and battery saver option to disable them) 2018-04-21 21:29:42 -07:00
Cameron Gutman 989d6fc169 Fix for broken keyboard d-pad and Shift+Space behavior on Samsung devices 2018-04-21 16:24:23 -07:00
Cameron Gutman 381509b3a6 Properly handle joysticks that only return events for one trigger axis 2018-04-21 15:09:57 -07:00
Cameron Gutman d8ae40376e Update to AGP 3.1.1 2018-04-09 20:32:06 -07:00
18 changed files with 192 additions and 156 deletions

No files matched your search

+16 -4
View File
@@ -7,8 +7,8 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 27 targetSdkVersion 27
versionName "5.7.4" versionName "5.8"
versionCode = 153 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'
} }
} }
+27
View File
@@ -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
+61 -28
View File
@@ -40,6 +40,7 @@ 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.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;
@@ -70,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;
@@ -189,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);
@@ -305,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) {
@@ -424,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();
}
} }
} }
} }
@@ -788,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
@@ -802,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);
@@ -816,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));
@@ -837,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
@@ -850,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);
@@ -864,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));
@@ -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,9 +185,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
continue; continue;
} }
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0 && if (hasJoystickAxes(dev)) {
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) != null &&
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) != null) {
LimeLog.info("Counting InputDevice: "+dev.getName()); LimeLog.info("Counting InputDevice: "+dev.getName());
mask |= 1 << count++; mask |= 1 << count++;
} }
@@ -837,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;
} }
} }
@@ -1042,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;
@@ -1162,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;
@@ -1301,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);
@@ -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
@@ -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");
} }
@@ -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,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"
-2
View File
@@ -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>
-2
View File
@@ -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>
+1 -3
View File
@@ -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>
-5
View File
@@ -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
View File
@@ -5,7 +5,8 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' classpath "com.android.tools:r8:1.0.25"
classpath 'com.android.tools.build:gradle:3.2.0-alpha15'
} }
} }
+2 -2
View File
@@ -1,6 +1,6 @@
#Tue Mar 20 18:12:28 PDT 2018 #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.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip