mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-20 15:27:18 +00:00
Compare commits
32
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa41bf8d97 | ||
|
|
fba9a125bf | ||
|
|
27312bd146 | ||
|
|
8f0c267ab8 | ||
|
|
a15d6a6b42 | ||
|
|
8f9061b250 | ||
|
|
ec57499e08 | ||
|
|
381598c5b6 | ||
|
|
452d020da5 | ||
|
|
b5f875c2e5 | ||
|
|
a31daeda96 | ||
|
|
437f52f53a | ||
|
|
33f0f7ecf0 | ||
|
|
6777e79e70 | ||
|
|
16d1e6181b | ||
|
|
a6c8db6c2c | ||
|
|
24aa0fecbe | ||
|
|
1a776b1990 | ||
|
|
27df265c81 | ||
|
|
84c0372719 | ||
|
|
3879e57c4c | ||
|
|
dcc3dcdaba | ||
|
|
d166635c7b | ||
|
|
33d484b7d1 | ||
|
|
26bff28e4d | ||
|
|
56eddff8d6 | ||
|
|
37b9133eb6 | ||
|
|
4a64967b1f | ||
|
|
23152b1264 | ||
|
|
c11338039f | ||
|
|
e712669d32 | ||
|
|
3768ae33b7 |
No files matched your search
+2
-2
@@ -9,8 +9,8 @@ android {
|
|||||||
minSdk 16
|
minSdk 16
|
||||||
targetSdk 33
|
targetSdk 33
|
||||||
|
|
||||||
versionName "10.10"
|
versionName "10.11"
|
||||||
versionCode = 298
|
versionCode = 301
|
||||||
|
|
||||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||||
ndk.debugSymbolLevel = 'FULL'
|
ndk.debugSymbolLevel = 'FULL'
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Enter landscape unless we're on a square screen
|
// Enter landscape unless we're on a square screen
|
||||||
setPreferredOrientationForCurrentDisplay();
|
setPreferredOrientationForCurrentDisplay();
|
||||||
|
|
||||||
if (prefConfig.stretchVideo || prefConfig.resolution.fullScreen) {
|
if (prefConfig.stretchVideo || shouldIgnoreInsetsForResolution(prefConfig.width, prefConfig.height)) {
|
||||||
// Allow the activity to layout under notches if the fill-screen option
|
// Allow the activity to layout under notches if the fill-screen option
|
||||||
// was turned on by the user or it's a full-screen native resolution
|
// was turned on by the user or it's a full-screen native resolution
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
@@ -456,7 +456,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
StreamConfiguration config = new StreamConfiguration.Builder()
|
StreamConfiguration config = new StreamConfiguration.Builder()
|
||||||
.setResolution(prefConfig.resolution.width, prefConfig.resolution.height)
|
.setResolution(prefConfig.width, prefConfig.height)
|
||||||
.setLaunchRefreshRate(prefConfig.fps)
|
.setLaunchRefreshRate(prefConfig.fps)
|
||||||
.setRefreshRate(chosenFrameRate)
|
.setRefreshRate(chosenFrameRate)
|
||||||
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
|
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
|
||||||
@@ -551,12 +551,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For native resolution, we will lock the orientation to the one that matches the specified resolution
|
// For native resolution, we will lock the orientation to the one that matches the specified resolution
|
||||||
if (prefConfig.resolution.type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
if (PreferenceConfiguration.isNativeResolution(prefConfig.width, prefConfig.height)) {
|
||||||
if (prefConfig.resolution.portrait) {
|
if (prefConfig.width > prefConfig.height) {
|
||||||
desiredOrientation = Configuration.ORIENTATION_PORTRAIT;
|
desiredOrientation = Configuration.ORIENTATION_LANDSCAPE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
desiredOrientation = Configuration.ORIENTATION_LANDSCAPE;
|
desiredOrientation = Configuration.ORIENTATION_PORTRAIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,7 +649,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
private PictureInPictureParams getPictureInPictureParams(boolean autoEnter) {
|
private PictureInPictureParams getPictureInPictureParams(boolean autoEnter) {
|
||||||
PictureInPictureParams.Builder builder =
|
PictureInPictureParams.Builder builder =
|
||||||
new PictureInPictureParams.Builder()
|
new PictureInPictureParams.Builder()
|
||||||
.setAspectRatio(new Rational(prefConfig.resolution.width, prefConfig.resolution.height))
|
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
||||||
.setSourceRectHint(new Rect(
|
.setSourceRectHint(new Rect(
|
||||||
streamView.getLeft(), streamView.getTop(),
|
streamView.getLeft(), streamView.getTop(),
|
||||||
streamView.getRight(), streamView.getBottom()));
|
streamView.getRight(), streamView.getBottom()));
|
||||||
@@ -771,6 +771,26 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
Math.round(refreshRate) % prefConfig.fps <= 3;
|
Math.round(refreshRate) % prefConfig.fps <= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldIgnoreInsetsForResolution(int width, int height) {
|
||||||
|
// Never ignore insets for non-native resolutions
|
||||||
|
if (!PreferenceConfiguration.isNativeResolution(width, height)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
Display display = getWindowManager().getDefaultDisplay();
|
||||||
|
for (Display.Mode candidate : display.getSupportedModes()) {
|
||||||
|
// Ignore insets if this is an exact match for the display resolution
|
||||||
|
if ((width == candidate.getPhysicalWidth() && height == candidate.getPhysicalHeight()) ||
|
||||||
|
(height == candidate.getPhysicalWidth() && width == candidate.getPhysicalHeight())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean mayReduceRefreshRate() {
|
private boolean mayReduceRefreshRate() {
|
||||||
return prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS ||
|
return prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS ||
|
||||||
prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
|
prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
|
||||||
@@ -785,6 +805,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// On M, we can explicitly set the optimal display mode
|
// On M, we can explicitly set the optimal display mode
|
||||||
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();
|
||||||
|
boolean isNativeResolutionStream = PreferenceConfiguration.isNativeResolution(prefConfig.width, prefConfig.height);
|
||||||
boolean refreshRateIsGood = isRefreshRateGoodMatch(bestMode.getRefreshRate());
|
boolean refreshRateIsGood = isRefreshRateGoodMatch(bestMode.getRefreshRate());
|
||||||
boolean refreshRateIsEqual = isRefreshRateEqualMatch(bestMode.getRefreshRate());
|
boolean refreshRateIsEqual = isRefreshRateEqualMatch(bestMode.getRefreshRate());
|
||||||
|
|
||||||
@@ -792,13 +813,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
boolean refreshRateReduced = candidate.getRefreshRate() < bestMode.getRefreshRate();
|
boolean refreshRateReduced = candidate.getRefreshRate() < bestMode.getRefreshRate();
|
||||||
boolean resolutionReduced = candidate.getPhysicalWidth() < bestMode.getPhysicalWidth() ||
|
boolean resolutionReduced = candidate.getPhysicalWidth() < bestMode.getPhysicalWidth() ||
|
||||||
candidate.getPhysicalHeight() < bestMode.getPhysicalHeight();
|
candidate.getPhysicalHeight() < bestMode.getPhysicalHeight();
|
||||||
boolean resolutionFitsStream = candidate.getPhysicalWidth() >= prefConfig.resolution.width &&
|
boolean resolutionFitsStream = candidate.getPhysicalWidth() >= prefConfig.width &&
|
||||||
candidate.getPhysicalHeight() >= prefConfig.resolution.height;
|
candidate.getPhysicalHeight() >= prefConfig.height;
|
||||||
|
|
||||||
LimeLog.info("Examining display mode: "+candidate.getPhysicalWidth()+"x"+
|
LimeLog.info("Examining display mode: "+candidate.getPhysicalWidth()+"x"+
|
||||||
candidate.getPhysicalHeight()+"x"+candidate.getRefreshRate());
|
candidate.getPhysicalHeight()+"x"+candidate.getRefreshRate());
|
||||||
|
|
||||||
if (candidate.getPhysicalWidth() > 4096 && prefConfig.resolution.width <= 4096) {
|
if (candidate.getPhysicalWidth() > 4096 && prefConfig.width <= 4096) {
|
||||||
// Avoid resolutions options above 4K to be safe
|
// Avoid resolutions options above 4K to be safe
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -806,8 +827,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// On non-4K streams, we force the resolution to never change unless it's above
|
// On non-4K streams, we force the resolution to never change unless it's above
|
||||||
// 60 FPS, which may require a resolution reduction due to HDMI bandwidth limitations,
|
// 60 FPS, which may require a resolution reduction due to HDMI bandwidth limitations,
|
||||||
// or it's a native resolution stream.
|
// or it's a native resolution stream.
|
||||||
if (prefConfig.resolution.width < 3840 && prefConfig.fps <= 60 &&
|
if (prefConfig.width < 3840 && prefConfig.fps <= 60 && !isNativeResolutionStream) {
|
||||||
prefConfig.resolution.type != PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
|
||||||
if (display.getMode().getPhysicalWidth() != candidate.getPhysicalWidth() ||
|
if (display.getMode().getPhysicalWidth() != candidate.getPhysicalWidth() ||
|
||||||
display.getMode().getPhysicalHeight() != candidate.getPhysicalHeight()) {
|
display.getMode().getPhysicalHeight() != candidate.getPhysicalHeight()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -920,7 +940,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
display.getSize(screenSize);
|
display.getSize(screenSize);
|
||||||
|
|
||||||
double screenAspectRatio = ((double)screenSize.y) / screenSize.x;
|
double screenAspectRatio = ((double)screenSize.y) / screenSize.x;
|
||||||
double streamAspectRatio = ((double)prefConfig.resolution.height) / prefConfig.resolution.width;
|
double streamAspectRatio = ((double)prefConfig.height) / prefConfig.width;
|
||||||
if (Math.abs(screenAspectRatio - streamAspectRatio) < 0.001) {
|
if (Math.abs(screenAspectRatio - streamAspectRatio) < 0.001) {
|
||||||
LimeLog.info("Stream has compatible aspect ratio with output display");
|
LimeLog.info("Stream has compatible aspect ratio with output display");
|
||||||
aspectRatioMatch = true;
|
aspectRatioMatch = true;
|
||||||
@@ -929,11 +949,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
if (prefConfig.stretchVideo || aspectRatioMatch) {
|
if (prefConfig.stretchVideo || aspectRatioMatch) {
|
||||||
// Set the surface to the size of the video
|
// Set the surface to the size of the video
|
||||||
streamView.getHolder().setFixedSize(prefConfig.resolution.width, prefConfig.resolution.height);
|
streamView.getHolder().setFixedSize(prefConfig.width, prefConfig.height);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Set the surface to scale based on the aspect ratio of the stream
|
// Set the surface to scale based on the aspect ratio of the stream
|
||||||
streamView.setDesiredAspectRatio((double)prefConfig.resolution.width / (double)prefConfig.resolution.height);
|
streamView.setDesiredAspectRatio((double)prefConfig.width / (double)prefConfig.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION) ||
|
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION) ||
|
||||||
@@ -1106,17 +1126,25 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setInputGrabState(boolean grab) {
|
||||||
|
// Grab/ungrab the mouse cursor
|
||||||
|
if (grab) {
|
||||||
|
inputCaptureProvider.enableCapture();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inputCaptureProvider.disableCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab/ungrab system keyboard shortcuts
|
||||||
|
setMetaKeyCaptureState(grab);
|
||||||
|
|
||||||
|
grabbedInput = grab;
|
||||||
|
}
|
||||||
|
|
||||||
private final Runnable toggleGrab = new Runnable() {
|
private final Runnable toggleGrab = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (grabbedInput) {
|
setInputGrabState(!grabbedInput);
|
||||||
inputCaptureProvider.disableCapture();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
inputCaptureProvider.enableCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
grabbedInput = !grabbedInput;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1136,6 +1164,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
androidKeyCode == KeyEvent.KEYCODE_ALT_RIGHT) {
|
androidKeyCode == KeyEvent.KEYCODE_ALT_RIGHT) {
|
||||||
modifierMask = KeyboardPacket.MODIFIER_ALT;
|
modifierMask = KeyboardPacket.MODIFIER_ALT;
|
||||||
}
|
}
|
||||||
|
else if (androidKeyCode == KeyEvent.KEYCODE_META_LEFT ||
|
||||||
|
androidKeyCode == KeyEvent.KEYCODE_META_RIGHT) {
|
||||||
|
modifierMask = KeyboardPacket.MODIFIER_META;
|
||||||
|
}
|
||||||
|
|
||||||
if (down) {
|
if (down) {
|
||||||
this.modifierFlags |= modifierMask;
|
this.modifierFlags |= modifierMask;
|
||||||
@@ -1144,10 +1176,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
this.modifierFlags &= ~modifierMask;
|
this.modifierFlags &= ~modifierMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Ctrl+Shift+Z is pressed
|
// Check if Ctrl+Alt+Shift+Z is pressed
|
||||||
if (androidKeyCode == KeyEvent.KEYCODE_Z &&
|
if (androidKeyCode == KeyEvent.KEYCODE_Z &&
|
||||||
(modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_SHIFT)) ==
|
(modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT)) ==
|
||||||
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_SHIFT))
|
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT))
|
||||||
{
|
{
|
||||||
if (down) {
|
if (down) {
|
||||||
// Now that we've pressed the magic combo
|
// Now that we've pressed the magic combo
|
||||||
@@ -1198,6 +1230,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
if (event.isAltPressed()) {
|
if (event.isAltPressed()) {
|
||||||
modifier |= KeyboardPacket.MODIFIER_ALT;
|
modifier |= KeyboardPacket.MODIFIER_ALT;
|
||||||
}
|
}
|
||||||
|
if (event.isMetaPressed()) {
|
||||||
|
modifier |= KeyboardPacket.MODIFIER_META;
|
||||||
|
}
|
||||||
return modifier;
|
return modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1861,11 +1896,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Let the display go to sleep now
|
// Let the display go to sleep now
|
||||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
// Enable cursor visibility again
|
// Ungrab input
|
||||||
inputCaptureProvider.disableCapture();
|
setInputGrabState(false);
|
||||||
|
|
||||||
// Disable meta key capture
|
|
||||||
setMetaKeyCaptureState(false);
|
|
||||||
|
|
||||||
if (!displayedFailureDialog) {
|
if (!displayedFailureDialog) {
|
||||||
displayedFailureDialog = true;
|
displayedFailureDialog = true;
|
||||||
@@ -1975,16 +2007,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
h.postDelayed(new Runnable() {
|
h.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
inputCaptureProvider.enableCapture();
|
setInputGrabState(true);
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
// Keep the display on
|
// Keep the display on
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
// Enable meta key capture
|
|
||||||
setMetaKeyCaptureState(true);
|
|
||||||
|
|
||||||
// Update GameManager state to indicate we're in game
|
// Update GameManager state to indicate we're in game
|
||||||
UiHelper.notifyStreamConnected(Game.this);
|
UiHelper.notifyStreamConnected(Game.this);
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
private boolean decoderCanMeetPerformancePoint(MediaCodecInfo.VideoCapabilities caps, PreferenceConfiguration prefs) {
|
private boolean decoderCanMeetPerformancePoint(MediaCodecInfo.VideoCapabilities caps, PreferenceConfiguration prefs) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.width, prefs.height, prefs.fps);
|
||||||
List<MediaCodecInfo.VideoCapabilities.PerformancePoint> perfPoints = caps.getSupportedPerformancePoints();
|
List<MediaCodecInfo.VideoCapabilities.PerformancePoint> perfPoints = caps.getSupportedPerformancePoints();
|
||||||
if (perfPoints != null) {
|
if (perfPoints != null) {
|
||||||
for (MediaCodecInfo.VideoCapabilities.PerformancePoint perfPoint : perfPoints) {
|
for (MediaCodecInfo.VideoCapabilities.PerformancePoint perfPoint : perfPoints) {
|
||||||
@@ -155,7 +155,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
try {
|
try {
|
||||||
// We'll ask the decoder what it can do for us at this resolution and see if our
|
// We'll ask the decoder what it can do for us at this resolution and see if our
|
||||||
// requested frame rate falls below or inside the range of achievable frame rates.
|
// requested frame rate falls below or inside the range of achievable frame rates.
|
||||||
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.resolution.width, prefs.resolution.height);
|
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.width, prefs.height);
|
||||||
if (fpsRange != null) {
|
if (fpsRange != null) {
|
||||||
return prefs.fps <= fpsRange.getUpper();
|
return prefs.fps <= fpsRange.getUpper();
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
// As a last resort, we will use areSizeAndRateSupported() which is explicitly NOT a
|
// As a last resort, we will use areSizeAndRateSupported() which is explicitly NOT a
|
||||||
// performance metric, but it can work at least for the purpose of determining if
|
// performance metric, but it can work at least for the purpose of determining if
|
||||||
// the codec is going to die when given a stream with the specified settings.
|
// the codec is going to die when given a stream with the specified settings.
|
||||||
return caps.areSizeAndRateSupported(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
return caps.areSizeAndRateSupported(prefs.width, prefs.height, prefs.fps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo avcDecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo avcDecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
||||||
@@ -211,7 +211,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
LimeLog.info("Forcing HEVC enabled for HDR streaming");
|
LimeLog.info("Forcing HEVC enabled for HDR streaming");
|
||||||
}
|
}
|
||||||
// > 4K streaming also requires HEVC, so force it on there too.
|
// > 4K streaming also requires HEVC, so force it on there too.
|
||||||
else if (prefs.resolution.width > 4096 || prefs.resolution.height > 4096) {
|
else if (prefs.width > 4096 || prefs.height > 4096) {
|
||||||
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
||||||
}
|
}
|
||||||
// Use HEVC if the H.264 decoder is unable to meet the performance point
|
// Use HEVC if the H.264 decoder is unable to meet the performance point
|
||||||
@@ -271,7 +271,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
int hevcOptimalSlicesPerFrame = 0;
|
int hevcOptimalSlicesPerFrame = 0;
|
||||||
if (avcDecoder != null) {
|
if (avcDecoder != null) {
|
||||||
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
||||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.resolution.height);
|
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height);
|
||||||
avcOptimalSlicesPerFrame = MediaCodecHelper.getDecoderOptimalSlicesPerFrame(avcDecoder.getName());
|
avcOptimalSlicesPerFrame = MediaCodecHelper.getDecoderOptimalSlicesPerFrame(avcDecoder.getName());
|
||||||
|
|
||||||
if (directSubmit) {
|
if (directSubmit) {
|
||||||
@@ -328,11 +328,28 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getPreferredColorSpace() {
|
public int getPreferredColorSpace() {
|
||||||
return MoonBridge.COLORSPACE_REC_601;
|
// Default to Rec 709 which is probably better supported on modern devices.
|
||||||
|
//
|
||||||
|
// We are sticking to Rec 601 on older devices unless the device has an HEVC decoder
|
||||||
|
// to avoid possible regressions (and they are < 5% of installed devices). If we have
|
||||||
|
// an HEVC decoder, we will use Rec 709 (even for H.264) since we can't choose a
|
||||||
|
// colorspace by codec (and it's probably safe to say a SoC with HEVC decoding is
|
||||||
|
// plenty modern enough to handle H.264 VUI colorspace info).
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || hevcDecoder != null) {
|
||||||
|
return MoonBridge.COLORSPACE_REC_709;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return MoonBridge.COLORSPACE_REC_601;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPreferredColorRange() {
|
public int getPreferredColorRange() {
|
||||||
return MoonBridge.COLOR_RANGE_LIMITED;
|
if (prefs.fullRange) {
|
||||||
|
return MoonBridge.COLOR_RANGE_FULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return MoonBridge.COLOR_RANGE_LIMITED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyVideoForeground() {
|
public void notifyVideoForeground() {
|
||||||
@@ -1303,9 +1320,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
|||||||
sps.numRefFrames = 1;
|
sps.numRefFrames = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GFE 2.5.11 changed the SPS to add additional extensions
|
// GFE 2.5.11 changed the SPS to add additional extensions. Some devices don't like these
|
||||||
// Some devices don't like these so we remove them here on old devices.
|
// so we remove them here on old devices unless these devices also support HEVC.
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && sps.vuiParams != null) {
|
// See getPreferredColorSpace() for further information.
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && hevcDecoder == null && sps.vuiParams != null) {
|
||||||
sps.vuiParams.videoSignalTypePresentFlag = false;
|
sps.vuiParams.videoSignalTypePresentFlag = false;
|
||||||
sps.vuiParams.colourDescriptionPresentFlag = false;
|
sps.vuiParams.colourDescriptionPresentFlag = false;
|
||||||
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.limelight.binding.video;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -78,12 +77,6 @@ public class MediaCodecHelper {
|
|||||||
refFrameInvalidationHevcPrefixes.add("omx.exynos");
|
refFrameInvalidationHevcPrefixes.add("omx.exynos");
|
||||||
refFrameInvalidationHevcPrefixes.add("c2.exynos");
|
refFrameInvalidationHevcPrefixes.add("c2.exynos");
|
||||||
|
|
||||||
// The Chromecast with Google TV 4K works well with HEVC RFI since we also use the
|
|
||||||
// vendor.low-latency.enable option.
|
|
||||||
if (Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
|
||||||
refFrameInvalidationHevcPrefixes.add("omx.amlogic");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Qualcomm and NVIDIA may be added at runtime
|
// Qualcomm and NVIDIA may be added at runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,6 +177,9 @@ public class MediaCodecHelper {
|
|||||||
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
||||||
// determines it's the only way to meet the performance requirements.
|
// determines it's the only way to meet the performance requirements.
|
||||||
//
|
//
|
||||||
|
// With the Android 12 update, Sabrina now uses HEVC (with RFI) based upon FEATURE_LowLatency
|
||||||
|
// support, which provides equivalent latency to H.264 now.
|
||||||
|
//
|
||||||
// FIXME: Should we do this for all Amlogic S905X SoCs?
|
// FIXME: Should we do this for all Amlogic S905X SoCs?
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
||||||
whitelistedHevcDecoders.add("omx.amlogic");
|
whitelistedHevcDecoders.add("omx.amlogic");
|
||||||
@@ -715,19 +711,12 @@ public class MediaCodecHelper {
|
|||||||
// HEVC decoder present is fast and modern enough for streaming.
|
// HEVC decoder present is fast and modern enough for streaming.
|
||||||
//
|
//
|
||||||
// [5.3/H-1-1] MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load.
|
// [5.3/H-1-1] MUST NOT drop more than 2 frames in 10 seconds (i.e less than 0.333 percent frame drop) for a 1080p 60 fps video session under load.
|
||||||
//
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
// NB: We use reflection here because this field seems to be absent on Amazon Fire OS devices
|
LimeLog.info("Media performance class: " + Build.VERSION.MEDIA_PERFORMANCE_CLASS);
|
||||||
try {
|
if (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S) {
|
||||||
Field mediaClassField = Build.VERSION.class.getDeclaredField("MEDIA_PERFORMANCE_CLASS");
|
LimeLog.info("Allowing HEVC based on media performance class");
|
||||||
int mediaClass = mediaClassField.getInt(null);
|
|
||||||
if (mediaClass >= Build.VERSION_CODES.S) {
|
|
||||||
LimeLog.info("Allowing HEVC based on media performance class: " + mediaClass);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
LimeLog.info("Build.VERSION.MEDIA_PERFORMANCE_CLASS not present");
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the decoder supports FEATURE_LowLatency, we will assume it is fast and modern enough
|
// If the decoder supports FEATURE_LowLatency, we will assume it is fast and modern enough
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ public class ComputerManagerService extends Service {
|
|||||||
private boolean pollingActive = false;
|
private boolean pollingActive = false;
|
||||||
private final Lock defaultNetworkLock = new ReentrantLock();
|
private final Lock defaultNetworkLock = new ReentrantLock();
|
||||||
|
|
||||||
|
private ConnectivityManager.NetworkCallback networkCallback;
|
||||||
|
|
||||||
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
||||||
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
||||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||||
@@ -553,7 +555,8 @@ public class ComputerManagerService extends Service {
|
|||||||
// If the current address's port number matches the active address's port number, we can also assume
|
// If the current address's port number matches the active address's port number, we can also assume
|
||||||
// the HTTPS port will also match. This assumption is currently safe because Sunshine sets all ports
|
// the HTTPS port will also match. This assumption is currently safe because Sunshine sets all ports
|
||||||
// as offsets from the base HTTP port and doesn't allow custom HttpsPort responses for WAN vs LAN.
|
// as offsets from the base HTTP port and doesn't allow custom HttpsPort responses for WAN vs LAN.
|
||||||
boolean portMatchesActiveAddress = details.activeAddress != null && address.port == details.activeAddress.port;
|
boolean portMatchesActiveAddress = details.state == ComputerDetails.State.ONLINE &&
|
||||||
|
details.activeAddress != null && address.port == details.activeAddress.port;
|
||||||
|
|
||||||
NvHTTP http = new NvHTTP(address, portMatchesActiveAddress ? details.httpsPort : 0, idManager.getUniqueId(), details.serverCert,
|
NvHTTP http = new NvHTTP(address, portMatchesActiveAddress ? details.httpsPort : 0, idManager.getUniqueId(), details.serverCert,
|
||||||
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
||||||
@@ -743,10 +746,49 @@ public class ComputerManagerService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
releaseLocalDatabaseReference();
|
releaseLocalDatabaseReference();
|
||||||
|
|
||||||
|
// Monitor for network changes to invalidate our PC state
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
networkCallback = new ConnectivityManager.NetworkCallback() {
|
||||||
|
@Override
|
||||||
|
public void onAvailable(Network network) {
|
||||||
|
LimeLog.info("Resetting PC state for new available network");
|
||||||
|
synchronized (pollingTuples) {
|
||||||
|
for (PollingTuple tuple : pollingTuples) {
|
||||||
|
tuple.computer.state = ComputerDetails.State.UNKNOWN;
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyComputerUpdated(tuple.computer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLost(Network network) {
|
||||||
|
LimeLog.info("Offlining PCs due to network loss");
|
||||||
|
synchronized (pollingTuples) {
|
||||||
|
for (PollingTuple tuple : pollingTuples) {
|
||||||
|
tuple.computer.state = ComputerDetails.State.OFFLINE;
|
||||||
|
if (listener != null) {
|
||||||
|
listener.notifyComputerUpdated(tuple.computer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
connMgr.registerDefaultNetworkCallback(networkCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
connMgr.unregisterNetworkCallback(networkCallback);
|
||||||
|
}
|
||||||
|
|
||||||
if (discoveryBinder != null) {
|
if (discoveryBinder != null) {
|
||||||
// Unbind from the discovery service
|
// Unbind from the discovery service
|
||||||
unbindService(discoveryServiceConnection);
|
unbindService(discoveryServiceConnection);
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ public class ComputerDetails {
|
|||||||
throw new IllegalArgumentException("Invalid port");
|
throw new IllegalArgumentException("Invalid port");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this was an escaped IPv6 address, remove the brackets
|
||||||
|
if (address.startsWith("[") && address.endsWith("]")) {
|
||||||
|
address = address.substring(1, address.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@@ -40,7 +45,14 @@ public class ComputerDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return address + ":" + port;
|
if (address.contains(":")) {
|
||||||
|
// IPv6
|
||||||
|
return "[" + address + "]:" + port;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// IPv4 and hostnames
|
||||||
|
return address + ":" + port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ public class KeyboardPacket {
|
|||||||
public static final byte MODIFIER_SHIFT = 0x01;
|
public static final byte MODIFIER_SHIFT = 0x01;
|
||||||
public static final byte MODIFIER_CTRL = 0x02;
|
public static final byte MODIFIER_CTRL = 0x02;
|
||||||
public static final byte MODIFIER_ALT = 0x04;
|
public static final byte MODIFIER_ALT = 0x04;
|
||||||
}
|
public static final byte MODIFIER_META = 0x08;
|
||||||
|
}
|
||||||
@@ -98,8 +98,31 @@ public class AddComputerManually extends Activity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private URI parseRawUserInputToUri(String rawUserInput) {
|
||||||
|
try {
|
||||||
|
// Try adding a scheme and parsing the remaining input.
|
||||||
|
// This handles input like 127.0.0.1:47989, [::1], [::1]:47989, and 127.0.0.1.
|
||||||
|
URI uri = new URI("moonlight://" + rawUserInput);
|
||||||
|
if (uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException ignored) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Attempt to escape the input as an IPv6 literal.
|
||||||
|
// This handles input like ::1.
|
||||||
|
URI uri = new URI("moonlight://[" + rawUserInput + "]");
|
||||||
|
if (uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException ignored) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void doAddPc(String rawUserInput) throws InterruptedException {
|
private void doAddPc(String rawUserInput) throws InterruptedException {
|
||||||
boolean wrongSiteLocal = false;
|
boolean wrongSiteLocal = false;
|
||||||
|
boolean invalidInput = false;
|
||||||
boolean success;
|
boolean success;
|
||||||
int portTestResult;
|
int portTestResult;
|
||||||
|
|
||||||
@@ -109,26 +132,26 @@ public class AddComputerManually extends Activity {
|
|||||||
try {
|
try {
|
||||||
ComputerDetails details = new ComputerDetails();
|
ComputerDetails details = new ComputerDetails();
|
||||||
|
|
||||||
// Use URI-style parsing for the host address input
|
// Check if we parsed a host address successfully
|
||||||
URI uri = new URI("moonlight://" + rawUserInput);
|
URI uri = parseRawUserInputToUri(rawUserInput);
|
||||||
|
if (uri != null && uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||||
|
String host = uri.getHost();
|
||||||
|
int port = uri.getPort();
|
||||||
|
|
||||||
String host = uri.getHost();
|
// If a port was not specified, use the default
|
||||||
int port = uri.getPort();
|
if (port == -1) {
|
||||||
|
port = NvHTTP.DEFAULT_HTTP_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
// URI allows empty hosts, but we don't want that
|
details.manualAddress = new ComputerDetails.AddressTuple(host, port);
|
||||||
if (host == null || host.isEmpty()) {
|
success = managerBinder.addComputerBlocking(details);
|
||||||
throw new URISyntaxException(rawUserInput, "Host failed to parse");
|
if (!success){
|
||||||
}
|
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
||||||
|
}
|
||||||
// If a port was not specified, use the default
|
} else {
|
||||||
if (port == -1) {
|
// Invalid user input
|
||||||
port = NvHTTP.DEFAULT_HTTP_PORT;
|
success = false;
|
||||||
}
|
invalidInput = true;
|
||||||
|
|
||||||
details.manualAddress = new ComputerDetails.AddressTuple(host, port);
|
|
||||||
success = managerBinder.addComputerBlocking(details);
|
|
||||||
if (!success){
|
|
||||||
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// Propagate the InterruptedException to the caller for proper handling
|
// Propagate the InterruptedException to the caller for proper handling
|
||||||
@@ -139,13 +162,11 @@ public class AddComputerManually extends Activity {
|
|||||||
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
success = false;
|
success = false;
|
||||||
} catch (URISyntaxException e) {
|
invalidInput = true;
|
||||||
e.printStackTrace();
|
|
||||||
success = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the SpinnerDialog open while testing connectivity
|
// Keep the SpinnerDialog open while testing connectivity
|
||||||
if (!success && !wrongSiteLocal) {
|
if (!success && !wrongSiteLocal && !invalidInput) {
|
||||||
// Run the test before dismissing the spinner because it can take a few seconds.
|
// Run the test before dismissing the spinner because it can take a few seconds.
|
||||||
portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443,
|
portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443,
|
||||||
MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989);
|
MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989);
|
||||||
@@ -156,7 +177,10 @@ public class AddComputerManually extends Activity {
|
|||||||
|
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
|
|
||||||
if (wrongSiteLocal) {
|
if (invalidInput) {
|
||||||
|
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_unknown_host), false);
|
||||||
|
}
|
||||||
|
else if (wrongSiteLocal) {
|
||||||
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
|
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
|
||||||
}
|
}
|
||||||
else if (!success) {
|
else if (!success) {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class PreferenceConfiguration {
|
|||||||
private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode";
|
private static final String ABSOLUTE_MOUSE_MODE_PREF_STRING = "checkbox_absolute_mouse_mode";
|
||||||
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
|
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
|
||||||
private static final String REDUCE_REFRESH_RATE_PREF_STRING = "checkbox_reduce_refresh_rate";
|
private static final String REDUCE_REFRESH_RATE_PREF_STRING = "checkbox_reduce_refresh_rate";
|
||||||
|
private static final String FULL_RANGE_PREF_STRING = "checkbox_full_range";
|
||||||
|
|
||||||
static final String DEFAULT_RESOLUTION = "1280x720";
|
static final String DEFAULT_RESOLUTION = "1280x720";
|
||||||
static final String DEFAULT_FPS = "60";
|
static final String DEFAULT_FPS = "60";
|
||||||
@@ -80,6 +81,7 @@ public class PreferenceConfiguration {
|
|||||||
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
||||||
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
||||||
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
|
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
|
||||||
|
private static final boolean DEFAULT_FULL_RANGE = 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;
|
||||||
@@ -90,15 +92,15 @@ public class PreferenceConfiguration {
|
|||||||
public static final int FRAME_PACING_CAP_FPS = 2;
|
public static final int FRAME_PACING_CAP_FPS = 2;
|
||||||
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
||||||
|
|
||||||
public static final String RES_360P = "s_640x360";
|
public static final String RES_360P = "640x360";
|
||||||
public static final String RES_480P = "s_854x480";
|
public static final String RES_480P = "854x480";
|
||||||
public static final String RES_720P = "s_1280x720";
|
public static final String RES_720P = "1280x720";
|
||||||
public static final String RES_1080P = "s_1920x1080";
|
public static final String RES_1080P = "1920x1080";
|
||||||
public static final String RES_1440P = "s_2560x1440";
|
public static final String RES_1440P = "2560x1440";
|
||||||
public static final String RES_4K = "s_3840x2160";
|
public static final String RES_4K = "3840x2160";
|
||||||
|
public static final String RES_NATIVE = "Native";
|
||||||
|
|
||||||
public StreamResolution resolution;
|
public int width, height, fps;
|
||||||
public int fps;
|
|
||||||
public int bitrate;
|
public int bitrate;
|
||||||
public int videoFormat;
|
public int videoFormat;
|
||||||
public int deadzonePercentage;
|
public int deadzonePercentage;
|
||||||
@@ -124,10 +126,9 @@ public class PreferenceConfiguration {
|
|||||||
public boolean absoluteMouseMode;
|
public boolean absoluteMouseMode;
|
||||||
public boolean enableAudioFx;
|
public boolean enableAudioFx;
|
||||||
public boolean reduceRefreshRate;
|
public boolean reduceRefreshRate;
|
||||||
|
public boolean fullRange;
|
||||||
|
|
||||||
// This is used only for migration to the new type code format of resolution strings
|
public static boolean isNativeResolution(int width, int height) {
|
||||||
// It doesn't properly handle custom resolutions!
|
|
||||||
private static boolean legacyIsNativeResolution(int width, int height) {
|
|
||||||
// It's not a native resolution if it matches an existing resolution option
|
// It's not a native resolution if it matches an existing resolution option
|
||||||
if (width == 640 && height == 360) {
|
if (width == 640 && height == 360) {
|
||||||
return false;
|
return false;
|
||||||
@@ -177,47 +178,59 @@ public class PreferenceConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String convertFromLegacyResolutionString(String resString) {
|
private static String convertFromLegacyResolutionString(String resString) {
|
||||||
if (!resString.contains("x")) {
|
if (resString.equalsIgnoreCase("360p")) {
|
||||||
// Convert from hardcoded strings to strings with dimensions embedded
|
return RES_360P;
|
||||||
if (resString.equalsIgnoreCase("360p")) {
|
|
||||||
return RES_360P;
|
|
||||||
}
|
|
||||||
else if (resString.equalsIgnoreCase("480p")) {
|
|
||||||
return RES_480P;
|
|
||||||
}
|
|
||||||
else if (resString.equalsIgnoreCase("720p")) {
|
|
||||||
return RES_720P;
|
|
||||||
}
|
|
||||||
else if (resString.equalsIgnoreCase("1080p")) {
|
|
||||||
return RES_1080P;
|
|
||||||
}
|
|
||||||
else if (resString.equalsIgnoreCase("1440p")) {
|
|
||||||
return RES_1440P;
|
|
||||||
}
|
|
||||||
else if (resString.equalsIgnoreCase("4K")) {
|
|
||||||
return RES_4K;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Should be unreachable
|
|
||||||
return RES_720P;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Character.isDigit(resString.charAt(0))) {
|
else if (resString.equalsIgnoreCase("480p")) {
|
||||||
// Convert to type code prefix format
|
return RES_480P;
|
||||||
String[] dims = resString.split("x");
|
}
|
||||||
int width = Integer.parseInt(dims[0]);
|
else if (resString.equalsIgnoreCase("720p")) {
|
||||||
int height = Integer.parseInt(dims[1]);
|
return RES_720P;
|
||||||
return new StreamResolution(width, height,
|
}
|
||||||
legacyIsNativeResolution(width, height) ? StreamResolution.ResolutionType.NATIVE : StreamResolution.ResolutionType.STANDARD)
|
else if (resString.equalsIgnoreCase("1080p")) {
|
||||||
.toPrefString();
|
return RES_1080P;
|
||||||
|
}
|
||||||
|
else if (resString.equalsIgnoreCase("1440p")) {
|
||||||
|
return RES_1440P;
|
||||||
|
}
|
||||||
|
else if (resString.equalsIgnoreCase("4K")) {
|
||||||
|
return RES_4K;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return resString;
|
// Should be unreachable
|
||||||
|
return RES_720P;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getWidthFromResolutionString(String resString) {
|
||||||
|
return Integer.parseInt(resString.split("x")[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getHeightFromResolutionString(String resString) {
|
||||||
|
return Integer.parseInt(resString.split("x")[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getResolutionString(int width, int height) {
|
||||||
|
switch (height) {
|
||||||
|
case 360:
|
||||||
|
return RES_360P;
|
||||||
|
case 480:
|
||||||
|
return RES_480P;
|
||||||
|
default:
|
||||||
|
case 720:
|
||||||
|
return RES_720P;
|
||||||
|
case 1080:
|
||||||
|
return RES_1080P;
|
||||||
|
case 1440:
|
||||||
|
return RES_1440P;
|
||||||
|
case 2160:
|
||||||
|
return RES_4K;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getDefaultBitrate(String resString, String fpsString) {
|
public static int getDefaultBitrate(String resString, String fpsString) {
|
||||||
StreamResolution res = new StreamResolution(resString);
|
int width = getWidthFromResolutionString(resString);
|
||||||
|
int height = getHeightFromResolutionString(resString);
|
||||||
int fps = Integer.parseInt(fpsString);
|
int fps = Integer.parseInt(fpsString);
|
||||||
|
|
||||||
// This table prefers 16:10 resolutions because they are
|
// This table prefers 16:10 resolutions because they are
|
||||||
@@ -228,23 +241,23 @@ public class PreferenceConfiguration {
|
|||||||
// This logic is shamelessly stolen from Moonlight Qt:
|
// This logic is shamelessly stolen from Moonlight Qt:
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
||||||
|
|
||||||
if (res.width * res.height <= 640 * 360) {
|
if (width * height <= 640 * 360) {
|
||||||
return (int)(1000 * (fps / 30.0));
|
return (int)(1000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
else if (res.width * res.height <= 854 * 480) {
|
else if (width * height <= 854 * 480) {
|
||||||
return (int)(1500 * (fps / 30.0));
|
return (int)(1500 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
// This covers 1280x720 and 1280x800 too
|
// This covers 1280x720 and 1280x800 too
|
||||||
else if (res.width * res.height <= 1366 * 768) {
|
else if (width * height <= 1366 * 768) {
|
||||||
return (int)(5000 * (fps / 30.0));
|
return (int)(5000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
else if (res.width * res.height <= 1920 * 1200) {
|
else if (width * height <= 1920 * 1200) {
|
||||||
return (int)(10000 * (fps / 30.0));
|
return (int)(10000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
else if (res.width * res.height <= 2560 * 1600) {
|
else if (width * height <= 2560 * 1600) {
|
||||||
return (int)(20000 * (fps / 30.0));
|
return (int)(20000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
else /* if (res.width * res.height <= 3840 * 2160) */ {
|
else /* if (width * height <= 3840 * 2160) */ {
|
||||||
return (int)(40000 * (fps / 30.0));
|
return (int)(40000 * (fps / 30.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,6 +351,7 @@ public class PreferenceConfiguration {
|
|||||||
.remove(VIDEO_FORMAT_PREF_STRING)
|
.remove(VIDEO_FORMAT_PREF_STRING)
|
||||||
.remove(ENABLE_HDR_PREF_STRING)
|
.remove(ENABLE_HDR_PREF_STRING)
|
||||||
.remove(UNLOCK_FPS_STRING)
|
.remove(UNLOCK_FPS_STRING)
|
||||||
|
.remove(FULL_RANGE_PREF_STRING)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,46 +385,55 @@ public class PreferenceConfiguration {
|
|||||||
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
||||||
if (str != null) {
|
if (str != null) {
|
||||||
if (str.equals("360p30")) {
|
if (str.equals("360p30")) {
|
||||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
config.width = 640;
|
||||||
|
config.height = 360;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("360p60")) {
|
else if (str.equals("360p60")) {
|
||||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
config.width = 640;
|
||||||
|
config.height = 360;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("720p30")) {
|
else if (str.equals("720p30")) {
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("720p60")) {
|
else if (str.equals("720p60")) {
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("1080p30")) {
|
else if (str.equals("1080p30")) {
|
||||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("1080p60")) {
|
else if (str.equals("1080p60")) {
|
||||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1920;
|
||||||
|
config.height = 1080;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else if (str.equals("4K30")) {
|
else if (str.equals("4K30")) {
|
||||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
config.fps = 30;
|
config.fps = 30;
|
||||||
}
|
}
|
||||||
else if (str.equals("4K60")) {
|
else if (str.equals("4K60")) {
|
||||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
config.width = 3840;
|
||||||
|
config.height = 2160;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Should never get here
|
// Should never get here
|
||||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
config.width = 1280;
|
||||||
|
config.height = 720;
|
||||||
config.fps = 60;
|
config.fps = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
prefs.edit()
|
prefs.edit()
|
||||||
.remove(LEGACY_RES_FPS_PREF_STRING)
|
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||||
.putString(RESOLUTION_PREF_STRING, config.resolution.toPrefString())
|
.putString(RESOLUTION_PREF_STRING, getResolutionString(config.width, config.height))
|
||||||
.putString(FPS_PREF_STRING, ""+config.fps)
|
.putString(FPS_PREF_STRING, ""+config.fps)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
@@ -419,12 +442,13 @@ public class PreferenceConfiguration {
|
|||||||
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
||||||
|
|
||||||
// Convert legacy resolution strings to the new style
|
// Convert legacy resolution strings to the new style
|
||||||
if (Character.isDigit(resStr.charAt(0)) || !resStr.contains("x")) {
|
if (!resStr.contains("x")) {
|
||||||
resStr = PreferenceConfiguration.convertFromLegacyResolutionString(resStr);
|
resStr = PreferenceConfiguration.convertFromLegacyResolutionString(resStr);
|
||||||
prefs.edit().putString(RESOLUTION_PREF_STRING, resStr).apply();
|
prefs.edit().putString(RESOLUTION_PREF_STRING, resStr).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
config.resolution = new StreamResolution(resStr);
|
config.width = PreferenceConfiguration.getWidthFromResolutionString(resStr);
|
||||||
|
config.height = PreferenceConfiguration.getHeightFromResolutionString(resStr);
|
||||||
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,115 +509,8 @@ public class PreferenceConfiguration {
|
|||||||
config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE);
|
config.absoluteMouseMode = prefs.getBoolean(ABSOLUTE_MOUSE_MODE_PREF_STRING, DEFAULT_ABSOLUTE_MOUSE_MODE);
|
||||||
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
|
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
|
||||||
config.reduceRefreshRate = prefs.getBoolean(REDUCE_REFRESH_RATE_PREF_STRING, DEFAULT_REDUCE_REFRESH_RATE);
|
config.reduceRefreshRate = prefs.getBoolean(REDUCE_REFRESH_RATE_PREF_STRING, DEFAULT_REDUCE_REFRESH_RATE);
|
||||||
|
config.fullRange = prefs.getBoolean(FULL_RANGE_PREF_STRING, DEFAULT_FULL_RANGE);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StreamResolution {
|
|
||||||
public int width;
|
|
||||||
public int height;
|
|
||||||
public ResolutionType type;
|
|
||||||
public boolean portrait;
|
|
||||||
public boolean fullScreen;
|
|
||||||
|
|
||||||
private static final char RES_START_DELIMITER = '_';
|
|
||||||
private static final char RES_DIM_DELIMITER = 'x';
|
|
||||||
|
|
||||||
private static final char TYPE_CODE_STANDARD = 's';
|
|
||||||
private static final char TYPE_CODE_NATIVE = 'n';
|
|
||||||
|
|
||||||
private static final char OPTION_CODE_PORTRAIT = 'p';
|
|
||||||
private static final char OPTION_CODE_FULL_SCREEN = 'f';
|
|
||||||
|
|
||||||
public enum ResolutionType {
|
|
||||||
STANDARD,
|
|
||||||
NATIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
private StreamResolution(int width, int height, ResolutionType type) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
// Just guess for the options, since we don't know for sure
|
|
||||||
this.portrait = height > width;
|
|
||||||
this.fullScreen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamResolution(int width, int height, ResolutionType type, boolean portrait, boolean fullScreen) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.type = type;
|
|
||||||
this.portrait = portrait;
|
|
||||||
this.fullScreen = fullScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
StreamResolution(String resString) {
|
|
||||||
// Type code is the first character in the string
|
|
||||||
switch (resString.charAt(0)) {
|
|
||||||
case TYPE_CODE_NATIVE:
|
|
||||||
this.type = StreamResolution.ResolutionType.NATIVE;
|
|
||||||
break;
|
|
||||||
case TYPE_CODE_STANDARD:
|
|
||||||
this.type = StreamResolution.ResolutionType.STANDARD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid type code: " + resString.charAt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse options until we reach the resolution start delimiter
|
|
||||||
int currentIndex = 1;
|
|
||||||
while (resString.charAt(currentIndex) != RES_START_DELIMITER) {
|
|
||||||
switch (resString.charAt(currentIndex)) {
|
|
||||||
case OPTION_CODE_PORTRAIT:
|
|
||||||
portrait = true;
|
|
||||||
break;
|
|
||||||
case OPTION_CODE_FULL_SCREEN:
|
|
||||||
fullScreen = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid option code: " + resString.charAt(currentIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the type code before splitting
|
|
||||||
String[] dims = resString.substring(currentIndex).split(""+RES_DIM_DELIMITER);
|
|
||||||
this.width = Integer.parseInt(dims[0]);
|
|
||||||
this.height = Integer.parseInt(dims[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toPrefString() {
|
|
||||||
String str = "";
|
|
||||||
|
|
||||||
// Start with the type code
|
|
||||||
switch (type) {
|
|
||||||
case NATIVE:
|
|
||||||
str += TYPE_CODE_NATIVE;
|
|
||||||
break;
|
|
||||||
case STANDARD:
|
|
||||||
str += TYPE_CODE_STANDARD;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Invalid type: "+type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now any option codes that may apply
|
|
||||||
if (portrait) {
|
|
||||||
str += OPTION_CODE_PORTRAIT;
|
|
||||||
}
|
|
||||||
if (fullScreen) {
|
|
||||||
str += OPTION_CODE_FULL_SCREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// And finally the dimensions
|
|
||||||
str += RES_START_DELIMITER;
|
|
||||||
str += width;
|
|
||||||
str += RES_DIM_DELIMITER;
|
|
||||||
str += height;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -122,49 +122,44 @@ public class StreamSettings extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragment {
|
public static class SettingsFragment extends PreferenceFragment {
|
||||||
|
private int nativeResolutionStartIndex = Integer.MAX_VALUE;
|
||||||
|
|
||||||
private void setValue(String preferenceKey, String value) {
|
private void setValue(String preferenceKey, String value) {
|
||||||
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||||
|
|
||||||
pref.setValue(value);
|
pref.setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addResolutionEntry(int width, int height, PreferenceConfiguration.StreamResolution.ResolutionType type,
|
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) {
|
||||||
boolean insetsRemoved, boolean portrait) {
|
|
||||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
||||||
PreferenceConfiguration.StreamResolution newRes =
|
|
||||||
new PreferenceConfiguration.StreamResolution(width, height, type, portrait, insetsRemoved);
|
|
||||||
|
|
||||||
String newName;
|
String newName;
|
||||||
|
|
||||||
if (type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
if (insetsRemoved) {
|
||||||
if (insetsRemoved) {
|
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
||||||
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newName = getResources().getString(R.string.resolution_prefix_native);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PreferenceConfiguration.isSquarishScreen(width, height)) {
|
|
||||||
if (portrait) {
|
|
||||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
newName = null;
|
newName = getResources().getString(R.string.resolution_prefix_native);
|
||||||
}
|
}
|
||||||
|
|
||||||
newName += " ("+width+"x"+height+")";
|
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||||
|
if (portrait) {
|
||||||
|
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newName += " ("+nativeWidth+"x"+nativeHeight+")";
|
||||||
|
|
||||||
|
String newValue = nativeWidth+"x"+nativeHeight;
|
||||||
|
|
||||||
CharSequence[] values = pref.getEntryValues();
|
CharSequence[] values = pref.getEntryValues();
|
||||||
|
|
||||||
// Check if the new resolution is already present
|
// Check if the native resolution is already present
|
||||||
for (CharSequence value : values) {
|
for (CharSequence value : values) {
|
||||||
PreferenceConfiguration.StreamResolution existingResolution = new PreferenceConfiguration.StreamResolution(value.toString());
|
if (newValue.equals(value.toString())) {
|
||||||
if (existingResolution.width == newRes.width && existingResolution.height == newRes.height) {
|
|
||||||
// It is present in the default list, so don't add it again
|
// It is present in the default list, so don't add it again
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -173,23 +168,23 @@ public class StreamSettings extends Activity {
|
|||||||
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
||||||
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
|
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
|
||||||
|
|
||||||
// Add the new resolution option
|
// Add the new native option
|
||||||
newEntries[newEntries.length - 1] = newName;
|
newEntries[newEntries.length - 1] = newName;
|
||||||
newValues[newValues.length - 1] = newRes.toPrefString();
|
newValues[newValues.length - 1] = newValue;
|
||||||
|
|
||||||
pref.setEntries(newEntries);
|
pref.setEntries(newEntries);
|
||||||
pref.setEntryValues(newValues);
|
pref.setEntryValues(newValues);
|
||||||
|
|
||||||
|
if (newValues.length - 1 < nativeResolutionStartIndex) {
|
||||||
|
nativeResolutionStartIndex = newValues.length - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
||||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||||
addResolutionEntry(nativeHeight, nativeWidth,
|
addNativeResolutionEntry(nativeHeight, nativeWidth, insetsRemoved, true);
|
||||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
|
||||||
insetsRemoved, true);
|
|
||||||
}
|
}
|
||||||
addResolutionEntry(nativeWidth, nativeHeight,
|
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
|
||||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
|
||||||
insetsRemoved, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||||
@@ -613,10 +608,20 @@ public class StreamSettings extends Activity {
|
|||||||
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;
|
||||||
PreferenceConfiguration.StreamResolution resolution = new PreferenceConfiguration.StreamResolution(valueStr);
|
|
||||||
|
// Detect if this value is the native resolution option
|
||||||
|
CharSequence[] values = ((ListPreference)preference).getEntryValues();
|
||||||
|
boolean isNativeRes = true;
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
// Look for a match prior to the start of the native resolution entries
|
||||||
|
if (valueStr.equals(values[i].toString()) && i < nativeResolutionStartIndex) {
|
||||||
|
isNativeRes = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If this is native resolution, show the warning dialog
|
// If this is native resolution, show the warning dialog
|
||||||
if (resolution.type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
if (isNativeRes) {
|
||||||
Dialog.displayDialog(getActivity(),
|
Dialog.displayDialog(getActivity(),
|
||||||
getResources().getString(R.string.title_native_res_dialog),
|
getResources().getString(R.string.title_native_res_dialog),
|
||||||
getResources().getString(R.string.text_native_res_dialog),
|
getResources().getString(R.string.text_native_res_dialog),
|
||||||
|
|||||||
Submodule app/src/main/jni/moonlight-core/moonlight-common-c updated: 50c0a51b10...8169a31ecc.
@@ -1,2 +1,251 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources></resources>
|
<resources>
|
||||||
|
<string name="conn_establishing_title">Připojování</string>
|
||||||
|
<string name="conn_metered">Varování: Vaše aktivní připojení je měřené!</string>
|
||||||
|
<string name="conn_error_msg">Spouštění se nezdařilo</string>
|
||||||
|
<string name="conn_client_latency_hw">zpoždění hardwarového dekodéru:</string>
|
||||||
|
<string name="conn_terminated_title">Spojení ukončeno</string>
|
||||||
|
<string name="resolution_prefix_native_fullscreen">Nativní celá obrazovka</string>
|
||||||
|
<string name="summary_checkbox_enable_audiofx">Umožňuje fungování zvukových efektů během streamování, ale může zvýšit zpoždění zvuku</string>
|
||||||
|
<string name="early_termination_error">Na hostitelském PC se něco pokazilo při spouštění streamu.
|
||||||
|
\n
|
||||||
|
\nUjistěte se, že na hostitelském počítači neběží žádný obsah chráněný DRM. Můžete také zkusit restartovat hostitelský PC.
|
||||||
|
\n
|
||||||
|
\nPokud problém přetrvává, zkuste přeinstalovat ovladače GPU a GeForce Experience.</string>
|
||||||
|
<string name="wol_waking_pc">Probouzení PC…</string>
|
||||||
|
<string name="nettest_text_success">Vypadá to, že vaše síť Moonlight neblokuje. Pokud máte i tak potíže s připojením, zkontrolujte nastavení firewallu vašeho PC.
|
||||||
|
\n
|
||||||
|
\nPokud se pokoušíte streamovat po internetu, nainstalujte si na svůj počítač Moonlight Internet Hosting Tool a spusťte přiložený program Internet Streaming Tester pro kontrolu vašeho připojení k Internetu.</string>
|
||||||
|
<string name="error_unknown_host">Nezdařilo se zjistit hostitele</string>
|
||||||
|
<string name="nettest_text_waiting">Moonlight testuje vaše síťové připojení, aby zjistil, jestli je NVIDIA GameStream zablokován.
|
||||||
|
\n
|
||||||
|
\nTo může chvilku zabrat…</string>
|
||||||
|
<string name="nettest_title_waiting">Testování připojení k síti</string>
|
||||||
|
<string name="pairing">Párování…</string>
|
||||||
|
<string name="pair_pc_offline">Počítač je offline</string>
|
||||||
|
<string name="unpairing">Rušení párování…</string>
|
||||||
|
<string name="unpair_success">Párování úspěšně zrušeno</string>
|
||||||
|
<string name="unpair_error">Zařízení nebylo spárováno</string>
|
||||||
|
<string name="error_manager_not_running">Služba ComputerManager neběží. Vyčkejte prosím chvíli nebo restartujte aplikaci.</string>
|
||||||
|
<string name="error_pc_offline">Počítač je offline</string>
|
||||||
|
<string name="unpair_fail">Zrušení párování se nezdařilo</string>
|
||||||
|
<string name="error_404">GFE vrátilo HTTP chybu 404. Ujistěte se, že vaše PC má podporované GPU. Tato chyba může být způsobena i použitím softwaru pro vzdálenou plochu. Zkuste restartovat počítač, nebo přeinstalujte GFE.</string>
|
||||||
|
<string name="title_decoding_error">Dekodér videa spadnul</string>
|
||||||
|
<string name="error_usb_prohibited">Správce zařízení neumožňuje přístup k USB. Zkontrolujte nastavení Knoxu nebo MDM.</string>
|
||||||
|
<string name="message_decoding_error">Moonlight spadnul kvůli nekompatibilnímu video dekodéru na tomto zařízení. Ujistěte se, že je GeForce Experience na vašem PC aktualizováno na nejnovější verzi. Zkuste upravit nastavení streamování, pokud aplikace padá opakovaně.</string>
|
||||||
|
<string name="message_decoding_reset">Video dekodér vašeho zařízení při současných nastaveních streamování padá. Vaše nastavení streamování byla resetována na výchozí.</string>
|
||||||
|
<string name="video_decoder_init_failed">Nezdařilo se spustit video dekodér. Vaše zařízení nemusí podporovat zvolené rozlišení nebo snímkovou frekvenci.</string>
|
||||||
|
<string name="no_video_received_error">Od hostitele nebylo přijato žádné video.</string>
|
||||||
|
<string name="no_frame_received_error">Vaše připojení k síti není dost rychlé. Zkuste snížit datový tok videa nebo použijte rychlejší připojení.</string>
|
||||||
|
<string name="applist_menu_hide_app">Skrýt aplikaci</string>
|
||||||
|
<string name="title_add_pc">Přidat PC ručně</string>
|
||||||
|
<string name="title_audio_config_list">Konfigurace prostorového zvuku</string>
|
||||||
|
<string name="searching_pc">Hledání PC, na kterých běží GameStream...
|
||||||
|
\n
|
||||||
|
\nUjistěte se, že je GameStream povolen v záložce SHIELD v nastavení GeForce Experience.</string>
|
||||||
|
<string name="applist_menu_quit">Ukončit</string>
|
||||||
|
<string name="applist_menu_quit_and_start">Ukončit současnou hru a spustit</string>
|
||||||
|
<string name="applist_menu_cancel">Zrušit</string>
|
||||||
|
<string name="applist_menu_tv_channel">Přidat do kanálu</string>
|
||||||
|
<string name="applist_refresh_title">Seznam aplikací</string>
|
||||||
|
<string name="applist_menu_resume">Pokračovat</string>
|
||||||
|
<string name="applist_menu_details">Zobrazit detaily</string>
|
||||||
|
<string name="applist_menu_scut">Vytvořit zkratku</string>
|
||||||
|
<string name="addpc_success">Počítač přidán úspěšně</string>
|
||||||
|
<string name="applist_details_id">ID aplikace:</string>
|
||||||
|
<string name="addpc_fail">K zadanému počítači se nepodařilo připojit. Ujistěte se, že jsou ve firewallu povoleny nezbytné porty.</string>
|
||||||
|
<string name="addpc_enter_ip">Musíte zadat IP adresu</string>
|
||||||
|
<string name="title_native_res_dialog">Varování pro nativní rozlišení</string>
|
||||||
|
<string name="title_checkbox_vibrate_fallback">Emulovat podporu vibrací</string>
|
||||||
|
<string name="title_seekbar_deadzone">Upravit deadzone analogových páček</string>
|
||||||
|
<string name="check_ports_msg">Zkontrolujte svůj firewall a pravidla přesměrování pro tyto porty:</string>
|
||||||
|
<string name="conn_terminated_msg">Spojení bylo ukončeno</string>
|
||||||
|
<string name="ip_hint">IP adresa GeForce PC</string>
|
||||||
|
<string name="conn_hardware_latency">Průměrné zpoždění hardwarového dekodéru:</string>
|
||||||
|
<string name="conn_client_latency">Průměrné zpoždění při dekódování snímků:</string>
|
||||||
|
<string name="perf_overlay_netlatency">Průměrné zpoždění sítě: %1$d ms (odchylka: %2$d ms)</string>
|
||||||
|
<string name="perf_overlay_dectime">Průměrný čas pro dekódování: %1$.2f ms</string>
|
||||||
|
<string name="applist_connect_msg">Připojování k PC…</string>
|
||||||
|
<string name="title_checkbox_touchscreen_trackpad">Použít dotykový displej jako trackpad</string>
|
||||||
|
<string name="title_checkbox_multi_controller">Automatická detekce připojení herního ovladače</string>
|
||||||
|
<string name="summary_checkbox_multi_controller">Odškrtnutí této možnosti vynutí, aby byl herní ovladač vždy připojen</string>
|
||||||
|
<string name="summary_checkbox_xb1_driver">Povolí zabudovaný USB ovladač pro zařízení bez nativní podpory pro Xbox ovladač</string>
|
||||||
|
<string name="summary_checkbox_vibrate_fallback">Rozvibruje vaše zařízení pro emulaci vibrací ovladače, pokud je váš herní ovladač nepodporuje</string>
|
||||||
|
<string name="suffix_seekbar_deadzone">%</string>
|
||||||
|
<string name="summary_seekbar_deadzone">Poznámka: Některé hry mohou vynutit větší deadzone, než jaká je nastavena v Moonlightu.</string>
|
||||||
|
<string name="title_checkbox_xb1_driver">Xbox 360/One USB gamepad ovladač</string>
|
||||||
|
<string name="title_checkbox_usb_bind_all">Vynutit nativní podporu herního ovladače Xbox</string>
|
||||||
|
<string name="summary_checkbox_mouse_emulation">Dlouhým podržením tlačítka Start přepnete herní ovladač do režimu myši</string>
|
||||||
|
<string name="summary_checkbox_usb_bind_all">Použít USB ovladač Moonlightu pro všechny podporované gamepady, i když existuje nativní podpora pro Xbox ovladač</string>
|
||||||
|
<string name="title_checkbox_mouse_emulation">Emulace myši pomocí herního ovladače</string>
|
||||||
|
<string name="title_checkbox_flip_face_buttons">Přehodit tlačítka A/B, X/Y</string>
|
||||||
|
<string name="title_checkbox_absolute_mouse_mode">Režim myši pro vzdálenou plochu</string>
|
||||||
|
<string name="summary_checkbox_absolute_mouse_mode">Tímto zapnete přirozenější zrychlování myši pro použití ve vzdálené ploše, ale možnost je nekompatibilní se spoustou her.</string>
|
||||||
|
<string name="summary_osc_opacity">Zmenšete či zvětšete průhlednost ovladače na obrazovce</string>
|
||||||
|
<string name="summary_only_l3r3">Skryje veškerá virtuální tlačítka kromě L3 a R3</string>
|
||||||
|
<string name="category_ui_settings">Nastavení zobrazení</string>
|
||||||
|
<string name="suffix_osc_opacity">%</string>
|
||||||
|
<string name="title_setup_guide">Průvodce nastavením</string>
|
||||||
|
<string name="title_checkbox_disable_warnings">Zakázat varovací zprávy</string>
|
||||||
|
<string name="category_help">Nápověda</string>
|
||||||
|
<string name="summary_checkbox_disable_warnings">Zakáže varování o pomalém připojení během streamování</string>
|
||||||
|
<string name="title_disable_frame_drop">Nezahazovat snímky</string>
|
||||||
|
<string name="title_enable_perf_overlay">Zobrazit během streamování informace o výkonu</string>
|
||||||
|
<string name="summary_enable_perf_overlay">Zobrazit realtime informace o výkonu streamu během streamování</string>
|
||||||
|
<string name="resolution_4k">4K</string>
|
||||||
|
<string name="fps_30">30 FPS</string>
|
||||||
|
<string name="title_troubleshooting">Průvodce řešením problémů</string>
|
||||||
|
<string name="summary_troubleshooting">Zobrazit tipy pro diagnózu a opravu běžných problémů se streamováním</string>
|
||||||
|
<string name="resolution_720p">720p</string>
|
||||||
|
<string name="resolution_1080p">1080p</string>
|
||||||
|
<string name="resolution_1440p">1440p</string>
|
||||||
|
<string name="videoformat_hevcauto">Automaticky</string>
|
||||||
|
<string name="audioconf_71surround">7.1 prostorový zvuk</string>
|
||||||
|
<string name="pacing_balanced">Vyvážené</string>
|
||||||
|
<string name="pacing_smoothness">Preferovat plynulejší video (může výrazně zvýšit zpoždění)</string>
|
||||||
|
<string name="resolution_prefix_native_landscape">(na šířku)</string>
|
||||||
|
<string name="resolution_prefix_native_portrait">(na výšku)</string>
|
||||||
|
<string name="category_audio_settings">Nastavení zvuku</string>
|
||||||
|
<string name="title_checkbox_enable_audiofx">Povolit podporu systémového ekvalizéru</string>
|
||||||
|
<string name="category_input_settings">Nastavení vstupu</string>
|
||||||
|
<string name="summary_setup_guide">Zobrazit instrukce k nastavení vašeho herního PC pro streamování</string>
|
||||||
|
<string name="dialog_title_osc_opacity">Změnit průhlednost</string>
|
||||||
|
<string name="fps_60">60 FPS</string>
|
||||||
|
<string name="fps_90">90 FPS</string>
|
||||||
|
<string name="fps_120">120 FPS</string>
|
||||||
|
<string name="audioconf_stereo">Stereo</string>
|
||||||
|
<string name="audioconf_51surround">5.1 prostorový zvuk</string>
|
||||||
|
<string name="help_loading_msg">Načítání stránky s nápovědou…</string>
|
||||||
|
<string name="pcview_menu_header_online">Online</string>
|
||||||
|
<string name="pcview_menu_header_offline">Offline</string>
|
||||||
|
<string name="pcview_menu_header_unknown">Obnovování</string>
|
||||||
|
<string name="pcview_menu_app_list">Zobrazit všechny aplikace</string>
|
||||||
|
<string name="pcview_menu_pair_pc">Spárovat s PC</string>
|
||||||
|
<string name="pcview_menu_unpair_pc">Zrušit párování</string>
|
||||||
|
<string name="pcview_menu_send_wol">Poslat Wake-On-LAN požadavek</string>
|
||||||
|
<string name="pcview_menu_delete_pc">Smazat PC</string>
|
||||||
|
<string name="pcview_menu_test_network">Otestovat připojení k síti</string>
|
||||||
|
<string name="pcview_menu_details">Zobrazit detaily</string>
|
||||||
|
<string name="nettest_title_done">Test sítě dokončen</string>
|
||||||
|
<string name="nettest_text_inconclusive">Test sítě nemohl být proveden, protože se nezdařilo připoojení k žádným z testovacíh serverů Moonlight. Zkontrolujte své připojení k Internetu, nebo to zkuste znovu později.</string>
|
||||||
|
<string name="nettest_text_failure">Současná síť vašeho počítače nejspíš blokuje Moonlight. Streamování přes Internet nemusí během připojení k této síti fungovat.
|
||||||
|
\n
|
||||||
|
\nNásledující porty byly zablokovány:
|
||||||
|
\n</string>
|
||||||
|
<string name="nettest_text_blocked">Vaše současné připojení k síti blokuje Moonlight. Streamování přes Internet nemusí fungovat, dokud jste připojeni k této síti.</string>
|
||||||
|
<string name="pair_pc_ingame">Na počítači momentálně běží hra. Před párováním musíte hru zavřít.</string>
|
||||||
|
<string name="pair_pairing_title">Párování</string>
|
||||||
|
<string name="pair_pairing_msg">Vložte prosím následující PIN na cílovém PC:</string>
|
||||||
|
<string name="pair_incorrect_pin">Nesprávný PIN</string>
|
||||||
|
<string name="pair_fail">Párování selhalo</string>
|
||||||
|
<string name="pair_already_in_progress">Párování již probíhá</string>
|
||||||
|
<string name="wol_pc_online">Počítač je online</string>
|
||||||
|
<string name="wol_no_mac">Nezdařilo se probudit PC, protože GFE nezaslalo MAC adresu</string>
|
||||||
|
<string name="title_decoding_reset">Reset nastavení videa</string>
|
||||||
|
<string name="unable_to_pin_shortcut">Váš současný launcher neumožňuje vytváření zástupců.</string>
|
||||||
|
<string name="conn_establishing_msg">Připojování</string>
|
||||||
|
<string name="conn_starting">Spouštění</string>
|
||||||
|
<string name="conn_error_title">Chyba připojení</string>
|
||||||
|
<string name="frame_conversion_error">Hostitelský počítač hlásí fatální chybu enkódování videa.
|
||||||
|
\n
|
||||||
|
\nZkuste vypnout HDR, změňte rozlišení streamu nebo rozlišení displeje hostitelského PC.</string>
|
||||||
|
<string name="yes">Ano</string>
|
||||||
|
<string name="no">Ne</string>
|
||||||
|
<string name="lost_connection">Připojení k PC bylo ztraceno</string>
|
||||||
|
<string name="title_details">Detaily</string>
|
||||||
|
<string name="perf_overlay_renderingfps">Vykreslovací snímková frekvence: %1$.2f FPS</string>
|
||||||
|
<string name="perf_overlay_netdrops">Snímky zahozeny vašim připojením: %1$.2f%%</string>
|
||||||
|
<string name="applist_refresh_msg">Obnovování aplikací…</string>
|
||||||
|
<string name="applist_refresh_error_title">Chyba</string>
|
||||||
|
<string name="applist_refresh_error_msg">Nezdařilo se získat seznam aplikací</string>
|
||||||
|
<string name="applist_quit_app">Ukončování</string>
|
||||||
|
<string name="applist_quit_success">Úspěšně ukončeno</string>
|
||||||
|
<string name="applist_quit_fail">Ukončení se nezdařilo</string>
|
||||||
|
<string name="applist_quit_confirmation">Určitě chcete ukončit běžící aplikaci\? Neuložená data budou ztracena.</string>
|
||||||
|
<string name="msg_add_pc">Připojování k PC…</string>
|
||||||
|
<string name="addpc_unknown_host">Nezdařilo se připojit k adrese PC. Ujistěte se, že v adrese není překlep.</string>
|
||||||
|
<string name="addpc_wrong_sitelocal">Tahle adresa nevypadá správně. Musíte zadat veřejnou IP vašeho routeru, pokud chcete streamovat přes Internet.</string>
|
||||||
|
<string name="category_basic_settings">Základní nastavení</string>
|
||||||
|
<string name="title_resolution_list">Rozlišení videa</string>
|
||||||
|
<string name="summary_resolution_list">Zvyšte přo zlepšení ostrosti obrazu. Snižte pro lepší výkon na levnějších zařízeních nebo pomalejších sítích.</string>
|
||||||
|
<string name="summary_audio_config_list">Povolit 5.1 nebo 7.1 prostorový zvuk pro systémy domácího kina</string>
|
||||||
|
<string name="summary_checkbox_touchscreen_trackpad">Pokud je povoleno, dotykový displej funguje jako trackpad. Pokud je zakázáno, dotykový displej ovládá kurzor myši přímo.</string>
|
||||||
|
<string name="title_reset_osc">Vymazat uložené rozložení ovladače na obrazovce</string>
|
||||||
|
<string name="summary_reset_osc">Resetuje všechna nastavení ovladače na obrazovce na jejich výchozí velikost a pozici</string>
|
||||||
|
<string name="title_osc_opacity">Změnit průhlednost ovladače na obrazovce</string>
|
||||||
|
<string name="category_advanced_settings">Pokročilá nastavení</string>
|
||||||
|
<string name="title_unlock_fps">Odemknout všechny možné snímkové frekvence</string>
|
||||||
|
<string name="title_checkbox_reduce_refresh_rate">Povolit snížení obnovovací frekvence</string>
|
||||||
|
<string name="summary_checkbox_reduce_refresh_rate">Menší obnovovací frekvence displeje může šetřit energii výměnou za zvýšení zpoždění videa</string>
|
||||||
|
<string name="title_checkbox_mouse_nav_buttons">Povolit tlačítka myši zpět a vpřed</string>
|
||||||
|
<string name="summary_checkbox_mouse_nav_buttons">Povolení této možnosti může na některých pochybných zařízeních rozbít klikání pravým tlačítkem</string>
|
||||||
|
<string name="summary_checkbox_flip_face_buttons">Přehodí tlačítka A/B a X/Y na herním ovladači a instrukcích na obrazovce</string>
|
||||||
|
<string name="toast_reset_osc_success">Ovladač na obrazovce resetován</string>
|
||||||
|
<string name="dialog_title_reset_osc">Reset rozložení</string>
|
||||||
|
<string name="dialog_text_reset_osc">Jste si jisti, že chcete smazat vaše uložené rozložení ovladače\?</string>
|
||||||
|
<string name="title_checkbox_enable_pip">Povolit sledovací rezim obraz-v-obraze</string>
|
||||||
|
<string name="summary_checkbox_enable_sops">Povolit GFE měnit herní nastavení pro optimální streamování</string>
|
||||||
|
<string name="title_checkbox_host_audio">Přehrávat zvuk na PC</string>
|
||||||
|
<string name="summary_checkbox_host_audio">Přehraje zvuk z počítače a tohoto zařízení</string>
|
||||||
|
<string name="summary_unlock_fps">Streamování v 90 nebo 120 FPS může snížit zpoždění na dražších zařízeních, ale může způsobit zasekávání nebo nestabilitu na zařízeních, které je nepodporují</string>
|
||||||
|
<string name="title_enable_post_stream_toast">Zobrazit informace o zpoždění po streamování</string>
|
||||||
|
<string name="summary_enable_post_stream_toast">Zobrazit informace o zpoždění po skončení streamování</string>
|
||||||
|
<string name="title_privacy_policy">Zásady ochrany osobních údajů</string>
|
||||||
|
<string name="summary_privacy_policy">Zobrazit zásady ochrany osobních údajů Moonlightu</string>
|
||||||
|
<string name="resolution_360p">360p</string>
|
||||||
|
<string name="resolution_480p">480p</string>
|
||||||
|
<string name="pacing_balanced_alt">Vyvážené s limitem FPS</string>
|
||||||
|
<string name="scut_deleted_pc">PC smazán</string>
|
||||||
|
<string name="scut_not_paired">PC nespárován</string>
|
||||||
|
<string name="scut_pc_not_found">PC nenalezen</string>
|
||||||
|
<string name="scut_invalid_uuid">Zadaný počítač není platný</string>
|
||||||
|
<string name="scut_invalid_app_id">Zadaná aplikace není platná</string>
|
||||||
|
<string name="help_loading_title">Zobrazení nápovědy</string>
|
||||||
|
<string name="wol_waking_msg">Může trvat pár sekund, než se váš počítač probudí. Pokud se tak nestane, ujistěte se, že máte správně nastaveno Wake-On-LAN.</string>
|
||||||
|
<string name="wol_fail">Nezdařilo se odeslat Wake-On-LAN pakety</string>
|
||||||
|
<string name="help">Nápověda</string>
|
||||||
|
<string name="delete_pc_msg">Určitě chcete smazat tento PC\?</string>
|
||||||
|
<string name="slow_connection_msg">Pomalé připojení k PC
|
||||||
|
\nSnižte datový tok</string>
|
||||||
|
<string name="poor_connection_msg">Špatné připojení k PC</string>
|
||||||
|
<string name="perf_overlay_streamdetails">Video stream: %1$s %2$.2f FPS</string>
|
||||||
|
<string name="perf_overlay_decoder">Dekodér: %1$s</string>
|
||||||
|
<string name="perf_overlay_incomingfps">Příchozí snímková frekvence po síti: %1$.2f FPS</string>
|
||||||
|
<string name="text_native_res_dialog">GeForce Experience oficiálně nepodporuje nativní rozlišení a proto nenastaví rozlišení displeje vašeho hostitelského PC. Musíte jej nastavit ručně ve hře.
|
||||||
|
\n
|
||||||
|
\nPokud v NVIDIA Control Panelu vytvoříte vlastní rozlišení pro vaše zařízení, prosím ujistěte se, že jste si přečetli a že chápete varování od NVIDIE ohledně možného poškození monitoru, nestability PC a dalších možných problémů.
|
||||||
|
\n
|
||||||
|
\nNejsme zodpovědni za žádné problémy, které vzniknou používáním vlastního rozlišení na vašem PC.
|
||||||
|
\n
|
||||||
|
\nA nakonec, vaše zařízení nebo hostitelský počítač nemusí podporovat streamování v nativním rozlišení. Pokud vám to nefunguje, bohužel se s tím nedá nic dělat.</string>
|
||||||
|
<string name="title_fps_list">Snímková frekvence videa</string>
|
||||||
|
<string name="summary_fps_list">Zvyšte pro plynulejší video stream. Snižte pro lepší výkon na levnějších zařízeních.</string>
|
||||||
|
<string name="title_seekbar_bitrate">Datový tok videa</string>
|
||||||
|
<string name="summary_seekbar_bitrate">Zvyšte pro lepší kvalitu obrazu. Snižte pro zlepšení výkonu u pomalých připojení.</string>
|
||||||
|
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||||
|
<string name="title_checkbox_stretch_video">Natáhnout video na celou obrazovku</string>
|
||||||
|
<string name="resolution_prefix_native">Nativní</string>
|
||||||
|
<string name="category_on_screen_controls_settings">Nastavení ovládání na obrazovce</string>
|
||||||
|
<string name="title_checkbox_show_onscreen_controls">Zobrazovat ovládání na obrazovce</string>
|
||||||
|
<string name="summary_checkbox_show_onscreen_controls">Zobrazit překrytí virtuálního ovladače na dotykovém displeji</string>
|
||||||
|
<string name="title_checkbox_vibrate_osc">Povolit vibrace</string>
|
||||||
|
<string name="summary_checkbox_vibrate_osc">Vibruje vašim zařízením pro emulaci vibrací ovladače při použití ovladače na obrazovce</string>
|
||||||
|
<string name="title_only_l3r3">Zobrazit pouze L3 a R3</string>
|
||||||
|
<string name="summary_checkbox_enable_pip">Umožní, aby byl stream sledován (ale ne ovládá) během multitaskingu</string>
|
||||||
|
<string name="title_language_list">Jazyk</string>
|
||||||
|
<string name="summary_language_list">Jazyk, který bude Moonlight používat</string>
|
||||||
|
<string name="title_checkbox_small_icon_mode">Použít malý box art</string>
|
||||||
|
<string name="summary_checkbox_small_icon_mode">Díky menšímu box artu v seznamu aplikací uvidíte na obrazovce více aplikací naráz</string>
|
||||||
|
<string name="category_host_settings">Nastavení hostitele</string>
|
||||||
|
<string name="title_checkbox_enable_sops">Optimalizovat herní nastavení</string>
|
||||||
|
<string name="summary_disable_frame_drop">Může na některých zařízeních snížit mikrozádrhy, ale může zvýšit zpoždění</string>
|
||||||
|
<string name="title_video_format">Změnit nastavení HEVC</string>
|
||||||
|
<string name="summary_video_format">HEVC sníží datový přenos, ale vyžaduje novější zařízení</string>
|
||||||
|
<string name="title_enable_hdr">Povolit HDR (experimentální)</string>
|
||||||
|
<string name="summary_enable_hdr">Streamovat v HDR, pokud jej hra a GPU počítače podporují. HDR vyžaduje GPU GTX 1000 nebo novější.</string>
|
||||||
|
<string name="videoformat_hevcalways">Vždy použít HEVC (může padat)</string>
|
||||||
|
<string name="videoformat_hevcnever">Nikdy nepoužívat HEVC</string>
|
||||||
|
<string name="title_frame_pacing">Frame pacing videa</string>
|
||||||
|
<string name="summary_frame_pacing">Zvolte, jak vyvážit zpoždění videa a jeho plynulost</string>
|
||||||
|
<string name="pacing_latency">Preferovat nejnižší zpoždění</string>
|
||||||
|
</resources>
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
<string name="addpc_enter_ip">Debes introducir una dirección IP</string>
|
<string name="addpc_enter_ip">Debes introducir una dirección IP</string>
|
||||||
<!-- Preferences -->
|
<!-- Preferences -->
|
||||||
<string name="category_basic_settings">Configuración básica</string>
|
<string name="category_basic_settings">Configuración básica</string>
|
||||||
<string name="title_resolution_list">Seleccionar resolución y FPS</string>
|
<string name="title_resolution_list">Seleccionar resolución</string>
|
||||||
<string name="summary_resolution_list">Establecer unos valores demasiado altos puede causar retraso o cierres inesperados.</string>
|
<string name="summary_resolution_list">Establecer unos valores demasiado altos puede causar retraso o cierres inesperados.</string>
|
||||||
<string name="title_seekbar_bitrate">Seleccionar bitrate de vídeo</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="summary_seekbar_bitrate">Usa bitrate bajo para reducir "parpadeo". Incrementa el bitrate para mayor calidad de imagen.</string>
|
||||||
@@ -109,8 +109,8 @@
|
|||||||
<string name="title_video_format">Cambiar configuración HEVC</string>
|
<string name="title_video_format">Cambiar configuración HEVC</string>
|
||||||
<string name="summary_video_format">HEVC reduce el ancho de banda de vídeo, pero requiere un dispositivo reciente</string>
|
<string name="summary_video_format">HEVC reduce el ancho de banda de vídeo, pero requiere un dispositivo reciente</string>
|
||||||
<!-- Array strings -->
|
<!-- Array strings -->
|
||||||
<string name="videoformat_hevcauto">Usar HEVC sólo si es estable</string>
|
<string name="videoformat_hevcauto">Automático (Recomendado)</string>
|
||||||
<string name="videoformat_hevcalways">Siempre usar HEVC (puede fallar)</string>
|
<string name="videoformat_hevcalways">Preferir HEVC</string>
|
||||||
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
||||||
<string name="nettest_title_done">Prueba de Red Completada</string>
|
<string name="nettest_title_done">Prueba de Red Completada</string>
|
||||||
<string name="scut_not_paired">PC no emparejado</string>
|
<string name="scut_not_paired">PC no emparejado</string>
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
<string name="resolution_1440p">1440p</string>
|
<string name="resolution_1440p">1440p</string>
|
||||||
<string name="resolution_4k">4K</string>
|
<string name="resolution_4k">4K</string>
|
||||||
<string name="suffix_osc_opacity">%</string>
|
<string name="suffix_osc_opacity">%</string>
|
||||||
<string name="title_checkbox_enable_pip">Actividad modo Pantalla-en-Pantalla para observador</string>
|
<string name="title_checkbox_enable_pip">Activar modo Pantalla-en-Pantalla para modo espectador</string>
|
||||||
<string name="resolution_720p">720p</string>
|
<string name="resolution_720p">720p</string>
|
||||||
<string name="fps_120">120 FPS</string>
|
<string name="fps_120">120 FPS</string>
|
||||||
<string name="audioconf_71surround">7.1 Sonido Envolvente</string>
|
<string name="audioconf_71surround">7.1 Sonido Envolvente</string>
|
||||||
@@ -256,4 +256,13 @@
|
|||||||
<string name="fps_60">60 FPS</string>
|
<string name="fps_60">60 FPS</string>
|
||||||
<string name="fps_90">90 FPS</string>
|
<string name="fps_90">90 FPS</string>
|
||||||
<string name="title_frame_pacing">Ritmo de cuadros por segundo en video</string>
|
<string name="title_frame_pacing">Ritmo de cuadros por segundo en video</string>
|
||||||
|
<string name="resolution_prefix_native_portrait">(Retrato)</string>
|
||||||
|
<string name="frame_conversion_error">El PC anfitrión ha reportado un error fatal en el codificador de video.
|
||||||
|
\n
|
||||||
|
\nIntenta deshabilitar el modo HDR, cambiar la resolución de la transmisión, o cambiar la resolución de pantalla del PC anfitrión.</string>
|
||||||
|
<string name="resolution_prefix_native_landscape">(Panorama)</string>
|
||||||
|
<string name="summary_checkbox_reduce_refresh_rate">Tasa de refresco menores pueden ahorrar energía a cambio de una mayor latencia de video</string>
|
||||||
|
<string name="title_checkbox_reduce_refresh_rate">Permitir reducción de la tasa de refresco</string>
|
||||||
|
<string name="title_full_range">Usar rango (0-255) de color completo</string>
|
||||||
|
<string name="summary_full_range">Esto puede causar problemas de video o bloqueos si la pantalla de tu dispositivo no puede manejar contenido de rango completo.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -228,8 +228,8 @@
|
|||||||
<string name="audioconf_stereo">Stéréo</string>
|
<string name="audioconf_stereo">Stéréo</string>
|
||||||
<string name="audioconf_51surround">Son surround 5.1</string>
|
<string name="audioconf_51surround">Son surround 5.1</string>
|
||||||
<string name="audioconf_71surround">Son surround 7.1</string>
|
<string name="audioconf_71surround">Son surround 7.1</string>
|
||||||
<string name="videoformat_hevcauto">Automatique</string>
|
<string name="videoformat_hevcauto">Automatique (recommandé)</string>
|
||||||
<string name="videoformat_hevcalways">Utilisez toujours HEVC (mais il peut planter)</string>
|
<string name="videoformat_hevcalways">Préférez le HEVC</string>
|
||||||
<string name="videoformat_hevcnever">N\'utilisez jamais HEVC</string>
|
<string name="videoformat_hevcnever">N\'utilisez jamais HEVC</string>
|
||||||
<string name="title_frame_pacing">Frame-pacing vidéo</string>
|
<string name="title_frame_pacing">Frame-pacing vidéo</string>
|
||||||
<string name="summary_frame_pacing">Spécifiez comment équilibrer latence et fluidité de la vidéo</string>
|
<string name="summary_frame_pacing">Spécifiez comment équilibrer latence et fluidité de la vidéo</string>
|
||||||
@@ -259,4 +259,9 @@
|
|||||||
<string name="summary_checkbox_reduce_refresh_rate">Des taux de rafraîchissement d\'affichage plus bas peuvent économiser de l\'énergie au détriment d\'une latence vidéo plus importante</string>
|
<string name="summary_checkbox_reduce_refresh_rate">Des taux de rafraîchissement d\'affichage plus bas peuvent économiser de l\'énergie au détriment d\'une latence vidéo plus importante</string>
|
||||||
<string name="summary_checkbox_enable_audiofx">Permet aux effets audio de fonctionner lors du streaming, mais peut augmenter la latence</string>
|
<string name="summary_checkbox_enable_audiofx">Permet aux effets audio de fonctionner lors du streaming, mais peut augmenter la latence</string>
|
||||||
<string name="title_checkbox_enable_audiofx">Activer le support de l\'égalisateur système</string>
|
<string name="title_checkbox_enable_audiofx">Activer le support de l\'égalisateur système</string>
|
||||||
|
<string name="frame_conversion_error">Le PC hôte a signalé une erreur d\'encodage fatale.
|
||||||
|
\n
|
||||||
|
\nEssayez de désactiver le mode HDR, de changer la résolution du flux ou la résolution de votre PC hôte.</string>
|
||||||
|
<string name="title_full_range">Forcer la vidéo sur toute la gamme de couleurs (expérimental)</string>
|
||||||
|
<string name="summary_full_range">Ceci entraînera une perte de détails dans les zones claires et sombres si votre appareil n\'affiche pas correctement le contenu vidéo de la gamme complète de couleurs.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -254,4 +254,13 @@
|
|||||||
<string name="title_privacy_policy">Informativa sulla privacy</string>
|
<string name="title_privacy_policy">Informativa sulla privacy</string>
|
||||||
<string name="summary_troubleshooting">Visualizza i suggerimenti per la diagnosi e la risoluzione dei problemi di streaming più comuni</string>
|
<string name="summary_troubleshooting">Visualizza i suggerimenti per la diagnosi e la risoluzione dei problemi di streaming più comuni</string>
|
||||||
<string name="summary_privacy_policy">Visualizza l\'informativa sulla privacy di Moonlight</string>
|
<string name="summary_privacy_policy">Visualizza l\'informativa sulla privacy di Moonlight</string>
|
||||||
|
<string name="frame_conversion_error">Il PC host ha segnalato un errore fatale di codifica video.
|
||||||
|
\n
|
||||||
|
\nProva a disabilitare la modalità HDR, modificare la risoluzione dello streaming o la risoluzione del display del tuo PC host.</string>
|
||||||
|
<string name="summary_checkbox_reduce_refresh_rate">Una minore frequenza di aggiornamento del display può risparmiare energia a scapito di una latenza video aggiuntiva</string>
|
||||||
|
<string name="resolution_prefix_native_landscape">(Panorama)</string>
|
||||||
|
<string name="resolution_prefix_native_portrait">(Ritratto)</string>
|
||||||
|
<string name="title_checkbox_enable_audiofx">Abilita il supporto per l\'equalizzatore di sistema</string>
|
||||||
|
<string name="summary_checkbox_enable_audiofx">Consente agli effetti audio di funzionare durante lo streaming, ma può aumentare la latenza audio</string>
|
||||||
|
<string name="title_checkbox_reduce_refresh_rate">Consenti riduzione della frequenza di aggiornamento</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -53,8 +53,8 @@
|
|||||||
<string name="resolution_4k">4K</string>
|
<string name="resolution_4k">4K</string>
|
||||||
<string name="fps_30">30 FPS</string>
|
<string name="fps_30">30 FPS</string>
|
||||||
<string name="fps_60">60 FPS</string>
|
<string name="fps_60">60 FPS</string>
|
||||||
<string name="videoformat_hevcalways">Sempre usar HEVC (talvez crashe)</string>
|
<string name="videoformat_hevcalways">Prefira HEVC</string>
|
||||||
<string name="videoformat_hevcauto">Automático</string>
|
<string name="videoformat_hevcauto">Automático (recomendado)</string>
|
||||||
<string name="fps_120">120 FPS</string>
|
<string name="fps_120">120 FPS</string>
|
||||||
<string name="audioconf_stereo">Stereo</string>
|
<string name="audioconf_stereo">Stereo</string>
|
||||||
<string name="audioconf_51surround">5.1 Surround</string>
|
<string name="audioconf_51surround">5.1 Surround</string>
|
||||||
@@ -245,4 +245,9 @@
|
|||||||
<string name="resolution_prefix_native_portrait">(Retrato)</string>
|
<string name="resolution_prefix_native_portrait">(Retrato)</string>
|
||||||
<string name="title_checkbox_enable_audiofx">Habilitar sistema de suporte à equalização</string>
|
<string name="title_checkbox_enable_audiofx">Habilitar sistema de suporte à equalização</string>
|
||||||
<string name="summary_checkbox_enable_audiofx">Permitir que efeitos de audio funcionem durante o streaming, pode acrescentar latência de audio</string>
|
<string name="summary_checkbox_enable_audiofx">Permitir que efeitos de audio funcionem durante o streaming, pode acrescentar latência de audio</string>
|
||||||
|
<string name="title_full_range">Forçar vídeo de gama completa de cores (Experimental)</string>
|
||||||
|
<string name="frame_conversion_error">O PC host relatou um erro fatal de codificação de vídeo.
|
||||||
|
\n
|
||||||
|
\nTente desativar o modo HDR, alterar a resolução de streaming ou alterar a resolução do PC host.</string>
|
||||||
|
<string name="summary_full_range">Isso causará perda de detalhes em áreas claras e escuras se o seu dispositivo não exibir corretamente todo o conteúdo de vídeo em cores.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -218,8 +218,8 @@
|
|||||||
<string name="pcview_menu_header_offline">Поза мережею</string>
|
<string name="pcview_menu_header_offline">Поза мережею</string>
|
||||||
<string name="pcview_menu_header_online">В мережі</string>
|
<string name="pcview_menu_header_online">В мережі</string>
|
||||||
<!-- Array strings -->
|
<!-- Array strings -->
|
||||||
<string name="videoformat_hevcauto">Використовувати HEVC тільки якщо безпечно</string>
|
<string name="videoformat_hevcauto">Автоматичний (рекомендовано)</string>
|
||||||
<string name="videoformat_hevcalways">Завжди використовувати HEVC якщо доступно</string>
|
<string name="videoformat_hevcalways">Використовувати HEVC</string>
|
||||||
<string name="videoformat_hevcnever">Ніколи не використовувати HEVC</string>
|
<string name="videoformat_hevcnever">Ніколи не використовувати HEVC</string>
|
||||||
<string name="title_frame_pacing">Швидкість кадрів відео</string>
|
<string name="title_frame_pacing">Швидкість кадрів відео</string>
|
||||||
<string name="summary_frame_pacing">Укажіть баланс відео затримки та плавності</string>
|
<string name="summary_frame_pacing">Укажіть баланс відео затримки та плавності</string>
|
||||||
@@ -239,4 +239,26 @@
|
|||||||
<string name="audioconf_stereo">Стерео</string>
|
<string name="audioconf_stereo">Стерео</string>
|
||||||
<string name="audioconf_51surround">5.1 Об\'ємний Звук</string>
|
<string name="audioconf_51surround">5.1 Об\'ємний Звук</string>
|
||||||
<string name="audioconf_71surround">7.1 Об\'ємний Звук</string>
|
<string name="audioconf_71surround">7.1 Об\'ємний Звук</string>
|
||||||
|
<string name="summary_checkbox_enable_audiofx">Дозволяє аудіоефектам функціонувати під час потокового передавання, але може збільшити затримку звуку</string>
|
||||||
|
<string name="title_troubleshooting">Гайд з усунення несправностей</string>
|
||||||
|
<string name="title_privacy_policy">Політика конфіденційності</string>
|
||||||
|
<string name="summary_troubleshooting">Переглянути поради щодо діагностики та усунення поширених проблем з потоковою передачею</string>
|
||||||
|
<string name="summary_checkbox_reduce_refresh_rate">Більш низька частота оновлення дисплея може заощадити енергію за рахунок деякої додаткової затримки відео</string>
|
||||||
|
<string name="summary_seekbar_deadzone">Примітка: Деякі ігри можуть встановлювати більшу мертву зону, ніж та, на яку налаштовано Moonlight.</string>
|
||||||
|
<string name="title_checkbox_absolute_mouse_mode">Режим миші віддаленого робочого столу</string>
|
||||||
|
<string name="title_setup_guide">Гайд по налаштуванню</string>
|
||||||
|
<string name="summary_setup_guide">Переглянути інструкцію, як налаштувати ігровий ПК для стрімінгу</string>
|
||||||
|
<string name="pacing_balanced_alt">Збалансований з лімітом FPS</string>
|
||||||
|
<string name="resolution_prefix_native_landscape">(Горизонтальний)</string>
|
||||||
|
<string name="resolution_prefix_native_portrait">(Портретний)</string>
|
||||||
|
<string name="title_checkbox_enable_audiofx">Увімкнення підтримки системного еквалайзера</string>
|
||||||
|
<string name="summary_checkbox_absolute_mouse_mode">Це може зробити прискорення миші більш природним під час використання віддаленого робочого столу, але воно несумісне з багатьма іграми.</string>
|
||||||
|
<string name="title_checkbox_reduce_refresh_rate">Дозволити зниження частоти оновлення</string>
|
||||||
|
<string name="category_help">Допомога</string>
|
||||||
|
<string name="summary_privacy_policy">Переглянути політику конфіденційності Moonlight</string>
|
||||||
|
<string name="frame_conversion_error">Головний комп\'ютер повідомив про фатальну помилку кодування відео.
|
||||||
|
\n
|
||||||
|
\nСпробуйте вимкнути режим HDR, змінити роздільну здатність потокового відео або змінити роздільну здатність дисплея головного комп\'ютера.</string>
|
||||||
|
<string name="title_full_range">Сила повного спектру відео (експериментальна)</string>
|
||||||
|
<string name="summary_full_range">Це може призвести до втрати деталей у світлих і темних областях, якщо пристрій не відображає належним чином весь діапазон відеоконтенту.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -222,8 +222,8 @@
|
|||||||
<string name="audioconf_stereo">立体声</string>
|
<string name="audioconf_stereo">立体声</string>
|
||||||
<string name="audioconf_51surround">5.1环绕声</string>
|
<string name="audioconf_51surround">5.1环绕声</string>
|
||||||
<string name="audioconf_71surround">7.1环绕声</string>
|
<string name="audioconf_71surround">7.1环绕声</string>
|
||||||
<string name="videoformat_hevcauto">自动</string>
|
<string name="videoformat_hevcauto">自动(推荐)</string>
|
||||||
<string name="videoformat_hevcalways">强制使用HEVC(不稳定)</string>
|
<string name="videoformat_hevcalways">首选 HEVC</string>
|
||||||
<string name="videoformat_hevcnever">不使用HEVC</string>
|
<string name="videoformat_hevcnever">不使用HEVC</string>
|
||||||
<string name="title_frame_pacing">视频帧速调节</string>
|
<string name="title_frame_pacing">视频帧速调节</string>
|
||||||
<string name="resolution_360p">360p</string>
|
<string name="resolution_360p">360p</string>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<string name="conn_hardware_latency">硬體解碼器平均延時:</string>
|
<string name="conn_hardware_latency">硬體解碼器平均延時:</string>
|
||||||
<string name="conn_starting">正在啟動</string>
|
<string name="conn_starting">正在啟動</string>
|
||||||
<string name="conn_error_title">連線錯誤</string>
|
<string name="conn_error_title">連線錯誤</string>
|
||||||
<string name="conn_error_msg"> 啟動失敗 </string>
|
<string name="conn_error_msg">無法啟動</string>
|
||||||
<string name="conn_terminated_title">連線已終止</string>
|
<string name="conn_terminated_title">連線已終止</string>
|
||||||
<string name="conn_terminated_msg">連線已終止</string>
|
<string name="conn_terminated_msg">連線已終止</string>
|
||||||
<!-- General strings -->
|
<!-- General strings -->
|
||||||
@@ -90,10 +90,10 @@
|
|||||||
<string name="applist_refresh_title">遊戲清單</string>
|
<string name="applist_refresh_title">遊戲清單</string>
|
||||||
<string name="applist_refresh_msg">正在重新整理…</string>
|
<string name="applist_refresh_msg">正在重新整理…</string>
|
||||||
<string name="applist_refresh_error_title"> 錯誤 </string>
|
<string name="applist_refresh_error_title"> 錯誤 </string>
|
||||||
<string name="applist_refresh_error_msg">取得遊戲清單失敗</string>
|
<string name="applist_refresh_error_msg">無法取得遊戲清單</string>
|
||||||
<string name="applist_quit_app">正在結束</string>
|
<string name="applist_quit_app">正在結束</string>
|
||||||
<string name="applist_quit_success">結束成功</string>
|
<string name="applist_quit_success">結束成功</string>
|
||||||
<string name="applist_quit_fail">結束失敗</string>
|
<string name="applist_quit_fail">無法結束</string>
|
||||||
<string name="applist_quit_confirmation">您確定要結束執行中的遊戲?所有未儲存的資料將丟失。</string>
|
<string name="applist_quit_confirmation">您確定要結束執行中的遊戲?所有未儲存的資料將丟失。</string>
|
||||||
<string name="applist_details_id">App ID:</string>
|
<string name="applist_details_id">App ID:</string>
|
||||||
<!-- Add computer manually activity -->
|
<!-- Add computer manually activity -->
|
||||||
@@ -109,9 +109,9 @@
|
|||||||
<string name="title_resolution_list">視訊解析度</string>
|
<string name="title_resolution_list">視訊解析度</string>
|
||||||
<string name="summary_resolution_list">高解析度提升圖像清晰度。低解析度提升在低效能裝置和較慢網路中的串流體驗。</string>
|
<string name="summary_resolution_list">高解析度提升圖像清晰度。低解析度提升在低效能裝置和較慢網路中的串流體驗。</string>
|
||||||
<string name="title_fps_list">視訊影格速率</string>
|
<string name="title_fps_list">視訊影格速率</string>
|
||||||
<string name="summary_fps_list">提高影格速率以獲得更順暢的視訊串流,降低可在低效能裝置上獲得更好的串流體驗。</string>
|
<string name="summary_fps_list">提高影格速率以取得更順暢的視訊串流,降低可在低效能裝置上取得更好的串流體驗。</string>
|
||||||
<string name="title_seekbar_bitrate">視訊位元速率</string>
|
<string name="title_seekbar_bitrate">視訊位元速率</string>
|
||||||
<string name="summary_seekbar_bitrate">提高位元速率以提升圖像品質,降低可在較慢的網路中獲得更好的串流體驗。</string>
|
<string name="summary_seekbar_bitrate">提高位元速率以提升圖像品質,降低可在較慢的網路中取得更好的串流體驗。</string>
|
||||||
<string name="title_unlock_fps">解鎖所有可用影格速率</string>
|
<string name="title_unlock_fps">解鎖所有可用影格速率</string>
|
||||||
<string name="summary_unlock_fps">以 90 或 120 畫面更新率串流可能會減少在高效能裝置上的網路延時,但會在不支援的裝置上造成卡頓或崩潰</string>
|
<string name="summary_unlock_fps">以 90 或 120 畫面更新率串流可能會減少在高效能裝置上的網路延時,但會在不支援的裝置上造成卡頓或崩潰</string>
|
||||||
<string name="title_checkbox_stretch_video">將畫面延展至全螢幕</string>
|
<string name="title_checkbox_stretch_video">將畫面延展至全螢幕</string>
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
\n如果問題仍然存在,請嘗試重新安裝 GPU 驅動程式和 GFE。</string>
|
\n如果問題仍然存在,請嘗試重新安裝 GPU 驅動程式和 GFE。</string>
|
||||||
<string name="no_frame_received_error">您的網路連線品質不佳。降低視訊位元速率設定或更換更快的連線。</string>
|
<string name="no_frame_received_error">您的網路連線品質不佳。降低視訊位元速率設定或更換更快的連線。</string>
|
||||||
<string name="no_video_received_error">沒有接收到來自主機的視訊。</string>
|
<string name="no_video_received_error">沒有接收到來自主機的視訊。</string>
|
||||||
<string name="video_decoder_init_failed">視訊解碼器初始化失敗。您的裝置可能不支援選取的解析度或影格速率。</string>
|
<string name="video_decoder_init_failed">無法初始化視訊解碼器,您的裝置可能不支援選取的解析度或影格速率。</string>
|
||||||
<string name="nettest_text_blocked">您裝置目前的網路連線封鎖了 Moonlight。連線到該網路時可能無法透過網際網路串流。</string>
|
<string name="nettest_text_blocked">您裝置目前的網路連線封鎖了 Moonlight。連線到該網路時可能無法透過網際網路串流。</string>
|
||||||
<string name="nettest_text_failure">您裝置目前的網路連線似乎封鎖了 Moonlight。連線到該網路時可能無法透過網際網路串流。
|
<string name="nettest_text_failure">您裝置目前的網路連線似乎封鎖了 Moonlight。連線到該網路時可能無法透過網際網路串流。
|
||||||
\n
|
\n
|
||||||
@@ -223,8 +223,8 @@
|
|||||||
<string name="audioconf_stereo">立體聲</string>
|
<string name="audioconf_stereo">立體聲</string>
|
||||||
<string name="audioconf_51surround">5.1 環場音效</string>
|
<string name="audioconf_51surround">5.1 環場音效</string>
|
||||||
<string name="audioconf_71surround">7.1 環場音效</string>
|
<string name="audioconf_71surround">7.1 環場音效</string>
|
||||||
<string name="videoformat_hevcauto">自動</string>
|
<string name="videoformat_hevcauto">自動 (建議)</string>
|
||||||
<string name="videoformat_hevcalways">強制使用 HEVC (可能會當機)</string>
|
<string name="videoformat_hevcalways">優先使用 HEVC</string>
|
||||||
<string name="videoformat_hevcnever">不使用 HEVC</string>
|
<string name="videoformat_hevcnever">不使用 HEVC</string>
|
||||||
<string name="resolution_4k">4K</string>
|
<string name="resolution_4k">4K</string>
|
||||||
<string name="fps_30">30 FPS</string>
|
<string name="fps_30">30 FPS</string>
|
||||||
@@ -261,4 +261,6 @@
|
|||||||
<string name="frame_conversion_error">主機電腦回報了一個嚴重的視訊編碼錯誤。
|
<string name="frame_conversion_error">主機電腦回報了一個嚴重的視訊編碼錯誤。
|
||||||
\n
|
\n
|
||||||
\n嘗試停用 HDR 模式,變更串流解析度,或變更您的主機電腦的顯示器解析度。</string>
|
\n嘗試停用 HDR 模式,變更串流解析度,或變更您的主機電腦的顯示器解析度。</string>
|
||||||
|
<string name="title_full_range">強制全範圍視訊 (實驗性)</string>
|
||||||
|
<string name="summary_full_range">若您的裝置無法正確地顯示全範圍視訊內容,將會導致淺色區域和深色區域的細節遺失。</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -9,13 +9,14 @@
|
|||||||
<item>@string/resolution_4k</item>
|
<item>@string/resolution_4k</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Keep this in sync with PreferenceConfiguration.isNativeResolution()! -->
|
||||||
<string-array name="resolution_values" translatable="false">
|
<string-array name="resolution_values" translatable="false">
|
||||||
<item>s_640x360</item>
|
<item>640x360</item>
|
||||||
<item>s_854x480</item>
|
<item>854x480</item>
|
||||||
<item>s_1280x720</item>
|
<item>1280x720</item>
|
||||||
<item>s_1920x1080</item>
|
<item>1920x1080</item>
|
||||||
<item>s_2560x1440</item>
|
<item>2560x1440</item>
|
||||||
<item>s_3840x2160</item>
|
<item>3840x2160</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="fps_names">
|
<string-array name="fps_names">
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
<item>Magyar</item>
|
<item>Magyar</item>
|
||||||
<item>Ελληνικά</item>
|
<item>Ελληνικά</item>
|
||||||
<item>Português do Brasil</item>
|
<item>Português do Brasil</item>
|
||||||
|
<item>Čeština</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="language_values" translatable="false">
|
<string-array name="language_values" translatable="false">
|
||||||
<item>default</item>
|
<item>default</item>
|
||||||
@@ -84,6 +86,7 @@
|
|||||||
<item>hu</item>
|
<item>hu</item>
|
||||||
<item>el</item>
|
<item>el</item>
|
||||||
<item>pt-BR</item>
|
<item>pt-BR</item>
|
||||||
|
<item>cs</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="video_format_names">
|
<string-array name="video_format_names">
|
||||||
|
|||||||
@@ -229,6 +229,8 @@
|
|||||||
<string name="summary_video_format">HEVC lowers video bandwidth requirements but requires a newer device</string>
|
<string name="summary_video_format">HEVC lowers video bandwidth requirements but requires a newer device</string>
|
||||||
<string name="title_enable_hdr">Enable HDR (Experimental)</string>
|
<string name="title_enable_hdr">Enable HDR (Experimental)</string>
|
||||||
<string name="summary_enable_hdr">Stream HDR when the game and PC GPU support it. HDR requires a GTX 1000 series GPU or later.</string>
|
<string name="summary_enable_hdr">Stream HDR when the game and PC GPU support it. HDR requires a GTX 1000 series GPU or later.</string>
|
||||||
|
<string name="title_full_range">Force full range video (Experimental)</string>
|
||||||
|
<string name="summary_full_range">This will cause loss of detail in light and dark areas if your device doesn\'t properly display full range video content.</string>
|
||||||
<string name="title_enable_perf_overlay">Show performance stats while streaming</string>
|
<string name="title_enable_perf_overlay">Show performance stats while streaming</string>
|
||||||
<string name="summary_enable_perf_overlay">Display real-time stream performance information while streaming</string>
|
<string name="summary_enable_perf_overlay">Display real-time stream performance information while streaming</string>
|
||||||
<string name="title_enable_post_stream_toast">Show latency message after streaming</string>
|
<string name="title_enable_post_stream_toast">Show latency message after streaming</string>
|
||||||
@@ -259,8 +261,8 @@
|
|||||||
<string name="audioconf_51surround">5.1 Surround Sound</string>
|
<string name="audioconf_51surround">5.1 Surround Sound</string>
|
||||||
<string name="audioconf_71surround">7.1 Surround Sound</string>
|
<string name="audioconf_71surround">7.1 Surround Sound</string>
|
||||||
|
|
||||||
<string name="videoformat_hevcauto">Automatic</string>
|
<string name="videoformat_hevcauto">Automatic (Recommended)</string>
|
||||||
<string name="videoformat_hevcalways">Always use HEVC (may crash)</string>
|
<string name="videoformat_hevcalways">Prefer HEVC</string>
|
||||||
<string name="videoformat_hevcnever">Never use HEVC</string>
|
<string name="videoformat_hevcnever">Never use HEVC</string>
|
||||||
|
|
||||||
<string name="title_frame_pacing">Video frame pacing</string>
|
<string name="title_frame_pacing">Video frame pacing</string>
|
||||||
|
|||||||
@@ -19,4 +19,5 @@
|
|||||||
<locale android:name="hu"/>
|
<locale android:name="hu"/>
|
||||||
<locale android:name="el"/>
|
<locale android:name="el"/>
|
||||||
<locale android:name="pt-BR"/>
|
<locale android:name="pt-BR"/>
|
||||||
|
<locale android:name="cs"/>
|
||||||
</locale-config>
|
</locale-config>
|
||||||
@@ -211,6 +211,11 @@
|
|||||||
android:title="@string/title_enable_hdr"
|
android:title="@string/title_enable_hdr"
|
||||||
android:summary="@string/summary_enable_hdr"
|
android:summary="@string/summary_enable_hdr"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="checkbox_full_range"
|
||||||
|
android:title="@string/title_full_range"
|
||||||
|
android:summary="@string/summary_full_range"
|
||||||
|
android:defaultValue="false" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="checkbox_enable_perf_overlay"
|
android:key="checkbox_enable_perf_overlay"
|
||||||
android:title="@string/title_enable_perf_overlay"
|
android:title="@string/title_enable_perf_overlay"
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
- Changed the default SDR colorspace from BT.601 to BT.709
|
||||||
|
- Changed the input capture toggle shortcut from Ctrl+Shift+Z to Ctrl+Alt+Shift+Z for consistency with other clients
|
||||||
|
- Toggling input capture now properly toggles keyboard capture on Samsung devices
|
||||||
|
- PC state is now refreshed more quickly after a network change
|
||||||
|
- Fixed entering IPv6 addresses on the Add PC page
|
||||||
|
- Added an experimental option to request full range video
|
||||||
|
- Updated community contributed translations from Weblate
|
||||||
Reference in new issue
Block a user