mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-01 15:25:59 +00:00
Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f10085f552 | ||
|
eb7f0887bf | ||
|
34a9132d60 | ||
|
24d3fb000a | ||
|
b7b6adaff7 | ||
|
85ed72802f | ||
|
f54f8c83e7 | ||
|
124bfdf418 | ||
|
01507d9995 | ||
|
070c82bc44 | ||
|
17df15293f | ||
|
6551076613 | ||
|
1b1b100e63 | ||
|
e70014bb28 | ||
|
082cc84a71 | ||
|
2ba7f0d989 | ||
|
9a7381b35f | ||
|
613ecfff44 | ||
|
f638548a02 | ||
|
224bab68bf | ||
|
6aca18bd76 | ||
|
3c58e2fbba | ||
|
aaaebde05e | ||
|
8ff9f70bd7 | ||
|
523ca862b9 | ||
|
78b8d1e9f3 | ||
|
83c698b36d | ||
|
27fe37f221 | ||
|
3722106daf | ||
|
3ea9ef1ef2 | ||
|
fcd27b48b2 | ||
|
6ff37a17ec | ||
|
f2c6e9e32e | ||
|
dbf1b88a3d | ||
|
3aab9eb13b | ||
|
3f9f8f7b3b | ||
|
f7520ba40c | ||
|
7b13f12817 | ||
|
57e19d75e2 | ||
|
4330a223c6 | ||
|
69387c32ad | ||
|
a102ec4ee8 | ||
|
2a094437dd | ||
|
4142907376 | ||
|
e63dc9a93b | ||
|
1fe19e912e | ||
|
56ad48446e | ||
|
a18aa26985 | ||
|
5443cc014a | ||
|
7d77e1c1f2 | ||
|
ca82cd9752 | ||
|
dbd86bb861 | ||
|
0af56b4981 | ||
|
f1be5365bb | ||
|
c356862ac1 | ||
|
fc77322f59 | ||
|
032e944d49 | ||
|
0da47da8d8 | ||
|
ebfe843299 | ||
|
827d2362b7 | ||
|
4fa1eb4088 | ||
|
885b59fd52 | ||
|
ff5d9f72aa | ||
|
030bb91789 | ||
|
34788b2808 |
@ -1,18 +1,18 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
ndkVersion "23.2.8568313"
|
||||
ndkVersion "27.0.12077973"
|
||||
|
||||
compileSdk 34
|
||||
|
||||
namespace 'com.limelight'
|
||||
|
||||
defaultConfig {
|
||||
minSdk 16
|
||||
minSdk 21
|
||||
targetSdk 34
|
||||
|
||||
versionName "12.0.1"
|
||||
versionCode = 312
|
||||
versionName "12.1"
|
||||
versionCode = 314
|
||||
|
||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||
ndk.debugSymbolLevel = 'FULL'
|
||||
@ -136,12 +136,10 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
|
||||
implementation 'org.jcodec:jcodec:0.2.3'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
|
||||
implementation 'com.squareup.okio:okio:1.17.5'
|
||||
// 3.5.8 requires minSdk 19, uses StandardCharsets.UTF_8 internally
|
||||
implementation 'org.jmdns:jmdns:3.5.7'
|
||||
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
|
||||
implementation 'org.jcodec:jcodec:0.2.5'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||
implementation 'org.jmdns:jmdns:3.5.9'
|
||||
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
|
||||
}
|
||||
|
@ -50,7 +50,6 @@
|
||||
android:banner="@drawable/atv_banner"
|
||||
android:appCategory="game"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:installLocation="auto"
|
||||
android:gwpAsanMode="always"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
@ -77,6 +76,11 @@
|
||||
<meta-data
|
||||
android:name="com.android.graphics.intervention.wm.allowDownscale"
|
||||
android:value="false"/>
|
||||
|
||||
<!-- Game Mode configuration -->
|
||||
<meta-data
|
||||
android:name="android.game_mode_config"
|
||||
android:resource="@xml/game_mode_config" />
|
||||
|
||||
<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
|
||||
in each activity even though it is implied by targeting API 24+ -->
|
||||
|
@ -127,6 +127,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
private int suppressPipRefCount = 0;
|
||||
private String pcName;
|
||||
private String appName;
|
||||
private NvApp app;
|
||||
private float desiredRefreshRate;
|
||||
|
||||
private InputCaptureProvider inputCaptureProvider;
|
||||
@ -146,8 +147,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
private int requestedNotificationOverlayVisibility = View.GONE;
|
||||
private TextView performanceOverlayView;
|
||||
|
||||
private ShortcutHelper shortcutHelper;
|
||||
|
||||
private MediaCodecDecoderRenderer decoderRenderer;
|
||||
private boolean reportedCrash;
|
||||
|
||||
@ -196,14 +195,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
// If we're going to use immersive mode, we want to have
|
||||
// the entire screen
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
||||
}
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
|
||||
|
||||
// Listen for UI visibility events
|
||||
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
|
||||
@ -318,10 +315,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
int httpsPort = Game.this.getIntent().getIntExtra(EXTRA_HTTPS_PORT, 0); // 0 is treated as unknown
|
||||
int appId = Game.this.getIntent().getIntExtra(EXTRA_APP_ID, StreamConfiguration.INVALID_APP_ID);
|
||||
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
|
||||
String uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
|
||||
boolean appSupportsHdr = Game.this.getIntent().getBooleanExtra(EXTRA_APP_HDR, false);
|
||||
byte[] derCertData = Game.this.getIntent().getByteArrayExtra(EXTRA_SERVER_CERT);
|
||||
|
||||
app = new NvApp(appName != null ? appName : "app", appId, appSupportsHdr);
|
||||
|
||||
X509Certificate serverCert = null;
|
||||
try {
|
||||
if (derCertData != null) {
|
||||
@ -337,17 +335,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
return;
|
||||
}
|
||||
|
||||
// Report this shortcut being used
|
||||
ComputerDetails computer = new ComputerDetails();
|
||||
computer.name = pcName;
|
||||
computer.uuid = uuid;
|
||||
shortcutHelper = new ShortcutHelper(this);
|
||||
shortcutHelper.reportComputerShortcutUsed(computer);
|
||||
if (appName != null) {
|
||||
// This may be null if launched from the "Resume Session" PC context menu item
|
||||
shortcutHelper.reportGameLaunched(computer, new NvApp(appName, appId, appSupportsHdr));
|
||||
}
|
||||
|
||||
// Initialize the MediaCodec helper before creating the decoder
|
||||
GlPreferences glPrefs = GlPreferences.readPreferences(this);
|
||||
MediaCodecHelper.initialize(this, glPrefs.glRenderer);
|
||||
@ -479,19 +466,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
.setResolution(prefConfig.width, prefConfig.height)
|
||||
.setLaunchRefreshRate(prefConfig.fps)
|
||||
.setRefreshRate(chosenFrameRate)
|
||||
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
|
||||
.setApp(app)
|
||||
.setBitrate(prefConfig.bitrate)
|
||||
.setEnableSops(prefConfig.enableSops)
|
||||
.enableLocalAudioPlayback(prefConfig.playHostAudio)
|
||||
.setMaxPacketSize(1392)
|
||||
.setRemoteConfiguration(StreamConfiguration.STREAM_CFG_AUTO) // NvConnection will perform LAN and VPN detection
|
||||
.setHevcBitratePercentageMultiplier(75)
|
||||
.setAv1BitratePercentageMultiplier(75)
|
||||
.setSupportedVideoFormats(supportedVideoFormats)
|
||||
.setAttachedGamepadMask(gamepadMask)
|
||||
.setClientRefreshRateX100((int)(displayRefreshRate * 100))
|
||||
.setAudioConfiguration(prefConfig.audioConfiguration)
|
||||
.setAudioEncryption(true)
|
||||
.setColorSpace(decoderRenderer.getPreferredColorSpace())
|
||||
.setColorRange(decoderRenderer.getPreferredColorRange())
|
||||
.setPersistGamepadsAfterDisconnect(!prefConfig.multiController)
|
||||
@ -506,7 +490,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
keyboardTranslator = new KeyboardTranslator();
|
||||
|
||||
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.registerInputDeviceListener(controllerHandler, null);
|
||||
inputManager.registerInputDeviceListener(keyboardTranslator, null);
|
||||
|
||||
// Initialize touch contexts
|
||||
@ -521,12 +504,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
}
|
||||
|
||||
// Use sustained performance mode on N+ to ensure consistent
|
||||
// CPU availability
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
getWindow().setSustainedPerformanceMode(true);
|
||||
}
|
||||
|
||||
if (prefConfig.onscreenController) {
|
||||
// create virtual onscreen controller
|
||||
virtualController = new VirtualController(controllerHandler,
|
||||
@ -581,39 +558,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
if (desiredOrientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
|
||||
}
|
||||
else {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
}
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
|
||||
}
|
||||
else if (desiredOrientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
|
||||
}
|
||||
else {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
||||
}
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
|
||||
}
|
||||
else {
|
||||
// If we don't have a reason to lock to portrait or landscape, allow any orientation
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
|
||||
}
|
||||
else {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
|
||||
}
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For regular displays, we always request landscape
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
|
||||
}
|
||||
else {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
}
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,7 +898,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
displayRefreshRate = bestMode.getRefreshRate();
|
||||
}
|
||||
// On L, we can at least tell the OS that we want a refresh rate
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
else {
|
||||
float bestRefreshRate = display.getRefreshRate();
|
||||
for (float candidate : display.getSupportedRefreshRates()) {
|
||||
LimeLog.info("Examining refresh rate: "+candidate);
|
||||
@ -965,19 +922,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Apply the refresh rate change
|
||||
getWindow().setAttributes(windowLayoutParams);
|
||||
}
|
||||
else {
|
||||
// Otherwise, the active display refresh rate is just
|
||||
// whatever is currently in use.
|
||||
displayRefreshRate = display.getRefreshRate();
|
||||
}
|
||||
|
||||
// From 4.4 to 5.1 we can't ask for a 4K display mode, so we'll
|
||||
// Until Marshmallow, we can't ask for a 4K display mode, so we'll
|
||||
// need to hint the OS to provide one.
|
||||
boolean aspectRatioMatch = false;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
|
||||
Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
// On KitKat and later (where we can use the whole screen via immersive mode), we'll
|
||||
// calculate whether we need to scale by aspect ratio or not. If not, we'll use
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
// We'll calculate whether we need to scale by aspect ratio. If not, we'll use
|
||||
// setFixedSize so we can handle 4K properly. The only known devices that have
|
||||
// >= 4K screens have exactly 4K screens, so we'll be able to hit this good path
|
||||
// on these devices. On Marshmallow, we can start changing to 4K manually but no
|
||||
@ -1032,8 +982,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
Game.this.getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
}
|
||||
// Use immersive mode on 4.4+ or standard low profile on previous builds
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
else {
|
||||
// Use immersive mode
|
||||
Game.this.getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
@ -1042,11 +992,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||
}
|
||||
else {
|
||||
Game.this.getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1069,16 +1014,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// that case here too.
|
||||
if (isInMultiWindowMode) {
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
// Disable performance optimizations for foreground
|
||||
getWindow().setSustainedPerformanceMode(false);
|
||||
decoderRenderer.notifyVideoBackground();
|
||||
}
|
||||
else {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
// Enable performance optimizations for foreground
|
||||
getWindow().setSustainedPerformanceMode(true);
|
||||
decoderRenderer.notifyVideoForeground();
|
||||
}
|
||||
|
||||
@ -1090,12 +1029,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
||||
if (controllerHandler != null) {
|
||||
inputManager.unregisterInputDeviceListener(controllerHandler);
|
||||
controllerHandler.destroy();
|
||||
}
|
||||
if (keyboardTranslator != null) {
|
||||
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
||||
inputManager.unregisterInputDeviceListener(keyboardTranslator);
|
||||
}
|
||||
|
||||
@ -1115,6 +1053,21 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
inputCaptureProvider.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if (isFinishing()) {
|
||||
// Stop any further input device notifications before we lose focus (and pointer capture)
|
||||
if (controllerHandler != null) {
|
||||
controllerHandler.stop();
|
||||
}
|
||||
|
||||
// Ungrab input to prevent further input device notifications
|
||||
setInputGrabState(false);
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
@ -1300,10 +1253,20 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
else if ((modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT)) ==
|
||||
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT) &&
|
||||
(down && nonModifierKeyCode != KeyEvent.KEYCODE_UNKNOWN)) {
|
||||
// Remember that a special key combo was activated, so we can consume all key events until the modifiers come up
|
||||
specialKeyCode = androidKeyCode;
|
||||
waitingForAllModifiersUp = true;
|
||||
return true;
|
||||
switch (androidKeyCode) {
|
||||
case KeyEvent.KEYCODE_Z:
|
||||
case KeyEvent.KEYCODE_Q:
|
||||
case KeyEvent.KEYCODE_C:
|
||||
// Remember that a special key combo was activated, so we can consume all key
|
||||
// events until the modifiers come up
|
||||
specialKeyCode = androidKeyCode;
|
||||
waitingForAllModifiersUp = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
// This isn't a special combo that we consume on the client side
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a special combo
|
||||
@ -1869,7 +1832,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
if (deltaX != 0 || deltaY != 0) {
|
||||
if (prefConfig.absoluteMouseMode) {
|
||||
conn.sendMouseMoveAsMousePosition(deltaX, deltaY, (short)view.getWidth(), (short)view.getHeight());
|
||||
// NB: view may be null, but we can unconditionally use streamView because we don't need to adjust
|
||||
// relative axis deltas for the position of the streamView within the parent's coordinate system.
|
||||
conn.sendMouseMoveAsMousePosition(deltaX, deltaY, (short)streamView.getWidth(), (short)streamView.getHeight());
|
||||
}
|
||||
else {
|
||||
conn.sendMouseMove(deltaX, deltaY);
|
||||
@ -2215,13 +2180,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// Tell the OS not to buffer input events for us
|
||||
//
|
||||
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
|
||||
view.requestUnbufferedDispatch(event);
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
// Tell the OS not to buffer input events for us
|
||||
//
|
||||
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
|
||||
view.requestUnbufferedDispatch(event);
|
||||
}
|
||||
|
||||
return handleMotionEvent(view, event);
|
||||
@ -2319,6 +2282,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Let the display go to sleep now
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
// Stop processing controller input
|
||||
controllerHandler.stop();
|
||||
|
||||
// Ungrab input
|
||||
setInputGrabState(false);
|
||||
|
||||
@ -2356,7 +2322,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
break;
|
||||
|
||||
default:
|
||||
message = getResources().getString(R.string.conn_terminated_msg);
|
||||
String errorCodeString;
|
||||
// We'll assume large errors are hex values
|
||||
if (Math.abs(errorCode) > 1000) {
|
||||
errorCodeString = Integer.toHexString(errorCode);
|
||||
}
|
||||
else {
|
||||
errorCodeString = Integer.toString(errorCode);
|
||||
}
|
||||
message = getResources().getString(R.string.conn_terminated_msg) + "\n\n" +
|
||||
getResources().getString(R.string.error_code_prefix) + " " + errorCodeString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2443,6 +2418,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
hideSystemUi(1000);
|
||||
}
|
||||
});
|
||||
|
||||
// Report this shortcut being used (off the main thread to prevent ANRs)
|
||||
ComputerDetails computer = new ComputerDetails();
|
||||
computer.name = pcName;
|
||||
computer.uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
|
||||
ShortcutHelper shortcutHelper = new ShortcutHelper(this);
|
||||
shortcutHelper.reportComputerShortcutUsed(computer);
|
||||
if (appName != null) {
|
||||
// This may be null if launched from the "Resume Session" PC context menu item
|
||||
shortcutHelper.reportGameLaunched(computer, app);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2645,14 +2631,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
hideSystemUi(2000);
|
||||
}
|
||||
// This flag is only set on 4.4+
|
||||
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT &&
|
||||
(visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
|
||||
hideSystemUi(2000);
|
||||
}
|
||||
// This flag is only set before 4.4+
|
||||
else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT &&
|
||||
(visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
|
||||
else if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
|
||||
hideSystemUi(2000);
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +260,11 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
updateComputer(details);
|
||||
}
|
||||
});
|
||||
|
||||
// Add a launcher shortcut for this PC (off the main thread to prevent ANRs)
|
||||
if (details.pairState == PairState.PAIRED) {
|
||||
shortcutHelper.createAppViewShortcutForOnlineHost(details);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -720,11 +725,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
// Add a launcher shortcut for this PC
|
||||
if (details.pairState == PairState.PAIRED) {
|
||||
shortcutHelper.createAppViewShortcutForOnlineHost(details);
|
||||
}
|
||||
|
||||
if (existingEntry != null) {
|
||||
// Replace the information in the existing entry
|
||||
existingEntry.details = details;
|
||||
|
@ -8,19 +8,26 @@ import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.limelight.computers.ComputerDatabaseManager;
|
||||
import com.limelight.computers.ComputerManagerListener;
|
||||
import com.limelight.computers.ComputerManagerService;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.nvstream.http.NvHTTP;
|
||||
import com.limelight.nvstream.http.PairingManager;
|
||||
import com.limelight.nvstream.wol.WakeOnLanSender;
|
||||
import com.limelight.utils.CacheHelper;
|
||||
import com.limelight.utils.Dialog;
|
||||
import com.limelight.utils.ServerHelper;
|
||||
import com.limelight.utils.SpinnerDialog;
|
||||
import com.limelight.utils.UiHelper;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ShortcutTrampoline extends Activity {
|
||||
@ -33,6 +40,7 @@ public class ShortcutTrampoline extends Activity {
|
||||
private SpinnerDialog blockingLoadSpinner;
|
||||
|
||||
private ComputerManagerService.ComputerManagerBinder managerBinder;
|
||||
|
||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder binder) {
|
||||
final ComputerManagerService.ComputerManagerBinder localBinder =
|
||||
@ -214,9 +222,9 @@ public class ShortcutTrampoline extends Activity {
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean validateInput(String uuidString, String appIdString) {
|
||||
// Validate UUID
|
||||
if (uuidString == null) {
|
||||
protected boolean validateInput(String uuidString, String appIdString, String nameString) {
|
||||
// Validate PC UUID/Name
|
||||
if (uuidString == null && nameString == null) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_uuid),
|
||||
@ -224,14 +232,25 @@ public class ShortcutTrampoline extends Activity {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
UUID.fromString(uuidString);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_uuid),
|
||||
true);
|
||||
return false;
|
||||
if (uuidString != null && !uuidString.isEmpty()) {
|
||||
try {
|
||||
UUID.fromString(uuidString);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_uuid),
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// UUID is null, so fallback to Name
|
||||
if (nameString == null || nameString.isEmpty()) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_uuid),
|
||||
true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate App ID (if provided)
|
||||
@ -255,24 +274,93 @@ public class ShortcutTrampoline extends Activity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
UiHelper.notifyNewRootView(this);
|
||||
ComputerDatabaseManager dbManager = new ComputerDatabaseManager(this);
|
||||
ComputerDetails _computer = null;
|
||||
|
||||
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
|
||||
// PC arguments, both are optional, but at least one must be provided
|
||||
uuidString = getIntent().getStringExtra(AppView.UUID_EXTRA);
|
||||
String nameString = getIntent().getStringExtra(AppView.NAME_EXTRA);
|
||||
|
||||
if (validateInput(uuidString, appIdString)) {
|
||||
if (appIdString != null && !appIdString.isEmpty()) {
|
||||
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
|
||||
Integer.parseInt(appIdString),
|
||||
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
|
||||
// App arguments, both are optional, but one must be provided in order to start an app
|
||||
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
|
||||
String appNameString = getIntent().getStringExtra(Game.EXTRA_APP_NAME);
|
||||
|
||||
if (!validateInput(uuidString, appIdString, nameString)) {
|
||||
// Invalid input, so just return
|
||||
return;
|
||||
}
|
||||
|
||||
if (uuidString == null || uuidString.isEmpty()) {
|
||||
// Use nameString to find the corresponding UUID
|
||||
_computer = dbManager.getComputerByName(nameString);
|
||||
|
||||
if (_computer == null) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_pc_not_found),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind to the computer manager service
|
||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||
Service.BIND_AUTO_CREATE);
|
||||
uuidString = _computer.uuid;
|
||||
|
||||
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||
getResources().getString(R.string.applist_connect_msg), true);
|
||||
// Set the AppView UUID intent, since it wasn't provided
|
||||
setIntent(new Intent(getIntent()).putExtra(AppView.UUID_EXTRA, uuidString));
|
||||
}
|
||||
|
||||
if (appIdString != null && !appIdString.isEmpty()) {
|
||||
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
|
||||
Integer.parseInt(appIdString),
|
||||
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
|
||||
}
|
||||
else if (appNameString != null && !appNameString.isEmpty()) {
|
||||
// Use appNameString to find the corresponding AppId
|
||||
try {
|
||||
int appId = -1;
|
||||
String rawAppList = CacheHelper.readInputStreamToString(CacheHelper.openCacheFileForInput(getCacheDir(), "applist", uuidString));
|
||||
|
||||
if (rawAppList.isEmpty()) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_app_id),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
List<NvApp> applist = NvHTTP.getAppListByReader(new StringReader(rawAppList));
|
||||
|
||||
for (NvApp _app : applist) {
|
||||
if (_app.getAppName().equals(appNameString)) {
|
||||
appId = _app.getAppId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (appId < 0) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_app_id),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
setIntent(new Intent(getIntent()).putExtra(Game.EXTRA_APP_ID, appId));
|
||||
app = new NvApp(
|
||||
appNameString,
|
||||
appId,
|
||||
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
Dialog.displayDialog(ShortcutTrampoline.this,
|
||||
getResources().getString(R.string.conn_error_title),
|
||||
getResources().getString(R.string.scut_invalid_app_id),
|
||||
true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Bind to the computer manager service
|
||||
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
|
||||
Service.BIND_AUTO_CREATE);
|
||||
|
||||
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
|
||||
getResources().getString(R.string.applist_connect_msg), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,51 +26,41 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
||||
}
|
||||
|
||||
private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new AudioTrack(AudioManager.STREAM_MUSIC,
|
||||
sampleRate,
|
||||
channelConfig,
|
||||
AudioFormat.ENCODING_PCM_16BIT,
|
||||
bufferSize,
|
||||
AudioTrack.MODE_STREAM);
|
||||
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME);
|
||||
AudioFormat format = new AudioFormat.Builder()
|
||||
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
||||
.setSampleRate(sampleRate)
|
||||
.setChannelMask(channelConfig)
|
||||
.build();
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
// Use FLAG_LOW_LATENCY on L through N
|
||||
if (lowLatency) {
|
||||
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
|
||||
.setAudioFormat(format)
|
||||
.setAudioAttributes(attributesBuilder.build())
|
||||
.setTransferMode(AudioTrack.MODE_STREAM)
|
||||
.setBufferSizeInBytes(bufferSize);
|
||||
|
||||
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
|
||||
if (lowLatency) {
|
||||
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
|
||||
}
|
||||
|
||||
return trackBuilder.build();
|
||||
}
|
||||
else {
|
||||
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME);
|
||||
AudioFormat format = new AudioFormat.Builder()
|
||||
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
|
||||
.setSampleRate(sampleRate)
|
||||
.setChannelMask(channelConfig)
|
||||
.build();
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
// Use FLAG_LOW_LATENCY on L through N
|
||||
if (lowLatency) {
|
||||
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
|
||||
.setAudioFormat(format)
|
||||
.setAudioAttributes(attributesBuilder.build())
|
||||
.setTransferMode(AudioTrack.MODE_STREAM)
|
||||
.setBufferSizeInBytes(bufferSize);
|
||||
|
||||
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
|
||||
if (lowLatency) {
|
||||
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
|
||||
}
|
||||
|
||||
return trackBuilder.build();
|
||||
}
|
||||
else {
|
||||
return new AudioTrack(attributesBuilder.build(),
|
||||
format,
|
||||
bufferSize,
|
||||
AudioTrack.MODE_STREAM,
|
||||
AudioManager.AUDIO_SESSION_ID_GENERATE);
|
||||
}
|
||||
return new AudioTrack(attributesBuilder.build(),
|
||||
format,
|
||||
bufferSize,
|
||||
AudioTrack.MODE_STREAM,
|
||||
AudioManager.AUDIO_SESSION_ID_GENERATE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,20 +81,10 @@ public class AndroidAudioRenderer implements AudioRenderer {
|
||||
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
|
||||
break;
|
||||
case 8:
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
|
||||
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
|
||||
// in 5.0, so just hardcode the constant so we can work on Lollipop.
|
||||
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
|
||||
}
|
||||
else {
|
||||
// On KitKat and lower, creation of the AudioTrack will fail if we specify
|
||||
// CHANNEL_OUT_SIDE_LEFT or CHANNEL_OUT_SIDE_RIGHT. That leaves us with
|
||||
// the old CHANNEL_OUT_7POINT1 which uses left-of-center and right-of-center
|
||||
// speakers instead of side-left and side-right. This non-standard layout
|
||||
// is probably not what the user wants, but we don't really have a choice.
|
||||
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1;
|
||||
}
|
||||
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
|
||||
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
|
||||
// in 5.0, so just hardcode the constant so we can work on Lollipop.
|
||||
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
|
||||
break;
|
||||
default:
|
||||
LimeLog.severe("Decoder returned unhandled channel count");
|
||||
|
@ -12,12 +12,12 @@ import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Calendar;
|
||||
@ -48,7 +48,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
||||
private final File keyFile;
|
||||
|
||||
private X509Certificate cert;
|
||||
private RSAPrivateKey key;
|
||||
private PrivateKey key;
|
||||
private byte[] pemCertBytes;
|
||||
|
||||
private static final Object globalCryptoLock = new Object();
|
||||
@ -94,7 +94,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
||||
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
|
||||
pemCertBytes = certBytes;
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
|
||||
key = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
|
||||
key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
|
||||
} catch (CertificateException e) {
|
||||
// May happen if the cert is corrupt
|
||||
LimeLog.warning("Corrupted certificate");
|
||||
@ -144,7 +144,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
||||
try {
|
||||
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
|
||||
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
|
||||
key = (RSAPrivateKey) keyPair.getPrivate();
|
||||
key = keyPair.getPrivate();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -215,7 +215,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public RSAPrivateKey getClientPrivateKey() {
|
||||
public PrivateKey getClientPrivateKey() {
|
||||
// Use a lock here to ensure only one guy will be generating or loading
|
||||
// the certificate and key at a time
|
||||
synchronized (globalCryptoLock) {
|
||||
|
@ -114,6 +114,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
private final double stickDeadzone;
|
||||
private final InputDeviceContext defaultContext = new InputDeviceContext();
|
||||
private final GameGestures gestures;
|
||||
private final InputManager inputManager;
|
||||
private final Vibrator deviceVibrator;
|
||||
private final VibratorManager deviceVibratorManager;
|
||||
private final SensorManager deviceSensorManager;
|
||||
@ -134,6 +135,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
this.prefConfig = prefConfig;
|
||||
this.deviceVibrator = (Vibrator) activityContext.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
this.deviceSensorManager = (SensorManager) activityContext.getSystemService(Context.SENSOR_SERVICE);
|
||||
this.inputManager = (InputManager) activityContext.getSystemService(Context.INPUT_SERVICE);
|
||||
this.mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
// Create a HandlerThread to process battery state updates. These can be slow enough
|
||||
@ -205,6 +207,9 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// currentControllers set which will allow them to properly unplug
|
||||
// if they are removed.
|
||||
initialControllers = getAttachedControllerMask(activityContext);
|
||||
|
||||
// Register ourselves for input device notifications
|
||||
inputManager.registerInputDeviceListener(this, null);
|
||||
}
|
||||
|
||||
private static InputDevice.MotionRange getMotionRangeForJoystickAxis(InputDevice dev, int axis) {
|
||||
@ -260,9 +265,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop new device contexts from being created or used
|
||||
stopped = true;
|
||||
|
||||
// Unregister our input device callbacks
|
||||
inputManager.unregisterInputDeviceListener(this);
|
||||
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
deviceContext.destroy();
|
||||
@ -293,6 +305,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
|
||||
public void enableSensors() {
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
deviceContext.enableSensors();
|
||||
@ -650,7 +666,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// back button to function for navigation.
|
||||
//
|
||||
// First, check if this is an internal device we're being called on.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && !isExternal(dev)) {
|
||||
if (!isExternal(dev)) {
|
||||
InputManager im = (InputManager) activityContext.getSystemService(Context.INPUT_SERVICE);
|
||||
|
||||
boolean foundInternalGamepad = false;
|
||||
@ -696,10 +712,8 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
String devName = dev.getName();
|
||||
|
||||
LimeLog.info("Creating controller context for device: "+devName);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
LimeLog.info("Vendor ID: "+dev.getVendorId());
|
||||
LimeLog.info("Product ID: "+dev.getProductId());
|
||||
}
|
||||
LimeLog.info("Vendor ID: " + dev.getVendorId());
|
||||
LimeLog.info("Product ID: "+dev.getProductId());
|
||||
LimeLog.info(dev.toString());
|
||||
|
||||
context.inputDevice = dev;
|
||||
@ -707,15 +721,13 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
context.id = dev.getId();
|
||||
context.external = isExternal(dev);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
context.vendorId = dev.getVendorId();
|
||||
context.productId = dev.getProductId();
|
||||
context.vendorId = dev.getVendorId();
|
||||
context.productId = dev.getProductId();
|
||||
|
||||
// These aren't always present in the Android key layout files, so they won't show up
|
||||
// in our normal InputDevice.hasKeys() probing.
|
||||
context.hasPaddles = MoonBridge.guessControllerHasPaddles(context.vendorId, context.productId);
|
||||
context.hasShare = MoonBridge.guessControllerHasShareButton(context.vendorId, context.productId);
|
||||
}
|
||||
// These aren't always present in the Android key layout files, so they won't show up
|
||||
// in our normal InputDevice.hasKeys() probing.
|
||||
context.hasPaddles = MoonBridge.guessControllerHasPaddles(context.vendorId, context.productId);
|
||||
context.hasShare = MoonBridge.guessControllerHasShareButton(context.vendorId, context.productId);
|
||||
|
||||
// Try to use the InputDevice's associated vibrators first
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasQuadAmplitudeControlledRumbleVibrators(dev.getVibratorManager())) {
|
||||
@ -762,13 +774,21 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this device has a usable RGB LED and cache that result
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
for (Light light : dev.getLightsManager().getLights()) {
|
||||
if (light.hasRgbControl()) {
|
||||
context.hasRgbLed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if the gamepad has Mode and Select buttons according to the Android key layouts.
|
||||
// We do this first because other codepaths below may override these defaults.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
boolean[] buttons = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_MODE, KeyEvent.KEYCODE_BUTTON_SELECT, KeyEvent.KEYCODE_BACK, 0);
|
||||
context.hasMode = buttons[0];
|
||||
context.hasSelect = buttons[1] || buttons[2];
|
||||
}
|
||||
boolean[] buttons = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_MODE, KeyEvent.KEYCODE_BUTTON_SELECT, KeyEvent.KEYCODE_BACK, 0);
|
||||
context.hasMode = buttons[0];
|
||||
context.hasSelect = buttons[1] || buttons[2];
|
||||
|
||||
context.touchpadXRange = dev.getMotionRange(MotionEvent.AXIS_X, InputDevice.SOURCE_TOUCHPAD);
|
||||
context.touchpadYRange = dev.getMotionRange(MotionEvent.AXIS_Y, InputDevice.SOURCE_TOUCHPAD);
|
||||
@ -818,22 +838,15 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
InputDevice.MotionRange rxRange = getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_RX);
|
||||
InputDevice.MotionRange ryRange = getMotionRangeForJoystickAxis(dev, MotionEvent.AXIS_RY);
|
||||
if (rxRange != null && ryRange != null && devName != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (dev.getVendorId() == 0x054c) { // Sony
|
||||
if (dev.hasKeys(KeyEvent.KEYCODE_BUTTON_C)[0]) {
|
||||
LimeLog.info("Detected non-standard DualShock 4 mapping");
|
||||
context.isNonStandardDualShock4 = true;
|
||||
}
|
||||
else {
|
||||
LimeLog.info("Detected DualShock 4 (Linux standard mapping)");
|
||||
context.usesLinuxGamepadStandardFaceButtons = true;
|
||||
}
|
||||
if (dev.getVendorId() == 0x054c) { // Sony
|
||||
if (dev.hasKeys(KeyEvent.KEYCODE_BUTTON_C)[0]) {
|
||||
LimeLog.info("Detected non-standard DualShock 4 mapping");
|
||||
context.isNonStandardDualShock4 = true;
|
||||
} else {
|
||||
LimeLog.info("Detected DualShock 4 (Linux standard mapping)");
|
||||
context.usesLinuxGamepadStandardFaceButtons = true;
|
||||
}
|
||||
}
|
||||
else if (!devName.contains("Xbox") && !devName.contains("XBox") && !devName.contains("X-Box")) {
|
||||
LimeLog.info("Assuming non-standard DualShock 4 mapping on < 4.4");
|
||||
context.isNonStandardDualShock4 = true;
|
||||
}
|
||||
|
||||
if (context.isNonStandardDualShock4) {
|
||||
// The old DS4 driver uses RX and RY for triggers
|
||||
@ -917,16 +930,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
|
||||
// The ADT-1 controller needs a similar fixup to the ASUS Gamepad
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// The device name provided is just "Gamepad" which is pretty useless, so we
|
||||
// use VID/PID instead
|
||||
if (dev.getVendorId() == 0x18d1 && dev.getProductId() == 0x2c40) {
|
||||
context.backIsStart = true;
|
||||
context.modeIsSelect = true;
|
||||
context.triggerDeadzone = 0.30f;
|
||||
context.hasSelect = true;
|
||||
context.hasMode = false;
|
||||
}
|
||||
if (dev.getVendorId() == 0x18d1 && dev.getProductId() == 0x2c40) {
|
||||
context.backIsStart = true;
|
||||
context.modeIsSelect = true;
|
||||
context.triggerDeadzone = 0.30f;
|
||||
context.hasSelect = true;
|
||||
context.hasMode = false;
|
||||
}
|
||||
|
||||
context.ignoreBack = shouldIgnoreBack(dev);
|
||||
@ -936,16 +945,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
// use the back button as start since it doesn't have a start/menu button
|
||||
// on the controller
|
||||
if (devName.contains("ASUS Gamepad")) {
|
||||
// We can only do this check on KitKat or higher, but it doesn't matter since ATV
|
||||
// is Android 5.0 anyway
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
boolean[] hasStartKey = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_MENU, 0);
|
||||
if (!hasStartKey[0] && !hasStartKey[1]) {
|
||||
context.backIsStart = true;
|
||||
context.modeIsSelect = true;
|
||||
context.hasSelect = true;
|
||||
context.hasMode = false;
|
||||
}
|
||||
boolean[] hasStartKey = dev.hasKeys(KeyEvent.KEYCODE_BUTTON_START, KeyEvent.KEYCODE_MENU, 0);
|
||||
if (!hasStartKey[0] && !hasStartKey[1]) {
|
||||
context.backIsStart = true;
|
||||
context.modeIsSelect = true;
|
||||
context.hasSelect = true;
|
||||
context.hasMode = false;
|
||||
}
|
||||
|
||||
// The ASUS Gamepad has triggers that sit far forward and are prone to false presses
|
||||
@ -988,6 +993,12 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
}
|
||||
|
||||
// Thrustmaster Score A gamepad home button reports directly to android as
|
||||
// KEY_HOMEPAGE event on another event channel
|
||||
if (dev.getVendorId() == 0x044f && dev.getProductId() == 0xb328) {
|
||||
context.hasMode = false;
|
||||
}
|
||||
|
||||
LimeLog.info("Analog stick deadzone: "+context.leftStickDeadzoneRadius+" "+context.rightStickDeadzoneRadius);
|
||||
LimeLog.info("Trigger deadzone: "+context.triggerDeadzone);
|
||||
|
||||
@ -1823,21 +1834,30 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
return true;
|
||||
}
|
||||
|
||||
private short scaleRawStickAxis(float stickValue) {
|
||||
return (short)Math.pow(stickValue, 3);
|
||||
}
|
||||
|
||||
private void sendEmulatedMouseEvent(short x, short y) {
|
||||
private Vector2d convertRawStickAxisToPixelMovement(short stickX, short stickY) {
|
||||
Vector2d vector = new Vector2d();
|
||||
vector.initialize(x, y);
|
||||
vector.initialize(stickX, stickY);
|
||||
vector.scalarMultiply(1 / 32766.0f);
|
||||
vector.scalarMultiply(4);
|
||||
if (vector.getMagnitude() > 0) {
|
||||
// Move faster as the stick is pressed further from center
|
||||
vector.scalarMultiply(Math.pow(vector.getMagnitude(), 2));
|
||||
if (vector.getMagnitude() >= 1) {
|
||||
conn.sendMouseMove((short)vector.getX(), (short)-vector.getY());
|
||||
}
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
private void sendEmulatedMouseMove(short x, short y) {
|
||||
Vector2d vector = convertRawStickAxisToPixelMovement(x, y);
|
||||
if (vector.getMagnitude() >= 1) {
|
||||
conn.sendMouseMove((short)vector.getX(), (short)-vector.getY());
|
||||
}
|
||||
}
|
||||
|
||||
private void sendEmulatedMouseScroll(short x, short y) {
|
||||
Vector2d vector = convertRawStickAxisToPixelMovement(x, y);
|
||||
if (vector.getMagnitude() >= 1) {
|
||||
conn.sendMouseHighResScroll((short)vector.getY());
|
||||
conn.sendMouseHighResHScroll((short)vector.getX());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2005,21 +2025,22 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
.build();
|
||||
vibrator.vibrate(VibrationEffect.createWaveform(new long[]{0, onTime, offTime}, 0), vibrationAttributes);
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
else {
|
||||
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_GAME)
|
||||
.build();
|
||||
vibrator.vibrate(new long[]{0, onTime, offTime}, 0, audioAttributes);
|
||||
}
|
||||
else {
|
||||
vibrator.vibrate(new long[]{0, onTime, offTime}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRumble(short controllerNumber, short lowFreqMotor, short highFreqMotor) {
|
||||
boolean foundMatchingDevice = false;
|
||||
boolean vibrated = false;
|
||||
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
|
||||
@ -2074,12 +2095,25 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
else if (foundMatchingDevice && !vibrated && prefConfig.vibrateFallbackToDevice) {
|
||||
// We found a device to vibrate but it didn't have rumble support. The user
|
||||
// has requested us to vibrate the device in this case.
|
||||
rumbleSingleVibrator(deviceVibrator, lowFreqMotor, highFreqMotor);
|
||||
|
||||
// We cast the unsigned short value to a signed int before multiplying by
|
||||
// the preferred strength. The resulting value is capped at 65534 before
|
||||
// we cast it back to a short so it doesn't go above 100%.
|
||||
short lowFreqMotorAdjusted = (short)(Math.min((((lowFreqMotor & 0xffff)
|
||||
* prefConfig.vibrateFallbackToDeviceStrength) / 100), Short.MAX_VALUE*2));
|
||||
short highFreqMotorAdjusted = (short)(Math.min((((highFreqMotor & 0xffff)
|
||||
* prefConfig.vibrateFallbackToDeviceStrength) / 100), Short.MAX_VALUE*2));
|
||||
|
||||
rumbleSingleVibrator(deviceVibrator, lowFreqMotorAdjusted, highFreqMotorAdjusted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
@ -2191,6 +2225,10 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
|
||||
public void handleSetMotionEventState(final short controllerNumber, final byte motionType, short reportRateHz) {
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Report rate is restricted to <= 200 Hz without the HIGH_SAMPLING_RATE_SENSORS permission
|
||||
reportRateHz = (short) Math.min(200, reportRateHz);
|
||||
|
||||
@ -2252,11 +2290,16 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
}
|
||||
|
||||
public void handleSetControllerLED(short controllerNumber, byte r, byte g, byte b) {
|
||||
if (stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
for (int i = 0; i < inputDeviceContexts.size(); i++) {
|
||||
InputDeviceContext deviceContext = inputDeviceContexts.valueAt(i);
|
||||
|
||||
if (deviceContext.controllerNumber == controllerNumber) {
|
||||
// Ignore input devices without an RGB LED
|
||||
if (deviceContext.controllerNumber == controllerNumber && deviceContext.hasRgbLed) {
|
||||
// Create a new light session if one doesn't already exist
|
||||
if (deviceContext.lightsSession == null) {
|
||||
deviceContext.lightsSession = deviceContext.inputDevice.getLightsManager().openSession();
|
||||
@ -2855,9 +2898,19 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
return;
|
||||
}
|
||||
|
||||
// Send mouse movement events from analog sticks
|
||||
sendEmulatedMouseEvent(leftStickX, leftStickY);
|
||||
sendEmulatedMouseEvent(rightStickX, rightStickY);
|
||||
// Send mouse events from analog sticks
|
||||
if (prefConfig.analogStickForScrolling == PreferenceConfiguration.AnalogStickForScrolling.RIGHT) {
|
||||
sendEmulatedMouseMove(leftStickX, leftStickY);
|
||||
sendEmulatedMouseScroll(rightStickX, rightStickY);
|
||||
}
|
||||
else if (prefConfig.analogStickForScrolling == PreferenceConfiguration.AnalogStickForScrolling.LEFT) {
|
||||
sendEmulatedMouseMove(rightStickX, rightStickY);
|
||||
sendEmulatedMouseScroll(leftStickX, leftStickY);
|
||||
}
|
||||
else {
|
||||
sendEmulatedMouseMove(leftStickX, leftStickY);
|
||||
sendEmulatedMouseMove(rightStickX, rightStickY);
|
||||
}
|
||||
|
||||
// Requeue the callback
|
||||
mainThreadHandler.postDelayed(this, mouseEmulationReportPeriod);
|
||||
@ -2898,6 +2951,7 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
|
||||
public InputDevice inputDevice;
|
||||
|
||||
public boolean hasRgbLed;
|
||||
public LightsManager.LightsSession lightsSession;
|
||||
|
||||
// These are BatteryState values, not Moonlight values
|
||||
@ -3006,11 +3060,6 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
|
||||
@Override
|
||||
public void sendControllerArrival() {
|
||||
// Below KitKat we can't get enough information to report controller details accurately
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte type;
|
||||
switch (inputDevice.getVendorId()) {
|
||||
case 0x045e: // Microsoft
|
||||
@ -3065,19 +3114,20 @@ public class ControllerHandler implements InputManager.InputDeviceListener, UsbD
|
||||
capabilities |= MoonBridge.LI_CCAP_RUMBLE;
|
||||
}
|
||||
|
||||
if (inputDevice.getBatteryState().isPresent()) {
|
||||
// Calling InputDevice.getBatteryState() to see if a battery is present
|
||||
// performs a Binder transaction that can cause ANRs on some devices.
|
||||
// To avoid this, we will just claim we can report battery state for all
|
||||
// external gamepad devices on Android S. If it turns out that no battery
|
||||
// is actually present, we'll just report unknown battery state to the host.
|
||||
if (external) {
|
||||
capabilities |= MoonBridge.LI_CCAP_BATTERY_STATE;
|
||||
}
|
||||
|
||||
for (Light light : inputDevice.getLightsManager().getLights()) {
|
||||
if (light.hasRgbControl()) {
|
||||
// Light.hasRgbControl() was totally broken prior to Android 14.
|
||||
// It always returned true because LIGHT_CAPABILITY_RGB was defined as 0,
|
||||
// so we will just guess RGB is supported if it's a PlayStation controller.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE || type == MoonBridge.LI_CTYPE_PS) {
|
||||
capabilities |= MoonBridge.LI_CCAP_RGB_LED;
|
||||
}
|
||||
}
|
||||
// Light.hasRgbControl() was totally broken prior to Android 14.
|
||||
// It always returned true because LIGHT_CAPABILITY_RGB was defined as 0,
|
||||
// so we will just guess RGB is supported if it's a PlayStation controller.
|
||||
if (hasRgbLed && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE || type == MoonBridge.LI_CTYPE_PS)) {
|
||||
capabilities |= MoonBridge.LI_CCAP_RGB_LED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,9 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
||||
public void showCursor() {
|
||||
super.showCursor();
|
||||
|
||||
// It is important to unregister the listener *before* releasing pointer capture,
|
||||
// because releasing pointer capture can cause an onInputDeviceChanged() callback
|
||||
// for devices with a touchpad (like a DS4 controller).
|
||||
inputManager.unregisterInputDeviceListener(this);
|
||||
targetView.releasePointerCapture();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.limelight.binding.input.driver;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
@ -210,28 +211,22 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
}
|
||||
|
||||
public static boolean isRecognizedInputDevice(UsbDevice device) {
|
||||
// On KitKat and later, we can determine if this VID and PID combo
|
||||
// matches an existing input device and defer to the built-in controller
|
||||
// support in that case. Prior to KitKat, we'll always return true to be safe.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDev = InputDevice.getDevice(id);
|
||||
if (inputDev == null) {
|
||||
// Device was removed while looping
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inputDev.getVendorId() == device.getVendorId() &&
|
||||
inputDev.getProductId() == device.getProductId()) {
|
||||
return true;
|
||||
}
|
||||
// Determine if this VID and PID combo matches an existing input device
|
||||
// and defer to the built-in controller support in that case.
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDev = InputDevice.getDevice(id);
|
||||
if (inputDev == null) {
|
||||
// Device was removed while looping
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
if (inputDev.getVendorId() == device.getVendorId() &&
|
||||
inputDev.getProductId() == device.getProductId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean kernelSupportsXboxOne() {
|
||||
@ -286,6 +281,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
((!kernelSupportsXbox360W() || claimAllAvailable) && Xbox360WirelessDongle.canClaimDevice(device));
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||
private void start() {
|
||||
if (started || usbManager == null) {
|
||||
return;
|
||||
|
@ -39,6 +39,7 @@ public class Xbox360Controller extends AbstractXboxController {
|
||||
0x20d6, // PowerA
|
||||
0x24c6, // PowerA
|
||||
0x2f24, // GameSir
|
||||
0x2dc8, // 8BitDo
|
||||
};
|
||||
|
||||
public static boolean canClaimDevice(UsbDevice device) {
|
||||
|
@ -89,28 +89,26 @@ public class Xbox360WirelessDongle extends AbstractController {
|
||||
public boolean start() {
|
||||
int controllerIndex = 0;
|
||||
|
||||
// On KitKat, there is a controller number associated with input devices.
|
||||
// On Android, there is a controller number associated with input devices.
|
||||
// We can use this to approximate the likely controller number. This won't
|
||||
// be completely accurate because there's no guarantee the order of interfaces
|
||||
// matches the order that devices were enumerated by xpad, but it's probably
|
||||
// better than nothing.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDev = InputDevice.getDevice(id);
|
||||
if (inputDev == null) {
|
||||
// Device was removed while looping
|
||||
continue;
|
||||
}
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice inputDev = InputDevice.getDevice(id);
|
||||
if (inputDev == null) {
|
||||
// Device was removed while looping
|
||||
continue;
|
||||
}
|
||||
|
||||
// Newer xpad versions use a special product ID (0x02a1) for controllers
|
||||
// rather than copying the product ID of the dongle itself.
|
||||
if (inputDev.getVendorId() == device.getVendorId() &&
|
||||
(inputDev.getProductId() == device.getProductId() ||
|
||||
inputDev.getProductId() == 0x02a1) &&
|
||||
inputDev.getControllerNumber() > 0) {
|
||||
controllerIndex = inputDev.getControllerNumber() - 1;
|
||||
break;
|
||||
}
|
||||
// Newer xpad versions use a special product ID (0x02a1) for controllers
|
||||
// rather than copying the product ID of the dongle itself.
|
||||
if (inputDev.getVendorId() == device.getVendorId() &&
|
||||
(inputDev.getProductId() == device.getProductId() ||
|
||||
inputDev.getProductId() == 0x02a1) &&
|
||||
inputDev.getControllerNumber() > 0) {
|
||||
controllerIndex = inputDev.getControllerNumber() - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,10 @@ public class VirtualControllerConfigurationLoader {
|
||||
private static final int START_BACK_WIDTH = 12;
|
||||
private static final int START_BACK_HEIGHT = 7;
|
||||
|
||||
// Make the Guide Menu be in the center of START and BACK menu
|
||||
private static final int GUIDE_X = START_X-BACK_X;
|
||||
private static final int GUIDE_Y = START_BACK_Y;
|
||||
|
||||
public static void createDefaultLayout(final VirtualController controller, final Context context) {
|
||||
|
||||
DisplayMetrics screen = context.getResources().getDisplayMetrics();
|
||||
@ -333,6 +337,16 @@ public class VirtualControllerConfigurationLoader {
|
||||
);
|
||||
}
|
||||
|
||||
if(config.showGuideButton){
|
||||
controller.addElement(createDigitalButton(VirtualControllerElement.EID_GDB,
|
||||
ControllerPacket.SPECIAL_BUTTON_FLAG, 0, 1, "GUIDE", -1, controller, context),
|
||||
screenScale(GUIDE_X, height)+ rightDisplacement,
|
||||
screenScale(GUIDE_Y, height),
|
||||
screenScale(START_BACK_WIDTH, height),
|
||||
screenScale(START_BACK_HEIGHT, height)
|
||||
);
|
||||
}
|
||||
|
||||
controller.setOpacity(config.oscOpacity);
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ public abstract class VirtualControllerElement extends View {
|
||||
public static final int EID_RS = 13;
|
||||
public static final int EID_LSB = 14;
|
||||
public static final int EID_RSB = 15;
|
||||
public static final int EID_GDB = 16;
|
||||
|
||||
protected VirtualController virtualController;
|
||||
protected final int elementId;
|
||||
|
@ -471,9 +471,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, refreshRate);
|
||||
}
|
||||
|
||||
// Adaptive playback can also be enabled by the whitelist on pre-KitKat devices
|
||||
// so we don't fill these pre-KitKat
|
||||
if (adaptivePlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// Populate keys for adaptive playback
|
||||
if (adaptivePlayback) {
|
||||
videoFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, initialWidth);
|
||||
videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, initialHeight);
|
||||
}
|
||||
@ -486,7 +485,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
|
||||
// If the stream is HDR-capable, the decoder will detect transitions in color standards
|
||||
// rather than us hardcoding them into the MediaFormat.
|
||||
if (getActiveVideoFormat() != MoonBridge.VIDEO_FORMAT_H265_MAIN10) {
|
||||
if ((getActiveVideoFormat() & MoonBridge.VIDEO_FORMAT_MASK_10BIT) == 0) {
|
||||
// Set color format keys when not in HDR mode, since we know they won't change
|
||||
videoFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
|
||||
switch (getPreferredColorSpace()) {
|
||||
|
@ -596,45 +596,39 @@ public class MediaCodecHelper {
|
||||
|
||||
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
// If adaptive playback is supported, we can submit new CSD together with a keyframe
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
||||
{
|
||||
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Tolerate buggy codecs
|
||||
e.printStackTrace();
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) {
|
||||
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Tolerate buggy codecs
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
|
||||
// Possibly enable adaptive playback on KitKat and above
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
|
||||
LimeLog.info("Decoder blacklisted for adaptive playback");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
||||
{
|
||||
// This will make getCapabilities() return that adaptive playback is supported
|
||||
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Tolerate buggy codecs
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
|
||||
LimeLog.info("Decoder blacklisted for adaptive playback");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
if (decoderInfo.getCapabilitiesForType(mimeType).
|
||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
||||
{
|
||||
// This will make getCapabilities() return that adaptive playback is supported
|
||||
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Tolerate buggy codecs
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -709,13 +703,6 @@ public class MediaCodecHelper {
|
||||
}
|
||||
|
||||
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
|
||||
// Google didn't have official support for HEVC (or more importantly, a CTS test) until
|
||||
// Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC,
|
||||
// so I'm restricting HEVC usage to Lollipop and higher.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Software decoders are terrible and we never want to use them.
|
||||
// We want to catch decoders like:
|
||||
@ -784,17 +771,10 @@ public class MediaCodecHelper {
|
||||
@SuppressLint("NewApi")
|
||||
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
|
||||
LinkedList<MediaCodecInfo> infoList = new LinkedList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
||||
Collections.addAll(infoList, mcl.getCodecInfos());
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
|
||||
infoList.add(MediaCodecList.getCodecInfoAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
|
||||
Collections.addAll(infoList, mcl.getCodecInfos());
|
||||
|
||||
return infoList;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,35 @@ public class ComputerDatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a computer by name
|
||||
* NOTE: It is perfectly valid for multiple computers to have the same name,
|
||||
* this function will only return the first one it finds.
|
||||
* Consider using getComputerByUUID instead.
|
||||
* @param name The name of the computer
|
||||
* @see ComputerDatabaseManager#getComputerByUUID(String) for alternative.
|
||||
* @return The computer details, or null if no computer with that name exists
|
||||
*/
|
||||
public ComputerDetails getComputerByName(String name) {
|
||||
try (final Cursor c = computerDb.query(
|
||||
COMPUTER_TABLE_NAME, null, COMPUTER_NAME_COLUMN_NAME+"=?",
|
||||
new String[]{ name }, null, null, null)
|
||||
) {
|
||||
if (!c.moveToFirst()) {
|
||||
// No matching computer
|
||||
return null;
|
||||
}
|
||||
|
||||
return getComputerFromCursor(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a computer by UUID
|
||||
* @param uuid The UUID of the computer
|
||||
* @see ComputerDatabaseManager#getComputerByName(String) for alternative.
|
||||
* @return The computer details, or null if no computer with that UUID exists
|
||||
*/
|
||||
public ComputerDetails getComputerByUUID(String uuid) {
|
||||
try (final Cursor c = computerDb.query(
|
||||
COMPUTER_TABLE_NAME, null, COMPUTER_UUID_COLUMN_NAME+"=?",
|
||||
|
@ -341,57 +341,53 @@ public class ComputerManagerService extends Service {
|
||||
// Acquire the default network lock since we could be changing global process state
|
||||
defaultNetworkLock.lock();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// On Lollipop or later, we can bind our process to the underlying interface
|
||||
// to ensure our STUN request goes out on that interface or not at all (which is
|
||||
// preferable to getting a VPN endpoint address back).
|
||||
Network[] networks = connMgr.getAllNetworks();
|
||||
for (Network net : networks) {
|
||||
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
|
||||
if (netCaps != null) {
|
||||
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
|
||||
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
|
||||
// This network looks like an underlying multicast-capable transport,
|
||||
// so let's guess that it's probably where our mDNS response came from.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (connMgr.bindProcessToNetwork(net)) {
|
||||
boundToNetwork = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
|
||||
// On Lollipop or later, we can bind our process to the underlying interface
|
||||
// to ensure our STUN request goes out on that interface or not at all (which is
|
||||
// preferable to getting a VPN endpoint address back).
|
||||
Network[] networks = connMgr.getAllNetworks();
|
||||
for (Network net : networks) {
|
||||
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
|
||||
if (netCaps != null) {
|
||||
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
|
||||
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
|
||||
// This network looks like an underlying multicast-capable transport,
|
||||
// so let's guess that it's probably where our mDNS response came from.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (connMgr.bindProcessToNetwork(net)) {
|
||||
boundToNetwork = true;
|
||||
break;
|
||||
}
|
||||
} else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
|
||||
boundToNetwork = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the STUN request if we're not on a VPN or if we bound to a network
|
||||
if (!activeNetworkIsVpn || boundToNetwork) {
|
||||
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
|
||||
if (stunResolvedAddress != null) {
|
||||
// We don't know for sure what the external port is, so we will have to guess.
|
||||
// When we contact the PC (if we haven't already), it will update the port.
|
||||
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
|
||||
// Perform the STUN request if we're not on a VPN or if we bound to a network
|
||||
if (!activeNetworkIsVpn || boundToNetwork) {
|
||||
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
|
||||
if (stunResolvedAddress != null) {
|
||||
// We don't know for sure what the external port is, so we will have to guess.
|
||||
// When we contact the PC (if we haven't already), it will update the port.
|
||||
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unbind from the network
|
||||
if (boundToNetwork) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
connMgr.bindProcessToNetwork(null);
|
||||
// Unbind from the network
|
||||
if (boundToNetwork) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
connMgr.bindProcessToNetwork(null);
|
||||
} else {
|
||||
ConnectivityManager.setProcessDefaultNetwork(null);
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
ConnectivityManager.setProcessDefaultNetwork(null);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock the network state
|
||||
if (activeNetworkIsVpn) {
|
||||
defaultNetworkLock.unlock();
|
||||
// Unlock the network state
|
||||
if (activeNetworkIsVpn) {
|
||||
defaultNetworkLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,14 +28,8 @@ public class DiskAssetLoader {
|
||||
|
||||
public DiskAssetLoader(Context context) {
|
||||
this.cacheDir = context.getCacheDir();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
this.isLowRamDevice =
|
||||
((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
|
||||
}
|
||||
else {
|
||||
// Use conservative low RAM behavior on very old devices
|
||||
this.isLowRamDevice = true;
|
||||
}
|
||||
this.isLowRamDevice =
|
||||
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
|
||||
}
|
||||
|
||||
public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) {
|
||||
|
@ -198,7 +198,7 @@ public class NvConnection {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
else {
|
||||
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
|
||||
if (activeNetworkInfo != null) {
|
||||
switch (activeNetworkInfo.getType()) {
|
||||
@ -433,10 +433,7 @@ public class NvConnection {
|
||||
context.negotiatedPacketSize, context.negotiatedRemoteStreaming,
|
||||
context.streamConfig.getAudioConfiguration().toInt(),
|
||||
context.streamConfig.getSupportedVideoFormats(),
|
||||
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
||||
context.streamConfig.getAv1BitratePercentageMultiplier(),
|
||||
context.streamConfig.getClientRefreshRateX100(),
|
||||
context.streamConfig.getEncryptionFlags(),
|
||||
context.riKey.getEncoded(), ib.array(),
|
||||
context.videoCapabilities,
|
||||
context.streamConfig.getColorSpace(),
|
||||
|
@ -23,8 +23,6 @@ public class StreamConfiguration {
|
||||
private int remote;
|
||||
private MoonBridge.AudioConfiguration audioConfiguration;
|
||||
private int supportedVideoFormats;
|
||||
private int hevcBitratePercentageMultiplier;
|
||||
private int av1BitratePercentageMultiplier;
|
||||
private int attachedGamepadMask;
|
||||
private int encryptionFlags;
|
||||
private int colorRange;
|
||||
@ -85,16 +83,6 @@ public class StreamConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setHevcBitratePercentageMultiplier(int multiplier) {
|
||||
config.hevcBitratePercentageMultiplier = multiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setAv1BitratePercentageMultiplier(int multiplier) {
|
||||
config.av1BitratePercentageMultiplier = multiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setAttachedGamepadMask(int attachedGamepadMask) {
|
||||
config.attachedGamepadMask = attachedGamepadMask;
|
||||
return this;
|
||||
@ -120,16 +108,6 @@ public class StreamConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setAudioEncryption(boolean enable) {
|
||||
if (enable) {
|
||||
config.encryptionFlags |= MoonBridge.ENCFLG_AUDIO;
|
||||
}
|
||||
else {
|
||||
config.encryptionFlags &= ~MoonBridge.ENCFLG_AUDIO;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setAudioConfiguration(MoonBridge.AudioConfiguration audioConfig) {
|
||||
config.audioConfiguration = audioConfig;
|
||||
return this;
|
||||
@ -224,14 +202,6 @@ public class StreamConfiguration {
|
||||
return supportedVideoFormats;
|
||||
}
|
||||
|
||||
public int getHevcBitratePercentageMultiplier() {
|
||||
return hevcBitratePercentageMultiplier;
|
||||
}
|
||||
|
||||
public int getAv1BitratePercentageMultiplier() {
|
||||
return av1BitratePercentageMultiplier;
|
||||
}
|
||||
|
||||
public int getAttachedGamepadMask() {
|
||||
return attachedGamepadMask;
|
||||
}
|
||||
@ -244,10 +214,6 @@ public class StreamConfiguration {
|
||||
return clientRefreshRateX100;
|
||||
}
|
||||
|
||||
public int getEncryptionFlags() {
|
||||
return encryptionFlags;
|
||||
}
|
||||
|
||||
public int getColorRange() {
|
||||
return colorRange;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.limelight.nvstream.http;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
|
||||
public interface LimelightCryptoProvider {
|
||||
X509Certificate getClientCertificate();
|
||||
RSAPrivateKey getClientPrivateKey();
|
||||
PrivateKey getClientPrivateKey();
|
||||
byte[] getPemEncodedClientCertificate();
|
||||
String encodeBase64String(byte[] data);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ import com.limelight.BuildConfig;
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.nvstream.ConnectionContext;
|
||||
import com.limelight.nvstream.http.PairingManager.PairState;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.HttpUrl;
|
||||
@ -402,16 +403,7 @@ public class NvHTTP {
|
||||
try {
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
|
||||
|
||||
// TLS 1.2 is not enabled by default prior to Android 5.0, so we'll need a custom
|
||||
// SSLSocketFactory in order to connect to GFE 3.20.4 which requires TLSv1.2 or later.
|
||||
// We don't just always use TLSv12SocketFactory because explicitly specifying TLS versions
|
||||
// prevents later TLS versions from being negotiated even if client and server otherwise
|
||||
// support them.
|
||||
return client.newBuilder().sslSocketFactory(
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
|
||||
sc.getSocketFactory() : new TLSv12SocketFactory(sc),
|
||||
trustManager).build();
|
||||
return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -594,6 +586,12 @@ public class NvHTTP {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an app by ID
|
||||
* @param appId The ID of the app
|
||||
* @see #getAppByName(String) for alternative.
|
||||
* @return app details, or null if no app with that ID exists
|
||||
*/
|
||||
public NvApp getAppById(int appId) throws IOException, XmlPullParserException {
|
||||
LinkedList<NvApp> appList = getAppList();
|
||||
for (NvApp appFromList : appList) {
|
||||
@ -603,11 +601,16 @@ public class NvHTTP {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* NOTE: Only use this function if you know what you're doing.
|
||||
* It's totally valid to have two apps named the same thing,
|
||||
* or even nothing at all! Look apps up by ID if at all possible
|
||||
* using the above function */
|
||||
|
||||
/**
|
||||
* Get an app by name
|
||||
* NOTE: It is perfectly valid for multiple apps to have the same name,
|
||||
* this function will only return the first one it finds.
|
||||
* Consider using getAppById instead.
|
||||
* @param appName The name of the app
|
||||
* @see #getAppById(int) for alternative.
|
||||
* @return app details, or null if no app with that name exists
|
||||
*/
|
||||
public NvApp getAppByName(String appName) throws IOException, XmlPullParserException {
|
||||
LinkedList<NvApp> appList = getAppList();
|
||||
for (NvApp appFromList : appList) {
|
||||
@ -784,7 +787,8 @@ public class NvHTTP {
|
||||
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo() +
|
||||
"&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() +
|
||||
"&gcmap=" + context.streamConfig.getAttachedGamepadMask() +
|
||||
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0));
|
||||
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0) +
|
||||
MoonBridge.getLaunchUrlQueryParameters());
|
||||
if ((verb.equals("launch") && !getXmlString(xmlStr, "gamesession", true).equals("0") ||
|
||||
(verb.equals("resume") && !getXmlString(xmlStr, "resume", true).equals("0")))) {
|
||||
// sessionUrl0 will be missing for older GFE versions
|
||||
@ -812,62 +816,4 @@ public class NvHTTP {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Based on example code from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
|
||||
private static class TLSv12SocketFactory extends SSLSocketFactory {
|
||||
private SSLSocketFactory internalSSLSocketFactory;
|
||||
|
||||
public TLSv12SocketFactory(SSLContext context) {
|
||||
internalSSLSocketFactory = context.getSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return internalSSLSocketFactory.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return internalSSLSocketFactory.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
|
||||
}
|
||||
|
||||
private Socket enableTLSv12OnSocket(Socket socket) {
|
||||
if (socket instanceof SSLSocket) {
|
||||
// TLS 1.2 is not enabled by default prior to Android 5.0. We must enable it
|
||||
// explicitly to ensure we can communicate with GFE 3.20.4 which blocks TLS 1.0.
|
||||
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,10 +98,21 @@ public class PairingManager {
|
||||
System.arraycopy(pin.getBytes("UTF-8"), 0, saltedPin, salt.length, pin.length());
|
||||
return saltedPin;
|
||||
}
|
||||
|
||||
private static Signature getSha256SignatureInstanceForKey(Key key) throws NoSuchAlgorithmException {
|
||||
switch (key.getAlgorithm()) {
|
||||
case "RSA":
|
||||
return Signature.getInstance("SHA256withRSA");
|
||||
case "EC":
|
||||
return Signature.getInstance("SHA256withECDSA");
|
||||
default:
|
||||
throw new NoSuchAlgorithmException("Unhandled key algorithm: " + key.getAlgorithm());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean verifySignature(byte[] data, byte[] signature, Certificate cert) {
|
||||
try {
|
||||
Signature sig = Signature.getInstance("SHA256withRSA");
|
||||
Signature sig = PairingManager.getSha256SignatureInstanceForKey(cert.getPublicKey());
|
||||
sig.initVerify(cert.getPublicKey());
|
||||
sig.update(data);
|
||||
return sig.verify(signature);
|
||||
@ -113,12 +124,10 @@ public class PairingManager {
|
||||
|
||||
private static byte[] signData(byte[] data, PrivateKey key) {
|
||||
try {
|
||||
Signature sig = Signature.getInstance("SHA256withRSA");
|
||||
Signature sig = PairingManager.getSha256SignatureInstanceForKey(key);
|
||||
sig.initSign(key);
|
||||
sig.update(data);
|
||||
byte[] signature = new byte[256];
|
||||
sig.sign(signature, 0, signature.length);
|
||||
return signature;
|
||||
return sig.sign();
|
||||
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
@ -245,7 +254,7 @@ public class PairingManager {
|
||||
// Get the server's signed secret
|
||||
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
|
||||
byte[] serverSecret = Arrays.copyOfRange(serverSecretResp, 0, 16);
|
||||
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, 272);
|
||||
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, serverSecretResp.length);
|
||||
|
||||
// Ensure the authenticity of the data
|
||||
if (!verifySignature(serverSecret, serverSignature, serverCert)) {
|
||||
|
@ -22,10 +22,6 @@ public class MoonBridge {
|
||||
public static final int VIDEO_FORMAT_MASK_AV1 = 0xF000;
|
||||
public static final int VIDEO_FORMAT_MASK_10BIT = 0x2200;
|
||||
|
||||
public static final int ENCFLG_NONE = 0;
|
||||
public static final int ENCFLG_AUDIO = 1;
|
||||
public static final int ENCFLG_ALL = 0xFFFFFFFF;
|
||||
|
||||
public static final int BUFFER_TYPE_PICDATA = 0;
|
||||
public static final int BUFFER_TYPE_SPS = 1;
|
||||
public static final int BUFFER_TYPE_PPS = 2;
|
||||
@ -347,10 +343,7 @@ public class MoonBridge {
|
||||
int width, int height, int fps,
|
||||
int bitrate, int packetSize, int streamingRemotely,
|
||||
int audioConfiguration, int supportedVideoFormats,
|
||||
int hevcBitratePercentageMultiplier,
|
||||
int av1BitratePercentageMultiplier,
|
||||
int clientRefreshRateX100,
|
||||
int encryptionFlags,
|
||||
byte[] riAesKey, byte[] riAesIv,
|
||||
int videoCapabilities,
|
||||
int colorSpace, int colorRange);
|
||||
@ -415,6 +408,8 @@ public class MoonBridge {
|
||||
// The RTT is in the top 32 bits, and the RTT variance is in the bottom 32 bits
|
||||
public static native long getEstimatedRttInfo();
|
||||
|
||||
public static native String getLaunchUrlQueryParameters();
|
||||
|
||||
public static native byte guessControllerType(int vendorId, int productId);
|
||||
|
||||
public static native boolean guessControllerHasPaddles(int vendorId, int productId);
|
||||
|
@ -13,7 +13,6 @@ import com.limelight.R;
|
||||
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
|
||||
|
||||
public class ConfirmDeleteOscPreference extends DialogPreference {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
@ -26,7 +25,6 @@ public class ConfirmDeleteOscPreference extends DialogPreference {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public ConfirmDeleteOscPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
@ -11,12 +11,10 @@ import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class LanguagePreference extends ListPreference {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
@ -17,6 +17,12 @@ public class PreferenceConfiguration {
|
||||
FORCE_H264,
|
||||
};
|
||||
|
||||
public enum AnalogStickForScrolling {
|
||||
NONE,
|
||||
RIGHT,
|
||||
LEFT
|
||||
}
|
||||
|
||||
private static final String LEGACY_RES_FPS_PREF_STRING = "list_resolution_fps";
|
||||
private static final String LEGACY_ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround";
|
||||
|
||||
@ -38,16 +44,19 @@ public class PreferenceConfiguration {
|
||||
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
|
||||
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
||||
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
|
||||
private static final String SHOW_GUIDE_BUTTON_PREF_STRING = "checkbox_show_guide_button";
|
||||
private static final String LEGACY_DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
|
||||
private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
|
||||
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
|
||||
private static final String ENABLE_PERF_OVERLAY_STRING = "checkbox_enable_perf_overlay";
|
||||
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
|
||||
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
|
||||
private static final String ANALOG_SCROLLING_PREF_STRING = "analog_scrolling";
|
||||
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
|
||||
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
|
||||
private static final String VIBRATE_OSC_PREF_STRING = "checkbox_vibrate_osc";
|
||||
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
|
||||
private static final String VIBRATE_FALLBACK_STRENGTH_PREF_STRING = "seekbar_vibrate_fallback_strength";
|
||||
private static final String FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
|
||||
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
|
||||
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
|
||||
@ -75,15 +84,18 @@ public class PreferenceConfiguration {
|
||||
|
||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
||||
private static final boolean SHOW_GUIDE_BUTTON_DEFAULT = true;
|
||||
private static final boolean DEFAULT_ENABLE_HDR = false;
|
||||
private static final boolean DEFAULT_ENABLE_PIP = false;
|
||||
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
|
||||
private static final boolean DEFAULT_BIND_ALL_USB = false;
|
||||
private static final boolean DEFAULT_MOUSE_EMULATION = true;
|
||||
private static final String DEFAULT_ANALOG_STICK_FOR_SCROLLING = "right";
|
||||
private static final boolean DEFAULT_MOUSE_NAV_BUTTONS = false;
|
||||
private static final boolean DEFAULT_UNLOCK_FPS = false;
|
||||
private static final boolean DEFAULT_VIBRATE_OSC = true;
|
||||
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
|
||||
private static final int DEFAULT_VIBRATE_FALLBACK_STRENGTH = 100;
|
||||
private static final boolean DEFAULT_FLIP_FACE_BUTTONS = false;
|
||||
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
|
||||
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
|
||||
@ -120,16 +132,19 @@ public class PreferenceConfiguration {
|
||||
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
|
||||
public boolean onscreenController;
|
||||
public boolean onlyL3R3;
|
||||
public boolean showGuideButton;
|
||||
public boolean enableHdr;
|
||||
public boolean enablePip;
|
||||
public boolean enablePerfOverlay;
|
||||
public boolean enableLatencyToast;
|
||||
public boolean bindAllUsb;
|
||||
public boolean mouseEmulation;
|
||||
public AnalogStickForScrolling analogStickForScrolling;
|
||||
public boolean mouseNavButtons;
|
||||
public boolean unlockFps;
|
||||
public boolean vibrateOsc;
|
||||
public boolean vibrateFallbackToDevice;
|
||||
public int vibrateFallbackToDeviceStrength;
|
||||
public boolean touchscreenTrackpad;
|
||||
public MoonBridge.AudioConfiguration audioConfiguration;
|
||||
public int framePacing;
|
||||
@ -384,6 +399,21 @@ public class PreferenceConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private static AnalogStickForScrolling getAnalogStickForScrollingValue(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
String str = prefs.getString(ANALOG_SCROLLING_PREF_STRING, DEFAULT_ANALOG_STICK_FOR_SCROLLING);
|
||||
if (str.equals("right")) {
|
||||
return AnalogStickForScrolling.RIGHT;
|
||||
}
|
||||
else if (str.equals("left")) {
|
||||
return AnalogStickForScrolling.LEFT;
|
||||
}
|
||||
else {
|
||||
return AnalogStickForScrolling.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetStreamingSettings(Context context) {
|
||||
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
@ -532,6 +562,8 @@ public class PreferenceConfiguration {
|
||||
config.videoFormat = getVideoFormatValue(context);
|
||||
config.framePacing = getFramePacingValue(context);
|
||||
|
||||
config.analogStickForScrolling = getAnalogStickForScrollingValue(context);
|
||||
|
||||
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
||||
|
||||
config.oscOpacity = prefs.getInt(OSC_OPACITY_PREF_STRING, DEFAULT_OPACITY);
|
||||
@ -548,6 +580,7 @@ public class PreferenceConfiguration {
|
||||
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
|
||||
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
|
||||
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
|
||||
config.showGuideButton = prefs.getBoolean(SHOW_GUIDE_BUTTON_PREF_STRING, SHOW_GUIDE_BUTTON_DEFAULT);
|
||||
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR) && !isShieldAtvFirmwareWithBrokenHdr();
|
||||
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
|
||||
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
|
||||
@ -557,6 +590,7 @@ public class PreferenceConfiguration {
|
||||
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
||||
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
|
||||
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
|
||||
config.vibrateFallbackToDeviceStrength = prefs.getInt(VIBRATE_FALLBACK_STRENGTH_PREF_STRING, DEFAULT_VIBRATE_FALLBACK_STRENGTH);
|
||||
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
|
||||
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
|
||||
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
|
||||
|
@ -190,8 +190,13 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
|
||||
private void addNativeFrameRateEntry(float framerate) {
|
||||
int frameRateRounded = Math.round(framerate);
|
||||
if (frameRateRounded == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.FPS_PREF_STRING);
|
||||
String fpsValue = Integer.toString(Math.round(framerate));
|
||||
String fpsValue = Integer.toString(frameRateRounded);
|
||||
String fpsName = getResources().getString(R.string.resolution_prefix_native) +
|
||||
" (" + fpsValue + " " + getResources().getString(R.string.fps_suffix_fps) + ")";
|
||||
|
||||
@ -328,26 +333,29 @@ public class StreamSettings extends Activity {
|
||||
(PreferenceCategory) findPreference("category_help");
|
||||
screen.removePreference(category);
|
||||
}*/
|
||||
|
||||
PreferenceCategory category_gamepad_settings =
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
// Remove the vibration options if the device can't vibrate
|
||||
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
category.removePreference(findPreference("checkbox_vibrate_fallback"));
|
||||
|
||||
category_gamepad_settings.removePreference(findPreference("checkbox_vibrate_fallback"));
|
||||
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
|
||||
// The entire OSC category may have already been removed by the touchscreen check above
|
||||
category = (PreferenceCategory) findPreference("category_onscreen_controls");
|
||||
PreferenceCategory category = (PreferenceCategory) findPreference("category_onscreen_controls");
|
||||
if (category != null) {
|
||||
category.removePreference(findPreference("checkbox_vibrate_osc"));
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||
!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasAmplitudeControl() ) {
|
||||
// Remove the vibration strength selector of the device doesn't have amplitude control
|
||||
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
|
||||
}
|
||||
|
||||
int maxSupportedFps = 0;
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
float maxSupportedFps = display.getRefreshRate();
|
||||
|
||||
// Hide non-supported resolution/FPS combinations
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
|
||||
int maxSupportedResW = 0;
|
||||
|
||||
// Add a native resolution with any insets included for users that don't want content
|
||||
@ -415,7 +423,7 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
|
||||
if (candidate.getRefreshRate() > maxSupportedFps) {
|
||||
maxSupportedFps = (int)candidate.getRefreshRate();
|
||||
maxSupportedFps = candidate.getRefreshRate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,30 +511,15 @@ public class StreamSettings extends Activity {
|
||||
// Never remove 720p
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
// On Android 4.2 and later, we can get the true metrics via the
|
||||
// getRealMetrics() function (unlike the lies that getWidth() and getHeight()
|
||||
// tell to us).
|
||||
else {
|
||||
// We can get the true metrics via the getRealMetrics() function (unlike the lies
|
||||
// that getWidth() and getHeight() tell to us).
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
|
||||
display.getRealMetrics(metrics);
|
||||
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
|
||||
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
|
||||
addNativeResolutionEntries(width, height, false);
|
||||
}
|
||||
else {
|
||||
// On Android 4.1, we have to resort to reflection to invoke hidden APIs
|
||||
// to get the real screen dimensions.
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
try {
|
||||
Method getRawHeightFunc = Display.class.getMethod("getRawHeight");
|
||||
Method getRawWidthFunc = Display.class.getMethod("getRawWidth");
|
||||
int width = (Integer) getRawWidthFunc.invoke(display);
|
||||
int height = (Integer) getRawHeightFunc.invoke(display);
|
||||
addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
|
||||
// We give some extra room in case the FPS is rounded down
|
||||
@ -555,49 +548,29 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
addNativeFrameRateEntry(maxSupportedFps);
|
||||
|
||||
// Android L introduces proper 7.1 surround sound support. Remove the 7.1 option
|
||||
// for earlier versions of Android to prevent AudioTrack initialization issues.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
LimeLog.info("Excluding 7.1 surround sound option based on OS");
|
||||
removeValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "71", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "51");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
|
||||
// that the unlock FPS option relies on to not massively increase latency.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
LimeLog.info("Excluding unlock FPS toggle based on OS");
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_advanced_settings");
|
||||
category.removePreference(findPreference("checkbox_unlock_fps"));
|
||||
}
|
||||
else {
|
||||
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
// HACK: We need to let the preference change succeed before reinitializing to ensure
|
||||
// it's reflected in the new layout.
|
||||
final Handler h = new Handler();
|
||||
h.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Ensure the activity is still open when this timeout expires
|
||||
StreamSettings settingsActivity = (StreamSettings)SettingsFragment.this.getActivity();
|
||||
if (settingsActivity != null) {
|
||||
settingsActivity.reloadSettings();
|
||||
}
|
||||
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
// HACK: We need to let the preference change succeed before reinitializing to ensure
|
||||
// it's reflected in the new layout.
|
||||
final Handler h = new Handler();
|
||||
h.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Ensure the activity is still open when this timeout expires
|
||||
StreamSettings settingsActivity = (StreamSettings) SettingsFragment.this.getActivity();
|
||||
if (settingsActivity != null) {
|
||||
settingsActivity.reloadSettings();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// Allow the original preference change to take place
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Allow the original preference change to take place
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Remove HDR preference for devices below Nougat
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
@ -607,7 +580,6 @@ public class StreamSettings extends Activity {
|
||||
category.removePreference(findPreference("checkbox_enable_hdr"));
|
||||
}
|
||||
else {
|
||||
Display display = getActivity().getWindowManager().getDefaultDisplay();
|
||||
Display.HdrCapabilities hdrCaps = display.getHdrCapabilities();
|
||||
|
||||
// We must now ensure our display is compatible with HDR10
|
||||
@ -617,6 +589,7 @@ public class StreamSettings extends Activity {
|
||||
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
|
||||
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
|
||||
foundHdr10 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ public class WebLauncherPreference extends Preference {
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize(attrs);
|
||||
|
@ -30,6 +30,6 @@ public class AdapterFragment extends Fragment {
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
callbacks.receiveAbsListView((AbsListView) getView().findViewById(R.id.fragmentView));
|
||||
callbacks.receiveAbsListView(getView().findViewById(R.id.fragmentView));
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ public class StreamView extends SurfaceView {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class NetHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
else {
|
||||
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
|
||||
if (activeNetworkInfo != null) {
|
||||
return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN;
|
||||
|
@ -2,15 +2,12 @@ package com.limelight.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
|
||||
import com.limelight.AppView;
|
||||
import com.limelight.ShortcutTrampoline;
|
||||
import com.limelight.R;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
|
@ -53,7 +53,11 @@ public class TvChannelHelper {
|
||||
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
|
||||
try {
|
||||
context.startActivityForResult(intent, 0);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
} catch (Exception ignored) {
|
||||
// ActivityNotFoundException is the only officially documented
|
||||
// exception that can result from this call. However some buggy
|
||||
// devices throw others.
|
||||
// See https://github.com/moonlight-stream/moonlight-android/issues/1302
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
# Application.mk for Moonlight
|
||||
|
||||
# Our minimum version is Android 4.1
|
||||
APP_PLATFORM := android-16
|
||||
# Our minimum version is Android 5.0
|
||||
APP_PLATFORM := android-21
|
||||
|
||||
# We support 16KB pages
|
||||
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
|
||||
|
@ -55,7 +55,11 @@ endif
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto
|
||||
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto cpufeatures
|
||||
LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
|
||||
|
||||
LOCAL_BRANCH_PROTECTION := standard
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,android/cpufeatures)
|
1
app/src/main/jni/moonlight-core/Build.txt
Normal file
1
app/src/main/jni/moonlight-core/Build.txt
Normal file
@ -0,0 +1 @@
|
||||
Static libraries were built from https://github.com/cgutman/moonlight-mobile-deps using AppVeyor CI
|
@ -8,6 +8,8 @@
|
||||
#include <opus_multistream.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#include <cpu-features.h>
|
||||
|
||||
static OpusMSDecoder* Decoder;
|
||||
static OPUS_MULTISTREAM_CONFIGURATION OpusConfig;
|
||||
|
||||
@ -426,6 +428,29 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
|
||||
.setControllerLED = BridgeClSetControllerLED,
|
||||
};
|
||||
|
||||
static bool
|
||||
hasFastAes() {
|
||||
if (android_getCpuCount() <= 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (android_getCpuFamily()) {
|
||||
case ANDROID_CPU_FAMILY_ARM:
|
||||
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES);
|
||||
case ANDROID_CPU_FAMILY_ARM64:
|
||||
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES);
|
||||
case ANDROID_CPU_FAMILY_X86:
|
||||
case ANDROID_CPU_FAMILY_X86_64:
|
||||
return !!(android_getCpuFeatures() & ANDROID_CPU_X86_FEATURE_AES_NI);
|
||||
case ANDROID_CPU_FAMILY_MIPS:
|
||||
case ANDROID_CPU_FAMILY_MIPS64:
|
||||
return false;
|
||||
default:
|
||||
// Assume new architectures will all have crypto acceleration (RISC-V will)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
|
||||
jstring address, jstring appVersion, jstring gfeVersion,
|
||||
@ -433,10 +458,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
jint width, jint height, jint fps,
|
||||
jint bitrate, jint packetSize, jint streamingRemotely,
|
||||
jint audioConfiguration, jint supportedVideoFormats,
|
||||
jint hevcBitratePercentageMultiplier,
|
||||
jint av1BitratePercentageMultiplier,
|
||||
jint clientRefreshRateX100,
|
||||
jint encryptionFlags,
|
||||
jbyteArray riAesKey, jbyteArray riAesIv,
|
||||
jint videoCapabilities,
|
||||
jint colorSpace, jint colorRange) {
|
||||
@ -456,10 +478,8 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
.streamingRemotely = streamingRemotely,
|
||||
.audioConfiguration = audioConfiguration,
|
||||
.supportedVideoFormats = supportedVideoFormats,
|
||||
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
||||
.av1BitratePercentageMultiplier = av1BitratePercentageMultiplier,
|
||||
.clientRefreshRateX100 = clientRefreshRateX100,
|
||||
.encryptionFlags = encryptionFlags,
|
||||
.encryptionFlags = ENCFLG_AUDIO,
|
||||
.colorSpace = colorSpace,
|
||||
.colorRange = colorRange
|
||||
};
|
||||
@ -474,6 +494,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
|
||||
BridgeVideoRendererCallbacks.capabilities = videoCapabilities;
|
||||
|
||||
// Enable all encryption features if the platform has fast AES support
|
||||
if (hasFastAes()) {
|
||||
streamConfig.encryptionFlags = ENCFLG_ALL;
|
||||
}
|
||||
|
||||
int ret = LiStartConnection(&serverInfo,
|
||||
&streamConfig,
|
||||
&BridgeConnListenerCallbacks,
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,100 +0,0 @@
|
||||
ANDROID_API_TARGET=21
|
||||
PARALLEL_JOBS=$(nproc)
|
||||
|
||||
rm -r ./android
|
||||
mkdir android
|
||||
|
||||
function build_one
|
||||
{
|
||||
PREFIX=$(pwd)/android/$CPU
|
||||
SYSROOT=$NDK/platforms/android-$ANDROID_API_TARGET/arch-$SYSROOT_CPU
|
||||
TOOLCHAIN_PATH=$NDK/toolchains/$TOOLCHAIN_DIR/prebuilt/linux-x86_64
|
||||
export PATH=$PATH:$TOOLCHAIN_PATH/bin
|
||||
./configure \
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--host=$TOOLCHAIN_BIN_PREFIX \
|
||||
--target=$TOOLCHAIN_BIN_PREFIX \
|
||||
CFLAGS="--sysroot=$SYSROOT -O2 $ADDI_CFLAGS" \
|
||||
$ADDI_CONFIGURE_FLAGS
|
||||
make clean
|
||||
make -j$PARALLEL_JOBS
|
||||
mkdir android/$CPU
|
||||
cp .libs/libopus.a android/$CPU
|
||||
}
|
||||
|
||||
function build_mips
|
||||
{
|
||||
CPU=mips
|
||||
SYSROOT_CPU=mips
|
||||
TOOLCHAIN_BIN_PREFIX=mipsel-linux-android
|
||||
TOOLCHAIN_DIR=mipsel-linux-android-4.9
|
||||
ADDI_CFLAGS="-mips32 -mhard-float -EL -mno-dsp"
|
||||
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
|
||||
build_one
|
||||
}
|
||||
|
||||
function build_mips64
|
||||
{
|
||||
CPU=mips64
|
||||
SYSROOT_CPU=mips64
|
||||
TOOLCHAIN_BIN_PREFIX=mips64el-linux-android
|
||||
TOOLCHAIN_DIR=mips64el-linux-android-4.9
|
||||
ADDI_CFLAGS="-mips64r6"
|
||||
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
|
||||
build_one
|
||||
}
|
||||
|
||||
function build_x86
|
||||
{
|
||||
CPU=x86
|
||||
SYSROOT_CPU=x86
|
||||
TOOLCHAIN_BIN_PREFIX=i686-linux-android
|
||||
TOOLCHAIN_DIR=x86-4.9
|
||||
ADDI_CFLAGS="-march=i686 -mtune=atom -mstackrealign -msse -msse2 -msse3 -mssse3 -mfpmath=sse -m32"
|
||||
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
|
||||
build_one
|
||||
}
|
||||
|
||||
function build_x86_64
|
||||
{
|
||||
CPU=x86_64
|
||||
SYSROOT_CPU=x86_64
|
||||
TOOLCHAIN_BIN_PREFIX=x86_64-linux-android
|
||||
TOOLCHAIN_DIR=x86_64-4.9
|
||||
ADDI_CFLAGS="-msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 -mpopcnt -m64"
|
||||
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
|
||||
build_one
|
||||
}
|
||||
|
||||
function build_armv7
|
||||
{
|
||||
CPU=arm
|
||||
SYSROOT_CPU=arm
|
||||
TOOLCHAIN_BIN_PREFIX=arm-linux-androideabi
|
||||
TOOLCHAIN_DIR=arm-linux-androideabi-4.9
|
||||
ADDI_CFLAGS="-marm -mfpu=vfpv3-d16"
|
||||
ADDI_LDFLAGS=""
|
||||
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point for NEON, EDSP, Media
|
||||
build_one
|
||||
}
|
||||
|
||||
# ARMv8 doesn't currently have assembly in the opus project. We still use fixed point
|
||||
# anyway in the hopes that it will be more performant even without assembly.
|
||||
function build_armv8
|
||||
{
|
||||
CPU=aarch64
|
||||
SYSROOT_CPU=arm64
|
||||
TOOLCHAIN_BIN_PREFIX=aarch64-linux-android
|
||||
TOOLCHAIN_DIR=aarch64-linux-android-4.9
|
||||
ADDI_CFLAGS=""
|
||||
ADDI_LDFLAGS=""
|
||||
ADDI_CONFIGURE_FLAGS="--enable-fixed-point"
|
||||
build_one
|
||||
}
|
||||
|
||||
build_mips
|
||||
build_mips64
|
||||
build_x86
|
||||
build_x86_64
|
||||
build_armv7
|
||||
build_armv8
|
@ -103,7 +103,7 @@ extern "C" {
|
||||
* @endcode
|
||||
*
|
||||
* where opus_encoder_get_size() returns the required size for the encoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
* future versions of this code may change the size, so no assumptions should be made about it.
|
||||
*
|
||||
* The encoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
@ -198,7 +198,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
|
||||
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
|
||||
* can switch to a lower audio bandwidth or number of channels if the bitrate
|
||||
@ -222,7 +222,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
|
||||
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY)
|
||||
* @retval #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_encoder_init(
|
||||
@ -357,7 +357,7 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
|
||||
* error = opus_decoder_init(dec, Fs, channels);
|
||||
* @endcode
|
||||
* where opus_decoder_get_size() returns the required size for the decoder state. Note that
|
||||
* future versions of this code may change the size, so no assuptions should be made about it.
|
||||
* future versions of this code may change the size, so no assumptions should be made about it.
|
||||
*
|
||||
* The decoder state is always continuous in memory and only a shallow copy is sufficient
|
||||
* to copy it (e.g. memcpy())
|
||||
@ -398,6 +398,21 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
|
||||
*/
|
||||
typedef struct OpusDecoder OpusDecoder;
|
||||
|
||||
/** Opus DRED decoder.
|
||||
* This contains the complete state of an Opus DRED decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_dred_decoder_create,opus_dred_decoder_init
|
||||
*/
|
||||
typedef struct OpusDREDDecoder OpusDREDDecoder;
|
||||
|
||||
|
||||
/** Opus DRED state.
|
||||
* This contains the complete state of an Opus DRED packet.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_dred_create,opus_dred_init
|
||||
*/
|
||||
typedef struct OpusDRED OpusDRED;
|
||||
|
||||
/** Gets the size of an <code>OpusDecoder</code> structure.
|
||||
* @param [in] channels <tt>int</tt>: Number of channels.
|
||||
* This must be 1 or 2.
|
||||
@ -511,6 +526,101 @@ OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NON
|
||||
*/
|
||||
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
|
||||
|
||||
/** Gets the size of an <code>OpusDREDDecoder</code> structure.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_decoder_get_size(void);
|
||||
|
||||
/** Allocates and initializes an OpusDREDDecoder state.
|
||||
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OpusDREDDecoder *opus_dred_decoder_create(int *error);
|
||||
|
||||
/** Initializes an <code>OpusDREDDecoder</code> state.
|
||||
* @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be initialized.
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_decoder_init(OpusDREDDecoder *dec);
|
||||
|
||||
/** Frees an <code>OpusDREDDecoder</code> allocated by opus_dred_decoder_create().
|
||||
* @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_dred_decoder_destroy(OpusDREDDecoder *dec);
|
||||
|
||||
/** Perform a CTL function on an Opus DRED decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @param dred_dec <tt>OpusDREDDecoder*</tt>: DRED Decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls or
|
||||
* @ref opus_decoderctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...);
|
||||
|
||||
/** Gets the size of an <code>OpusDRED</code> structure.
|
||||
* @returns The size in bytes.
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_get_size(void);
|
||||
|
||||
/** Allocates and initializes a DRED state.
|
||||
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT OpusDRED *opus_dred_alloc(int *error);
|
||||
|
||||
/** Frees an <code>OpusDRED</code> allocated by opus_dred_create().
|
||||
* @param[in] dec <tt>OpusDRED*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_dred_free(OpusDRED *dec);
|
||||
|
||||
/** Decode an Opus DRED packet.
|
||||
* @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
|
||||
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
|
||||
* @param [in] data <tt>char*</tt>: Input payload
|
||||
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
|
||||
* @param [in] max_dred_samples <tt>opus_int32</tt>: Maximum number of DRED samples that may be needed (if available in the packet).
|
||||
* @param [in] sampling_rate <tt>opus_int32</tt>: Sampling rate used for max_dred_samples argument. Needs not match the actual sampling rate of the decoder.
|
||||
* @param [out] dred_end <tt>opus_int32*</tt>: Number of non-encoded (silence) samples between the DRED timestamp and the last DRED sample.
|
||||
* @param [in] defer_processing <tt>int</tt>: Flag (0 or 1). If set to one, the CPU-intensive part of the DRED decoding is deferred until opus_dred_process() is called.
|
||||
* @returns Offset (positive) of the first decoded DRED samples, zero if no DRED is present, or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Finish decoding an Opus DRED packet. The function only needs to be called if opus_dred_parse() was called with defer_processing=1.
|
||||
* The source and destination will often be the same DRED state.
|
||||
* @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
|
||||
* @param [in] src <tt>OpusDRED*</tt>: Source DRED state to start the processing from.
|
||||
* @param [out] dst <tt>OpusDRED*</tt>: Destination DRED state to store the updated state after processing.
|
||||
* @returns @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
|
||||
|
||||
/** Decode audio from an Opus DRED packet with floating point output.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
|
||||
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel to decode in \a pcm.
|
||||
* frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
|
||||
|
||||
/** Decode audio from an Opus DRED packet with floating point output.
|
||||
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
|
||||
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel to decode in \a pcm.
|
||||
* frame_size <b>must</b> be a multiple of 2.5 ms.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_EXPORT int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size);
|
||||
|
||||
|
||||
/** Parse an opus packet into one or more frames.
|
||||
* Opus_decode will perform this operation internally so most applications do
|
||||
* not need to use this function.
|
||||
@ -583,6 +693,14 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Checks whether an Opus packet has LBRR.
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
* @param [in] len <tt>opus_int32</tt>: Length of packet
|
||||
* @returns 1 is LBRR is present, 0 otherwise
|
||||
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len);
|
||||
|
||||
/** Gets the number of samples of an Opus packet.
|
||||
* @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
|
||||
* @param [in] packet <tt>char*</tt>: Opus packet
|
||||
|
@ -1,342 +0,0 @@
|
||||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008-2012 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file opus_custom.h
|
||||
@brief Opus-Custom reference implementation API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_CUSTOM_H
|
||||
#define OPUS_CUSTOM_H
|
||||
|
||||
#include "opus_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
|
||||
#else
|
||||
# define OPUS_CUSTOM_EXPORT
|
||||
# ifdef OPUS_BUILD
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
|
||||
# else
|
||||
# define OPUS_CUSTOM_EXPORT_STATIC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_custom Opus Custom
|
||||
* @{
|
||||
* Opus Custom is an optional part of the Opus specification and
|
||||
* reference implementation which uses a distinct API from the regular
|
||||
* API and supports frame sizes that are not normally supported.\ Use
|
||||
* of Opus Custom is discouraged for all but very special applications
|
||||
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
|
||||
* (for either complexity or latency reasons) and where interoperability
|
||||
* is less important.
|
||||
*
|
||||
* In addition to the interoperability limitations the use of Opus custom
|
||||
* disables a substantial chunk of the codec and generally lowers the
|
||||
* quality available at a given bitrate. Normally when an application needs
|
||||
* a different frame size from the codec it should buffer to match the
|
||||
* sizes but this adds a small amount of delay which may be important
|
||||
* in some very low latency applications. Some transports (especially
|
||||
* constant rate RF transports) may also work best with frames of
|
||||
* particular durations.
|
||||
*
|
||||
* Libopus only supports custom modes if they are enabled at compile time.
|
||||
*
|
||||
* The Opus Custom API is similar to the regular API but the
|
||||
* @ref opus_encoder_create and @ref opus_decoder_create calls take
|
||||
* an additional mode parameter which is a structure produced by
|
||||
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
|
||||
* must create a mode using the same sample rate (fs) and frame size
|
||||
* (frame size) so these parameters must either be signaled out of band
|
||||
* or fixed in a particular implementation.
|
||||
*
|
||||
* Similar to regular Opus the custom modes support on the fly frame size
|
||||
* switching, but the sizes available depend on the particular frame size in
|
||||
* use. For some initial frame sizes on a single on the fly size is available.
|
||||
*/
|
||||
|
||||
/** Contains the state of an encoder. One encoder state is needed
|
||||
for each stream. It is initialized once at the beginning of the
|
||||
stream. Do *not* re-initialize the state for every frame.
|
||||
@brief Encoder state
|
||||
*/
|
||||
typedef struct OpusCustomEncoder OpusCustomEncoder;
|
||||
|
||||
/** State of the decoder. One decoder state is needed for each stream.
|
||||
It is initialized once at the beginning of the stream. Do *not*
|
||||
re-initialize the state for every frame.
|
||||
@brief Decoder state
|
||||
*/
|
||||
typedef struct OpusCustomDecoder OpusCustomDecoder;
|
||||
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialized
|
||||
with exactly the same mode, otherwise the output will be
|
||||
corrupted.
|
||||
@brief Mode configuration
|
||||
*/
|
||||
typedef struct OpusCustomMode OpusCustomMode;
|
||||
|
||||
/** Creates a new mode struct. This will be passed to an encoder or
|
||||
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
|
||||
* decoders that use it are destroyed as well.
|
||||
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
|
||||
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
|
||||
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
|
||||
* @return A newly created mode
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
|
||||
|
||||
/** Destroys a mode struct. Only call this after all encoders and
|
||||
* decoders using this mode are destroyed as well.
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
|
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
|
||||
|
||||
/* Encoder */
|
||||
/** Gets the size of an OpusCustomEncoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
# ifdef CUSTOM_MODES
|
||||
/** Initializes a previously allocated encoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
|
||||
OpusCustomEncoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/** Creates a new encoder state. Each stream needs its own encoder
|
||||
* state (can't be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created encoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
/** Destroys a an encoder state.
|
||||
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
|
||||
* Samples with a range beyond +/-1.0 are supported but will
|
||||
* be clipped by decoders using the integer API and should
|
||||
* only be used if it is known that the far end supports
|
||||
* extended dynamic range. There must be exactly
|
||||
* frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
|
||||
OpusCustomEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
|
||||
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
|
||||
* There must be exactly frame_size samples per channel.
|
||||
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
|
||||
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
|
||||
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
* @return Number of bytes written to "compressed".
|
||||
* If negative, an error has occurred (see error codes). It is IMPORTANT that
|
||||
* the length returned be somehow transmitted to the decoder. Otherwise, no
|
||||
* decoding is possible.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
|
||||
OpusCustomEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *compressed,
|
||||
int maxCompressedBytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_encoderctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
|
||||
/* Decoder */
|
||||
|
||||
/** Gets the size of an OpusCustomDecoder structure.
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @returns size
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Initializes a previously allocated decoder state
|
||||
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
|
||||
* This is intended for applications which use their own allocator instead of malloc.
|
||||
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
|
||||
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @return OPUS_OK Success or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
|
||||
OpusCustomDecoder *st,
|
||||
const OpusCustomMode *mode,
|
||||
int channels
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** Creates a new decoder state. Each stream needs its own decoder state (can't
|
||||
* be shared across simultaneous streams).
|
||||
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
|
||||
* stream (must be the same characteristics as used for the encoder)
|
||||
* @param [in] channels <tt>int</tt>: Number of channels
|
||||
* @param [out] error <tt>int*</tt>: Returns an error code
|
||||
* @return Newly created decoder state.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
|
||||
const OpusCustomMode *mode,
|
||||
int channels,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Destroys a an decoder state.
|
||||
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
|
||||
|
||||
/** Decode an opus custom frame with floating point output
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(float)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
float *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode an opus custom frame
|
||||
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
|
||||
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
|
||||
* @param [in] len <tt>int</tt>: Number of bytes in payload
|
||||
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
|
||||
* is frame_size*channels*sizeof(opus_int16)
|
||||
* @param [in] frame_size Number of samples per channel of available space in *pcm.
|
||||
* @returns Number of decoded samples or @ref opus_errorcodes
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
|
||||
OpusCustomDecoder *st,
|
||||
const unsigned char *data,
|
||||
int len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on an Opus custom decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated
|
||||
* by a convenience macro.
|
||||
* @see opus_genericctls
|
||||
*/
|
||||
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_CUSTOM_H */
|
@ -64,7 +64,7 @@ extern "C" {
|
||||
/**Export control for opus functions */
|
||||
|
||||
#ifndef OPUS_EXPORT
|
||||
# if defined(WIN32)
|
||||
# if defined(_WIN32)
|
||||
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
|
||||
# define OPUS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
@ -168,15 +168,33 @@ extern "C" {
|
||||
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
|
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
|
||||
#define OPUS_GET_IN_DTX_REQUEST 4049
|
||||
#define OPUS_SET_DRED_DURATION_REQUEST 4050
|
||||
#define OPUS_GET_DRED_DURATION_REQUEST 4051
|
||||
#define OPUS_SET_DNN_BLOB_REQUEST 4052
|
||||
/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */
|
||||
|
||||
/** Defines for the presence of extended APIs. */
|
||||
#define OPUS_HAVE_OPUS_PROJECTION_H
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
|
||||
#ifdef DISABLE_PTR_CHECK
|
||||
/* Disable checks to prevent ubsan from complaining about NULL checks
|
||||
in test_opus_api. */
|
||||
#define __opus_check_int_ptr(ptr) (ptr)
|
||||
#define __opus_check_uint_ptr(ptr) (ptr)
|
||||
#define __opus_check_uint8_ptr(ptr) (ptr)
|
||||
#define __opus_check_val16_ptr(ptr) (ptr)
|
||||
#define __opus_check_void_ptr(ptr) (ptr)
|
||||
#else
|
||||
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
|
||||
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
|
||||
#define __opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr)))
|
||||
#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
|
||||
#define __opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x))
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
|
||||
@ -481,7 +499,8 @@ extern "C" {
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
|
||||
* <dt>1</dt><dd>Enable inband FEC.</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
|
||||
@ -490,7 +509,8 @@ extern "C" {
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled.</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
|
||||
@ -617,6 +637,18 @@ extern "C" {
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Provide external DNN weights from binary object (only when explicitly built without the weights)
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, __opus_check_void_ptr(data), __opus_check_int(len)
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_genericctls Generic CTLs
|
||||
@ -715,6 +747,16 @@ extern "C" {
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Gets the DTX state of the encoder.
|
||||
* Returns whether the last encoded frame was either a comfort noise update
|
||||
* during DTX or not encoded because of DTX.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>The encoder is not in DTX.</dd>
|
||||
* <dt>1</dt><dd>The encoder is in DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
@ -143,7 +143,7 @@ extern "C" {
|
||||
* <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
* channel ordering</a>. A decoder may wish to apply an additional permutation
|
||||
* to the mapping the encoder used to achieve a different output channel
|
||||
* order (e.g. for outputing in WAV order).
|
||||
* order (e.g. for outputting in WAV order).
|
||||
*
|
||||
* Each multistream packet contains an Opus packet for each stream, and all of
|
||||
* the Opus packets in a single multistream packet must have the same
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
||||
Subproject commit c86f49ee7f9d55ee3646ac4ab903268a0222ddbd
|
||||
Subproject commit 8af4562af672dd6b9ed28553ead172984fd9a683
|
@ -212,6 +212,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_getEstimatedRttInfo(JNIEnv *env, jcla
|
||||
return ((uint64_t)rtt << 32U) | variance;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_getLaunchUrlQueryParameters(JNIEnv *env, jclass clazz) {
|
||||
return (*env)->NewStringUTF(env, LiGetLaunchUrlQueryParameters());
|
||||
}
|
||||
|
||||
JNIEXPORT jbyte JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_guessControllerType(JNIEnv *env, jclass clazz, jint vendorId, jint productId) {
|
||||
unsigned int unDeviceID = MAKE_CONTROLLER_ID(vendorId, productId);
|
||||
|
@ -270,4 +270,9 @@
|
||||
<string name="pair_pairing_help">Wenn dein Host PC Sunshine verwendet, navigiere zur Sunshine Web UI und gebe dort die PIN ein.</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Die Maus immer mit dem Touchpad steuern</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Host Verarbeitungslatenz min/max/avg: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="title_analog_scrolling">Verwenden Sie zum Scrollen einen Analogstick</string>
|
||||
<string name="summary_analog_scrolling">Wählen Sie einen Analogstick aus, der zum scrollen im Mausemulationsmodus verwendet werden soll</string>
|
||||
<string name="analogscroll_none">Keine (beide Sticks bewegen die Maus)</string>
|
||||
<string name="analogscroll_right">Rechter Analogstick</string>
|
||||
<string name="analogscroll_left">Linker Analogstick</string>
|
||||
</resources>
|
@ -112,7 +112,8 @@
|
||||
<string name="scut_not_paired">Ο υπολογιστής δεν έχει συζευχθεί</string>
|
||||
<string name="pcview_menu_header_offline">Εκτός σύνδεσης</string>
|
||||
<string name="pcview_menu_test_network">Δοκιμή σύνδεσης δικτύου</string>
|
||||
<string name="nettest_text_waiting">Το Moonlight δοκιμάζει τη σύνδεση δικτύου σας για να καθορίσει εάν το NVIDIA GameStream είναι αποκλεισμένο.
|
||||
<string name="nettest_text_waiting">Το Moonlight δοκιμάζει τη σύνδεση δικτύου σας για να διαπιστώσει εάν κάποια θύρα είναι αποκλεισμένη.
|
||||
\n
|
||||
\n
|
||||
\nΑυτό μπορεί να πάρει μερικά δευτερόλεπτα…</string>
|
||||
<string name="pair_fail">Η σύζευξη απέτυχε</string>
|
||||
@ -205,4 +206,10 @@
|
||||
<string name="title_video_format">Αλλαγή ρυθμίσεων HEVC</string>
|
||||
<string name="title_enable_post_stream_toast">Εμφάνιση μηνύματος λανθάνοντος χρόνου μετά τη ροή</string>
|
||||
<string name="summary_video_format">Το HEVC μειώνει τις απαιτήσεις εύρους ζώνης βίντεο, αλλά απαιτεί μια νεότερη συσκευή</string>
|
||||
<string name="error_code_prefix">Κωδικός σφάλματος:</string>
|
||||
<string name="frame_conversion_error">Ο υπολογιστής φιλοξενίας ανέφερε ένα σφάλμα κωδικοποίησης βίντεο.
|
||||
\n
|
||||
\nΔοκιμάστε να απενεργοποιήσετε τη λειτουργία HDR, να αλλάξετε την ανάλυση ροής ή να αλλάξετε την ανάλυση οθόνης του υπολογιστή φιλοξενίας.</string>
|
||||
<string name="pcview_menu_eol">Λήξη Υποστήριξης NVIDA GameStream</string>
|
||||
<string name="pair_pairing_help">Εάν ο υπολογιστής οικοδεσπότης χρησιμοποιεί το Sunshine, πλοηγηθείτε στην διαδικτυακή διεπαφή χρήστη του Sunshine για να εισάγετε το PIN.</string>
|
||||
</resources>
|
@ -45,7 +45,7 @@
|
||||
<string name="conn_error_title">Error de conexión</string>
|
||||
<string name="conn_error_msg">Fallo al iniciar</string>
|
||||
<string name="conn_terminated_title">Conexión finalizada</string>
|
||||
<string name="conn_terminated_msg">La conexión ha finalizando</string>
|
||||
<string name="conn_terminated_msg">La conexión ha finalizado.</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Dirección IP del host del ordenador</string>
|
||||
<string name="searching_pc">Buscando el hostal del PC en tu red local...
|
||||
@ -278,4 +278,13 @@
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Utiliza los sensores de movimiento integrados de tu dispositivo si el gamepad conectado o tu versión de Android no admiten los sensores del gamepad.
|
||||
\nNota: Activar esta opción puede hacer que tu gamepad aparezca como un mando de PlayStation en el host.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Emular el sensor de movimiento del gamepad</string>
|
||||
<string name="analogscroll_none">Ninguno (ambos joysticks mueven el mouse)</string>
|
||||
<string name="analogscroll_right">Joystick analógico derecho</string>
|
||||
<string name="analogscroll_left">Joystick analógico izquierdo</string>
|
||||
<string name="title_analog_scrolling">Usa un joystick analógico para hacer scroll</string>
|
||||
<string name="summary_analog_scrolling">Selecciona un joystick analógico para scroll cuando la emulación del mouse está habilitada</string>
|
||||
<string name="error_code_prefix">Código del error:</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Ajustar la intensidad del ruido emulado</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Amplifica o reduce la intensidad de la vibración de tu dispositivo</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
</resources>
|
@ -10,11 +10,11 @@
|
||||
<string name="help_loading_title">Visionneuse d\'aide</string>
|
||||
<string name="help_loading_msg">Chargement de la page d\'aide…</string>
|
||||
<!-- PC view menu entries -->
|
||||
<string name="pcview_menu_app_list">Afficher la liste des jeux</string>
|
||||
<string name="pcview_menu_pair_pc">Appairer avec PC</string>
|
||||
<string name="pcview_menu_app_list">Afficher toutes les applis</string>
|
||||
<string name="pcview_menu_pair_pc">Appairer avec ce PC</string>
|
||||
<string name="pcview_menu_unpair_pc">Désappairer</string>
|
||||
<string name="pcview_menu_send_wol">Envoyer la requête Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Supprimer PC</string>
|
||||
<string name="pcview_menu_send_wol">Envoyer une requête Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Supprimer le PC</string>
|
||||
<string name="pcview_menu_details">Voir les détails</string>
|
||||
<!-- Network test strings -->
|
||||
<string name="nettest_title_waiting">Test de la connexion réseau</string>
|
||||
@ -22,19 +22,21 @@
|
||||
\n
|
||||
\nCela peut prendre quelques secondes…</string>
|
||||
<string name="nettest_title_done">Test du réseau terminé</string>
|
||||
<string name="nettest_text_success">Votre réseau ne semble pas bloquer Moonlight. Si vous avez encore de la difficulté à vous connecter, vérifiez les paramètres du pare-feu de votre PC.\n\nSi vous essayez de diffuser sur Internet, installez l\'outil d\'hébergement Internet Moonlight sur votre PC et exécutez le testeur de streaming Internet inclus pour vérifier la connexion Internet de votre PC.</string>
|
||||
<string name="nettest_text_inconclusive">Le test réseau n’a pas pu être effectué car aucun des serveurs de test de connexion Moonlight n’était accessible. Vérifiez votre connexion Internet ou réessayez plus tard.</string>
|
||||
<string name="nettest_text_failure">La connexion réseau actuelle de votre appareil semble bloquer Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsqu’il est connecté à ce réseau.
|
||||
<string name="nettest_text_success">Votre réseau ne semble pas bloquer Moonlight. Si vous avez encore des difficultés à vous connecter, vérifiez les paramètres du pare-feu de votre PC.
|
||||
\n
|
||||
\nSi vous essayez de streamer depuis Internet, installez l\'outil Moonlight Internet Hosting Tool sur votre PC et exécutez le testeur de streaming Internet inclus pour vérifier la connexion Internet de votre PC.</string>
|
||||
<string name="nettest_text_inconclusive">Le test réseau n\'a pas pu être effectué car aucun des serveurs de test de connexion de Moonlight n\'était accessible. Vérifiez votre connexion Internet ou réessayez plus tard.</string>
|
||||
<string name="nettest_text_failure">La connexion réseau actuelle de votre appareil semble bloquer Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsque vous êtes connecté à ce réseau.
|
||||
\n
|
||||
\nLes ports réseau suivants ont été bloqués :
|
||||
\n</string>
|
||||
<string name="nettest_text_blocked">La connexion réseau actuelle de votre appareil bloque Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsqu’il est connecté à ce réseau.</string>
|
||||
<string name="nettest_text_blocked">La connexion réseau actuelle de votre appareil bloque Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsque vous êtes connecté à ce réseau.</string>
|
||||
<!-- Pair messages -->
|
||||
<string name="pairing">Appariement…</string>
|
||||
<string name="pair_pc_offline">L\'ordinateur est hors ligne</string>
|
||||
<string name="pair_pc_ingame">L\'ordinateur est actuellement dans un jeu. Vous devez fermer le jeu avant l\'appariement.</string>
|
||||
<string name="pair_pc_ingame">L\'ordinateur est actuellement dans un jeu. Vous devez fermer le jeu avant l’appairage.</string>
|
||||
<string name="pair_pairing_title">Appariement</string>
|
||||
<string name="pair_pairing_msg">SVP entrer le code PIN suivant sur le PC concerné :</string>
|
||||
<string name="pair_pairing_msg">Veuillez saisir le code PIN suivant sur le PC cible :</string>
|
||||
<string name="pair_incorrect_pin">Code PIN incorrect</string>
|
||||
<string name="pair_fail">Échec de l\'appariement</string>
|
||||
<string name="pair_already_in_progress">Appariement déjà en cours</string>
|
||||
@ -42,40 +44,36 @@
|
||||
<string name="wol_pc_online">L\'ordinateur est en ligne</string>
|
||||
<string name="wol_no_mac">Impossible de réveiller le PC car il n\'y a pas d\'addresse MAC enregistrée pour ce PC</string>
|
||||
<string name="wol_waking_pc">Réveil PC…</string>
|
||||
<string name="wol_waking_msg">Votre PC peut prendre quelques secondes pour se réveiller.
|
||||
Si ce n\'est pas le cas, assurez-vous qu\'il est correctement configuré pour Wake-On-LAN.
|
||||
</string>
|
||||
<string name="wol_waking_msg">Votre PC peut prendre quelques secondes pour démarrer. S\'il ne démarre toujours pas, assurez-vous qu\'il est correctement configuré pour le Wake-On-LAN.</string>
|
||||
<string name="wol_fail">Échec de l\'envoi des paquets Wake-On-LAN</string>
|
||||
<!-- Unpair messages -->
|
||||
<string name="unpairing">Désappariage…</string>
|
||||
<string name="unpair_success">Désapparié avec succès</string>
|
||||
<string name="unpair_fail">Échec de désappariement</string>
|
||||
<string name="unpair_error">Le périphérique n\'a pas été appareillé</string>
|
||||
<string name="unpair_fail">Échec du désappairage</string>
|
||||
<string name="unpair_error">Le périphérique n\'est appareillé</string>
|
||||
<!-- Errors -->
|
||||
<string name="error_pc_offline">L\'ordinateur est déconnecté</string>
|
||||
<string name="error_manager_not_running">Le service ComputerManager n\'est pas en cours d\'exécution. Veuillez patienter quelques secondes ou redémarrer l\'application.</string>
|
||||
<string name="error_pc_offline">L\'ordinateur est hors ligne</string>
|
||||
<string name="error_manager_not_running">Le service ComputerManager n\'est pas en cours d\'exécution. Veuillez attendre quelques secondes ou redémarrez l\'application.</string>
|
||||
<string name="error_unknown_host">Échec de la résolution de l\'hôte</string>
|
||||
<string name="error_404">GFE renvoi une erreur HTTP 404. Assurez-vous que votre PC exécute un GPU pris en charge.
|
||||
L\'utilisation d\'un logiciel de bureau à distance peut également provoquer cette erreur. Essayez de redémarrer votre machine ou de réinstaller GFE.
|
||||
</string>
|
||||
<string name="title_decoding_error">Le décodeur vidéo s\'est écrasé</string>
|
||||
<string name="message_decoding_error">Moonlight s\'est arrêté en raison d\'une incompatibilité avec le décodeur vidéo de cet appareil. Essayez d\'ajuster les paramètres de diffusion si les plantages continuent.</string>
|
||||
<string name="title_decoding_reset">Paramètres vidéo réinitialiser</string>
|
||||
<string name="message_decoding_reset">Le décodeur vidéo de votre appareil continue de planter avec les paramètres de diffusion sélectionnés. Vos paramètres de diffusion ont été réinitialisés par défaut.</string>
|
||||
<string name="error_usb_prohibited">L\'accès USB est interdit par votre appareil. Vérifiez vos paramètres Knox ou MDM.</string>
|
||||
<string name="unable_to_pin_shortcut">Votre lanceur actuel ne permet pas de créer des raccourcis épinglés.</string>
|
||||
<string name="error_404">GFE renvoie une erreur HTTP 404. Assurez-vous que votre PC possède un GPU pris en charge. L\'utilisation d\'un logiciel de bureau à distance peut également provoquer cette erreur. Essayez de redémarrer votre machine ou de réinstaller GFE.</string>
|
||||
<string name="title_decoding_error">Le décodeur vidéo a planté</string>
|
||||
<string name="message_decoding_error">Moonlight a planté en raison d\'une incompatibilité avec le décodeur vidéo de cet appareil. Essayez d\'ajuster les paramètres de streaming si les plantages continuent.</string>
|
||||
<string name="title_decoding_reset">Réinitialiser les paramètres vidéo</string>
|
||||
<string name="message_decoding_reset">Le décodeur vidéo de votre appareil continue de planter avec les paramètres de streaming sélectionnés. Vos paramètres de streaming ont été réinitialisés à ceux par défaut.</string>
|
||||
<string name="error_usb_prohibited">L\'accès USB est interdit par l\'administrateur de votre appareil. Vérifiez vos paramètres Knox ou MDM.</string>
|
||||
<string name="unable_to_pin_shortcut">Votre launcher actuel ne permet pas de créer des raccourcis épinglés.</string>
|
||||
<!-- Start application messages -->
|
||||
<string name="conn_establishing_title">Établissement de la connexion</string>
|
||||
<string name="conn_establishing_msg">Démarrage de la connection</string>
|
||||
<string name="conn_metered">Attention : Votre connexion réseau active est mesurée !</string>
|
||||
<string name="conn_metered">Attention : Votre connexion réseau active est limitée !</string>
|
||||
<string name="conn_client_latency">Latence moyenne de décodage de trame :</string>
|
||||
<string name="conn_client_latency_hw">Latence du décodeur matériel :</string>
|
||||
<string name="conn_hardware_latency">Latence moyenne du décodage matériel :</string>
|
||||
<string name="conn_starting">Démarrage</string>
|
||||
<string name="conn_error_title">Erreur de connexion</string>
|
||||
<string name="conn_error_msg">Impossible de démarrer</string>
|
||||
<string name="conn_terminated_title">Connexion terminée</string>
|
||||
<string name="conn_terminated_msg">La connexion a été interrompue</string>
|
||||
<string name="conn_terminated_title">Connexion interrompue</string>
|
||||
<string name="conn_terminated_msg">La connexion a été interrompue.</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Adresse IP du PC hôte</string>
|
||||
<string name="searching_pc">Recherche de PC hôtes sur votre réseau local…
|
||||
@ -83,7 +81,7 @@
|
||||
\n Assurez-vous que Sunshine est en cours d\'execution ou que GameStream est activé dans les paramètres GeForce Experience SHIELD.</string>
|
||||
<string name="yes">Oui</string>
|
||||
<string name="no">Non</string>
|
||||
<string name="lost_connection">Perte de connexion avec le PC</string>
|
||||
<string name="lost_connection">Connexion perdue avec le PC</string>
|
||||
<string name="title_details">Détails</string>
|
||||
<string name="help">Aide</string>
|
||||
<string name="delete_pc_msg">Êtes-vous sûr de vouloir supprimer ce PC \?</string>
|
||||
@ -96,105 +94,105 @@
|
||||
<string name="perf_overlay_dectime">Temps moyen de décodage : %1$.2f ms</string>
|
||||
<!-- AppList activity -->
|
||||
<string name="applist_connect_msg">Connexion au PC…</string>
|
||||
<string name="applist_menu_resume">Reprise de la session</string>
|
||||
<string name="applist_menu_resume">Reprendre la session</string>
|
||||
<string name="applist_menu_quit">Quitter la session</string>
|
||||
<string name="applist_menu_quit_and_start">Quitter le jeu actuel et démarrer</string>
|
||||
<string name="applist_menu_cancel">Annuler</string>
|
||||
<string name="applist_menu_details">Voir les détails</string>
|
||||
<string name="applist_menu_scut">Créer un raccourci</string>
|
||||
<string name="applist_menu_tv_channel">Ajouter à la chaîne</string>
|
||||
<string name="applist_menu_tv_channel">Ajouter à la liste de chaînes</string>
|
||||
<string name="applist_refresh_title">Liste des applications</string>
|
||||
<string name="applist_refresh_msg">Actualisation des applications…</string>
|
||||
<string name="applist_refresh_error_title">Erreur</string>
|
||||
<string name="applist_refresh_error_msg">Impossible d\'obtenir la liste des applications</string>
|
||||
<string name="applist_quit_app">Fermeture</string>
|
||||
<string name="applist_quit_success">Fermeture avec succès</string>
|
||||
<string name="applist_quit_success">Application fermée avec succès</string>
|
||||
<string name="applist_quit_fail">Échec de la fermeture</string>
|
||||
<string name="applist_quit_confirmation">Voulez-vous vraiment quitter l\'application en cours d\'exécution \? Toutes les données non enregistrées seront perdues.</string>
|
||||
<string name="applist_details_id">ID de l\'appli :</string>
|
||||
<!-- Add computer manually activity -->
|
||||
<string name="title_add_pc">Ajouter un PC manuellement</string>
|
||||
<string name="msg_add_pc">Connexion au PC…</string>
|
||||
<string name="addpc_fail">Impossible de se connecter à l\'ordinateur spécifié. Assurez-vous que les ports requis sont autorisés par le pare-feu.</string>
|
||||
<string name="addpc_success">Ajouté avec succès de l\'ordinateur</string>
|
||||
<string name="addpc_unknown_host">Impossible de résoudre l\'adresse du PC. Assurez-vous que vous n\'avez pas fait une faute de frappe dans l\'adresse.</string>
|
||||
<string name="addpc_fail">Impossible de se connecter à l\'ordinateur spécifié. Assurez-vous que les ports requis sont autorisés via le pare-feu.</string>
|
||||
<string name="addpc_success">Ordinateur ajouté avec succès</string>
|
||||
<string name="addpc_unknown_host">Impossible de résoudre l\'adresse du PC. Assurez-vous que vous n\'avez pas fait de faute de frappe dans l\'adresse.</string>
|
||||
<string name="addpc_enter_ip">Vous devez entrer une adresse IP</string>
|
||||
<string name="addpc_wrong_sitelocal">Cette adresse ne semble pas correcte. Vous devez utiliser l\'adresse IP publique de votre routeur pour la diffusion en continu sur Internet..</string>
|
||||
<string name="addpc_wrong_sitelocal">Cette adresse ne semble pas correcte. Vous devez utiliser l\'adresse IP publique de votre routeur pour le streaming depuis Internet.</string>
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">Paramètres de base</string>
|
||||
<string name="title_resolution_list">Résolution vidéo</string>
|
||||
<string name="summary_resolution_list">Le réglage de valeurs trop élevées pour votre appareil peut provoquer un retard ou un plantage.</string>
|
||||
<string name="summary_resolution_list">Augmentez pour une meilleure clarté de l\'image. Réduisez pour de meilleures performances sur les appareils bas de gamme et les réseaux lents.</string>
|
||||
<string name="title_fps_list">Fréquence d\'images vidéo</string>
|
||||
<string name="summary_fps_list">Augmenter pour un flux vidéo plus lisse. Diminution pour de meilleures performances sur les périphériques bas de gamme.</string>
|
||||
<string name="title_seekbar_bitrate">Sélectionnez le bitrate vidéo à obtenir</string>
|
||||
<string name="summary_seekbar_bitrate">Bitrate inférieur pour réduire la saccade. Augmentez le bitrate pour augmenter la qualité de l\'image.</string>
|
||||
<string name="title_checkbox_stretch_video">Étirez la vidéo en plein écran</string>
|
||||
<string name="summary_fps_list">Augmentez pour un flux vidéo plus fluide. Diminuez pour de meilleures performances sur les appareils bas de gamme.</string>
|
||||
<string name="title_seekbar_bitrate">Bitrate vidéo</string>
|
||||
<string name="summary_seekbar_bitrate">Augmentez-le pour une meilleure qualité d’image. Diminuez-le pour améliorer les performances sur les connexions plus lentes.</string>
|
||||
<string name="title_checkbox_stretch_video">Étirer la vidéo en plein écran</string>
|
||||
<string name="title_checkbox_disable_warnings">Désactiver les messages d\'avertissement</string>
|
||||
<string name="title_checkbox_enable_pip">Activer le mode observateur dans l\'image</string>
|
||||
<string name="summary_checkbox_enable_pip">Permet de visualiser le flux (sans le contrôleur) tout en multitâche</string>
|
||||
<string name="title_checkbox_enable_pip">Activer le mode observateur</string>
|
||||
<string name="summary_checkbox_enable_pip">Permet de visualiser le stream (sans le contrôler) tout en utilisant une autre appli</string>
|
||||
<string name="category_audio_settings">Paramètres audio</string>
|
||||
<string name="title_audio_config_list">Configuration son surround</string>
|
||||
<string name="summary_audio_config_list">Activer le son surround 5.1 ou 7.1 pour les systèmes home cinéma</string>
|
||||
<string name="category_input_settings">Paramètres d\'entrée</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Utilisez l\'écran tactile comme trackpad</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">S\'il est activé, l\'écran tactile agit comme un trackpad. S\'il est désactivé, l\'écran tactile contrôle directement le curseur de la souris.</string>
|
||||
<string name="title_checkbox_multi_controller">Forcer la présence d\'un contrôleur</string>
|
||||
<string name="summary_checkbox_multi_controller">Lorsqu\'elle n\'est pas cochée, tous les contrôleurs sont regroupés</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emuler support vibration de secours</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Emuler des tremblements si votre manette ne le prend pas en charge</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Utiliser l\'écran tactile comme trackpad</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">Si activé, l\'écran tactile agit comme un trackpad. Si désactivé, l\'écran tactile contrôle directement le curseur de la souris.</string>
|
||||
<string name="title_checkbox_multi_controller">Forcer la présence d\'une manette</string>
|
||||
<string name="summary_checkbox_multi_controller">Décocher cette option force une manette à toujours être présente</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Émuler les vibrations de la manette avec l\'appareil</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Fait vibrer votre appareil pour émuler les vibrations de la manette si elle ne le supporte pas</string>
|
||||
<string name="title_seekbar_deadzone">Régler la zone morte du stick analogique</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Pilote de contrôleur Xbox 360/One</string>
|
||||
<string name="summary_checkbox_xb1_driver">Active un pilote USB intégré pour les périphériques sans prise en charge du contrôleur Xbox natif</string>
|
||||
<string name="title_checkbox_usb_bind_all">Ignorer le support du contrôleur Android</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Force le pilote USB de Moonlight à prendre en charge tous les gamepads Xbox pris en charge</string>
|
||||
<string name="title_checkbox_mouse_emulation">Emulation de la souris via le gamepad</string>
|
||||
<string name="title_checkbox_xb1_driver">Pilote USB pour manette Xbox 360/One</string>
|
||||
<string name="summary_checkbox_xb1_driver">Active un pilote USB intégré pour les appareils qui ne prennent pas nativement en charge les manettes Xbox</string>
|
||||
<string name="title_checkbox_usb_bind_all">Remplacer le support natif des manettes Xbox</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Utilise le pilote USB de Moonlight pour toutes les manettes prises en charge, même si l\'appareil supporte nativement celles-ci</string>
|
||||
<string name="title_checkbox_mouse_emulation">Émuler la souris avec la manette</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Appuyez longuement sur le bouton Start pour faire basculer la manette en mode souris</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Activer les boutons de la souris arrière et avant</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">L\' activation de cette option peut casser le clic droit sur certains appareils bogués</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Boutons de face inversé</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Commute les boutons de face A/B et X/Y pour les manettes de jeu et les commandes à l\'écran</string>
|
||||
<string name="category_on_screen_controls_settings">Paramètres des contrôles à l\'écran</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Inverser les boutons en façade</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Commute les boutons de face A/B et X/Y pour les manettes et les commandes à l\'écran</string>
|
||||
<string name="category_on_screen_controls_settings">Paramètres des commandes à l\'écran</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Afficher les commandes à l\'écran</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Afficher la superposition du contrôleur virtuel sur l\'écran tactile</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Affiche une manette virtuelle sur l\'écran tacile</string>
|
||||
<string name="title_checkbox_vibrate_osc">Activer les vibrations</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Emuler des tremblements des commandes à l\'écran</string>
|
||||
<string name="title_only_l3r3">Montre seulement L3 et R3</string>
|
||||
<string name="summary_only_l3r3">Cacher tout sauf L3 et R3</string>
|
||||
<string name="title_reset_osc">Effacer la disposition des commandes à l\'écran sauvegardée</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Fait vibrer votre appareil pour émuler les vibrations des commandes à l\'écran</string>
|
||||
<string name="title_only_l3r3">Montrer seulement L3 et R3</string>
|
||||
<string name="summary_only_l3r3">Cacher tous les boutons sauf L3 et R3</string>
|
||||
<string name="title_reset_osc">Réinitialiser la disposition des commandes</string>
|
||||
<string name="summary_reset_osc">Rétablit la taille et la position par défaut de tous les contrôles à l\'écran</string>
|
||||
<string name="dialog_title_reset_osc">Réinitialiser la mise en page</string>
|
||||
<string name="dialog_text_reset_osc">Êtes-vous sûr de vouloir supprimer la disposition des commandes à l\'écran que vous avez sauvegardée \?</string>
|
||||
<string name="toast_reset_osc_success">Les contrôles à l\'écran sont réinitialisés</string>
|
||||
<string name="dialog_title_reset_osc">Réinitialiser la disposition</string>
|
||||
<string name="dialog_text_reset_osc">Êtes-vous sûr de vouloir supprimer votre disposition de commandes à l\'écran ?</string>
|
||||
<string name="toast_reset_osc_success">Les contrôles à l\'écran ont été réinitialisés</string>
|
||||
<string name="title_osc_opacity">Modifier l\'opacité des contrôles à l\'écran</string>
|
||||
<string name="summary_osc_opacity">Rendre les contrôles à l\'écran plus/moins transparents</string>
|
||||
<string name="dialog_title_osc_opacity">Modifiez l\'opacité</string>
|
||||
<string name="summary_osc_opacity">Permet de rendre les contrôles à l\'écran plus ou moins transparents</string>
|
||||
<string name="dialog_title_osc_opacity">Modifier l\'opacité</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="category_ui_settings">Paramètres de l\'interface utilisateur</string>
|
||||
<string name="title_language_list">Langue</string>
|
||||
<string name="summary_language_list">Langue à utiliser pour Moonlight</string>
|
||||
<string name="title_checkbox_small_icon_mode">Utiliser des petites icônes</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Utilisez les petites icônes dans les éléments de la grille pour permettre plus d\'éléments à l\'écran</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Des icônes plus petites permettent d\'afficher plus d\'applications en même temps</string>
|
||||
<string name="category_host_settings">Paramètres de l\'hôte</string>
|
||||
<string name="title_checkbox_enable_sops">Optimiser les paramètres de jeu</string>
|
||||
<string name="summary_checkbox_enable_sops">Autoriser GFE à modifier les paramètres de jeu pour une diffusion optimale</string>
|
||||
<string name="title_checkbox_enable_sops">Optimiser les paramètres du jeu</string>
|
||||
<string name="summary_checkbox_enable_sops">Autoriser GFE à modifier les paramètres du jeu pour un streaming optimal</string>
|
||||
<string name="title_checkbox_host_audio">Jouer l\'audio sur le PC</string>
|
||||
<string name="summary_checkbox_host_audio">Lire l\'audio de l\'ordinateur et de ce périphérique</string>
|
||||
<string name="summary_checkbox_host_audio">Lire l\'audio sur l\'ordinateur et sur cet appareil</string>
|
||||
<string name="category_advanced_settings">Réglages avancés</string>
|
||||
<string name="title_unlock_fps">Débloquez toutes les fréquences d\'images possibles</string>
|
||||
<string name="summary_unlock_fps">Le streaming à 90 ou 120 FPS peut réduire la latence sur les appareils haut de gamme, mais peut entraîner un décalage ou une instabilité sur les appareils qui ne peuvent pas le prendre en charge</string>
|
||||
<string name="summary_checkbox_disable_warnings">Désactiver les messages d\'avertissement de connexion à l\'écran pendant la diffusion</string>
|
||||
<string name="title_disable_frame_drop">Ne jamais laisser tomber les frames</string>
|
||||
<string name="title_unlock_fps">Débloquer toutes les fréquences d\'images possibles</string>
|
||||
<string name="summary_unlock_fps">Le streaming à 90 ou 120 FPS peut réduire la latence sur les appareils haut de gamme, mais peut entraîner un décalage ou une instabilité sur les appareils qui ne le supporte pas</string>
|
||||
<string name="summary_checkbox_disable_warnings">Désactive les messages d\'avertissement sur la connexion pendant le stream</string>
|
||||
<string name="title_disable_frame_drop">Ne jamais perdre d\'images</string>
|
||||
<string name="summary_disable_frame_drop">Peut réduire les micro-saccades sur certains appareils, mais peut augmenter la latence</string>
|
||||
<string name="title_video_format">Modifier les paramètres de codec</string>
|
||||
<string name="summary_video_format">Les nouveaux codecs peuvent réduire la bande passante vidéo requise si votre appareil les prend en charge. Les codecs séléctionnés peuvent être ignorés si ils ne sont pas prises en charge par le logiciel hôte ou le GPU.</string>
|
||||
<string name="title_enable_hdr">Activer le HDR (expérimental)</string>
|
||||
<string name="summary_enable_hdr">Diffuser du HDR lorsque le jeu et le processeur graphique du PC le prennent en charge. Le HDR nécessite un GPU pouvant encoder en HEVC Main 10.</string>
|
||||
<string name="title_enable_perf_overlay">Activer la superposition de performance</string>
|
||||
<string name="summary_enable_perf_overlay">Afficher une superposition à l\'écran avec des informations de performance en temps réel pendant la lecture en continu</string>
|
||||
<string name="title_enable_post_stream_toast">Afficher le message de latence après la diffusion en continu</string>
|
||||
<string name="summary_enable_post_stream_toast">Afficher un message d’informations de latence après la fin du flux</string>
|
||||
<string name="no_video_received_error">Aucune vidéo reçue depuis l\'hôte.</string>
|
||||
<string name="summary_enable_hdr">Streamer en HDR lorsque le jeu et le GPU du PC le prennent en charge. Le HDR nécessite un GPU pouvant encoder en HEVC Main 10.</string>
|
||||
<string name="title_enable_perf_overlay">Afficher les statistiques de peformance lors du stream</string>
|
||||
<string name="summary_enable_perf_overlay">Affiche des informations sur les performances du stream en temps réel pendant le stream</string>
|
||||
<string name="title_enable_post_stream_toast">Afficher la latence moyenne après un stream</string>
|
||||
<string name="summary_enable_post_stream_toast">Affiche un message d’information sur la latence après la fin du stream</string>
|
||||
<string name="no_video_received_error">Aucune vidéo reçue de l\'hôte.</string>
|
||||
<string name="video_decoder_init_failed">Le décodeur vidéo n\'a pas pu démarrer. Vérifiez que votre appareil supporte la résolution ou la fréquence d\'images choisie.</string>
|
||||
<string name="pcview_menu_test_network">Tester la connection réseau</string>
|
||||
<string name="pcview_menu_header_unknown">Actualisation</string>
|
||||
@ -209,13 +207,13 @@
|
||||
\nNous ne sommes pas responsables des problèmes résultant de la création d\'une résolution personnalisée sur votre PC.
|
||||
\n
|
||||
\nIl se peut que votre moniteur ne prenne pas en charge la configuration d\'affichage requise. Si c\'est le cas, vous pouvez essayer de configurer un moniteur virtuel. Enfin, si votre appareil ou votre PC hôte ne prend pas en charge le streaming à une résolution ou à un taux de rafraîchissement spécifique, vous ne pourrez pas y faire grand chose malheureusement.</string>
|
||||
<string name="title_native_res_dialog">Avertissement résolution native</string>
|
||||
<string name="title_native_res_dialog">Avertissement sur la résolution native</string>
|
||||
<string name="applist_menu_hide_app">Cacher l\'application</string>
|
||||
<string name="check_ports_msg">Vérifiez vos règles de pare-feu pour les ports suivants :</string>
|
||||
<string name="early_termination_error">Quelque chose s\'est mal passé sur votre PC hôte en démarrant le flux.
|
||||
<string name="early_termination_error">Quelque chose s\'est mal passé sur votre PC hôte en démarrant le stream.
|
||||
\n
|
||||
\nVérifiez qu\'aucune application utilisant un DRM n\'est ouverte sur votre PC hôte. Vous pouvez aussi essayer de redémarrer votre PC hôte.</string>
|
||||
<string name="no_frame_received_error">Votre connexion ne fonctionne pas bien. Baissez votre paramètres de débit ou utilisez une connexion plus rapide.</string>
|
||||
<string name="no_frame_received_error">Votre connexion réseau ne fonctionne pas bien. Baissez votre débit ou utilisez une connexion plus rapide.</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Plein-écran natif</string>
|
||||
<string name="perf_overlay_netlatency">Latence réseau moyenne : %1$d ms (variance : %2$d ms)</string>
|
||||
<string name="perf_overlay_streamdetails">Stream vidéo : %1$s %2$.2f FPS</string>
|
||||
@ -228,7 +226,7 @@
|
||||
<string name="audioconf_51surround">Son surround 5.1</string>
|
||||
<string name="audioconf_71surround">Son surround 7.1</string>
|
||||
<string name="videoformat_auto">Automatique (recommandé)</string>
|
||||
<string name="videoformat_hevcalways">Préférez le HEVC</string>
|
||||
<string name="videoformat_hevcalways">Préférer 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>
|
||||
<string name="pacing_latency">Préférer une latence plus faible</string>
|
||||
@ -245,12 +243,12 @@
|
||||
<string name="title_troubleshooting">Guide de dépannage</string>
|
||||
<string name="title_privacy_policy">Politique de confidentialité</string>
|
||||
<string name="summary_privacy_policy">Voir la politique de confidentialité de Moonlight</string>
|
||||
<string name="summary_setup_guide">Afficher les instructions sur la façon de configurer votre PC de jeu pour le streaming</string>
|
||||
<string name="summary_troubleshooting">Afficher des conseils pour diagnostiquer et résoudre les problèmes de streaming courants</string>
|
||||
<string name="summary_setup_guide">Voir les instructions sur la façon de configurer votre PC de jeu pour le streaming</string>
|
||||
<string name="summary_troubleshooting">Voir des conseils pour diagnostiquer et résoudre les problèmes de streaming courants</string>
|
||||
<string name="pacing_balanced_alt">Équilibré avec limite FPS</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Mode souris pour bureau à distance</string>
|
||||
<string name="summary_seekbar_deadzone">Remarque : Certains jeux peuvent imposer une zone morte plus grande que celle que Moonlight est configuré pour utiliser.</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Cela peut rendre l\'accélération de la souris plus naturelle pour l\'utilisation du bureau à distance, mais elle est incompatible avec de nombreux jeux.</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Cela peut rendre l\'accélération de la souris plus naturelle pour l\'utilisation du bureau à distance, mais il est incompatible avec de nombreux jeux.</string>
|
||||
<string name="resolution_prefix_native_landscape">(Paysage)</string>
|
||||
<string name="resolution_prefix_native_portrait">(Portrait)</string>
|
||||
<string name="title_checkbox_reduce_refresh_rate">Autoriser la réduction du taux de rafraîchissement</string>
|
||||
@ -259,23 +257,32 @@
|
||||
<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>
|
||||
\nEssayez de désactiver le mode HDR, de changer la résolution du stream 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>
|
||||
<string name="summary_full_range">Cela causera une perte de détails dans les zones claires et sombres si votre appareil n\'affiche pas correctement la vidéo avec une gamme de couleurs complète.</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream : fin de service</string>
|
||||
<string name="pair_pairing_help">Si votre PC hôte utilise Sunshine, accédez à l\'interface web de Sunshine pour saisir le code PIN.</string>
|
||||
<string name="category_gamepad_settings">Paramètres manette</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Latence de traitement de l\'hôte min/max/moyenne : %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="title_native_fps_dialog">Avertissement FPS natif</string>
|
||||
<string name="title_native_fps_dialog">Avertissement sur le FPS natif</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Autoriser l\'utilisation des capteurs de mouvement de la manette</string>
|
||||
<string name="videoformat_av1always">Préférer AV1 (expérimental)</string>
|
||||
<string name="videoformat_h264always">Préférer H.264</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Toujours controller la souris avec le pavé tactile</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Force le pavé tactile de la manette à contrôler la souris de l\'hôte, même quand l\'émulation d\'une manette par le pavé tactile est activée.</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Permet aux hôtes pris en charge de demander des données de capteur de mouvement lors de l\'émulation d\'une manette avec des capteurs de mouvement. Désactiver ce paramètre peut réduire légèrement l\'utilisation de l\'alimentation et du réseau si les capteurs de mouvement ne sont pas utilisés en jeu.</string>
|
||||
<string name="toast_controller_type_changed">Le type de manette peut être modifié en raison de l\'émulation du capteur de mouvement</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Force le pavé tactile de la manette à contrôler la souris de l\'hôte, même quand une manette avec pavé tactile est émulée.</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Permet aux hôtes pris en charge de demander les données du capteur de mouvement lors de l\'émulation d\'une manette compatible. Désactiver ce paramètre peut réduire légèrement l\'utilisation de la batterie et du réseau si les capteurs de mouvement ne sont pas utilisés en jeu.</string>
|
||||
<string name="toast_controller_type_changed">Le type de manette peut être différent dû à l\'émulation du capteur de mouvement</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Utilise les capteurs de mouvement de votre appareil si la manette connéctée n\'en a pas, ou qu\'ils ne sont pas pris en charge par votre version d\'Android.
|
||||
\nRemarque : l\'activation de cette option peut faire apparaître votre manette de jeu comme une manette PlayStation du côté hôte.</string>
|
||||
\nRemarque : activer cette option peut faire apparaître votre manette côté hôte comme une manette PlayStation.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Émuler les capteurs de mouvement de la manette</string>
|
||||
<string name="title_analog_scrolling">Utiliser un stick analogique pour faire défiler</string>
|
||||
<string name="summary_analog_scrolling">Séléctionner un stick analogique à utiliser pour faire défiler lors de l\'émulation de la souris</string>
|
||||
<string name="analogscroll_none">Aucun (les deux sticks déplacent la souris)</string>
|
||||
<string name="analogscroll_right">Stick analogique droit</string>
|
||||
<string name="analogscroll_left">Stick analogique gauche</string>
|
||||
<string name="error_code_prefix">Code d\'erreur :</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Ajuster l\'intensité de la vibration émulée</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Amplifie ou réduit l\'intensité de la vibration sur votre appareil</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
</resources>
|
@ -33,7 +33,7 @@
|
||||
<string name="unpairing">Disaccoppiamento…</string>
|
||||
<string name="unpair_success">Disaccoppiato con successo</string>
|
||||
<string name="unpair_fail">Disaccoppiamento fallito</string>
|
||||
<string name="unpair_error">PC non accoppiato</string>
|
||||
<string name="unpair_error">Il dispositivo non è stato accoppiato</string>
|
||||
<!-- Errors -->
|
||||
<string name="error_pc_offline">PC offline</string>
|
||||
<string name="error_manager_not_running">Il servizio ComputerManager non è avviato. Attendi qualche secondo o riavvia l\'applicazione.</string>
|
||||
@ -91,7 +91,7 @@
|
||||
<string name="addpc_wrong_sitelocal">Quell\'indirizzo non sembra corretto. È necessario utilizzare l\'indirizzo IP pubblico del router per lo streaming su Internet.</string>
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">Impostazioni generali</string>
|
||||
<string name="title_resolution_list">Risoluzione e FPS</string>
|
||||
<string name="title_resolution_list">Risoluzione video</string>
|
||||
<string name="summary_resolution_list">Aumentare per migliorare la nitidezza dell\'immagine. Diminuire per aumentare le prestazioni su dispositivi di fascia più bassa e reti più lente.</string>
|
||||
<string name="title_seekbar_bitrate">Velocità di trasmissione video</string>
|
||||
<string name="summary_seekbar_bitrate">Aumentare per migliorare la qualità dell\'immagine. Diminuire per aumentare le prestazioni su reti più lente.</string>
|
||||
|
@ -221,7 +221,6 @@
|
||||
<string name="perf_overlay_netdrops">Frames overgeslagen door uw netwerkverbinding: %1$.2f%%</string>
|
||||
<string name="perf_overlay_dectime">Gemiddelde decodeertijd: %1$.2f ms</string>
|
||||
<string name="applist_menu_tv_channel">Toevoegen aan Kanaal</string>
|
||||
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcalways">Gebruik HEVC altijd (mogelijkheid tot crashes)</string>
|
||||
</resources>
|
@ -4,4 +4,272 @@
|
||||
<string name="scut_pc_not_found">PC nie znaleziony</string>
|
||||
<string name="pcview_menu_header_unknown">Odświeżanie</string>
|
||||
<string name="scut_not_paired">PC niesparowany</string>
|
||||
<string name="check_ports_msg">Sprawdź zaporę sieciową i reguły przekierowania portów:</string>
|
||||
<string name="conn_establishing_title">Nawiązywanie połączenia</string>
|
||||
<string name="conn_establishing_msg">Uruchamianie połączenia</string>
|
||||
<string name="title_details">Szczegóły</string>
|
||||
<string name="searching_pc">Wyszukiwanie komputerów-hostów w sieci lokalnej...
|
||||
\n
|
||||
\nUpewnij się, że aplikacja Sunshine jest uruchomiona na komputerze-hoście lub funkcja GameStream jest włączona w ustawieniach aplikacji GeForce Experience SHIELD.</string>
|
||||
<string name="yes">Tak</string>
|
||||
<string name="title_audio_config_list">Konfiguracja dźwięku przestrzennego</string>
|
||||
<string name="summary_audio_config_list">Włączenie dźwięku przestrzennego 5.1 lub 7.1 dla systemów kina domowego</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Długie naciśnięcie przycisku Start spowoduje przełączenie gamepada w tryb myszy</string>
|
||||
<string name="error_code_prefix">Kod błędu:</string>
|
||||
<string name="help">Pomoc</string>
|
||||
<string name="delete_pc_msg">Czy na pewno chcesz usunąć ten komputer?</string>
|
||||
<string name="slow_connection_msg">Wolne połączenie z komputerem
|
||||
\nZmniejsz szybkość transmisji</string>
|
||||
<string name="poor_connection_msg">Słabe połączenie z komputerem</string>
|
||||
<string name="perf_overlay_streamdetails">Strumień wideo: %1$s %2$.2f FPS</string>
|
||||
<string name="perf_overlay_decoder">Dekoder: %1$s</string>
|
||||
<string name="perf_overlay_incomingfps">Przychodząca liczba klatek na sekundę z sieci: %1$.2f FPS</string>
|
||||
<string name="applist_menu_quit_and_start">Zakończ bieżącą grę i uruchom</string>
|
||||
<string name="applist_menu_scut">Utwórz skrót</string>
|
||||
<string name="applist_menu_tv_channel">Dodaj do kanału</string>
|
||||
<string name="applist_refresh_title">Lista aplikacji</string>
|
||||
<string name="applist_refresh_error_msg">Nie udało się pobrać listy aplikacji</string>
|
||||
<string name="applist_quit_app">Rezygnacja</string>
|
||||
<string name="applist_quit_success">Zakończono z powodzeniem</string>
|
||||
<string name="applist_quit_fail">Nie udało się zakończyć</string>
|
||||
<string name="applist_quit_confirmation">Czy na pewno chcesz zamknąć uruchomioną aplikację? Wszystkie niezapisane dane zostaną utracone.</string>
|
||||
<string name="applist_details_id">App ID:</string>
|
||||
<string name="title_add_pc">Dodaj komputer ręcznie</string>
|
||||
<string name="msg_add_pc">Podłączanie do komputera…</string>
|
||||
<string name="addpc_unknown_host">Nie można określić adresu komputera. Upewnij się, że nie popełniłeś literówki w adresie.</string>
|
||||
<string name="addpc_wrong_sitelocal">Ten adres nie wygląda prawidłowo. Do przesyłania strumieniowego przez Internet należy używać publicznego adresu IP routera.</string>
|
||||
<string name="title_resolution_list">Rozdzielczość wideo</string>
|
||||
<string name="summary_resolution_list">Zwiększ, aby poprawić klarowność obrazu. Zmniejsz, aby uzyskać lepszą wydajność na słabszych urządzeniach i wolniejszych połączeniach sieciowych.</string>
|
||||
<string name="title_native_res_dialog">Ostrzeżenie o rozdzielczości natywnej</string>
|
||||
<string name="title_fps_list">Częstotliwość odświeżania wideo</string>
|
||||
<string name="summary_fps_list">Zwiększ, aby uzyskać płynniejszy strumień wideo. Zmniejsz, aby uzyskać lepszą wydajność na słabszych urządzeniach.</string>
|
||||
<string name="summary_seekbar_bitrate">Zwiększ, aby uzyskać lepszą jakość obrazu. Zmniejsz, aby poprawić wydajność na wolniejszych połączeniach.</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||
<string name="title_checkbox_stretch_video">Rozciągnięcie wideo do pełnego ekranu</string>
|
||||
<string name="resolution_prefix_native">Natywna</string>
|
||||
<string name="title_native_fps_dialog">Ostrzeżenie o natywnym FPS</string>
|
||||
<string name="title_checkbox_enable_audiofx">Włącz obsługę korektora systemowego</string>
|
||||
<string name="category_gamepad_settings">Ustawienia gamepada</string>
|
||||
<string name="title_checkbox_multi_controller">Automatyczne wykrywanie obecności gamepada</string>
|
||||
<string name="summary_checkbox_enable_audiofx">Umożliwia działanie efektów audio podczas przesyłania strumieniowego, ale może zwiększyć opóźnienie dźwięku</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emuluj wsparcie dudnienia za pomocą wibracji</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Regulacja intensywności emulowanego dudnienia</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Wzmocnienie lub zmniejszenie intensywności wibracji na urządzeniu</string>
|
||||
<string name="summary_checkbox_multi_controller">Odznaczenie tej opcji wymusza, by gamepad był zawsze obecny</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Wibruje urządzenie, aby naśladować dudnienie, jeśli gamepad go nie obsługuje</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
<string name="title_seekbar_deadzone">Regulacja strefy martwej drążka analogowego</string>
|
||||
<string name="summary_seekbar_deadzone">Uwaga: Niektóre gry mogą wymuszać większą strefę martwą niż ta, do której skonfigurowany jest Moonlight.</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Sterownik USB gamepada Xbox 360/One</string>
|
||||
<string name="title_checkbox_usb_bind_all">Zastąpienie natywnej obsługi gamepada Xbox</string>
|
||||
<string name="title_checkbox_mouse_emulation">Emulacja myszy za pomocą gamepada</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Zamiana przycisków akcji A/B/X/Y</string>
|
||||
<string name="summary_checkbox_xb1_driver">Włącza wbudowany sterownik USB dla urządzeń bez natywnej obsługi kontrolera Xbox</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Użyj sterownika USB Moonlight dla wszystkich obsługiwanych gamepadów, nawet jeśli natywna obsługa kontrolera Xbox jest obecna</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Zawsze kontroluj mysz za pomocą touchpada</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Wymusza sterowanie myszą za pomocą touchpada gamepada, nawet w przypadku emulacji gamepada z touchpadem.</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Zezwalaj na korzystanie z czujników ruchu gamepada</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Umożliwia obsługiwanym hostom żądanie danych z czujników ruchu podczas emulacji gamepada z czujnikami ruchu. Wyłączenie może nieznacznie zmniejszyć zużycie energii i sieci, jeśli czujniki ruchu nie są używane w grze.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Emulacja obsługi czujnika ruchu gamepada</string>
|
||||
<string name="category_input_settings">Ustawienia wejścia</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Używanie ekranu dotykowego jako gładzika</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">Jeśli opcja ta jest włączona, ekran dotykowy działa jak gładzik. Jeśli jest wyłączony, ekran dotykowy bezpośrednio steruje kursorem myszy.</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Tryb myszy dla pulpitu zdalnego</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Włączanie przycisków myszy wstecz i dalej</string>
|
||||
<string name="category_on_screen_controls_settings">Ustawienia sterowania na ekranie</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Wyświetlanie ustawień sterowania na ekranie</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Wyświetlanie nakładki wirtualnego kontrolera na ekranie dotykowym</string>
|
||||
<string name="title_checkbox_vibrate_osc">Włącz wibracje</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Włączenie tej opcji może uniemożliwić kliknięcie prawym przyciskiem myszy na niektórych problematycznych urządzeniach</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Wibruje urządzenie, aby naśladować dudnienie przy ustawieniach sterowania na ekranie</string>
|
||||
<string name="title_only_l3r3">Pokaż tylko L3 i R3</string>
|
||||
<string name="summary_only_l3r3">Ukryj wszystkie przyciski wirtualne z wyjątkiem L3 i R3</string>
|
||||
<string name="title_reset_osc">Wyczyść zapisany układ elementów sterujących na ekranie</string>
|
||||
<string name="toast_reset_osc_success">Przywrócenie domyślnych ustawień elementów sterujących na ekranie</string>
|
||||
<string name="title_osc_opacity">Zmiana krycia elementów sterujących na ekranie</string>
|
||||
<string name="summary_osc_opacity">Zwiększanie/zmniejszanie przezroczystości elementów sterujących na ekranie</string>
|
||||
<string name="dialog_title_osc_opacity">Zmiana krycia</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="category_ui_settings">Ustawienia interfejsu użytkownika</string>
|
||||
<string name="title_checkbox_enable_pip">Włącz tryb obserwatora obrazu w obrazie</string>
|
||||
<string name="summary_reset_osc">Przywraca domyślny rozmiar i położenie wszystkich elementów sterujących na ekranie</string>
|
||||
<string name="title_language_list">Język</string>
|
||||
<string name="summary_language_list">Język używany w Moonlight</string>
|
||||
<string name="category_host_settings">Ustawienia hosta</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Mniejsze ramki w siatce aplikacji pozwalają na wyświetlanie większej liczby aplikacji na ekranie</string>
|
||||
<string name="title_checkbox_enable_sops">Optymalizacja ustawień gry</string>
|
||||
<string name="summary_checkbox_enable_sops">Zezwalanie GFE na modyfikowanie ustawień gry w celu optymalnego streamowania</string>
|
||||
<string name="title_checkbox_host_audio">Odtwarzanie dźwięku na komputerze</string>
|
||||
<string name="summary_checkbox_host_audio">Odtwarzanie dźwięku z komputera i tego urządzenia</string>
|
||||
<string name="category_advanced_settings">Ustawienia zaawansowane</string>
|
||||
<string name="title_unlock_fps">Odblokuj wszystkie możliwe liczby klatek na sekundę</string>
|
||||
<string name="title_checkbox_reduce_refresh_rate">Zezwalaj na zmniejszenie częstotliwości odświeżania</string>
|
||||
<string name="summary_checkbox_reduce_refresh_rate">Niższe częstotliwości odświeżania wyświetlacza mogą oszczędzać energię kosztem dodatkowych opóźnień wideo</string>
|
||||
<string name="summary_unlock_fps">Przesyłanie strumieniowe w 90 lub 120 klatkach na sekundę może zmniejszyć opóźnienia na urządzeniach wysokiej klasy, ale może powodować opóźnienia lub niestabilność na urządzeniach, które nie są w stanie tego obsłużyć</string>
|
||||
<string name="title_checkbox_disable_warnings">Wyłączanie komunikatów ostrzegawczych</string>
|
||||
<string name="summary_checkbox_disable_warnings">Wyłączanie wyświetlanych na ekranie komunikatów ostrzegawczych o połączeniu podczas przesyłania strumieniowego</string>
|
||||
<string name="title_disable_frame_drop">Nigdy nie porzucaj klatek</string>
|
||||
<string name="title_video_format">Zmiana ustawień kodeka</string>
|
||||
<string name="summary_video_format">Nowsze kodeki mogą obniżyć wymagania dotyczące przepustowości wideo, jeśli urządzenie je obsługuje. Wybrane kodeki mogą zostać zignorowane, jeśli nie są obsługiwane przez oprogramowanie hosta lub procesor graficzny.</string>
|
||||
<string name="summary_disable_frame_drop">Może zmniejszyć mikroprzycięcia na niektórych urządzeniach, ale może zwiększyć opóźnienia</string>
|
||||
<string name="title_enable_hdr">Włącz HDR (eksperymentalnie)</string>
|
||||
<string name="summary_enable_hdr">Przesyłaj strumieniowo HDR, gdy gra i procesor graficzny komputera obsługują tę funkcję. HDR wymaga GPU z obsługą kodowania HEVC Main 10.</string>
|
||||
<string name="title_full_range">Wymuś pełny zakres wideo (eksperymentalne)</string>
|
||||
<string name="summary_enable_perf_overlay">Wyświetlanie informacji o wydajności strumienia w czasie rzeczywistym podczas strumieniowania</string>
|
||||
<string name="title_enable_post_stream_toast">Wyświetlanie komunikatu o opóźnieniu po przesyłaniu strumieniowym</string>
|
||||
<string name="summary_full_range">Spowoduje to utratę szczegółów w jasnych i ciemnych obszarach, jeśli urządzenie nie wyświetla prawidłowo treści wideo w pełnym zakresie.</string>
|
||||
<string name="summary_enable_post_stream_toast">Wyświetlanie komunikatu informującego o opóźnieniu po zakończeniu strumienia</string>
|
||||
<string name="title_setup_guide">Instrukcja konfiguracji</string>
|
||||
<string name="title_privacy_policy">Polityka prywatności</string>
|
||||
<string name="summary_privacy_policy">Zobacz politykę prywatności Moonlight</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="toast_controller_type_changed">Typ gamepada może zostać zmieniony z powodu emulacji czujnika ruchu</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="fps_90">90 FPS</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="videoformat_h264always">Preferowany H.264</string>
|
||||
<string name="pacing_balanced_alt">Zrównoważone z limitem FPS</string>
|
||||
<string name="pacing_smoothness">Preferowanie najbardziej płynnego wideo (może znacznie zwiększyć opóźnienie)</string>
|
||||
<string name="title_analog_scrolling">Użyj drążka analogowego do przewijania</string>
|
||||
<string name="summary_analog_scrolling">Wybór drążka analogowego do przewijania w trybie emulacji myszy</string>
|
||||
<string name="analogscroll_none">Brak (oba drążki poruszają myszą)</string>
|
||||
<string name="analogscroll_right">Prawy drążek analogowy</string>
|
||||
<string name="analogscroll_left">Lewy drążek analogowy</string>
|
||||
<string name="scut_invalid_app_id">Podana aplikacja jest niepoprawna</string>
|
||||
<string name="scut_invalid_uuid">Podany PC jest niepoprawny</string>
|
||||
<string name="pcview_menu_delete_pc">Usuń PC</string>
|
||||
<string name="pcview_menu_test_network">Test połączenia sieciowego</string>
|
||||
<string name="pcview_menu_details">Wyświetl szczegóły</string>
|
||||
<string name="nettest_title_done">Test sieci zakończony</string>
|
||||
<string name="nettest_text_failure">Bieżące połączenie sieciowe urządzenia wydaje się blokować Moonlight. Przesyłanie strumieniowe przez Internet może nie działać podczas połączenia z tą siecią.
|
||||
\n
|
||||
\nNastępujące porty sieciowe zostały zablokowane:
|
||||
\n</string>
|
||||
<string name="nettest_text_blocked">Bieżące połączenie sieciowe urządzenia blokuje Moonlight. Przesyłanie strumieniowe przez Internet może nie działać podczas połączenia z tą siecią.</string>
|
||||
<string name="pair_pairing_title">Parowanie</string>
|
||||
<string name="pair_pc_offline">Komputer jest offline</string>
|
||||
<string name="pair_incorrect_pin">Nieprawidłowy kod PIN</string>
|
||||
<string name="pair_fail">Parowanie nie powiodło się</string>
|
||||
<string name="pair_already_in_progress">Parowanie jest już w toku</string>
|
||||
<string name="wol_pc_online">Komputer jest online</string>
|
||||
<string name="wol_no_mac">Nie można wybudzić komputera, ponieważ nie ma zapisanego adresu MAC</string>
|
||||
<string name="wol_waking_pc">Uruchamianie PC…</string>
|
||||
<string name="wol_waking_msg">Uruchomienie komputera może potrwać kilka sekund. Jeśli tak się nie stanie, upewnij się, że jest prawidłowo skonfigurowany do Wake-On-LAN.</string>
|
||||
<string name="unpair_fail">Rozparowanie nie powiodło się</string>
|
||||
<string name="unpair_error">Urządzenie nie zostało sparowane</string>
|
||||
<string name="error_pc_offline">Komputer jest offline</string>
|
||||
<string name="error_unknown_host">Nie udało się zlokalizować hosta</string>
|
||||
<string name="message_decoding_error">Moonlight uległ awarii z powodu niezgodności z dekoderem wideo tego urządzenia. Spróbuj dostosować ustawienia przesyłania strumieniowego jeśli awarie będą się powtarzać.</string>
|
||||
<string name="error_404">GFE zwrócił błąd HTTP 404. Upewnij się, że w Twoim komputerze działa obsługiwany procesor graficzny. Używanie oprogramowania pulpitu zdalnego może również powodować ten błąd. Spróbuj ponownie uruchomić komputer lub ponownie zainstalować GFE.</string>
|
||||
<string name="title_decoding_reset">Reset ustawień wideo</string>
|
||||
<string name="error_usb_prohibited">Dostęp USB jest zabroniony przez administratora urządzenia. Sprawdź ustawienia Knox lub MDM.</string>
|
||||
<string name="video_decoder_init_failed">Nie udało się zainicjować dekodera wideo. Urządzenie może nie obsługiwać wybranej rozdzielczości lub liczby klatek na sekundę.</string>
|
||||
<string name="early_termination_error">Coś poszło nie tak na komputerze hosta podczas uruchamiania transmisji.
|
||||
\n
|
||||
\nUpewnij się, że na komputerze hosta nie masz otwartej żadnej zawartości zabezpieczonej DRM. Możesz także spróbować ponownie uruchomić komputer hosta.</string>
|
||||
<string name="conn_error_msg">Nie udało się uruchomić</string>
|
||||
<string name="conn_terminated_msg">Połączenie zostało przerwane.</string>
|
||||
<string name="perf_overlay_renderingfps">Liczba klatek na sekundę renderowania: %1$.2f FPS</string>
|
||||
<string name="applist_refresh_error_title">Błąd</string>
|
||||
<string name="applist_refresh_msg">Odświeżanie aplikacji…</string>
|
||||
<string name="addpc_enter_ip">Należy wprowadzić adres IP</string>
|
||||
<string name="category_audio_settings">Ustawienia audio</string>
|
||||
<string name="title_frame_pacing">Tempo klatek wideo</string>
|
||||
<string name="pacing_balanced">Zrównoważone</string>
|
||||
<string name="no">Nie</string>
|
||||
<string name="applist_menu_quit">Zakończenie sesji</string>
|
||||
<string name="title_seekbar_bitrate">Szybkość transmisji wideo</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Przełącza przyciski A/B i X/Y dla gamepadów i elementów sterujących na ekranie</string>
|
||||
<string name="category_help">Pomoc</string>
|
||||
<string name="resolution_480p">480p</string>
|
||||
<string name="pair_pairing_msg">Wprowadź następujący kod PIN na komputerze docelowym:</string>
|
||||
<string name="pair_pairing_help">Jeśli na komputerze hosta działa Sunshine, przejdź do interfejsu użytkownika Sunshine aby wprowadzić kod PIN.</string>
|
||||
<string name="unpairing">Rozparowywanie…</string>
|
||||
<string name="unpair_success">Rozparowano z powodzeniem</string>
|
||||
<string name="unable_to_pin_shortcut">Obecny program uruchamiający nie pozwala na tworzenie przypiętych skrótów.</string>
|
||||
<string name="conn_client_latency">Średnie opóźnienie dekodowania ramki:</string>
|
||||
<string name="conn_client_latency_hw">opóźnienie dekodera sprzętowego:</string>
|
||||
<string name="conn_metered">Ostrzeżenie: Aktywne połączenie sieciowe jest taryfowe!</string>
|
||||
<string name="conn_hardware_latency">Średnie opóźnienie dekodowania sprzętowego:</string>
|
||||
<string name="conn_starting">Uruchamianie</string>
|
||||
<string name="conn_error_title">Błąd połączenia</string>
|
||||
<string name="lost_connection">Utrata połączenia z komputerem</string>
|
||||
<string name="dialog_title_reset_osc">Reset układu</string>
|
||||
<string name="dialog_text_reset_osc">Czy na pewno chcesz usunąć zapisany układ kontrolek ekranowych?</string>
|
||||
<string name="summary_checkbox_enable_pip">Umożliwia wyświetlanie strumienia (ale nie sterowanie nim) podczas pracy wielozadaniowej</string>
|
||||
<string name="title_checkbox_small_icon_mode">Używaj małe ramki</string>
|
||||
<string name="title_enable_perf_overlay">Wyświetlanie statystyk wydajności podczas przesyłania strumieniowego</string>
|
||||
<string name="summary_troubleshooting">Zobacz wskazówki dotyczące diagnozowania i naprawiania typowych problemów z transmisją strumieniową</string>
|
||||
<string name="audioconf_51surround">5.1 Surround Sound</string>
|
||||
<string name="audioconf_71surround">7.1 Surround Sound</string>
|
||||
<string name="videoformat_hevcalways">Preferowany HEVC</string>
|
||||
<string name="summary_frame_pacing">Określenie sposobu równoważenia opóźnienia i płynności wideo</string>
|
||||
<string name="pacing_latency">Preferowane najniższe opóźnienia</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Opóźnienie przetwarzania hosta min/max/średnia: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="perf_overlay_netlatency">Średnie opóźnienie sieci: %1$d ms (wariancja: %2$d ms)</string>
|
||||
<string name="applist_connect_msg">Podłączanie do komputera…</string>
|
||||
<string name="applist_menu_resume">Wznowienie sesji</string>
|
||||
<string name="perf_overlay_netdrops">Ramki porzucone przez połączenie sieciowe: %1$.2f%%</string>
|
||||
<string name="perf_overlay_dectime">Średni czas dekodowania: %1$.2f ms</string>
|
||||
<string name="addpc_success">Dodano komputer z powodzeniem</string>
|
||||
<string name="resolution_prefix_native_landscape">(Panoramiczny)</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Natywny pełny ekran</string>
|
||||
<string name="resolution_prefix_native_portrait">(Portretowy)</string>
|
||||
<string name="resolution_1080p">1080p</string>
|
||||
<string name="help_loading_msg">Ładowanie strony pomocy…</string>
|
||||
<string name="pcview_menu_header_online">Online</string>
|
||||
<string name="pcview_menu_header_offline">Offline</string>
|
||||
<string name="pcview_menu_app_list">Wyświetl wszystkie aplikacje</string>
|
||||
<string name="help_loading_title">Przeglądarka pomocy</string>
|
||||
<string name="pcview_menu_pair_pc">Sparuj z PC</string>
|
||||
<string name="pcview_menu_unpair_pc">Rozparuj</string>
|
||||
<string name="pcview_menu_send_wol">Wyślij żądanie Wake-On-LAN</string>
|
||||
<string name="nettest_text_waiting">Moonlight testuje połączenie sieciowe w celu ustalenia, czy wymagane porty są zablokowane.
|
||||
\n
|
||||
\nMoże to potrwać kilka sekund…</string>
|
||||
<string name="pairing">Parowanie…</string>
|
||||
<string name="pair_pc_ingame">Komputer jest obecnie w trakcie gry. Przed sparowaniem należy zamknąć grę.</string>
|
||||
<string name="nettest_text_success">Wygląda na to, że sieć nie blokuje Moonlight. Jeśli nadal masz problemy z połączeniem, sprawdź ustawienia zapory sieciowej na swoim komputerze.
|
||||
\n
|
||||
\nJeśli próbujesz przesyłać strumieniowo przez Internet, zainstaluj narzędzie Moonlight Internet Hosting Tool na swoim komputerze i uruchom dołączony tester przesyłania strumieniowego przez Internet, aby sprawdzić połączenie internetowe komputera.</string>
|
||||
<string name="pcview_menu_eol">Zakończenie usług NVIDIA GameStream</string>
|
||||
<string name="nettest_text_inconclusive">Nie można było wykonać testu sieci ponieważ żaden z serwerów testujących połączenie Moonlight nie był osiągalny. Sprawdź połączenie internetowe lub spróbuj ponownie później.</string>
|
||||
<string name="nettest_title_waiting">Testowanie połączenia sieciowego</string>
|
||||
<string name="wol_fail">Nie udało się wysłać pakietów Wake-On-LAN</string>
|
||||
<string name="error_manager_not_running">Usługa ComputerManager nie jest uruchomiona. Poczekaj kilka sekund lub uruchom ponownie aplikację.</string>
|
||||
<string name="title_decoding_error">Awaria dekodera wideo</string>
|
||||
<string name="message_decoding_reset">Dekoder wideo urządzenia nadal ulega awarii przy wybranych ustawieniach przesyłania strumieniowego. Ustawienia przesyłania strumieniowego zostały zresetowane do wartości domyślnych.</string>
|
||||
<string name="no_video_received_error">Brak sygnału wideo od hosta.</string>
|
||||
<string name="no_frame_received_error">Połączenie sieciowe nie działa prawidłowo. Zmniejsz ustawienie szybkości transmisji wideo lub wypróbuj szybsze połączenie.</string>
|
||||
<string name="frame_conversion_error">Komputer host zgłosił krytyczny błąd kodowania wideo.
|
||||
\n
|
||||
\nSpróbuj wyłączyć tryb HDR, zmienić rozdzielczość przesyłania strumieniowego lub rozdzielczość wyświetlacza komputera hosta.</string>
|
||||
<string name="conn_terminated_title">Połączenie zakończone</string>
|
||||
<string name="ip_hint">Adres IP komputera hosta</string>
|
||||
<string name="applist_menu_cancel">Anuluj</string>
|
||||
<string name="applist_menu_hide_app">Ukryj aplikację</string>
|
||||
<string name="applist_menu_details">Wyświetl szczegóły</string>
|
||||
<string name="addpc_fail">Nie można połączyć się z określonym komputerem. Upewnij się, że wymagane porty są dozwolone przez zaporę sieciową.</string>
|
||||
<string name="category_basic_settings">Ustawienia podstawowe</string>
|
||||
<string name="text_native_res_dialog">Natywna rozdzielczość i/lub liczba klatek na sekundę mogą nie być obsługiwane przez serwer streamingu. Prawdopodobnie konieczne będzie ręczne skonfigurowanie odpowiedniego niestandardowego trybu wyświetlania dla komputera hosta.
|
||||
\n
|
||||
\nJeśli zdecydujesz się utworzyć niestandardową rozdzielczość w panelu sterowania NVIDIA aby dopasować ustawienia ekranu, upewnij się, że przeczytałeś i zrozumiałeś ostrzeżenie firmy NVIDIA dotyczące możliwego uszkodzenia monitora, niestabilności komputera i innych potencjalnych problemów.
|
||||
\n
|
||||
\nNie ponosimy odpowiedzialności za jakiekolwiek problemy wynikające z utworzenia niestandardowej rozdzielczości na komputerze.
|
||||
\n
|
||||
\nMoże się zdarzyć, że monitor nie obsługuje wymaganej konfiguracji wyświetlania. W takim przypadku można spróbować skonfigurować monitor wirtualny. Jeśli urządzenie lub komputer hosta nie obsługuje przesyłania strumieniowego w określonej rozdzielczości lub częstotliwości odświeżania, niestety nie masz szczęścia.</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Używa wbudowanych czujników ruchu urządzenia, jeśli czujniki gamepada nie są obsługiwane przez podłączony gamepad lub wersję systemu Android.
|
||||
\nUwaga: Włączenie tej opcji może spowodować, że gamepad będzie wyświetlany na hoście jako kontroler PlayStation.</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Może to sprawić, że akceleracja myszy będzie zachowywać się bardziej naturalnie podczas korzystania ze zdalnego pulpitu, ale jest niekompatybilna z wieloma grami.</string>
|
||||
<string name="title_troubleshooting">Przewodnik rozwiązywania problemów</string>
|
||||
<string name="resolution_1440p">1440p</string>
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="videoformat_auto">Automatycznie (zalecane)</string>
|
||||
<string name="videoformat_av1always">Preferowany AV1 (eksperymentalny)</string>
|
||||
<string name="summary_setup_guide">Wyświetl instrukcje, jak skonfigurować komputer do gier do streamowania</string>
|
||||
</resources>
|
@ -249,4 +249,9 @@
|
||||
\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>
|
||||
<string name="analogscroll_none">Nenhum (ambos os sticks movem o rato)</string>
|
||||
<string name="analogscroll_right">Stick analógico direito</string>
|
||||
<string name="analogscroll_left">Stick analógico esquerdo</string>
|
||||
<string name="title_analog_scrolling">Usar um stick analógico para fazer scroll</string>
|
||||
<string name="summary_analog_scrolling">Selecciona um stick analógico para fazer scroll quando a emulação de rato está ativada</string>
|
||||
</resources>
|
@ -249,4 +249,9 @@
|
||||
<string name="resolution_480p">480p</string>
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="summary_frame_pacing">Especifique o equilíbrio entre latência e suavidade do vídeo</string>
|
||||
<string name="analogscroll_none">Nenhum (ambos os sticks movem o rato)</string>
|
||||
<string name="analogscroll_right">Stick analógico direito</string>
|
||||
<string name="analogscroll_left">Stick analógico esquerdo</string>
|
||||
<string name="title_analog_scrolling">Usar um stick analógico para fazer scroll</string>
|
||||
<string name="summary_analog_scrolling">Selecciona um stick analógico para fazer scroll quando a emulação de rato está ativada</string>
|
||||
</resources>
|
@ -6,11 +6,9 @@
|
||||
<string name="scut_pc_not_found">PC negăsit</string>
|
||||
<string name="scut_invalid_uuid">PC-ul este invalid</string>
|
||||
<string name="scut_invalid_app_id">Aplicația este invalidă</string>
|
||||
|
||||
<!-- Help strings -->
|
||||
<string name="help_loading_title">Ajutor</string>
|
||||
<string name="help_loading_msg">Se încarcă pagina de ajutor…</string>
|
||||
|
||||
<!-- PC view menu entries -->
|
||||
<string name="pcview_menu_app_list">Vezi lista de jocuri</string>
|
||||
<string name="pcview_menu_pair_pc">Împerechează PC-ul</string>
|
||||
@ -18,7 +16,6 @@
|
||||
<string name="pcview_menu_send_wol">Trimite o cerere Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Șterge PC</string>
|
||||
<string name="pcview_menu_details">Vezi detalii</string>
|
||||
|
||||
<!-- Pair messages -->
|
||||
<string name="pairing">Se împerechează…</string>
|
||||
<string name="pair_pc_offline">PC-ul nu este accesibil</string>
|
||||
@ -28,20 +25,17 @@
|
||||
<string name="pair_incorrect_pin">PIN-ul este greșit</string>
|
||||
<string name="pair_fail">Împerecherea a eșuat</string>
|
||||
<string name="pair_already_in_progress">Împerecherea este deja în curs</string>
|
||||
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">PC-ul este accesibil</string>
|
||||
<string name="wol_no_mac">Nu s-a putut porni PC-ul deoarece GFE nu a comunicat o adresa MAC</string>
|
||||
<string name="wol_waking_pc">Se pornește PC-ul…</string>
|
||||
<string name="wol_waking_msg">Poate dura puțin până PC-ul pornește. Dacă nu pornește, verifică dacă este configurat corect pentru Wake-On-LAN.</string>
|
||||
<string name="wol_fail">Nu s-au putut trimite pachetele Wake-On-LAN</string>
|
||||
|
||||
<!-- Unpair messages -->
|
||||
<string name="unpairing">Desperecherechere…</string>
|
||||
<string name="unpair_success">Desperecherechere efectuată cu succes</string>
|
||||
<string name="unpair_fail">Desperecherea a eșuat</string>
|
||||
<string name="unpair_error">Dispozitivul nu este împerecheat</string>
|
||||
|
||||
<!-- Errors -->
|
||||
<string name="error_pc_offline">PC-ul este inaccesibil</string>
|
||||
<string name="error_manager_not_running">Serviciul ComputerManager nu este pornit. Te rugăm să aștepți câteva secunde sau să repornești aplicația.</string>
|
||||
@ -56,7 +50,6 @@
|
||||
<string name="error_usb_prohibited">Accesul USB este interzis de către administratorul dispozitivului. Verifică setarile Knox sau MDM.</string>
|
||||
<string name="unable_to_pin_shortcut">Launcher-ul tău curent nu permite crearea de scurtături fixate.</string>
|
||||
<string name="video_decoder_init_failed">Inițializarea decodorului video a eșuat. Este posibil ca acest dispozitiv să nu suporte rezoluția sau rata cadrelor selectată.</string>
|
||||
|
||||
<!-- Start application messages -->
|
||||
<string name="conn_establishing_title">Se stabilește conexiunea</string>
|
||||
<string name="conn_establishing_msg">Se pornește conexiunea</string>
|
||||
@ -69,7 +62,6 @@
|
||||
<string name="conn_error_msg">Pornirea a eșuat</string>
|
||||
<string name="conn_terminated_title">Conexiunea închisă</string>
|
||||
<string name="conn_terminated_msg">Conexiunea a fost terminată</string>
|
||||
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Adresa IP a PC-ului cu GFE</string>
|
||||
<string name="searching_pc">Se caută PC-uri cu GameStream activat…\n\n
|
||||
@ -87,7 +79,6 @@
|
||||
<string name="perf_overlay_renderingfps">Rata de afisare a cadrelor: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_netdrops">Cadre pierdute de rețea: %1$.2f%%</string>
|
||||
<string name="perf_overlay_dectime">Timpul mediu de decodare: %1$.2f ms</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="applist_connect_msg">Se conectează la PC…</string>
|
||||
<string name="applist_menu_resume">Continuă Sesiunea</string>
|
||||
@ -106,7 +97,6 @@
|
||||
<string name="applist_quit_fail">Nu s-a putut închide lista</string>
|
||||
<string name="applist_quit_confirmation">Sigur dorești să închizi aplicația curentă? Toate datele nesalvate vor fi pierdute.</string>
|
||||
<string name="applist_details_id">ID-ul aplicației:</string>
|
||||
|
||||
<!-- Add computer manually activity -->
|
||||
<string name="title_add_pc">Adaugă PC manual</string>
|
||||
<string name="msg_add_pc">Conectare în curs…</string>
|
||||
@ -115,7 +105,6 @@
|
||||
<string name="addpc_unknown_host">Nu am putut identifica adresa PC-ului. Asigură-te că ai introdus-o corect.</string>
|
||||
<string name="addpc_enter_ip">Trebuie să introduci o adresa IP</string>
|
||||
<string name="addpc_wrong_sitelocal">Adresa introdusă nu pare corectă. Pentru conectare prin Internet, este nevoie de adresa publică a routerului.</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">Setări de bază</string>
|
||||
<string name="title_resolution_list">Rezolutia video</string>
|
||||
@ -131,11 +120,9 @@
|
||||
<string name="summary_checkbox_disable_warnings">Dezactivează mesajele de avertizare privind rețeaua în timpul conexiunii</string>
|
||||
<string name="title_checkbox_enable_pip">Activează modul Picture-In-Picture</string>
|
||||
<string name="summary_checkbox_enable_pip">Permite vizualizarea (dar nu și controlul) când efectuezi multitasking</string>
|
||||
|
||||
<string name="category_audio_settings">Setări Audio</string>
|
||||
<string name="title_audio_config_list">Configurarea sunetului surround</string>
|
||||
<string name="summary_audio_config_list">Activeaza sunetul 5.1 sau 7.1 pentru sisteme home-theater</string>
|
||||
|
||||
<string name="category_input_settings">Setări de control</string>
|
||||
<string name="title_checkbox_multi_controller">Detectează automat prezența controllerelor.</string>
|
||||
<string name="summary_checkbox_multi_controller">Dezactivarea acestei opțiuni implică prezența constantă a unui controller</string>
|
||||
@ -151,7 +138,6 @@
|
||||
<string name="summary_checkbox_mouse_emulation">Apăsarea lungă pe butonul Start schimba modul de operare a controllerului în modul mouse.</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Activează butoanele de înainte și înapoi ale mousului</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Această opțiune poate afecta click dreapta pentru unele dispozitive problematice.</string>
|
||||
|
||||
<string name="category_on_screen_controls_settings">Setări ale controalelor pe ecran</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Afișează controale pe ecran</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Afișează un controller virtual pe ecran</string>
|
||||
@ -168,19 +154,16 @@
|
||||
<string name="summary_osc_opacity">Ajustează gradul de transparență al controalelor de pe ecran</string>
|
||||
<string name="dialog_title_osc_opacity">Modifică opacitatea</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
|
||||
<string name="category_ui_settings">Setari UI</string>
|
||||
<string name="title_language_list">Limba (Language)</string>
|
||||
<string name="summary_language_list">Limba folosită de către Moonlight</string>
|
||||
<string name="title_checkbox_small_icon_mode">Folosește iconițe mici</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Iconițele folosite în grile vor fi mici pentru a încăpea mai multe odata</string>
|
||||
|
||||
<string name="category_host_settings">Setările PC-ului gazdă</string>
|
||||
<string name="title_checkbox_enable_sops">Optimizarea setărilor de joc</string>
|
||||
<string name="summary_checkbox_enable_sops">Permite GFE să modifice setările jocurilor pentru experiența optimă</string>
|
||||
<string name="title_checkbox_host_audio">Redă audio si pe PC</string>
|
||||
<string name="summary_checkbox_host_audio">Sunetul se va auzi atat pe acest dispozitiv cât și pe PC</string>
|
||||
|
||||
<string name="category_advanced_settings">Setări avansate</string>
|
||||
<string name="title_disable_frame_drop">Nu pierde cadre intenționat</string>
|
||||
<string name="summary_disable_frame_drop">Poate să reducă micro-stuttering pe anumite device-uri, dar s-ar putea să crească latența</string>
|
||||
@ -190,11 +173,9 @@
|
||||
<string name="summary_enable_hdr">Folosește HDR daca aplicația si placa video suportă. Necesită o placa video seria GTX 1000 sau mai nouă.</string>
|
||||
<string name="title_enable_perf_overlay">Activează statisticile de performanță</string>
|
||||
<string name="summary_enable_perf_overlay">Afișează în timp real statisticile de performanță ale conexiunii.</string>
|
||||
|
||||
<!-- Array strings -->
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">Sunet Surround 5.1</string>
|
||||
<string name="audioconf_71surround">Sunet Surround 7.1</string>
|
||||
|
||||
<string name="videoformat_hevcalways">Folosește HEVC mereu (se poate bloca)</string>
|
||||
</resources>
|
||||
</resources>
|
@ -59,7 +59,7 @@
|
||||
<string name="conn_error_title">Fogningsfel</string>
|
||||
<string name="conn_error_msg">Misslyckades att börja</string>
|
||||
<string name="conn_terminated_title">Fogning förstörd</string>
|
||||
<string name="conn_terminated_msg">Fogningen har förstörts</string>
|
||||
<string name="conn_terminated_msg">Förbindelsen avbröts.</string>
|
||||
<string name="yes">Ja</string>
|
||||
<string name="no">Nej</string>
|
||||
<string name="lost_connection">Tappade fogning till dator</string>
|
||||
@ -259,4 +259,17 @@
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Styr alltid musen med pekplatta</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Tvingar indata från spelkontroll pekplattan att styra värdmusen, även när man emulerar en spelkontroll med en pekplatta.</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Aktiverar stöd för värden att begära rörelsesensor data när du emulerar en spelkontroll med rörelsesensorer. Inaktivering kan minska ström och nätverksanvändningen något om rörelsesensorer inte används i spelet.</string>
|
||||
<string name="toast_controller_type_changed">Spelkontroll-typ kan ändras på grund av rörelsesensoremulering</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Använder enhetens inbyggda rörelsesensorer om spelkontrollsensorer inte stöds av din anslutna spelkontroll eller din Android-version.
|
||||
\nObs: Om du aktiverar det här alternativet kan din spelkontroll visas som en PlayStation-kontroller på värden.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Emulera spelkontroll rörelsesensor stöd</string>
|
||||
<string name="error_code_prefix">Felkod:</string>
|
||||
<string name="summary_analog_scrolling">Välj en analog spak för att scrolla när du är i musemuleringsläge</string>
|
||||
<string name="analogscroll_none">Ingen (båda spakarna flyttar musen)</string>
|
||||
<string name="analogscroll_left">Vänster analogspak</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Justera intensiteten på emulerat skakande</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Förstärk eller reducera vibrationsintensiteten på din enhet</string>
|
||||
<string name="analogscroll_right">Höger analogspak</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
<string name="title_analog_scrolling">Använd en analog spak för att bläddra</string>
|
||||
</resources>
|
@ -16,7 +16,7 @@
|
||||
<string name="pair_fail">Створення пари не вдалося</string>
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">Пристрій у мережі</string>
|
||||
<string name="wol_no_mac">Неможливо розбудити пристрій бо GFE не відправило MAC адреса</string>
|
||||
<string name="wol_no_mac">Не вдається розбудити ПК, оскільки немає збереженої MAC-адреси</string>
|
||||
<string name="wol_waking_pc">Пробудження пристрою…</string>
|
||||
<string name="wol_waking_msg">Пробудження пристрою може зайняти кілька секунд. Якщо цього не відбувається, упевніться що Wake-On-LAN налаштований правильно.</string>
|
||||
<string name="wol_fail">Помилка при відправці Wake-On-LAN пакетів</string>
|
||||
@ -41,12 +41,12 @@
|
||||
<string name="conn_error_title">Помилка з\'єднання</string>
|
||||
<string name="conn_error_msg">Запуск не вдався</string>
|
||||
<string name="conn_terminated_title">З\'єднання припинено</string>
|
||||
<string name="conn_terminated_msg">З\'єднання перервано</string>
|
||||
<string name="conn_terminated_msg">З’єднання було розірване.</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">IP-адреса пристрою з GeForce</string>
|
||||
<string name="searching_pc">Пошук пристроїв із запущеним GameStream…
|
||||
<string name="ip_hint">IP-адреса головного ПК</string>
|
||||
<string name="searching_pc">Пошук головного ПК у локальній мережі…
|
||||
\n
|
||||
\n Переконайтеся що GameStream увімкнений в налаштуваннях GeForce Experience в розділі SHIELD.</string>
|
||||
\nПереконайтеся, що Sunshine запущено на вашому головному ПК або GameStream увімкнено в налаштуваннях GeForce Experience SHIELD.</string>
|
||||
<string name="yes">Так</string>
|
||||
<string name="no">Ні</string>
|
||||
<string name="lost_connection">З\'єднання з пристроєм втрачено</string>
|
||||
@ -100,8 +100,8 @@
|
||||
<string name="title_checkbox_host_audio">Програвати звук на пристрої хоста</string>
|
||||
<string name="summary_checkbox_host_audio">Програвати звук на пристроях хоста та клієнта</string>
|
||||
<string name="category_advanced_settings">Розширені налаштування</string>
|
||||
<string name="title_video_format">Змінити налаштування HEVC</string>
|
||||
<string name="summary_video_format">HEVC знижує вимоги мережі, даючи можливість транслювати на повільних мережах але, вимагає нового пристрою з підтримкою цієї системи</string>
|
||||
<string name="title_video_format">Змінити налаштування кодека</string>
|
||||
<string name="summary_video_format">Нові кодеки можуть знизити вимоги до пропускної здатності відео, якщо ваш пристрій їх підтримує. Вибрані кодеки можуть ігноруватися, якщо вони не підтримуються програмним забезпеченням хоста або графічним процесором.</string>
|
||||
<string name="category_on_screen_controls_settings">Налаштування екранних ґудзиків</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Показувати екранні ґудзики</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Відображати віртуальні ґудзики контролера на екрані</string>
|
||||
@ -115,7 +115,7 @@
|
||||
<string name="help">Допомога</string>
|
||||
<string name="applist_connect_msg">Підключення до пристрою…</string>
|
||||
<string name="title_decoding_error">Збій відео розцифрувача</string>
|
||||
<string name="message_decoding_error">Стався збій Moonlight через несумітність з відео розцифрувачем даного пристрою. Спробуйте змінити налаштування трансляції якщо збої продовжуватимуться.</string>
|
||||
<string name="message_decoding_error">Moonlight аварійно завершив роботу через несумісність із відеодекодером цього пристрою. Спробуйте налаштувати параметри потокового передавання, якщо збої триватимуть.</string>
|
||||
<string name="title_decoding_reset">Налаштування відео скинуті</string>
|
||||
<string name="message_decoding_reset">Відео розцифрувач вашого пристрою продовжує давати збої з поточними налаштуваннями трансляції. Налаштування трансляції були скинуті до значень за замовчуванням.</string>
|
||||
<string name="error_usb_prohibited">USB доступ заборонений адміністратором пристрою. Перевірте налаштування Knox або MDM.</string>
|
||||
@ -134,16 +134,16 @@
|
||||
<string name="title_disable_frame_drop">Ніколи не пропускати кадри</string>
|
||||
<string name="summary_disable_frame_drop">Може зменшити мікрозависання на деяких пристроях але, також збільшити затримку</string>
|
||||
<string name="title_enable_hdr">Увімкнути HDR (Експериментально)</string>
|
||||
<string name="summary_enable_hdr">Транслювати в HDR якщо гра та відео карта на пристрої хоста підтримують це. HDR вимагає відеокарти серії GTX 1000 або новіше.</string>
|
||||
<string name="summary_enable_hdr">Транслювати в HDR, якщо це підтримується грою та графічним процесором ПК. Для HDR потрібен графічний процесор із підтримкою кодування HEVC Main 10.</string>
|
||||
<string name="title_checkbox_vibrate_osc">Увімкнути вібрацію</string>
|
||||
<string name="title_fps_list">Частота кадрів</string>
|
||||
<string name="applist_menu_details">Деталі</string>
|
||||
<string name="applist_menu_details">Переглянути деталі</string>
|
||||
<string name="applist_menu_scut">Створити ярлик</string>
|
||||
<string name="category_input_settings">Налаштування введення</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Використовувати сенсорний екран як пальцевід</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">Якщо увімкнено, сенсорний екран працює як ноутбуковий пальцевід. Якщо вимкнено, безпосередньо керує вказівником миші.</string>
|
||||
<string name="delete_pc_msg">Ви впевнені що хочете видалити цей пристрій\?</string>
|
||||
<string name="pcview_menu_details">Деталі</string>
|
||||
<string name="pcview_menu_details">Переглянути деталі</string>
|
||||
<string name="poor_connection_msg">Слабке з\'єднання з пристроєм</string>
|
||||
<string name="title_details">Деталі</string>
|
||||
<string name="title_enable_perf_overlay">Увімкнути відображення статистики</string>
|
||||
@ -176,24 +176,22 @@
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="title_enable_post_stream_toast">Статистика затримки після трансляції</string>
|
||||
<string name="summary_enable_post_stream_toast">Показувати статистику затримки після закінчення трансляції</string>
|
||||
<string name="early_termination_error">Щось пішло не так на пристрої хоста при початку трансляції.
|
||||
<string name="early_termination_error">Щось пішло не так на вашому головному ПК під час запуску потоку.
|
||||
\n
|
||||
\nПереконайтеся, що на головному ПК немає відкритого вмісту, захищеного DRM. Ви також можете спробувати перезавантажити головний ПК.
|
||||
\n
|
||||
\nЯкщо проблема не зникає, спробуйте перевстановити драйвери GPU та GeForce Experience.</string>
|
||||
\nПереконайтеся, що на головному ПК немає відкритого вмісту, захищеного DRM. Ви також можете спробувати перезавантажити головний ПК.</string>
|
||||
<string name="nettest_text_success">Схоже що ваша мережа не блокує Moonlight. Якщо у вас й надалі проблеми з підключенням, перевірте налаштування брандмауера.
|
||||
\n
|
||||
\nЯкщо ви намагаєтеся транслювати через Інтернет, встановіть на своєму пристрої Moonlight Internet Hosting Tool, та запустіть випробування мережі щоб перевірити ваше з\'єднання до Інтернету.</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Рідний повноекранний</string>
|
||||
<string name="resolution_prefix_native">Рідна</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Мб/с</string>
|
||||
<string name="text_native_res_dialog">Режими рідної роздільної здатності не підтримуються офіційно через GeForce Experience, і тому не змінять роздільну здатність хоста на ту що в клієнта автоматично. Вам потрібно буде виставити її самостійно у грі.
|
||||
<string name="text_native_res_dialog">Власна роздільна здатність і/або FPS можуть не підтримуватися потоковим сервером. Ймовірно, вам доведеться вручну налаштувати відповідний спеціальний режим відображення для головного ПК.
|
||||
\n
|
||||
\nЯкщо ви вирішили створити власну роздільну здатність у панелі керування NVIDIA переконайтеся, що ви прочитали та зрозуміли попередження NVIDIA щодо можливих пошкоджень монітора, нестабільності пристрою та інших потенційних проблем.
|
||||
\nЯкщо ви вирішили вказати спеціальну роздільну здатність на панелі керування NVIDIA відповідно до налаштувань екрана, переконайтеся, що ви прочитали та зрозуміли попередження NVIDIA щодо можливого пошкодження монітора, нестабільної роботи ПК та інших потенційних проблем.
|
||||
\n
|
||||
\nМи не несемо відповідальності за будь-які проблеми, спричинені створенням власних роздільних здатностей на ваших пристроях.
|
||||
\nМи не несемо відповідальності за будь-які проблеми, що виникли в результаті встановлення власної роздільної здатності на вашому ПК.
|
||||
\n
|
||||
\nЗрештою, пристрої клієнта чи хоста можуть не підтримувати трансляції рідною роздільною здатністю. Якщо це не працює на вашому пристрої, вам на жаль просто не пощастило.</string>
|
||||
\nМожливо, ваш монітор не підтримує необхідну конфігурацію дисплея. Якщо так, ви можете спробувати налаштувати віртуальний монітор. Врешті-решт, якщо ваш пристрій або хост-комп’ютер не підтримує потокове передавання з певною роздільною здатністю чи частотою оновлення, вам, на жаль, не пощастило.</string>
|
||||
<string name="title_native_res_dialog">Застереження про рідну роздільну здатність</string>
|
||||
<string name="applist_menu_hide_app">Сховати застосунок</string>
|
||||
<string name="perf_overlay_netlatency">Середня затримка мережі: %1$d мс (розбіжність %2$d мс)</string>
|
||||
@ -209,9 +207,9 @@
|
||||
\n</string>
|
||||
<string name="nettest_text_inconclusive">Не вдалося перевірити мережу, тому що усі мережо-перевірочні сервери Moonlight недосяжні. Перевірте ваше з\'єднання з інтернетом та спробуйте знову.</string>
|
||||
<string name="nettest_title_done">Перевірка мережі завершена</string>
|
||||
<string name="nettest_text_waiting">Moonlight перевіряє мережеве з\'єднання щоб визначити чи заблокований NVIDIA GameStream.
|
||||
<string name="nettest_text_waiting">Moonlight перевіряє ваше мережеве з’єднання, щоб визначити, чи заблоковані необхідні порти.
|
||||
\n
|
||||
\nЦе займе кілька секунд…</string>
|
||||
\nЦе може зайняти кілька секунд…</string>
|
||||
<string name="nettest_title_waiting">Перевіряємо з\'єднання</string>
|
||||
<string name="pcview_menu_test_network">Перевірити мережеве з\'єднання</string>
|
||||
<string name="pcview_menu_header_unknown">Оновлення</string>
|
||||
@ -260,4 +258,29 @@
|
||||
\nСпробуйте вимкнути режим HDR, змінити роздільну здатність потокового відео або змінити роздільну здатність дисплея головного комп\'ютера.</string>
|
||||
<string name="title_full_range">Сила повного спектру відео (експериментальна)</string>
|
||||
<string name="summary_full_range">Це може призвести до втрати деталей у світлих і темних областях, якщо пристрій не відображає належним чином весь діапазон відеоконтенту.</string>
|
||||
<string name="pair_pairing_help">Якщо на вашому комп’ютері встановлений Sunshine, перейдіть до веб-інтерфейсу користувача Sunshine, щоб ввести PIN-код.</string>
|
||||
<string name="error_code_prefix">Код помилки:</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Налаштування інтенсивності вібро</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Посилюйте або зменшуйте інтенсивність вібрації пристрою</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Емуляція підтримки датчика руху геймпада</string>
|
||||
<string name="videoformat_av1always">Використовувати AV1 (експериментальний)</string>
|
||||
<string name="videoformat_h264always">Використовувати H.264</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="title_native_fps_dialog">Попередження рідного FPS</string>
|
||||
<string name="category_gamepad_settings">Налаштування геймпада</string>
|
||||
<string name="title_analog_scrolling">Використовувати аналоговий стік для прокручування</string>
|
||||
<string name="summary_analog_scrolling">Виберіть аналоговий стік для прокручування під час режиму емуляції миші</string>
|
||||
<string name="analogscroll_none">Немає (обидва стіка пересувають мишу)</string>
|
||||
<string name="analogscroll_right">Аналоговий стік праворуч</string>
|
||||
<string name="analogscroll_left">Аналоговий стік ліворуч</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Завжди керувати мишею за допомогою сенсорної панелі</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Примусове використання сенсорної панелі геймпада для керування основною мишею, навіть якщо емулюється геймпад із сенсорною панеллю.</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Дозволити використовувати датчики руху геймпада</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Дозволяє підтримуваним хостам запитувати дані датчиків руху під час емуляції геймпада з датчиками руху. Якщо в грі не використовуються датчики руху, вимкнення може дещо зменшити енергоспоживання та використання мережі.</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Використовує вбудовані датчики руху вашого пристрою, якщо датчики геймпада не підтримуються підключеним геймпадом або вашою версією Android.
|
||||
\nПримітка. Якщо ввімкнути цей параметр, ваш геймпад може відображатися як контролер PlayStation на хості.</string>
|
||||
<string name="toast_controller_type_changed">Тип геймпада може бути змінений через емуляцію датчика руху</string>
|
||||
<string name="pcview_menu_eol">Закриття сервісів NVIDIA GameStream</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Затримка обробки хостом мін./макс./середня: %1$.1f/%2$.1f/%3$.1f мс</string>
|
||||
</resources>
|
@ -58,7 +58,7 @@
|
||||
<string name="conn_error_title"> 连接错误 </string>
|
||||
<string name="conn_error_msg"> 启动失败 </string>
|
||||
<string name="conn_terminated_title"> 连接终结 </string>
|
||||
<string name="conn_terminated_msg"> 连接已被终结 </string>
|
||||
<string name="conn_terminated_msg">连接已被终结.</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">串流电脑的IP地址</string>
|
||||
<string name="searching_pc">在你的本地网络中搜索串流主机PC...
|
||||
@ -275,4 +275,13 @@
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">如果你连接的游戏手柄或 Android 版本不支持游戏手柄传感器,请使用设备的内置运动传感器。
|
||||
\n注意:启用此选项可能会导致您的游戏手柄在主机上被识别为 PlayStation 4控制器。</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">模拟游戏手柄运动传感器支持</string>
|
||||
<string name="error_code_prefix">错误代码:</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">调整模拟震动强度</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
<string name="title_analog_scrolling">使用摇杆控制鼠标移动</string>
|
||||
<string name="analogscroll_left">左摇杆</string>
|
||||
<string name="analogscroll_right">右摇杆</string>
|
||||
<string name="summary_analog_scrolling">在鼠标模式下选择用哪个摇杆控制鼠标移动</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">增强或减弱设备的震动强度</string>
|
||||
<string name="analogscroll_none">默认 (两个摇杆都控制鼠标)</string>
|
||||
</resources>
|
@ -120,4 +120,15 @@
|
||||
<item>cap-fps</item>
|
||||
<item>smoothness</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="analog_scrolling_names">
|
||||
<item>@string/analogscroll_none</item>
|
||||
<item>@string/analogscroll_right</item>
|
||||
<item>@string/analogscroll_left</item>
|
||||
</string-array>
|
||||
<string-array name="analog_scrolling_values" translatable="false">
|
||||
<item>none</item>
|
||||
<item>right</item>
|
||||
<item>left</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
@ -90,7 +90,8 @@
|
||||
<string name="conn_error_title">Connection Error</string>
|
||||
<string name="conn_error_msg">Failed to start</string>
|
||||
<string name="conn_terminated_title">Connection Terminated</string>
|
||||
<string name="conn_terminated_msg">The connection was terminated</string>
|
||||
<string name="conn_terminated_msg">The connection was terminated.</string>
|
||||
<string name="error_code_prefix">Error code:</string>
|
||||
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">IP address of host PC</string>
|
||||
@ -172,6 +173,9 @@
|
||||
<string name="summary_checkbox_multi_controller">Unchecking this option forces a gamepad to always be present</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emulate rumble support with vibration</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Vibrates your device to emulate rumble if your gamepad does not support it</string>
|
||||
<string name="title_seekbar_vibrate_fallback_strength">Adjust emulated rumble intensity</string>
|
||||
<string name="summary_seekbar_vibrate_fallback_strength">Amplify or reduce the vibration intensity on your device</string>
|
||||
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
|
||||
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
|
||||
<string name="summary_seekbar_deadzone">Note: Some games can enforce a larger deadzone than what Moonlight is configured to use.</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
@ -205,6 +209,8 @@
|
||||
<string name="summary_checkbox_vibrate_osc">Vibrates your device to emulate rumble for the on-screen controls</string>
|
||||
<string name="title_only_l3r3">Only show L3 and R3</string>
|
||||
<string name="summary_only_l3r3">Hide all virtual buttons except L3 and R3</string>
|
||||
<string name="title_show_guide_button">Show Guide Button</string>
|
||||
<string name="summary_show_guide_button">Show the guide button on screen</string>
|
||||
<string name="title_reset_osc">Clear saved on-screen controls layout</string>
|
||||
<string name="summary_reset_osc">Resets all on-screen controls to their default size and position</string>
|
||||
<string name="dialog_title_reset_osc">Reset Layout</string>
|
||||
@ -288,4 +294,10 @@
|
||||
<string name="pacing_balanced">Balanced</string>
|
||||
<string name="pacing_balanced_alt">Balanced with FPS limit</string>
|
||||
<string name="pacing_smoothness">Prefer smoothest video (may significantly increase latency)</string>
|
||||
|
||||
<string name="title_analog_scrolling">Use an analog stick to scroll</string>
|
||||
<string name="summary_analog_scrolling">Select an analog stick to scroll when in mouse emulation mode</string>
|
||||
<string name="analogscroll_none">None (both sticks move the mouse)</string>
|
||||
<string name="analogscroll_right">Right analog stick</string>
|
||||
<string name="analogscroll_left">Left analog stick</string>
|
||||
</resources>
|
||||
|
8
app/src/main/res/xml/game_mode_config.xml
Normal file
8
app/src/main/res/xml/game_mode_config.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<game-mode-config
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:supportsBatteryGameMode="false"
|
||||
android:supportsPerformanceGameMode="false"
|
||||
android:allowGameDownscaling="false"
|
||||
android:allowGameFpsOverride="false"
|
||||
/>
|
@ -85,11 +85,27 @@
|
||||
android:title="@string/title_checkbox_mouse_emulation"
|
||||
android:summary="@string/summary_checkbox_mouse_emulation"
|
||||
android:defaultValue="true" />
|
||||
<ListPreference
|
||||
android:key="analog_scrolling"
|
||||
android:dependency="checkbox_mouse_emulation"
|
||||
android:title="@string/title_analog_scrolling"
|
||||
android:summary="@string/summary_analog_scrolling"
|
||||
android:entries="@array/analog_scrolling_names"
|
||||
android:entryValues="@array/analog_scrolling_values"
|
||||
android:defaultValue="right" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_vibrate_fallback"
|
||||
android:title="@string/title_checkbox_vibrate_fallback"
|
||||
android:summary="@string/summary_checkbox_vibrate_fallback"
|
||||
android:defaultValue="false" />
|
||||
<com.limelight.preferences.SeekBarPreference
|
||||
android:key="seekbar_vibrate_fallback_strength"
|
||||
android:dependency="checkbox_vibrate_fallback"
|
||||
android:defaultValue="100"
|
||||
android:max="200"
|
||||
android:summary="@string/summary_seekbar_vibrate_fallback_strength"
|
||||
android:text="@string/suffix_seekbar_vibrate_fallback_strength"
|
||||
android:title="@string/title_seekbar_vibrate_fallback_strength"/>
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_flip_face_buttons"
|
||||
android:title="@string/title_checkbox_flip_face_buttons"
|
||||
@ -148,6 +164,14 @@
|
||||
android:key="checkbox_only_show_L3R3"
|
||||
android:summary="@string/summary_only_l3r3"
|
||||
android:title="@string/title_only_l3r3" />
|
||||
<CheckBoxPreference
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:defaultValue="true"
|
||||
android:dependency="checkbox_show_onscreen_controls"
|
||||
android:key="checkbox_show_guide_button"
|
||||
android:summary="@string/summary_show_guide_button"
|
||||
android:title="@string/title_show_guide_button" />
|
||||
<com.limelight.preferences.SeekBarPreference
|
||||
android:key="seekbar_osc_opacity"
|
||||
android:dependency="checkbox_show_onscreen_controls"
|
||||
|
@ -5,7 +5,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.1.2'
|
||||
classpath 'com.android.tools.build:gradle:8.5.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
3
fastlane/metadata/android/en-US/changelogs/313.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/313.txt
Normal file
@ -0,0 +1,3 @@
|
||||
- Fixed connection issue with some hosts running GeForce Experience and older Sunshine versions
|
||||
- Fixed native frame rate streaming support on older versions of Android
|
||||
- Stability improvements
|
9
fastlane/metadata/android/en-US/changelogs/314.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/314.txt
Normal file
@ -0,0 +1,9 @@
|
||||
- Adjusted bitrate calculation logic to provide consistency across codecs, HDR settings, and local/remote streaming
|
||||
- Added support for full end-to-end stream encryption with Sunshine*
|
||||
- Fixed immediate connection termination error when streaming over some Internet connections*
|
||||
- Added option to adjust emulated rumble intensity
|
||||
- Added option to scroll in controller mouse emulation mode
|
||||
- Improved connection reliability during temporary network interruptions
|
||||
- Fixed pass-through of special Sunshine key combos to the host
|
||||
|
||||
* Requires upcoming Sunshine v0.22.0 release or the latest Sunshine nightly build
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
Loading…
x
Reference in New Issue
Block a user