Compare commits

..

17 Commits

Author SHA1 Message Date
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
Cameron Gutman 4ea93f5e68 Version 5.7.4 2018-04-08 21:21:37 -07:00
Cameron Gutman cd84c8f30e Fix grammar issue in decoder crash message 2018-04-08 21:19:49 -07:00
Cameron Gutman 8d4cdca7c3 Fix RFI disabling for KDDI/b5_jp_kdi/b5:7.0/NRD90U/1801120299534:user/release-keys and KDDI/b3_jp_kdi/b3:7.0/NRD90U/180120857f434:user/release-keys 2018-04-08 19:56:01 -07:00
Cameron Gutman c0239c36fd Update language around decoder crashes 2018-03-27 20:52:01 -07:00
Cameron Gutman 9d9f729e42 Address another buggy LGE variant (b5_jp_kdi) 2018-03-27 20:48:16 -07:00
Cameron Gutman 6c5fe18b6e Update Gradle for AS 3.1 2018-03-26 23:30:33 -07:00
Cameron Gutman 1994bf6522 Version 5.7.3.1 for Amazon 2018-03-24 23:48:04 -07:00
Cameron Gutman 31381e5664 Add Amlogic SoC to HEVC whitelist for Fire TV 3 now that maxNumReferenceFrames support has been out for a while 2018-03-24 23:47:05 -07:00
14 changed files with 143 additions and 148 deletions
+2 -2
View File
@@ -7,8 +7,8 @@ android {
minSdkVersion 16
targetSdkVersion 27
versionName "5.7.3"
versionCode = 151
versionName "5.7.5"
versionCode = 154
}
flavorDimensions "root"
+57 -26
View File
@@ -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);
@@ -424,19 +426,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 +817,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 +836,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 +846,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 +867,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 +885,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 +895,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);
@@ -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
@@ -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);
}
}
-2
View File
@@ -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>
-2
View File
@@ -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>
+1 -3
View File
@@ -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>
-5
View File
@@ -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
View File
@@ -5,7 +5,8 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0-rc03'
classpath "com.android.tools:r8:1.0.23"
classpath 'com.android.tools.build:gradle:3.1.1'
}
}