Compare commits

..

38 Commits

Author SHA1 Message Date
Cameron Gutman fac1b1d7e5 Version 5.7.3 2018-03-24 13:05:31 -07:00
Cameron Gutman 40c406051c Ignore non-relative MotionEvents on Oreo to fix mouse jumping when toggling capture 2018-03-20 20:21:21 -07:00
Cameron Gutman 8bac873e67 Make sure the joystick actually has relevant axes to avoid FPing on some weird keyboards 2018-03-20 19:47:33 -07:00
Cameron Gutman a170e1efd7 Update to Gradle 4.5 2018-03-20 19:21:02 -07:00
Cameron Gutman 17bffa8d78 Fix race condition between polling return and onPause() 2018-03-20 19:10:04 -07:00
Cameron Gutman 289222749b Cover another broken G Pad III 8.0 FHD variant (b3_open_kr) 2018-03-20 18:54:48 -07:00
Cameron Gutman 81d84600d4 Start connection in onSurfaceChanged() just in case we render our first frame prior to surface configuration 2018-03-20 18:37:31 -07:00
Cameron Gutman 0b15fd582d Update gitignore and delete iml file 2018-03-20 18:06:02 -07:00
Cameron Gutman cbe4a1cde6 Update Gradle for AS 3.1 RC3 2018-03-20 18:02:34 -07:00
Cameron Gutman 89ef16c02e Fix level_idc 31 patch 2018-03-18 00:59:58 -07:00
Cameron Gutman 58b6ed8d00 Update Gradle wrapper 2018-03-11 18:12:01 -07:00
Cameron Gutman 7d01e1a7a4 Fix landscape orientation lock 2018-03-11 15:31:10 -07:00
Cameron Gutman ab769a1606 Version 5.7.2 2018-03-07 18:53:38 -08:00
Nikita Glazkov 3ac9abbab1 Russian translation (#546)
* Fix russian translation

* Complete russian translation
2018-03-07 18:44:33 -08:00
Marco 288efd0726 Added new strings (#542) 2018-03-07 18:43:33 -08:00
Nikita Glazkov d2d0ed65d6 Different app label for debug builds (#545)
* Different app label for debug builds

* Remove underscores from app labels
2018-03-07 18:41:34 -08:00
Cameron Gutman e697ed72db Add missing <network-security-config> tag 2018-03-07 18:17:00 -08:00
Cameron Gutman b657c746be Pass the BouncyCastle provider directly rather than by name, since the latter doesn't work on Android P (at least DP1) 2018-03-07 17:56:50 -08:00
Cameron Gutman 947f8db2d5 Update for Android Studio 3.1 2018-03-07 17:55:49 -08:00
Cameron Gutman 15857efd36 Add network security config allowing plaintext for Android P 2018-03-07 11:47:19 -08:00
Cameron Gutman 3fd0f20e10 Version 5.7.1 2018-03-01 22:18:32 -08:00
Cameron Gutman a2e64fd7df Fix crash when running Dutch language. Fixes #543 2018-03-01 22:09:49 -08:00
Cameron Gutman a620dc7d0c Version 5.7 2018-02-25 13:41:09 -08:00
Cameron Gutman 9d7a28e408 Implement deletion of OSC settings 2018-02-25 13:33:52 -08:00
Cameron Gutman 3244344fc7 Add preference dependencies for USB and OSC 2018-02-25 13:12:37 -08:00
Cameron Gutman 75057f2d39 Persist OSC configuration between launches 2018-02-25 13:07:07 -08:00
Cameron Gutman bbec3402d9 Reduce opacity of OSC configuration button 2018-02-25 12:18:45 -08:00
Cameron Gutman dcf4dac8dd Only add L3/R3 buttons for the L3/R3-only config, since the analog sticks work for this 2018-02-25 12:17:59 -08:00
Cameron Gutman d98f484aaf Change OSC configuration button to work better on rounded screen devices 2018-02-25 12:12:23 -08:00
Cameron Gutman 0218a9ce14 Small string update 2018-02-24 21:07:18 -08:00
Cameron Gutman 0ec6dcd67e Add 360p option and change bitrate to kbps 2018-02-24 21:05:45 -08:00
Cameron Gutman 88f9b68db7 Add mouse emulation and bind all USB devices options 2018-02-24 20:17:14 -08:00
Cameron Gutman 3c2fd32d1e Improve error reporting for incorrect IP address 2018-02-24 19:36:23 -08:00
Cameron Gutman 6557cba307 Add support for scrolling with d-pad in mouse emulation mode 2018-02-24 18:57:09 -08:00
Cameron Gutman ae6f797436 Handle right-clicks that are synthesized into back button presses 2018-02-19 17:29:18 -08:00
Cameron Gutman 3442a64f4d Update common to fix audio dropouts. Fixes #523 2018-02-19 01:21:13 -08:00
Cameron Gutman 37ddccde0c Version 5.6.7 2018-02-14 18:39:04 -08:00
Cameron Gutman ffc59c6bd6 Update moonlight-common to fix pairing timeout issue 2018-02-14 18:34:45 -08:00
45 changed files with 634 additions and 257 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ Thumbs.db
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
build/
app/app.iml
*.iml
# Compiled JNI libraries folder
**/jniLibs
+2 -6
View File
@@ -1,18 +1,14 @@
import com.android.builder.model.ProductFlavor
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 27
versionName "5.6.6"
versionCode = 146
versionName "5.7.3"
versionCode = 151
}
flavorDimensions "root"
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_label" translatable="false">Moonlight (Debug)</string>
<string name="app_label_root" translatable="false">Moonlight (Root Debug)</string>
</resources>
+3 -1
View File
@@ -32,6 +32,7 @@
<application
android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:isGame="true"
android:banner="@drawable/atv_banner"
android:appCategory="game"
@@ -98,10 +99,11 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="com.limelight.PcView" />
</activity>
<!-- This will fall back to sensorLandscape at runtime on Android 4.2 and below -->
<activity
android:name=".Game"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:screenOrientation="sensorLandscape"
android:screenOrientation="userLandscape"
android:noHistory="true"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
@@ -69,6 +69,13 @@ public class AppViewShortcutTrampoline extends Activity {
blockingLoadSpinner = null;
}
// If the managerBinder was destroyed before this callback,
// just finish the activity.
if (managerBinder == null) {
finish();
return;
}
if (details.state == ComputerDetails.State.ONLINE) {
// Close this activity
finish();
+53 -13
View File
@@ -39,6 +39,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.input.InputManager;
@@ -95,6 +96,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private boolean displayedFailureDialog = false;
private boolean connecting = false;
private boolean connected = false;
private boolean surfaceCreated = false;
private boolean attemptedConnection = false;
private InputCaptureProvider inputCaptureProvider;
private int modifierFlags = 0;
@@ -158,6 +161,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
}
// We specified userLandscape in the manifest which isn't supported until 4.3,
// so we must fall back at runtime to sensorLandscape.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
// Listen for UI visibility events
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
@@ -350,7 +359,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
.setResolution(prefConfig.width, prefConfig.height)
.setRefreshRate(prefConfig.fps)
.setApp(new NvApp(appName, appId, willStreamHdr))
.setBitrate(prefConfig.bitrate * 1000)
.setBitrate(prefConfig.bitrate)
.setEnableSops(prefConfig.enableSops)
.enableLocalAudioPlayback(prefConfig.playHostAudio)
.setMaxPacketSize((remote || prefConfig.width <= 1920) ? 1024 : 1292)
@@ -367,7 +376,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Initialize the connection
conn = new NvConnection(host, uniqueId, config, PlatformBinding.getCryptoProvider(this));
controllerHandler = new ControllerHandler(this, conn, this, prefConfig.multiController, prefConfig.deadzonePercentage);
controllerHandler = new ControllerHandler(this, conn, this, prefConfig);
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(controllerHandler, null);
@@ -784,6 +793,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return super.onKeyDown(keyCode, event);
}
// Handle a synthetic back button event that some Android OS versions
// create as a result of a right-click.
if (event.getSource() == InputDevice.SOURCE_MOUSE && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
return true;
}
boolean handled = false;
boolean detectedGamepad = event.getDevice() != null && ((event.getDevice().getSources() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK ||
@@ -826,6 +842,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return super.onKeyUp(keyCode, event);
}
// Handle a synthetic back button event that some Android OS versions
// create as a result of a right-click.
if (event.getSource() == InputDevice.SOURCE_MOUSE && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
return true;
}
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);
@@ -947,6 +970,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
lastMouseX = (int)event.getX();
lastMouseY = (int)event.getY();
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// We get a normal (non-relative) MotionEvent when starting pointer capture to synchronize the
// location of the cursor with our app. We don't want this, so we must discard this event.
lastMouseX = (int)event.getX();
lastMouseY = (int)event.getY();
}
else {
// First process the history
for (int i = 0; i < event.getHistorySize(); i++) {
@@ -1179,8 +1208,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
spinner = null;
}
connecting = false;
connected = true;
connecting = false;
runOnUiThread(new Runnable() {
@Override
@@ -1219,12 +1248,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
if (!surfaceCreated) {
throw new IllegalStateException("Surface changed before creation!");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!connected && !connecting) {
connecting = true;
if (!attemptedConnection) {
attemptedConnection = true;
decoderRenderer.setRenderTarget(holder);
conn.start(PlatformBinding.getAudioRenderer(), decoderRenderer, Game.this);
@@ -1232,12 +1261,23 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Let the decoder know immediately that the surface is gone
decoderRenderer.prepareForStop();
public void surfaceCreated(SurfaceHolder holder) {
surfaceCreated = true;
}
if (connected) {
stopConnection();
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (!surfaceCreated) {
throw new IllegalStateException("Surface destroyed before creation!");
}
if (attemptedConnection) {
// Let the decoder know immediately that the surface is gone
decoderRenderer.prepareForStop();
if (connected) {
stopConnection();
}
}
}
@@ -13,8 +13,8 @@ import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -54,10 +54,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
private static final Object globalCryptoLock = new Object();
static {
// Install the Bouncy Castle provider
Security.addProvider(new BouncyCastleProvider());
}
private static final Provider bcProvider = new BouncyCastleProvider();
public AndroidCryptoProvider(Context c) {
String dataPath = c.getFilesDir().getAbsolutePath();
@@ -96,10 +93,10 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
}
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC");
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", bcProvider);
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
pemCertBytes = certBytes;
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
key = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
} catch (CertificateException e) {
// May happen if the cert is corrupt
@@ -113,10 +110,6 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
// May happen if the key is corrupt
LimeLog.warning("Corrupted key");
return false;
} catch (NoSuchProviderException e) {
// Should never happen
e.printStackTrace();
return false;
}
return true;
@@ -129,17 +122,13 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", bcProvider);
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e1) {
// Should never happen
e1.printStackTrace();
return false;
} catch (NoSuchProviderException e) {
// Should never happen
e.printStackTrace();
return false;
}
Date now = new Date();
@@ -160,8 +149,8 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
try {
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BouncyCastleProvider.PROVIDER_NAME).build(keyPair.getPrivate());
cert = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate(certBuilder.build(sigGen));
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
key = (RSAPrivateKey) keyPair.getPrivate();
} catch (Exception e) {
// Nothing should go wrong here
@@ -18,6 +18,7 @@ import com.limelight.binding.input.driver.UsbDriverService;
import com.limelight.nvstream.NvConnection;
import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.nvstream.input.MouseButtonPacket;
import com.limelight.preferences.PreferenceConfiguration;
import com.limelight.ui.GameGestures;
import com.limelight.utils.Vector2d;
@@ -50,18 +51,18 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
private final GameGestures gestures;
private boolean hasGameController;
private final boolean multiControllerEnabled;
private final PreferenceConfiguration prefConfig;
private short currentControllers, initialControllers;
public ControllerHandler(Context activityContext, NvConnection conn, GameGestures gestures, boolean multiControllerEnabled, int deadzonePercentage) {
public ControllerHandler(Context activityContext, NvConnection conn, GameGestures gestures, PreferenceConfiguration prefConfig) {
this.activityContext = activityContext;
this.conn = conn;
this.gestures = gestures;
this.multiControllerEnabled = multiControllerEnabled;
this.prefConfig = prefConfig;
// HACK: For now we're hardcoding a 10% deadzone. Some deadzone
// is required for controller batching support to work.
deadzonePercentage = 10;
int deadzonePercentage = 10;
int[] ids = InputDevice.getDeviceIds();
for (int id : ids) {
@@ -160,18 +161,24 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
continue;
}
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0) {
if ((dev.getSources() & InputDevice.SOURCE_JOYSTICK) != 0 &&
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_X) != null &&
getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_Y) != null) {
LimeLog.info("Counting InputDevice: "+dev.getName());
mask |= 1 << count++;
}
}
// Count all USB devices that match our drivers
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (UsbDevice dev : usbManager.getDeviceList().values()) {
if (UsbDriverService.shouldClaimDevice(dev)) {
LimeLog.info("Counting UsbDevice: "+dev.getDeviceName());
mask |= 1 << count++;
if (PreferenceConfiguration.readPreferences(context).usbDriver) {
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (UsbDevice dev : usbManager.getDeviceList().values()) {
// We explicitly ask not to claim devices that appear as InputDevices
// otherwise we will double count them.
if (UsbDriverService.shouldClaimDevice(dev, false)) {
LimeLog.info("Counting UsbDevice: "+dev.getDeviceName());
mask |= 1 << count++;
}
}
}
@@ -215,7 +222,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
LimeLog.info("Built-in buttons hardcoded as controller 0");
context.controllerNumber = 0;
}
else if (multiControllerEnabled && devContext.hasJoystickAxes) {
else if (prefConfig.multiController && devContext.hasJoystickAxes) {
context.controllerNumber = 0;
LimeLog.info("Reserving the next available controller number");
@@ -239,7 +246,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
}
else {
if (multiControllerEnabled) {
if (prefConfig.multiController) {
context.controllerNumber = 0;
LimeLog.info("Reserving the next available controller number");
@@ -522,7 +529,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
}
private short getActiveControllerMask() {
if (multiControllerEnabled) {
if (prefConfig.multiController) {
return (short)(currentControllers | initialControllers);
}
else {
@@ -609,6 +616,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
}
}
if ((changedMask & ControllerPacket.UP_FLAG) != 0) {
if ((inputMap & ControllerPacket.UP_FLAG) != 0) {
conn.sendMouseScroll((byte) 1);
}
}
if ((changedMask & ControllerPacket.DOWN_FLAG) != 0) {
if ((inputMap & ControllerPacket.DOWN_FLAG) != 0) {
conn.sendMouseScroll((byte) -1);
}
}
conn.sendControllerInput(controllerNumber, getActiveControllerMask(),
(short)0, (byte)0, (byte)0, (short)0, (short)0, (short)0, (short)0);
@@ -975,7 +992,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
// Make sure it's real by checking that the key is actually down before taking
// any action.
if ((context.inputMap & ControllerPacket.PLAY_FLAG) != 0 &&
SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS) {
SystemClock.uptimeMillis() - context.startDownTime > ControllerHandler.START_DOWN_TIME_MOUSE_MODE_MS &&
prefConfig.mouseEmulation) {
toggleMouseEmulation(context);
}
context.inputMap &= ~ControllerPacket.PLAY_FLAG;
@@ -18,6 +18,7 @@ import android.widget.Toast;
import com.limelight.LimeLog;
import com.limelight.R;
import com.limelight.preferences.PreferenceConfiguration;
import java.util.ArrayList;
@@ -27,6 +28,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
"com.limelight.USB_PERMISSION";
private UsbManager usbManager;
private PreferenceConfiguration prefConfig;
private final UsbEventReceiver receiver = new UsbEventReceiver();
private final UsbDriverBinder binder = new UsbDriverBinder();
@@ -119,7 +121,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
private void handleUsbDeviceState(UsbDevice device) {
// Are we able to operate it?
if (shouldClaimDevice(device)) {
if (shouldClaimDevice(device, prefConfig.bindAllUsb)) {
// Do we have permission yet?
if (!usbManager.hasPermission(device)) {
// Let's ask for permission
@@ -194,16 +196,17 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
}
public static boolean shouldClaimDevice(UsbDevice device) {
public static boolean shouldClaimDevice(UsbDevice device, boolean claimAllAvailable) {
// We always bind to XB1 controllers but only bind to XB360 controllers
// if we know the kernel isn't already driving this device.
return XboxOneController.canClaimDevice(device) ||
(!isRecognizedInputDevice(device) && Xbox360Controller.canClaimDevice(device));
((!isRecognizedInputDevice(device) || claimAllAvailable) && Xbox360Controller.canClaimDevice(device));
}
@Override
public void onCreate() {
this.usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
this.prefConfig = PreferenceConfiguration.readPreferences(this);
// Register for USB attach broadcasts and permission completions
IntentFilter filter = new IntentFilter();
@@ -213,7 +216,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
// Enumerate existing devices
for (UsbDevice dev : usbManager.getDeviceList().values()) {
if (shouldClaimDevice(dev)) {
if (shouldClaimDevice(dev, prefConfig.bindAllUsb)) {
// Start the process of claiming this device
handleUsbDeviceState(dev);
}
@@ -164,8 +164,8 @@ public class AnalogStick extends VirtualControllerElement {
}
}
public AnalogStick(VirtualController controller, Context context) {
super(controller, context);
public AnalogStick(VirtualController controller, Context context, int elementId) {
super(controller, context, elementId);
// reset stick position
position_stick_x = getWidth() / 2;
position_stick_y = getHeight() / 2;
@@ -120,8 +120,8 @@ public class DigitalButton extends VirtualControllerElement {
}
}
public DigitalButton(VirtualController controller, int layer, Context context) {
super(controller, context);
public DigitalButton(VirtualController controller, int elementId, int layer, Context context) {
super(controller, context, elementId);
this.layer = layer;
}
@@ -27,7 +27,7 @@ public class DigitalPad extends VirtualControllerElement {
private final Paint paint = new Paint();
public DigitalPad(VirtualController controller, Context context) {
super(controller, context);
super(controller, context, EID_DPAD);
}
public void addDigitalPadListener(DigitalPadListener listener) {
@@ -10,7 +10,7 @@ import com.limelight.nvstream.input.ControllerPacket;
public class LeftAnalogStick extends AnalogStick {
public LeftAnalogStick(final VirtualController controller, final Context context) {
super(controller, context);
super(controller, context, EID_LS);
addAnalogStickListener(new AnalogStick.AnalogStickListener() {
@Override
@@ -8,7 +8,7 @@ import android.content.Context;
public class LeftTrigger extends DigitalButton {
public LeftTrigger(final VirtualController controller, final int layer, final Context context) {
super(controller, layer, context);
super(controller, EID_LT, layer, context);
addDigitalButtonListener(new DigitalButton.DigitalButtonListener() {
@Override
public void onClick() {
@@ -10,7 +10,7 @@ import com.limelight.nvstream.input.ControllerPacket;
public class RightAnalogStick extends AnalogStick {
public RightAnalogStick(final VirtualController controller, final Context context) {
super(controller, context);
super(controller, context, EID_RS);
addAnalogStickListener(new AnalogStick.AnalogStickListener() {
@Override
@@ -8,7 +8,7 @@ import android.content.Context;
public class RightTrigger extends DigitalButton {
public RightTrigger(final VirtualController controller, final int layer, final Context context) {
super(controller, layer, context);
super(controller, EID_RT, layer, context);
addDigitalButtonListener(new DigitalButton.DigitalButtonListener() {
@Override
public void onClick() {
@@ -45,7 +45,6 @@ public class VirtualController {
ControllerMode currentMode = ControllerMode.Active;
ControllerInputContext inputContext = new ControllerInputContext();
private RelativeLayout.LayoutParams layoutParamsButtonConfigure = null;
private Button buttonConfigure = null;
private List<VirtualControllerElement> elements = new ArrayList<>();
@@ -60,6 +59,7 @@ public class VirtualController {
frame_layout.addView(relative_layout);
buttonConfigure = new Button(context);
buttonConfigure.setAlpha(0.25f);
buttonConfigure.setBackgroundResource(R.drawable.ic_settings);
buttonConfigure.setOnClickListener(new View.OnClickListener() {
@Override
@@ -68,6 +68,7 @@ public class VirtualController {
if (currentMode == ControllerMode.Configuration) {
currentMode = ControllerMode.Active;
VirtualControllerConfigurationLoader.saveProfile(VirtualController.this, context);
message = "Exiting configuration mode";
} else {
currentMode = ControllerMode.Configuration;
@@ -116,11 +117,19 @@ public class VirtualController {
DisplayMetrics screen = context.getResources().getDisplayMetrics();
int buttonSize = (int)(screen.heightPixels*0.05f);
layoutParamsButtonConfigure = new RelativeLayout.LayoutParams(buttonSize, buttonSize);
relative_layout.addView(buttonConfigure, layoutParamsButtonConfigure);
int buttonSize = (int)(screen.heightPixels*0.06f);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(buttonSize, buttonSize);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
params.leftMargin = 15;
params.topMargin = 15;
relative_layout.addView(buttonConfigure, params);
// Start with the default layout
VirtualControllerConfigurationLoader.createDefaultLayout(this, context);
// Apply user preferences onto the default layout
VirtualControllerConfigurationLoader.loadFromPreferences(this, context);
}
public ControllerMode getControllerMode() {
@@ -4,14 +4,19 @@
package com.limelight.binding.input.virtual_controller;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.DisplayMetrics;
import com.limelight.nvstream.input.ControllerPacket;
import com.limelight.preferences.PreferenceConfiguration;
import org.json.JSONException;
import org.json.JSONObject;
public class VirtualControllerConfigurationLoader {
private static final String PROFILE_PATH = "profiles";
public static final String OSC_PREFERENCE = "OSC";
private static int getPercent(
int percent,
@@ -59,6 +64,7 @@ public class VirtualControllerConfigurationLoader {
}
private static DigitalButton createDigitalButton(
final int elementId,
final int keyShort,
final int keyLong,
final int layer,
@@ -66,7 +72,7 @@ public class VirtualControllerConfigurationLoader {
final int icon,
final VirtualController controller,
final Context context) {
DigitalButton button = new DigitalButton(controller, layer, context);
DigitalButton button = new DigitalButton(controller, elementId, layer, context);
button.setText(text);
button.setIcon(icon);
@@ -162,6 +168,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_A,
ControllerPacket.A_FLAG, 0, 1, "A", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels) + getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels),
@@ -170,6 +177,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_B,
ControllerPacket.B_FLAG, 0, 1, "B", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels) + 2 * getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels) + getPercent(BUTTON_HEIGHT, screen.heightPixels),
@@ -178,6 +186,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_X,
ControllerPacket.X_FLAG, 0, 1, "X", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels) + getPercent(BUTTON_HEIGHT, screen.heightPixels),
@@ -186,6 +195,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_Y,
ControllerPacket.Y_FLAG, 0, 1, "Y", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels) + getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels),
@@ -210,6 +220,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_LB,
ControllerPacket.LB_FLAG, 0, 1, "LB", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels),
@@ -218,6 +229,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_RB,
ControllerPacket.RB_FLAG, 0, 1, "RB", -1, controller, context),
getPercent(BUTTON_BASE_X, screen.widthPixels) + 2 * getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_BASE_Y, screen.heightPixels) + 2 * getPercent(BUTTON_HEIGHT, screen.heightPixels),
@@ -240,6 +252,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_BACK,
ControllerPacket.BACK_FLAG, 0, 2, "BACK", -1, controller, context),
getPercent(40, screen.widthPixels),
getPercent(90, screen.heightPixels),
@@ -248,6 +261,7 @@ public class VirtualControllerConfigurationLoader {
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_START,
ControllerPacket.PLAY_FLAG, 0, 3, "START", -1, controller, context),
getPercent(40, screen.widthPixels) + getPercent(10, screen.widthPixels),
getPercent(90, screen.heightPixels),
@@ -255,52 +269,60 @@ public class VirtualControllerConfigurationLoader {
getPercent(10, screen.heightPixels)
);
}
else {
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_LSB,
ControllerPacket.LS_CLK_FLAG, 0, 1, "L3", -1, controller, context),
getPercent(2, screen.widthPixels),
getPercent(80, screen.heightPixels),
getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_HEIGHT, screen.heightPixels)
);
controller.addElement(createDigitalButton(
ControllerPacket.LS_CLK_FLAG, 0, 1, "L3", -1, controller, context),
getPercent(2, screen.widthPixels),
getPercent(80, screen.heightPixels),
getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_HEIGHT, screen.heightPixels)
);
controller.addElement(createDigitalButton(
ControllerPacket.RS_CLK_FLAG, 0, 1, "R3", -1, controller, context),
getPercent(89, screen.widthPixels),
getPercent(80, screen.heightPixels),
getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_HEIGHT, screen.heightPixels)
);
controller.addElement(createDigitalButton(
VirtualControllerElement.EID_RSB,
ControllerPacket.RS_CLK_FLAG, 0, 1, "R3", -1, controller, context),
getPercent(89, screen.widthPixels),
getPercent(80, screen.heightPixels),
getPercent(BUTTON_WIDTH, screen.widthPixels),
getPercent(BUTTON_HEIGHT, screen.heightPixels)
);
}
}
/*
NOT IMPLEMENTED YET,
this should later be used to store and load a profile for the virtual controller
public static void saveProfile(final String name,
final VirtualController controller,
public static void saveProfile(final VirtualController controller,
final Context context) {
SharedPreferences.Editor prefEditor = context.getSharedPreferences(OSC_PREFERENCE, Activity.MODE_PRIVATE).edit();
SharedPreferences preferences = context.getSharedPreferences(PROFILE_PATH + "/" +
name, Activity.MODE_PRIVATE);
JSONArray elementConfigurations = new JSONArray();
for (VirtualControllerElement element : controller.getElements()) {
JSONObject elementConfiguration = new JSONObject();
String prefKey = ""+element.elementId;
try {
elementConfiguration.put("TYPE", element.getClass().getName());
elementConfiguration.put("CONFIGURATION", element.getConfiguration());
elementConfigurations.put(elementConfiguration);
} catch (Exception e) {
prefEditor.putString(prefKey, element.getConfiguration().toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
SharedPreferences.Editor editor= preferences.edit();
editor.putString("ELEMENTS", elementConfigurations.toString());
prefEditor.apply();
}
public static void loadFromPreferences(final VirtualController controller) {
public static void loadFromPreferences(final VirtualController controller, final Context context) {
SharedPreferences pref = context.getSharedPreferences(OSC_PREFERENCE, Activity.MODE_PRIVATE);
for (VirtualControllerElement element : controller.getElements()) {
String prefKey = ""+element.elementId;
String jsonConfig = pref.getString(prefKey, null);
if (jsonConfig != null) {
try {
element.loadConfiguration(new JSONObject(jsonConfig));
} catch (JSONException e) {
e.printStackTrace();
// Remove the corrupt element from the preferences
pref.edit().remove(prefKey).apply();
}
}
}
}
*/
}
@@ -14,10 +14,30 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import org.json.JSONException;
import org.json.JSONObject;
public abstract class VirtualControllerElement extends View {
protected static boolean _PRINT_DEBUG_INFORMATION = false;
public static final int EID_DPAD = 1;
public static final int EID_LT = 2;
public static final int EID_RT = 3;
public static final int EID_LB = 4;
public static final int EID_RB = 5;
public static final int EID_A = 6;
public static final int EID_B = 7;
public static final int EID_X = 8;
public static final int EID_Y = 9;
public static final int EID_BACK = 10;
public static final int EID_START = 11;
public static final int EID_LS = 12;
public static final int EID_RS = 13;
public static final int EID_LSB = 14;
public static final int EID_RSB = 15;
protected VirtualController virtualController;
protected final int elementId;
private final Paint paint = new Paint();
@@ -40,10 +60,11 @@ public abstract class VirtualControllerElement extends View {
private Mode currentMode = Mode.Normal;
protected VirtualControllerElement(VirtualController controller, Context context) {
protected VirtualControllerElement(VirtualController controller, Context context, int elementId) {
super(context);
this.virtualController = controller;
this.elementId = elementId;
}
protected void moveElement(int pressed_x, int pressed_y, int x, int y) {
@@ -278,13 +299,28 @@ public abstract class VirtualControllerElement extends View {
return getWidth() > getHeight() ? getHeight() : getWidth();
}
/**
public JSONObject getConfiguration () {
JSONObject configuration = new JSONObject();
return configuration;
}
public void loadConfiguration (JSONObject configuration) {
}
*/
public JSONObject getConfiguration() throws JSONException {
JSONObject configuration = new JSONObject();
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
configuration.put("LEFT", layoutParams.leftMargin);
configuration.put("TOP", layoutParams.topMargin);
configuration.put("WIDTH", layoutParams.width);
configuration.put("HEIGHT", layoutParams.height);
return configuration;
}
public void loadConfiguration(JSONObject configuration) throws JSONException {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = configuration.getInt("LEFT");
layoutParams.topMargin = configuration.getInt("TOP");
layoutParams.width = configuration.getInt("WIDTH");
layoutParams.height = configuration.getInt("HEIGHT");
requestLayout();
}
}
@@ -713,12 +713,17 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
// for known resolution combinations. Reference frame invalidation may need
// these, so leave them be for those decoders.
if (!refFrameInvalidationActive) {
if (initialWidth == 1280 && initialHeight == 720) {
if (initialWidth <= 720 && initialHeight <= 480) {
// Max 5 buffered frames at 720x480x60
LimeLog.info("Patching level_idc to 31");
sps.levelIdc = 31;
}
else if (initialWidth <= 1280 && initialHeight <= 720) {
// Max 5 buffered frames at 1280x720x60
LimeLog.info("Patching level_idc to 32");
sps.levelIdc = 32;
}
else if (initialWidth == 1920 && initialHeight == 1080) {
else if (initialWidth <= 1920 && initialHeight <= 1080) {
// Max 4 buffered frames at 1920x1080x64
LimeLog.info("Patching level_idc to 42");
sps.levelIdc = 42;
@@ -1053,7 +1058,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
str += "RFI active: "+renderer.refFrameInvalidationActive+"\n";
str += "Video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n";
str += "FPS target: "+renderer.refreshRate+"\n";
str += "Bitrate: "+renderer.prefs.bitrate+" Mbps \n";
str += "Bitrate: "+renderer.prefs.bitrate+" Kbps \n";
str += "In stats: "+renderer.numVpsIn+", "+renderer.numSpsIn+", "+renderer.numPpsIn+"\n";
str += "Total frames received: "+renderer.totalFramesReceived+"\n";
str += "Total frames rendered: "+renderer.totalFramesRendered+"\n";
@@ -336,7 +336,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.PRODUCT.equalsIgnoreCase("b3_att_us")) {
if (Build.BRAND.toLowerCase().equals("lge") && Build.PRODUCT.toLowerCase().startsWith("b3_")) {
return false;
}
@@ -1,5 +1,12 @@
package com.limelight.preferences;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.concurrent.LinkedBlockingQueue;
import com.limelight.computers.ComputerManagerService;
@@ -39,36 +46,84 @@ public class AddComputerManually extends Activity {
}
};
private boolean isWrongSubnetSiteLocalAddress(String address) {
try {
InetAddress targetAddress = InetAddress.getByName(address);
if (!(targetAddress instanceof Inet4Address) || !targetAddress.isSiteLocalAddress()) {
return false;
}
// We have a site-local address. Look for a matching local interface.
for (NetworkInterface iface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
for (InterfaceAddress addr : iface.getInterfaceAddresses()) {
if (!(addr.getAddress() instanceof Inet4Address) || !addr.getAddress().isSiteLocalAddress()) {
// Skip non-site-local or non-IPv4 addresses
continue;
}
byte[] targetAddrBytes = targetAddress.getAddress();
byte[] ifaceAddrBytes = addr.getAddress().getAddress();
// Compare prefix to ensure it's the same
boolean addressMatches = true;
for (int i = 0; i < addr.getNetworkPrefixLength(); i++) {
if ((ifaceAddrBytes[i / 8] & (1 << (i % 8))) != (targetAddrBytes[i / 8] & (1 << (i % 8)))) {
addressMatches = false;
break;
}
}
if (addressMatches) {
return false;
}
}
}
// Couldn't find a matching interface
return true;
} catch (SocketException e) {
e.printStackTrace();
return false;
} catch (UnknownHostException e) {
return false;
}
}
private void doAddPc(String host) {
String msg;
boolean finish = false;
boolean wrongSiteLocal = false;
boolean success;
SpinnerDialog dialog = SpinnerDialog.displayDialog(this, getResources().getString(R.string.title_add_pc),
getResources().getString(R.string.msg_add_pc), false);
if (!managerBinder.addComputerBlocking(host, true)){
msg = getResources().getString(R.string.addpc_fail);
}
else {
msg = getResources().getString(R.string.addpc_success);
finish = true;
success = managerBinder.addComputerBlocking(host, true);
if (!success){
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
}
dialog.dismiss();
final boolean toastFinish = finish;
final String toastMsg = msg;
AddComputerManually.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(AddComputerManually.this, toastMsg, Toast.LENGTH_LONG).show();
if (wrongSiteLocal) {
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
}
else if (!success) {
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_fail), false);
}
else {
AddComputerManually.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(AddComputerManually.this, getResources().getString(R.string.addpc_success), Toast.LENGTH_LONG).show();
if (toastFinish && !isFinishing()) {
if (!isFinishing()) {
// Close the activity
AddComputerManually.this.finish();
}
}
});
}
});
}
}
private void startAddThread() {
@@ -0,0 +1,41 @@
package com.limelight.preferences;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.widget.Toast;
import com.limelight.R;
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
public class ConfirmDeleteOscPreference extends DialogPreference {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context) {
super(context);
}
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
getContext().getSharedPreferences(OSC_PREFERENCE, Context.MODE_PRIVATE).edit().clear().apply();
Toast.makeText(getContext(), R.string.toast_reset_osc_success, Toast.LENGTH_SHORT).show();
}
}
}
@@ -8,7 +8,8 @@ import android.preference.PreferenceManager;
public class PreferenceConfiguration {
static final String RES_FPS_PREF_STRING = "list_resolution_fps";
static final String BITRATE_PREF_STRING = "seekbar_bitrate";
static final String BITRATE_PREF_STRING = "seekbar_bitrate_kbps";
private static final String BITRATE_PREF_OLD_STRING = "seekbar_bitrate";
private static final String STRETCH_PREF_STRING = "checkbox_stretch_video";
private static final String SOPS_PREF_STRING = "checkbox_enable_sops";
private static final String DISABLE_TOASTS_PREF_STRING = "checkbox_disable_warnings";
@@ -27,13 +28,17 @@ public class PreferenceConfiguration {
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";
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
private static final int BITRATE_DEFAULT_720_30 = 5;
private static final int BITRATE_DEFAULT_720_60 = 10;
private static final int BITRATE_DEFAULT_1080_30 = 10;
private static final int BITRATE_DEFAULT_1080_60 = 20;
private static final int BITRATE_DEFAULT_4K_30 = 40;
private static final int BITRATE_DEFAULT_4K_60 = 80;
private static final int BITRATE_DEFAULT_360_30 = 1000;
private static final int BITRATE_DEFAULT_360_60 = 2000;
private static final int BITRATE_DEFAULT_720_30 = 5000;
private static final int BITRATE_DEFAULT_720_60 = 10000;
private static final int BITRATE_DEFAULT_1080_30 = 10000;
private static final int BITRATE_DEFAULT_1080_60 = 20000;
private static final int BITRATE_DEFAULT_4K_30 = 40000;
private static final int BITRATE_DEFAULT_4K_60 = 80000;
private static final String DEFAULT_RES_FPS = "720p60";
private static final int DEFAULT_BITRATE = BITRATE_DEFAULT_720_60;
@@ -54,6 +59,8 @@ public class PreferenceConfiguration {
private static final boolean DEFAULT_DISABLE_FRAME_DROP = false;
private static final boolean DEFAULT_ENABLE_HDR = false;
private static final boolean DEFAULT_ENABLE_PIP = false;
private static final boolean DEFAULT_BIND_ALL_USB = false;
private static final boolean DEFAULT_MOUSE_EMULATION = true;
public static final int FORCE_H265_ON = -1;
public static final int AUTOSELECT_H265 = 0;
@@ -72,9 +79,17 @@ public class PreferenceConfiguration {
public boolean disableFrameDrop;
public boolean enableHdr;
public boolean enablePip;
public boolean bindAllUsb;
public boolean mouseEmulation;
public static int getDefaultBitrate(String resFpsString) {
if (resFpsString.equals("720p30")) {
if (resFpsString.equals("360p30")) {
return BITRATE_DEFAULT_360_30;
}
else if (resFpsString.equals("360p60")) {
return BITRATE_DEFAULT_360_60;
}
else if (resFpsString.equals("720p30")) {
return BITRATE_DEFAULT_720_30;
}
else if (resFpsString.equals("720p60")) {
@@ -147,6 +162,7 @@ public class PreferenceConfiguration {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit()
.remove(BITRATE_PREF_STRING)
.remove(BITRATE_PREF_OLD_STRING)
.remove(RES_FPS_PREF_STRING)
.remove(VIDEO_FORMAT_PREF_STRING)
.remove(ENABLE_HDR_PREF_STRING)
@@ -157,9 +173,23 @@ public class PreferenceConfiguration {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
PreferenceConfiguration config = new PreferenceConfiguration();
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, getDefaultBitrate(context));
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
if (config.bitrate == 0) {
config.bitrate = getDefaultBitrate(context);
}
String str = prefs.getString(RES_FPS_PREF_STRING, DEFAULT_RES_FPS);
if (str.equals("720p30")) {
if (str.equals("360p30")) {
config.width = 640;
config.height = 360;
config.fps = 30;
}
else if (str.equals("360p60")) {
config.width = 640;
config.height = 360;
config.fps = 60;
}
else if (str.equals("720p30")) {
config.width = 1280;
config.height = 720;
config.fps = 30;
@@ -218,6 +248,8 @@ public class PreferenceConfiguration {
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);
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
return config;
}
@@ -16,7 +16,8 @@ import android.widget.TextView;
// Based on a Stack Overflow example: http://stackoverflow.com/questions/1974193/slider-on-my-preferencescreen
public class SeekBarPreference extends DialogPreference
{
private static final String SCHEMA_URL = "http://schemas.android.com/apk/res/android";
private static final String ANDROID_SCHEMA_URL = "http://schemas.android.com/apk/res/android";
private static final String SEEKBAR_SCHEMA_URL = "http://schemas.moonlight-stream.com/apk/res/seekbar";
private SeekBar seekBar;
private TextView valueText;
@@ -27,6 +28,7 @@ public class SeekBarPreference extends DialogPreference
private final int defaultValue;
private final int maxValue;
private final int minValue;
private final int stepSize;
private int currentValue;
public SeekBarPreference(Context context, AttributeSet attrs) {
@@ -34,27 +36,28 @@ public class SeekBarPreference extends DialogPreference
this.context = context;
// Read the message from XML
int dialogMessageId = attrs.getAttributeResourceValue(SCHEMA_URL, "dialogMessage", 0);
int dialogMessageId = attrs.getAttributeResourceValue(ANDROID_SCHEMA_URL, "dialogMessage", 0);
if (dialogMessageId == 0) {
dialogMessage = attrs.getAttributeValue(SCHEMA_URL, "dialogMessage");
dialogMessage = attrs.getAttributeValue(ANDROID_SCHEMA_URL, "dialogMessage");
}
else {
dialogMessage = context.getString(dialogMessageId);
}
// Get the suffix for the number displayed in the dialog
int suffixId = attrs.getAttributeResourceValue(SCHEMA_URL, "text", 0);
int suffixId = attrs.getAttributeResourceValue(ANDROID_SCHEMA_URL, "text", 0);
if (suffixId == 0) {
suffix = attrs.getAttributeValue(SCHEMA_URL, "text");
suffix = attrs.getAttributeValue(ANDROID_SCHEMA_URL, "text");
}
else {
suffix = context.getString(suffixId);
}
// Get default, min, and max seekbar values
defaultValue = attrs.getAttributeIntValue(SCHEMA_URL, "defaultValue", PreferenceConfiguration.getDefaultBitrate(context));
maxValue = attrs.getAttributeIntValue(SCHEMA_URL, "max", 100);
minValue = 1;
defaultValue = attrs.getAttributeIntValue(ANDROID_SCHEMA_URL, "defaultValue", PreferenceConfiguration.getDefaultBitrate(context));
maxValue = attrs.getAttributeIntValue(ANDROID_SCHEMA_URL, "max", 100);
minValue = attrs.getAttributeIntValue(SEEKBAR_SCHEMA_URL, "min", 1);
stepSize = attrs.getAttributeIntValue(SEEKBAR_SCHEMA_URL, "step", 1);
}
@Override
@@ -89,6 +92,12 @@ public class SeekBarPreference extends DialogPreference
return;
}
int roundedValue = ((value + (stepSize - 1))/stepSize)*stepSize;
if (roundedValue != value) {
seekBar.setProgress(roundedValue);
return;
}
String t = String.valueOf(value);
valueText.setText(suffix == null ? t : t.concat(suffix.length() > 1 ? " "+suffix : suffix));
}
+1 -1
View File
@@ -89,7 +89,7 @@
<string name="summary_resolution_list">Establecer unos valores demasiado altos puede causar lag o cierres inesperados</string>
<string name="title_seekbar_bitrate">Seleccionar bitrate de vídeo</string>
<string name="summary_seekbar_bitrate">Usa bitrate bajo para reducir "parpadeo". Incrementa el bitrate para mayor calidad de imagen.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">Ajustar vídeo a pantalla completa</string>
<string name="title_checkbox_disable_warnings">Desactivar mensajes de advertencia</string>
<string name="summary_checkbox_disable_warnings">Desactivar mensajes de advertencia en pantalla durante la transmisión</string>
+1 -1
View File
@@ -100,7 +100,7 @@
<string name="summary_resolution_list">Le réglage de valeurs trop élevées pour votre appareil peut provoquer un retard ou un plantage</string>
<string name="title_seekbar_bitrate">Sélectionnez le bitrate vidéo à obtenir</string>
<string name="summary_seekbar_bitrate">Bitrate inférieur pour réduire la saccade. Augmentez le bitrate pour augmenter la qualité de l\'image.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">Étirez la vidéo en plein écran</string>
<string name="title_checkbox_disable_warnings">Désactiver les messages d\'avertissement</string>
<string name="summary_checkbox_disable_warnings">Désactiver les messages d\'avertissement de connexion à l\'écran pendant le streaming</string>
+80 -31
View File
@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Shortcut strings -->
<string name="scut_deleted_pc">PC eliminato</string>
<string name="scut_not_paired">PC non accoppiato</string>
<!-- Help strings -->
<string name="help_loading_title">Visualizza assistenza</string>
<string name="help_loading_msg">Caricamento pagina di assistenza…</string>
<!-- PC view menu entries -->
<string name="pcview_menu_app_list">Lista applicazioni</string>
<string name="pcview_menu_pair_pc">Accoppia PC</string>
@@ -10,21 +17,22 @@
<!-- Pair messages -->
<string name="pairing">Accoppiamento…</string>
<string name="pair_pc_offline">PC offline</string>
<string name="pair_pc_offline">Il PC è offline</string>
<string name="pair_pc_ingame">PC con applicazione avviata. Devi chiudere l\'applicazione prima dell\'accoppiamento.</string>
<string name="pair_pairing_title">Accoppiamento</string>
<string name="pair_pairing_msg">Inserisci il seguente PIN sul PC:</string>
<string name="pair_incorrect_pin">PIN non corretto</string>
<string name="pair_fail">Accoppiamento fallito</string>
<string name="pair_already_in_progress">Accoppiamento già in corso</string>
<!-- WOL messages -->
<string name="wol_pc_online">PC già avviato</string>
<string name="wol_no_mac">Impossibile risvegliare il PC perchè GFE non ha inviato nessun indirizzo MAC</string>
<string name="wol_no_mac">Impossibile risvegliare il PC perché GFE non ha inviato nessun indirizzo MAC</string>
<string name="wol_waking_pc">Risveglio PC…</string>
<string name="wol_waking_msg">Il PC potrebbe impiegare qualche secondo per risvegliarsi.
Se non succede niente, assicurati che l\'opzione Wake-On-LAN sia configurata correttamente.
Se non succede niente, assicurati che l\'opzione Wake-On-LAN sia configurata correttamente.
</string>
<string name="wol_fail">Invio pacchetto Wake-On-LAN fallito</string>
<string name="wol_fail">Invio pacchetti Wake-On-LAN fallito</string>
<!-- Unpair messages -->
<string name="unpairing">Disaccoppiamento…</string>
@@ -37,33 +45,41 @@
<string name="error_manager_not_running">Il servizio ComputerManager non è avviato. Attendi qualche secondo o riavvia l\'applicazione.</string>
<string name="error_unknown_host">Risoluzione nome host fallita</string>
<string name="error_404">GFE ha ritornato un errore HTTP 404 error. Assicurati che il PC stia usando una GPU supportata.
Usare un software di remote-desktop può causare questo errore. Prova a riavviare il PC o a reinstallare GFE.
Usare un software di desktop remoto può causare questo errore. Prova a riavviare il PC o a reinstallare GFE.
</string>
<string name="title_decoding_error">Il decodificatore video ha smesso di funzionare</string>
<string name="message_decoding_error">Moonlight ha smesso di funzionare per colpa di un problema al decodificatore video di questo dispositivo. Prova a modificare le impostazioni di stream se il problema persiste.</string>
<string name="title_decoding_reset">Ripristino impostazioni video</string>
<string name="message_decoding_reset">Il decodificatore video del dispositivo continua a funzionare in modo anomalo con le impostazioni di streaming selezionate. Le impostazioni di streaming sono state ripristinate ai valori predefiniti.</string>
<string name="error_usb_prohibited">L\'accesso USB è vietato dall\'amministratore del dispositivo. Verifica le impostazioni Knox o MDM.</string>
<!-- Start application messages -->
<string name="conn_establishing_title">Connessione</string>
<string name="conn_establishing_msg">Connessione in corso</string>
<string name="conn_establishing_title">Connessione in corso</string>
<string name="conn_establishing_msg">Avvio connessione</string>
<string name="conn_metered">Attenzione: la rete attiva prevede costi aggiuntivi in base all\'utilizzo!</string>
<string name="conn_client_latency">Latenza frame media client-side:</string>
<string name="conn_client_latency_hw">latenza decoder hardware:</string>
<string name="conn_hardware_latency">Latenza decoder hardware media:</string>
<string name="conn_client_latency">Latenza decodifica fotogrammi media:</string>
<string name="conn_client_latency_hw">latenza decodificatore hardware:</string>
<string name="conn_hardware_latency">Latenza decodificatore hardware media:</string>
<string name="conn_starting">Avvio in corso…</string>
<string name="conn_error_title">Errore connessione</string>
<string name="conn_error_msg">Avvio fallito</string>
<string name="conn_terminated_title">Connessione terminata</string>
<string name="conn_terminated_title">Connessione interrotta</string>
<string name="conn_terminated_msg">La connessione è stata interrotta</string>
<!-- General strings -->
<string name="ip_hint">Indirizzo IP del PC</string>
<string name="searching_pc">Ricerca PC in corso…</string>
<string name="searching_pc">Ricerca di PC con GameStream avviato…\n\n
Assicurati che GameStream sia abilitato nelle impostazioni SHIELD di GeForce Experience.</string>
<string name="yes"></string>
<string name="no">No</string>
<string name="lost_connection">Connessione con il PC persa</string>
<string name="help">Assistenza</string>
<!-- AppList activity -->
<string name="title_applist">Applicazioni su</string>
<string name="applist_menu_resume">Riprendi Sessione</string>
<string name="applist_menu_quit">Chiudi Sessione</string>
<string name="applist_connect_msg">Connessione al PC in corso…</string>
<string name="applist_menu_resume">Riprendi sessione</string>
<string name="applist_menu_quit">Chiudi sessione</string>
<string name="applist_menu_quit_and_start">Chiudi sessione corrente e avvia</string>
<string name="applist_menu_cancel">Annulla</string>
<string name="applist_refresh_title">Lista applicazioni</string>
@@ -76,43 +92,76 @@
<string name="applist_quit_confirmation">Sei sicuro di voler chiudere l\'applicazione avviata? Tutti i dati non salvati saranno persi.</string>
<!-- Add computer manually activity -->
<string name="title_add_pc">Aggiungi PC Manualmente</string>
<string name="title_add_pc">Aggiungi PC manualmente</string>
<string name="msg_add_pc">Connessione al PC in corso…</string>
<string name="addpc_fail">Impossibile connettersi al PC. Assicurati che il firewall del PC sia configurato correttamente.</string>
<string name="addpc_fail">Impossibile connettersi al PC specificato. Assicurati che le porte nel firewall del PC siano configurate correttamente.</string>
<string name="addpc_success">PC aggiunto con successo</string>
<string name="addpc_unknown_host">Impossibile risovere l\'indirizzo del PC. Assicurati di aver scritto correttamente l\'indirizzo.</string>
<string name="addpc_enter_ip">Devi inserire un indirizzo IP</string>
<string name="addpc_wrong_sitelocal">Quell\'indirizzo non sembra corretto. È necessario utilizzare l\'indirizzo IP pubblico del router per lo streaming su Internet.</string>
<!-- Preferences -->
<string name="category_basic_settings">Impostazioni Base</string>
<string name="category_basic_settings">Impostazioni generali</string>
<string name="title_resolution_list">Risoluzione e FPS</string>
<string name="summary_resolution_list">Valori troppo elevati possono causare lag o crash</string>
<string name="title_seekbar_bitrate">Bitrate video</string>
<string name="summary_seekbar_bitrate">Abbassa il bitrate per ridurre lo stuttering; alza il bitrate per aumenteare la qualità dell\'immagine</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="title_checkbox_stretch_video">Forza video in full-screen</string>
<string name="title_seekbar_bitrate">Velocità di trasmissione video</string>
<string name="summary_seekbar_bitrate">Abbassa la velocità di trasmissione per ridurre lo stuttering; alzala per migliorare la qualità dell\'immagine</string>
<string name="suffix_seekbar_bitrate">Kbps</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="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>
<string name="category_gamepad_settings">Impostazioni Gamepad</string>
<string name="title_checkbox_multi_controller">Supporto controller multipli</string>
<string name="summary_checkbox_multi_controller">Quando disabilitato, tutti i controllers appaiono come uno solo</string>
<string name="title_seekbar_deadzone">Aggiusta deadzone degli stick analogici</string>
<string name="category_audio_settings">Impostazioni audio</string>
<string name="title_checkbox_51_surround">Abilita l\'audio 5.1 surround</string>
<string name="summary_checkbox_51_surround">Se riscontri problemi, disabilitalo. Richiede GFE 2.7 o versioni sucessive.</string>
<string name="category_gamepad_settings">Impostazioni controller</string>
<string name="title_checkbox_multi_controller">Supporto a più controller</string>
<string name="summary_checkbox_multi_controller">Quando disabilitato, tutti i controller appaiono come uno solo</string>
<string name="title_seekbar_deadzone">Regola i punti morti degli stick analogici</string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Driver del controller Xbox 360/One</string>
<string name="summary_checkbox_xb1_driver">Abilita un driver USB integrato per dispositivi senza supporto al controller Xbox nativo</string>
<string name="title_checkbox_usb_bind_all">Sovrascrivi il supporto ai controller su Android</string>
<string name="summary_checkbox_usb_bind_all">Forza i driver USB di Moonlight di assumere il controllo su tutti i controller Xbox supportati</string>
<string name="title_checkbox_mouse_emulation">Emulazione del mouse tramite controller</string>
<string name="summary_checkbox_mouse_emulation">Tenendo premuto il pulsante Start, il controller passerà alla modalità mouse</string>
<string name="category_on_screen_controls_settings">Impostazioni dei controlli a schermo</string>
<string name="title_checkbox_show_onscreen_controls">Mostra controlli a schermo</string>
<string name="summary_checkbox_show_onscreen_controls">Mostra l\'overlay virtuale del controller su schermo</string>
<string name="title_only_l3r3">Mostra solo L3 e R3</string>
<string name="summary_only_l3r3">Nasconde tutti i pulsanti virtuali tranne L3 e R3</string>
<string name="title_reset_osc">Ripristina il layout personalizzato dei controlli a schermo</string>
<string name="summary_reset_osc">Ripristina tutti i controlli a schermo nelle loro posizioni e dimensioni predefinite</string>
<string name="dialog_title_reset_osc">Ripristino del layout</string>
<string name="dialog_text_reset_osc">Sei sicuro di voler ripristinare ai valori predefiniti i layout dei controlli a schermo?</string>
<string name="toast_reset_osc_success">I controlli a schermo sono stati ripristinati</string>
<string name="category_ui_settings">Impostazioni Interfaccia</string>
<string name="category_ui_settings">Impostazioni dell\'interfaccia</string>
<string name="title_language_list">Lingua</string>
<string name="summary_language_list">Lingua da usare in Moonlight</string>
<string name="title_checkbox_list_mode">Usa lista invece della griglia</string>
<string name="summary_checkbox_list_mode">Visualizza applicazioni e computers in una lista invece di una griglia</string>
<string name="summary_checkbox_list_mode">Visualizza le applicazioni e i PC in una lista invece di una griglia</string>
<string name="title_checkbox_small_icon_mode">Usa icone piccole</string>
<string name="summary_checkbox_small_icon_mode">Usa icone piccole nella vista a griglia per avere più oggetti sullo schermo</string>
<string name="summary_checkbox_small_icon_mode">Usa icone piccole nella griglia per avere più oggetti a schermo</string>
<string name="category_host_settings">Impostazioni Host</string>
<string name="category_host_settings">Impostazioni del PC host</string>
<string name="title_checkbox_enable_sops">Ottimizza le impostazioni dei giochi</string>
<string name="summary_checkbox_enable_sops">Permetti a GFE di modificare le impostazioni dei giochi per uno streaming ottimale</string>
<string name="title_checkbox_host_audio">Riproduci audio sul PC</string>
<string name="summary_checkbox_host_audio">Riproduci l\'audio sul computer e su questo dispositivo</string>
<string name="summary_checkbox_host_audio">Riproduce l\'audio sul PC e su questo dispositivo</string>
<string name="category_advanced_settings">Impostazioni Avanzate</string>
<string name="category_advanced_settings">Impostazioni avanzate</string>
<string name="title_disable_frame_drop">Non saltare i fotogrammi</string>
<string name="summary_disable_frame_drop">Potrebbe ridurre il micro-stuttering su alcuni dispositivi, ma può aumentare la latenza</string>
<string name="title_video_format">Modifica impostazioni H.265</string>
<string name="summary_video_format">H.265 riduce i requisiti di larghezza di banda video ma richiede un dispositivo molto recente</string>
<string name="title_enable_hdr">Abilita HDR (sperimentale)</string>
<string name="summary_enable_hdr">Utilizza l\'HDR quando il gioco e la scheda video del PC lo supportano. L\'HDR richiede una scheda video serie GTX 1000 o sucessive.</string>
</resources>
+1 -1
View File
@@ -85,7 +85,7 @@
<string name="summary_resolution_list">品質が高いほどラグとクラッシュが発生しやすくなります</string>
<string name="title_seekbar_bitrate">映像のビットレート</string>
<string name="summary_seekbar_bitrate">ビットレートを低くすればカクつきが抑制され、高くすれば画質が向上します</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">映像を全画面に拡大</string>
<string name="title_checkbox_disable_warnings">警告を無効化</string>
<string name="summary_checkbox_disable_warnings">ストリーミング中に画面に警告メッセージを表示しない</string>
+1 -1
View File
@@ -100,7 +100,7 @@
<string name="summary_resolution_list">세팅 값이 자신의 PC 성능보다 너무 높으면 렉이나 깨짐을 유발할 수 있습니다.</string>
<string name="title_seekbar_bitrate">비트레이트 타겟 지정</string>
<string name="summary_seekbar_bitrate">낮은 비트레이트는 끊김을 줄이고, 높은 비트레이트는 품질을 높입니다.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">전체 화면으로 렌더링 스크린 늘이기</string>
<string name="title_checkbox_disable_warnings">경고 메세지 끄기</string>
<string name="summary_checkbox_disable_warnings">화면 상의 연결 경고 메세지를 스트리밍 중에 비활성화합니다.</string>
-9
View File
@@ -1,14 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="resolution_names">
<item>720p 30 FPS</item>
<item>720p 60 FPS</item>
<item>1080p 30 FPS</item>
<item>1080p 60 FPS</item>
<item>4K 30 FPS</item>
<item>4K 60 FPS</item>
</string-array>
<string-array name="decoder_names">
<item>Selecteer Decoder Automatisch</item>
<item>Forceer Software Decoderen</item>
+1 -1
View File
@@ -89,7 +89,7 @@
<string name="summary_resolution_list">Te hoge instellingen kunnen crashes en haperingen veroorzaken.</string>
<string name="title_seekbar_bitrate">Selecteer doel video bitsnelheid</string>
<string name="summary_seekbar_bitrate">Verlaag bitsnelheid om haperingen te verminderen. Verhoog de bitsnelheid voor een betere videokwaliteit.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">Rek video uit tot volledig scherm</string>
<string name="title_checkbox_disable_warnings">Verberg waarschuwingsberichten</string>
<string name="summary_checkbox_disable_warnings">Verberg on-screen verbindingswaarschuwingen tijdens het streamen</string>
+62 -26
View File
@@ -28,7 +28,7 @@
<!-- Unpair messages -->
<string name="unpairing">Разрыв пары…</string>
<string name="unpair_success">Разрыв пары закончился успешно.</string>
<string name="unpair_success">Разрыв пары закончился успешно</string>
<string name="unpair_fail">Разрыв пары не удался</string>
<string name="unpair_error">Устройство не было спарено</string>
@@ -36,14 +36,14 @@
<string name="error_pc_offline">Компьютер выключен или находится не в сети</string>
<string name="error_manager_not_running">Сервис ComputerManager не запущен. Пожалуйста, подождите несколько секунд или перезапустите приложение.</string>
<string name="error_unknown_host">Не удалось найти хост</string>
<string name="error_404">GFE вернул ошибку HTTP 404. Убедитесь что ваш PC is испольщует поддерживаемый GPU.
Использование программ для удалённого доступа также можнт вызывать эту ошибку. Попробуйте перезагрузить компьютер или переустановить GFE.
<string name="error_404">GFE вернул ошибку HTTP 404. Убедитесь что Ваш PC использует поддерживаемый GPU.
Использование программ для удалённого доступа также может вызывать эту ошибку. Попробуйте перезагрузить компьютер или переустановить GFE.
</string>
<!-- Start application messages -->
<string name="conn_establishing_title">Создание соединения.</string>
<string name="conn_establishing_title">Создание соединения</string>
<string name="conn_establishing_msg">Подключение</string>
<string name="conn_metered">Внимание: Происходит измерение вашего сетевого соединения!</string>
<string name="conn_metered">Внимание: Происходит измерение Вашего сетевого соединения!</string>
<string name="conn_client_latency">Средняя задержка декодирования кадра: </string>
<string name="conn_client_latency_hw">задержка аппаратного декодирования:</string>
<string name="conn_hardware_latency">Средняя задержка апаратного декодирования:</string>
@@ -54,8 +54,9 @@
<string name="conn_terminated_msg">Подключение было прервано</string>
<!-- General strings -->
<string name="ip_hint">IP адресс компьютера с GeForce</string>
<string name="searching_pc">Поиск компьютеров</string>
<string name="ip_hint">IP-адрес компьютера с GeForce</string>
<string name="searching_pc">Поиск компьютеров с запущенным GameStream…\n\n
Убедитесь что GameStream включен в настройках GeForce Experience в разделе SHIELD.</string>
<string name="yes">Да</string>
<string name="no">Нет</string>
<string name="lost_connection">Потеряно соединение с PC</string>
@@ -79,49 +80,84 @@
<string name="title_add_pc">Добавление PC вручную</string>
<string name="msg_add_pc">Соединение с PC…</string>
<string name="addpc_fail">Не удалось подключиться к выбранному компьютеру. Удостоверьтесь, что необходимые порты разрешены в настройках брандмауэра.</string>
<string name="addpc_success">Компьютер добавлен успешно.</string>
<string name="addpc_unknown_host">Не удалось найти PC по указанному адресу. Убедитесь, что вы не совершили ошибок во время его написания.</string>
<string name="addpc_success">Компьютер добавлен успешно</string>
<string name="addpc_unknown_host">Не удалось найти PC по указанному адресу. Убедитесь, что Вы не совершили ошибок во время его написания.</string>
<string name="addpc_enter_ip">Вы должны ввести IP адрес</string>
<!-- Preferences -->
<string name="category_basic_settings">Базовые Настройки</string>
<string name="title_resolution_list">Выберите разрешение и частоту кадров.</string>
<string name="summary_resolution_list">Выбор слишком высокого значеня для своего устройства может вызвать тормоза или вылеты.</string>
<string name="title_seekbar_bitrate">Выберите битрейт видео.</string>
<string name="category_basic_settings">Общие Настройки</string>
<string name="title_resolution_list">Выберите разрешение и частоту кадров</string>
<string name="summary_resolution_list">Выбор слишком высокого значеня для своего устройства может вызвать тормоза или вылеты</string>
<string name="title_seekbar_bitrate">Выберите битрейт видео</string>
<string name="summary_seekbar_bitrate">Низкий битрейт уменьшит зависания. Увеличение битрейта улучшит качество изображения.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video">Растягивать видео на весь экран</string>
<string name="title_checkbox_disable_warnings">Отключить сообщения с предупреждениями</string>
<string name="summary_checkbox_disable_warnings">Выключить экранные предупреждения о соединении во время стрима.</string>
<string name="summary_checkbox_disable_warnings">Выключить экранные предупреждения о соединении во время трансляции</string>
<string name="category_audio_settings">Аудио Настройки</string>
<string name="title_checkbox_51_surround">Включить объёмный звук 5.1</string>
<string name="summary_checkbox_51_surround">Отключите, если появляются аудио проблемы. Требуется GFE 2.7 или выше.</string>
<string name="category_gamepad_settings">Настройки Гемпада</string>
<string name="category_gamepad_settings">Настройки Геймпада</string>
<string name="title_checkbox_multi_controller">Поддержка нескольких контроллеров</string>
<string name="summary_checkbox_multi_controller">Когда отключена, все контроллеры определяются как один. </string>
<string name="title_seekbar_deadzone">Регулировать мертвую зону аналогового стика.</string>
<string name="summary_checkbox_multi_controller">Когда отключена, все контроллеры определяются как один</string>
<string name="title_seekbar_deadzone">Регулировать мертвую зону аналогового стика</string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Драйвер контроллера от Xbox One</string>
<string name="summary_checkbox_xb1_driver">Включить встроенный USB драйвер для устройств без встроенной поддержки контроллера от Xbox One.</string>
<string name="title_checkbox_xb1_driver">Драйвер контроллеров Xbox 360/One</string>
<string name="summary_checkbox_xb1_driver">Включить встроенный USB драйвер для устройств без собственной поддержки контроллеров Xbox</string>
<string name="category_ui_settings">Настройки Интерфейса</string>
<string name="title_language_list">Язык</string>
<string name="summary_language_list">Язык, который будет использоваться в Moonlight</string>
<string name="title_checkbox_list_mode">Использовать списки вместо сеток.</string>
<string name="summary_checkbox_list_mode">Выводить приложения и компьютеры списком, вместо использования сетки.</string>
<string name="title_checkbox_list_mode">Использовать списки вместо сеток</string>
<string name="summary_checkbox_list_mode">Выводить приложения и компьютеры списком, вместо использования сетки</string>
<string name="title_checkbox_small_icon_mode">Использовать маленькие иконки</string>
<string name="summary_checkbox_small_icon_mode">Использовать маленькие иконки в сетки для увеличения числа элементов, отображаемых на экране.</string>
<string name="summary_checkbox_small_icon_mode">Использовать маленькие иконки в сетке для отображения большего числа элементов на экране</string>
<string name="category_host_settings">Настройки Хоста</string>
<string name="title_checkbox_enable_sops">Оптимизировать игровые настройки</string>
<string name="summary_checkbox_enable_sops">Разрешить GFE изменять настройки игр для оптимальной потоковой передачи</string>
<string name="summary_checkbox_enable_sops">Разрешить GFE изменять настройки игр для оптимальной трансляции</string>
<string name="title_checkbox_host_audio">Проигрывать звук на PC</string>
<string name="summary_checkbox_host_audio">Проигрывать звук на компьютере и текущем устройстве.</string>
<string name="summary_checkbox_host_audio">Проигрывать звук на компьютере и текущем устройстве</string>
<string name="category_advanced_settings">Расширенные Настройки</string>
<string name="title_video_format">Изменить настройки H.265</string>
<string name="summary_video_format">H.265 снижает требования к пропускной способности, но требует очень свежих устройств.</string>
<string name="summary_video_format">H.265 снижает требования к пропускной способности, но требует очень нового устройства</string>
<string name="category_on_screen_controls_settings">Настройки Экранных Кнопок</string>
<string name="title_checkbox_show_onscreen_controls">Показывать экранные кнопки</string>
<string name="summary_checkbox_show_onscreen_controls">Отображать оверлей виртуального контроллера на сенсорном экране</string>
<string name="title_only_l3r3">Показывать только L3 и R3</string>
<string name="summary_only_l3r3">Скрывать все экранные кнопки кроме L3 и R3</string>
<string name="scut_deleted_pc">PC удален</string>
<string name="scut_not_paired">PC не сопряжен</string>
<string name="help_loading_title">Просмотр Помощи</string>
<string name="help_loading_msg">Загрузка страницы помощи…</string>
<string name="pair_already_in_progress">Сопряжение уже в процессе</string>
<string name="help">Помощь</string>
<string name="applist_connect_msg">Подключение к PC…</string>
<string name="title_decoding_error">Сбой Видео Декодера</string>
<string name="message_decoding_error">Произошел сбой Moonlight из-за проблем с видео декодером данного устройства. Попробуйте изменить настройки трансляции если сбои будут продолжаться.</string>
<string name="title_decoding_reset">Видео Настройки Сброшены</string>
<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>
<string name="summary_checkbox_usb_bind_all">Заставляет USB драйвер Moonlight взять на себя работу со всеми поддерживаемыми Xbox геймпадами</string>
<string name="title_checkbox_mouse_emulation">Эмуляция мыши на геймпаде</string>
<string name="summary_checkbox_mouse_emulation">Долгое нажатие кнопки Start переключит геймпад в режим мыши</string>
<string name="title_reset_osc">Сбросить схему расположения экранных кнопок</string>
<string name="summary_reset_osc">Возвращает все экранные элементы управления к их расположениям по умолчанию</string>
<string name="dialog_title_reset_osc">Сбросить Схему</string>
<string name="dialog_text_reset_osc">Вы уверены что хотите удалить сохранненную схему расположения кнопок?</string>
<string name="toast_reset_osc_success">Экранные элементы управления возвращены к положениям по умолчанию</string>
<string name="title_disable_frame_drop">Никогда не пропускать кадры</string>
<string name="summary_disable_frame_drop">Может уменьшить микрозависания на некоторых устройствах, но также увеличить задержку</string>
<string name="title_enable_hdr">Включить HDR (Экспериментально)</string>
<string name="summary_enable_hdr">Транслировать в HDR если игра и GPU компьютера поддерживают это. HDR требует видеокарты GTX 1000 серии или более новой.</string>
</resources>
+1 -1
View File
@@ -100,7 +100,7 @@
<string name="summary_resolution_list"> 过高的设定会引起串流卡顿甚至软件闪退 </string>
<string name="title_seekbar_bitrate"> 选择目标视频码率 </string>
<string name="summary_seekbar_bitrate"> 低码率减少卡顿,高码率提高画质 </string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video"> 将画面拉伸至全屏 </string>
<string name="title_checkbox_disable_warnings"> 禁用错误提示 </string>
<string name="summary_checkbox_disable_warnings"> 串流过程中禁用连接错误提示 </string>
+1 -1
View File
@@ -100,7 +100,7 @@
<string name="summary_resolution_list"> 過高的設定會引起串流卡頓甚至軟體閃退 </string>
<string name="title_seekbar_bitrate"> 選擇目標視頻碼率 </string>
<string name="summary_seekbar_bitrate"> 低碼率減少卡頓,高碼率提高畫質 </string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</string>
<string name="title_checkbox_stretch_video"> 將畫面拉伸至全屏 </string>
<string name="title_checkbox_disable_warnings"> 禁用錯誤提示 </string>
<string name="summary_checkbox_disable_warnings"> 串流過程中禁用連接錯誤提示 </string>
+4
View File
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="resolution_names">
<item>360p 30 FPS</item>
<item>360p 60 FPS</item>
<item>720p 30 FPS</item>
<item>720p 60 FPS</item>
<item>1080p 30 FPS</item>
@@ -9,6 +11,8 @@
<item>4K 60 FPS</item>
</string-array>
<string-array name="resolution_values" translatable="false">
<item>360p30</item>
<item>360p60</item>
<item>720p30</item>
<item>720p60</item>
<item>1080p30</item>
+15 -2
View File
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_label" translatable="false">Moonlight</string>
<string name="app_label_root" translatable="false">Moonlight (Root)</string>
<!-- Shortcut strings -->
<string name="scut_deleted_pc">PC deleted</string>
<string name="scut_not_paired">PC not paired</string>
@@ -98,6 +101,7 @@
<string name="addpc_success">Successfully added computer</string>
<string name="addpc_unknown_host">Unable to resolve PC address. Make sure you didn\'t make a typo in the address.</string>
<string name="addpc_enter_ip">You must enter an IP address</string>
<string name="addpc_wrong_sitelocal">That address doesn\'t look right. You must use your router\'s public IP address for streaming over the Internet.</string>
<!-- Preferences -->
<string name="category_basic_settings">Basic Settings</string>
@@ -105,7 +109,7 @@
<string name="summary_resolution_list">Setting values too high for your device may cause lag or crashing</string>
<string name="title_seekbar_bitrate">Select target video bitrate</string>
<string name="summary_seekbar_bitrate">Lower bitrate to reduce stuttering. Raise bitrate to increase image quality.</string>
<string name="suffix_seekbar_bitrate">Mbps</string>
<string name="suffix_seekbar_bitrate">Kbps</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="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
@@ -124,13 +128,22 @@
<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>
<string name="summary_checkbox_xb1_driver">Enables a built-in USB driver for devices without native Xbox controller support.</string>
<string name="summary_checkbox_xb1_driver">Enables a built-in USB driver for devices without native Xbox controller support</string>
<string name="title_checkbox_usb_bind_all">Override Android controller support</string>
<string name="summary_checkbox_usb_bind_all">Forces Moonlight\'s USB driver to take over all supported Xbox gamepads</string>
<string name="title_checkbox_mouse_emulation">Mouse emulation via gamepad</string>
<string name="summary_checkbox_mouse_emulation">Long pressing the Start button will switch the gamepad into mouse mode</string>
<string name="category_on_screen_controls_settings">On-screen Controls Settings</string>
<string name="title_checkbox_show_onscreen_controls">Show on-screen controls</string>
<string name="summary_checkbox_show_onscreen_controls">Show virtual controller overlay on touchscreen</string>
<string name="title_only_l3r3">Only show L3 and R3</string>
<string name="summary_only_l3r3">Hide all virtual buttons except L3 and R3</string>
<string name="title_reset_osc">Clear saved on-screen controls layout</string>
<string name="summary_reset_osc">Resets all on-screen controls to their default size and position</string>
<string name="dialog_title_reset_osc">Reset Layout</string>
<string name="dialog_text_reset_osc">Are you sure you want to delete your saved on-screen controls layout?</string>
<string name="toast_reset_osc_success">On-screen controls reset to default</string>
<string name="category_ui_settings">UI Settings</string>
<string name="title_language_list">Language</string>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
+27 -5
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:seekbar="http://schemas.moonlight-stream.com/apk/res/seekbar">
<PreferenceCategory android:title="@string/category_basic_settings"
android:key="category_basic_settings">
@@ -11,9 +12,11 @@
android:entryValues="@array/resolution_values"
android:defaultValue="720p60" />
<com.limelight.preferences.SeekBarPreference
android:key="seekbar_bitrate"
android:key="seekbar_bitrate_kbps"
android:dialogMessage="@string/summary_seekbar_bitrate"
android:max="100"
seekbar:min="500"
seekbar:step="500"
android:max="100000"
android:summary="@string/summary_seekbar_bitrate"
android:text="@string/suffix_seekbar_bitrate"
android:title="@string/title_seekbar_bitrate" />
@@ -56,21 +59,40 @@
android:title="@string/title_checkbox_xb1_driver"
android:summary="@string/summary_checkbox_xb1_driver"
android:defaultValue="true" />
<CheckBoxPreference
android:key="checkbox_usb_bind_all"
android:dependency="checkbox_usb_driver"
android:title="@string/title_checkbox_usb_bind_all"
android:summary="@string/summary_checkbox_usb_bind_all"
android:defaultValue="false" />
<CheckBoxPreference
android:key="checkbox_mouse_emulation"
android:title="@string/title_checkbox_mouse_emulation"
android:summary="@string/summary_checkbox_mouse_emulation"
android:defaultValue="true" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/category_on_screen_controls_settings"
android:key="category_onscreen_controls">
<CheckBoxPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="false"
android:key="checkbox_show_onscreen_controls"
android:summary="@string/summary_checkbox_show_onscreen_controls"
android:title="@string/title_checkbox_show_onscreen_controls" />
<CheckBoxPreference
android:defaultValue="false"
android:dependency="checkbox_show_onscreen_controls"
android:key="checkbox_only_show_L3R3"
android:summary="@string/summary_only_l3r3"
android:title="@string/title_only_l3r3" />
<com.limelight.preferences.ConfirmDeleteOscPreference
android:title="@string/title_reset_osc"
android:summary="@string/summary_reset_osc"
android:dialogTitle="@string/dialog_title_reset_osc"
android:dialogMessage="@string/dialog_text_reset_osc"
android:positiveButtonText="@string/yes"
android:negativeButtonText="@string/no"
/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/category_host_settings">
<CheckBoxPreference
+1 -1
View File
@@ -3,5 +3,5 @@
<!-- Non-root application name -->
<!-- FIXME: We should set extractNativeLibs=false but this breaks installation on the Fire TV 3 -->
<application android:label="Moonlight" />
<application android:label="@string/app_label" />
</manifest>
+1 -1
View File
@@ -5,6 +5,6 @@
<!-- Ensure native libraries are always extracted for root builds,
since we must invoke the evdev_reader binary ourselves -->
<application
android:label="Moonlight (Root)"
android:label="@string/app_label_root"
android:extractNativeLibs="true" />
</manifest>
+3 -1
View File
@@ -2,14 +2,16 @@
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.1.0-rc03'
}
}
allprojects {
repositories {
jcenter()
google()
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
#Sun Sep 03 12:51:12 PDT 2017
#Tue Mar 20 18:12:28 PDT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
-19
View File
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="moonlight-android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>