mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-10-12 11:34:10 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41592b2ef4 |
+2
-2
@@ -9,8 +9,8 @@ android {
|
||||
minSdk 16
|
||||
targetSdk 33
|
||||
|
||||
versionName "10.11"
|
||||
versionCode = 301
|
||||
versionName "10.10"
|
||||
versionCode = 298
|
||||
|
||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||
ndk.debugSymbolLevel = 'FULL'
|
||||
|
||||
@@ -220,7 +220,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Enter landscape unless we're on a square screen
|
||||
setPreferredOrientationForCurrentDisplay();
|
||||
|
||||
if (prefConfig.stretchVideo || shouldIgnoreInsetsForResolution(prefConfig.width, prefConfig.height)) {
|
||||
if (prefConfig.stretchVideo || prefConfig.resolution.fullScreen) {
|
||||
// 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
|
||||
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()
|
||||
.setResolution(prefConfig.width, prefConfig.height)
|
||||
.setResolution(prefConfig.resolution.width, prefConfig.resolution.height)
|
||||
.setLaunchRefreshRate(prefConfig.fps)
|
||||
.setRefreshRate(chosenFrameRate)
|
||||
.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
|
||||
if (PreferenceConfiguration.isNativeResolution(prefConfig.width, prefConfig.height)) {
|
||||
if (prefConfig.width > prefConfig.height) {
|
||||
desiredOrientation = Configuration.ORIENTATION_LANDSCAPE;
|
||||
if (prefConfig.resolution.type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
||||
if (prefConfig.resolution.portrait) {
|
||||
desiredOrientation = Configuration.ORIENTATION_PORTRAIT;
|
||||
}
|
||||
else {
|
||||
desiredOrientation = Configuration.ORIENTATION_PORTRAIT;
|
||||
desiredOrientation = Configuration.ORIENTATION_LANDSCAPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +649,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
private PictureInPictureParams getPictureInPictureParams(boolean autoEnter) {
|
||||
PictureInPictureParams.Builder builder =
|
||||
new PictureInPictureParams.Builder()
|
||||
.setAspectRatio(new Rational(prefConfig.width, prefConfig.height))
|
||||
.setAspectRatio(new Rational(prefConfig.resolution.width, prefConfig.resolution.height))
|
||||
.setSourceRectHint(new Rect(
|
||||
streamView.getLeft(), streamView.getTop(),
|
||||
streamView.getRight(), streamView.getBottom()));
|
||||
@@ -771,26 +771,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
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() {
|
||||
return prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS ||
|
||||
prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
|
||||
@@ -805,7 +785,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// On M, we can explicitly set the optimal display mode
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Display.Mode bestMode = display.getMode();
|
||||
boolean isNativeResolutionStream = PreferenceConfiguration.isNativeResolution(prefConfig.width, prefConfig.height);
|
||||
boolean refreshRateIsGood = isRefreshRateGoodMatch(bestMode.getRefreshRate());
|
||||
boolean refreshRateIsEqual = isRefreshRateEqualMatch(bestMode.getRefreshRate());
|
||||
|
||||
@@ -813,13 +792,13 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
boolean refreshRateReduced = candidate.getRefreshRate() < bestMode.getRefreshRate();
|
||||
boolean resolutionReduced = candidate.getPhysicalWidth() < bestMode.getPhysicalWidth() ||
|
||||
candidate.getPhysicalHeight() < bestMode.getPhysicalHeight();
|
||||
boolean resolutionFitsStream = candidate.getPhysicalWidth() >= prefConfig.width &&
|
||||
candidate.getPhysicalHeight() >= prefConfig.height;
|
||||
boolean resolutionFitsStream = candidate.getPhysicalWidth() >= prefConfig.resolution.width &&
|
||||
candidate.getPhysicalHeight() >= prefConfig.resolution.height;
|
||||
|
||||
LimeLog.info("Examining display mode: "+candidate.getPhysicalWidth()+"x"+
|
||||
candidate.getPhysicalHeight()+"x"+candidate.getRefreshRate());
|
||||
|
||||
if (candidate.getPhysicalWidth() > 4096 && prefConfig.width <= 4096) {
|
||||
if (candidate.getPhysicalWidth() > 4096 && prefConfig.resolution.width <= 4096) {
|
||||
// Avoid resolutions options above 4K to be safe
|
||||
continue;
|
||||
}
|
||||
@@ -827,7 +806,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// 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,
|
||||
// or it's a native resolution stream.
|
||||
if (prefConfig.width < 3840 && prefConfig.fps <= 60 && !isNativeResolutionStream) {
|
||||
if (prefConfig.resolution.width < 3840 && prefConfig.fps <= 60 &&
|
||||
prefConfig.resolution.type != PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
||||
if (display.getMode().getPhysicalWidth() != candidate.getPhysicalWidth() ||
|
||||
display.getMode().getPhysicalHeight() != candidate.getPhysicalHeight()) {
|
||||
continue;
|
||||
@@ -940,7 +920,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
display.getSize(screenSize);
|
||||
|
||||
double screenAspectRatio = ((double)screenSize.y) / screenSize.x;
|
||||
double streamAspectRatio = ((double)prefConfig.height) / prefConfig.width;
|
||||
double streamAspectRatio = ((double)prefConfig.resolution.height) / prefConfig.resolution.width;
|
||||
if (Math.abs(screenAspectRatio - streamAspectRatio) < 0.001) {
|
||||
LimeLog.info("Stream has compatible aspect ratio with output display");
|
||||
aspectRatioMatch = true;
|
||||
@@ -949,11 +929,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
if (prefConfig.stretchVideo || aspectRatioMatch) {
|
||||
// Set the surface to the size of the video
|
||||
streamView.getHolder().setFixedSize(prefConfig.width, prefConfig.height);
|
||||
streamView.getHolder().setFixedSize(prefConfig.resolution.width, prefConfig.resolution.height);
|
||||
}
|
||||
else {
|
||||
// Set the surface to scale based on the aspect ratio of the stream
|
||||
streamView.setDesiredAspectRatio((double)prefConfig.width / (double)prefConfig.height);
|
||||
streamView.setDesiredAspectRatio((double)prefConfig.resolution.width / (double)prefConfig.resolution.height);
|
||||
}
|
||||
|
||||
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION) ||
|
||||
@@ -1126,25 +1106,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
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() {
|
||||
@Override
|
||||
public void run() {
|
||||
setInputGrabState(!grabbedInput);
|
||||
if (grabbedInput) {
|
||||
inputCaptureProvider.disableCapture();
|
||||
}
|
||||
else {
|
||||
inputCaptureProvider.enableCapture();
|
||||
}
|
||||
|
||||
grabbedInput = !grabbedInput;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1164,10 +1136,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
androidKeyCode == KeyEvent.KEYCODE_ALT_RIGHT) {
|
||||
modifierMask = KeyboardPacket.MODIFIER_ALT;
|
||||
}
|
||||
else if (androidKeyCode == KeyEvent.KEYCODE_META_LEFT ||
|
||||
androidKeyCode == KeyEvent.KEYCODE_META_RIGHT) {
|
||||
modifierMask = KeyboardPacket.MODIFIER_META;
|
||||
}
|
||||
|
||||
if (down) {
|
||||
this.modifierFlags |= modifierMask;
|
||||
@@ -1176,10 +1144,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
this.modifierFlags &= ~modifierMask;
|
||||
}
|
||||
|
||||
// Check if Ctrl+Alt+Shift+Z is pressed
|
||||
// Check if Ctrl+Shift+Z is pressed
|
||||
if (androidKeyCode == KeyEvent.KEYCODE_Z &&
|
||||
(modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT)) ==
|
||||
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT))
|
||||
(modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_SHIFT)) ==
|
||||
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_SHIFT))
|
||||
{
|
||||
if (down) {
|
||||
// Now that we've pressed the magic combo
|
||||
@@ -1230,9 +1198,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
if (event.isAltPressed()) {
|
||||
modifier |= KeyboardPacket.MODIFIER_ALT;
|
||||
}
|
||||
if (event.isMetaPressed()) {
|
||||
modifier |= KeyboardPacket.MODIFIER_META;
|
||||
}
|
||||
return modifier;
|
||||
}
|
||||
|
||||
@@ -1896,8 +1861,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Let the display go to sleep now
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
// Ungrab input
|
||||
setInputGrabState(false);
|
||||
// Enable cursor visibility again
|
||||
inputCaptureProvider.disableCapture();
|
||||
|
||||
// Disable meta key capture
|
||||
setMetaKeyCaptureState(false);
|
||||
|
||||
if (!displayedFailureDialog) {
|
||||
displayedFailureDialog = true;
|
||||
@@ -2007,13 +1975,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
h.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setInputGrabState(true);
|
||||
inputCaptureProvider.enableCapture();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// Keep the display on
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
// Enable meta key capture
|
||||
setMetaKeyCaptureState(true);
|
||||
|
||||
// Update GameManager state to indicate we're in game
|
||||
UiHelper.notifyStreamConnected(Game.this);
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private boolean decoderCanMeetPerformancePoint(MediaCodecInfo.VideoCapabilities caps, PreferenceConfiguration prefs) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.width, prefs.height, prefs.fps);
|
||||
MediaCodecInfo.VideoCapabilities.PerformancePoint targetPerfPoint = new MediaCodecInfo.VideoCapabilities.PerformancePoint(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
||||
List<MediaCodecInfo.VideoCapabilities.PerformancePoint> perfPoints = caps.getSupportedPerformancePoints();
|
||||
if (perfPoints != null) {
|
||||
for (MediaCodecInfo.VideoCapabilities.PerformancePoint perfPoint : perfPoints) {
|
||||
@@ -155,7 +155,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
try {
|
||||
// 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.
|
||||
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.width, prefs.height);
|
||||
Range<Double> fpsRange = caps.getAchievableFrameRatesFor(prefs.resolution.width, prefs.resolution.height);
|
||||
if (fpsRange != null) {
|
||||
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
|
||||
// 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.
|
||||
return caps.areSizeAndRateSupported(prefs.width, prefs.height, prefs.fps);
|
||||
return caps.areSizeAndRateSupported(prefs.resolution.width, prefs.resolution.height, prefs.fps);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
// > 4K streaming also requires HEVC, so force it on there too.
|
||||
else if (prefs.width > 4096 || prefs.height > 4096) {
|
||||
else if (prefs.resolution.width > 4096 || prefs.resolution.height > 4096) {
|
||||
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
||||
}
|
||||
// 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;
|
||||
if (avcDecoder != null) {
|
||||
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height);
|
||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.resolution.height);
|
||||
avcOptimalSlicesPerFrame = MediaCodecHelper.getDecoderOptimalSlicesPerFrame(avcDecoder.getName());
|
||||
|
||||
if (directSubmit) {
|
||||
@@ -328,28 +328,11 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
}
|
||||
|
||||
public int getPreferredColorSpace() {
|
||||
// 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;
|
||||
}
|
||||
return MoonBridge.COLORSPACE_REC_601;
|
||||
}
|
||||
|
||||
public int getPreferredColorRange() {
|
||||
if (prefs.fullRange) {
|
||||
return MoonBridge.COLOR_RANGE_FULL;
|
||||
}
|
||||
else {
|
||||
return MoonBridge.COLOR_RANGE_LIMITED;
|
||||
}
|
||||
return MoonBridge.COLOR_RANGE_LIMITED;
|
||||
}
|
||||
|
||||
public void notifyVideoForeground() {
|
||||
@@ -1320,10 +1303,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
sps.numRefFrames = 1;
|
||||
}
|
||||
|
||||
// GFE 2.5.11 changed the SPS to add additional extensions. Some devices don't like these
|
||||
// so we remove them here on old devices unless these devices also support HEVC.
|
||||
// See getPreferredColorSpace() for further information.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && hevcDecoder == null && sps.vuiParams != null) {
|
||||
// GFE 2.5.11 changed the SPS to add additional extensions
|
||||
// Some devices don't like these so we remove them here on old devices.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && sps.vuiParams != null) {
|
||||
sps.vuiParams.videoSignalTypePresentFlag = false;
|
||||
sps.vuiParams.colourDescriptionPresentFlag = false;
|
||||
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.limelight.binding.video;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -77,6 +78,12 @@ public class MediaCodecHelper {
|
||||
refFrameInvalidationHevcPrefixes.add("omx.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
|
||||
}
|
||||
|
||||
@@ -177,9 +184,6 @@ public class MediaCodecHelper {
|
||||
// vendor.low-latency.enable. We will still use HEVC if decoderCanMeetPerformancePointWithHevcAndNotAvc()
|
||||
// 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?
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !Build.DEVICE.equalsIgnoreCase("sabrina")) {
|
||||
whitelistedHevcDecoders.add("omx.amlogic");
|
||||
@@ -711,12 +715,19 @@ public class MediaCodecHelper {
|
||||
// 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.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
LimeLog.info("Media performance class: " + Build.VERSION.MEDIA_PERFORMANCE_CLASS);
|
||||
if (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S) {
|
||||
LimeLog.info("Allowing HEVC based on media performance class");
|
||||
//
|
||||
// NB: We use reflection here because this field seems to be absent on Amazon Fire OS devices
|
||||
try {
|
||||
Field mediaClassField = Build.VERSION.class.getDeclaredField("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;
|
||||
}
|
||||
} 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
|
||||
|
||||
@@ -64,8 +64,6 @@ public class ComputerManagerService extends Service {
|
||||
private boolean pollingActive = false;
|
||||
private final Lock defaultNetworkLock = new ReentrantLock();
|
||||
|
||||
private ConnectivityManager.NetworkCallback networkCallback;
|
||||
|
||||
private DiscoveryService.DiscoveryBinder discoveryBinder;
|
||||
private final ServiceConnection discoveryServiceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||
@@ -555,8 +553,7 @@ public class ComputerManagerService extends Service {
|
||||
// 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
|
||||
// as offsets from the base HTTP port and doesn't allow custom HttpsPort responses for WAN vs LAN.
|
||||
boolean portMatchesActiveAddress = details.state == ComputerDetails.State.ONLINE &&
|
||||
details.activeAddress != null && address.port == details.activeAddress.port;
|
||||
boolean portMatchesActiveAddress = details.activeAddress != null && address.port == details.activeAddress.port;
|
||||
|
||||
NvHTTP http = new NvHTTP(address, portMatchesActiveAddress ? details.httpsPort : 0, idManager.getUniqueId(), details.serverCert,
|
||||
PlatformBinding.getCryptoProvider(ComputerManagerService.this));
|
||||
@@ -746,49 +743,10 @@ public class ComputerManagerService extends Service {
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
// Unbind from the discovery service
|
||||
unbindService(discoveryServiceConnection);
|
||||
|
||||
@@ -20,11 +20,6 @@ public class ComputerDetails {
|
||||
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.port = port;
|
||||
}
|
||||
@@ -45,14 +40,7 @@ public class ComputerDetails {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (address.contains(":")) {
|
||||
// IPv6
|
||||
return "[" + address + "]:" + port;
|
||||
}
|
||||
else {
|
||||
// IPv4 and hostnames
|
||||
return address + ":" + port;
|
||||
}
|
||||
return address + ":" + port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,5 +7,4 @@ public class KeyboardPacket {
|
||||
public static final byte MODIFIER_SHIFT = 0x01;
|
||||
public static final byte MODIFIER_CTRL = 0x02;
|
||||
public static final byte MODIFIER_ALT = 0x04;
|
||||
public static final byte MODIFIER_META = 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,31 +98,8 @@ 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 {
|
||||
boolean wrongSiteLocal = false;
|
||||
boolean invalidInput = false;
|
||||
boolean success;
|
||||
int portTestResult;
|
||||
|
||||
@@ -132,26 +109,26 @@ public class AddComputerManually extends Activity {
|
||||
try {
|
||||
ComputerDetails details = new ComputerDetails();
|
||||
|
||||
// Check if we parsed a host address successfully
|
||||
URI uri = parseRawUserInputToUri(rawUserInput);
|
||||
if (uri != null && uri.getHost() != null && !uri.getHost().isEmpty()) {
|
||||
String host = uri.getHost();
|
||||
int port = uri.getPort();
|
||||
// Use URI-style parsing for the host address input
|
||||
URI uri = new URI("moonlight://" + rawUserInput);
|
||||
|
||||
// If a port was not specified, use the default
|
||||
if (port == -1) {
|
||||
port = NvHTTP.DEFAULT_HTTP_PORT;
|
||||
}
|
||||
String host = uri.getHost();
|
||||
int port = uri.getPort();
|
||||
|
||||
details.manualAddress = new ComputerDetails.AddressTuple(host, port);
|
||||
success = managerBinder.addComputerBlocking(details);
|
||||
if (!success){
|
||||
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
||||
}
|
||||
} else {
|
||||
// Invalid user input
|
||||
success = false;
|
||||
invalidInput = true;
|
||||
// URI allows empty hosts, but we don't want that
|
||||
if (host == null || host.isEmpty()) {
|
||||
throw new URISyntaxException(rawUserInput, "Host failed to parse");
|
||||
}
|
||||
|
||||
// If a port was not specified, use the default
|
||||
if (port == -1) {
|
||||
port = NvHTTP.DEFAULT_HTTP_PORT;
|
||||
}
|
||||
|
||||
details.manualAddress = new ComputerDetails.AddressTuple(host, port);
|
||||
success = managerBinder.addComputerBlocking(details);
|
||||
if (!success){
|
||||
wrongSiteLocal = isWrongSubnetSiteLocalAddress(host);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Propagate the InterruptedException to the caller for proper handling
|
||||
@@ -162,11 +139,13 @@ public class AddComputerManually extends Activity {
|
||||
// https://github.com/square/okhttp/blob/okhttp_27/okhttp/src/main/java/com/squareup/okhttp/HttpUrl.java#L705
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
invalidInput = true;
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
|
||||
// Keep the SpinnerDialog open while testing connectivity
|
||||
if (!success && !wrongSiteLocal && !invalidInput) {
|
||||
if (!success && !wrongSiteLocal) {
|
||||
// Run the test before dismissing the spinner because it can take a few seconds.
|
||||
portTestResult = MoonBridge.testClientConnectivity(ServerHelper.CONNECTION_TEST_SERVER, 443,
|
||||
MoonBridge.ML_PORT_FLAG_TCP_47984 | MoonBridge.ML_PORT_FLAG_TCP_47989);
|
||||
@@ -177,10 +156,7 @@ public class AddComputerManually extends Activity {
|
||||
|
||||
dialog.dismiss();
|
||||
|
||||
if (invalidInput) {
|
||||
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_unknown_host), false);
|
||||
}
|
||||
else if (wrongSiteLocal) {
|
||||
if (wrongSiteLocal) {
|
||||
Dialog.displayDialog(this, getResources().getString(R.string.conn_error_title), getResources().getString(R.string.addpc_wrong_sitelocal), false);
|
||||
}
|
||||
else if (!success) {
|
||||
|
||||
@@ -48,7 +48,6 @@ public class PreferenceConfiguration {
|
||||
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 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_FPS = "60";
|
||||
@@ -81,7 +80,6 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_ABSOLUTE_MOUSE_MODE = false;
|
||||
private static final boolean DEFAULT_ENABLE_AUDIO_FX = 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 AUTOSELECT_H265 = 0;
|
||||
@@ -92,15 +90,15 @@ public class PreferenceConfiguration {
|
||||
public static final int FRAME_PACING_CAP_FPS = 2;
|
||||
public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
|
||||
|
||||
public static final String RES_360P = "640x360";
|
||||
public static final String RES_480P = "854x480";
|
||||
public static final String RES_720P = "1280x720";
|
||||
public static final String RES_1080P = "1920x1080";
|
||||
public static final String RES_1440P = "2560x1440";
|
||||
public static final String RES_4K = "3840x2160";
|
||||
public static final String RES_NATIVE = "Native";
|
||||
public static final String RES_360P = "s_640x360";
|
||||
public static final String RES_480P = "s_854x480";
|
||||
public static final String RES_720P = "s_1280x720";
|
||||
public static final String RES_1080P = "s_1920x1080";
|
||||
public static final String RES_1440P = "s_2560x1440";
|
||||
public static final String RES_4K = "s_3840x2160";
|
||||
|
||||
public int width, height, fps;
|
||||
public StreamResolution resolution;
|
||||
public int fps;
|
||||
public int bitrate;
|
||||
public int videoFormat;
|
||||
public int deadzonePercentage;
|
||||
@@ -126,9 +124,10 @@ public class PreferenceConfiguration {
|
||||
public boolean absoluteMouseMode;
|
||||
public boolean enableAudioFx;
|
||||
public boolean reduceRefreshRate;
|
||||
public boolean fullRange;
|
||||
|
||||
public static boolean isNativeResolution(int width, int height) {
|
||||
// This is used only for migration to the new type code format of resolution strings
|
||||
// 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
|
||||
if (width == 640 && height == 360) {
|
||||
return false;
|
||||
@@ -178,59 +177,47 @@ public class PreferenceConfiguration {
|
||||
}
|
||||
|
||||
private static String convertFromLegacyResolutionString(String resString) {
|
||||
if (resString.equalsIgnoreCase("360p")) {
|
||||
return RES_360P;
|
||||
if (!resString.contains("x")) {
|
||||
// Convert from hardcoded strings to strings with dimensions embedded
|
||||
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 (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 if (Character.isDigit(resString.charAt(0))) {
|
||||
// Convert to type code prefix format
|
||||
String[] dims = resString.split("x");
|
||||
int width = Integer.parseInt(dims[0]);
|
||||
int height = Integer.parseInt(dims[1]);
|
||||
return new StreamResolution(width, height,
|
||||
legacyIsNativeResolution(width, height) ? StreamResolution.ResolutionType.NATIVE : StreamResolution.ResolutionType.STANDARD)
|
||||
.toPrefString();
|
||||
}
|
||||
else {
|
||||
// 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;
|
||||
return resString;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getDefaultBitrate(String resString, String fpsString) {
|
||||
int width = getWidthFromResolutionString(resString);
|
||||
int height = getHeightFromResolutionString(resString);
|
||||
StreamResolution res = new StreamResolution(resString);
|
||||
int fps = Integer.parseInt(fpsString);
|
||||
|
||||
// This table prefers 16:10 resolutions because they are
|
||||
@@ -241,23 +228,23 @@ public class PreferenceConfiguration {
|
||||
// This logic is shamelessly stolen from Moonlight Qt:
|
||||
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
||||
|
||||
if (width * height <= 640 * 360) {
|
||||
if (res.width * res.height <= 640 * 360) {
|
||||
return (int)(1000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 854 * 480) {
|
||||
else if (res.width * res.height <= 854 * 480) {
|
||||
return (int)(1500 * (fps / 30.0));
|
||||
}
|
||||
// This covers 1280x720 and 1280x800 too
|
||||
else if (width * height <= 1366 * 768) {
|
||||
else if (res.width * res.height <= 1366 * 768) {
|
||||
return (int)(5000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 1920 * 1200) {
|
||||
else if (res.width * res.height <= 1920 * 1200) {
|
||||
return (int)(10000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 2560 * 1600) {
|
||||
else if (res.width * res.height <= 2560 * 1600) {
|
||||
return (int)(20000 * (fps / 30.0));
|
||||
}
|
||||
else /* if (width * height <= 3840 * 2160) */ {
|
||||
else /* if (res.width * res.height <= 3840 * 2160) */ {
|
||||
return (int)(40000 * (fps / 30.0));
|
||||
}
|
||||
}
|
||||
@@ -351,7 +338,6 @@ public class PreferenceConfiguration {
|
||||
.remove(VIDEO_FORMAT_PREF_STRING)
|
||||
.remove(ENABLE_HDR_PREF_STRING)
|
||||
.remove(UNLOCK_FPS_STRING)
|
||||
.remove(FULL_RANGE_PREF_STRING)
|
||||
.apply();
|
||||
}
|
||||
|
||||
@@ -385,55 +371,46 @@ public class PreferenceConfiguration {
|
||||
String str = prefs.getString(LEGACY_RES_FPS_PREF_STRING, null);
|
||||
if (str != null) {
|
||||
if (str.equals("360p30")) {
|
||||
config.width = 640;
|
||||
config.height = 360;
|
||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 30;
|
||||
}
|
||||
else if (str.equals("360p60")) {
|
||||
config.width = 640;
|
||||
config.height = 360;
|
||||
config.resolution = new StreamResolution(640, 360, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 60;
|
||||
}
|
||||
else if (str.equals("720p30")) {
|
||||
config.width = 1280;
|
||||
config.height = 720;
|
||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 30;
|
||||
}
|
||||
else if (str.equals("720p60")) {
|
||||
config.width = 1280;
|
||||
config.height = 720;
|
||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 60;
|
||||
}
|
||||
else if (str.equals("1080p30")) {
|
||||
config.width = 1920;
|
||||
config.height = 1080;
|
||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 30;
|
||||
}
|
||||
else if (str.equals("1080p60")) {
|
||||
config.width = 1920;
|
||||
config.height = 1080;
|
||||
config.resolution = new StreamResolution(1920, 1080, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 60;
|
||||
}
|
||||
else if (str.equals("4K30")) {
|
||||
config.width = 3840;
|
||||
config.height = 2160;
|
||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 30;
|
||||
}
|
||||
else if (str.equals("4K60")) {
|
||||
config.width = 3840;
|
||||
config.height = 2160;
|
||||
config.resolution = new StreamResolution(3840, 2160, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 60;
|
||||
}
|
||||
else {
|
||||
// Should never get here
|
||||
config.width = 1280;
|
||||
config.height = 720;
|
||||
config.resolution = new StreamResolution(1280, 720, StreamResolution.ResolutionType.STANDARD);
|
||||
config.fps = 60;
|
||||
}
|
||||
|
||||
prefs.edit()
|
||||
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||
.putString(RESOLUTION_PREF_STRING, getResolutionString(config.width, config.height))
|
||||
.putString(RESOLUTION_PREF_STRING, config.resolution.toPrefString())
|
||||
.putString(FPS_PREF_STRING, ""+config.fps)
|
||||
.apply();
|
||||
}
|
||||
@@ -442,13 +419,12 @@ public class PreferenceConfiguration {
|
||||
String resStr = prefs.getString(RESOLUTION_PREF_STRING, PreferenceConfiguration.DEFAULT_RESOLUTION);
|
||||
|
||||
// Convert legacy resolution strings to the new style
|
||||
if (!resStr.contains("x")) {
|
||||
if (Character.isDigit(resStr.charAt(0)) || !resStr.contains("x")) {
|
||||
resStr = PreferenceConfiguration.convertFromLegacyResolutionString(resStr);
|
||||
prefs.edit().putString(RESOLUTION_PREF_STRING, resStr).apply();
|
||||
}
|
||||
|
||||
config.width = PreferenceConfiguration.getWidthFromResolutionString(resStr);
|
||||
config.height = PreferenceConfiguration.getHeightFromResolutionString(resStr);
|
||||
config.resolution = new StreamResolution(resStr);
|
||||
config.fps = Integer.parseInt(prefs.getString(FPS_PREF_STRING, PreferenceConfiguration.DEFAULT_FPS));
|
||||
}
|
||||
|
||||
@@ -509,8 +485,115 @@ public class PreferenceConfiguration {
|
||||
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.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;
|
||||
}
|
||||
|
||||
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,44 +122,49 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragment {
|
||||
private int nativeResolutionStartIndex = Integer.MAX_VALUE;
|
||||
|
||||
private void setValue(String preferenceKey, String value) {
|
||||
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||
|
||||
pref.setValue(value);
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) {
|
||||
private void addResolutionEntry(int width, int height, PreferenceConfiguration.StreamResolution.ResolutionType type,
|
||||
boolean insetsRemoved, boolean portrait) {
|
||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
||||
PreferenceConfiguration.StreamResolution newRes =
|
||||
new PreferenceConfiguration.StreamResolution(width, height, type, portrait, insetsRemoved);
|
||||
|
||||
String newName;
|
||||
|
||||
if (insetsRemoved) {
|
||||
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
||||
}
|
||||
else {
|
||||
newName = getResources().getString(R.string.resolution_prefix_native);
|
||||
}
|
||||
|
||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||
if (portrait) {
|
||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait);
|
||||
if (type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
||||
if (insetsRemoved) {
|
||||
newName = getResources().getString(R.string.resolution_prefix_native_fullscreen);
|
||||
}
|
||||
else {
|
||||
newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape);
|
||||
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 {
|
||||
newName = null;
|
||||
}
|
||||
|
||||
newName += " ("+nativeWidth+"x"+nativeHeight+")";
|
||||
|
||||
String newValue = nativeWidth+"x"+nativeHeight;
|
||||
newName += " ("+width+"x"+height+")";
|
||||
|
||||
CharSequence[] values = pref.getEntryValues();
|
||||
|
||||
// Check if the native resolution is already present
|
||||
// Check if the new resolution is already present
|
||||
for (CharSequence value : values) {
|
||||
if (newValue.equals(value.toString())) {
|
||||
PreferenceConfiguration.StreamResolution existingResolution = new PreferenceConfiguration.StreamResolution(value.toString());
|
||||
if (existingResolution.width == newRes.width && existingResolution.height == newRes.height) {
|
||||
// It is present in the default list, so don't add it again
|
||||
return;
|
||||
}
|
||||
@@ -168,23 +173,23 @@ public class StreamSettings extends Activity {
|
||||
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
||||
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
|
||||
|
||||
// Add the new native option
|
||||
// Add the new resolution option
|
||||
newEntries[newEntries.length - 1] = newName;
|
||||
newValues[newValues.length - 1] = newValue;
|
||||
newValues[newValues.length - 1] = newRes.toPrefString();
|
||||
|
||||
pref.setEntries(newEntries);
|
||||
pref.setEntryValues(newValues);
|
||||
|
||||
if (newValues.length - 1 < nativeResolutionStartIndex) {
|
||||
nativeResolutionStartIndex = newValues.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
||||
if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) {
|
||||
addNativeResolutionEntry(nativeHeight, nativeWidth, insetsRemoved, true);
|
||||
addResolutionEntry(nativeHeight, nativeWidth,
|
||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
||||
insetsRemoved, true);
|
||||
}
|
||||
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
|
||||
addResolutionEntry(nativeWidth, nativeHeight,
|
||||
PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE,
|
||||
insetsRemoved, false);
|
||||
}
|
||||
|
||||
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||
@@ -608,20 +613,10 @@ public class StreamSettings extends Activity {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||
String valueStr = (String) newValue;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
PreferenceConfiguration.StreamResolution resolution = new PreferenceConfiguration.StreamResolution(valueStr);
|
||||
|
||||
// If this is native resolution, show the warning dialog
|
||||
if (isNativeRes) {
|
||||
if (resolution.type == PreferenceConfiguration.StreamResolution.ResolutionType.NATIVE) {
|
||||
Dialog.displayDialog(getActivity(),
|
||||
getResources().getString(R.string.title_native_res_dialog),
|
||||
getResources().getString(R.string.text_native_res_dialog),
|
||||
|
||||
Submodule app/src/main/jni/moonlight-core/moonlight-common-c updated: 8169a31ecc...50c0a51b10
@@ -1,251 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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>
|
||||
<resources></resources>
|
||||
@@ -76,7 +76,7 @@
|
||||
<string name="addpc_enter_ip">Debes introducir una dirección IP</string>
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">Configuración básica</string>
|
||||
<string name="title_resolution_list">Seleccionar resolución</string>
|
||||
<string name="title_resolution_list">Seleccionar resolución y FPS</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="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="summary_video_format">HEVC reduce el ancho de banda de vídeo, pero requiere un dispositivo reciente</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Automático (Recomendado)</string>
|
||||
<string name="videoformat_hevcalways">Preferir HEVC</string>
|
||||
<string name="videoformat_hevcauto">Usar HEVC sólo si es estable</string>
|
||||
<string name="videoformat_hevcalways">Siempre usar HEVC (puede fallar)</string>
|
||||
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
||||
<string name="nettest_title_done">Prueba de Red Completada</string>
|
||||
<string name="scut_not_paired">PC no emparejado</string>
|
||||
@@ -165,7 +165,7 @@
|
||||
<string name="resolution_1440p">1440p</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="title_checkbox_enable_pip">Activar modo Pantalla-en-Pantalla para modo espectador</string>
|
||||
<string name="title_checkbox_enable_pip">Actividad modo Pantalla-en-Pantalla para observador</string>
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="audioconf_71surround">7.1 Sonido Envolvente</string>
|
||||
@@ -256,13 +256,4 @@
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="fps_90">90 FPS</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>
|
||||
@@ -228,8 +228,8 @@
|
||||
<string name="audioconf_stereo">Stéréo</string>
|
||||
<string name="audioconf_51surround">Son surround 5.1</string>
|
||||
<string name="audioconf_71surround">Son surround 7.1</string>
|
||||
<string name="videoformat_hevcauto">Automatique (recommandé)</string>
|
||||
<string name="videoformat_hevcalways">Préférez le HEVC</string>
|
||||
<string name="videoformat_hevcauto">Automatique</string>
|
||||
<string name="videoformat_hevcalways">Utilisez toujours HEVC (mais il peut planter)</string>
|
||||
<string name="videoformat_hevcnever">N\'utilisez jamais HEVC</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>
|
||||
@@ -259,9 +259,4 @@
|
||||
<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="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>
|
||||
@@ -254,13 +254,4 @@
|
||||
<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_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>
|
||||
@@ -53,8 +53,8 @@
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="videoformat_hevcalways">Prefira HEVC</string>
|
||||
<string name="videoformat_hevcauto">Automático (recomendado)</string>
|
||||
<string name="videoformat_hevcalways">Sempre usar HEVC (talvez crashe)</string>
|
||||
<string name="videoformat_hevcauto">Automático</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">5.1 Surround</string>
|
||||
@@ -245,9 +245,4 @@
|
||||
<string name="resolution_prefix_native_portrait">(Retrato)</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="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>
|
||||
@@ -218,8 +218,8 @@
|
||||
<string name="pcview_menu_header_offline">Поза мережею</string>
|
||||
<string name="pcview_menu_header_online">В мережі</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Автоматичний (рекомендовано)</string>
|
||||
<string name="videoformat_hevcalways">Використовувати HEVC</string>
|
||||
<string name="videoformat_hevcauto">Використовувати HEVC тільки якщо безпечно</string>
|
||||
<string name="videoformat_hevcalways">Завжди використовувати HEVC якщо доступно</string>
|
||||
<string name="videoformat_hevcnever">Ніколи не використовувати HEVC</string>
|
||||
<string name="title_frame_pacing">Швидкість кадрів відео</string>
|
||||
<string name="summary_frame_pacing">Укажіть баланс відео затримки та плавності</string>
|
||||
@@ -239,26 +239,4 @@
|
||||
<string name="audioconf_stereo">Стерео</string>
|
||||
<string name="audioconf_51surround">5.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>
|
||||
@@ -222,8 +222,8 @@
|
||||
<string name="audioconf_stereo">立体声</string>
|
||||
<string name="audioconf_51surround">5.1环绕声</string>
|
||||
<string name="audioconf_71surround">7.1环绕声</string>
|
||||
<string name="videoformat_hevcauto">自动(推荐)</string>
|
||||
<string name="videoformat_hevcalways">首选 HEVC</string>
|
||||
<string name="videoformat_hevcauto">自动</string>
|
||||
<string name="videoformat_hevcalways">强制使用HEVC(不稳定)</string>
|
||||
<string name="videoformat_hevcnever">不使用HEVC</string>
|
||||
<string name="title_frame_pacing">视频帧速调节</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<string name="conn_hardware_latency">硬體解碼器平均延時:</string>
|
||||
<string name="conn_starting">正在啟動</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_msg">連線已終止</string>
|
||||
<!-- General strings -->
|
||||
@@ -90,10 +90,10 @@
|
||||
<string name="applist_refresh_title">遊戲清單</string>
|
||||
<string name="applist_refresh_msg">正在重新整理…</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_success">結束成功</string>
|
||||
<string name="applist_quit_fail">無法結束</string>
|
||||
<string name="applist_quit_fail">結束失敗</string>
|
||||
<string name="applist_quit_confirmation">您確定要結束執行中的遊戲?所有未儲存的資料將丟失。</string>
|
||||
<string name="applist_details_id">App ID:</string>
|
||||
<!-- Add computer manually activity -->
|
||||
@@ -109,9 +109,9 @@
|
||||
<string name="title_resolution_list">視訊解析度</string>
|
||||
<string name="summary_resolution_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="summary_seekbar_bitrate">提高位元速率以提升圖像品質,降低可在較慢的網路中取得更好的串流體驗。</string>
|
||||
<string name="summary_seekbar_bitrate">提高位元速率以提升圖像品質,降低可在較慢的網路中獲得更好的串流體驗。</string>
|
||||
<string name="title_unlock_fps">解鎖所有可用影格速率</string>
|
||||
<string name="summary_unlock_fps">以 90 或 120 畫面更新率串流可能會減少在高效能裝置上的網路延時,但會在不支援的裝置上造成卡頓或崩潰</string>
|
||||
<string name="title_checkbox_stretch_video">將畫面延展至全螢幕</string>
|
||||
@@ -197,7 +197,7 @@
|
||||
\n如果問題仍然存在,請嘗試重新安裝 GPU 驅動程式和 GFE。</string>
|
||||
<string name="no_frame_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_failure">您裝置目前的網路連線似乎封鎖了 Moonlight。連線到該網路時可能無法透過網際網路串流。
|
||||
\n
|
||||
@@ -223,8 +223,8 @@
|
||||
<string name="audioconf_stereo">立體聲</string>
|
||||
<string name="audioconf_51surround">5.1 環場音效</string>
|
||||
<string name="audioconf_71surround">7.1 環場音效</string>
|
||||
<string name="videoformat_hevcauto">自動 (建議)</string>
|
||||
<string name="videoformat_hevcalways">優先使用 HEVC</string>
|
||||
<string name="videoformat_hevcauto">自動</string>
|
||||
<string name="videoformat_hevcalways">強制使用 HEVC (可能會當機)</string>
|
||||
<string name="videoformat_hevcnever">不使用 HEVC</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
@@ -261,6 +261,4 @@
|
||||
<string name="frame_conversion_error">主機電腦回報了一個嚴重的視訊編碼錯誤。
|
||||
\n
|
||||
\n嘗試停用 HDR 模式,變更串流解析度,或變更您的主機電腦的顯示器解析度。</string>
|
||||
<string name="title_full_range">強制全範圍視訊 (實驗性)</string>
|
||||
<string name="summary_full_range">若您的裝置無法正確地顯示全範圍視訊內容,將會導致淺色區域和深色區域的細節遺失。</string>
|
||||
</resources>
|
||||
@@ -9,14 +9,13 @@
|
||||
<item>@string/resolution_4k</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Keep this in sync with PreferenceConfiguration.isNativeResolution()! -->
|
||||
<string-array name="resolution_values" translatable="false">
|
||||
<item>640x360</item>
|
||||
<item>854x480</item>
|
||||
<item>1280x720</item>
|
||||
<item>1920x1080</item>
|
||||
<item>2560x1440</item>
|
||||
<item>3840x2160</item>
|
||||
<item>s_640x360</item>
|
||||
<item>s_854x480</item>
|
||||
<item>s_1280x720</item>
|
||||
<item>s_1920x1080</item>
|
||||
<item>s_2560x1440</item>
|
||||
<item>s_3840x2160</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="fps_names">
|
||||
@@ -64,7 +63,6 @@
|
||||
<item>Magyar</item>
|
||||
<item>Ελληνικά</item>
|
||||
<item>Português do Brasil</item>
|
||||
<item>Čeština</item>
|
||||
</string-array>
|
||||
<string-array name="language_values" translatable="false">
|
||||
<item>default</item>
|
||||
@@ -86,7 +84,6 @@
|
||||
<item>hu</item>
|
||||
<item>el</item>
|
||||
<item>pt-BR</item>
|
||||
<item>cs</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_format_names">
|
||||
|
||||
@@ -229,8 +229,6 @@
|
||||
<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="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="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>
|
||||
@@ -261,8 +259,8 @@
|
||||
<string name="audioconf_51surround">5.1 Surround Sound</string>
|
||||
<string name="audioconf_71surround">7.1 Surround Sound</string>
|
||||
|
||||
<string name="videoformat_hevcauto">Automatic (Recommended)</string>
|
||||
<string name="videoformat_hevcalways">Prefer HEVC</string>
|
||||
<string name="videoformat_hevcauto">Automatic</string>
|
||||
<string name="videoformat_hevcalways">Always use HEVC (may crash)</string>
|
||||
<string name="videoformat_hevcnever">Never use HEVC</string>
|
||||
|
||||
<string name="title_frame_pacing">Video frame pacing</string>
|
||||
|
||||
@@ -19,5 +19,4 @@
|
||||
<locale android:name="hu"/>
|
||||
<locale android:name="el"/>
|
||||
<locale android:name="pt-BR"/>
|
||||
<locale android:name="cs"/>
|
||||
</locale-config>
|
||||
@@ -211,11 +211,6 @@
|
||||
android:title="@string/title_enable_hdr"
|
||||
android:summary="@string/summary_enable_hdr"
|
||||
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
|
||||
android:key="checkbox_enable_perf_overlay"
|
||||
android:title="@string/title_enable_perf_overlay"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
- 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