mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-21 15:56:57 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c175fecf6 | ||
|
|
773976b265 | ||
|
|
80070bbdbe | ||
|
|
4c8d433b6c | ||
|
|
404f096d11 | ||
|
|
d2ac927cec | ||
|
|
5e3d59d3d7 | ||
|
|
9cd2ce1309 | ||
|
|
9ed49730d4 | ||
|
|
39ebb48f58 | ||
|
|
1c29c70fba | ||
|
|
6993051529 | ||
|
|
4930087c4d | ||
|
|
795f0a013b | ||
|
|
213414778e | ||
|
|
7eac0ccaf8 | ||
|
|
6adc9dcb2d | ||
|
|
be620908f9 | ||
|
|
e4edfdb043 | ||
|
|
3b5028d1a4 | ||
|
|
bc8c45bd59 | ||
|
|
63eb346a70 | ||
|
|
27ad691d23 | ||
|
|
747e920061 | ||
|
|
8d09f56a0e | ||
|
|
113a0e2c45 | ||
|
|
977215a098 | ||
|
|
a7e65b47f9 | ||
|
|
7126055ad6 |
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
# Moonlight Android
|
# Moonlight Android
|
||||||
|
|
||||||
[Moonlight](http://moonlight-stream.com) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield.
|
[Moonlight](https://moonlight-stream.org) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield.
|
||||||
We reverse engineered the Shield streaming software and created a version that can be run on any Android device.
|
We reverse engineered the Shield streaming software and created a version that can be run on any Android device.
|
||||||
|
|
||||||
Moonlight will allow you to stream your full collection of games from your Windows PC to your Android device,
|
Moonlight will allow you to stream your full collection of games from your Windows PC to your Android device,
|
||||||
|
|||||||
+2
-2
@@ -8,8 +8,8 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
|
|
||||||
versionName "5.10"
|
versionName "6.0.1"
|
||||||
versionCode = 175
|
versionCode = 181
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions "root"
|
flavorDimensions "root"
|
||||||
|
|||||||
@@ -81,11 +81,8 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
// Wait for the binder to be ready
|
// Wait for the binder to be ready
|
||||||
localBinder.waitForReady();
|
localBinder.waitForReady();
|
||||||
|
|
||||||
// Now make the binder visible
|
|
||||||
managerBinder = localBinder;
|
|
||||||
|
|
||||||
// Get the computer object
|
// Get the computer object
|
||||||
computer = managerBinder.getComputer(UUID.fromString(uuidString));
|
computer = localBinder.getComputer(UUID.fromString(uuidString));
|
||||||
if (computer == null) {
|
if (computer == null) {
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
@@ -95,13 +92,18 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
appGridAdapter = new AppGridAdapter(AppView.this,
|
appGridAdapter = new AppGridAdapter(AppView.this,
|
||||||
PreferenceConfiguration.readPreferences(AppView.this).listMode,
|
PreferenceConfiguration.readPreferences(AppView.this).listMode,
|
||||||
PreferenceConfiguration.readPreferences(AppView.this).smallIconMode,
|
PreferenceConfiguration.readPreferences(AppView.this).smallIconMode,
|
||||||
computer, managerBinder.getUniqueId());
|
computer, localBinder.getUniqueId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now make the binder visible. We must do this after appGridAdapter
|
||||||
|
// is set to prevent us from reaching updateUiWithServerinfo() and
|
||||||
|
// touching the appGridAdapter prior to initialization.
|
||||||
|
managerBinder = localBinder;
|
||||||
|
|
||||||
// Load the app grid with cached data (if possible).
|
// Load the app grid with cached data (if possible).
|
||||||
// This must be done _before_ startComputerUpdates()
|
// This must be done _before_ startComputerUpdates()
|
||||||
// so the initial serverinfo response can update the running
|
// so the initial serverinfo response can update the running
|
||||||
|
|||||||
@@ -105,8 +105,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
private boolean grabbedInput = true;
|
private boolean grabbedInput = true;
|
||||||
private boolean grabComboDown = false;
|
private boolean grabComboDown = false;
|
||||||
private StreamView streamView;
|
private StreamView streamView;
|
||||||
private boolean gotBackPointerEvent = false;
|
|
||||||
private boolean syntheticBackDown = false;
|
|
||||||
|
|
||||||
private ShortcutHelper shortcutHelper;
|
private ShortcutHelper shortcutHelper;
|
||||||
|
|
||||||
@@ -134,7 +132,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
public static final String EXTRA_APP_NAME = "AppName";
|
public static final String EXTRA_APP_NAME = "AppName";
|
||||||
public static final String EXTRA_APP_ID = "AppId";
|
public static final String EXTRA_APP_ID = "AppId";
|
||||||
public static final String EXTRA_UNIQUEID = "UniqueId";
|
public static final String EXTRA_UNIQUEID = "UniqueId";
|
||||||
public static final String EXTRA_STREAMING_REMOTE = "Remote";
|
|
||||||
public static final String EXTRA_PC_UUID = "UUID";
|
public static final String EXTRA_PC_UUID = "UUID";
|
||||||
public static final String EXTRA_PC_NAME = "PcName";
|
public static final String EXTRA_PC_NAME = "PcName";
|
||||||
public static final String EXTRA_APP_HDR = "HDR";
|
public static final String EXTRA_APP_HDR = "HDR";
|
||||||
@@ -228,7 +225,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
String appName = Game.this.getIntent().getStringExtra(EXTRA_APP_NAME);
|
String appName = Game.this.getIntent().getStringExtra(EXTRA_APP_NAME);
|
||||||
int appId = Game.this.getIntent().getIntExtra(EXTRA_APP_ID, StreamConfiguration.INVALID_APP_ID);
|
int appId = Game.this.getIntent().getIntExtra(EXTRA_APP_ID, StreamConfiguration.INVALID_APP_ID);
|
||||||
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
|
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
|
||||||
boolean remote = Game.this.getIntent().getBooleanExtra(EXTRA_STREAMING_REMOTE, false);
|
|
||||||
String uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
|
String uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
|
||||||
String pcName = Game.this.getIntent().getStringExtra(EXTRA_PC_NAME);
|
String pcName = Game.this.getIntent().getStringExtra(EXTRA_PC_NAME);
|
||||||
boolean willStreamHdr = Game.this.getIntent().getBooleanExtra(EXTRA_APP_HDR, false);
|
boolean willStreamHdr = Game.this.getIntent().getBooleanExtra(EXTRA_APP_HDR, false);
|
||||||
@@ -348,8 +344,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Hopefully, we can get rid of this once someone comes up with a better way
|
// Hopefully, we can get rid of this once someone comes up with a better way
|
||||||
// to track the state of the pipeline and time frames.
|
// to track the state of the pipeline and time frames.
|
||||||
int roundedRefreshRate = Math.round(displayRefreshRate);
|
int roundedRefreshRate = Math.round(displayRefreshRate);
|
||||||
if (!prefConfig.disableFrameDrop && prefConfig.fps >= roundedRefreshRate) {
|
if ((!prefConfig.disableFrameDrop || prefConfig.unlockFps) && prefConfig.fps >= roundedRefreshRate) {
|
||||||
if (roundedRefreshRate <= 49) {
|
if (prefConfig.unlockFps) {
|
||||||
|
// Use frame drops when rendering above the screen frame rate
|
||||||
|
decoderRenderer.enableLegacyFrameDropRendering();
|
||||||
|
LimeLog.info("Using drop mode for FPS > Hz");
|
||||||
|
}
|
||||||
|
else if (roundedRefreshRate <= 49) {
|
||||||
// Let's avoid clearly bogus refresh rates and fall back to legacy rendering
|
// Let's avoid clearly bogus refresh rates and fall back to legacy rendering
|
||||||
decoderRenderer.enableLegacyFrameDropRendering();
|
decoderRenderer.enableLegacyFrameDropRendering();
|
||||||
LimeLog.info("Bogus refresh rate: "+roundedRefreshRate);
|
LimeLog.info("Bogus refresh rate: "+roundedRefreshRate);
|
||||||
@@ -372,8 +373,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
.setBitrate(prefConfig.bitrate)
|
.setBitrate(prefConfig.bitrate)
|
||||||
.setEnableSops(prefConfig.enableSops)
|
.setEnableSops(prefConfig.enableSops)
|
||||||
.enableLocalAudioPlayback(prefConfig.playHostAudio)
|
.enableLocalAudioPlayback(prefConfig.playHostAudio)
|
||||||
.setMaxPacketSize((remote || prefConfig.width <= 1920) ? 1024 : 1292)
|
.setMaxPacketSize(1392)
|
||||||
.setRemote(remote)
|
.setRemoteConfiguration(StreamConfiguration.STREAM_CFG_AUTO)
|
||||||
.setHevcBitratePercentageMultiplier(75)
|
.setHevcBitratePercentageMultiplier(75)
|
||||||
.setHevcSupported(decoderRenderer.isHevcSupported())
|
.setHevcSupported(decoderRenderer.isHevcSupported())
|
||||||
.setEnableHdr(willStreamHdr)
|
.setEnableHdr(willStreamHdr)
|
||||||
@@ -410,6 +411,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
(FrameLayout)streamView.getParent(),
|
(FrameLayout)streamView.getParent(),
|
||||||
this);
|
this);
|
||||||
virtualController.refreshLayout();
|
virtualController.refreshLayout();
|
||||||
|
virtualController.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefConfig.usbDriver) {
|
if (prefConfig.usbDriver) {
|
||||||
@@ -501,8 +503,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Display.Mode bestMode = display.getMode();
|
Display.Mode bestMode = display.getMode();
|
||||||
for (Display.Mode candidate : display.getSupportedModes()) {
|
for (Display.Mode candidate : display.getSupportedModes()) {
|
||||||
boolean refreshRateOk = candidate.getRefreshRate() >= bestMode.getRefreshRate() &&
|
boolean refreshRateOk = candidate.getRefreshRate() >= bestMode.getRefreshRate();
|
||||||
candidate.getRefreshRate() < 63;
|
|
||||||
boolean resolutionOk = candidate.getPhysicalWidth() >= bestMode.getPhysicalWidth() &&
|
boolean resolutionOk = candidate.getPhysicalWidth() >= bestMode.getPhysicalWidth() &&
|
||||||
candidate.getPhysicalHeight() >= bestMode.getPhysicalHeight() &&
|
candidate.getPhysicalHeight() >= bestMode.getPhysicalHeight() &&
|
||||||
candidate.getPhysicalWidth() <= 4096;
|
candidate.getPhysicalWidth() <= 4096;
|
||||||
@@ -518,6 +519,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the frame rate stays around 60 Hz for <= 60 FPS streams
|
||||||
|
if (prefConfig.fps <= 60) {
|
||||||
|
if (candidate.getRefreshRate() >= 63) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the refresh rate doesn't regress
|
// Make sure the refresh rate doesn't regress
|
||||||
if (!refreshRateOk) {
|
if (!refreshRateOk) {
|
||||||
continue;
|
continue;
|
||||||
@@ -535,12 +543,20 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
windowLayoutParams.preferredDisplayModeId = bestMode.getModeId();
|
windowLayoutParams.preferredDisplayModeId = bestMode.getModeId();
|
||||||
displayRefreshRate = bestMode.getRefreshRate();
|
displayRefreshRate = bestMode.getRefreshRate();
|
||||||
}
|
}
|
||||||
// On L, we can at least tell the OS that we want 60 Hz
|
// On L, we can at least tell the OS that we want a refresh rate
|
||||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
float bestRefreshRate = display.getRefreshRate();
|
float bestRefreshRate = display.getRefreshRate();
|
||||||
for (float candidate : display.getSupportedRefreshRates()) {
|
for (float candidate : display.getSupportedRefreshRates()) {
|
||||||
if (candidate > bestRefreshRate && candidate < 63) {
|
if (candidate > bestRefreshRate) {
|
||||||
LimeLog.info("Examining refresh rate: "+candidate);
|
LimeLog.info("Examining refresh rate: "+candidate);
|
||||||
|
|
||||||
|
// Ensure the frame rate stays around 60 Hz for <= 60 FPS streams
|
||||||
|
if (prefConfig.fps <= 60) {
|
||||||
|
if (candidate >= 63) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bestRefreshRate = candidate;
|
bestRefreshRate = candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -682,6 +698,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
SpinnerDialog.closeDialogs(this);
|
SpinnerDialog.closeDialogs(this);
|
||||||
Dialog.closeDialogs();
|
Dialog.closeDialogs();
|
||||||
|
|
||||||
|
if (virtualController != null) {
|
||||||
|
virtualController.hide();
|
||||||
|
}
|
||||||
|
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
int videoFormat = decoderRenderer.getActiveVideoFormat();
|
int videoFormat = decoderRenderer.getActiveVideoFormat();
|
||||||
|
|
||||||
@@ -838,16 +858,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
// create as a result of a right-click. This event WILL repeat if
|
// create as a result of a right-click. This event WILL repeat if
|
||||||
// the right mouse button is held down, so we ignore those.
|
// the right mouse button is held down, so we ignore those.
|
||||||
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
if (!prefConfig.mouseNavButtons &&
|
||||||
|
(event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||||
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||||
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||||
// It appears this may get turned into a right-click pointer event
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
// if we don't return true to indicate that we handled it on
|
|
||||||
// some devices. https://github.com/moonlight-stream/moonlight-android/issues/634
|
|
||||||
if (event.getRepeatCount() == 0 && !gotBackPointerEvent) {
|
|
||||||
syntheticBackDown = true;
|
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -896,19 +911,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
// Handle a synthetic back button event that some Android OS versions
|
// Handle a synthetic back button event that some Android OS versions
|
||||||
// create as a result of a right-click.
|
// create as a result of a right-click.
|
||||||
if ((event.getSource() == InputDevice.SOURCE_MOUSE ||
|
if (!prefConfig.mouseNavButtons &&
|
||||||
|
(event.getSource() == InputDevice.SOURCE_MOUSE ||
|
||||||
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE) &&
|
||||||
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||||
// It appears this may get turned into a right-click pointer event
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
// if we don't return true to indicate that we handled it on
|
|
||||||
// some devices. https://github.com/moonlight-stream/moonlight-android/issues/634
|
|
||||||
if (!gotBackPointerEvent || syntheticBackDown) {
|
|
||||||
// We need to raise the button if gotBackPointerEvent is true
|
|
||||||
// in the case where it transitioned to true after we already
|
|
||||||
// sent the right click down event.
|
|
||||||
syntheticBackDown = false;
|
|
||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,11 +1022,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
else {
|
else {
|
||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't use the KEYCODE_BACK hack (which interferes with mice
|
|
||||||
// with actual back buttons) since we're getting right clicks
|
|
||||||
// using this callback.
|
|
||||||
gotBackPointerEvent = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||||
@@ -1031,9 +1033,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Disable mouse back button press on Xiaomi due to reported
|
if (prefConfig.mouseNavButtons) {
|
||||||
// issues with right clicks triggering it.
|
|
||||||
if (!("Xiaomi".equalsIgnoreCase(Build.MANUFACTURER))) {
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_BACK) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_BACK) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_BACK) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_BACK) != 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X1);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X1);
|
||||||
@@ -1041,19 +1041,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
else {
|
else {
|
||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X1);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't use the KEYCODE_BACK hack. That will cause this
|
|
||||||
// button press to trigger a right-click.
|
|
||||||
gotBackPointerEvent = true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((changedButtons & MotionEvent.BUTTON_FORWARD) != 0) {
|
if ((changedButtons & MotionEvent.BUTTON_FORWARD) != 0) {
|
||||||
if ((event.getButtonState() & MotionEvent.BUTTON_FORWARD) != 0) {
|
if ((event.getButtonState() & MotionEvent.BUTTON_FORWARD) != 0) {
|
||||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X2);
|
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_X2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X2);
|
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_X2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -346,7 +346,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doPair(final ComputerDetails computer) {
|
private void doPair(final ComputerDetails computer) {
|
||||||
if (computer.state == ComputerDetails.State.OFFLINE) {
|
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||||
|
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||||
Toast.makeText(PcView.this, getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
Toast.makeText(PcView.this, getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -478,7 +479,8 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doUnpair(final ComputerDetails computer) {
|
private void doUnpair(final ComputerDetails computer) {
|
||||||
if (computer.state == ComputerDetails.State.OFFLINE) {
|
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||||
|
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||||
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
|
Toast.makeText(PcView.this, getResources().getString(R.string.error_pc_offline), Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,7 @@ public class AnalogStick extends VirtualControllerElement {
|
|||||||
} else {
|
} else {
|
||||||
stick_state = STICK_STATE.NO_MOVEMENT;
|
stick_state = STICK_STATE.NO_MOVEMENT;
|
||||||
notifyOnRevoke();
|
notifyOnRevoke();
|
||||||
|
|
||||||
// not longer pressed reset analog stick
|
// not longer pressed reset analog stick
|
||||||
notifyOnMovement(0, 0);
|
notifyOnMovement(0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-6
@@ -17,6 +17,8 @@ import com.limelight.nvstream.NvConnection;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class VirtualController {
|
public class VirtualController {
|
||||||
public class ControllerInputContext {
|
public class ControllerInputContext {
|
||||||
@@ -42,6 +44,8 @@ public class VirtualController {
|
|||||||
private FrameLayout frame_layout = null;
|
private FrameLayout frame_layout = null;
|
||||||
private RelativeLayout relative_layout = null;
|
private RelativeLayout relative_layout = null;
|
||||||
|
|
||||||
|
private Timer retransmitTimer;
|
||||||
|
|
||||||
ControllerMode currentMode = ControllerMode.Active;
|
ControllerMode currentMode = ControllerMode.Active;
|
||||||
ControllerInputContext inputContext = new ControllerInputContext();
|
ControllerInputContext inputContext = new ControllerInputContext();
|
||||||
|
|
||||||
@@ -88,11 +92,24 @@ public class VirtualController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void hide() {
|
public void hide() {
|
||||||
|
retransmitTimer.cancel();
|
||||||
relative_layout.setVisibility(View.INVISIBLE);
|
relative_layout.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show() {
|
public void show() {
|
||||||
relative_layout.setVisibility(View.VISIBLE);
|
relative_layout.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// HACK: GFE sometimes discards gamepad packets when they are received
|
||||||
|
// very shortly after another. This can be critical if an axis zeroing packet
|
||||||
|
// is lost and causes an analog stick to get stuck. To avoid this, we send
|
||||||
|
// a gamepad input packet every 100 ms to ensure any loss can be recovered.
|
||||||
|
retransmitTimer = new Timer("OSC timer", true);
|
||||||
|
retransmitTimer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendControllerInputContext();
|
||||||
|
}
|
||||||
|
}, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeElements() {
|
public void removeElements() {
|
||||||
@@ -149,18 +166,13 @@ public class VirtualController {
|
|||||||
return inputContext;
|
return inputContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendControllerInputContext() {
|
void sendControllerInputContext() {
|
||||||
sendControllerInputPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendControllerInputPacket() {
|
|
||||||
try {
|
try {
|
||||||
_DBG("INPUT_MAP + " + inputContext.inputMap);
|
_DBG("INPUT_MAP + " + inputContext.inputMap);
|
||||||
_DBG("LEFT_TRIGGER " + inputContext.leftTrigger);
|
_DBG("LEFT_TRIGGER " + inputContext.leftTrigger);
|
||||||
_DBG("RIGHT_TRIGGER " + inputContext.rightTrigger);
|
_DBG("RIGHT_TRIGGER " + inputContext.rightTrigger);
|
||||||
_DBG("LEFT STICK X: " + inputContext.leftStickX + " Y: " + inputContext.leftStickY);
|
_DBG("LEFT STICK X: " + inputContext.leftStickX + " Y: " + inputContext.leftStickY);
|
||||||
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
|
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
|
||||||
_DBG("RIGHT STICK X: " + inputContext.rightStickX + " Y: " + inputContext.rightStickY);
|
|
||||||
|
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
connection.sendControllerInput(
|
connection.sendControllerInput(
|
||||||
|
|||||||
@@ -405,10 +405,17 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render the last buffer
|
// Render the last buffer
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !legacyFrameDropRendering) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
// Use a PTS that will cause this frame to never be dropped if frame dropping
|
if (legacyFrameDropRendering) {
|
||||||
// is disabled
|
// Use a PTS that will cause this frame to be dropped if another comes in within
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, 0);
|
// the same V-sync period
|
||||||
|
videoDecoder.releaseOutputBuffer(lastIndex, System.nanoTime());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use a PTS that will cause this frame to never be dropped if frame dropping
|
||||||
|
// is disabled
|
||||||
|
videoDecoder.releaseOutputBuffer(lastIndex, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
videoDecoder.releaseOutputBuffer(lastIndex, true);
|
videoDecoder.releaseOutputBuffer(lastIndex, true);
|
||||||
|
|||||||
@@ -160,8 +160,8 @@ public class MediaCodecHelper {
|
|||||||
|
|
||||||
// We see a bunch of crashes on MediaTek Android TVs running
|
// We see a bunch of crashes on MediaTek Android TVs running
|
||||||
// at 49 FPS (PAL 50 Hz - 1). Blacklist this frame rate for
|
// at 49 FPS (PAL 50 Hz - 1). Blacklist this frame rate for
|
||||||
// these devices and hope they fix it in Oreo.
|
// these devices and hope they fix it in Pie.
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||||
blacklisted49FpsDecoderPrefixes.add("omx.mtk");
|
blacklisted49FpsDecoderPrefixes.add("omx.mtk");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,17 +105,27 @@ public class ComputerManagerService extends Service {
|
|||||||
|
|
||||||
// If it's online, update our persistent state
|
// If it's online, update our persistent state
|
||||||
if (details.state == ComputerDetails.State.ONLINE) {
|
if (details.state == ComputerDetails.State.ONLINE) {
|
||||||
if (!newPc) {
|
ComputerDetails existingComputer = dbManager.getComputerByUUID(details.uuid);
|
||||||
// Check if it's in the database because it could have been
|
|
||||||
// removed after this was issued
|
// Check if it's in the database because it could have been
|
||||||
if (dbManager.getComputerByUUID(details.uuid) == null) {
|
// removed after this was issued
|
||||||
// It's gone
|
if (!newPc && existingComputer == null) {
|
||||||
releaseLocalDatabaseReference();
|
// It's gone
|
||||||
return false;
|
releaseLocalDatabaseReference();
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbManager.updateComputer(details);
|
// If we already have an entry for this computer in the DB, we must
|
||||||
|
// combine the existing data with this new data (which may be partially available
|
||||||
|
// due to detecting the PC via mDNS) without the saved external address. If we
|
||||||
|
// write to the DB without doing this first, we can overwrite our existing data.
|
||||||
|
if (existingComputer != null) {
|
||||||
|
existingComputer.update(details);
|
||||||
|
dbManager.updateComputer(existingComputer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dbManager.updateComputer(details);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't call the listener if this is a failed lookup of a new PC
|
// Don't call the listener if this is a failed lookup of a new PC
|
||||||
@@ -304,7 +314,7 @@ public class ComputerManagerService extends Service {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTuple(ComputerDetails details, boolean manuallyAdded) {
|
private void addTuple(ComputerDetails details) {
|
||||||
synchronized (pollingTuples) {
|
synchronized (pollingTuples) {
|
||||||
for (PollingTuple tuple : pollingTuples) {
|
for (PollingTuple tuple : pollingTuples) {
|
||||||
// Check if this is the same computer
|
// Check if this is the same computer
|
||||||
@@ -365,7 +375,7 @@ public class ComputerManagerService extends Service {
|
|||||||
LimeLog.info("New PC ("+fakeDetails.name+") is UUID "+fakeDetails.uuid);
|
LimeLog.info("New PC ("+fakeDetails.name+") is UUID "+fakeDetails.uuid);
|
||||||
|
|
||||||
// Start a polling thread for this machine
|
// Start a polling thread for this machine
|
||||||
addTuple(fakeDetails, manuallyAdded);
|
addTuple(fakeDetails);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -537,7 +547,7 @@ public class ComputerManagerService extends Service {
|
|||||||
// b) if it's null, it will be unexpectedly nulling the activeAddress of a possibly online PC
|
// b) if it's null, it will be unexpectedly nulling the activeAddress of a possibly online PC
|
||||||
LimeLog.info("Starting fast poll for "+details.name+" ("+details.localAddress +", "+details.remoteAddress +", "+details.manualAddress +")");
|
LimeLog.info("Starting fast poll for "+details.name+" ("+details.localAddress +", "+details.remoteAddress +", "+details.manualAddress +")");
|
||||||
String candidateAddress = fastPollPc(details.localAddress, details.remoteAddress, details.manualAddress);
|
String candidateAddress = fastPollPc(details.localAddress, details.remoteAddress, details.manualAddress);
|
||||||
LimeLog.info("Fast poll for "+details.name+" returned active address: "+details.activeAddress);
|
LimeLog.info("Fast poll for "+details.name+" returned candidate address: "+candidateAddress);
|
||||||
|
|
||||||
// If no connection could be established to either IP address, there's nothing we can do
|
// If no connection could be established to either IP address, there's nothing we can do
|
||||||
if (candidateAddress == null) {
|
if (candidateAddress == null) {
|
||||||
@@ -593,7 +603,7 @@ public class ComputerManagerService extends Service {
|
|||||||
|
|
||||||
for (ComputerDetails computer : dbManager.getAllComputers()) {
|
for (ComputerDetails computer : dbManager.getAllComputers()) {
|
||||||
// Add tuples for each computer
|
// Add tuples for each computer
|
||||||
addTuple(computer, true);
|
addTuple(computer);
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseLocalDatabaseReference();
|
releaseLocalDatabaseReference();
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import android.os.Build;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
public class PreferenceConfiguration {
|
public class PreferenceConfiguration {
|
||||||
static final String RES_FPS_PREF_STRING = "list_resolution_fps";
|
private static final String LEGACY_RES_FPS_PREF_STRING = "list_resolution_fps";
|
||||||
|
|
||||||
|
|
||||||
|
static final String RESOLUTION_PREF_STRING = "list_resolution";
|
||||||
|
static final String FPS_PREF_STRING = "list_fps";
|
||||||
static final String BITRATE_PREF_STRING = "seekbar_bitrate_kbps";
|
static final String BITRATE_PREF_STRING = "seekbar_bitrate_kbps";
|
||||||
private static final String BITRATE_PREF_OLD_STRING = "seekbar_bitrate";
|
private static final String BITRATE_PREF_OLD_STRING = "seekbar_bitrate";
|
||||||
private static final String STRETCH_PREF_STRING = "checkbox_stretch_video";
|
private static final String STRETCH_PREF_STRING = "checkbox_stretch_video";
|
||||||
@@ -29,18 +33,11 @@ public class PreferenceConfiguration {
|
|||||||
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
|
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 BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
|
||||||
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
|
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
|
||||||
|
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
|
||||||
|
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
|
||||||
|
|
||||||
private static final int BITRATE_DEFAULT_360_30 = 1000;
|
static final String DEFAULT_RESOLUTION = "720p";
|
||||||
private static final int BITRATE_DEFAULT_360_60 = 2000;
|
static final String DEFAULT_FPS = "60";
|
||||||
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;
|
|
||||||
private static final boolean DEFAULT_STRETCH = false;
|
private static final boolean DEFAULT_STRETCH = false;
|
||||||
private static final boolean DEFAULT_SOPS = true;
|
private static final boolean DEFAULT_SOPS = true;
|
||||||
private static final boolean DEFAULT_DISABLE_TOASTS = false;
|
private static final boolean DEFAULT_DISABLE_TOASTS = false;
|
||||||
@@ -54,12 +51,13 @@ public class PreferenceConfiguration {
|
|||||||
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
||||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||||
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
||||||
private static final boolean DEFAULT_BATTERY_SAVER = false;
|
|
||||||
private static final boolean DEFAULT_DISABLE_FRAME_DROP = false;
|
private static final boolean DEFAULT_DISABLE_FRAME_DROP = false;
|
||||||
private static final boolean DEFAULT_ENABLE_HDR = false;
|
private static final boolean DEFAULT_ENABLE_HDR = false;
|
||||||
private static final boolean DEFAULT_ENABLE_PIP = false;
|
private static final boolean DEFAULT_ENABLE_PIP = false;
|
||||||
private static final boolean DEFAULT_BIND_ALL_USB = false;
|
private static final boolean DEFAULT_BIND_ALL_USB = false;
|
||||||
private static final boolean DEFAULT_MOUSE_EMULATION = true;
|
private static final boolean DEFAULT_MOUSE_EMULATION = true;
|
||||||
|
private static final boolean DEFAULT_MOUSE_NAV_BUTTONS = false;
|
||||||
|
private static final boolean DEFAULT_UNLOCK_FPS = false;
|
||||||
|
|
||||||
public static final int FORCE_H265_ON = -1;
|
public static final int FORCE_H265_ON = -1;
|
||||||
public static final int AUTOSELECT_H265 = 0;
|
public static final int AUTOSELECT_H265 = 0;
|
||||||
@@ -79,35 +77,80 @@ public class PreferenceConfiguration {
|
|||||||
public boolean enablePip;
|
public boolean enablePip;
|
||||||
public boolean bindAllUsb;
|
public boolean bindAllUsb;
|
||||||
public boolean mouseEmulation;
|
public boolean mouseEmulation;
|
||||||
|
public boolean mouseNavButtons;
|
||||||
|
public boolean unlockFps;
|
||||||
|
|
||||||
public static int getDefaultBitrate(String resFpsString) {
|
private static int getHeightFromResolutionString(String resString) {
|
||||||
if (resFpsString.equals("360p30")) {
|
if (resString.equalsIgnoreCase("360p")) {
|
||||||
return BITRATE_DEFAULT_360_30;
|
return 360;
|
||||||
}
|
}
|
||||||
else if (resFpsString.equals("360p60")) {
|
else if (resString.equalsIgnoreCase("720p")) {
|
||||||
return BITRATE_DEFAULT_360_60;
|
return 720;
|
||||||
}
|
}
|
||||||
else if (resFpsString.equals("720p30")) {
|
else if (resString.equalsIgnoreCase("1080p")) {
|
||||||
return BITRATE_DEFAULT_720_30;
|
return 1080;
|
||||||
}
|
}
|
||||||
else if (resFpsString.equals("720p60")) {
|
else if (resString.equalsIgnoreCase("1440p")) {
|
||||||
return BITRATE_DEFAULT_720_60;
|
return 1440;
|
||||||
}
|
}
|
||||||
else if (resFpsString.equals("1080p30")) {
|
else if (resString.equalsIgnoreCase("4K")) {
|
||||||
return BITRATE_DEFAULT_1080_30;
|
return 2160;
|
||||||
}
|
|
||||||
else if (resFpsString.equals("1080p60")) {
|
|
||||||
return BITRATE_DEFAULT_1080_60;
|
|
||||||
}
|
|
||||||
else if (resFpsString.equals("4K30")) {
|
|
||||||
return BITRATE_DEFAULT_4K_30;
|
|
||||||
}
|
|
||||||
else if (resFpsString.equals("4K60")) {
|
|
||||||
return BITRATE_DEFAULT_4K_60;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Should never get here
|
// Should be unreachable
|
||||||
return DEFAULT_BITRATE;
|
return 720;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getWidthFromResolutionString(String resString) {
|
||||||
|
return (getHeightFromResolutionString(resString) * 16) / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getResolutionString(int width, int height) {
|
||||||
|
switch (height) {
|
||||||
|
case 360:
|
||||||
|
return "360p";
|
||||||
|
default:
|
||||||
|
case 720:
|
||||||
|
return "720p";
|
||||||
|
case 1080:
|
||||||
|
return "1080p";
|
||||||
|
case 1440:
|
||||||
|
return "1440p";
|
||||||
|
case 2160:
|
||||||
|
return "4K";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultBitrate(String resString, String fpsString) {
|
||||||
|
int width = getWidthFromResolutionString(resString);
|
||||||
|
int height = getHeightFromResolutionString(resString);
|
||||||
|
int fps = Integer.parseInt(fpsString);
|
||||||
|
|
||||||
|
// This table prefers 16:10 resolutions because they are
|
||||||
|
// only slightly more pixels than the 16:9 equivalents, so
|
||||||
|
// we don't want to bump those 16:10 resolutions up to the
|
||||||
|
// next 16:9 slot.
|
||||||
|
//
|
||||||
|
// This logic is shamelessly stolen from Moonlight Qt:
|
||||||
|
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
||||||
|
|
||||||
|
if (width * height <= 640 * 360) {
|
||||||
|
return (int)(1000 * (fps / 30.0));
|
||||||
|
}
|
||||||
|
// This covers 1280x720 and 1280x800 too
|
||||||
|
else if (width * height <= 1366 * 768) {
|
||||||
|
return (int)(5000 * (fps / 30.0));
|
||||||
|
}
|
||||||
|
else if (width * height <= 1920 * 1200) {
|
||||||
|
return (int)(10000 * (fps / 30.0));
|
||||||
|
}
|
||||||
|
else if (width * height <= 2560 * 1600) {
|
||||||
|
return (int)(20000 * (fps / 30.0));
|
||||||
|
}
|
||||||
|
else /* if (width * height <= 3840 * 2160) */ {
|
||||||
|
return (int)(40000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +176,9 @@ public class PreferenceConfiguration {
|
|||||||
|
|
||||||
public static int getDefaultBitrate(Context context) {
|
public static int getDefaultBitrate(Context context) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
return getDefaultBitrate(prefs.getString(RES_FPS_PREF_STRING, DEFAULT_RES_FPS));
|
return getDefaultBitrate(
|
||||||
|
prefs.getString(RESOLUTION_PREF_STRING, DEFAULT_RESOLUTION),
|
||||||
|
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getVideoFormatValue(Context context) {
|
private static int getVideoFormatValue(Context context) {
|
||||||
@@ -161,9 +206,12 @@ public class PreferenceConfiguration {
|
|||||||
prefs.edit()
|
prefs.edit()
|
||||||
.remove(BITRATE_PREF_STRING)
|
.remove(BITRATE_PREF_STRING)
|
||||||
.remove(BITRATE_PREF_OLD_STRING)
|
.remove(BITRATE_PREF_OLD_STRING)
|
||||||
.remove(RES_FPS_PREF_STRING)
|
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||||
|
.remove(RESOLUTION_PREF_STRING)
|
||||||
|
.remove(FPS_PREF_STRING)
|
||||||
.remove(VIDEO_FORMAT_PREF_STRING)
|
.remove(VIDEO_FORMAT_PREF_STRING)
|
||||||
.remove(ENABLE_HDR_PREF_STRING)
|
.remove(ENABLE_HDR_PREF_STRING)
|
||||||
|
.remove(UNLOCK_FPS_STRING)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,59 +219,76 @@ public class PreferenceConfiguration {
|
|||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
PreferenceConfiguration config = new PreferenceConfiguration();
|
PreferenceConfiguration config = new PreferenceConfiguration();
|
||||||
|
|
||||||
|
// Migrate legacy preferences to the new locations
|
||||||
|
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
||||||
|
if (str != null) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else if (str.equals("720p60")) {
|
||||||
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
|
config.fps = 60;
|
||||||
|
}
|
||||||
|
else if (str.equals("1080p30")) {
|
||||||
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
|
config.fps = 30;
|
||||||
|
}
|
||||||
|
else if (str.equals("1080p60")) {
|
||||||
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
|
config.fps = 60;
|
||||||
|
}
|
||||||
|
else if (str.equals("4K30")) {
|
||||||
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
|
config.fps = 30;
|
||||||
|
}
|
||||||
|
else if (str.equals("4K60")) {
|
||||||
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
|
config.fps = 60;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Should never get here
|
||||||
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
|
config.fps = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs.edit()
|
||||||
|
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||||
|
.putString(RESOLUTION_PREF_STRING, getResolutionString(config.width, config.height))
|
||||||
|
.putString(FPS_PREF_STRING, ""+config.fps)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Use the new preference location
|
||||||
|
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
||||||
|
config.width = PreferenceConfiguration.getWidthFromResolutionString(resStr);
|
||||||
|
config.height = PreferenceConfiguration.getHeightFromResolutionString(resStr);
|
||||||
|
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must happen after the preferences migration to ensure the preferences are populated
|
||||||
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
|
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
|
||||||
if (config.bitrate == 0) {
|
if (config.bitrate == 0) {
|
||||||
config.bitrate = getDefaultBitrate(context);
|
config.bitrate = getDefaultBitrate(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
String str = prefs.getString(RES_FPS_PREF_STRING, DEFAULT_RES_FPS);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
else if (str.equals("720p60")) {
|
|
||||||
config.width = 1280;
|
|
||||||
config.height = 720;
|
|
||||||
config.fps = 60;
|
|
||||||
}
|
|
||||||
else if (str.equals("1080p30")) {
|
|
||||||
config.width = 1920;
|
|
||||||
config.height = 1080;
|
|
||||||
config.fps = 30;
|
|
||||||
}
|
|
||||||
else if (str.equals("1080p60")) {
|
|
||||||
config.width = 1920;
|
|
||||||
config.height = 1080;
|
|
||||||
config.fps = 60;
|
|
||||||
}
|
|
||||||
else if (str.equals("4K30")) {
|
|
||||||
config.width = 3840;
|
|
||||||
config.height = 2160;
|
|
||||||
config.fps = 30;
|
|
||||||
}
|
|
||||||
else if (str.equals("4K60")) {
|
|
||||||
config.width = 3840;
|
|
||||||
config.height = 2160;
|
|
||||||
config.fps = 60;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Should never get here
|
|
||||||
config.width = 1280;
|
|
||||||
config.height = 720;
|
|
||||||
config.fps = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
config.videoFormat = getVideoFormatValue(context);
|
config.videoFormat = getVideoFormatValue(context);
|
||||||
|
|
||||||
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
||||||
@@ -247,6 +312,8 @@ public class PreferenceConfiguration {
|
|||||||
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
||||||
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
|
config.bindAllUsb = prefs.getBoolean(BIND_ALL_USB_STRING, DEFAULT_BIND_ALL_USB);
|
||||||
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
|
config.mouseEmulation = prefs.getBoolean(MOUSE_EMULATION_STRING, DEFAULT_MOUSE_EMULATION);
|
||||||
|
config.mouseNavButtons = prefs.getBoolean(MOUSE_NAV_BUTTONS_STRING, DEFAULT_MOUSE_NAV_BUTTONS);
|
||||||
|
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.media.MediaCodecInfo;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.os.Handler;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
@@ -24,6 +25,12 @@ import com.limelight.utils.UiHelper;
|
|||||||
public class StreamSettings extends Activity {
|
public class StreamSettings extends Activity {
|
||||||
private PreferenceConfiguration previousPrefs;
|
private PreferenceConfiguration previousPrefs;
|
||||||
|
|
||||||
|
void reloadSettings() {
|
||||||
|
getFragmentManager().beginTransaction().replace(
|
||||||
|
R.id.stream_settings, new SettingsFragment()
|
||||||
|
).commit();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -33,9 +40,7 @@ public class StreamSettings extends Activity {
|
|||||||
UiHelper.setLocale(this);
|
UiHelper.setLocale(this);
|
||||||
|
|
||||||
setContentView(R.layout.activity_stream_settings);
|
setContentView(R.layout.activity_stream_settings);
|
||||||
getFragmentManager().beginTransaction().replace(
|
reloadSettings();
|
||||||
R.id.stream_settings, new SettingsFragment()
|
|
||||||
).commit();
|
|
||||||
|
|
||||||
UiHelper.notifyNewRootView(this);
|
UiHelper.notifyNewRootView(this);
|
||||||
}
|
}
|
||||||
@@ -58,12 +63,20 @@ public class StreamSettings extends Activity {
|
|||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragment {
|
public static class SettingsFragment extends PreferenceFragment {
|
||||||
|
|
||||||
private static void removeResolution(ListPreference pref, String prefix) {
|
private void setValue(String preferenceKey, String value) {
|
||||||
|
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||||
|
|
||||||
|
pref.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||||
int matchingCount = 0;
|
int matchingCount = 0;
|
||||||
|
|
||||||
|
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||||
|
|
||||||
// Count the number of matching entries we'll be removing
|
// Count the number of matching entries we'll be removing
|
||||||
for (CharSequence seq : pref.getEntryValues()) {
|
for (CharSequence seq : pref.getEntryValues()) {
|
||||||
if (seq.toString().startsWith(prefix)) {
|
if (seq.toString().equalsIgnoreCase(value)) {
|
||||||
matchingCount++;
|
matchingCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,8 +86,8 @@ public class StreamSettings extends Activity {
|
|||||||
CharSequence[] entryValues = new CharSequence[pref.getEntryValues().length-matchingCount];
|
CharSequence[] entryValues = new CharSequence[pref.getEntryValues().length-matchingCount];
|
||||||
int outIndex = 0;
|
int outIndex = 0;
|
||||||
for (int i = 0; i < pref.getEntryValues().length; i++) {
|
for (int i = 0; i < pref.getEntryValues().length; i++) {
|
||||||
if (pref.getEntryValues()[i].toString().startsWith(prefix)) {
|
if (pref.getEntryValues()[i].toString().equalsIgnoreCase(value)) {
|
||||||
// Skip matching prefixes
|
// Skip matching values
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,15 +96,34 @@ public class StreamSettings extends Activity {
|
|||||||
outIndex++;
|
outIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pref.getValue().equalsIgnoreCase(value)) {
|
||||||
|
onMatched.run();
|
||||||
|
}
|
||||||
|
|
||||||
// Update the preference with the new list
|
// Update the preference with the new list
|
||||||
pref.setEntries(entries);
|
pref.setEntries(entries);
|
||||||
pref.setEntryValues(entryValues);
|
pref.setEntryValues(entryValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void resetBitrateToDefault(SharedPreferences prefs, String res, String fps) {
|
||||||
|
if (res == null) {
|
||||||
|
res = prefs.getString(PreferenceConfiguration.RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
||||||
|
}
|
||||||
|
if (fps == null) {
|
||||||
|
fps = prefs.getString(PreferenceConfiguration.FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs.edit()
|
||||||
|
.putInt(PreferenceConfiguration.BITRATE_PREF_STRING,
|
||||||
|
PreferenceConfiguration.getDefaultBitrate(res, fps))
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
|
|
||||||
@@ -110,6 +142,8 @@ public class StreamSettings extends Activity {
|
|||||||
category.removePreference(findPreference("checkbox_enable_pip"));
|
category.removePreference(findPreference("checkbox_enable_pip"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maxSupportedFps = 0;
|
||||||
|
|
||||||
// Hide non-supported resolution/FPS combinations
|
// Hide non-supported resolution/FPS combinations
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||||
@@ -134,9 +168,16 @@ public class StreamSettings extends Activity {
|
|||||||
if ((width >= 3840 || height >= 2160) && maxSupportedResW < 3840) {
|
if ((width >= 3840 || height >= 2160) && maxSupportedResW < 3840) {
|
||||||
maxSupportedResW = 3840;
|
maxSupportedResW = 3840;
|
||||||
}
|
}
|
||||||
|
else if ((width >= 2560 || height >= 1440) && maxSupportedResW < 2560) {
|
||||||
|
maxSupportedResW = 2560;
|
||||||
|
}
|
||||||
else if ((width >= 1920 || height >= 1080) && maxSupportedResW < 1920) {
|
else if ((width >= 1920 || height >= 1080) && maxSupportedResW < 1920) {
|
||||||
maxSupportedResW = 1920;
|
maxSupportedResW = 1920;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (candidate.getRefreshRate() > maxSupportedFps) {
|
||||||
|
maxSupportedFps = (int)candidate.getRefreshRate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This must be called to do runtime initialization before calling functions that evaluate
|
// This must be called to do runtime initialization before calling functions that evaluate
|
||||||
@@ -186,20 +227,102 @@ public class StreamSettings extends Activity {
|
|||||||
|
|
||||||
LimeLog.info("Maximum resolution slot: "+maxSupportedResW);
|
LimeLog.info("Maximum resolution slot: "+maxSupportedResW);
|
||||||
|
|
||||||
ListPreference resPref = (ListPreference) findPreference("list_resolution_fps");
|
|
||||||
if (maxSupportedResW != 0) {
|
if (maxSupportedResW != 0) {
|
||||||
if (maxSupportedResW < 3840) {
|
if (maxSupportedResW < 3840) {
|
||||||
// 4K is unsupported
|
// 4K is unsupported
|
||||||
removeResolution(resPref, "4K");
|
removeValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "4K", new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
setValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "1440p");
|
||||||
|
resetBitrateToDefault(prefs, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (maxSupportedResW < 2560) {
|
||||||
|
// 1440p is unsupported
|
||||||
|
removeValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "1440p", new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
setValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "1080p");
|
||||||
|
resetBitrateToDefault(prefs, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (maxSupportedResW < 1920) {
|
if (maxSupportedResW < 1920) {
|
||||||
// 1080p is unsupported
|
// 1080p is unsupported
|
||||||
removeResolution(resPref, "1080p");
|
removeValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "1080p", new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
setValue(PreferenceConfiguration.RESOLUTION_PREF_STRING, "720p");
|
||||||
|
resetBitrateToDefault(prefs, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Never remove 720p
|
// Never remove 720p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
|
||||||
|
// We give some extra room in case the FPS is rounded down
|
||||||
|
if (maxSupportedFps < 118) {
|
||||||
|
removeValue(PreferenceConfiguration.FPS_PREF_STRING, "120", new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
setValue(PreferenceConfiguration.FPS_PREF_STRING, "90");
|
||||||
|
resetBitrateToDefault(prefs, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (maxSupportedFps < 88) {
|
||||||
|
// 1080p is unsupported
|
||||||
|
removeValue(PreferenceConfiguration.FPS_PREF_STRING, "90", new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
setValue(PreferenceConfiguration.FPS_PREF_STRING, "60");
|
||||||
|
resetBitrateToDefault(prefs, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Never remove 30 FPS or 60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
|
||||||
|
// that the unlock FPS option relies on to not massively increase latency.
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
LimeLog.info("Excluding unlock FPS toggle based on OS");
|
||||||
|
PreferenceCategory category =
|
||||||
|
(PreferenceCategory) findPreference("category_basic_settings");
|
||||||
|
category.removePreference(findPreference("checkbox_unlock_fps"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
// HACK: We need to let the preference change succeed before reinitializing to ensure
|
||||||
|
// it's reflected in the new layout.
|
||||||
|
final Handler h = new Handler();
|
||||||
|
h.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Ensure the activity is still open when this timeout expires
|
||||||
|
StreamSettings settingsActivity = (StreamSettings)SettingsFragment.this.getActivity();
|
||||||
|
if (settingsActivity != null) {
|
||||||
|
settingsActivity.reloadSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
// Allow the original preference change to take place
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Remove HDR preference for devices below Nougat
|
// Remove HDR preference for devices below Nougat
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||||
LimeLog.info("Excluding HDR toggle based on OS");
|
LimeLog.info("Excluding HDR toggle based on OS");
|
||||||
@@ -213,9 +336,12 @@ public class StreamSettings extends Activity {
|
|||||||
|
|
||||||
// We must now ensure our display is compatible with HDR10
|
// We must now ensure our display is compatible with HDR10
|
||||||
boolean foundHdr10 = false;
|
boolean foundHdr10 = false;
|
||||||
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
|
if (hdrCaps != null) {
|
||||||
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
|
// getHdrCapabilities() returns null on Lenovo Lenovo Mirage Solo (vega), Android 8.0
|
||||||
foundHdr10 = true;
|
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
|
||||||
|
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
|
||||||
|
foundHdr10 = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,18 +355,27 @@ public class StreamSettings extends Activity {
|
|||||||
|
|
||||||
// Add a listener to the FPS and resolution preference
|
// Add a listener to the FPS and resolution preference
|
||||||
// so the bitrate can be auto-adjusted
|
// so the bitrate can be auto-adjusted
|
||||||
Preference pref = findPreference(PreferenceConfiguration.RES_FPS_PREF_STRING);
|
findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
String valueStr = (String) newValue;
|
String valueStr = (String) newValue;
|
||||||
|
|
||||||
// Write the new bitrate value
|
// Write the new bitrate value
|
||||||
prefs.edit()
|
resetBitrateToDefault(prefs, valueStr, null);
|
||||||
.putInt(PreferenceConfiguration.BITRATE_PREF_STRING,
|
|
||||||
PreferenceConfiguration.getDefaultBitrate(valueStr))
|
// Allow the original preference change to take place
|
||||||
.apply();
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
findPreference(PreferenceConfiguration.FPS_PREF_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||||
|
String valueStr = (String) newValue;
|
||||||
|
|
||||||
|
// Write the new bitrate value
|
||||||
|
resetBitrateToDefault(prefs, null, valueStr);
|
||||||
|
|
||||||
// Allow the original preference change to take place
|
// Allow the original preference change to take place
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ public class ServerHelper {
|
|||||||
intent.putExtra(Game.EXTRA_APP_ID, app.getAppId());
|
intent.putExtra(Game.EXTRA_APP_ID, app.getAppId());
|
||||||
intent.putExtra(Game.EXTRA_APP_HDR, app.isHdrSupported());
|
intent.putExtra(Game.EXTRA_APP_HDR, app.isHdrSupported());
|
||||||
intent.putExtra(Game.EXTRA_UNIQUEID, managerBinder.getUniqueId());
|
intent.putExtra(Game.EXTRA_UNIQUEID, managerBinder.getUniqueId());
|
||||||
intent.putExtra(Game.EXTRA_STREAMING_REMOTE, getCurrentAddressFromComputer(computer).equals(computer.remoteAddress));
|
|
||||||
intent.putExtra(Game.EXTRA_PC_UUID, computer.uuid.toString());
|
intent.putExtra(Game.EXTRA_PC_UUID, computer.uuid.toString());
|
||||||
intent.putExtra(Game.EXTRA_PC_NAME, computer.name);
|
intent.putExtra(Game.EXTRA_PC_NAME, computer.name);
|
||||||
return intent;
|
return intent;
|
||||||
@@ -37,6 +36,11 @@ public class ServerHelper {
|
|||||||
|
|
||||||
public static void doStart(Activity parent, NvApp app, ComputerDetails computer,
|
public static void doStart(Activity parent, NvApp app, ComputerDetails computer,
|
||||||
ComputerManagerService.ComputerManagerBinder managerBinder) {
|
ComputerManagerService.ComputerManagerBinder managerBinder) {
|
||||||
|
if (computer.state == ComputerDetails.State.OFFLINE ||
|
||||||
|
ServerHelper.getCurrentAddressFromComputer(computer) == null) {
|
||||||
|
Toast.makeText(parent, parent.getResources().getString(R.string.pair_pc_offline), Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
parent.startActivity(createStartIntent(parent, app, computer, managerBinder));
|
parent.startActivity(createStartIntent(parent, app, computer, managerBinder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,6 @@
|
|||||||
<string name="title_checkbox_51_surround">Activar sonido 5.1 surround</string>
|
<string name="title_checkbox_51_surround">Activar sonido 5.1 surround</string>
|
||||||
<string name="summary_checkbox_51_surround">Desmarcar si experimentas problemas de audio. Requiere GFE 2.7 o superior.</string>
|
<string name="summary_checkbox_51_surround">Desmarcar si experimentas problemas de audio. Requiere GFE 2.7 o superior.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">Configuración de mando</string>
|
|
||||||
<string name="title_checkbox_multi_controller">Soporte para múltiples mandos</string>
|
<string name="title_checkbox_multi_controller">Soporte para múltiples mandos</string>
|
||||||
<string name="summary_checkbox_multi_controller">Si no está marcado, todos los mandos aparecen como uno solo</string>
|
<string name="summary_checkbox_multi_controller">Si no está marcado, todos los mandos aparecen como uno solo</string>
|
||||||
<string name="title_seekbar_deadzone">Ajustar zona muerta del stick analógico</string>
|
<string name="title_seekbar_deadzone">Ajustar zona muerta del stick analógico</string>
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
<string name="lost_connection">Perte de connexion avec le PC</string>
|
<string name="lost_connection">Perte de connexion avec le PC</string>
|
||||||
<string name="title_details">Détails</string>
|
<string name="title_details">Détails</string>
|
||||||
<string name="help">Aide</string>
|
<string name="help">Aide</string>
|
||||||
|
<string name="delete_pc_msg">Êtes-vous sûr de vouloir supprimer ce PC?</string>
|
||||||
|
|
||||||
<!-- AppList activity -->
|
<!-- AppList activity -->
|
||||||
<string name="applist_connect_msg">Connexion au PC…</string>
|
<string name="applist_connect_msg">Connexion au PC…</string>
|
||||||
@@ -125,7 +126,6 @@
|
|||||||
<string name="title_checkbox_51_surround">Activer son surround 5.1</string>
|
<string name="title_checkbox_51_surround">Activer son surround 5.1</string>
|
||||||
<string name="summary_checkbox_51_surround">Décochez si vous rencontrez des problèmes audio. Nécessite GFE 2.7 ou supérieur.</string>
|
<string name="summary_checkbox_51_surround">Décochez si vous rencontrez des problèmes audio. Nécessite GFE 2.7 ou supérieur.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">Paramètres du gamepad</string>
|
|
||||||
<string name="title_checkbox_multi_controller">Prise en charge de plusieurs contrôleurs</string>
|
<string name="title_checkbox_multi_controller">Prise en charge de plusieurs contrôleurs</string>
|
||||||
<string name="summary_checkbox_multi_controller">Lorsqu\'elle n\'est pas cochée, tous les contrôleurs sont regroupés</string>
|
<string name="summary_checkbox_multi_controller">Lorsqu\'elle n\'est pas cochée, tous les contrôleurs sont regroupés</string>
|
||||||
<string name="title_seekbar_deadzone">Régler la zone morte du stick analogique</string>
|
<string name="title_seekbar_deadzone">Régler la zone morte du stick analogique</string>
|
||||||
@@ -163,6 +163,8 @@
|
|||||||
<string name="summary_checkbox_host_audio">Lire l\'audio de l\'ordinateur et de ce périphérique</string>
|
<string name="summary_checkbox_host_audio">Lire l\'audio de l\'ordinateur et de ce périphérique</string>
|
||||||
|
|
||||||
<string name="category_advanced_settings">Réglages avancés</string>
|
<string name="category_advanced_settings">Réglages avancés</string>
|
||||||
|
<string name="title_disable_frame_drop">Désactiver la suppression d\'image</string>
|
||||||
|
<string name="summary_disable_frame_drop">Peut réduire les micro-saccades sur certains appareils, mais peut augmenter la latence</string>
|
||||||
<string name="title_video_format">Modifier les paramètres H.265</string>
|
<string name="title_video_format">Modifier les paramètres H.265</string>
|
||||||
<string name="summary_video_format">H.265 réduit les besoins en bande passante vidéo mais nécessite un périphérique très récent</string>
|
<string name="summary_video_format">H.265 réduit les besoins en bande passante vidéo mais nécessite un périphérique très récent</string>
|
||||||
<string name="title_enable_hdr">Activer le HDR (expérimental)</string>
|
<string name="title_enable_hdr">Activer le HDR (expérimental)</string>
|
||||||
|
|||||||
@@ -116,7 +116,6 @@
|
|||||||
<string name="title_checkbox_51_surround">Abilita l\'audio 5.1 surround</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="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="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="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="title_seekbar_deadzone">Regola i punti morti degli stick analogici</string>
|
||||||
|
|||||||
@@ -93,7 +93,6 @@
|
|||||||
<string name="title_checkbox_51_surround">5.1chサラウンド</string>
|
<string name="title_checkbox_51_surround">5.1chサラウンド</string>
|
||||||
<string name="summary_checkbox_51_surround">音声に問題が生じる場合はチェックを外してください。バージョン2.7以降のGFEが必要です</string>
|
<string name="summary_checkbox_51_surround">音声に問題が生じる場合はチェックを外してください。バージョン2.7以降のGFEが必要です</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">ゲームコントローラ</string>
|
|
||||||
<string name="title_checkbox_multi_controller">複数のゲームコントローラ</string>
|
<string name="title_checkbox_multi_controller">複数のゲームコントローラ</string>
|
||||||
<string name="summary_checkbox_multi_controller">チェックを外すと、全てのゲームコントローラが単一の物として認識されます</string>
|
<string name="summary_checkbox_multi_controller">チェックを外すと、全てのゲームコントローラが単一の物として認識されます</string>
|
||||||
<string name="title_seekbar_deadzone">アナログゲームコントローラのデッドゾーン</string>
|
<string name="title_seekbar_deadzone">アナログゲームコントローラのデッドゾーン</string>
|
||||||
|
|||||||
@@ -108,7 +108,6 @@
|
|||||||
<string name="title_checkbox_51_surround">5.1 서라운드 사운드 활성화</string>
|
<string name="title_checkbox_51_surround">5.1 서라운드 사운드 활성화</string>
|
||||||
<string name="summary_checkbox_51_surround">오디오 문제가 발생한다면 체크를 해제하세요. GFE 2.7이나 그 이상 버전이 필요합니다.</string>
|
<string name="summary_checkbox_51_surround">오디오 문제가 발생한다면 체크를 해제하세요. GFE 2.7이나 그 이상 버전이 필요합니다.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">게임패드 설정</string>
|
|
||||||
<string name="title_checkbox_multi_controller">다중 컨트롤러 지원</string>
|
<string name="title_checkbox_multi_controller">다중 컨트롤러 지원</string>
|
||||||
<string name="summary_checkbox_multi_controller">이 옵션을 선택하지 않으면 모든 컨트롤러가 하나로 표시됩니다</string>
|
<string name="summary_checkbox_multi_controller">이 옵션을 선택하지 않으면 모든 컨트롤러가 하나로 표시됩니다</string>
|
||||||
<string name="title_seekbar_deadzone">아날로그 스틱 데드존 설정</string>
|
<string name="title_seekbar_deadzone">아날로그 스틱 데드존 설정</string>
|
||||||
|
|||||||
@@ -97,7 +97,6 @@
|
|||||||
<string name="title_checkbox_51_surround">Gebruik 5.1 surround sound</string>
|
<string name="title_checkbox_51_surround">Gebruik 5.1 surround sound</string>
|
||||||
<string name="summary_checkbox_51_surround">Gebruik dit niet als er problemen zijn met de audio. Vereist GFE 2.7 of hoger.</string>
|
<string name="summary_checkbox_51_surround">Gebruik dit niet als er problemen zijn met de audio. Vereist GFE 2.7 of hoger.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">Gamepad Instellingen</string>
|
|
||||||
<string name="title_checkbox_multi_controller">Multi-gamepad support</string>
|
<string name="title_checkbox_multi_controller">Multi-gamepad support</string>
|
||||||
<string name="summary_checkbox_multi_controller">Wanneer uitgevinkt, alle controllers verschijnen als één.</string>
|
<string name="summary_checkbox_multi_controller">Wanneer uitgevinkt, alle controllers verschijnen als één.</string>
|
||||||
<string name="title_seekbar_deadzone">Pas analoge dodezone aan.</string>
|
<string name="title_seekbar_deadzone">Pas analoge dodezone aan.</string>
|
||||||
|
|||||||
@@ -98,7 +98,6 @@
|
|||||||
<string name="title_checkbox_51_surround">Включить объёмный звук 5.1</string>
|
<string name="title_checkbox_51_surround">Включить объёмный звук 5.1</string>
|
||||||
<string name="summary_checkbox_51_surround">Отключите, если появляются аудио проблемы. Требуется GFE 2.7 или выше.</string>
|
<string name="summary_checkbox_51_surround">Отключите, если появляются аудио проблемы. Требуется GFE 2.7 или выше.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">Настройки Геймпада</string>
|
|
||||||
<string name="title_checkbox_multi_controller">Поддержка нескольких контроллеров</string>
|
<string name="title_checkbox_multi_controller">Поддержка нескольких контроллеров</string>
|
||||||
<string name="summary_checkbox_multi_controller">Когда отключена, все контроллеры определяются как один</string>
|
<string name="summary_checkbox_multi_controller">Когда отключена, все контроллеры определяются как один</string>
|
||||||
<string name="title_seekbar_deadzone">Регулировать мертвую зону аналогового стика</string>
|
<string name="title_seekbar_deadzone">Регулировать мертвую зону аналогового стика</string>
|
||||||
|
|||||||
@@ -108,7 +108,6 @@
|
|||||||
<string name="title_checkbox_51_surround"> 启用 5.1 环绕音效 </string>
|
<string name="title_checkbox_51_surround"> 启用 5.1 环绕音效 </string>
|
||||||
<string name="summary_checkbox_51_surround"> 如果你的声音听起来有问题请禁用。\n\n需要GeForce Experience 2.7 或更高版本 </string>
|
<string name="summary_checkbox_51_surround"> 如果你的声音听起来有问题请禁用。\n\n需要GeForce Experience 2.7 或更高版本 </string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings"> 手柄设置 </string>
|
|
||||||
<string name="title_checkbox_multi_controller"> 启用多手柄支持 </string>
|
<string name="title_checkbox_multi_controller"> 启用多手柄支持 </string>
|
||||||
<string name="summary_checkbox_multi_controller"> 如果禁用,所有手柄将会认作一个手柄 </string>
|
<string name="summary_checkbox_multi_controller"> 如果禁用,所有手柄将会认作一个手柄 </string>
|
||||||
<string name="title_seekbar_deadzone"> 调整摇杆死区 </string>
|
<string name="title_seekbar_deadzone"> 调整摇杆死区 </string>
|
||||||
|
|||||||
@@ -108,7 +108,6 @@
|
|||||||
<string name="title_checkbox_51_surround"> 啟用 5.1 環繞音效 </string>
|
<string name="title_checkbox_51_surround"> 啟用 5.1 環繞音效 </string>
|
||||||
<string name="summary_checkbox_51_surround"> 如果你的聲音聽起來有問題請禁用。\n\n需要GeForce Experience 2.7 或更高版本 </string>
|
<string name="summary_checkbox_51_surround"> 如果你的聲音聽起來有問題請禁用。\n\n需要GeForce Experience 2.7 或更高版本 </string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings"> 手柄設置 </string>
|
|
||||||
<string name="title_checkbox_multi_controller"> 啟用多手柄支持 </string>
|
<string name="title_checkbox_multi_controller"> 啟用多手柄支持 </string>
|
||||||
<string name="summary_checkbox_multi_controller"> 如果禁用,所有手柄將會認作一個手柄 </string>
|
<string name="summary_checkbox_multi_controller"> 如果禁用,所有手柄將會認作一個手柄 </string>
|
||||||
<string name="title_seekbar_deadzone"> 調整搖桿死區 </string>
|
<string name="title_seekbar_deadzone"> 調整搖桿死區 </string>
|
||||||
|
|||||||
@@ -1,24 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string-array name="resolution_names">
|
<string-array name="resolution_names">
|
||||||
<item>360p 30 FPS</item>
|
<item>360p</item>
|
||||||
<item>360p 60 FPS</item>
|
<item>720p</item>
|
||||||
<item>720p 30 FPS</item>
|
<item>1080p</item>
|
||||||
<item>720p 60 FPS</item>
|
<item>1440p</item>
|
||||||
<item>1080p 30 FPS</item>
|
<item>4K</item>
|
||||||
<item>1080p 60 FPS</item>
|
|
||||||
<item>4K 30 FPS</item>
|
|
||||||
<item>4K 60 FPS</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="resolution_values" translatable="false">
|
<string-array name="resolution_values" translatable="false">
|
||||||
<item>360p30</item>
|
<item>360p</item>
|
||||||
<item>360p60</item>
|
<item>720p</item>
|
||||||
<item>720p30</item>
|
<item>1080p</item>
|
||||||
<item>720p60</item>
|
<item>1440p</item>
|
||||||
<item>1080p30</item>
|
<item>4K</item>
|
||||||
<item>1080p60</item>
|
</string-array>
|
||||||
<item>4K30</item>
|
|
||||||
<item>4K60</item>
|
<string-array name="fps_names">
|
||||||
|
<item>30 FPS</item>
|
||||||
|
<item>60 FPS</item>
|
||||||
|
<item>90 FPS</item>
|
||||||
|
<item>120 FPS</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="fps_values" translatable="false">
|
||||||
|
<item>30</item>
|
||||||
|
<item>60</item>
|
||||||
|
<item>90</item>
|
||||||
|
<item>120</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="language_names" translatable="false">
|
<string-array name="language_names" translatable="false">
|
||||||
|
|||||||
@@ -114,11 +114,15 @@
|
|||||||
|
|
||||||
<!-- Preferences -->
|
<!-- Preferences -->
|
||||||
<string name="category_basic_settings">Basic Settings</string>
|
<string name="category_basic_settings">Basic Settings</string>
|
||||||
<string name="title_resolution_list">Select resolution and FPS target</string>
|
<string name="title_resolution_list">Video resolution</string>
|
||||||
<string name="summary_resolution_list">Setting values too high for your device may cause lag or crashing</string>
|
<string name="summary_resolution_list">Increase to improve image clarity. Decrease for better performance on lower end devices and slower networks.</string>
|
||||||
<string name="title_seekbar_bitrate">Select target video bitrate</string>
|
<string name="title_fps_list">Video frame rate</string>
|
||||||
<string name="summary_seekbar_bitrate">Lower bitrate to reduce stuttering. Raise bitrate to increase image quality.</string>
|
<string name="summary_fps_list">Increase for a smoother video stream. Decrease for better performance on lower end devices.</string>
|
||||||
|
<string name="title_seekbar_bitrate">Video bitrate</string>
|
||||||
|
<string name="summary_seekbar_bitrate">Increase for better image quality. Decrease to improve performance on slower connections.</string>
|
||||||
<string name="suffix_seekbar_bitrate">Kbps</string>
|
<string name="suffix_seekbar_bitrate">Kbps</string>
|
||||||
|
<string name="title_unlock_fps">Unlock all possible frame rates</string>
|
||||||
|
<string name="summary_unlock_fps">Streaming at 90 or 120 FPS may reduce latency on high-end devices but can cause lag or crashes on devices that can\'t support it</string>
|
||||||
<string name="title_checkbox_stretch_video">Stretch video to full-screen</string>
|
<string name="title_checkbox_stretch_video">Stretch video to full-screen</string>
|
||||||
<string name="title_checkbox_disable_warnings">Disable warning messages</string>
|
<string name="title_checkbox_disable_warnings">Disable warning messages</string>
|
||||||
<string name="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
|
<string name="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
|
||||||
@@ -129,9 +133,9 @@
|
|||||||
<string name="title_checkbox_51_surround">Enable 5.1 surround sound</string>
|
<string name="title_checkbox_51_surround">Enable 5.1 surround sound</string>
|
||||||
<string name="summary_checkbox_51_surround">Uncheck if you experience audio issues. Requires GFE 2.7 or higher.</string>
|
<string name="summary_checkbox_51_surround">Uncheck if you experience audio issues. Requires GFE 2.7 or higher.</string>
|
||||||
|
|
||||||
<string name="category_gamepad_settings">Gamepad Settings</string>
|
<string name="category_input_settings">Input Settings</string>
|
||||||
<string name="title_checkbox_multi_controller">Multiple controller support</string>
|
<string name="title_checkbox_multi_controller">Automatic gamepad presence detection</string>
|
||||||
<string name="summary_checkbox_multi_controller">Uncheck for games with controller detection issues</string>
|
<string name="summary_checkbox_multi_controller">Unchecking this option forces a gamepad to always be present</string>
|
||||||
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
|
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
|
||||||
<string name="suffix_seekbar_deadzone">%</string>
|
<string name="suffix_seekbar_deadzone">%</string>
|
||||||
<string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string>
|
<string name="title_checkbox_xb1_driver">Xbox 360/One controller driver</string>
|
||||||
@@ -140,6 +144,8 @@
|
|||||||
<string name="summary_checkbox_usb_bind_all">Forces Moonlight\'s USB driver to take over all supported Xbox gamepads</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="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="summary_checkbox_mouse_emulation">Long pressing the Start button will switch the gamepad into mouse mode</string>
|
||||||
|
<string name="title_checkbox_mouse_nav_buttons">Enable back and forward mouse buttons</string>
|
||||||
|
<string name="summary_checkbox_mouse_nav_buttons">Enabling this option may break right clicking on some buggy devices</string>
|
||||||
|
|
||||||
<string name="category_on_screen_controls_settings">On-screen Controls Settings</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="title_checkbox_show_onscreen_controls">Show on-screen controls</string>
|
||||||
|
|||||||
@@ -5,12 +5,19 @@
|
|||||||
<PreferenceCategory android:title="@string/category_basic_settings"
|
<PreferenceCategory android:title="@string/category_basic_settings"
|
||||||
android:key="category_basic_settings">
|
android:key="category_basic_settings">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:key="list_resolution_fps"
|
android:key="list_resolution"
|
||||||
android:title="@string/title_resolution_list"
|
android:title="@string/title_resolution_list"
|
||||||
android:summary="@string/summary_resolution_list"
|
android:summary="@string/summary_resolution_list"
|
||||||
android:entries="@array/resolution_names"
|
android:entries="@array/resolution_names"
|
||||||
android:entryValues="@array/resolution_values"
|
android:entryValues="@array/resolution_values"
|
||||||
android:defaultValue="720p60" />
|
android:defaultValue="720p" />
|
||||||
|
<ListPreference
|
||||||
|
android:key="list_fps"
|
||||||
|
android:title="@string/title_fps_list"
|
||||||
|
android:summary="@string/summary_fps_list"
|
||||||
|
android:entries="@array/fps_names"
|
||||||
|
android:entryValues="@array/fps_values"
|
||||||
|
android:defaultValue="60" />
|
||||||
<com.limelight.preferences.SeekBarPreference
|
<com.limelight.preferences.SeekBarPreference
|
||||||
android:key="seekbar_bitrate_kbps"
|
android:key="seekbar_bitrate_kbps"
|
||||||
android:dialogMessage="@string/summary_seekbar_bitrate"
|
android:dialogMessage="@string/summary_seekbar_bitrate"
|
||||||
@@ -20,6 +27,11 @@
|
|||||||
android:summary="@string/summary_seekbar_bitrate"
|
android:summary="@string/summary_seekbar_bitrate"
|
||||||
android:text="@string/suffix_seekbar_bitrate"
|
android:text="@string/suffix_seekbar_bitrate"
|
||||||
android:title="@string/title_seekbar_bitrate" />
|
android:title="@string/title_seekbar_bitrate" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="checkbox_unlock_fps"
|
||||||
|
android:title="@string/title_unlock_fps"
|
||||||
|
android:summary="@string/summary_unlock_fps"
|
||||||
|
android:defaultValue="false" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="checkbox_stretch_video"
|
android:key="checkbox_stretch_video"
|
||||||
android:title="@string/title_checkbox_stretch_video"
|
android:title="@string/title_checkbox_stretch_video"
|
||||||
@@ -37,7 +49,7 @@
|
|||||||
android:summary="@string/summary_checkbox_51_surround"
|
android:summary="@string/summary_checkbox_51_surround"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/category_gamepad_settings">
|
<PreferenceCategory android:title="@string/category_input_settings">
|
||||||
<!--com.limelight.preferences.SeekBarPreference
|
<!--com.limelight.preferences.SeekBarPreference
|
||||||
android:key="seekbar_deadzone"
|
android:key="seekbar_deadzone"
|
||||||
android:defaultValue="15"
|
android:defaultValue="15"
|
||||||
@@ -49,6 +61,11 @@
|
|||||||
android:title="@string/title_checkbox_multi_controller"
|
android:title="@string/title_checkbox_multi_controller"
|
||||||
android:summary="@string/summary_checkbox_multi_controller"
|
android:summary="@string/summary_checkbox_multi_controller"
|
||||||
android:defaultValue="true" />
|
android:defaultValue="true" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="checkbox_mouse_nav_buttons"
|
||||||
|
android:title="@string/title_checkbox_mouse_nav_buttons"
|
||||||
|
android:summary="@string/summary_checkbox_mouse_nav_buttons"
|
||||||
|
android:defaultValue="false" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="checkbox_usb_driver"
|
android:key="checkbox_usb_driver"
|
||||||
android:title="@string/title_checkbox_xb1_driver"
|
android:title="@string/title_checkbox_xb1_driver"
|
||||||
|
|||||||
+1
-1
Submodule moonlight-common updated: dd6e76c0f2...1af5c24e56.
Reference in new issue
Block a user