Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| abc4123c52 | |||
| 26f8c0842e | |||
| d430d83ba8 | |||
| a52f189fb1 | |||
| dc1045b69e | |||
| 3a89dbf4ab | |||
| d69b4eca1e | |||
| 568bba82f0 | |||
| b52e6c88ec | |||
| 720595091e | |||
| fe929c8e58 | |||
| 9ecec1eb3c | |||
| 79532f6f14 | |||
| b400ba385e | |||
| 9915007f30 | |||
| 0168a55596 | |||
| 229eff49fb | |||
| 0e3b472f78 | |||
| 5f29b30d34 | |||
| 9480363362 | |||
| 5dd80edde4 | |||
| 2243cf2017 | |||
| d7791c8543 | |||
| 30822c1ba5 | |||
| d250f4dc60 | |||
| bc27492206 | |||
| 2b63203a5b | |||
| dc9a26f57b | |||
| 6f2d7464ba | |||
| 6996c101b4 | |||
| 99dc773c7a | |||
| 6ec3f9455a | |||
| 6589a568e2 | |||
| 55da48e28c | |||
| 081cca48fb | |||
| 6b6a93725c | |||
| c280a52d33 | |||
| b659439f0b | |||
| 6453b3c45c | |||
| 978a879c43 | |||
| 833ef3630b | |||
| 024b8c93bc | |||
| d32c4f86a7 | |||
| cafc4450b2 | |||
| 7d69b53958 | |||
| 4d3e883e49 | |||
| 8f9a687872 | |||
| 08d509d831 | |||
| b06dec8449 | |||
| 28c93b934b | |||
| 394a57a26d | |||
| 3856b57a6f | |||
| 9a3a076890 | |||
| 314dfcddcf | |||
| 1a85bda997 | |||
| e8b30d5a88 | |||
| 96bd1a7799 | |||
| cb0a1f13bc | |||
| e92fdeef47 | |||
| 62bae62386 | |||
| 2636d79b86 | |||
| c9c1ef91fd | |||
| ce7bba3e09 | |||
| bfd53f39bd | |||
| 554fee037c | |||
| 67b2853ef0 | |||
| 0e29e13d03 | |||
| 35f2a238e9 | |||
| fcb34ab6ee | |||
| 3fbf682785 | |||
| 16086a6d3f | |||
| 18b6aae381 | |||
| 642c353164 | |||
| 42f64e5e88 | |||
| 6af748b2cc | |||
| 4fe97b69c7 | |||
| 04d46272dd | |||
| 1c0290dc7a | |||
| 38588402e3 | |||
| dfe3b8888d | |||
| e8f4022f1e | |||
| e37bb32c82 | |||
| 1f72c82acb | |||
| e6876926a4 | |||
| 2b8a43ab13 | |||
| 8737466368 | |||
| 83916fa43e | |||
| 1fe5a12a45 | |||
| fa7f3115ed | |||
| 4dc6143440 | |||
| f1503aa56c | |||
| 67f344b755 | |||
| f1bcc217a9 | |||
| 458460515d | |||
| 3a78095574 | |||
| d6bbfa1af1 | |||
| 4e1b778f31 | |||
| 5f4496036c | |||
| d4079940b4 | |||
| 803ad116fb | |||
| 27701eda49 | |||
| 71c831b02d | |||
| 0d72a0e009 | |||
| 69a4502f90 | |||
| daaa7f4e63 | |||
| d1579e9b0d | |||
| 5890fff240 | |||
| d6f6307050 | |||
| 6bf9c31860 | |||
| a2e628f3f8 | |||
| 8f5416ff31 | |||
| db86f18133 | |||
| 419e4e656e | |||
| eed4327d26 | |||
| 5c6eaf2602 | |||
| 71169ed740 | |||
| dca8d93aa8 | |||
| 6cb152f602 | |||
| ddefda3afa | |||
| 7f15f45beb | |||
| 46f887efec | |||
| 90afecd766 | |||
| 388343c3ee | |||
| c8df37e89e | |||
| cc85d5c343 | |||
| f8437cdb8f | |||
| c99a210905 | |||
| e33673c9e9 | |||
| 79283e93cb | |||
| a60e85a3a4 | |||
| 80910ed38d | |||
| 825a338474 | |||
| 19b6e94824 | |||
| 6b7669bb75 |
@@ -3,7 +3,7 @@
|
||||
[](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
|
||||
[](https://hosted.weblate.org/projects/moonlight/moonlight-android/)
|
||||
|
||||
[Moonlight for Android](https://moonlight-stream.org) is an open source client for NVIDIA GameStream, as used by the NVIDIA Shield.
|
||||
[Moonlight for Android](https://moonlight-stream.org) is an open source client for NVIDIA GameStream and [Sunshine](https://github.com/LizardByte/Sunshine).
|
||||
|
||||
Moonlight for Android will allow you to stream your full collection of games from your Windows PC to your Android device,
|
||||
whether in your own home or over the internet.
|
||||
|
||||
+9
-5
@@ -3,16 +3,16 @@ apply plugin: 'com.android.application'
|
||||
android {
|
||||
ndkVersion "23.2.8568313"
|
||||
|
||||
compileSdk 33
|
||||
compileSdk 34
|
||||
|
||||
namespace 'com.limelight'
|
||||
|
||||
defaultConfig {
|
||||
minSdk 16
|
||||
targetSdk 33
|
||||
targetSdk 34
|
||||
|
||||
versionName "11.0"
|
||||
versionCode = 306
|
||||
versionName "12.0.1"
|
||||
versionCode = 312
|
||||
|
||||
// Generate native debug symbols to allow Google Play to symbolicate our native crashes
|
||||
ndk.debugSymbolLevel = 'FULL'
|
||||
@@ -20,6 +20,10 @@ android {
|
||||
|
||||
flavorDimensions.add("root")
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
root {
|
||||
// Android O has native mouse capture, so don't show the rooted
|
||||
@@ -139,5 +143,5 @@ dependencies {
|
||||
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 'com.github.cgutman:ShieldControllerExtensions:1.0'
|
||||
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
|
||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
|
||||
|
||||
<!-- We don't need a MulticastLock on API level 34+ because we use NsdManager for mDNS -->
|
||||
<uses-permission
|
||||
android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
|
||||
android:maxSdkVersion="33" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
@@ -25,6 +29,12 @@
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.sensor.accelerometer"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.sensor.gyroscope"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Disable legacy input emulation on ChromeOS -->
|
||||
<uses-feature
|
||||
@@ -75,7 +85,12 @@
|
||||
android:name=".PcView"
|
||||
android:exported="true"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -91,37 +106,37 @@
|
||||
android:noHistory="true"
|
||||
android:exported="true"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AppView"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".preferences.StreamSettings"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:label="Streaming Settings">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".preferences.AddComputerManually"
|
||||
android:resizeableActivity="true"
|
||||
android:windowSoftInputMode="stateVisible"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
|
||||
android:label="Add Computer Manually">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".Game"
|
||||
@@ -129,13 +144,14 @@
|
||||
android:noHistory="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="false"
|
||||
android:launchMode="singleTask"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/StreamTheme"
|
||||
android:preferMinimalPostProcessing="true">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.AppView" />
|
||||
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
|
||||
<!-- Special metadata for NVIDIA Shield devices to prevent input buffering
|
||||
and most importantly, opt out of mouse acceleration while streaming -->
|
||||
@@ -160,10 +176,10 @@
|
||||
<activity
|
||||
android:name=".HelpActivity"
|
||||
android:resizeableActivity="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:configChanges="mcc|mnc|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="com.limelight.PcView" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowSize" android:value="system-default" />
|
||||
<meta-data android:name="WindowManagerPreference:FreeformWindowOrientation" android:value="landscape" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.limelight.nvstream.StreamConfiguration;
|
||||
import com.limelight.nvstream.http.ComputerDetails;
|
||||
import com.limelight.nvstream.http.NvApp;
|
||||
import com.limelight.nvstream.http.NvHTTP;
|
||||
import com.limelight.nvstream.input.ControllerPacket;
|
||||
import com.limelight.nvstream.input.KeyboardPacket;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
@@ -131,7 +132,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
private InputCaptureProvider inputCaptureProvider;
|
||||
private int modifierFlags = 0;
|
||||
private boolean grabbedInput = true;
|
||||
private boolean grabComboDown = false;
|
||||
private boolean cursorVisible = false;
|
||||
private boolean waitingForAllModifiersUp = false;
|
||||
private int specialKeyCode = KeyEvent.KEYCODE_UNKNOWN;
|
||||
private StreamView streamView;
|
||||
private long lastAbsTouchUpTime = 0;
|
||||
private long lastAbsTouchDownTime = 0;
|
||||
@@ -404,14 +407,34 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
this);
|
||||
|
||||
// Don't stream HDR if the decoder can't support it
|
||||
if (willStreamHdr && !decoderRenderer.isHevcMain10Hdr10Supported()) {
|
||||
if (willStreamHdr && !decoderRenderer.isHevcMain10Hdr10Supported() && !decoderRenderer.isAv1Main10Supported()) {
|
||||
willStreamHdr = false;
|
||||
Toast.makeText(this, "Decoder does not support HEVC Main10HDR10", Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, "Decoder does not support HDR10 profile", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// Display a message to the user if HEVC was forced on but we still didn't find a decoder
|
||||
if (prefConfig.videoFormat == PreferenceConfiguration.FORCE_H265_ON && !decoderRenderer.isHevcSupported()) {
|
||||
Toast.makeText(this, "No HEVC decoder found.\nFalling back to H.264.", Toast.LENGTH_LONG).show();
|
||||
if (prefConfig.videoFormat == PreferenceConfiguration.FormatOption.FORCE_HEVC && !decoderRenderer.isHevcSupported()) {
|
||||
Toast.makeText(this, "No HEVC decoder found", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// Display a message to the user if AV1 was forced on but we still didn't find a decoder
|
||||
if (prefConfig.videoFormat == PreferenceConfiguration.FormatOption.FORCE_AV1 && !decoderRenderer.isAv1Supported()) {
|
||||
Toast.makeText(this, "No AV1 decoder found", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// H.264 is always supported
|
||||
int supportedVideoFormats = MoonBridge.VIDEO_FORMAT_H264;
|
||||
if (decoderRenderer.isHevcSupported()) {
|
||||
supportedVideoFormats |= MoonBridge.VIDEO_FORMAT_H265;
|
||||
if (willStreamHdr && decoderRenderer.isHevcMain10Hdr10Supported()) {
|
||||
supportedVideoFormats |= MoonBridge.VIDEO_FORMAT_H265_MAIN10;
|
||||
}
|
||||
}
|
||||
if (decoderRenderer.isAv1Supported()) {
|
||||
supportedVideoFormats |= MoonBridge.VIDEO_FORMAT_AV1_MAIN8;
|
||||
if (willStreamHdr && decoderRenderer.isAv1Main10Supported()) {
|
||||
supportedVideoFormats |= MoonBridge.VIDEO_FORMAT_AV1_MAIN10;
|
||||
}
|
||||
}
|
||||
|
||||
int gamepadMask = ControllerHandler.getAttachedControllerMask(this);
|
||||
@@ -463,8 +486,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
.setMaxPacketSize(1392)
|
||||
.setRemoteConfiguration(StreamConfiguration.STREAM_CFG_AUTO) // NvConnection will perform LAN and VPN detection
|
||||
.setHevcBitratePercentageMultiplier(75)
|
||||
.setHevcSupported(decoderRenderer.isHevcSupported())
|
||||
.setEnableHdr(willStreamHdr)
|
||||
.setAv1BitratePercentageMultiplier(75)
|
||||
.setSupportedVideoFormats(supportedVideoFormats)
|
||||
.setAttachedGamepadMask(gamepadMask)
|
||||
.setClientRefreshRateX100((int)(displayRefreshRate * 100))
|
||||
.setAudioConfiguration(prefConfig.audioConfiguration)
|
||||
@@ -618,6 +641,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
performanceOverlayView.setVisibility(View.GONE);
|
||||
notificationOverlayView.setVisibility(View.GONE);
|
||||
|
||||
// Disable sensors while in PiP mode
|
||||
controllerHandler.disableSensors();
|
||||
|
||||
// Update GameManager state to indicate we're in PiP (still gaming, but interruptible)
|
||||
UiHelper.notifyStreamEnteringPiP(this);
|
||||
}
|
||||
@@ -636,6 +662,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
notificationOverlayView.setVisibility(requestedNotificationOverlayVisibility);
|
||||
|
||||
// Enable sensors again after exiting PiP
|
||||
controllerHandler.enableSensors();
|
||||
|
||||
// Update GameManager state to indicate we're out of PiP (gaming, non-interruptible)
|
||||
UiHelper.notifyStreamExitingPiP(this);
|
||||
}
|
||||
@@ -1064,6 +1093,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
||||
if (controllerHandler != null) {
|
||||
inputManager.unregisterInputDeviceListener(controllerHandler);
|
||||
controllerHandler.destroy();
|
||||
}
|
||||
if (keyboardTranslator != null) {
|
||||
inputManager.unregisterInputDeviceListener(keyboardTranslator);
|
||||
@@ -1118,15 +1148,26 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
// Add the video codec to the post-stream toast
|
||||
if (message != null) {
|
||||
if (videoFormat == MoonBridge.VIDEO_FORMAT_H265_MAIN10) {
|
||||
message += " [HEVC HDR]";
|
||||
message += " [";
|
||||
|
||||
if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H264) != 0) {
|
||||
message += "H.264";
|
||||
}
|
||||
else if (videoFormat == MoonBridge.VIDEO_FORMAT_H265) {
|
||||
message += " [HEVC]";
|
||||
else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) {
|
||||
message += "HEVC";
|
||||
}
|
||||
else if (videoFormat == MoonBridge.VIDEO_FORMAT_H264) {
|
||||
message += " [H.264]";
|
||||
else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_AV1) != 0) {
|
||||
message += "AV1";
|
||||
}
|
||||
else {
|
||||
message += "UNKNOWN";
|
||||
}
|
||||
|
||||
if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_10BIT) != 0) {
|
||||
message += " HDR";
|
||||
}
|
||||
|
||||
message += "]";
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
@@ -1150,6 +1191,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Grab/ungrab the mouse cursor
|
||||
if (grab) {
|
||||
inputCaptureProvider.enableCapture();
|
||||
|
||||
// Enabling capture may hide the cursor again, so
|
||||
// we will need to show it again.
|
||||
if (cursorVisible) {
|
||||
inputCaptureProvider.showCursor();
|
||||
}
|
||||
}
|
||||
else {
|
||||
inputCaptureProvider.disableCapture();
|
||||
@@ -1171,6 +1218,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
// Returns true if the key stroke was consumed
|
||||
private boolean handleSpecialKeys(int androidKeyCode, boolean down) {
|
||||
int modifierMask = 0;
|
||||
int nonModifierKeyCode = KeyEvent.KEYCODE_UNKNOWN;
|
||||
|
||||
if (androidKeyCode == KeyEvent.KEYCODE_CTRL_LEFT ||
|
||||
androidKeyCode == KeyEvent.KEYCODE_CTRL_RIGHT) {
|
||||
@@ -1188,6 +1236,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
androidKeyCode == KeyEvent.KEYCODE_META_RIGHT) {
|
||||
modifierMask = KeyboardPacket.MODIFIER_META;
|
||||
}
|
||||
else {
|
||||
nonModifierKeyCode = androidKeyCode;
|
||||
}
|
||||
|
||||
if (down) {
|
||||
this.modifierFlags |= modifierMask;
|
||||
@@ -1196,36 +1247,62 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
this.modifierFlags &= ~modifierMask;
|
||||
}
|
||||
|
||||
// Check if Ctrl+Alt+Shift+Z is pressed
|
||||
if (androidKeyCode == KeyEvent.KEYCODE_Z &&
|
||||
(modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT)) ==
|
||||
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT))
|
||||
{
|
||||
if (down) {
|
||||
// Now that we've pressed the magic combo
|
||||
// we'll wait for one of the keys to come up
|
||||
grabComboDown = true;
|
||||
// Handle the special combos on the key up
|
||||
if (waitingForAllModifiersUp || specialKeyCode != KeyEvent.KEYCODE_UNKNOWN) {
|
||||
if (specialKeyCode == androidKeyCode) {
|
||||
// If this is a key up for the special key itself, eat that because the host never saw the original key down
|
||||
return true;
|
||||
}
|
||||
else if (modifierFlags != 0) {
|
||||
// While we're waiting for modifiers to come up, eat all key downs and allow all key ups to pass
|
||||
return down;
|
||||
}
|
||||
else {
|
||||
// Toggle the grab if Z comes up
|
||||
Handler h = getWindow().getDecorView().getHandler();
|
||||
if (h != null) {
|
||||
h.postDelayed(toggleGrab, 250);
|
||||
// When all modifiers are up, perform the special action
|
||||
switch (specialKeyCode) {
|
||||
// Toggle input grab
|
||||
case KeyEvent.KEYCODE_Z:
|
||||
Handler h = getWindow().getDecorView().getHandler();
|
||||
if (h != null) {
|
||||
h.postDelayed(toggleGrab, 250);
|
||||
}
|
||||
break;
|
||||
|
||||
// Quit
|
||||
case KeyEvent.KEYCODE_Q:
|
||||
finish();
|
||||
break;
|
||||
|
||||
// Toggle cursor visibility
|
||||
case KeyEvent.KEYCODE_C:
|
||||
if (!grabbedInput) {
|
||||
inputCaptureProvider.enableCapture();
|
||||
grabbedInput = true;
|
||||
}
|
||||
cursorVisible = !cursorVisible;
|
||||
if (cursorVisible) {
|
||||
inputCaptureProvider.showCursor();
|
||||
} else {
|
||||
inputCaptureProvider.hideCursor();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
grabComboDown = false;
|
||||
// Reset special key state
|
||||
specialKeyCode = KeyEvent.KEYCODE_UNKNOWN;
|
||||
waitingForAllModifiersUp = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// Toggle the grab if control or shift comes up
|
||||
else if (grabComboDown) {
|
||||
Handler h = getWindow().getDecorView().getHandler();
|
||||
if (h != null) {
|
||||
h.postDelayed(toggleGrab, 250);
|
||||
}
|
||||
|
||||
grabComboDown = false;
|
||||
// Check if Ctrl+Alt+Shift is down when a non-modifier key is pressed
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1445,20 +1522,300 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
inputManager.toggleSoftInput(0, 0);
|
||||
}
|
||||
|
||||
private byte getLiTouchTypeFromEvent(MotionEvent event) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
return MoonBridge.LI_TOUCH_EVENT_DOWN;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if ((event.getFlags() & MotionEvent.FLAG_CANCELED) != 0) {
|
||||
return MoonBridge.LI_TOUCH_EVENT_CANCEL;
|
||||
}
|
||||
else {
|
||||
return MoonBridge.LI_TOUCH_EVENT_UP;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
return MoonBridge.LI_TOUCH_EVENT_MOVE;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
// ACTION_CANCEL applies to *all* pointers in the gesture, so it maps to CANCEL_ALL
|
||||
// rather than CANCEL. For a single pointer cancellation, that's indicated via
|
||||
// FLAG_CANCELED on a ACTION_POINTER_UP.
|
||||
// https://developer.android.com/develop/ui/views/touch-and-input/gestures/multi
|
||||
return MoonBridge.LI_TOUCH_EVENT_CANCEL_ALL;
|
||||
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
return MoonBridge.LI_TOUCH_EVENT_HOVER;
|
||||
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
return MoonBridge.LI_TOUCH_EVENT_HOVER_LEAVE;
|
||||
|
||||
case MotionEvent.ACTION_BUTTON_PRESS:
|
||||
case MotionEvent.ACTION_BUTTON_RELEASE:
|
||||
return MoonBridge.LI_TOUCH_EVENT_BUTTON_ONLY;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private float[] getStreamViewRelativeNormalizedXY(View view, MotionEvent event, int pointerIndex) {
|
||||
float normalizedX = event.getX(pointerIndex);
|
||||
float normalizedY = event.getY(pointerIndex);
|
||||
|
||||
// For the containing background view, we must subtract the origin
|
||||
// of the StreamView to get video-relative coordinates.
|
||||
if (view != streamView) {
|
||||
normalizedX -= streamView.getX();
|
||||
normalizedY -= streamView.getY();
|
||||
}
|
||||
|
||||
normalizedX = Math.max(normalizedX, 0.0f);
|
||||
normalizedY = Math.max(normalizedY, 0.0f);
|
||||
|
||||
normalizedX = Math.min(normalizedX, streamView.getWidth());
|
||||
normalizedY = Math.min(normalizedY, streamView.getHeight());
|
||||
|
||||
normalizedX /= streamView.getWidth();
|
||||
normalizedY /= streamView.getHeight();
|
||||
|
||||
return new float[] { normalizedX, normalizedY };
|
||||
}
|
||||
|
||||
private static float normalizeValueInRange(float value, InputDevice.MotionRange range) {
|
||||
return (value - range.getMin()) / range.getRange();
|
||||
}
|
||||
|
||||
private static float getPressureOrDistance(MotionEvent event, int pointerIndex) {
|
||||
InputDevice dev = event.getDevice();
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
// Hover events report distance
|
||||
if (dev != null) {
|
||||
InputDevice.MotionRange distanceRange = dev.getMotionRange(MotionEvent.AXIS_DISTANCE, event.getSource());
|
||||
if (distanceRange != null) {
|
||||
return normalizeValueInRange(event.getAxisValue(MotionEvent.AXIS_DISTANCE, pointerIndex), distanceRange);
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
|
||||
default:
|
||||
// Other events report pressure
|
||||
return event.getPressure(pointerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private static short getRotationDegrees(MotionEvent event, int pointerIndex) {
|
||||
InputDevice dev = event.getDevice();
|
||||
if (dev != null) {
|
||||
if (dev.getMotionRange(MotionEvent.AXIS_ORIENTATION, event.getSource()) != null) {
|
||||
short rotationDegrees = (short) Math.toDegrees(event.getOrientation(pointerIndex));
|
||||
if (rotationDegrees < 0) {
|
||||
rotationDegrees += 360;
|
||||
}
|
||||
return rotationDegrees;
|
||||
}
|
||||
}
|
||||
return MoonBridge.LI_ROT_UNKNOWN;
|
||||
}
|
||||
|
||||
private static float[] polarToCartesian(float r, float theta) {
|
||||
return new float[] { (float)(r * Math.cos(theta)), (float)(r * Math.sin(theta)) };
|
||||
}
|
||||
|
||||
private static float cartesianToR(float[] point) {
|
||||
return (float)Math.sqrt(Math.pow(point[0], 2) + Math.pow(point[1], 2));
|
||||
}
|
||||
|
||||
private float[] getStreamViewNormalizedContactArea(MotionEvent event, int pointerIndex) {
|
||||
float orientation;
|
||||
|
||||
// If the orientation is unknown, we'll just assume it's at a 45 degree angle and scale it by
|
||||
// X and Y scaling factors evenly.
|
||||
if (event.getDevice() == null || event.getDevice().getMotionRange(MotionEvent.AXIS_ORIENTATION, event.getSource()) == null) {
|
||||
orientation = (float)(Math.PI / 4);
|
||||
}
|
||||
else {
|
||||
orientation = event.getOrientation(pointerIndex);
|
||||
}
|
||||
|
||||
float contactAreaMajor, contactAreaMinor;
|
||||
switch (event.getActionMasked()) {
|
||||
// Hover events report the tool size
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
contactAreaMajor = event.getToolMajor(pointerIndex);
|
||||
contactAreaMinor = event.getToolMinor(pointerIndex);
|
||||
break;
|
||||
|
||||
// Other events report contact area
|
||||
default:
|
||||
contactAreaMajor = event.getTouchMajor(pointerIndex);
|
||||
contactAreaMinor = event.getTouchMinor(pointerIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
// The contact area major axis is parallel to the orientation, so we simply convert
|
||||
// polar to cartesian coordinates using the orientation as theta.
|
||||
float[] contactAreaMajorCartesian = polarToCartesian(contactAreaMajor, orientation);
|
||||
|
||||
// The contact area minor axis is perpendicular to the contact area major axis (and thus
|
||||
// the orientation), so rotate the orientation angle by 90 degrees.
|
||||
float[] contactAreaMinorCartesian = polarToCartesian(contactAreaMinor, (float)(orientation + (Math.PI / 2)));
|
||||
|
||||
// Normalize the contact area to the stream view size
|
||||
contactAreaMajorCartesian[0] = Math.min(Math.abs(contactAreaMajorCartesian[0]), streamView.getWidth()) / streamView.getWidth();
|
||||
contactAreaMinorCartesian[0] = Math.min(Math.abs(contactAreaMinorCartesian[0]), streamView.getWidth()) / streamView.getWidth();
|
||||
contactAreaMajorCartesian[1] = Math.min(Math.abs(contactAreaMajorCartesian[1]), streamView.getHeight()) / streamView.getHeight();
|
||||
contactAreaMinorCartesian[1] = Math.min(Math.abs(contactAreaMinorCartesian[1]), streamView.getHeight()) / streamView.getHeight();
|
||||
|
||||
// Convert the normalized values back into polar coordinates
|
||||
return new float[] { cartesianToR(contactAreaMajorCartesian), cartesianToR(contactAreaMinorCartesian) };
|
||||
}
|
||||
|
||||
private boolean sendPenEventForPointer(View view, MotionEvent event, byte eventType, byte toolType, int pointerIndex) {
|
||||
byte penButtons = 0;
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0) {
|
||||
penButtons |= MoonBridge.LI_PEN_BUTTON_PRIMARY;
|
||||
}
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_STYLUS_SECONDARY) != 0) {
|
||||
penButtons |= MoonBridge.LI_PEN_BUTTON_SECONDARY;
|
||||
}
|
||||
|
||||
byte tiltDegrees = MoonBridge.LI_TILT_UNKNOWN;
|
||||
InputDevice dev = event.getDevice();
|
||||
if (dev != null) {
|
||||
if (dev.getMotionRange(MotionEvent.AXIS_TILT, event.getSource()) != null) {
|
||||
tiltDegrees = (byte)Math.toDegrees(event.getAxisValue(MotionEvent.AXIS_TILT, pointerIndex));
|
||||
}
|
||||
}
|
||||
|
||||
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event, pointerIndex);
|
||||
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event, pointerIndex);
|
||||
return conn.sendPenEvent(eventType, toolType, penButtons,
|
||||
normalizedCoords[0], normalizedCoords[1],
|
||||
getPressureOrDistance(event, pointerIndex),
|
||||
normalizedContactArea[0], normalizedContactArea[1],
|
||||
getRotationDegrees(event, pointerIndex), tiltDegrees) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
private static byte convertToolTypeToStylusToolType(MotionEvent event, int pointerIndex) {
|
||||
switch (event.getToolType(pointerIndex)) {
|
||||
case MotionEvent.TOOL_TYPE_ERASER:
|
||||
return MoonBridge.LI_TOOL_TYPE_ERASER;
|
||||
case MotionEvent.TOOL_TYPE_STYLUS:
|
||||
return MoonBridge.LI_TOOL_TYPE_PEN;
|
||||
default:
|
||||
return MoonBridge.LI_TOOL_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean trySendPenEvent(View view, MotionEvent event) {
|
||||
byte eventType = getLiTouchTypeFromEvent(event);
|
||||
if (eventType < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||
// Move events may impact all active pointers
|
||||
boolean handledStylusEvent = false;
|
||||
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||
byte toolType = convertToolTypeToStylusToolType(event, i);
|
||||
if (toolType == MoonBridge.LI_TOOL_TYPE_UNKNOWN) {
|
||||
// Not a stylus pointer, so skip it
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// This pointer is a stylus, so we'll report that we handled this event
|
||||
handledStylusEvent = true;
|
||||
}
|
||||
|
||||
if (!sendPenEventForPointer(view, event, eventType, toolType, i)) {
|
||||
// Pen events aren't supported by the host
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return handledStylusEvent;
|
||||
}
|
||||
else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
|
||||
// Cancel impacts all active pointers
|
||||
return conn.sendPenEvent(MoonBridge.LI_TOUCH_EVENT_CANCEL_ALL, MoonBridge.LI_TOOL_TYPE_UNKNOWN, (byte)0,
|
||||
0, 0, 0, 0, 0,
|
||||
MoonBridge.LI_ROT_UNKNOWN, MoonBridge.LI_TILT_UNKNOWN) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
// Up, Down, and Hover events are specific to the action index
|
||||
byte toolType = convertToolTypeToStylusToolType(event, event.getActionIndex());
|
||||
if (toolType == MoonBridge.LI_TOOL_TYPE_UNKNOWN) {
|
||||
// Not a stylus event
|
||||
return false;
|
||||
}
|
||||
return sendPenEventForPointer(view, event, eventType, toolType, event.getActionIndex());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendTouchEventForPointer(View view, MotionEvent event, byte eventType, int pointerIndex) {
|
||||
float[] normalizedCoords = getStreamViewRelativeNormalizedXY(view, event, pointerIndex);
|
||||
float[] normalizedContactArea = getStreamViewNormalizedContactArea(event, pointerIndex);
|
||||
return conn.sendTouchEvent(eventType, event.getPointerId(pointerIndex),
|
||||
normalizedCoords[0], normalizedCoords[1],
|
||||
getPressureOrDistance(event, pointerIndex),
|
||||
normalizedContactArea[0], normalizedContactArea[1],
|
||||
getRotationDegrees(event, pointerIndex)) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
private boolean trySendTouchEvent(View view, MotionEvent event) {
|
||||
byte eventType = getLiTouchTypeFromEvent(event);
|
||||
if (eventType < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
||||
// Move events may impact all active pointers
|
||||
for (int i = 0; i < event.getPointerCount(); i++) {
|
||||
if (!sendTouchEventForPointer(view, event, eventType, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
|
||||
// Cancel impacts all active pointers
|
||||
return conn.sendTouchEvent(MoonBridge.LI_TOUCH_EVENT_CANCEL_ALL, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
MoonBridge.LI_ROT_UNKNOWN) != MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
// Up, Down, and Hover events are specific to the action index
|
||||
return sendTouchEventForPointer(view, event, eventType, event.getActionIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the event was consumed
|
||||
// NB: View is only present if called from a view callback
|
||||
private boolean handleMotionEvent(View view, MotionEvent event) {
|
||||
// Pass through keyboard input if we're not grabbing
|
||||
// Pass through mouse/touch/joystick input if we're not grabbing
|
||||
if (!grabbedInput) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int eventSource = event.getSource();
|
||||
int deviceSources = event.getDevice() != null ? event.getDevice().getSources() : 0;
|
||||
if ((eventSource & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
|
||||
if (controllerHandler.handleMotionEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ((deviceSources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 && controllerHandler.tryHandleTouchpadEvent(event)) {
|
||||
return true;
|
||||
}
|
||||
else if ((eventSource & InputDevice.SOURCE_CLASS_POINTER) != 0 ||
|
||||
(eventSource & InputDevice.SOURCE_CLASS_POSITION) != 0 ||
|
||||
eventSource == InputDevice.SOURCE_MOUSE_RELATIVE)
|
||||
@@ -1545,6 +1902,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (view != null && trySendPenEvent(view, event)) {
|
||||
// If our host supports pen events, send it directly
|
||||
return true;
|
||||
}
|
||||
else if (view != null) {
|
||||
// Otherwise send absolute position based on the view for SOURCE_CLASS_POINTER
|
||||
updateMousePosition(view, event);
|
||||
@@ -1687,6 +2048,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Re-enable native touch when have a better solution for handling
|
||||
// cancelled touches from Android gestures and 3 finger taps to activate
|
||||
// the software keyboard.
|
||||
/*if (!prefConfig.touchscreenTrackpad && trySendTouchEvent(view, event)) {
|
||||
// If this host supports touch events and absolute touch is enabled,
|
||||
// send it directly as a touch event.
|
||||
return true;
|
||||
}*/
|
||||
|
||||
TouchContext context = getTouchContext(actionIndex);
|
||||
if (context == null) {
|
||||
return false;
|
||||
@@ -2104,12 +2474,29 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
controllerHandler.handleRumble(controllerNumber, lowFreqMotor, highFreqMotor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
|
||||
LimeLog.info(String.format((Locale)null, "Rumble on gamepad triggers %d: %04x %04x", controllerNumber, leftTrigger, rightTrigger));
|
||||
|
||||
controllerHandler.handleRumbleTriggers(controllerNumber, leftTrigger, rightTrigger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHdrMode(boolean enabled, byte[] hdrMetadata) {
|
||||
LimeLog.info("Display HDR mode: " + (enabled ? "enabled" : "disabled"));
|
||||
decoderRenderer.setHdrMode(enabled, hdrMetadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotionEventState(short controllerNumber, byte motionType, short reportRateHz) {
|
||||
controllerHandler.handleSetMotionEventState(controllerNumber, motionType, reportRateHz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControllerLED(short controllerNumber, byte r, byte g, byte b) {
|
||||
controllerHandler.handleSetControllerLED(controllerNumber, r, g, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
if (!surfaceCreated) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -232,6 +232,10 @@ public class KeyboardTranslator implements InputManager.InputDeviceListener {
|
||||
translated = 0x5c;
|
||||
break;
|
||||
|
||||
case KeyEvent.KEYCODE_MENU:
|
||||
translated = 0x5d;
|
||||
break;
|
||||
|
||||
case KeyEvent.KEYCODE_MINUS:
|
||||
translated = 0xbd;
|
||||
break;
|
||||
|
||||
+16
-12
@@ -15,8 +15,8 @@ import android.view.View;
|
||||
// is unavailable on this system (ex: DeX, ChromeOS)
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptureProvider implements InputManager.InputDeviceListener {
|
||||
private InputManager inputManager;
|
||||
private View targetView;
|
||||
private final InputManager inputManager;
|
||||
private final View targetView;
|
||||
|
||||
public AndroidNativePointerCaptureProvider(Activity activity, View targetView) {
|
||||
super(activity, targetView);
|
||||
@@ -62,8 +62,16 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
super.enableCapture();
|
||||
public void showCursor() {
|
||||
super.showCursor();
|
||||
|
||||
inputManager.unregisterInputDeviceListener(this);
|
||||
targetView.releasePointerCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideCursor() {
|
||||
super.hideCursor();
|
||||
|
||||
// Listen for device events to enable/disable capture
|
||||
inputManager.registerInputDeviceListener(this, null);
|
||||
@@ -74,16 +82,12 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCapture() {
|
||||
super.disableCapture();
|
||||
inputManager.unregisterInputDeviceListener(this);
|
||||
targetView.releasePointerCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean focusActive) {
|
||||
if (!focusActive || !isCapturing) {
|
||||
// NB: We have to check cursor visibility here because Android pointer capture
|
||||
// doesn't support capturing the cursor while it's visible. Enabling pointer
|
||||
// capture implicitly hides the cursor.
|
||||
if (!focusActive || !isCapturing || isCursorVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -4,14 +4,13 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.View;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
|
||||
private View targetView;
|
||||
private Context context;
|
||||
private final View targetView;
|
||||
private final Context context;
|
||||
|
||||
public AndroidPointerIconCaptureProvider(Activity activity, View targetView) {
|
||||
this.context = activity;
|
||||
@@ -23,14 +22,14 @@ public class AndroidPointerIconCaptureProvider extends InputCaptureProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
super.enableCapture();
|
||||
public void hideCursor() {
|
||||
super.hideCursor();
|
||||
targetView.setPointerIcon(PointerIcon.getSystemIcon(context, PointerIcon.TYPE_NULL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCapture() {
|
||||
super.disableCapture();
|
||||
public void showCursor() {
|
||||
super.showCursor();
|
||||
targetView.setPointerIcon(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ import android.view.MotionEvent;
|
||||
|
||||
public abstract class InputCaptureProvider {
|
||||
protected boolean isCapturing;
|
||||
protected boolean isCursorVisible;
|
||||
|
||||
public void enableCapture() {
|
||||
isCapturing = true;
|
||||
hideCursor();
|
||||
}
|
||||
public void disableCapture() {
|
||||
isCapturing = false;
|
||||
showCursor();
|
||||
}
|
||||
|
||||
public void destroy() {}
|
||||
@@ -22,6 +25,14 @@ public abstract class InputCaptureProvider {
|
||||
return isCapturing;
|
||||
}
|
||||
|
||||
public void showCursor() {
|
||||
isCursorVisible = true;
|
||||
}
|
||||
|
||||
public void hideCursor() {
|
||||
isCursorVisible = false;
|
||||
}
|
||||
|
||||
public boolean eventHasRelativeMouseAxes(MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
|
||||
private static int AXIS_RELATIVE_X;
|
||||
private static int AXIS_RELATIVE_Y;
|
||||
|
||||
private Context context;
|
||||
private final Context context;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -62,14 +62,14 @@ public class ShieldCaptureProvider extends InputCaptureProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
super.enableCapture();
|
||||
public void hideCursor() {
|
||||
super.hideCursor();
|
||||
setCursorVisibility(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCapture() {
|
||||
super.disableCapture();
|
||||
public void showCursor() {
|
||||
super.showCursor();
|
||||
setCursorVisibility(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ public abstract class AbstractController {
|
||||
|
||||
private UsbDriverListener listener;
|
||||
|
||||
protected short buttonFlags;
|
||||
protected int buttonFlags, supportedButtonFlags;
|
||||
protected float leftTrigger, rightTrigger;
|
||||
protected float rightStickX, rightStickY;
|
||||
protected float leftStickX, leftStickY;
|
||||
protected short capabilities;
|
||||
protected byte type;
|
||||
|
||||
public int getControllerId() {
|
||||
return deviceId;
|
||||
@@ -25,6 +27,18 @@ public abstract class AbstractController {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public int getSupportedButtonFlags() {
|
||||
return supportedButtonFlags;
|
||||
}
|
||||
|
||||
public short getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
protected void setButtonFlag(int buttonFlag, int data) {
|
||||
if (data != 0) {
|
||||
buttonFlags |= buttonFlag;
|
||||
@@ -51,6 +65,8 @@ public abstract class AbstractController {
|
||||
|
||||
public abstract void rumble(short lowFreqMotor, short highFreqMotor);
|
||||
|
||||
public abstract void rumbleTriggers(short leftTrigger, short rightTrigger);
|
||||
|
||||
protected void notifyDeviceRemoved() {
|
||||
listener.deviceRemoved(this);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import android.hardware.usb.UsbInterface;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.nvstream.input.ControllerPacket;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@@ -25,6 +27,14 @@ public abstract class AbstractXboxController extends AbstractController {
|
||||
super(deviceId, listener, device.getVendorId(), device.getProductId());
|
||||
this.device = device;
|
||||
this.connection = connection;
|
||||
this.type = MoonBridge.LI_CTYPE_XBOX;
|
||||
this.capabilities = MoonBridge.LI_CCAP_ANALOG_TRIGGERS | MoonBridge.LI_CCAP_RUMBLE;
|
||||
this.buttonFlags =
|
||||
ControllerPacket.A_FLAG | ControllerPacket.B_FLAG | ControllerPacket.X_FLAG | ControllerPacket.Y_FLAG |
|
||||
ControllerPacket.UP_FLAG | ControllerPacket.DOWN_FLAG | ControllerPacket.LEFT_FLAG | ControllerPacket.RIGHT_FLAG |
|
||||
ControllerPacket.LB_FLAG | ControllerPacket.RB_FLAG |
|
||||
ControllerPacket.LS_CLK_FLAG | ControllerPacket.RS_CLK_FLAG |
|
||||
ControllerPacket.BACK_FLAG | ControllerPacket.PLAY_FLAG | ControllerPacket.SPECIAL_BUTTON_FLAG;
|
||||
}
|
||||
|
||||
private Thread createInputThread() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.limelight.binding.input.driver;
|
||||
|
||||
public interface UsbDriverListener {
|
||||
void reportControllerState(int controllerId, short buttonFlags,
|
||||
void reportControllerState(int controllerId, int buttonFlags,
|
||||
float leftStickX, float leftStickY,
|
||||
float rightStickX, float rightStickY,
|
||||
float leftTrigger, float rightTrigger);
|
||||
|
||||
@@ -42,7 +42,8 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
private int nextDeviceId;
|
||||
|
||||
@Override
|
||||
public void reportControllerState(int controllerId, short buttonFlags, float leftStickX, float leftStickY, float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
|
||||
public void reportControllerState(int controllerId, int buttonFlags, float leftStickX, float leftStickY,
|
||||
float rightStickX, float rightStickY, float leftTrigger, float rightTrigger) {
|
||||
// Call through to the client's listener
|
||||
if (listener != null) {
|
||||
listener.reportControllerState(controllerId, buttonFlags, leftStickX, leftStickY, rightStickX, rightStickY, leftTrigger, rightTrigger);
|
||||
@@ -158,7 +159,12 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
// just returning a false result or returning 0 enumerated devices,
|
||||
// they throw an undocumented SecurityException from this call, crashing
|
||||
// the whole app. :(
|
||||
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, new Intent(ACTION_USB_PERMISSION), intentFlags));
|
||||
|
||||
// Use an explicit intent to activate our unexported broadcast receiver, as required on Android 14+
|
||||
Intent i = new Intent(ACTION_USB_PERMISSION);
|
||||
i.setPackage(getPackageName());
|
||||
|
||||
usbManager.requestPermission(device, PendingIntent.getBroadcast(UsbDriverService.this, 0, i, intentFlags));
|
||||
} catch (SecurityException e) {
|
||||
Toast.makeText(this, this.getText(R.string.error_usb_prohibited), Toast.LENGTH_LONG).show();
|
||||
if (stateListener != null) {
|
||||
@@ -281,7 +287,7 @@ public class UsbDriverService extends Service implements UsbDriverListener {
|
||||
}
|
||||
|
||||
private void start() {
|
||||
if (started) {
|
||||
if (started || usbManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,4 +156,9 @@ public class Xbox360Controller extends AbstractXboxController {
|
||||
LimeLog.warning("Rumble transfer failed: "+res);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
|
||||
// Trigger motors not present on Xbox 360 controllers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,4 +142,9 @@ public class Xbox360WirelessDongle extends AbstractController {
|
||||
public void rumble(short lowFreqMotor, short highFreqMotor) {
|
||||
// Unreachable.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
|
||||
// Unreachable.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.hardware.usb.UsbDeviceConnection;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
import com.limelight.nvstream.input.ControllerPacket;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
@@ -54,9 +55,14 @@ public class XboxOneController extends AbstractXboxController {
|
||||
};
|
||||
|
||||
private byte seqNum = 0;
|
||||
private short lowFreqMotor = 0;
|
||||
private short highFreqMotor = 0;
|
||||
private short leftTriggerMotor = 0;
|
||||
private short rightTriggerMotor = 0;
|
||||
|
||||
public XboxOneController(UsbDevice device, UsbDeviceConnection connection, int deviceId, UsbDriverListener listener) {
|
||||
super(device, connection, deviceId, listener);
|
||||
capabilities |= MoonBridge.LI_CCAP_TRIGGER_RUMBLE;
|
||||
}
|
||||
|
||||
private void processButtons(ByteBuffer buffer) {
|
||||
@@ -176,12 +182,14 @@ public class XboxOneController extends AbstractXboxController {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumble(short lowFreqMotor, short highFreqMotor) {
|
||||
private void sendRumblePacket() {
|
||||
byte[] data = {
|
||||
0x09, 0x00, seqNum++, 0x09, 0x00,
|
||||
0x0F, 0x00, 0x00,
|
||||
(byte)(lowFreqMotor >> 9), (byte)(highFreqMotor >> 9),
|
||||
0x0F,
|
||||
(byte)(leftTriggerMotor >> 9),
|
||||
(byte)(rightTriggerMotor >> 9),
|
||||
(byte)(lowFreqMotor >> 9),
|
||||
(byte)(highFreqMotor >> 9),
|
||||
(byte)0xFF, 0x00, (byte)0xFF
|
||||
};
|
||||
int res = connection.bulkTransfer(outEndpt, data, data.length, 100);
|
||||
@@ -190,6 +198,20 @@ public class XboxOneController extends AbstractXboxController {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumble(short lowFreqMotor, short highFreqMotor) {
|
||||
this.lowFreqMotor = lowFreqMotor;
|
||||
this.highFreqMotor = highFreqMotor;
|
||||
sendRumblePacket();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
|
||||
this.leftTriggerMotor = leftTrigger;
|
||||
this.rightTriggerMotor = rightTrigger;
|
||||
sendRumblePacket();
|
||||
}
|
||||
|
||||
private static class InitPacket {
|
||||
final int vendorId;
|
||||
final int productId;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.limelight.binding.video;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -20,6 +21,7 @@ import com.limelight.nvstream.jni.MoonBridge;
|
||||
import com.limelight.preferences.PreferenceConfiguration;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
@@ -45,24 +47,25 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
|
||||
private MediaCodecInfo avcDecoder;
|
||||
private MediaCodecInfo hevcDecoder;
|
||||
private MediaCodecInfo av1Decoder;
|
||||
|
||||
private byte[] vpsBuffer;
|
||||
private byte[] spsBuffer;
|
||||
private byte[] ppsBuffer;
|
||||
private final ArrayList<byte[]> vpsBuffers = new ArrayList<>();
|
||||
private final ArrayList<byte[]> spsBuffers = new ArrayList<>();
|
||||
private final ArrayList<byte[]> ppsBuffers = new ArrayList<>();
|
||||
private boolean submittedCsd;
|
||||
private boolean submitCsdNextCall;
|
||||
private byte[] currentHdrMetadata;
|
||||
|
||||
private int nextInputBufferIndex = -1;
|
||||
private ByteBuffer nextInputBuffer;
|
||||
|
||||
private Context context;
|
||||
private Activity activity;
|
||||
private MediaCodec videoDecoder;
|
||||
private Thread rendererThread;
|
||||
private boolean needsSpsBitstreamFixup, isExynos4;
|
||||
private boolean adaptivePlayback, directSubmit, fusedIdrFrame;
|
||||
private boolean constrainedHighProfile;
|
||||
private boolean refFrameInvalidationAvc, refFrameInvalidationHevc;
|
||||
private boolean refFrameInvalidationAvc, refFrameInvalidationHevc, refFrameInvalidationAv1;
|
||||
private byte optimalSlicesPerFrame;
|
||||
private boolean refFrameInvalidationActive;
|
||||
private int initialWidth, initialHeight;
|
||||
@@ -175,7 +178,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
return caps.areSizeAndRateSupported(prefs.width, prefs.height, prefs.fps);
|
||||
}
|
||||
|
||||
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo avcDecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
||||
private boolean decoderCanMeetPerformancePointWithHevcAndNotAvc(MediaCodecInfo hevcDecoderInfo, MediaCodecInfo avcDecoderInfo, PreferenceConfiguration prefs) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
MediaCodecInfo.VideoCapabilities avcCaps = avcDecoderInfo.getCapabilitiesForType("video/avc").getVideoCapabilities();
|
||||
MediaCodecInfo.VideoCapabilities hevcCaps = hevcDecoderInfo.getCapabilitiesForType("video/hevc").getVideoCapabilities();
|
||||
@@ -188,9 +191,35 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decoderCanMeetPerformancePointWithAv1AndNotHevc(MediaCodecInfo av1DecoderInfo, MediaCodecInfo hevcDecoderInfo, PreferenceConfiguration prefs) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
MediaCodecInfo.VideoCapabilities av1Caps = av1DecoderInfo.getCapabilitiesForType("video/av01").getVideoCapabilities();
|
||||
MediaCodecInfo.VideoCapabilities hevcCaps = hevcDecoderInfo.getCapabilitiesForType("video/hevc").getVideoCapabilities();
|
||||
|
||||
return !decoderCanMeetPerformancePoint(hevcCaps, prefs) && decoderCanMeetPerformancePoint(av1Caps, prefs);
|
||||
}
|
||||
else {
|
||||
// No performance data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean decoderCanMeetPerformancePointWithAv1AndNotAvc(MediaCodecInfo av1DecoderInfo, MediaCodecInfo avcDecoderInfo, PreferenceConfiguration prefs) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
MediaCodecInfo.VideoCapabilities avcCaps = avcDecoderInfo.getCapabilitiesForType("video/avc").getVideoCapabilities();
|
||||
MediaCodecInfo.VideoCapabilities av1Caps = av1DecoderInfo.getCapabilitiesForType("video/av01").getVideoCapabilities();
|
||||
|
||||
return !decoderCanMeetPerformancePoint(avcCaps, prefs) && decoderCanMeetPerformancePoint(av1Caps, prefs);
|
||||
}
|
||||
else {
|
||||
// No performance data
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private MediaCodecInfo findHevcDecoder(PreferenceConfiguration prefs, boolean meteredNetwork, boolean requestedHdr) {
|
||||
// Don't return anything if HEVC is forced off
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_OFF) {
|
||||
// Don't return anything if H.264 is forced
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_H264) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -205,7 +234,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+hevcDecoderInfo.getName());
|
||||
|
||||
// Force HEVC enabled if the user asked for it
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_ON) {
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_HEVC) {
|
||||
LimeLog.info("Forcing HEVC enabled despite non-whitelisted decoder");
|
||||
}
|
||||
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR.
|
||||
@@ -217,7 +246,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
LimeLog.info("Forcing HEVC enabled for over 4K streaming");
|
||||
}
|
||||
// Use HEVC if the H.264 decoder is unable to meet the performance point
|
||||
else if (avcDecoder != null && decoderCanMeetPerformancePointWithHevcAndNotAvc(avcDecoder, hevcDecoderInfo, prefs)) {
|
||||
else if (avcDecoder != null && decoderCanMeetPerformancePointWithHevcAndNotAvc(hevcDecoderInfo, avcDecoder, prefs)) {
|
||||
LimeLog.info("Using non-whitelisted HEVC decoder to meet performance point");
|
||||
}
|
||||
else {
|
||||
@@ -229,17 +258,50 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
return hevcDecoderInfo;
|
||||
}
|
||||
|
||||
private MediaCodecInfo findAv1Decoder(PreferenceConfiguration prefs) {
|
||||
// For now, don't use AV1 unless explicitly requested
|
||||
if (prefs.videoFormat != PreferenceConfiguration.FormatOption.FORCE_AV1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MediaCodecInfo decoderInfo = MediaCodecHelper.findProbableSafeDecoder("video/av01", -1);
|
||||
if (decoderInfo != null) {
|
||||
if (!MediaCodecHelper.isDecoderWhitelistedForAv1(decoderInfo)) {
|
||||
LimeLog.info("Found AV1 decoder, but it's not whitelisted - "+decoderInfo.getName());
|
||||
|
||||
// Force HEVC enabled if the user asked for it
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FormatOption.FORCE_AV1) {
|
||||
LimeLog.info("Forcing AV1 enabled despite non-whitelisted decoder");
|
||||
}
|
||||
// Use AV1 if the HEVC decoder is unable to meet the performance point
|
||||
else if (hevcDecoder != null && decoderCanMeetPerformancePointWithAv1AndNotHevc(decoderInfo, hevcDecoder, prefs)) {
|
||||
LimeLog.info("Using non-whitelisted AV1 decoder to meet performance point");
|
||||
}
|
||||
// Use AV1 if the H.264 decoder is unable to meet the performance point and we have no HEVC decoder
|
||||
else if (hevcDecoder == null && decoderCanMeetPerformancePointWithAv1AndNotAvc(decoderInfo, avcDecoder, prefs)) {
|
||||
LimeLog.info("Using non-whitelisted AV1 decoder to meet performance point");
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decoderInfo;
|
||||
}
|
||||
|
||||
public void setRenderTarget(SurfaceHolder renderTarget) {
|
||||
this.renderTarget = renderTarget;
|
||||
}
|
||||
|
||||
public MediaCodecDecoderRenderer(Context context, PreferenceConfiguration prefs,
|
||||
public MediaCodecDecoderRenderer(Activity activity, PreferenceConfiguration prefs,
|
||||
CrashListener crashListener, int consecutiveCrashCount,
|
||||
boolean meteredData, boolean requestedHdr,
|
||||
String glRenderer, PerfOverlayListener perfListener) {
|
||||
//dumpDecoders();
|
||||
|
||||
this.context = context;
|
||||
this.context = activity;
|
||||
this.activity = activity;
|
||||
this.prefs = prefs;
|
||||
this.crashListener = crashListener;
|
||||
this.consecutiveCrashCount = consecutiveCrashCount;
|
||||
@@ -266,6 +328,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
LimeLog.info("No HEVC decoder found");
|
||||
}
|
||||
|
||||
av1Decoder = findAv1Decoder(prefs);
|
||||
if (av1Decoder != null) {
|
||||
LimeLog.info("Selected AV1 decoder: "+av1Decoder.getName());
|
||||
}
|
||||
else {
|
||||
LimeLog.info("No AV1 decoder found");
|
||||
}
|
||||
|
||||
// Set attributes that are queried in getCapabilities(). This must be done here
|
||||
// because getCapabilities() may be called before setup() in current versions of the common
|
||||
// library. The limitation of this is that we don't know whether we're using HEVC or AVC.
|
||||
@@ -296,6 +366,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
LimeLog.info("Decoder "+hevcDecoder.getName()+" wants "+hevcOptimalSlicesPerFrame+" slices per frame");
|
||||
}
|
||||
|
||||
if (av1Decoder != null) {
|
||||
refFrameInvalidationAv1 = MediaCodecHelper.decoderSupportsRefFrameInvalidationAv1(av1Decoder);
|
||||
|
||||
if (refFrameInvalidationAv1) {
|
||||
LimeLog.info("Decoder "+av1Decoder.getName()+" will use reference frame invalidation for AV1");
|
||||
}
|
||||
}
|
||||
|
||||
// Use the larger of the two slices per frame preferences
|
||||
optimalSlicesPerFrame = (byte)Math.max(avcOptimalSlicesPerFrame, hevcOptimalSlicesPerFrame);
|
||||
LimeLog.info("Requesting "+optimalSlicesPerFrame+" slices per frame");
|
||||
@@ -329,6 +407,25 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAv1Supported() {
|
||||
return av1Decoder != null;
|
||||
}
|
||||
|
||||
public boolean isAv1Main10Supported() {
|
||||
if (av1Decoder == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (MediaCodecInfo.CodecProfileLevel profileLevel : av1Decoder.getCapabilitiesForType("video/av01").profileLevels) {
|
||||
if (profileLevel.profile == MediaCodecInfo.CodecProfileLevel.AV1ProfileMain10HDR10) {
|
||||
LimeLog.info("AV1 decoder "+av1Decoder.getName()+" supports AV1 Main 10 HDR10");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getPreferredColorSpace() {
|
||||
// Default to Rec 709 which is probably better supported on modern devices.
|
||||
//
|
||||
@@ -337,7 +434,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
// an HEVC decoder, we will use Rec 709 (even for H.264) since we can't choose a
|
||||
// colorspace by codec (and it's probably safe to say a SoC with HEVC decoding is
|
||||
// plenty modern enough to handle H.264 VUI colorspace info).
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || hevcDecoder != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O || hevcDecoder != null || av1Decoder != null) {
|
||||
return MoonBridge.COLORSPACE_REC_709;
|
||||
}
|
||||
else {
|
||||
@@ -447,10 +544,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
|
||||
// After reconfiguration, we must resubmit CSD buffers
|
||||
submittedCsd = false;
|
||||
submitCsdNextCall = false;
|
||||
vpsBuffer = null;
|
||||
spsBuffer = null;
|
||||
ppsBuffer = null;
|
||||
vpsBuffers.clear();
|
||||
spsBuffers.clear();
|
||||
ppsBuffers.clear();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// This will contain the actual accepted input format attributes
|
||||
@@ -548,6 +644,17 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
|
||||
refFrameInvalidationActive = refFrameInvalidationHevc;
|
||||
}
|
||||
else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_AV1) != 0) {
|
||||
mimeType = "video/av01";
|
||||
selectedDecoderInfo = av1Decoder;
|
||||
|
||||
if (av1Decoder == null) {
|
||||
LimeLog.severe("No available AV1 decoder!");
|
||||
return -2;
|
||||
}
|
||||
|
||||
refFrameInvalidationActive = refFrameInvalidationAv1;
|
||||
}
|
||||
else {
|
||||
// Unknown format
|
||||
LimeLog.severe("Unknown format");
|
||||
@@ -871,6 +978,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
frameTimeNanos -= activity.getWindowManager().getDefaultDisplay().getAppVsyncOffsetNanos();
|
||||
}
|
||||
|
||||
// Don't render unless a new frame is due. This prevents microstutter when streaming
|
||||
// at a frame rate that doesn't match the display (such as 60 FPS on 120 Hz).
|
||||
long actualFrameTimeDeltaNs = frameTimeNanos - lastRenderedFrameTimeNanos;
|
||||
@@ -1285,7 +1396,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||
int frameNumber, int frameType, long receiveTimeMs, long enqueueTimeMs) {
|
||||
int frameNumber, int frameType, char frameHostProcessingLatency,
|
||||
long receiveTimeMs, long enqueueTimeMs) {
|
||||
if (stopping) {
|
||||
// Don't bother if we're stopping
|
||||
return MoonBridge.DR_OK;
|
||||
@@ -1301,6 +1413,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
activeWindowVideoStats.frameLossEvents++;
|
||||
}
|
||||
|
||||
// Reset CSD data for each IDR frame
|
||||
if (lastFrameNumber != frameNumber && frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||
vpsBuffers.clear();
|
||||
spsBuffers.clear();
|
||||
ppsBuffers.clear();
|
||||
}
|
||||
|
||||
lastFrameNumber = frameNumber;
|
||||
|
||||
// Flip stats windows roughly every second
|
||||
@@ -1316,6 +1435,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
decoder = avcDecoder.getName();
|
||||
} else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) {
|
||||
decoder = hevcDecoder.getName();
|
||||
} else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_AV1) != 0) {
|
||||
decoder = av1Decoder.getName();
|
||||
} else {
|
||||
decoder = "(unknown)";
|
||||
}
|
||||
@@ -1331,6 +1452,12 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
(float)lastTwo.framesLost / lastTwo.totalFrames * 100)).append('\n');
|
||||
sb.append(context.getString(R.string.perf_overlay_netlatency,
|
||||
(int)(rttInfo >> 32), (int)rttInfo)).append('\n');
|
||||
if (lastTwo.framesWithHostProcessingLatency > 0) {
|
||||
sb.append(context.getString(R.string.perf_overlay_hostprocessinglatency,
|
||||
(float)lastTwo.minHostProcessingLatency / 10,
|
||||
(float)lastTwo.maxHostProcessingLatency / 10,
|
||||
(float)lastTwo.totalHostProcessingLatency / 10 / lastTwo.framesWithHostProcessingLatency)).append('\n');
|
||||
}
|
||||
sb.append(context.getString(R.string.perf_overlay_dectime, decodeTimeMs));
|
||||
perfListener.onPerfUpdate(sb.toString());
|
||||
}
|
||||
@@ -1341,236 +1468,270 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
activeWindowVideoStats.measurementStartTimestamp = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
long timestampUs;
|
||||
int codecFlags = 0;
|
||||
boolean csdSubmittedForThisFrame = false;
|
||||
|
||||
// H264 SPS
|
||||
if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS && (videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H264) != 0) {
|
||||
numSpsIn++;
|
||||
// IDR frames require special handling for CSD buffer submission
|
||||
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||
// H264 SPS
|
||||
if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS && (videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H264) != 0) {
|
||||
numSpsIn++;
|
||||
|
||||
ByteBuffer spsBuf = ByteBuffer.wrap(decodeUnitData);
|
||||
int startSeqLen = decodeUnitData[2] == 0x01 ? 3 : 4;
|
||||
ByteBuffer spsBuf = ByteBuffer.wrap(decodeUnitData);
|
||||
int startSeqLen = decodeUnitData[2] == 0x01 ? 3 : 4;
|
||||
|
||||
// Skip to the start of the NALU data
|
||||
spsBuf.position(startSeqLen + 1);
|
||||
// Skip to the start of the NALU data
|
||||
spsBuf.position(startSeqLen + 1);
|
||||
|
||||
// The H264Utils.readSPS function safely handles
|
||||
// Annex B NALUs (including NALUs with escape sequences)
|
||||
SeqParameterSet sps = H264Utils.readSPS(spsBuf);
|
||||
// The H264Utils.readSPS function safely handles
|
||||
// Annex B NALUs (including NALUs with escape sequences)
|
||||
SeqParameterSet sps = H264Utils.readSPS(spsBuf);
|
||||
|
||||
// Some decoders rely on H264 level to decide how many buffers are needed
|
||||
// Since we only need one frame buffered, we'll set the level as low as we can
|
||||
// for known resolution combinations. Reference frame invalidation may need
|
||||
// these, so leave them be for those decoders.
|
||||
if (!refFrameInvalidationActive) {
|
||||
if (initialWidth <= 720 && initialHeight <= 480 && refreshRate <= 60) {
|
||||
// Max 5 buffered frames at 720x480x60
|
||||
LimeLog.info("Patching level_idc to 31");
|
||||
sps.levelIdc = 31;
|
||||
}
|
||||
else if (initialWidth <= 1280 && initialHeight <= 720 && refreshRate <= 60) {
|
||||
// Max 5 buffered frames at 1280x720x60
|
||||
LimeLog.info("Patching level_idc to 32");
|
||||
sps.levelIdc = 32;
|
||||
}
|
||||
else if (initialWidth <= 1920 && initialHeight <= 1080 && refreshRate <= 60) {
|
||||
// Max 4 buffered frames at 1920x1080x64
|
||||
LimeLog.info("Patching level_idc to 42");
|
||||
sps.levelIdc = 42;
|
||||
}
|
||||
else {
|
||||
// Leave the profile alone (currently 5.0)
|
||||
}
|
||||
}
|
||||
|
||||
// TI OMAP4 requires a reference frame count of 1 to decode successfully. Exynos 4
|
||||
// also requires this fixup.
|
||||
//
|
||||
// I'm doing this fixup for all devices because I haven't seen any devices that
|
||||
// this causes issues for. At worst, it seems to do nothing and at best it fixes
|
||||
// issues with video lag, hangs, and crashes.
|
||||
//
|
||||
// It does break reference frame invalidation, so we will not do that for decoders
|
||||
// where we've enabled reference frame invalidation.
|
||||
if (!refFrameInvalidationActive) {
|
||||
LimeLog.info("Patching num_ref_frames in SPS");
|
||||
sps.numRefFrames = 1;
|
||||
}
|
||||
|
||||
// GFE 2.5.11 changed the SPS to add additional extensions. Some devices don't like these
|
||||
// so we remove them here on old devices unless these devices also support HEVC.
|
||||
// See getPreferredColorSpace() for further information.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && hevcDecoder == null && sps.vuiParams != null) {
|
||||
sps.vuiParams.videoSignalTypePresentFlag = false;
|
||||
sps.vuiParams.colourDescriptionPresentFlag = false;
|
||||
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
||||
}
|
||||
|
||||
// Some older devices used to choke on a bitstream restrictions, so we won't provide them
|
||||
// unless explicitly whitelisted. For newer devices, leave the bitstream restrictions present.
|
||||
if (needsSpsBitstreamFixup || isExynos4 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// The SPS that comes in the current H264 bytestream doesn't set bitstream_restriction_flag
|
||||
// or max_dec_frame_buffering which increases decoding latency on Tegra.
|
||||
|
||||
// If the encoder didn't include VUI parameters in the SPS, add them now
|
||||
if (sps.vuiParams == null) {
|
||||
LimeLog.info("Adding VUI parameters");
|
||||
sps.vuiParams = new VUIParameters();
|
||||
// Some decoders rely on H264 level to decide how many buffers are needed
|
||||
// Since we only need one frame buffered, we'll set the level as low as we can
|
||||
// for known resolution combinations. Reference frame invalidation may need
|
||||
// these, so leave them be for those decoders.
|
||||
if (!refFrameInvalidationActive) {
|
||||
if (initialWidth <= 720 && initialHeight <= 480 && refreshRate <= 60) {
|
||||
// Max 5 buffered frames at 720x480x60
|
||||
LimeLog.info("Patching level_idc to 31");
|
||||
sps.levelIdc = 31;
|
||||
}
|
||||
else if (initialWidth <= 1280 && initialHeight <= 720 && refreshRate <= 60) {
|
||||
// Max 5 buffered frames at 1280x720x60
|
||||
LimeLog.info("Patching level_idc to 32");
|
||||
sps.levelIdc = 32;
|
||||
}
|
||||
else if (initialWidth <= 1920 && initialHeight <= 1080 && refreshRate <= 60) {
|
||||
// Max 4 buffered frames at 1920x1080x64
|
||||
LimeLog.info("Patching level_idc to 42");
|
||||
sps.levelIdc = 42;
|
||||
}
|
||||
else {
|
||||
// Leave the profile alone (currently 5.0)
|
||||
}
|
||||
}
|
||||
|
||||
// GFE 2.5.11 started sending bitstream restrictions
|
||||
if (sps.vuiParams.bitstreamRestriction == null) {
|
||||
LimeLog.info("Adding bitstream restrictions");
|
||||
sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
|
||||
sps.vuiParams.bitstreamRestriction.motionVectorsOverPicBoundariesFlag = true;
|
||||
sps.vuiParams.bitstreamRestriction.maxBytesPerPicDenom = 2;
|
||||
sps.vuiParams.bitstreamRestriction.maxBitsPerMbDenom = 1;
|
||||
sps.vuiParams.bitstreamRestriction.log2MaxMvLengthHorizontal = 16;
|
||||
sps.vuiParams.bitstreamRestriction.log2MaxMvLengthVertical = 16;
|
||||
sps.vuiParams.bitstreamRestriction.numReorderFrames = 0;
|
||||
}
|
||||
else {
|
||||
LimeLog.info("Patching bitstream restrictions");
|
||||
// TI OMAP4 requires a reference frame count of 1 to decode successfully. Exynos 4
|
||||
// also requires this fixup.
|
||||
//
|
||||
// I'm doing this fixup for all devices because I haven't seen any devices that
|
||||
// this causes issues for. At worst, it seems to do nothing and at best it fixes
|
||||
// issues with video lag, hangs, and crashes.
|
||||
//
|
||||
// It does break reference frame invalidation, so we will not do that for decoders
|
||||
// where we've enabled reference frame invalidation.
|
||||
if (!refFrameInvalidationActive) {
|
||||
LimeLog.info("Patching num_ref_frames in SPS");
|
||||
sps.numRefFrames = 1;
|
||||
}
|
||||
|
||||
// Some devices throw errors if maxDecFrameBuffering < numRefFrames
|
||||
sps.vuiParams.bitstreamRestriction.maxDecFrameBuffering = sps.numRefFrames;
|
||||
|
||||
// These values are the defaults for the fields, but they are more aggressive
|
||||
// than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems.
|
||||
// We'll leave these alone for "modern" devices just in case they care.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
sps.vuiParams.bitstreamRestriction.maxBytesPerPicDenom = 2;
|
||||
sps.vuiParams.bitstreamRestriction.maxBitsPerMbDenom = 1;
|
||||
// GFE 2.5.11 changed the SPS to add additional extensions. Some devices don't like these
|
||||
// so we remove them here on old devices unless these devices also support HEVC.
|
||||
// See getPreferredColorSpace() for further information.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O &&
|
||||
sps.vuiParams != null &&
|
||||
hevcDecoder == null &&
|
||||
av1Decoder == null) {
|
||||
sps.vuiParams.videoSignalTypePresentFlag = false;
|
||||
sps.vuiParams.colourDescriptionPresentFlag = false;
|
||||
sps.vuiParams.chromaLocInfoPresentFlag = false;
|
||||
}
|
||||
|
||||
// log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more
|
||||
// conservative values by GFE 2.5.11. We'll let those values stand.
|
||||
}
|
||||
else if (sps.vuiParams != null) {
|
||||
// Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11
|
||||
// will continue to not receive them now
|
||||
sps.vuiParams.bitstreamRestriction = null;
|
||||
}
|
||||
// Some older devices used to choke on a bitstream restrictions, so we won't provide them
|
||||
// unless explicitly whitelisted. For newer devices, leave the bitstream restrictions present.
|
||||
if (needsSpsBitstreamFixup || isExynos4 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// The SPS that comes in the current H264 bytestream doesn't set bitstream_restriction_flag
|
||||
// or max_dec_frame_buffering which increases decoding latency on Tegra.
|
||||
|
||||
// If we need to hack this SPS to say we're baseline, do so now
|
||||
if (needsBaselineSpsHack) {
|
||||
LimeLog.info("Hacking SPS to baseline");
|
||||
sps.profileIdc = 66;
|
||||
savedSps = sps;
|
||||
}
|
||||
// If the encoder didn't include VUI parameters in the SPS, add them now
|
||||
if (sps.vuiParams == null) {
|
||||
LimeLog.info("Adding VUI parameters");
|
||||
sps.vuiParams = new VUIParameters();
|
||||
}
|
||||
|
||||
// Patch the SPS constraint flags
|
||||
doProfileSpecificSpsPatching(sps);
|
||||
// GFE 2.5.11 started sending bitstream restrictions
|
||||
if (sps.vuiParams.bitstreamRestriction == null) {
|
||||
LimeLog.info("Adding bitstream restrictions");
|
||||
sps.vuiParams.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
|
||||
sps.vuiParams.bitstreamRestriction.motionVectorsOverPicBoundariesFlag = true;
|
||||
sps.vuiParams.bitstreamRestriction.maxBytesPerPicDenom = 2;
|
||||
sps.vuiParams.bitstreamRestriction.maxBitsPerMbDenom = 1;
|
||||
sps.vuiParams.bitstreamRestriction.log2MaxMvLengthHorizontal = 16;
|
||||
sps.vuiParams.bitstreamRestriction.log2MaxMvLengthVertical = 16;
|
||||
sps.vuiParams.bitstreamRestriction.numReorderFrames = 0;
|
||||
}
|
||||
else {
|
||||
LimeLog.info("Patching bitstream restrictions");
|
||||
}
|
||||
|
||||
// The H264Utils.writeSPS function safely handles
|
||||
// Annex B NALUs (including NALUs with escape sequences)
|
||||
ByteBuffer escapedNalu = H264Utils.writeSPS(sps, decodeUnitLength);
|
||||
// Some devices throw errors if maxDecFrameBuffering < numRefFrames
|
||||
sps.vuiParams.bitstreamRestriction.maxDecFrameBuffering = sps.numRefFrames;
|
||||
|
||||
// Batch this to submit together with PPS
|
||||
spsBuffer = new byte[startSeqLen + 1 + escapedNalu.limit()];
|
||||
System.arraycopy(decodeUnitData, 0, spsBuffer, 0, startSeqLen + 1);
|
||||
escapedNalu.get(spsBuffer, startSeqLen + 1, escapedNalu.limit());
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_VPS) {
|
||||
numVpsIn++;
|
||||
// These values are the defaults for the fields, but they are more aggressive
|
||||
// than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems.
|
||||
// We'll leave these alone for "modern" devices just in case they care.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
sps.vuiParams.bitstreamRestriction.maxBytesPerPicDenom = 2;
|
||||
sps.vuiParams.bitstreamRestriction.maxBitsPerMbDenom = 1;
|
||||
}
|
||||
|
||||
// Batch this to submit together with SPS and PPS per AOSP docs
|
||||
vpsBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, vpsBuffer, 0, decodeUnitLength);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
// Only the HEVC SPS hits this path (H.264 is handled above)
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS) {
|
||||
numSpsIn++;
|
||||
|
||||
// Batch this to submit together with VPS and PPS per AOSP docs
|
||||
spsBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, spsBuffer, 0, decodeUnitLength);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
||||
numPpsIn++;
|
||||
|
||||
// If this is the first CSD blob or we aren't supporting
|
||||
// fused IDR frames, we will submit the CSD blob in a
|
||||
// separate input buffer.
|
||||
if (!submittedCsd || !fusedIdrFrame) {
|
||||
if (!fetchNextInputBuffer()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
// log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more
|
||||
// conservative values by GFE 2.5.11. We'll let those values stand.
|
||||
}
|
||||
else if (sps.vuiParams != null) {
|
||||
// Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11
|
||||
// will continue to not receive them now
|
||||
sps.vuiParams.bitstreamRestriction = null;
|
||||
}
|
||||
|
||||
// When we get the PPS, submit the VPS and SPS together with
|
||||
// the PPS, as required by AOSP docs on use of MediaCodec.
|
||||
if (vpsBuffer != null) {
|
||||
nextInputBuffer.put(vpsBuffer);
|
||||
}
|
||||
if (spsBuffer != null) {
|
||||
nextInputBuffer.put(spsBuffer);
|
||||
// If we need to hack this SPS to say we're baseline, do so now
|
||||
if (needsBaselineSpsHack) {
|
||||
LimeLog.info("Hacking SPS to baseline");
|
||||
sps.profileIdc = 66;
|
||||
savedSps = sps;
|
||||
}
|
||||
|
||||
// This is the CSD blob
|
||||
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
|
||||
timestampUs = 0;
|
||||
}
|
||||
else {
|
||||
// Batch this to submit together with the next I-frame
|
||||
ppsBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, ppsBuffer, 0, decodeUnitLength);
|
||||
// Patch the SPS constraint flags
|
||||
doProfileSpecificSpsPatching(sps);
|
||||
|
||||
// Next call will be I-frame data
|
||||
submitCsdNextCall = true;
|
||||
// The H264Utils.writeSPS function safely handles
|
||||
// Annex B NALUs (including NALUs with escape sequences)
|
||||
ByteBuffer escapedNalu = H264Utils.writeSPS(sps, decodeUnitLength);
|
||||
|
||||
// Construct the patched SPS
|
||||
byte[] naluBuffer = new byte[startSeqLen + 1 + escapedNalu.limit()];
|
||||
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, startSeqLen + 1);
|
||||
escapedNalu.get(naluBuffer, startSeqLen + 1, escapedNalu.limit());
|
||||
|
||||
// Batch this to submit together with other CSD per AOSP docs
|
||||
spsBuffers.add(naluBuffer);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_VPS) {
|
||||
numVpsIn++;
|
||||
|
||||
// Batch this to submit together with other CSD per AOSP docs
|
||||
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||
vpsBuffers.add(naluBuffer);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
// Only the HEVC SPS hits this path (H.264 is handled above)
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS) {
|
||||
numSpsIn++;
|
||||
|
||||
// Batch this to submit together with other CSD per AOSP docs
|
||||
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||
spsBuffers.add(naluBuffer);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
||||
numPpsIn++;
|
||||
|
||||
// Batch this to submit together with other CSD per AOSP docs
|
||||
byte[] naluBuffer = new byte[decodeUnitLength];
|
||||
System.arraycopy(decodeUnitData, 0, naluBuffer, 0, decodeUnitLength);
|
||||
ppsBuffers.add(naluBuffer);
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
else if ((videoFormat & (MoonBridge.VIDEO_FORMAT_MASK_H264 | MoonBridge.VIDEO_FORMAT_MASK_H265)) != 0) {
|
||||
// If this is the first CSD blob or we aren't supporting fused IDR frames, we will
|
||||
// submit the CSD blob in a separate input buffer for each IDR frame.
|
||||
if (!submittedCsd || !fusedIdrFrame) {
|
||||
if (!fetchNextInputBuffer()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
// Submit all CSD when we receive the first non-CSD blob in an IDR frame
|
||||
for (byte[] vpsBuffer : vpsBuffers) {
|
||||
nextInputBuffer.put(vpsBuffer);
|
||||
}
|
||||
for (byte[] spsBuffer : spsBuffers) {
|
||||
nextInputBuffer.put(spsBuffer);
|
||||
}
|
||||
for (byte[] ppsBuffer : ppsBuffers) {
|
||||
nextInputBuffer.put(ppsBuffer);
|
||||
}
|
||||
|
||||
if (!queueNextInputBuffer(0, MediaCodec.BUFFER_FLAG_CODEC_CONFIG)) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
// Remember that we already submitted CSD for this frame, so we don't do it
|
||||
// again in the fused IDR case below.
|
||||
csdSubmittedForThisFrame = true;
|
||||
|
||||
// Remember that we submitted CSD globally for this MediaCodec instance
|
||||
submittedCsd = true;
|
||||
|
||||
if (needsBaselineSpsHack) {
|
||||
needsBaselineSpsHack = false;
|
||||
|
||||
if (!replaySps()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
LimeLog.info("SPS replay complete");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
activeWindowVideoStats.totalFramesReceived++;
|
||||
activeWindowVideoStats.totalFrames++;
|
||||
|
||||
if (!FRAME_RENDER_TIME_ONLY) {
|
||||
// Count time from first packet received to enqueue time as receive time
|
||||
// We will count DU queue time as part of decoding, because it is directly
|
||||
// caused by a slow decoder.
|
||||
activeWindowVideoStats.totalTimeMs += enqueueTimeMs - receiveTimeMs;
|
||||
if (frameHostProcessingLatency != 0) {
|
||||
if (activeWindowVideoStats.minHostProcessingLatency != 0) {
|
||||
activeWindowVideoStats.minHostProcessingLatency = (char) Math.min(activeWindowVideoStats.minHostProcessingLatency, frameHostProcessingLatency);
|
||||
} else {
|
||||
activeWindowVideoStats.minHostProcessingLatency = frameHostProcessingLatency;
|
||||
}
|
||||
activeWindowVideoStats.framesWithHostProcessingLatency += 1;
|
||||
}
|
||||
activeWindowVideoStats.maxHostProcessingLatency = (char) Math.max(activeWindowVideoStats.maxHostProcessingLatency, frameHostProcessingLatency);
|
||||
activeWindowVideoStats.totalHostProcessingLatency += frameHostProcessingLatency;
|
||||
|
||||
if (!fetchNextInputBuffer()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
activeWindowVideoStats.totalFramesReceived++;
|
||||
activeWindowVideoStats.totalFrames++;
|
||||
|
||||
if (submitCsdNextCall) {
|
||||
if (vpsBuffer != null) {
|
||||
if (!FRAME_RENDER_TIME_ONLY) {
|
||||
// Count time from first packet received to enqueue time as receive time
|
||||
// We will count DU queue time as part of decoding, because it is directly
|
||||
// caused by a slow decoder.
|
||||
activeWindowVideoStats.totalTimeMs += enqueueTimeMs - receiveTimeMs;
|
||||
}
|
||||
|
||||
if (!fetchNextInputBuffer()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
int codecFlags = 0;
|
||||
|
||||
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
|
||||
|
||||
// If we are using fused IDR frames, submit the CSD with each IDR frame
|
||||
if (fusedIdrFrame && !csdSubmittedForThisFrame) {
|
||||
for (byte[] vpsBuffer : vpsBuffers) {
|
||||
nextInputBuffer.put(vpsBuffer);
|
||||
}
|
||||
if (spsBuffer != null) {
|
||||
for (byte[] spsBuffer : spsBuffers) {
|
||||
nextInputBuffer.put(spsBuffer);
|
||||
}
|
||||
if (ppsBuffer != null) {
|
||||
for (byte[] ppsBuffer : ppsBuffers) {
|
||||
nextInputBuffer.put(ppsBuffer);
|
||||
}
|
||||
|
||||
submitCsdNextCall = false;
|
||||
}
|
||||
|
||||
if (frameType == MoonBridge.FRAME_TYPE_IDR) {
|
||||
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
|
||||
}
|
||||
|
||||
timestampUs = enqueueTimeMs * 1000;
|
||||
|
||||
if (timestampUs <= lastTimestampUs) {
|
||||
// We can't submit multiple buffers with the same timestamp
|
||||
// so bump it up by one before queuing
|
||||
timestampUs = lastTimestampUs + 1;
|
||||
}
|
||||
|
||||
lastTimestampUs = timestampUs;
|
||||
|
||||
numFramesIn++;
|
||||
}
|
||||
|
||||
long timestampUs = enqueueTimeMs * 1000;
|
||||
if (timestampUs <= lastTimestampUs) {
|
||||
// We can't submit multiple buffers with the same timestamp
|
||||
// so bump it up by one before queuing
|
||||
timestampUs = lastTimestampUs + 1;
|
||||
}
|
||||
lastTimestampUs = timestampUs;
|
||||
|
||||
numFramesIn++;
|
||||
|
||||
if (decodeUnitLength > nextInputBuffer.limit() - nextInputBuffer.position()) {
|
||||
IllegalArgumentException exception = new IllegalArgumentException(
|
||||
"Decode unit length "+decodeUnitLength+" too large for input buffer "+nextInputBuffer.limit());
|
||||
@@ -1588,20 +1749,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
if ((codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
||||
submittedCsd = true;
|
||||
|
||||
if (needsBaselineSpsHack) {
|
||||
needsBaselineSpsHack = false;
|
||||
|
||||
if (!replaySps()) {
|
||||
return MoonBridge.DR_NEED_IDR;
|
||||
}
|
||||
|
||||
LimeLog.info("SPS replay complete");
|
||||
}
|
||||
}
|
||||
|
||||
return MoonBridge.DR_OK;
|
||||
}
|
||||
|
||||
@@ -1645,6 +1792,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
if (refFrameInvalidationHevc) {
|
||||
capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC;
|
||||
}
|
||||
if (refFrameInvalidationAv1) {
|
||||
capabilities |= MoonBridge.CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1;
|
||||
}
|
||||
|
||||
// Enable direct submit on supported hardware
|
||||
if (directSubmit) {
|
||||
@@ -1727,6 +1877,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
str += "Format: "+String.format("%x", renderer.videoFormat)+DELIMITER;
|
||||
str += "AVC Decoder: "+((renderer.avcDecoder != null) ? renderer.avcDecoder.getName():"(none)")+DELIMITER;
|
||||
str += "HEVC Decoder: "+((renderer.hevcDecoder != null) ? renderer.hevcDecoder.getName():"(none)")+DELIMITER;
|
||||
str += "AV1 Decoder: "+((renderer.av1Decoder != null) ? renderer.av1Decoder.getName():"(none)")+DELIMITER;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && renderer.avcDecoder != null) {
|
||||
Range<Integer> avcWidthRange = renderer.avcDecoder.getCapabilitiesForType("video/avc").getVideoCapabilities().getSupportedWidths();
|
||||
str += "AVC supported width range: "+avcWidthRange+DELIMITER;
|
||||
@@ -1751,6 +1902,18 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && renderer.av1Decoder != null) {
|
||||
Range<Integer> av1WidthRange = renderer.av1Decoder.getCapabilitiesForType("video/av01").getVideoCapabilities().getSupportedWidths();
|
||||
str += "AV1 supported width range: "+av1WidthRange+DELIMITER;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
try {
|
||||
Range<Double> av1FpsRange = renderer.av1Decoder.getCapabilitiesForType("video/av01").getVideoCapabilities().getAchievableFrameRatesFor(renderer.initialWidth, renderer.initialHeight);
|
||||
str += "AV1 achievable FPS range: " + av1FpsRange + DELIMITER;
|
||||
} catch (IllegalArgumentException e) {
|
||||
str += "AV1 achievable FPS range: UNSUPPORTED!"+DELIMITER;
|
||||
}
|
||||
}
|
||||
}
|
||||
str += "Configured format: "+renderer.configuredFormat+DELIMITER;
|
||||
str += "Input format: "+renderer.inputFormat+DELIMITER;
|
||||
str += "Output format: "+renderer.outputFormat+DELIMITER;
|
||||
|
||||
@@ -529,6 +529,17 @@ public class MediaCodecHelper {
|
||||
setNewOption = true;
|
||||
}
|
||||
|
||||
if (tryNumber < 3) {
|
||||
if (MediaCodecHelper.decoderSupportsMaxOperatingRate(decoderInfo.getName())) {
|
||||
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
|
||||
setNewOption = true;
|
||||
}
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
videoFormat.setInteger(MediaFormat.KEY_PRIORITY, 0);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
// MediaCodec supports vendor-defined format keys using the "vendor.<extension name>.<parameter name>" syntax.
|
||||
// These allow access to functionality that is not exposed through documented MediaFormat.KEY_* values.
|
||||
// https://cs.android.com/android/platform/superproject/+/master:hardware/qcom/sdm845/media/mm-video-v4l2/vidc/common/inc/vidc_vendor_extensions.h;l=67
|
||||
@@ -545,17 +556,17 @@ public class MediaCodecHelper {
|
||||
// https://cs.android.com/android/_/android/platform/hardware/qcom/sm8150/media/+/0621ceb1c1b19564999db8293574a0e12952ff6c
|
||||
//
|
||||
// We will first try both, then try vendor.qti-ext-dec-low-latency.enable alone if that fails
|
||||
if (tryNumber < 3) {
|
||||
if (tryNumber < 4) {
|
||||
videoFormat.setInteger("vendor.qti-ext-dec-picture-order.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
if (tryNumber < 4) {
|
||||
if (tryNumber < 5) {
|
||||
videoFormat.setInteger("vendor.qti-ext-dec-low-latency.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(kirinDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
if (tryNumber < 4) {
|
||||
// Kirin low latency options
|
||||
// https://developer.huawei.com/consumer/cn/forum/topic/0202325564295980115
|
||||
videoFormat.setInteger("vendor.hisi-ext-low-latency-video-dec.video-scene-for-low-latency-req", 1);
|
||||
@@ -564,14 +575,14 @@ public class MediaCodecHelper {
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(exynosDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
if (tryNumber < 4) {
|
||||
// Exynos low latency option for H.264 decoder
|
||||
videoFormat.setInteger("vendor.rtc-ext-dec-low-latency.enable", 1);
|
||||
setNewOption = true;
|
||||
}
|
||||
}
|
||||
else if (isDecoderInList(amlogicDecoderPrefixes, decoderInfo.getName())) {
|
||||
if (tryNumber < 3) {
|
||||
if (tryNumber < 4) {
|
||||
// Amlogic low latency vendor extension
|
||||
// https://github.com/codewalkerster/android_vendor_amlogic_common_prebuilt_libstagefrighthw/commit/41fefc4e035c476d58491324a5fe7666bfc2989e
|
||||
videoFormat.setInteger("vendor.low-latency.enable", 1);
|
||||
@@ -580,11 +591,6 @@ public class MediaCodecHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: We should probably integrate this into the try system
|
||||
if (MediaCodecHelper.decoderSupportsMaxOperatingRate(decoderInfo.getName())) {
|
||||
videoFormat.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
|
||||
}
|
||||
|
||||
return setNewOption;
|
||||
}
|
||||
|
||||
@@ -691,6 +697,17 @@ public class MediaCodecHelper {
|
||||
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderInfo.getName());
|
||||
}
|
||||
|
||||
public static boolean decoderSupportsRefFrameInvalidationAv1(MediaCodecInfo decoderInfo) {
|
||||
// We'll use the same heuristics as HEVC for now
|
||||
if (decoderSupportsAndroidRLowLatency(decoderInfo, "video/av01") ||
|
||||
decoderSupportsKnownVendorLowLatencyOption(decoderInfo.getName())) {
|
||||
LimeLog.info("Enabling AV1 RFI based on low latency option support");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -736,7 +753,33 @@ public class MediaCodecHelper {
|
||||
// Otherwise, we use our list of known working HEVC decoders
|
||||
return isDecoderInList(whitelistedHevcDecoders, decoderInfo.getName());
|
||||
}
|
||||
|
||||
|
||||
public static boolean isDecoderWhitelistedForAv1(MediaCodecInfo decoderInfo) {
|
||||
// Google didn't have official support for AV1 (or more importantly, a CTS test) until
|
||||
// Android 10, so don't use any decoder before then.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Software decoders are terrible and we never want to use them.
|
||||
// We want to catch decoders like:
|
||||
// OMX.qcom.video.decoder.hevcswvdec
|
||||
// OMX.SEC.hevc.sw.dec
|
||||
//
|
||||
if (decoderInfo.getName().contains("sw")) {
|
||||
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
|
||||
return false;
|
||||
}
|
||||
else if (!decoderInfo.isHardwareAccelerated() || decoderInfo.isSoftwareOnly()) {
|
||||
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Test some AV1 decoders
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressLint("NewApi")
|
||||
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
|
||||
|
||||
@@ -11,6 +11,10 @@ class VideoStats {
|
||||
int totalFramesRendered;
|
||||
int frameLossEvents;
|
||||
int framesLost;
|
||||
char minHostProcessingLatency;
|
||||
char maxHostProcessingLatency;
|
||||
int totalHostProcessingLatency;
|
||||
int framesWithHostProcessingLatency;
|
||||
long measurementStartTimestamp;
|
||||
|
||||
void add(VideoStats other) {
|
||||
@@ -22,6 +26,15 @@ class VideoStats {
|
||||
this.frameLossEvents += other.frameLossEvents;
|
||||
this.framesLost += other.framesLost;
|
||||
|
||||
if (this.minHostProcessingLatency == 0) {
|
||||
this.minHostProcessingLatency = other.minHostProcessingLatency;
|
||||
} else {
|
||||
this.minHostProcessingLatency = (char) Math.min(this.minHostProcessingLatency, other.minHostProcessingLatency);
|
||||
}
|
||||
this.maxHostProcessingLatency = (char) Math.max(this.maxHostProcessingLatency, other.maxHostProcessingLatency);
|
||||
this.totalHostProcessingLatency += other.totalHostProcessingLatency;
|
||||
this.framesWithHostProcessingLatency += other.framesWithHostProcessingLatency;
|
||||
|
||||
if (this.measurementStartTimestamp == 0) {
|
||||
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
||||
}
|
||||
@@ -37,6 +50,10 @@ class VideoStats {
|
||||
this.totalFramesRendered = other.totalFramesRendered;
|
||||
this.frameLossEvents = other.frameLossEvents;
|
||||
this.framesLost = other.framesLost;
|
||||
this.minHostProcessingLatency = other.minHostProcessingLatency;
|
||||
this.maxHostProcessingLatency = other.maxHostProcessingLatency;
|
||||
this.totalHostProcessingLatency = other.totalHostProcessingLatency;
|
||||
this.framesWithHostProcessingLatency = other.framesWithHostProcessingLatency;
|
||||
this.measurementStartTimestamp = other.measurementStartTimestamp;
|
||||
}
|
||||
|
||||
@@ -48,6 +65,10 @@ class VideoStats {
|
||||
this.totalFramesRendered = 0;
|
||||
this.frameLossEvents = 0;
|
||||
this.framesLost = 0;
|
||||
this.minHostProcessingLatency = 0;
|
||||
this.maxHostProcessingLatency = 0;
|
||||
this.totalHostProcessingLatency = 0;
|
||||
this.framesWithHostProcessingLatency = 0;
|
||||
this.measurementStartTimestamp = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,22 +3,21 @@ package com.limelight.discovery;
|
||||
import java.util.List;
|
||||
|
||||
import com.limelight.nvstream.mdns.MdnsComputer;
|
||||
import com.limelight.nvstream.mdns.JmDNSDiscoveryAgent;
|
||||
import com.limelight.nvstream.mdns.MdnsDiscoveryAgent;
|
||||
import com.limelight.nvstream.mdns.MdnsDiscoveryListener;
|
||||
import com.limelight.nvstream.mdns.NsdManagerDiscoveryAgent;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.WifiManager.MulticastLock;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class DiscoveryService extends Service {
|
||||
|
||||
private MdnsDiscoveryAgent discoveryAgent;
|
||||
private MdnsDiscoveryListener boundListener;
|
||||
private MulticastLock multicastLock;
|
||||
|
||||
public class DiscoveryBinder extends Binder {
|
||||
public void setListener(MdnsDiscoveryListener listener) {
|
||||
@@ -26,13 +25,11 @@ public class DiscoveryService extends Service {
|
||||
}
|
||||
|
||||
public void startDiscovery(int queryIntervalMs) {
|
||||
multicastLock.acquire();
|
||||
discoveryAgent.startDiscovery(queryIntervalMs);
|
||||
}
|
||||
|
||||
public void stopDiscovery() {
|
||||
discoveryAgent.stopDiscovery();
|
||||
multicastLock.release();
|
||||
}
|
||||
|
||||
public List<MdnsComputer> getComputerSet() {
|
||||
@@ -42,11 +39,7 @@ public class DiscoveryService extends Service {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
WifiManager wifiMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
multicastLock = wifiMgr.createMulticastLock("Limelight mDNS");
|
||||
multicastLock.setReferenceCounted(false);
|
||||
|
||||
discoveryAgent = new MdnsDiscoveryAgent(new MdnsDiscoveryListener() {
|
||||
MdnsDiscoveryListener listener = new MdnsDiscoveryListener() {
|
||||
@Override
|
||||
public void notifyComputerAdded(MdnsComputer computer) {
|
||||
if (boundListener != null) {
|
||||
@@ -60,7 +53,22 @@ public class DiscoveryService extends Service {
|
||||
boundListener.notifyDiscoveryFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Prior to Android 14, NsdManager doesn't provide all the capabilities needed for parity
|
||||
// with jmDNS (specifically handling multiple addresses for a single service). There are
|
||||
// also documented reliability bugs early in the Android 4.x series shortly after it was
|
||||
// introduced. The benefit of using NsdManager over jmDNS is that it works correctly in
|
||||
// environments where mDNS proxying is required, like ChromeOS, WSA, and the emulator.
|
||||
//
|
||||
// As such, we use the jmDNS-based MdnsDiscoveryAgent prior to Android 14 and NsdManager
|
||||
// on Android 14 and above.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
discoveryAgent = new JmDNSDiscoveryAgent(getApplicationContext(), listener);
|
||||
}
|
||||
else {
|
||||
discoveryAgent = new NsdManagerDiscoveryAgent(getApplicationContext(), listener);
|
||||
}
|
||||
}
|
||||
|
||||
private final DiscoveryBinder binder = new DiscoveryBinder();
|
||||
@@ -74,7 +82,6 @@ public class DiscoveryService extends Service {
|
||||
public boolean onUnbind(Intent intent) {
|
||||
// Stop any discovery session
|
||||
discoveryAgent.stopDiscovery();
|
||||
multicastLock.release();
|
||||
|
||||
// Unbind the listener
|
||||
boundListener = null;
|
||||
|
||||
@@ -19,6 +19,7 @@ public class ConnectionContext {
|
||||
// This is the version quad from the appversion tag of /serverinfo
|
||||
public String serverAppVersion;
|
||||
public String serverGfeVersion;
|
||||
public int serverCodecModeSupport;
|
||||
|
||||
// This is the sessionUrl0 tag from /resume and /launch
|
||||
public String rtspSessionUrl;
|
||||
|
||||
@@ -242,9 +242,11 @@ public class NvConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
context.negotiatedHdr = context.streamConfig.getEnableHdr();
|
||||
if ((h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.negotiatedHdr) {
|
||||
context.connListener.displayTransientMessage("Your GPU does not support streaming HDR. The stream will be SDR.");
|
||||
context.serverCodecModeSupport = (int)h.getServerCodecModeSupport(serverInfo);
|
||||
|
||||
context.negotiatedHdr = (context.streamConfig.getSupportedVideoFormats() & MoonBridge.VIDEO_FORMAT_MASK_10BIT) != 0;
|
||||
if ((context.serverCodecModeSupport & 0x20200) == 0 && context.negotiatedHdr) {
|
||||
context.connListener.displayTransientMessage("Your PC GPU does not support streaming HDR. The stream will be SDR.");
|
||||
context.negotiatedHdr = false;
|
||||
}
|
||||
|
||||
@@ -254,13 +256,13 @@ public class NvConnection {
|
||||
|
||||
// Check for a supported stream resolution
|
||||
if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
||||
(h.getServerCodecModeSupport(serverInfo) & 0x200) == 0) {
|
||||
(h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.isNvidiaServerSoftware) {
|
||||
context.connListener.displayMessage("Your host PC does not support streaming at resolutions above 4K.");
|
||||
return false;
|
||||
}
|
||||
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
|
||||
!context.streamConfig.getHevcSupported()) {
|
||||
context.connListener.displayMessage("Your streaming device must support HEVC to stream at resolutions above 4K.");
|
||||
(context.streamConfig.getSupportedVideoFormats() & ~MoonBridge.VIDEO_FORMAT_MASK_H264) == 0) {
|
||||
context.connListener.displayMessage("Your streaming device must support HEVC or AV1 to stream at resolutions above 4K.");
|
||||
return false;
|
||||
}
|
||||
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
|
||||
@@ -425,13 +427,14 @@ public class NvConnection {
|
||||
MoonBridge.setupBridge(videoDecoderRenderer, audioRenderer, connectionListener);
|
||||
int ret = MoonBridge.startConnection(context.serverAddress.address,
|
||||
context.serverAppVersion, context.serverGfeVersion, context.rtspSessionUrl,
|
||||
context.serverCodecModeSupport,
|
||||
context.negotiatedWidth, context.negotiatedHeight,
|
||||
context.streamConfig.getRefreshRate(), context.streamConfig.getBitrate(),
|
||||
context.negotiatedPacketSize, context.negotiatedRemoteStreaming,
|
||||
context.streamConfig.getAudioConfiguration().toInt(),
|
||||
context.streamConfig.getHevcSupported(),
|
||||
context.negotiatedHdr,
|
||||
context.streamConfig.getSupportedVideoFormats(),
|
||||
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
||||
context.streamConfig.getAv1BitratePercentageMultiplier(),
|
||||
context.streamConfig.getClientRefreshRateX100(),
|
||||
context.streamConfig.getEncryptionFlags(),
|
||||
context.riKey.getEncoded(), ib.array(),
|
||||
@@ -486,7 +489,7 @@ public class NvConnection {
|
||||
}
|
||||
|
||||
public void sendControllerInput(final short controllerNumber,
|
||||
final short activeGamepadMask, final short buttonFlags,
|
||||
final short activeGamepadMask, final int buttonFlags,
|
||||
final byte leftTrigger, final byte rightTrigger,
|
||||
final short leftStickX, final short leftStickY,
|
||||
final short rightStickX, final short rightStickY)
|
||||
@@ -496,18 +499,7 @@ public class NvConnection {
|
||||
leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendControllerInput(final short buttonFlags,
|
||||
final byte leftTrigger, final byte rightTrigger,
|
||||
final short leftStickX, final short leftStickY,
|
||||
final short rightStickX, final short rightStickY)
|
||||
{
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendControllerInput(buttonFlags, leftTrigger, rightTrigger, leftStickX,
|
||||
leftStickY, rightStickX, rightStickY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendKeyboardInput(final short keyMap, final byte keyDirection, final byte modifier, final byte flags) {
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendKeyboardInput(keyMap, keyDirection, modifier, flags);
|
||||
@@ -538,6 +530,58 @@ public class NvConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressureOrDistance,
|
||||
float contactAreaMajor, float contactAreaMinor, short rotation) {
|
||||
if (!isMonkey) {
|
||||
return MoonBridge.sendTouchEvent(eventType, pointerId, x, y, pressureOrDistance,
|
||||
contactAreaMajor, contactAreaMinor, rotation);
|
||||
}
|
||||
else {
|
||||
return MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
|
||||
float pressureOrDistance, float contactAreaMajor, float contactAreaMinor,
|
||||
short rotation, byte tilt) {
|
||||
if (!isMonkey) {
|
||||
return MoonBridge.sendPenEvent(eventType, toolType, penButtons, x, y, pressureOrDistance,
|
||||
contactAreaMajor, contactAreaMinor, rotation, tilt);
|
||||
}
|
||||
else {
|
||||
return MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type,
|
||||
int supportedButtonFlags, short capabilities) {
|
||||
return MoonBridge.sendControllerArrivalEvent(controllerNumber, activeGamepadMask, type, supportedButtonFlags, capabilities);
|
||||
}
|
||||
|
||||
public int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId,
|
||||
float x, float y, float pressure) {
|
||||
if (!isMonkey) {
|
||||
return MoonBridge.sendControllerTouchEvent(controllerNumber, eventType, pointerId, x, y, pressure);
|
||||
}
|
||||
else {
|
||||
return MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public int sendControllerMotionEvent(byte controllerNumber, byte motionType,
|
||||
float x, float y, float z) {
|
||||
if (!isMonkey) {
|
||||
return MoonBridge.sendControllerMotionEvent(controllerNumber, motionType, x, y, z);
|
||||
}
|
||||
else {
|
||||
return MoonBridge.LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public void sendControllerBatteryEvent(byte controllerNumber, byte batteryState, byte batteryPercentage) {
|
||||
MoonBridge.sendControllerBatteryEvent(controllerNumber, batteryState, batteryPercentage);
|
||||
}
|
||||
|
||||
public void sendUtf8Text(final String text) {
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendUtf8Text(text);
|
||||
|
||||
@@ -13,6 +13,11 @@ public interface NvConnectionListener {
|
||||
void displayTransientMessage(String message);
|
||||
|
||||
void rumble(short controllerNumber, short lowFreqMotor, short highFreqMotor);
|
||||
void rumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger);
|
||||
|
||||
void setHdrMode(boolean enabled, byte[] hdrMetadata);
|
||||
|
||||
void setMotionEventState(short controllerNumber, byte motionType, short reportRateHz);
|
||||
|
||||
void setControllerLED(short controllerNumber, byte r, byte g, byte b);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ public class StreamConfiguration {
|
||||
private int maxPacketSize;
|
||||
private int remote;
|
||||
private MoonBridge.AudioConfiguration audioConfiguration;
|
||||
private boolean supportsHevc;
|
||||
private int supportedVideoFormats;
|
||||
private int hevcBitratePercentageMultiplier;
|
||||
private boolean enableHdr;
|
||||
private int av1BitratePercentageMultiplier;
|
||||
private int attachedGamepadMask;
|
||||
private int encryptionFlags;
|
||||
private int colorRange;
|
||||
@@ -90,8 +90,8 @@ public class StreamConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setEnableHdr(boolean enableHdr) {
|
||||
config.enableHdr = enableHdr;
|
||||
public StreamConfiguration.Builder setAv1BitratePercentageMultiplier(int multiplier) {
|
||||
config.av1BitratePercentageMultiplier = multiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -135,8 +135,8 @@ public class StreamConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamConfiguration.Builder setHevcSupported(boolean supportsHevc) {
|
||||
config.supportsHevc = supportsHevc;
|
||||
public StreamConfiguration.Builder setSupportedVideoFormats(int supportedVideoFormats) {
|
||||
config.supportedVideoFormats = supportedVideoFormats;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -168,8 +168,7 @@ public class StreamConfiguration {
|
||||
this.sops = true;
|
||||
this.enableAdaptiveResolution = false;
|
||||
this.audioConfiguration = MoonBridge.AUDIO_CONFIGURATION_STEREO;
|
||||
this.supportsHevc = false;
|
||||
this.enableHdr = false;
|
||||
this.supportedVideoFormats = MoonBridge.VIDEO_FORMAT_H264;
|
||||
this.attachedGamepadMask = 0;
|
||||
}
|
||||
|
||||
@@ -221,16 +220,16 @@ public class StreamConfiguration {
|
||||
return audioConfiguration;
|
||||
}
|
||||
|
||||
public boolean getHevcSupported() {
|
||||
return supportsHevc;
|
||||
public int getSupportedVideoFormats() {
|
||||
return supportedVideoFormats;
|
||||
}
|
||||
|
||||
public int getHevcBitratePercentageMultiplier() {
|
||||
return hevcBitratePercentageMultiplier;
|
||||
}
|
||||
|
||||
public boolean getEnableHdr() {
|
||||
return enableHdr;
|
||||
public int getAv1BitratePercentageMultiplier() {
|
||||
return av1BitratePercentageMultiplier;
|
||||
}
|
||||
|
||||
public int getAttachedGamepadMask() {
|
||||
|
||||
@@ -10,7 +10,8 @@ public abstract class VideoDecoderRenderer {
|
||||
// This is called once for each frame-start NALU. This means it will be called several times
|
||||
// for an IDR frame which contains several parameter sets and the I-frame data.
|
||||
public abstract int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||
int frameNumber, int frameType, long receiveTimeMs, long enqueueTimeMs);
|
||||
int frameNumber, int frameType, char frameHostProcessingLatency,
|
||||
long receiveTimeMs, long enqueueTimeMs);
|
||||
|
||||
public abstract void cleanup();
|
||||
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package com.limelight.nvstream.input;
|
||||
|
||||
public class ControllerPacket {
|
||||
public static final short A_FLAG = 0x1000;
|
||||
public static final short B_FLAG = 0x2000;
|
||||
public static final short X_FLAG = 0x4000;
|
||||
public static final short Y_FLAG = (short)0x8000;
|
||||
public static final short UP_FLAG = 0x0001;
|
||||
public static final short DOWN_FLAG = 0x0002;
|
||||
public static final short LEFT_FLAG = 0x0004;
|
||||
public static final short RIGHT_FLAG = 0x0008;
|
||||
public static final short LB_FLAG = 0x0100;
|
||||
public static final short RB_FLAG = 0x0200;
|
||||
public static final short PLAY_FLAG = 0x0010;
|
||||
public static final short BACK_FLAG = 0x0020;
|
||||
public static final short LS_CLK_FLAG = 0x0040;
|
||||
public static final short RS_CLK_FLAG = 0x0080;
|
||||
public static final short SPECIAL_BUTTON_FLAG = 0x0400;
|
||||
public static final int A_FLAG = 0x1000;
|
||||
public static final int B_FLAG = 0x2000;
|
||||
public static final int X_FLAG = 0x4000;
|
||||
public static final int Y_FLAG = 0x8000;
|
||||
public static final int UP_FLAG = 0x0001;
|
||||
public static final int DOWN_FLAG = 0x0002;
|
||||
public static final int LEFT_FLAG = 0x0004;
|
||||
public static final int RIGHT_FLAG = 0x0008;
|
||||
public static final int LB_FLAG = 0x0100;
|
||||
public static final int RB_FLAG = 0x0200;
|
||||
public static final int PLAY_FLAG = 0x0010;
|
||||
public static final int BACK_FLAG = 0x0020;
|
||||
public static final int LS_CLK_FLAG = 0x0040;
|
||||
public static final int RS_CLK_FLAG = 0x0080;
|
||||
public static final int SPECIAL_BUTTON_FLAG = 0x0400;
|
||||
|
||||
// Extended buttons (Sunshine only)
|
||||
public static final int PADDLE1_FLAG = 0x010000;
|
||||
public static final int PADDLE2_FLAG = 0x020000;
|
||||
public static final int PADDLE3_FLAG = 0x040000;
|
||||
public static final int PADDLE4_FLAG = 0x080000;
|
||||
public static final int TOUCHPAD_FLAG = 0x100000; // Touchpad buttons on Sony controllers
|
||||
public static final int MISC_FLAG = 0x200000; // Share/Mic/Capture/Mute buttons on various controllers
|
||||
}
|
||||
@@ -14,9 +14,13 @@ public class MoonBridge {
|
||||
public static final int VIDEO_FORMAT_H264 = 0x0001;
|
||||
public static final int VIDEO_FORMAT_H265 = 0x0100;
|
||||
public static final int VIDEO_FORMAT_H265_MAIN10 = 0x0200;
|
||||
public static final int VIDEO_FORMAT_AV1_MAIN8 = 0x1000;
|
||||
public static final int VIDEO_FORMAT_AV1_MAIN10 = 0x2000;
|
||||
|
||||
public static final int VIDEO_FORMAT_MASK_H264 = 0x00FF;
|
||||
public static final int VIDEO_FORMAT_MASK_H265 = 0xFF00;
|
||||
public static final int VIDEO_FORMAT_MASK_H264 = 0x000F;
|
||||
public static final int VIDEO_FORMAT_MASK_H265 = 0x0F00;
|
||||
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;
|
||||
@@ -40,6 +44,7 @@ public class MoonBridge {
|
||||
public static final int CAPABILITY_DIRECT_SUBMIT = 1;
|
||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC = 2;
|
||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC = 4;
|
||||
public static final int CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1 = 0x40;
|
||||
|
||||
public static final int DR_OK = 0;
|
||||
public static final int DR_NEED_IDR = -1;
|
||||
@@ -75,6 +80,54 @@ public class MoonBridge {
|
||||
|
||||
public static final byte SS_KBE_FLAG_NON_NORMALIZED = 0x01;
|
||||
|
||||
public static final int LI_ERR_UNSUPPORTED = -5501;
|
||||
|
||||
public static final byte LI_TOUCH_EVENT_HOVER = 0x00;
|
||||
public static final byte LI_TOUCH_EVENT_DOWN = 0x01;
|
||||
public static final byte LI_TOUCH_EVENT_UP = 0x02;
|
||||
public static final byte LI_TOUCH_EVENT_MOVE = 0x03;
|
||||
public static final byte LI_TOUCH_EVENT_CANCEL = 0x04;
|
||||
public static final byte LI_TOUCH_EVENT_BUTTON_ONLY = 0x05;
|
||||
public static final byte LI_TOUCH_EVENT_HOVER_LEAVE = 0x06;
|
||||
public static final byte LI_TOUCH_EVENT_CANCEL_ALL = 0x07;
|
||||
|
||||
public static final byte LI_TOOL_TYPE_UNKNOWN = 0x00;
|
||||
public static final byte LI_TOOL_TYPE_PEN = 0x01;
|
||||
public static final byte LI_TOOL_TYPE_ERASER = 0x02;
|
||||
|
||||
public static final byte LI_PEN_BUTTON_PRIMARY = 0x01;
|
||||
public static final byte LI_PEN_BUTTON_SECONDARY = 0x02;
|
||||
public static final byte LI_PEN_BUTTON_TERTIARY = 0x04;
|
||||
|
||||
public static final byte LI_TILT_UNKNOWN = (byte)0xFF;
|
||||
public static final short LI_ROT_UNKNOWN = (short)0xFFFF;
|
||||
|
||||
public static final byte LI_CTYPE_UNKNOWN = 0x00;
|
||||
public static final byte LI_CTYPE_XBOX = 0x01;
|
||||
public static final byte LI_CTYPE_PS = 0x02;
|
||||
public static final byte LI_CTYPE_NINTENDO = 0x03;
|
||||
|
||||
public static final short LI_CCAP_ANALOG_TRIGGERS = 0x01;
|
||||
public static final short LI_CCAP_RUMBLE = 0x02;
|
||||
public static final short LI_CCAP_TRIGGER_RUMBLE = 0x04;
|
||||
public static final short LI_CCAP_TOUCHPAD = 0x08;
|
||||
public static final short LI_CCAP_ACCEL = 0x10;
|
||||
public static final short LI_CCAP_GYRO = 0x20;
|
||||
public static final short LI_CCAP_BATTERY_STATE = 0x40;
|
||||
public static final short LI_CCAP_RGB_LED = 0x80;
|
||||
|
||||
public static final byte LI_MOTION_TYPE_ACCEL = 0x01;
|
||||
public static final byte LI_MOTION_TYPE_GYRO = 0x02;
|
||||
|
||||
public static final byte LI_BATTERY_STATE_UNKNOWN = 0x00;
|
||||
public static final byte LI_BATTERY_STATE_NOT_PRESENT = 0x01;
|
||||
public static final byte LI_BATTERY_STATE_DISCHARGING = 0x02;
|
||||
public static final byte LI_BATTERY_STATE_CHARGING = 0x03;
|
||||
public static final byte LI_BATTERY_STATE_NOT_CHARGING = 0x04; // Connected to power but not charging
|
||||
public static final byte LI_BATTERY_STATE_FULL = 0x05;
|
||||
|
||||
public static final byte LI_BATTERY_PERCENTAGE_UNKNOWN = (byte)0xFF;
|
||||
|
||||
private static AudioRenderer audioRenderer;
|
||||
private static VideoDecoderRenderer videoRenderer;
|
||||
private static NvConnectionListener connectionListener;
|
||||
@@ -167,11 +220,11 @@ public class MoonBridge {
|
||||
}
|
||||
|
||||
public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType,
|
||||
int frameNumber, int frameType,
|
||||
int frameNumber, int frameType, char frameHostProcessingLatency,
|
||||
long receiveTimeMs, long enqueueTimeMs) {
|
||||
if (videoRenderer != null) {
|
||||
return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength,
|
||||
decodeUnitType, frameNumber, frameType, receiveTimeMs, enqueueTimeMs);
|
||||
decodeUnitType, frameNumber, frameType, frameHostProcessingLatency, receiveTimeMs, enqueueTimeMs);
|
||||
}
|
||||
else {
|
||||
return DR_OK;
|
||||
@@ -259,6 +312,24 @@ public class MoonBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void bridgeClRumbleTriggers(short controllerNumber, short leftTrigger, short rightTrigger) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.rumbleTriggers(controllerNumber, leftTrigger, rightTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
public static void bridgeClSetMotionEventState(short controllerNumber, byte eventType, short sampleRateHz) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.setMotionEventState(controllerNumber, eventType, sampleRateHz);
|
||||
}
|
||||
}
|
||||
|
||||
public static void bridgeClSetControllerLED(short controllerNumber, byte r, byte g, byte b) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.setControllerLED(controllerNumber, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setupBridge(VideoDecoderRenderer videoRenderer, AudioRenderer audioRenderer, NvConnectionListener connectionListener) {
|
||||
MoonBridge.videoRenderer = videoRenderer;
|
||||
MoonBridge.audioRenderer = audioRenderer;
|
||||
@@ -272,12 +343,12 @@ public class MoonBridge {
|
||||
}
|
||||
|
||||
public static native int startConnection(String address, String appVersion, String gfeVersion,
|
||||
String rtspSessionUrl,
|
||||
String rtspSessionUrl, int serverCodecModeSupport,
|
||||
int width, int height, int fps,
|
||||
int bitrate, int packetSize, int streamingRemotely,
|
||||
int audioConfiguration, boolean supportsHevc,
|
||||
boolean enableHdr,
|
||||
int audioConfiguration, int supportedVideoFormats,
|
||||
int hevcBitratePercentageMultiplier,
|
||||
int av1BitratePercentageMultiplier,
|
||||
int clientRefreshRateX100,
|
||||
int encryptionFlags,
|
||||
byte[] riAesKey, byte[] riAesIv,
|
||||
@@ -297,15 +368,25 @@ public class MoonBridge {
|
||||
public static native void sendMouseButton(byte buttonEvent, byte mouseButton);
|
||||
|
||||
public static native void sendMultiControllerInput(short controllerNumber,
|
||||
short activeGamepadMask, short buttonFlags,
|
||||
short activeGamepadMask, int buttonFlags,
|
||||
byte leftTrigger, byte rightTrigger,
|
||||
short leftStickX, short leftStickY,
|
||||
short rightStickX, short rightStickY);
|
||||
|
||||
public static native void sendControllerInput(short buttonFlags,
|
||||
byte leftTrigger, byte rightTrigger,
|
||||
short leftStickX, short leftStickY,
|
||||
short rightStickX, short rightStickY);
|
||||
public static native int sendTouchEvent(byte eventType, int pointerId, float x, float y, float pressure,
|
||||
float contactAreaMajor, float contactAreaMinor, short rotation);
|
||||
|
||||
public static native int sendPenEvent(byte eventType, byte toolType, byte penButtons, float x, float y,
|
||||
float pressure, float contactAreaMajor, float contactAreaMinor,
|
||||
short rotation, byte tilt);
|
||||
|
||||
public static native int sendControllerArrivalEvent(byte controllerNumber, short activeGamepadMask, byte type, int supportedButtonFlags, short capabilities);
|
||||
|
||||
public static native int sendControllerTouchEvent(byte controllerNumber, byte eventType, int pointerId, float x, float y, float pressure);
|
||||
|
||||
public static native int sendControllerMotionEvent(byte controllerNumber, byte motionType, float x, float y, float z);
|
||||
|
||||
public static native int sendControllerBatteryEvent(byte controllerNumber, byte batteryState, byte batteryPercentage);
|
||||
|
||||
public static native void sendKeyboardInput(short keyMap, byte keyDirection, byte modifier, byte flags);
|
||||
|
||||
@@ -334,5 +415,11 @@ 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 byte guessControllerType(int vendorId, int productId);
|
||||
|
||||
public static native boolean guessControllerHasPaddles(int vendorId, int productId);
|
||||
|
||||
public static native boolean guessControllerHasShareButton(int vendorId, int productId);
|
||||
|
||||
public static native void init();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
package com.limelight.nvstream.mdns;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.jmdns.JmmDNS;
|
||||
import javax.jmdns.NetworkTopologyDiscovery;
|
||||
import javax.jmdns.ServiceEvent;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.ServiceListener;
|
||||
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
|
||||
public class JmDNSDiscoveryAgent extends MdnsDiscoveryAgent implements ServiceListener {
|
||||
private static final String SERVICE_TYPE = "_nvstream._tcp.local.";
|
||||
private WifiManager.MulticastLock multicastLock;
|
||||
private Thread discoveryThread;
|
||||
private HashSet<String> pendingResolution = new HashSet<>();
|
||||
|
||||
// The resolver factory's instance member has a static lifetime which
|
||||
// means our ref count and listener must be static also.
|
||||
private static int resolverRefCount = 0;
|
||||
private static HashSet<ServiceListener> listeners = new HashSet<>();
|
||||
private static ServiceListener nvstreamListener = new ServiceListener() {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceAdded(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceRemoved(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceResolved(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static class MyNetworkTopologyDiscovery extends NetworkTopologyDiscoveryImpl {
|
||||
@Override
|
||||
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
|
||||
// This is an copy of jmDNS's implementation, except we omit the multicast check, since
|
||||
// it seems at least some devices lie about interfaces not supporting multicast when they really do.
|
||||
try {
|
||||
if (!networkInterface.isUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!networkInterface.supportsMulticast()) {
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
if (networkInterface.isLoopback()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
// Override jmDNS's default topology discovery class with ours
|
||||
NetworkTopologyDiscovery.Factory.setClassDelegate(new NetworkTopologyDiscovery.Factory.ClassDelegate() {
|
||||
@Override
|
||||
public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
|
||||
return new MyNetworkTopologyDiscovery();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static JmmDNS referenceResolver() {
|
||||
synchronized (JmDNSDiscoveryAgent.class) {
|
||||
JmmDNS instance = JmmDNS.Factory.getInstance();
|
||||
if (++resolverRefCount == 1) {
|
||||
// This will cause the listener to be invoked for known hosts immediately.
|
||||
// JmDNS only supports one listener per service, so we have to do this here
|
||||
// with a static listener.
|
||||
instance.addServiceListener(SERVICE_TYPE, nvstreamListener);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void dereferenceResolver() {
|
||||
synchronized (JmDNSDiscoveryAgent.class) {
|
||||
if (--resolverRefCount == 0) {
|
||||
try {
|
||||
JmmDNS.Factory.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JmDNSDiscoveryAgent(Context context, MdnsDiscoveryListener listener) {
|
||||
super(listener);
|
||||
|
||||
// Create the multicast lock required to receive mDNS traffic
|
||||
WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
multicastLock = wifiMgr.createMulticastLock("Limelight mDNS");
|
||||
multicastLock.setReferenceCounted(false);
|
||||
}
|
||||
|
||||
private void handleResolvedServiceInfo(ServiceInfo info) {
|
||||
synchronized (pendingResolution) {
|
||||
pendingResolution.remove(info.getName());
|
||||
}
|
||||
|
||||
try {
|
||||
handleServiceInfo(info);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Invalid DNS response
|
||||
LimeLog.info("mDNS: Invalid response for machine: "+info.getName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServiceInfo(ServiceInfo info) throws UnsupportedEncodingException {
|
||||
reportNewComputer(info.getName(), info.getPort(), info.getInet4Addresses(), info.getInet6Addresses());
|
||||
}
|
||||
|
||||
public void startDiscovery(final int discoveryIntervalMs) {
|
||||
// Kill any existing discovery before starting a new one
|
||||
stopDiscovery();
|
||||
|
||||
// Acquire the multicast lock to start receiving mDNS traffic
|
||||
multicastLock.acquire();
|
||||
|
||||
// Add our listener to the set
|
||||
synchronized (listeners) {
|
||||
listeners.add(JmDNSDiscoveryAgent.this);
|
||||
}
|
||||
|
||||
discoveryThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// This may result in listener callbacks so we must register
|
||||
// our listener first.
|
||||
JmmDNS resolver = referenceResolver();
|
||||
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
// Start an mDNS request
|
||||
resolver.requestServiceInfo(SERVICE_TYPE, null, discoveryIntervalMs);
|
||||
|
||||
// Run service resolution again for pending machines
|
||||
ArrayList<String> pendingNames;
|
||||
synchronized (pendingResolution) {
|
||||
pendingNames = new ArrayList<String>(pendingResolution);
|
||||
}
|
||||
for (String name : pendingNames) {
|
||||
LimeLog.info("mDNS: Retrying service resolution for machine: "+name);
|
||||
ServiceInfo[] infos = resolver.getServiceInfos(SERVICE_TYPE, name, 500);
|
||||
if (infos != null && infos.length != 0) {
|
||||
LimeLog.info("mDNS: Resolved (retry) with "+infos.length+" service entries");
|
||||
for (ServiceInfo svcinfo : infos) {
|
||||
handleResolvedServiceInfo(svcinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the next polling interval
|
||||
try {
|
||||
Thread.sleep(discoveryIntervalMs);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Dereference the resolver
|
||||
dereferenceResolver();
|
||||
}
|
||||
}
|
||||
};
|
||||
discoveryThread.setName("mDNS Discovery Thread");
|
||||
discoveryThread.start();
|
||||
}
|
||||
|
||||
public void stopDiscovery() {
|
||||
// Release the multicast lock to stop receiving mDNS traffic
|
||||
multicastLock.release();
|
||||
|
||||
// Remove our listener from the set
|
||||
synchronized (listeners) {
|
||||
listeners.remove(JmDNSDiscoveryAgent.this);
|
||||
}
|
||||
|
||||
// If there's already a running thread, interrupt it
|
||||
if (discoveryThread != null) {
|
||||
discoveryThread.interrupt();
|
||||
discoveryThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent event) {
|
||||
LimeLog.info("mDNS: Machine appeared: "+event.getInfo().getName());
|
||||
|
||||
ServiceInfo info = event.getDNS().getServiceInfo(SERVICE_TYPE, event.getInfo().getName(), 500);
|
||||
if (info == null) {
|
||||
// This machine is pending resolution
|
||||
synchronized (pendingResolution) {
|
||||
pendingResolution.add(event.getInfo().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LimeLog.info("mDNS: Resolved (blocking)");
|
||||
handleResolvedServiceInfo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent event) {
|
||||
LimeLog.info("mDNS: Machine disappeared: "+event.getInfo().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent event) {
|
||||
// We handle this synchronously
|
||||
}
|
||||
}
|
||||
@@ -1,165 +1,64 @@
|
||||
package com.limelight.nvstream.mdns;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import com.limelight.LimeLog;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jmdns.JmmDNS;
|
||||
import javax.jmdns.NetworkTopologyDiscovery;
|
||||
import javax.jmdns.ServiceEvent;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.ServiceListener;
|
||||
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
|
||||
public abstract class MdnsDiscoveryAgent {
|
||||
protected MdnsDiscoveryListener listener;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
|
||||
public class MdnsDiscoveryAgent implements ServiceListener {
|
||||
public static final String SERVICE_TYPE = "_nvstream._tcp.local.";
|
||||
|
||||
private MdnsDiscoveryListener listener;
|
||||
private Thread discoveryThread;
|
||||
private HashSet<MdnsComputer> computers = new HashSet<>();
|
||||
private HashSet<String> pendingResolution = new HashSet<>();
|
||||
|
||||
// The resolver factory's instance member has a static lifetime which
|
||||
// means our ref count and listener must be static also.
|
||||
private static int resolverRefCount = 0;
|
||||
private static HashSet<ServiceListener> listeners = new HashSet<>();
|
||||
private static ServiceListener nvstreamListener = new ServiceListener() {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceAdded(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceRemoved(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent event) {
|
||||
HashSet<ServiceListener> localListeners;
|
||||
|
||||
// Copy the listener set into a new set so we can invoke
|
||||
// the callbacks without holding the listeners monitor the
|
||||
// whole time.
|
||||
synchronized (listeners) {
|
||||
localListeners = new HashSet<ServiceListener>(listeners);
|
||||
}
|
||||
|
||||
for (ServiceListener listener : localListeners) {
|
||||
listener.serviceResolved(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static class MyNetworkTopologyDiscovery extends NetworkTopologyDiscoveryImpl {
|
||||
@Override
|
||||
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
|
||||
// This is an copy of jmDNS's implementation, except we omit the multicast check, since
|
||||
// it seems at least some devices lie about interfaces not supporting multicast when they really do.
|
||||
try {
|
||||
if (!networkInterface.isUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!networkInterface.supportsMulticast()) {
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
if (networkInterface.isLoopback()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
// Override jmDNS's default topology discovery class with ours
|
||||
NetworkTopologyDiscovery.Factory.setClassDelegate(new NetworkTopologyDiscovery.Factory.ClassDelegate() {
|
||||
@Override
|
||||
public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
|
||||
return new MyNetworkTopologyDiscovery();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static JmmDNS referenceResolver() {
|
||||
synchronized (MdnsDiscoveryAgent.class) {
|
||||
JmmDNS instance = JmmDNS.Factory.getInstance();
|
||||
if (++resolverRefCount == 1) {
|
||||
// This will cause the listener to be invoked for known hosts immediately.
|
||||
// JmDNS only supports one listener per service, so we have to do this here
|
||||
// with a static listener.
|
||||
instance.addServiceListener(SERVICE_TYPE, nvstreamListener);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void dereferenceResolver() {
|
||||
synchronized (MdnsDiscoveryAgent.class) {
|
||||
if (--resolverRefCount == 0) {
|
||||
try {
|
||||
JmmDNS.Factory.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected HashSet<MdnsComputer> computers = new HashSet<>();
|
||||
|
||||
public MdnsDiscoveryAgent(MdnsDiscoveryListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private void handleResolvedServiceInfo(ServiceInfo info) {
|
||||
synchronized (pendingResolution) {
|
||||
pendingResolution.remove(info.getName());
|
||||
public abstract void startDiscovery(final int discoveryIntervalMs);
|
||||
|
||||
public abstract void stopDiscovery();
|
||||
|
||||
protected void reportNewComputer(String name, int port, Inet4Address[] v4Addrs, Inet6Address[] v6Addrs) {
|
||||
LimeLog.info("mDNS: "+name+" has "+v4Addrs.length+" IPv4 addresses");
|
||||
LimeLog.info("mDNS: "+name+" has "+v6Addrs.length+" IPv6 addresses");
|
||||
|
||||
Inet6Address v6GlobalAddr = getBestIpv6Address(v6Addrs);
|
||||
|
||||
// Add a computer object for each IPv4 address reported by the PC
|
||||
for (Inet4Address v4Addr : v4Addrs) {
|
||||
synchronized (computers) {
|
||||
MdnsComputer computer = new MdnsComputer(name, v4Addr, v6GlobalAddr, port);
|
||||
if (computers.add(computer)) {
|
||||
// This was a new entry
|
||||
listener.notifyComputerAdded(computer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
handleServiceInfo(info);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// Invalid DNS response
|
||||
LimeLog.info("mDNS: Invalid response for machine: "+info.getName());
|
||||
return;
|
||||
// If there were no IPv4 addresses, use IPv6 for registration
|
||||
if (v4Addrs.length == 0) {
|
||||
Inet6Address v6LocalAddr = getLocalAddress(v6Addrs);
|
||||
|
||||
if (v6LocalAddr != null || v6GlobalAddr != null) {
|
||||
MdnsComputer computer = new MdnsComputer(name, v6LocalAddr, v6GlobalAddr, port);
|
||||
if (computers.add(computer)) {
|
||||
// This was a new entry
|
||||
listener.notifyComputerAdded(computer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Inet6Address getLocalAddress(Inet6Address[] addresses) {
|
||||
public List<MdnsComputer> getComputerSet() {
|
||||
synchronized (computers) {
|
||||
return new ArrayList<>(computers);
|
||||
}
|
||||
}
|
||||
|
||||
protected static Inet6Address getLocalAddress(Inet6Address[] addresses) {
|
||||
for (Inet6Address addr : addresses) {
|
||||
if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) {
|
||||
return addr;
|
||||
@@ -173,7 +72,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
|
||||
protected static Inet6Address getLinkLocalAddress(Inet6Address[] addresses) {
|
||||
for (Inet6Address addr : addresses) {
|
||||
if (addr.isLinkLocalAddress()) {
|
||||
LimeLog.info("Found link-local address: "+addr.getHostAddress());
|
||||
@@ -184,7 +83,7 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Inet6Address getBestIpv6Address(Inet6Address[] addresses) {
|
||||
protected static Inet6Address getBestIpv6Address(Inet6Address[] addresses) {
|
||||
// First try to find a link local address, so we can match the interface identifier
|
||||
// with a global address (this will work for SLAAC but not DHCPv6).
|
||||
Inet6Address linkLocalAddr = getLinkLocalAddress(addresses);
|
||||
@@ -246,139 +145,4 @@ public class MdnsDiscoveryAgent implements ServiceListener {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void handleServiceInfo(ServiceInfo info) throws UnsupportedEncodingException {
|
||||
Inet4Address v4Addrs[] = info.getInet4Addresses();
|
||||
Inet6Address v6Addrs[] = info.getInet6Addresses();
|
||||
|
||||
LimeLog.info("mDNS: "+info.getName()+" has "+v4Addrs.length+" IPv4 addresses");
|
||||
LimeLog.info("mDNS: "+info.getName()+" has "+v6Addrs.length+" IPv6 addresses");
|
||||
|
||||
Inet6Address v6GlobalAddr = getBestIpv6Address(v6Addrs);
|
||||
|
||||
// Add a computer object for each IPv4 address reported by the PC
|
||||
for (Inet4Address v4Addr : v4Addrs) {
|
||||
synchronized (computers) {
|
||||
MdnsComputer computer = new MdnsComputer(info.getName(), v4Addr, v6GlobalAddr, info.getPort());
|
||||
if (computers.add(computer)) {
|
||||
// This was a new entry
|
||||
listener.notifyComputerAdded(computer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there were no IPv4 addresses, use IPv6 for registration
|
||||
if (v4Addrs.length == 0) {
|
||||
Inet6Address v6LocalAddr = getLocalAddress(v6Addrs);
|
||||
|
||||
if (v6LocalAddr != null || v6GlobalAddr != null) {
|
||||
MdnsComputer computer = new MdnsComputer(info.getName(), v6LocalAddr, v6GlobalAddr, info.getPort());
|
||||
if (computers.add(computer)) {
|
||||
// This was a new entry
|
||||
listener.notifyComputerAdded(computer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void startDiscovery(final int discoveryIntervalMs) {
|
||||
// Kill any existing discovery before starting a new one
|
||||
stopDiscovery();
|
||||
|
||||
// Add our listener to the set
|
||||
synchronized (listeners) {
|
||||
listeners.add(MdnsDiscoveryAgent.this);
|
||||
}
|
||||
|
||||
discoveryThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// This may result in listener callbacks so we must register
|
||||
// our listener first.
|
||||
JmmDNS resolver = referenceResolver();
|
||||
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
// Start an mDNS request
|
||||
resolver.requestServiceInfo(SERVICE_TYPE, null, discoveryIntervalMs);
|
||||
|
||||
// Run service resolution again for pending machines
|
||||
ArrayList<String> pendingNames;
|
||||
synchronized (pendingResolution) {
|
||||
pendingNames = new ArrayList<String>(pendingResolution);
|
||||
}
|
||||
for (String name : pendingNames) {
|
||||
LimeLog.info("mDNS: Retrying service resolution for machine: "+name);
|
||||
ServiceInfo[] infos = resolver.getServiceInfos(SERVICE_TYPE, name, 500);
|
||||
if (infos != null && infos.length != 0) {
|
||||
LimeLog.info("mDNS: Resolved (retry) with "+infos.length+" service entries");
|
||||
for (ServiceInfo svcinfo : infos) {
|
||||
handleResolvedServiceInfo(svcinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the next polling interval
|
||||
try {
|
||||
Thread.sleep(discoveryIntervalMs);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Dereference the resolver
|
||||
dereferenceResolver();
|
||||
}
|
||||
}
|
||||
};
|
||||
discoveryThread.setName("mDNS Discovery Thread");
|
||||
discoveryThread.start();
|
||||
}
|
||||
|
||||
public void stopDiscovery() {
|
||||
// Remove our listener from the set
|
||||
synchronized (listeners) {
|
||||
listeners.remove(MdnsDiscoveryAgent.this);
|
||||
}
|
||||
|
||||
// If there's already a running thread, interrupt it
|
||||
if (discoveryThread != null) {
|
||||
discoveryThread.interrupt();
|
||||
discoveryThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<MdnsComputer> getComputerSet() {
|
||||
synchronized (computers) {
|
||||
return new ArrayList<>(computers);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent event) {
|
||||
LimeLog.info("mDNS: Machine appeared: "+event.getInfo().getName());
|
||||
|
||||
ServiceInfo info = event.getDNS().getServiceInfo(SERVICE_TYPE, event.getInfo().getName(), 500);
|
||||
if (info == null) {
|
||||
// This machine is pending resolution
|
||||
synchronized (pendingResolution) {
|
||||
pendingResolution.add(event.getInfo().getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LimeLog.info("mDNS: Resolved (blocking)");
|
||||
handleResolvedServiceInfo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent event) {
|
||||
LimeLog.info("mDNS: Machine disappeared: "+event.getInfo().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent event) {
|
||||
// We handle this synchronously
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
package com.limelight.nvstream.mdns;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.net.nsd.NsdManager;
|
||||
import android.net.nsd.NsdServiceInfo;
|
||||
import android.os.Build;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public class NsdManagerDiscoveryAgent extends MdnsDiscoveryAgent {
|
||||
private static final String SERVICE_TYPE = "_nvstream._tcp";
|
||||
private final NsdManager nsdManager;
|
||||
private final Object listenerLock = new Object();
|
||||
private NsdManager.DiscoveryListener pendingListener;
|
||||
private NsdManager.DiscoveryListener activeListener;
|
||||
private final HashMap<String, NsdManager.ServiceInfoCallback> serviceCallbacks = new HashMap<>();
|
||||
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
|
||||
|
||||
private NsdManager.DiscoveryListener createDiscoveryListener() {
|
||||
return new NsdManager.DiscoveryListener() {
|
||||
@Override
|
||||
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
|
||||
LimeLog.severe("NSD: Service discovery start failed: " + errorCode);
|
||||
|
||||
// This listener is no longer pending after this failure
|
||||
synchronized (listenerLock) {
|
||||
if (pendingListener != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
pendingListener = null;
|
||||
}
|
||||
|
||||
listener.notifyDiscoveryFailure(new RuntimeException("onStartDiscoveryFailed(): " + errorCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
|
||||
LimeLog.severe("NSD: Service discovery stop failed: " + errorCode);
|
||||
|
||||
// This listener is no longer active after this failure
|
||||
synchronized (listenerLock) {
|
||||
if (activeListener != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
activeListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDiscoveryStarted(String serviceType) {
|
||||
LimeLog.info("NSD: Service discovery started");
|
||||
|
||||
synchronized (listenerLock) {
|
||||
if (pendingListener != this) {
|
||||
// If we registered another discovery listener in the meantime, stop this one
|
||||
nsdManager.stopServiceDiscovery(this);
|
||||
return;
|
||||
}
|
||||
|
||||
pendingListener = null;
|
||||
activeListener = this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDiscoveryStopped(String serviceType) {
|
||||
LimeLog.info("NSD: Service discovery stopped");
|
||||
|
||||
synchronized (listenerLock) {
|
||||
if (activeListener != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
activeListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceFound(NsdServiceInfo nsdServiceInfo) {
|
||||
// Protect against racing stopDiscovery() call
|
||||
synchronized (listenerLock) {
|
||||
// Ignore callbacks if we're not the active listener
|
||||
if (activeListener != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
LimeLog.info("NSD: Machine appeared: " + nsdServiceInfo.getServiceName());
|
||||
|
||||
NsdManager.ServiceInfoCallback serviceInfoCallback = new NsdManager.ServiceInfoCallback() {
|
||||
@Override
|
||||
public void onServiceInfoCallbackRegistrationFailed(int errorCode) {
|
||||
LimeLog.severe("NSD: Service info callback registration failed: " + errorCode);
|
||||
listener.notifyDiscoveryFailure(new RuntimeException("onServiceInfoCallbackRegistrationFailed(): " + errorCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceUpdated(NsdServiceInfo nsdServiceInfo) {
|
||||
LimeLog.info("NSD: Machine resolved: " + nsdServiceInfo.getServiceName());
|
||||
reportNewComputer(nsdServiceInfo.getServiceName(), nsdServiceInfo.getPort(),
|
||||
getV4Addrs(nsdServiceInfo.getHostAddresses()),
|
||||
getV6Addrs(nsdServiceInfo.getHostAddresses()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceLost() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceInfoCallbackUnregistered() {
|
||||
}
|
||||
};
|
||||
|
||||
nsdManager.registerServiceInfoCallback(nsdServiceInfo, executor, serviceInfoCallback);
|
||||
serviceCallbacks.put(nsdServiceInfo.getServiceName(), serviceInfoCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceLost(NsdServiceInfo nsdServiceInfo) {
|
||||
// Protect against racing stopDiscovery() call
|
||||
synchronized (listenerLock) {
|
||||
// Ignore callbacks if we're not the active listener
|
||||
if (activeListener != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
LimeLog.info("NSD: Machine lost: " + nsdServiceInfo.getServiceName());
|
||||
|
||||
NsdManager.ServiceInfoCallback serviceInfoCallback = serviceCallbacks.remove(nsdServiceInfo.getServiceName());
|
||||
if (serviceInfoCallback != null) {
|
||||
nsdManager.unregisterServiceInfoCallback(serviceInfoCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public NsdManagerDiscoveryAgent(Context context, MdnsDiscoveryListener listener) {
|
||||
super(listener);
|
||||
this.nsdManager = context.getSystemService(NsdManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDiscovery(int discoveryIntervalMs) {
|
||||
synchronized (listenerLock) {
|
||||
// Register a new service discovery listener if there's not already one starting or running
|
||||
if (pendingListener == null && activeListener == null) {
|
||||
pendingListener = createDiscoveryListener();
|
||||
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, pendingListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopDiscovery() {
|
||||
// Protect against racing ServiceInfoCallback and DiscoveryListener callbacks
|
||||
synchronized (listenerLock) {
|
||||
// Clear any pending listener to ensure the discoverStarted() callback
|
||||
// will realize it's gone and stop itself.
|
||||
pendingListener = null;
|
||||
|
||||
// Unregister the service discovery listener
|
||||
if (activeListener != null) {
|
||||
nsdManager.stopServiceDiscovery(activeListener);
|
||||
|
||||
// Even though listener stoppage is asynchronous, the listener is gone as far as
|
||||
// we're concerned. We null this right now to ensure pending callbacks know it's
|
||||
// stopped and startDiscovery() can immediately create a new listener. If we left
|
||||
// it until onDiscoveryStopped() was called, startDiscovery() would get confused
|
||||
// and assume a listener was already running, even though it's stopping.
|
||||
activeListener = null;
|
||||
}
|
||||
|
||||
// Unregister all service info callbacks
|
||||
for (NsdManager.ServiceInfoCallback callback : serviceCallbacks.values()) {
|
||||
nsdManager.unregisterServiceInfoCallback(callback);
|
||||
}
|
||||
serviceCallbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static Inet4Address[] getV4Addrs(List<InetAddress> addrs) {
|
||||
int matchCount = 0;
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet4Address) {
|
||||
matchCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Inet4Address[] matching = new Inet4Address[matchCount];
|
||||
|
||||
int i = 0;
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet4Address) {
|
||||
matching[i++] = (Inet4Address) addr;
|
||||
}
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
|
||||
private static Inet6Address[] getV6Addrs(List<InetAddress> addrs) {
|
||||
int matchCount = 0;
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet6Address) {
|
||||
matchCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Inet6Address[] matching = new Inet6Address[matchCount];
|
||||
|
||||
int i = 0;
|
||||
for (InetAddress addr : addrs) {
|
||||
if (addr instanceof Inet6Address) {
|
||||
matching[i++] = (Inet6Address) addr;
|
||||
}
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,13 @@ import android.view.Display;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
public class PreferenceConfiguration {
|
||||
public enum FormatOption {
|
||||
AUTO,
|
||||
FORCE_AV1,
|
||||
FORCE_HEVC,
|
||||
FORCE_H264,
|
||||
};
|
||||
|
||||
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";
|
||||
|
||||
@@ -49,6 +56,9 @@ public class PreferenceConfiguration {
|
||||
private static final String ENABLE_AUDIO_FX_PREF_STRING = "checkbox_enable_audiofx";
|
||||
private static final String REDUCE_REFRESH_RATE_PREF_STRING = "checkbox_reduce_refresh_rate";
|
||||
private static final String FULL_RANGE_PREF_STRING = "checkbox_full_range";
|
||||
private static final String GAMEPAD_TOUCHPAD_AS_MOUSE_PREF_STRING = "checkbox_gamepad_touchpad_as_mouse";
|
||||
private static final String GAMEPAD_MOTION_SENSORS_PREF_STRING = "checkbox_gamepad_motion_sensors";
|
||||
private static final String GAMEPAD_MOTION_FALLBACK_PREF_STRING = "checkbox_gamepad_motion_fallback";
|
||||
|
||||
static final String DEFAULT_RESOLUTION = "1280x720";
|
||||
static final String DEFAULT_FPS = "60";
|
||||
@@ -62,6 +72,7 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
|
||||
private static final boolean DEFAULT_USB_DRIVER = true;
|
||||
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
||||
|
||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
||||
private static final boolean DEFAULT_ENABLE_HDR = false;
|
||||
@@ -82,10 +93,9 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_ENABLE_AUDIO_FX = false;
|
||||
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
|
||||
private static final boolean DEFAULT_FULL_RANGE = false;
|
||||
|
||||
public static final int FORCE_H265_ON = -1;
|
||||
public static final int AUTOSELECT_H265 = 0;
|
||||
public static final int FORCE_H265_OFF = 1;
|
||||
private static final boolean DEFAULT_GAMEPAD_TOUCHPAD_AS_MOUSE = false;
|
||||
private static final boolean DEFAULT_GAMEPAD_MOTION_SENSORS = true;
|
||||
private static final boolean DEFAULT_GAMEPAD_MOTION_FALLBACK = false;
|
||||
|
||||
public static final int FRAME_PACING_MIN_LATENCY = 0;
|
||||
public static final int FRAME_PACING_BALANCED = 1;
|
||||
@@ -102,7 +112,7 @@ public class PreferenceConfiguration {
|
||||
|
||||
public int width, height, fps;
|
||||
public int bitrate;
|
||||
public int videoFormat;
|
||||
public FormatOption videoFormat;
|
||||
public int deadzonePercentage;
|
||||
public int oscOpacity;
|
||||
public boolean stretchVideo, enableSops, playHostAudio, disableWarnings;
|
||||
@@ -127,6 +137,9 @@ public class PreferenceConfiguration {
|
||||
public boolean enableAudioFx;
|
||||
public boolean reduceRefreshRate;
|
||||
public boolean fullRange;
|
||||
public boolean gamepadMotionSensors;
|
||||
public boolean gamepadTouchpadAsMouse;
|
||||
public boolean gamepadMotionSensorsFallbackToDevice;
|
||||
|
||||
public static boolean isNativeResolution(int width, int height) {
|
||||
// It's not a native resolution if it matches an existing resolution option
|
||||
@@ -233,33 +246,62 @@ public class PreferenceConfiguration {
|
||||
int height = getHeightFromResolutionString(resString);
|
||||
int fps = Integer.parseInt(fpsString);
|
||||
|
||||
// This table prefers 16:10 resolutions because they are
|
||||
// only slightly more pixels than the 16:9 equivalents, so
|
||||
// we don't want to bump those 16:10 resolutions up to the
|
||||
// next 16:9 slot.
|
||||
//
|
||||
// This logic is shamelessly stolen from Moonlight Qt:
|
||||
// https://github.com/moonlight-stream/moonlight-qt/blob/master/app/settings/streamingpreferences.cpp
|
||||
|
||||
if (width * height <= 640 * 360) {
|
||||
return (int)(1000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 854 * 480) {
|
||||
return (int)(1500 * (fps / 30.0));
|
||||
}
|
||||
// This covers 1280x720 and 1280x800 too
|
||||
else if (width * height <= 1366 * 768) {
|
||||
return (int)(5000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 1920 * 1200) {
|
||||
return (int)(10000 * (fps / 30.0));
|
||||
}
|
||||
else if (width * height <= 2560 * 1600) {
|
||||
return (int)(20000 * (fps / 30.0));
|
||||
}
|
||||
else /* if (width * height <= 3840 * 2160) */ {
|
||||
return (int)(40000 * (fps / 30.0));
|
||||
// Don't scale bitrate linearly beyond 60 FPS. It's definitely not a linear
|
||||
// bitrate increase for frame rate once we get to values that high.
|
||||
double frameRateFactor = (fps <= 60 ? fps : (Math.sqrt(fps / 60.f) * 60.f)) / 30.f;
|
||||
|
||||
// TODO: Collect some empirical data to see if these defaults make sense.
|
||||
// We're just using the values that the Shield used, as we have for years.
|
||||
int[] pixelVals = {
|
||||
640 * 360,
|
||||
854 * 480,
|
||||
1280 * 720,
|
||||
1920 * 1080,
|
||||
2560 * 1440,
|
||||
3840 * 2160,
|
||||
-1,
|
||||
};
|
||||
int[] factorVals = {
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
10,
|
||||
20,
|
||||
40,
|
||||
-1
|
||||
};
|
||||
|
||||
// Calculate the resolution factor by linear interpolation of the resolution table
|
||||
float resolutionFactor;
|
||||
int pixels = width * height;
|
||||
for (int i = 0; ; i++) {
|
||||
if (pixels == pixelVals[i]) {
|
||||
// We can bail immediately for exact matches
|
||||
resolutionFactor = factorVals[i];
|
||||
break;
|
||||
}
|
||||
else if (pixels < pixelVals[i]) {
|
||||
if (i == 0) {
|
||||
// Never go below the lowest resolution entry
|
||||
resolutionFactor = factorVals[i];
|
||||
}
|
||||
else {
|
||||
// Interpolate between the entry greater than the chosen resolution (i) and the entry less than the chosen resolution (i-1)
|
||||
resolutionFactor = ((float)(pixels - pixelVals[i-1]) / (pixelVals[i] - pixelVals[i-1])) * (factorVals[i] - factorVals[i-1]) + factorVals[i-1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (pixelVals[i] == -1) {
|
||||
// Never go above the highest resolution entry
|
||||
resolutionFactor = factorVals[i-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)Math.round(resolutionFactor * frameRateFactor) * 1000;
|
||||
}
|
||||
|
||||
public static boolean getDefaultSmallMode(Context context) {
|
||||
@@ -289,22 +331,25 @@ public class PreferenceConfiguration {
|
||||
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
|
||||
}
|
||||
|
||||
private static int getVideoFormatValue(Context context) {
|
||||
private static FormatOption getVideoFormatValue(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT);
|
||||
if (str.equals("auto")) {
|
||||
return AUTOSELECT_H265;
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
else if (str.equals("forceav1")) {
|
||||
return FormatOption.FORCE_AV1;
|
||||
}
|
||||
else if (str.equals("forceh265")) {
|
||||
return FORCE_H265_ON;
|
||||
return FormatOption.FORCE_HEVC;
|
||||
}
|
||||
else if (str.equals("neverh265")) {
|
||||
return FORCE_H265_OFF;
|
||||
return FormatOption.FORCE_H264;
|
||||
}
|
||||
else {
|
||||
// Should never get here
|
||||
return AUTOSELECT_H265;
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,6 +503,15 @@ public class PreferenceConfiguration {
|
||||
prefs.edit().putBoolean(SMALL_ICONS_PREF_STRING, getDefaultSmallMode(context)).apply();
|
||||
}
|
||||
|
||||
if (!prefs.contains(GAMEPAD_MOTION_SENSORS_PREF_STRING) && Build.VERSION.SDK_INT == Build.VERSION_CODES.S) {
|
||||
// Android 12 has a nasty bug that causes crashes when the app touches the InputDevice's
|
||||
// associated InputDeviceSensorManager (just calling getSensorManager() is enough).
|
||||
// As a workaround, we will override the default value for the gamepad motion sensor
|
||||
// option to disabled on Android 12 to reduce the impact of this bug.
|
||||
// https://cs.android.com/android/_/android/platform/frameworks/base/+/8970010a5e9f3dc5c069f56b4147552accfcbbeb
|
||||
prefs.edit().putBoolean(GAMEPAD_MOTION_SENSORS_PREF_STRING, false).apply();
|
||||
}
|
||||
|
||||
// This must happen after the preferences migration to ensure the preferences are populated
|
||||
config.bitrate = prefs.getInt(BITRATE_PREF_STRING, prefs.getInt(BITRATE_PREF_OLD_STRING, 0) * 1000);
|
||||
if (config.bitrate == 0) {
|
||||
@@ -510,6 +564,9 @@ public class PreferenceConfiguration {
|
||||
config.enableAudioFx = prefs.getBoolean(ENABLE_AUDIO_FX_PREF_STRING, DEFAULT_ENABLE_AUDIO_FX);
|
||||
config.reduceRefreshRate = prefs.getBoolean(REDUCE_REFRESH_RATE_PREF_STRING, DEFAULT_REDUCE_REFRESH_RATE);
|
||||
config.fullRange = prefs.getBoolean(FULL_RANGE_PREF_STRING, DEFAULT_FULL_RANGE);
|
||||
config.gamepadTouchpadAsMouse = prefs.getBoolean(GAMEPAD_TOUCHPAD_AS_MOUSE_PREF_STRING, DEFAULT_GAMEPAD_TOUCHPAD_AS_MOUSE);
|
||||
config.gamepadMotionSensors = prefs.getBoolean(GAMEPAD_MOTION_SENSORS_PREF_STRING, DEFAULT_GAMEPAD_MOTION_SENSORS);
|
||||
config.gamepadMotionSensorsFallbackToDevice = prefs.getBoolean(GAMEPAD_MOTION_FALLBACK_PREF_STRING, DEFAULT_GAMEPAD_MOTION_FALLBACK);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ public class StreamSettings extends Activity {
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragment {
|
||||
private int nativeResolutionStartIndex = Integer.MAX_VALUE;
|
||||
private boolean nativeFramerateShown = false;
|
||||
|
||||
private void setValue(String preferenceKey, String value) {
|
||||
ListPreference pref = (ListPreference) findPreference(preferenceKey);
|
||||
@@ -130,6 +131,18 @@ public class StreamSettings extends Activity {
|
||||
pref.setValue(value);
|
||||
}
|
||||
|
||||
private void appendPreferenceEntry(ListPreference pref, String newEntryName, String newEntryValue) {
|
||||
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
||||
CharSequence[] newValues = Arrays.copyOf(pref.getEntryValues(), pref.getEntryValues().length + 1);
|
||||
|
||||
// Add the new option
|
||||
newEntries[newEntries.length - 1] = newEntryName;
|
||||
newValues[newValues.length - 1] = newEntryValue;
|
||||
|
||||
pref.setEntries(newEntries);
|
||||
pref.setEntryValues(newValues);
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) {
|
||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
|
||||
|
||||
@@ -155,29 +168,18 @@ public class StreamSettings extends Activity {
|
||||
|
||||
String newValue = nativeWidth+"x"+nativeHeight;
|
||||
|
||||
CharSequence[] values = pref.getEntryValues();
|
||||
|
||||
// Check if the native resolution is already present
|
||||
for (CharSequence value : values) {
|
||||
for (CharSequence value : pref.getEntryValues()) {
|
||||
if (newValue.equals(value.toString())) {
|
||||
// It is present in the default list, so don't add it again
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CharSequence[] newEntries = Arrays.copyOf(pref.getEntries(), pref.getEntries().length + 1);
|
||||
CharSequence[] newValues = Arrays.copyOf(values, values.length + 1);
|
||||
|
||||
// Add the new native option
|
||||
newEntries[newEntries.length - 1] = newName;
|
||||
newValues[newValues.length - 1] = newValue;
|
||||
|
||||
pref.setEntries(newEntries);
|
||||
pref.setEntryValues(newValues);
|
||||
|
||||
if (newValues.length - 1 < nativeResolutionStartIndex) {
|
||||
nativeResolutionStartIndex = newValues.length - 1;
|
||||
if (pref.getEntryValues().length < nativeResolutionStartIndex) {
|
||||
nativeResolutionStartIndex = pref.getEntryValues().length;
|
||||
}
|
||||
appendPreferenceEntry(pref, newName, newValue);
|
||||
}
|
||||
|
||||
private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) {
|
||||
@@ -187,6 +189,25 @@ public class StreamSettings extends Activity {
|
||||
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
|
||||
}
|
||||
|
||||
private void addNativeFrameRateEntry(float framerate) {
|
||||
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.FPS_PREF_STRING);
|
||||
String fpsValue = Integer.toString(Math.round(framerate));
|
||||
String fpsName = getResources().getString(R.string.resolution_prefix_native) +
|
||||
" (" + fpsValue + " " + getResources().getString(R.string.fps_suffix_fps) + ")";
|
||||
|
||||
// Check if the native frame rate is already present
|
||||
for (CharSequence value : pref.getEntryValues()) {
|
||||
if (fpsValue.equals(value.toString())) {
|
||||
// It is present in the default list, so don't add it again
|
||||
nativeFramerateShown = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
appendPreferenceEntry(pref, fpsName, fpsValue);
|
||||
nativeFramerateShown = true;
|
||||
}
|
||||
|
||||
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
|
||||
int matchingCount = 0;
|
||||
|
||||
@@ -267,6 +288,30 @@ public class StreamSettings extends Activity {
|
||||
category.removePreference(findPreference("checkbox_absolute_mouse_mode"));
|
||||
}
|
||||
|
||||
// Hide gamepad motion sensor option when running on OSes before Android 12.
|
||||
// Support for motion, LED, battery, and other extensions were introduced in S.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
category.removePreference(findPreference("checkbox_gamepad_motion_sensors"));
|
||||
}
|
||||
|
||||
// Hide gamepad motion sensor fallback option if the device has no gyro or accelerometer
|
||||
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER) &&
|
||||
!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_GYROSCOPE)) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
category.removePreference(findPreference("checkbox_gamepad_motion_fallback"));
|
||||
}
|
||||
|
||||
// Hide USB driver options on devices without USB host support
|
||||
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
category.removePreference(findPreference("checkbox_usb_bind_all"));
|
||||
category.removePreference(findPreference("checkbox_usb_driver"));
|
||||
}
|
||||
|
||||
// Remove PiP mode on devices pre-Oreo, where the feature is not available (some low RAM devices),
|
||||
// and on Fire OS where it violates the Amazon App Store guidelines for some reason.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
|
||||
@@ -287,7 +332,7 @@ public class StreamSettings extends Activity {
|
||||
// Remove the vibration options if the device can't vibrate
|
||||
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_input_settings");
|
||||
(PreferenceCategory) findPreference("category_gamepad_settings");
|
||||
category.removePreference(findPreference("checkbox_vibrate_fallback"));
|
||||
|
||||
// The entire OSC category may have already been removed by the touchscreen check above
|
||||
@@ -508,6 +553,7 @@ public class StreamSettings extends Activity {
|
||||
}
|
||||
// Never remove 30 FPS or 60 FPS
|
||||
}
|
||||
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.
|
||||
@@ -632,6 +678,15 @@ public class StreamSettings extends Activity {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
|
||||
String valueStr = (String) newValue;
|
||||
|
||||
// If this is native frame rate, show the warning dialog
|
||||
CharSequence[] values = ((ListPreference)preference).getEntryValues();
|
||||
if (nativeFramerateShown && values[values.length - 1].toString().equals(newValue.toString())) {
|
||||
Dialog.displayDialog(getActivity(),
|
||||
getResources().getString(R.string.title_native_fps_dialog),
|
||||
getResources().getString(R.string.text_native_res_dialog),
|
||||
false);
|
||||
}
|
||||
|
||||
// Write the new bitrate value
|
||||
resetBitrateToDefault(prefs, null, valueStr);
|
||||
|
||||
|
||||
@@ -29,37 +29,37 @@ public class UiHelper {
|
||||
private static final int TV_VERTICAL_PADDING_DP = 15;
|
||||
private static final int TV_HORIZONTAL_PADDING_DP = 15;
|
||||
|
||||
private static void setGameModeStatus(Context context, boolean streaming, boolean loading, boolean interruptible) {
|
||||
private static void setGameModeStatus(Context context, boolean streaming, boolean interruptible) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
GameManager gameManager = context.getSystemService(GameManager.class);
|
||||
|
||||
if (streaming) {
|
||||
gameManager.setGameState(new GameState(loading, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
|
||||
gameManager.setGameState(new GameState(false, interruptible ? GameState.MODE_GAMEPLAY_INTERRUPTIBLE : GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE));
|
||||
}
|
||||
else {
|
||||
gameManager.setGameState(new GameState(loading, GameState.MODE_NONE));
|
||||
gameManager.setGameState(new GameState(false, GameState.MODE_NONE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyStreamConnecting(Context context) {
|
||||
setGameModeStatus(context, true, true, true);
|
||||
setGameModeStatus(context, true, true);
|
||||
}
|
||||
|
||||
public static void notifyStreamConnected(Context context) {
|
||||
setGameModeStatus(context, true, false, false);
|
||||
setGameModeStatus(context, true, false);
|
||||
}
|
||||
|
||||
public static void notifyStreamEnteringPiP(Context context) {
|
||||
setGameModeStatus(context, true, false, true);
|
||||
setGameModeStatus(context, true, true);
|
||||
}
|
||||
|
||||
public static void notifyStreamExitingPiP(Context context) {
|
||||
setGameModeStatus(context, true, false, false);
|
||||
setGameModeStatus(context, true, false);
|
||||
}
|
||||
|
||||
public static void notifyStreamEnded(Context context) {
|
||||
setGameModeStatus(context, false, false, false);
|
||||
setGameModeStatus(context, false, false);
|
||||
}
|
||||
|
||||
public static void setLocale(Activity activity)
|
||||
@@ -115,7 +115,7 @@ public class UiHelper {
|
||||
UiModeManager modeMgr = (UiModeManager) activity.getSystemService(Context.UI_MODE_SERVICE);
|
||||
|
||||
// Set GameState.MODE_NONE initially for all activities
|
||||
setGameModeStatus(activity, false, false, false);
|
||||
setGameModeStatus(activity, false, false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
// Allow this non-streaming activity to layout under notches.
|
||||
|
||||
@@ -40,6 +40,7 @@ LOCAL_SRC_FILES := moonlight-common-c/src/AudioStream.c \
|
||||
moonlight-common-c/enet/win32.c \
|
||||
simplejni.c \
|
||||
callbacks.c \
|
||||
minisdl.c \
|
||||
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/moonlight-common-c/enet/include \
|
||||
|
||||
@@ -33,6 +33,9 @@ static jmethodID BridgeClConnectionTerminatedMethod;
|
||||
static jmethodID BridgeClRumbleMethod;
|
||||
static jmethodID BridgeClConnectionStatusUpdateMethod;
|
||||
static jmethodID BridgeClSetHdrModeMethod;
|
||||
static jmethodID BridgeClRumbleTriggersMethod;
|
||||
static jmethodID BridgeClSetMotionEventStateMethod;
|
||||
static jmethodID BridgeClSetControllerLEDMethod;
|
||||
static jbyteArray DecodedFrameBuffer;
|
||||
static jshortArray DecodedAudioBuffer;
|
||||
|
||||
@@ -80,7 +83,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
|
||||
BridgeDrStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStart", "()V");
|
||||
BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V");
|
||||
BridgeDrCleanupMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrCleanup", "()V");
|
||||
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIIJJ)I");
|
||||
BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIICJJ)I");
|
||||
BridgeArInitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArInit", "(III)I");
|
||||
BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V");
|
||||
BridgeArStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStop", "()V");
|
||||
@@ -94,6 +97,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) {
|
||||
BridgeClRumbleMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumble", "(SSS)V");
|
||||
BridgeClConnectionStatusUpdateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClConnectionStatusUpdate", "(I)V");
|
||||
BridgeClSetHdrModeMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetHdrMode", "(Z[B)V");
|
||||
BridgeClRumbleTriggersMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClRumbleTriggers", "(SSS)V");
|
||||
BridgeClSetMotionEventStateMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetMotionEventState", "(SBS)V");
|
||||
BridgeClSetControllerLEDMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeClSetControllerLED", "(SBBB)V");
|
||||
}
|
||||
|
||||
int BridgeDrSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
@@ -159,7 +165,7 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||
DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType,
|
||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
||||
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
|
||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
@@ -180,7 +186,7 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod,
|
||||
DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA,
|
||||
decodeUnit->frameNumber, decodeUnit->frameType,
|
||||
decodeUnit->frameNumber, decodeUnit->frameType, (jchar)decodeUnit->frameHostProcessingLatency,
|
||||
(jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
@@ -347,6 +353,40 @@ void BridgeClSetHdrMode(bool enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClRumbleTriggers(unsigned short controllerNumber, unsigned short leftTrigger, unsigned short rightTrigger) {
|
||||
JNIEnv* env = GetThreadEnv();
|
||||
|
||||
// The seemingly redundant short casts are required in order to convert the unsigned short to a signed short.
|
||||
// If we leave it as an unsigned short, CheckJNI will fail when the value exceeds 32767. The cast itself is
|
||||
// fine because the Java code treats the value as unsigned even though it's stored in a signed type.
|
||||
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClRumbleTriggersMethod, controllerNumber, (short)leftTrigger, (short)rightTrigger);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
(*JVM)->DetachCurrentThread(JVM);
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz) {
|
||||
JNIEnv* env = GetThreadEnv();
|
||||
|
||||
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetMotionEventStateMethod, controllerNumber, motionType, reportRateHz);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
(*JVM)->DetachCurrentThread(JVM);
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b) {
|
||||
JNIEnv* env = GetThreadEnv();
|
||||
|
||||
// These jbyte casts are necessary to satisfy CheckJNI
|
||||
(*env)->CallStaticVoidMethod(env, GlobalBridgeClass, BridgeClSetControllerLEDMethod, controllerNumber, (jbyte)r, (jbyte)g, (jbyte)b);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
// We will crash here
|
||||
(*JVM)->DetachCurrentThread(JVM);
|
||||
}
|
||||
}
|
||||
|
||||
void BridgeClLogMessage(const char* format, ...) {
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
@@ -381,17 +421,20 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
|
||||
.rumble = BridgeClRumble,
|
||||
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
|
||||
.setHdrMode = BridgeClSetHdrMode,
|
||||
.rumbleTriggers = BridgeClRumbleTriggers,
|
||||
.setMotionEventState = BridgeClSetMotionEventState,
|
||||
.setControllerLED = BridgeClSetControllerLED,
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
|
||||
jstring address, jstring appVersion, jstring gfeVersion,
|
||||
jstring rtspSessionUrl,
|
||||
jstring rtspSessionUrl, jint serverCodecModeSupport,
|
||||
jint width, jint height, jint fps,
|
||||
jint bitrate, jint packetSize, jint streamingRemotely,
|
||||
jint audioConfiguration, jboolean supportsHevc,
|
||||
jboolean enableHdr,
|
||||
jint audioConfiguration, jint supportedVideoFormats,
|
||||
jint hevcBitratePercentageMultiplier,
|
||||
jint av1BitratePercentageMultiplier,
|
||||
jint clientRefreshRateX100,
|
||||
jint encryptionFlags,
|
||||
jbyteArray riAesKey, jbyteArray riAesIv,
|
||||
@@ -402,6 +445,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
.serverInfoAppVersion = (*env)->GetStringUTFChars(env, appVersion, 0),
|
||||
.serverInfoGfeVersion = gfeVersion ? (*env)->GetStringUTFChars(env, gfeVersion, 0) : NULL,
|
||||
.rtspSessionUrl = rtspSessionUrl ? (*env)->GetStringUTFChars(env, rtspSessionUrl, 0) : NULL,
|
||||
.serverCodecModeSupport = serverCodecModeSupport,
|
||||
};
|
||||
STREAM_CONFIGURATION streamConfig = {
|
||||
.width = width,
|
||||
@@ -411,9 +455,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
|
||||
.packetSize = packetSize,
|
||||
.streamingRemotely = streamingRemotely,
|
||||
.audioConfiguration = audioConfiguration,
|
||||
.supportsHevc = supportsHevc,
|
||||
.enableHdr = enableHdr,
|
||||
.supportedVideoFormats = supportedVideoFormats,
|
||||
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
||||
.av1BitratePercentageMultiplier = av1BitratePercentageMultiplier,
|
||||
.clientRefreshRateX100 = clientRefreshRateX100,
|
||||
.encryptionFlags = encryptionFlags,
|
||||
.colorSpace = colorSpace,
|
||||
|
||||
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
Copyright (C) Valve Corporation
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#define MAKE_CONTROLLER_ID( nVID, nPID ) (unsigned int)( (unsigned int)nVID << 16 | (unsigned int)nPID )
|
||||
|
||||
static const ControllerDescription_t arrControllers[] = {
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x1844 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1
|
||||
//{ MAKE_CONTROLLER_ID( 0x046d, 0xc24f ), k_eControllerType_PS3Controller, NULL }, // Logitech G29 (PS3)
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x0268 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x056e, 0x200f ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x056e, 0x2013 ), k_eControllerType_PS3Controller, NULL }, // JC-U4113SBK
|
||||
{ MAKE_CONTROLLER_ID( 0x05b8, 0x1004 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x05b8, 0x1006 ), k_eControllerType_PS3Controller, NULL }, // JC-U3412SBK
|
||||
{ MAKE_CONTROLLER_ID( 0x06a3, 0xf622 ), k_eControllerType_PS3Controller, NULL }, // Cyborg V3
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x3180 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz Alpha PS3 mode
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x3250 ), k_eControllerType_PS3Controller, NULL }, // madcats fightpad pro ps3
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x3481 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz FightStick TE 2+ PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8180 ), k_eControllerType_PS3Controller, NULL }, // Mad Catz Alpha PS4 mode (no touchpad on device)
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8838 ), k_eControllerType_PS3Controller, NULL }, // Madcatz Fightstick Pro
|
||||
{ MAKE_CONTROLLER_ID( 0x0810, 0x0001 ), k_eControllerType_PS3Controller, NULL }, // actually ps2 - maybe break out later
|
||||
{ MAKE_CONTROLLER_ID( 0x0810, 0x0003 ), k_eControllerType_PS3Controller, NULL }, // actually ps2 - maybe break out later
|
||||
{ MAKE_CONTROLLER_ID( 0x0925, 0x0005 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0925, 0x8866 ), k_eControllerType_PS3Controller, NULL }, // PS2 maybe break out later
|
||||
{ MAKE_CONTROLLER_ID( 0x0925, 0x8888 ), k_eControllerType_PS3Controller, NULL }, // Actually ps2 -maybe break out later Lakeview Research WiseGroup Ltd, MP-8866 Dual Joypad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0109 ), k_eControllerType_PS3Controller, NULL }, // PDP Versus Fighting Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x011e ), k_eControllerType_PS3Controller, NULL }, // Rock Candy PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0128 ), k_eControllerType_PS3Controller, NULL }, // Rock Candy PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0214 ), k_eControllerType_PS3Controller, NULL }, // afterglow ps3
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x1314 ), k_eControllerType_PS3Controller, NULL }, // PDP Afterglow Wireless PS3 controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x6302 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x0008 ), k_eControllerType_PS3Controller, NULL }, // Green Asia
|
||||
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x3075 ), k_eControllerType_PS3Controller, NULL }, // SpeedLink Strike FX
|
||||
{ MAKE_CONTROLLER_ID( 0x0e8f, 0x310d ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0009 ), k_eControllerType_PS3Controller, NULL }, // HORI BDA GP1
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x004d ), k_eControllerType_PS3Controller, NULL }, // Horipad 3
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x005f ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander 4 PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006a ), k_eControllerType_PS3Controller, NULL }, // Real Arcade Pro 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006e ), k_eControllerType_PS3Controller, NULL }, // HORI horipad4 ps3
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0085 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0086 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Commander PC (Uses the Xbox 360 protocol, but has PS3 buttons)
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0088 ), k_eControllerType_PS3Controller, NULL }, // HORI Fighting Stick mini 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f30, 0x1100 ), k_eControllerType_PS3Controller, NULL }, // Qanba Q1 fight stick
|
||||
{ MAKE_CONTROLLER_ID( 0x11ff, 0x3331 ), k_eControllerType_PS3Controller, NULL }, // SRXJ-PH2400
|
||||
{ MAKE_CONTROLLER_ID( 0x1345, 0x1000 ), k_eControllerType_PS3Controller, NULL }, // PS2 ACME GA-D5
|
||||
{ MAKE_CONTROLLER_ID( 0x1345, 0x6005 ), k_eControllerType_PS3Controller, NULL }, // ps2 maybe break out later
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x1a34, 0x0836 ), k_eControllerType_PS3Controller, NULL }, // Afterglow PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x20bc, 0x5500 ), k_eControllerType_PS3Controller, NULL }, // ShanWan PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x576d ), k_eControllerType_PS3Controller, NULL }, // Power A PS3
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xca6d ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x2563, 0x0523 ), k_eControllerType_PS3Controller, NULL }, // Digiflip GP006
|
||||
{ MAKE_CONTROLLER_ID( 0x2563, 0x0575 ), k_eControllerType_PS3Controller, NULL }, // From SDL
|
||||
{ MAKE_CONTROLLER_ID( 0x25f0, 0x83c3 ), k_eControllerType_PS3Controller, NULL }, // gioteck vx2
|
||||
{ MAKE_CONTROLLER_ID( 0x25f0, 0xc121 ), k_eControllerType_PS3Controller, NULL }, //
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2003 ), k_eControllerType_PS3Controller, NULL }, // Qanba Drone
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2302 ), k_eControllerType_PS3Controller, NULL }, // Qanba Obsidian
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2502 ), k_eControllerType_PS3Controller, NULL }, // Qanba Dragon
|
||||
{ MAKE_CONTROLLER_ID( 0x8380, 0x0003 ), k_eControllerType_PS3Controller, NULL }, // BTP 2163
|
||||
{ MAKE_CONTROLLER_ID( 0x8888, 0x0308 ), k_eControllerType_PS3Controller, NULL }, // Sony PS3 Controller
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x181b ), k_eControllerType_PS4Controller, NULL }, // Venom Arcade Stick - XXX:this may not work and may need to be called a ps3 controller
|
||||
//{ MAKE_CONTROLLER_ID( 0x046d, 0xc260 ), k_eControllerType_PS4Controller, NULL }, // Logitech G29 (PS4)
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xd00e ), k_eControllerType_PS4Controller, NULL }, // Thrustmaster Eswap Pro - No gyro and lightbar doesn't change color. Works otherwise
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x05c4 ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x05c5 ), k_eControllerType_PS4Controller, NULL }, // STRIKEPAD PS4 Grip Add-on
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x09cc ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Slim Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x0ba0 ), k_eControllerType_PS4Controller, NULL }, // Sony PS4 Controller (Wireless dongle)
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8250 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightPad Pro PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8384 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE S+ PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8480 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE 2 PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x8481 ), k_eControllerType_PS4Controller, NULL }, // Mad Catz FightStick TE 2+ PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e10 ), k_eControllerType_PS4Controller, NULL }, // Armor Armor 3 Pad PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e13 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e15 ), k_eControllerType_PS4Controller, NULL }, // Game:Pad 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0e20 ), k_eControllerType_PS4Controller, NULL }, // Brook Mars Controller - needs FW update to show up as Ps4 controller on PC. Has Gyro but touchpad is a single button.
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0055 ), k_eControllerType_PS4Controller, NULL }, // HORIPAD 4 FPS
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x005e ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander 4 PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0066 ), k_eControllerType_PS4Controller, NULL }, // HORIPAD 4 FPS Plus
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0084 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0087 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Stick mini 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x008a ), k_eControllerType_PS4Controller, NULL }, // HORI Real Arcade Pro 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x009c ), k_eControllerType_PS4Controller, NULL }, // HORI TAC PRO mousething
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00a0 ), k_eControllerType_PS4Controller, NULL }, // HORI TAC4 mousething
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ed ), k_eControllerType_XInputPS4Controller, NULL }, // Hori Fighting Stick mini 4 kai - becomes an Xbox 360 controller on PC
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ee ), k_eControllerType_PS4Controller, NULL }, // Hori mini wired https://www.playstation.com/en-us/explore/accessories/gaming-controllers/mini-wired-gamepad/
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x011c ), k_eControllerType_PS4Controller, NULL }, // Hori Fighting Stick α
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0123 ), k_eControllerType_PS4Controller, NULL }, // HORI Wireless Controller Light (Japan only) - only over bt- over usb is xbox and pid 0x0124
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0162 ), k_eControllerType_PS4Controller, NULL }, // HORI Fighting Commander OCTA
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0164 ), k_eControllerType_XInputPS4Controller, NULL }, // HORI Fighting Commander OCTA
|
||||
{ MAKE_CONTROLLER_ID( 0x11c0, 0x4001 ), k_eControllerType_PS4Controller, NULL }, // "PS4 Fun Controller" added from user log
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0603 ), k_eControllerType_XInputPS4Controller, NULL }, // Nacon PS4 Compact Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0604 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Daija Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0605 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON PS4 controller in Xbox mode - might also be other bigben brand xbox controllers
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0606 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0609 ), k_eControllerType_XInputPS4Controller, NULL }, // NACON Wireless Controller for PS4
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d01 ), k_eControllerType_PS4Controller, NULL }, // Nacon Revolution Pro Controller - has gyro
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d02 ), k_eControllerType_PS4Controller, NULL }, // Nacon Revolution Pro Controller v2 - has gyro
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d06 ), k_eControllerType_PS4Controller, NULL }, // NACON Asymetrical Controller Wireless Dongle -- show up as ps4 until you connect controller to it then it reboots into Xbox controller with different vvid/pid
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d08 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Unlimited Wireless Dongle
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d09 ), k_eControllerType_PS4Controller, NULL }, // NACON Daija Fight Stick - touchpad but no gyro/rumble
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d10 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Infinite - has gyro
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d10 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Unlimited
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0d13 ), k_eControllerType_PS4Controller, NULL }, // NACON Revolution Pro Controller 3
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x1103 ), k_eControllerType_PS4Controller, NULL }, // NACON Asymetrical Controller -- on windows this doesn't enumerate
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0X0401 ), k_eControllerType_PS4Controller, NULL }, // Razer Panthera PS4 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1000 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju PS4 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1004 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Ultimate USB
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1007 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Tournament edition USB
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1008 ), k_eControllerType_PS4Controller, NULL }, // Razer Panthera Evo Fightstick
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1009 ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Ultimate BT
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x100A ), k_eControllerType_PS4Controller, NULL }, // Razer Raiju 2 Tournament edition BT
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x1100 ), k_eControllerType_PS4Controller, NULL }, // Razer RAION Fightpad - Trackpad, no gyro, lightbar hardcoded to green
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x792a ), k_eControllerType_PS4Controller, NULL }, // PowerA Fusion Fight Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2000 ), k_eControllerType_PS4Controller, NULL }, // Qanba Drone
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2300 ), k_eControllerType_PS4Controller, NULL }, // Qanba Obsidian
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2303 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Obsidian Arcade Joystick
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2500 ), k_eControllerType_PS4Controller, NULL }, // Qanba Dragon
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2503 ), k_eControllerType_XInputPS4Controller, NULL }, // Qanba Dragon Arcade Joystick
|
||||
{ MAKE_CONTROLLER_ID( 0x7545, 0x0104 ), k_eControllerType_PS4Controller, NULL }, // Armor 3 or Level Up Cobra - At least one variant has gyro
|
||||
{ MAKE_CONTROLLER_ID (0x9886, 0x0024 ), k_eControllerType_XInputPS4Controller, NULL }, // Astro C40 in Xbox 360 mode
|
||||
{ MAKE_CONTROLLER_ID( 0x9886, 0x0025 ), k_eControllerType_PS4Controller, NULL }, // Astro C40
|
||||
// Removing the Giotek because there were a bunch of help tickets from users w/ issues including from non-PS4 controller users. This VID/PID is probably used in different FW's
|
||||
// { MAKE_CONTROLLER_ID( 0x7545, 0x1122 ), k_eControllerType_PS4Controller, NULL }, // Giotek VX4 - trackpad/gyro don't work. Had to not filter on interface info. Light bar is flaky, but works.
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x0ce6 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x054c, 0x0df2 ), k_eControllerType_PS5Controller, NULL }, // Sony DualSense Edge Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0163 ), k_eControllerType_PS5Controller, NULL }, // HORI Fighting Commander OCTA
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0184 ), k_eControllerType_PS5Controller, NULL }, // Hori Fighting Stick α
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x100b ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wired)
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x100c ), k_eControllerType_PS5Controller, NULL }, // Razer Wolverine V2 Pro (Wireless)
|
||||
{ MAKE_CONTROLLER_ID( 0x358a, 0x0104 ), k_eControllerType_PS5Controller, NULL }, // Backbone One PlayStation Edition for iOS
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x0006 ), k_eControllerType_UnknownNonSteamController, NULL }, // DragonRise Generic USB PCB, sometimes configured as a PC Twin Shock Controller - looks like a DS3 but the face buttons are 1-4 instead of symbols
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x18d4 ), k_eControllerType_XBox360Controller, NULL }, // GPD Win 2 X-Box Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x03eb, 0xff02 ), k_eControllerType_XBox360Controller, NULL }, // Wooting Two
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xb326 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Gamepad GP XID
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x028e ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Wireless Controller with XUSB driver on Windows
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21e ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F510
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21f ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F710
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xc242 ), k_eControllerType_XBox360Controller, NULL }, // Logitech Chillstream Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x056e, 0x2004 ), k_eControllerType_XBox360Controller, NULL }, // Elecom JC-U3613M
|
||||
// This isn't actually an Xbox 360 controller, it just looks like one
|
||||
// { MAKE_CONTROLLER_ID( 0x06a3, 0xf51a ), k_eControllerType_XBox360Controller, NULL }, // Saitek P3600
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4716 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wired Xbox 360 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4718 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV FightStick SE
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4726 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox 360 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4728 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV FightPad
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4736 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MicroCon Gamepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4738 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Wired Xbox 360 Controller (SFIV)
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4740 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Beat Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0xb726 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox controller - MW2
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0xbeef ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz JOYTECH NEO SE Advanced GamePad
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0xcb02 ), k_eControllerType_XBox360Controller, NULL }, // Saitek Cyborg Rumble Pad - PC/Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0xcb03 ), k_eControllerType_XBox360Controller, NULL }, // Saitek P3200 Rumble Pad - PC/Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0xf738 ), k_eControllerType_XBox360Controller, NULL }, // Super SFIV FightStick TE S
|
||||
{ MAKE_CONTROLLER_ID( 0x0955, 0x7210 ), k_eControllerType_XBox360Controller, NULL }, // Nvidia Shield local controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0955, 0xb400 ), k_eControllerType_XBox360Controller, NULL }, // NVIDIA Shield streaming controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0105 ), k_eControllerType_XBox360Controller, NULL }, // HSM3 Xbox360 dancepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0113 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x011f ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Rock Candy" }, // PDP Rock Candy Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0125 ), k_eControllerType_XBox360Controller, "PDP INJUSTICE FightStick" }, // PDP INJUSTICE FightStick for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0127 ), k_eControllerType_XBox360Controller, "PDP INJUSTICE FightPad" }, // PDP INJUSTICE FightPad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0131 ), k_eControllerType_XBox360Controller, "PDP EA Soccer Controller" }, // PDP EA Soccer Gamepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0133 ), k_eControllerType_XBox360Controller, "PDP Battlefield 4 Controller" }, // PDP Battlefield 4 Gamepad
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0143 ), k_eControllerType_XBox360Controller, "PDP MK X Fight Stick" }, // PDP MK X Fight Stick for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0147 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Marvel Controller" }, // PDP Marvel Controller for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0201 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0213 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x021f ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Rock Candy" }, // PDP Rock Candy Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0301 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0313 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0314 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Afterglow" }, // PDP Afterglow Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0401 ), k_eControllerType_XBox360Controller, "PDP Xbox 360 Controller" }, // PDP Gamepad for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0413 ), k_eControllerType_XBox360Controller, NULL }, // PDP Afterglow AX.1 (unlisted)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0501 ), k_eControllerType_XBox360Controller, NULL }, // PDP Xbox 360 Controller (unlisted)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0xf900 ), k_eControllerType_XBox360Controller, NULL }, // PDP Afterglow AX.1 (unlisted)
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000a ), k_eControllerType_XBox360Controller, NULL }, // Hori Co. DOA4 FightStick
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000c ), k_eControllerType_XBox360Controller, NULL }, // Hori PadEX Turbo
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x000d ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick EX2
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0016 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.EX
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x001b ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro VX
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x008c ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro 4
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00db ), k_eControllerType_XBox360Controller, "HORI Slime Controller" }, // Hori Dragon Quest Slime Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x011e ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick α
|
||||
{ MAKE_CONTROLLER_ID( 0x1038, 0x1430 ), k_eControllerType_XBox360Controller, "SteelSeries Stratus Duo" }, // SteelSeries Stratus Duo
|
||||
{ MAKE_CONTROLLER_ID( 0x1038, 0x1431 ), k_eControllerType_XBox360Controller, "SteelSeries Stratus Duo" }, // SteelSeries Stratus Duo
|
||||
{ MAKE_CONTROLLER_ID( 0x1038, 0xb360 ), k_eControllerType_XBox360Controller, NULL }, // SteelSeries Nimbus/Stratus XL
|
||||
{ MAKE_CONTROLLER_ID( 0x11c9, 0x55f0 ), k_eControllerType_XBox360Controller, NULL }, // Nacon GC-100XF
|
||||
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0004 ), k_eControllerType_XBox360Controller, NULL }, // Honey Bee Xbox360 dancepad
|
||||
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0301 ), k_eControllerType_XBox360Controller, NULL }, // PDP AFTERGLOW AX.1
|
||||
{ MAKE_CONTROLLER_ID( 0x12ab, 0x0303 ), k_eControllerType_XBox360Controller, NULL }, // Mortal Kombat Klassic FightStick
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Controller Adapter
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x4748 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Guitar Hero X-plorer
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0xf801 ), k_eControllerType_XBox360Controller, NULL }, // RedOctane Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0601 ), k_eControllerType_XBox360Controller, NULL }, // BigBen Interactive XBOX 360 Controller
|
||||
// { MAKE_CONTROLLER_ID( 0x1532, 0x0037 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
|
||||
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f00 ), k_eControllerType_XBox360Controller, NULL }, // Power A Mini Pro Elite
|
||||
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f0a ), k_eControllerType_XBox360Controller, NULL }, // Xbox Airflo wired controller
|
||||
{ MAKE_CONTROLLER_ID( 0x15e4, 0x3f10 ), k_eControllerType_XBox360Controller, NULL }, // Batarang Xbox 360 controller
|
||||
{ MAKE_CONTROLLER_ID( 0x162e, 0xbeef ), k_eControllerType_XBox360Controller, NULL }, // Joytech Neo-Se Take2
|
||||
{ MAKE_CONTROLLER_ID( 0x1689, 0xfd00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza Tournament Edition
|
||||
{ MAKE_CONTROLLER_ID( 0x1689, 0xfd01 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza Classic Edition
|
||||
{ MAKE_CONTROLLER_ID( 0x1689, 0xfe00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
|
||||
{ MAKE_CONTROLLER_ID( 0x1949, 0x041a ), k_eControllerType_XBox360Controller, "Amazon Luna Controller" }, // Amazon Luna Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0x0002 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Rock Band Guitar
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0x0003 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Rock Band Drumkit
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf016 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Xbox 360 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf018 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Street Fighter IV SE Fighting Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf019 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Brawlstick for Xbox 360
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf021 ), k_eControllerType_XBox360Controller, NULL }, // Mad Cats Ghost Recon FS GamePad
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf023 ), k_eControllerType_XBox360Controller, NULL }, // MLG Pro Circuit Controller (Xbox)
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf025 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Call Of Duty
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf027 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FPS Pro
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf028 ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV FightPad
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf02e ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Fightpad
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf036 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MicroCon GamePad Pro
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf038 ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV FightStick TE
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf039 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MvC2 TE
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03a ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz SFxT Fightstick Pro
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03d ), k_eControllerType_XBox360Controller, NULL }, // Street Fighter IV Arcade Stick TE - Chun Li
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03e ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz MLG FightStick TE
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf03f ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick SoulCaliber
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf042 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick TES+
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf080 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz FightStick TE2
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf501 ), k_eControllerType_XBox360Controller, NULL }, // HoriPad EX2 Turbo
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf502 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.VX SA
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf503 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick VX
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf504 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro. EX
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf505 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick EX2B
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf506 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro.EX Premium VLX
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf900 ), k_eControllerType_XBox360Controller, NULL }, // Harmonix Xbox 360 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf901 ), k_eControllerType_XBox360Controller, NULL }, // Gamestop Xbox 360 Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf902 ), k_eControllerType_XBox360Controller, NULL }, // Mad Catz Gamepad2
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf903 ), k_eControllerType_XBox360Controller, NULL }, // Tron Xbox 360 controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf904 ), k_eControllerType_XBox360Controller, NULL }, // PDP Versus Fighting Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xf906 ), k_eControllerType_XBox360Controller, NULL }, // MortalKombat FightStick
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfa01 ), k_eControllerType_XBox360Controller, NULL }, // MadCatz GamePad
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfd00 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza TE
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0xfd01 ), k_eControllerType_XBox360Controller, NULL }, // Razer Onza
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5000 ), k_eControllerType_XBox360Controller, NULL }, // Razer Atrox Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5300 ), k_eControllerType_XBox360Controller, NULL }, // PowerA MINI PROEX Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5303 ), k_eControllerType_XBox360Controller, NULL }, // Xbox Airflo wired controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x530a ), k_eControllerType_XBox360Controller, NULL }, // Xbox 360 Pro EX Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x531a ), k_eControllerType_XBox360Controller, NULL }, // PowerA Pro Ex
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5397 ), k_eControllerType_XBox360Controller, NULL }, // FUS1ON Tournament Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5500 ), k_eControllerType_XBox360Controller, NULL }, // Hori XBOX 360 EX 2 with Turbo
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5501 ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro VX-SA
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5502 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Stick VX Alt
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5503 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Edge
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5506 ), k_eControllerType_XBox360Controller, NULL }, // Hori SOULCALIBUR V Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x550d ), k_eControllerType_XBox360Controller, NULL }, // Hori GEM Xbox controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x550e ), k_eControllerType_XBox360Controller, NULL }, // Hori Real Arcade Pro V Kai 360
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5508 ), k_eControllerType_XBox360Controller, NULL }, // Hori PAD A
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5510 ), k_eControllerType_XBox360Controller, NULL }, // Hori Fighting Commander ONE
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b00 ), k_eControllerType_XBox360Controller, NULL }, // ThrustMaster Ferrari Italia 458 Racing Wheel
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b02 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster, Inc. GPX Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5b03 ), k_eControllerType_XBox360Controller, NULL }, // Thrustmaster Ferrari 458 Racing Wheel
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5d04 ), k_eControllerType_XBox360Controller, NULL }, // Razer Sabertooth
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafa ), k_eControllerType_XBox360Controller, NULL }, // Aplay Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafb ), k_eControllerType_XBox360Controller, NULL }, // Aplay Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafc ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 1
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafd ), k_eControllerType_XBox360Controller, NULL }, // Afterglow Gamepad 3
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfafe ), k_eControllerType_XBox360Controller, NULL }, // Rock Candy Gamepad for Xbox 360
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x044f, 0xd012 ), k_eControllerType_XBoxOneController, NULL }, // ThrustMaster eSwap PRO Controller Xbox
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02d1 ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02dd ), k_eControllerType_XBoxOneController, "Xbox One Controller" }, // Microsoft X-Box One pad (Firmware 2015)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e0 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with XBOXGIP driver on Windows
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad
|
||||
// { MAKE_CONTROLLER_ID( 0x045e, 0x0b02 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // The virtual keyboard generated by XboxGip drivers for Xbox One Controllers (see https://github.com/libsdl-org/SDL/pull/5121 for details)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0a ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b0c ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (Bluetooth)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox Series X Controller" }, // Microsoft X-Box Series X pad (BLE)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b20 ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (BLE)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b21 ), k_eControllerType_XBoxOneController, "Xbox Adaptive Controller" }, // Microsoft X-Box Adaptive pad (BLE)
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b22 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (BLE)
|
||||
{ MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013a ), k_eControllerType_XBoxOneController, NULL }, // PDP Xbox One Controller (unlisted)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0145 ), k_eControllerType_XBoxOneController, "PDP MK X Fight Pad" }, // PDP MK X Fight Pad for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0146 ), k_eControllerType_XBoxOneController, "PDP Xbox One Rock Candy" }, // PDP Rock Candy Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015b ), k_eControllerType_XBoxOneController, "PDP Fallout 4 Vault Boy Controller" }, // PDP Fallout 4 Vault Boy Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015c ), k_eControllerType_XBoxOneController, "PDP Xbox One @Play Controller" }, // PDP @Play Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015d ), k_eControllerType_XBoxOneController, "PDP Mirror's Edge Controller" }, // PDP Mirror's Edge Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x015f ), k_eControllerType_XBoxOneController, "PDP Metallic Controller" }, // PDP Metallic Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0160 ), k_eControllerType_XBoxOneController, "PDP NFL Face-Off Controller" }, // PDP NFL Official Face-Off Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0161 ), k_eControllerType_XBoxOneController, "PDP Xbox One Camo" }, // PDP Camo Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0162 ), k_eControllerType_XBoxOneController, "PDP Xbox One Controller" }, // PDP Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0163 ), k_eControllerType_XBoxOneController, "PDP Deliverer of Truth" }, // PDP Legendary Collection: Deliverer of Truth
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0164 ), k_eControllerType_XBoxOneController, "PDP Battlefield 1 Controller" }, // PDP Battlefield 1 Official Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0165 ), k_eControllerType_XBoxOneController, "PDP Titanfall 2 Controller" }, // PDP Titanfall 2 Official Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0166 ), k_eControllerType_XBoxOneController, "PDP Mass Effect: Andromeda Controller" }, // PDP Mass Effect: Andromeda Official Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0167 ), k_eControllerType_XBoxOneController, "PDP Halo Wars 2 Face-Off Controller" }, // PDP Halo Wars 2 Official Face-Off Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0205 ), k_eControllerType_XBoxOneController, "PDP Victrix Pro Fight Stick" }, // PDP Victrix Pro Fight Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0206 ), k_eControllerType_XBoxOneController, "PDP Mortal Kombat Controller" }, // PDP Mortal Kombat 25 Anniversary Edition Stick (Xbox One)
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0246 ), k_eControllerType_XBoxOneController, "PDP Xbox One Rock Candy" }, // PDP Rock Candy Wired Controller for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0261 ), k_eControllerType_XBoxOneController, "PDP Xbox One Camo" }, // PDP Camo Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0262 ), k_eControllerType_XBoxOneController, "PDP Xbox One Controller" }, // PDP Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Wired Controller for Xbox One - Midnight Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Wired Controller for Xbox One - Verdant Green
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a2 ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Wired Controller for Xbox One - Crimson Red
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a4 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Wired Controller for Xbox One - Stealth Series | Phantom Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Wired Controller for Xbox One - Stealth Series | Ghost White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a6 ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Wired Controller for Xbox One - Stealth Series | Revenant Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a7 ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Wired Controller for Xbox One - Raven Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a8 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02a9 ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Wired Controller for Xbox One - Midnight Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02aa ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Wired Controller for Xbox One - Verdant Green
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ab ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Wired Controller for Xbox One - Crimson Red
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ac ), k_eControllerType_XBoxOneController, "PDP Xbox One Ember Orange" }, // PDP Wired Controller for Xbox One - Ember Orange
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ad ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Wired Controller for Xbox One - Stealth Series | Phantom Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ae ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Wired Controller for Xbox One - Stealth Series | Ghost White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02af ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Wired Controller for Xbox One - Stealth Series | Revenant Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Wired Controller for Xbox One - Raven Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Wired Controller for Xbox One - Arctic White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Prismatic Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b5 ), k_eControllerType_XBoxOneController, "PDP Xbox One GAMEware Controller" }, // PDP GAMEware Wired Controller Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02b6 ), k_eControllerType_XBoxOneController, NULL }, // PDP One-Handed Joystick Adaptive Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02bd ), k_eControllerType_XBoxOneController, "PDP Xbox One Royal Purple" }, // PDP Wired Controller for Xbox One - Royal Purple
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02be ), k_eControllerType_XBoxOneController, "PDP Xbox One Raven Black" }, // PDP Deluxe Wired Controller for Xbox One - Raven Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02bf ), k_eControllerType_XBoxOneController, "PDP Xbox One Midnight Blue" }, // PDP Deluxe Wired Controller for Xbox One - Midnight Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c0 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantom Black" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Phantom Black
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c1 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ghost White" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Ghost White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c2 ), k_eControllerType_XBoxOneController, "PDP Xbox One Revenant Blue" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Revenant Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c3 ), k_eControllerType_XBoxOneController, "PDP Xbox One Verdant Green" }, // PDP Deluxe Wired Controller for Xbox One - Verdant Green
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c4 ), k_eControllerType_XBoxOneController, "PDP Xbox One Ember Orange" }, // PDP Deluxe Wired Controller for Xbox One - Ember Orange
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Royal Purple" }, // PDP Deluxe Wired Controller for Xbox One - Royal Purple
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c6 ), k_eControllerType_XBoxOneController, "PDP Xbox One Crimson Red" }, // PDP Deluxe Wired Controller for Xbox One - Crimson Red
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c7 ), k_eControllerType_XBoxOneController, "PDP Xbox One Arctic White" }, // PDP Deluxe Wired Controller for Xbox One - Arctic White
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c8 ), k_eControllerType_XBoxOneController, "PDP Kingdom Hearts Controller" }, // PDP Kingdom Hearts Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02c9 ), k_eControllerType_XBoxOneController, "PDP Xbox One Phantasm Red" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Phantasm Red
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ca ), k_eControllerType_XBoxOneController, "PDP Xbox One Specter Violet" }, // PDP Deluxe Wired Controller for Xbox One - Stealth Series | Specter Violet
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cb ), k_eControllerType_XBoxOneController, "PDP Xbox One Specter Violet" }, // PDP Wired Controller for Xbox One - Stealth Series | Specter Violet
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cd ), k_eControllerType_XBoxOneController, "PDP Xbox One Blu-merang" }, // PDP Rock Candy Wired Controller for Xbox One - Blu-merang
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02ce ), k_eControllerType_XBoxOneController, "PDP Xbox One Cranblast" }, // PDP Rock Candy Wired Controller for Xbox One - Cranblast
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02cf ), k_eControllerType_XBoxOneController, "PDP Xbox One Aqualime" }, // PDP Rock Candy Wired Controller for Xbox One - Aqualime
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d5 ), k_eControllerType_XBoxOneController, "PDP Xbox One Red Camo" }, // PDP Wired Controller for Xbox One - Red Camo
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0346 ), k_eControllerType_XBoxOneController, "PDP Xbox One RC Gamepad" }, // PDP RC Gamepad for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0446 ), k_eControllerType_XBoxOneController, "PDP Xbox One RC Gamepad" }, // PDP RC Gamepad for Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02da ), k_eControllerType_XBoxOneController, "PDP Xbox Series X Afterglow" }, // PDP Xbox Series X Afterglow
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d6 ), k_eControllerType_XBoxOneController, "Victrix Gambit Tournament Controller" }, // Victrix Gambit Tournament Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x02d9 ), k_eControllerType_XBoxOneController, "PDP Xbox Series X Midnight Blue" }, // PDP Xbox Series X Midnight Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0063 ), k_eControllerType_XBoxOneController, NULL }, // Hori Real Arcade Pro Hayabusa (USA) Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0067 ), k_eControllerType_XBoxOneController, NULL }, // HORIPAD ONE
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0078 ), k_eControllerType_XBoxOneController, NULL }, // Hori Real Arcade Pro V Kai Xbox One
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00c5 ), k_eControllerType_XBoxOneController, NULL }, // HORI Fighting Commander
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0150 ), k_eControllerType_XBoxOneController, NULL }, // HORI Fighting Commander OCTA for Xbox Series X
|
||||
{ MAKE_CONTROLLER_ID( 0x10f5, 0x7009 ), k_eControllerType_XBoxOneController, NULL }, // Turtle Beach Recon Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x10f5, 0x7013 ), k_eControllerType_XBoxOneController, NULL }, // Turtle Beach REACT-R
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a00 ), k_eControllerType_XBoxOneController, NULL }, // Razer Atrox Arcade Stick
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a03 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wildcat
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a14 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wolverine Ultimate
|
||||
{ MAKE_CONTROLLER_ID( 0x1532, 0x0a15 ), k_eControllerType_XBoxOneController, NULL }, // Razer Wolverine Tournament Edition
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2001 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Black Inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2002 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Gray/White Inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2003 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Green Inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2004 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Pink inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2005 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Wired Controller Core - Black
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2006 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Wired Controller Core - White
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2009 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Red inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200a ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Blue inline
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200b ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Camo Metallic Red
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200c ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Camo Metallic Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200d ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Seafoam Fade
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200e ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Midnight Blue
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x200f ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Soldier Green
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2011 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired - Metallic Ice
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2012 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X Cuphead EnWired Controller - Mugman
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2015 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Blue Hint
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2016 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller - Green Hint
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2017 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Cntroller - Arctic Camo
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2018 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Arc Lightning
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x2019 ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Royal Purple
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x201a ), k_eControllerType_XBoxOneController, "PowerA Xbox Series X Controller" }, // PowerA Xbox Series X EnWired Controller Nebula
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x4001 ), k_eControllerType_XBoxOneController, "PowerA Fusion Pro 2 Controller" }, // PowerA Fusion Pro 2 Wired Controller (Xbox Series X style)
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x4002 ), k_eControllerType_XBoxOneController, "PowerA Spectra Infinity Controller" }, // PowerA Spectra Infinity Wired Controller (Xbox Series X style)
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0x890b ), k_eControllerType_XBoxOneController, NULL }, // PowerA MOGA XP-Ultra Controller (Xbox Series X style)
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x541a ), k_eControllerType_XBoxOneController, NULL }, // PowerA Xbox One Mini Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x542a ), k_eControllerType_XBoxOneController, NULL }, // Xbox ONE spectra
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x543a ), k_eControllerType_XBoxOneController, "PowerA Xbox One Controller" }, // PowerA Xbox ONE liquid metal controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x551a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Pro Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x561a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x581a ), k_eControllerType_XBoxOneController, NULL }, // BDA XB1 Classic Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x591a ), k_eControllerType_XBoxOneController, NULL }, // PowerA FUSION Pro Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x592a ), k_eControllerType_XBoxOneController, NULL }, // BDA XB1 Spectra Pro
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x791a ), k_eControllerType_XBoxOneController, NULL }, // PowerA Fusion Fight Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x2dc8, 0x2002 ), k_eControllerType_XBoxOneController, NULL }, // 8BitDo Ultimate Wired Controller for Xbox
|
||||
{ MAKE_CONTROLLER_ID( 0x2e24, 0x0652 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke
|
||||
{ MAKE_CONTROLLER_ID( 0x2e24, 0x1618 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin Duke
|
||||
{ MAKE_CONTROLLER_ID( 0x2e24, 0x1688 ), k_eControllerType_XBoxOneController, NULL }, // Hyperkin X91
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0611 ), k_eControllerType_XBoxOneController, NULL }, // Xbox Controller Mode for NACON Revolution 3
|
||||
|
||||
// These have been added via Minidump for unrecognized Xinput controller assert
|
||||
{ MAKE_CONTROLLER_ID( 0x0000, 0x0000 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a2 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller - Microsoft VID
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x1414 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0159 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0xfaff ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x006d ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00a4 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x1832 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x187f ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x1883 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x03eb, 0xff01 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef8 ), k_eControllerType_XBox360Controller, NULL }, // Homemade fightstick based on brook pcb (with XInput driver??)
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0x1000 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1345, 0x6006 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x056e, 0x2012 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x146b, 0x0602 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00ae ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0x0401 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0x0301 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xcaa3 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0xc261 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
|
||||
{ MAKE_CONTROLLER_ID( 0x046d, 0x0291 ), k_eControllerType_XBox360Controller, NULL }, // logitech xinput
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x18d3 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00b1 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0001, 0x0001 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x188e ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x187c ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x189c ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0079, 0x1874 ), k_eControllerType_XBox360Controller, NULL }, // Unknown Controller
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x0050 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x2e ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x91 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x719 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xf0d, 0xed ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xf0d, 0xc0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x152 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2a7 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x46d, 0x1007 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2b8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2a8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x79, 0x18a1 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
|
||||
/* Added from Minidumps 10-9-19 */
|
||||
{ MAKE_CONTROLLER_ID( 0x0, 0x6686 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x11ff, 0x511 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x12ab, 0x304 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x291 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x2a9 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1430, 0x70b ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0x28e ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0x2a0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x1bad, 0x5500 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x20ab, 0x55ef ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x24c6, 0x5509 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2516, 0x69 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x25b1, 0x360 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2c22, 0x2203 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x11 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x53 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0xb7 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x46d, 0x0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x46d, 0x1004 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x46d, 0x1008 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x46d, 0xf301 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x738, 0x2a0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x738, 0x7263 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x738, 0xb738 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x738, 0xcb29 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x738, 0xf401 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x79, 0x18c2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x79, 0x18c8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x79, 0x18cf ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xc12, 0xe17 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xc12, 0xe1c ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xc12, 0xe22 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xc12, 0xe30 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xd2d2, 0xd2d2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xd62, 0x9a1a ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xd62, 0x9a1b ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe00, 0xe00 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x12a ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2a1 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2a2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2a5 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2b2 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2bd ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2bf ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2c0 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0x2c6 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xf0d, 0x97 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xf0d, 0xba ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xf0d, 0xd8 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xfff, 0x2a1 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x45e, 0x867 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
// Added 12-17-2020
|
||||
{ MAKE_CONTROLLER_ID( 0x16d0, 0xf3f ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x2f24, 0x8f ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
{ MAKE_CONTROLLER_ID( 0xe6f, 0xf501 ), k_eControllerType_XBoxOneController, NULL }, // Unknown Controller
|
||||
|
||||
//{ MAKE_CONTROLLER_ID( 0x1949, 0x0402 ), /*android*/, NULL }, // Unknown Controller
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x05ac, 0x0001 ), k_eControllerType_AppleController, NULL }, // MFI Extended Gamepad (generic entry for iOS/tvOS)
|
||||
{ MAKE_CONTROLLER_ID( 0x05ac, 0x0002 ), k_eControllerType_AppleController, NULL }, // MFI Standard Gamepad (generic entry for iOS/tvOS)
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x057e, 0x2006 ), k_eControllerType_SwitchJoyConLeft, NULL }, // Nintendo Switch Joy-Con (Left)
|
||||
{ MAKE_CONTROLLER_ID( 0x057e, 0x2007 ), k_eControllerType_SwitchJoyConRight, NULL }, // Nintendo Switch Joy-Con (Right)
|
||||
{ MAKE_CONTROLLER_ID( 0x057e, 0x2008 ), k_eControllerType_SwitchJoyConPair, NULL }, // Nintendo Switch Joy-Con (Left+Right Combined)
|
||||
|
||||
// This same controller ID is spoofed by many 3rd-party Switch controllers.
|
||||
// The ones we currently know of are:
|
||||
// * Any 8bitdo controller with Switch support
|
||||
// * ORTZ Gaming Wireless Pro Controller
|
||||
// * ZhiXu Gamepad Wireless
|
||||
// * Sunwaytek Wireless Motion Controller for Nintendo Switch
|
||||
{ MAKE_CONTROLLER_ID( 0x057e, 0x2009 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Switch Pro Controller
|
||||
//{ MAKE_CONTROLLER_ID( 0x057e, 0x2017 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online SNES Controller
|
||||
//{ MAKE_CONTROLLER_ID( 0x057e, 0x2019 ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online N64 Controller
|
||||
//{ MAKE_CONTROLLER_ID( 0x057e, 0x201e ), k_eControllerType_SwitchProController, NULL }, // Nintendo Online SEGA Genesis Controller
|
||||
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00c1 ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORIPAD for Nintendo Switch
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x0092 ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Pokken Tournament DX Pro Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00f6 ), k_eControllerType_SwitchProController, NULL }, // HORI Wireless Switch Pad
|
||||
// The HORIPAD S, which comes in multiple styles:
|
||||
// - NSW-108, classic GameCube controller
|
||||
// - NSW-244, Fighting Commander arcade pad
|
||||
// - NSW-278, Hori Pad Mini gamepad
|
||||
// - NSW-326, HORIPAD FPS for Nintendo Switch
|
||||
//
|
||||
// The first two, at least, shouldn't have their buttons remapped, and since we
|
||||
// can't tell which model we're actually using, we won't do any button remapping
|
||||
// for any of them.
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00dc ), k_eControllerType_XInputSwitchController, NULL }, // HORIPAD S - Looks like a Switch controller but uses the Xbox 360 controller protocol
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0180 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Pro Controller for Nintendo Switch
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0181 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Deluxe Wired Pro Controller for Nintendo Switch
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0184 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Faceoff Wired Deluxe+ Audio Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0185 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Wired Fight Pad Pro for Nintendo Switch
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0186 ), k_eControllerType_SwitchProController, NULL }, // PDP Afterglow Wireless Switch Controller - working gyro. USB is for charging only. Many later "Wireless" line devices w/ gyro also use this vid/pid
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0187 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Rockcandy Wired Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0188 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PDP Afterglow Wired Deluxe+ Audio Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x0f0d, 0x00aa ), k_eControllerType_SwitchInputOnlyController, NULL }, // HORI Real Arcade Pro V Hayabusa in Switch Mode
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa711 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Wired Controller Plus/PowerA Wired Controller Nintendo GameCube Style
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa712 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Fight Pad
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa713 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Super Mario Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa714 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Spectra Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa715 ), k_eControllerType_SwitchInputOnlyController, NULL }, // Power A Fusion Wireless Arcade Stick (USB Mode) Over BT is shows up as 057e 2009
|
||||
{ MAKE_CONTROLLER_ID( 0x20d6, 0xa716 ), k_eControllerType_SwitchInputOnlyController, NULL }, // PowerA Nintendo Switch Fusion Pro Controller - USB requires toggling switch on back of device
|
||||
|
||||
// Valve products
|
||||
{ MAKE_CONTROLLER_ID( 0x0000, 0x11fb ), k_eControllerType_MobileTouch, NULL }, // Streaming mobile touch virtual controls
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1101 ), k_eControllerType_SteamController, NULL }, // Valve Legacy Steam Controller (CHELL)
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1102 ), k_eControllerType_SteamController, NULL }, // Valve wired Steam Controller (D0G)
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1105 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1106 ), k_eControllerType_SteamController, NULL }, // Valve Bluetooth Steam Controller (D0G)
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1142 ), k_eControllerType_SteamController, NULL }, // Valve wireless Steam Controller
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1201 ), k_eControllerType_SteamControllerV2, NULL }, // Valve wired Steam Controller (HEADCRAB)
|
||||
{ MAKE_CONTROLLER_ID( 0x28de, 0x1202 ), k_eControllerType_SteamControllerV2, NULL }, // Valve Bluetooth Steam Controller (HEADCRAB)
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (C) Valve Corporation
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef CONTROLLER_TYPE_H
|
||||
#define CONTROLLER_TYPE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Steam Controller models
|
||||
// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN A DATABASE
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef enum
|
||||
{
|
||||
k_eControllerType_None = -1,
|
||||
k_eControllerType_Unknown = 0,
|
||||
|
||||
// Steam Controllers
|
||||
k_eControllerType_UnknownSteamController = 1,
|
||||
k_eControllerType_SteamController = 2,
|
||||
k_eControllerType_SteamControllerV2 = 3,
|
||||
|
||||
// Other Controllers
|
||||
k_eControllerType_UnknownNonSteamController = 30,
|
||||
k_eControllerType_XBox360Controller = 31,
|
||||
k_eControllerType_XBoxOneController = 32,
|
||||
k_eControllerType_PS3Controller = 33,
|
||||
k_eControllerType_PS4Controller = 34,
|
||||
k_eControllerType_WiiController = 35,
|
||||
k_eControllerType_AppleController = 36,
|
||||
k_eControllerType_AndroidController = 37,
|
||||
k_eControllerType_SwitchProController = 38,
|
||||
k_eControllerType_SwitchJoyConLeft = 39,
|
||||
k_eControllerType_SwitchJoyConRight = 40,
|
||||
k_eControllerType_SwitchJoyConPair = 41,
|
||||
k_eControllerType_SwitchInputOnlyController = 42,
|
||||
k_eControllerType_MobileTouch = 43,
|
||||
k_eControllerType_XInputSwitchController = 44, // Client-side only, used to mark Nintendo Switch style controllers as using XInput instead of the Nintendo Switch protocol
|
||||
k_eControllerType_PS5Controller = 45,
|
||||
k_eControllerType_XInputPS4Controller = 46, // Client-side only, used to mark DualShock 4 style controllers using XInput instead of the DualShock 4 controller protocol
|
||||
k_eControllerType_LastController, // Don't add game controllers below this enumeration - this enumeration can change value
|
||||
|
||||
// Keyboards and Mice
|
||||
k_eControllertype_GenericKeyboard = 400,
|
||||
k_eControllertype_GenericMouse = 800,
|
||||
} EControllerType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int m_unDeviceID;
|
||||
EControllerType m_eControllerType;
|
||||
const char *m_pszName;
|
||||
} ControllerDescription_t;
|
||||
|
||||
|
||||
extern EControllerType GuessControllerType( int nVID, int nPID );
|
||||
extern const char *GuessControllerName( int nVID, int nPID );
|
||||
|
||||
#endif // CONTROLLER_TYPE_H
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
// This file includes a few functions standalone from SDL_joystick.c useful for joystick typing
|
||||
|
||||
#include "minisdl.h"
|
||||
#include "usb_ids.h"
|
||||
|
||||
SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_MICROSOFT) {
|
||||
if (product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH ||
|
||||
product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_MICROSOFT) {
|
||||
if (product_id == USB_PRODUCT_XBOX_SERIES_X ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_BLE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_PDP) {
|
||||
if (product_id == USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_POWERA_ALT) {
|
||||
if ((product_id >= 0x2001 && product_id <= 0x201a) ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_MOGA_XP_ULTRA ||
|
||||
product_id == USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_HORI) {
|
||||
if (product_id == USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X ||
|
||||
product_id == USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_RAZER) {
|
||||
if (product_id == USB_PRODUCT_RAZER_WOLVERINE_V2 ||
|
||||
product_id == USB_PRODUCT_RAZER_WOLVERINE_V2_CHROMA) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_THRUSTMASTER) {
|
||||
if (product_id == USB_PRODUCT_THRUSTMASTER_ESWAPX_PRO) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_TURTLE_BEACH) {
|
||||
if (product_id == USB_PRODUCT_TURTLE_BEACH_SERIES_X_REACT_R ||
|
||||
product_id == USB_PRODUCT_TURTLE_BEACH_SERIES_X_RECON) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_8BITDO) {
|
||||
if (product_id == USB_PRODUCT_8BITDO_XBOX_CONTROLLER) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
if (vendor_id == USB_VENDOR_GAMESIR) {
|
||||
if (product_id == USB_PRODUCT_GAMESIR_G7) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_SONY) {
|
||||
if (product_id == USB_PRODUCT_SONY_DS5_EDGE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
typedef int SDL_bool;
|
||||
#define SDL_TRUE 1
|
||||
#define SDL_FALSE 0
|
||||
|
||||
typedef unsigned short Uint16;
|
||||
|
||||
SDL_bool SDL_IsJoystickXboxOneElite(Uint16 vendor_id, Uint16 product_id);
|
||||
SDL_bool SDL_IsJoystickXboxSeriesX(Uint16 vendor_id, Uint16 product_id);
|
||||
SDL_bool SDL_IsJoystickDualSenseEdge(Uint16 vendor_id, Uint16 product_id);
|
||||
Submodule app/src/main/jni/moonlight-core/moonlight-common-c updated: b77072d399...c86f49ee7f
@@ -6,6 +6,10 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "minisdl.h"
|
||||
#include "controller_type.h"
|
||||
#include "controller_list.h"
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendMouseMove(JNIEnv *env, jclass clazz, jshort deltaX, jshort deltaY) {
|
||||
LiSendMouseMoveEvent(deltaX, deltaY);
|
||||
@@ -30,7 +34,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_sendMouseButton(JNIEnv *env, jclass c
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendMultiControllerInput(JNIEnv *env, jclass clazz, jshort controllerNumber,
|
||||
jshort activeGamepadMask, jshort buttonFlags,
|
||||
jshort activeGamepadMask, jint buttonFlags,
|
||||
jbyte leftTrigger, jbyte rightTrigger,
|
||||
jshort leftStickX, jshort leftStickY,
|
||||
jshort rightStickX, jshort rightStickY) {
|
||||
@@ -38,12 +42,59 @@ Java_com_limelight_nvstream_jni_MoonBridge_sendMultiControllerInput(JNIEnv *env,
|
||||
leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerInput(JNIEnv *env, jclass clazz, jshort buttonFlags,
|
||||
jbyte leftTrigger, jbyte rightTrigger,
|
||||
jshort leftStickX, jshort leftStickY,
|
||||
jshort rightStickX, jshort rightStickY) {
|
||||
LiSendControllerEvent(buttonFlags, leftTrigger, rightTrigger, leftStickX, leftStickY, rightStickX, rightStickY);
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendTouchEvent(JNIEnv *env, jclass clazz,
|
||||
jbyte eventType, jint pointerId,
|
||||
jfloat x, jfloat y, jfloat pressureOrDistance,
|
||||
jfloat contactAreaMajor, jfloat contactAreaMinor,
|
||||
jshort rotation) {
|
||||
return LiSendTouchEvent(eventType, pointerId, x, y, pressureOrDistance,
|
||||
contactAreaMajor, contactAreaMinor, rotation);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendPenEvent(JNIEnv *env, jclass clazz, jbyte eventType,
|
||||
jbyte toolType, jbyte penButtons,
|
||||
jfloat x, jfloat y, jfloat pressureOrDistance,
|
||||
jfloat contactAreaMajor, jfloat contactAreaMinor,
|
||||
jshort rotation, jbyte tilt) {
|
||||
return LiSendPenEvent(eventType, toolType, penButtons, x, y, pressureOrDistance,
|
||||
contactAreaMajor, contactAreaMinor, rotation, tilt);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerArrivalEvent(JNIEnv *env, jclass clazz,
|
||||
jbyte controllerNumber,
|
||||
jshort activeGamepadMask,
|
||||
jbyte type,
|
||||
jint supportedButtonFlags,
|
||||
jshort capabilities) {
|
||||
return LiSendControllerArrivalEvent(controllerNumber, activeGamepadMask, type, supportedButtonFlags, capabilities);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerTouchEvent(JNIEnv *env, jclass clazz,
|
||||
jbyte controllerNumber,
|
||||
jbyte eventType,
|
||||
jint pointerId, jfloat x,
|
||||
jfloat y, jfloat pressure) {
|
||||
return LiSendControllerTouchEvent(controllerNumber, eventType, pointerId, x, y, pressure);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerMotionEvent(JNIEnv *env, jclass clazz,
|
||||
jbyte controllerNumber,
|
||||
jbyte motionType, jfloat x,
|
||||
jfloat y, jfloat z) {
|
||||
return LiSendControllerMotionEvent(controllerNumber, motionType, x, y, z);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendControllerBatteryEvent(JNIEnv *env, jclass clazz,
|
||||
jbyte controllerNumber,
|
||||
jbyte batteryState,
|
||||
jbyte batteryPercentage) {
|
||||
return LiSendControllerBatteryEvent(controllerNumber, batteryState, batteryPercentage);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
@@ -159,4 +210,47 @@ Java_com_limelight_nvstream_jni_MoonBridge_getEstimatedRttInfo(JNIEnv *env, jcla
|
||||
}
|
||||
|
||||
return ((uint64_t)rtt << 32U) | variance;
|
||||
}
|
||||
|
||||
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);
|
||||
for (int i = 0; i < sizeof(arrControllers) / sizeof(arrControllers[0]); i++) {
|
||||
if (unDeviceID == arrControllers[i].m_unDeviceID) {
|
||||
switch (arrControllers[i].m_eControllerType) {
|
||||
case k_eControllerType_XBox360Controller:
|
||||
case k_eControllerType_XBoxOneController:
|
||||
return LI_CTYPE_XBOX;
|
||||
|
||||
case k_eControllerType_PS3Controller:
|
||||
case k_eControllerType_PS4Controller:
|
||||
case k_eControllerType_PS5Controller:
|
||||
return LI_CTYPE_PS;
|
||||
|
||||
case k_eControllerType_WiiController:
|
||||
case k_eControllerType_SwitchProController:
|
||||
case k_eControllerType_SwitchJoyConLeft:
|
||||
case k_eControllerType_SwitchJoyConRight:
|
||||
case k_eControllerType_SwitchJoyConPair:
|
||||
case k_eControllerType_SwitchInputOnlyController:
|
||||
return LI_CTYPE_NINTENDO;
|
||||
|
||||
default:
|
||||
return LI_CTYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
return LI_CTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_guessControllerHasPaddles(JNIEnv *env, jclass clazz, jint vendorId, jint productId) {
|
||||
// Xbox Elite and DualSense Edge controllers have paddles
|
||||
return SDL_IsJoystickXboxOneElite(vendorId, productId) || SDL_IsJoystickDualSenseEdge(vendorId, productId);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_guessControllerHasShareButton(JNIEnv *env, jclass clazz, jint vendorId, jint productId) {
|
||||
// Xbox Elite and DualSense Edge controllers have paddles
|
||||
return SDL_IsJoystickXboxSeriesX(vendorId, productId);
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef usb_ids_h_
|
||||
#define usb_ids_h_
|
||||
|
||||
/* Definitions of useful USB VID/PID values */
|
||||
|
||||
#define USB_VENDOR_8BITDO 0x2dc8
|
||||
#define USB_VENDOR_AMAZON 0x1949
|
||||
#define USB_VENDOR_APPLE 0x05ac
|
||||
#define USB_VENDOR_ASTRO 0x9886
|
||||
#define USB_VENDOR_BACKBONE 0x358a
|
||||
#define USB_VENDOR_GAMESIR 0x3537
|
||||
#define USB_VENDOR_DRAGONRISE 0x0079
|
||||
#define USB_VENDOR_GOOGLE 0x18d1
|
||||
#define USB_VENDOR_HORI 0x0f0d
|
||||
#define USB_VENDOR_HYPERKIN 0x2e24
|
||||
#define USB_VENDOR_LOGITECH 0x046d
|
||||
#define USB_VENDOR_MADCATZ 0x0738
|
||||
#define USB_VENDOR_MICROSOFT 0x045e
|
||||
#define USB_VENDOR_NACON 0x146b
|
||||
#define USB_VENDOR_NINTENDO 0x057e
|
||||
#define USB_VENDOR_NVIDIA 0x0955
|
||||
#define USB_VENDOR_PDP 0x0e6f
|
||||
#define USB_VENDOR_POWERA 0x24c6
|
||||
#define USB_VENDOR_POWERA_ALT 0x20d6
|
||||
#define USB_VENDOR_QANBA 0x2c22
|
||||
#define USB_VENDOR_RAZER 0x1532
|
||||
#define USB_VENDOR_SAITEK 0x06a3
|
||||
#define USB_VENDOR_SHANWAN 0x2563
|
||||
#define USB_VENDOR_SHANWAN_ALT 0x20bc
|
||||
#define USB_VENDOR_SONY 0x054c
|
||||
#define USB_VENDOR_THRUSTMASTER 0x044f
|
||||
#define USB_VENDOR_TURTLE_BEACH 0x10f5
|
||||
#define USB_VENDOR_VALVE 0x28de
|
||||
#define USB_VENDOR_ZEROPLUS 0x0c12
|
||||
|
||||
#define USB_PRODUCT_8BITDO_XBOX_CONTROLLER 0x2002
|
||||
#define USB_PRODUCT_AMAZON_LUNA_CONTROLLER 0x0419
|
||||
#define USB_PRODUCT_ASTRO_C40_XBOX360 0x0024
|
||||
#define USB_PRODUCT_BACKBONE_ONE_IOS 0x0103
|
||||
#define USB_PRODUCT_BACKBONE_ONE_IOS_PS5 0x0104
|
||||
#define USB_PRODUCT_GAMESIR_G7 0x1001
|
||||
#define USB_PRODUCT_GOOGLE_STADIA_CONTROLLER 0x9400
|
||||
#define USB_PRODUCT_EVORETRO_GAMECUBE_ADAPTER 0x1846
|
||||
#define USB_PRODUCT_HORI_FIGHTING_COMMANDER_OCTA_SERIES_X 0x0150
|
||||
#define USB_PRODUCT_HORI_HORIPAD_PRO_SERIES_X 0x014f
|
||||
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c
|
||||
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
|
||||
#define USB_PRODUCT_LOGITECH_F310 0xc216
|
||||
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
|
||||
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
|
||||
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
|
||||
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
|
||||
#define USB_PRODUCT_NINTENDO_SNES_CONTROLLER 0x2017
|
||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_GRIP 0x200e
|
||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT 0x2006
|
||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_PAIR 0x2008 /* Used by joycond */
|
||||
#define USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT 0x2007
|
||||
#define USB_PRODUCT_NINTENDO_SWITCH_PRO 0x2009
|
||||
#define USB_PRODUCT_NINTENDO_WII_REMOTE 0x0306
|
||||
#define USB_PRODUCT_NINTENDO_WII_REMOTE2 0x0330
|
||||
#define USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V103 0x7210
|
||||
#define USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V104 0x7214
|
||||
#define USB_PRODUCT_RAZER_ATROX 0x0a00
|
||||
#define USB_PRODUCT_RAZER_PANTHERA 0x0401
|
||||
#define USB_PRODUCT_RAZER_PANTHERA_EVO 0x1008
|
||||
#define USB_PRODUCT_RAZER_RAIJU 0x1000
|
||||
#define USB_PRODUCT_RAZER_TOURNAMENT_EDITION_USB 0x1007
|
||||
#define USB_PRODUCT_RAZER_TOURNAMENT_EDITION_BLUETOOTH 0x100a
|
||||
#define USB_PRODUCT_RAZER_ULTIMATE_EDITION_USB 0x1004
|
||||
#define USB_PRODUCT_RAZER_ULTIMATE_EDITION_BLUETOOTH 0x1009
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2 0x0a29
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2_CHROMA 0x0a2e
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRED 0x100b
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_PS5_WIRELESS 0x100c
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_XBOX_WIRED 0x1010
|
||||
#define USB_PRODUCT_RAZER_WOLVERINE_V2_PRO_XBOX_WIRELESS 0x1011
|
||||
#define USB_PRODUCT_SAITEK_CYBORG_V3 0xf622
|
||||
#define USB_PRODUCT_SHANWAN_DS3 0x0523
|
||||
#define USB_PRODUCT_SONY_DS3 0x0268
|
||||
#define USB_PRODUCT_SONY_DS4 0x05c4
|
||||
#define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0
|
||||
#define USB_PRODUCT_SONY_DS4_SLIM 0x09cc
|
||||
#define USB_PRODUCT_SONY_DS4_STRIKEPAD 0x05c5
|
||||
#define USB_PRODUCT_SONY_DS5 0x0ce6
|
||||
#define USB_PRODUCT_SONY_DS5_EDGE 0x0df2
|
||||
#define USB_PRODUCT_THRUSTMASTER_ESWAPX_PRO 0xd012
|
||||
#define USB_PRODUCT_TURTLE_BEACH_SERIES_X_REACT_R 0x7013
|
||||
#define USB_PRODUCT_TURTLE_BEACH_SERIES_X_RECON 0x7009
|
||||
#define USB_PRODUCT_VICTRIX_FS_PRO 0x0203
|
||||
#define USB_PRODUCT_VICTRIX_FS_PRO_V2 0x0207
|
||||
#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */
|
||||
#define USB_PRODUCT_XBOX360_WIRED_CONTROLLER 0x028e
|
||||
#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719
|
||||
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE 0x0b0a
|
||||
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLUETOOTH 0x0b0c
|
||||
#define USB_PRODUCT_XBOX_ONE_ADAPTIVE_BLE 0x0b21
|
||||
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3
|
||||
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00
|
||||
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05
|
||||
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLE 0x0b22
|
||||
#define USB_PRODUCT_XBOX_ONE_S 0x02ea
|
||||
#define USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH 0x02e0
|
||||
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLUETOOTH 0x02fd
|
||||
#define USB_PRODUCT_XBOX_ONE_S_REV2_BLE 0x0b20
|
||||
#define USB_PRODUCT_XBOX_SERIES_X 0x0b12
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_BLE 0x0b13
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_VICTRIX_GAMBIT 0x02d6
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_PDP_BLUE 0x02d9
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_PDP_AFTERGLOW 0x02da
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_FUSION_PRO2 0x4001
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_MOGA_XP_ULTRA 0x890b
|
||||
#define USB_PRODUCT_XBOX_SERIES_X_POWERA_SPECTRA 0x4002
|
||||
#define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */
|
||||
#define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */
|
||||
#define USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD 0x11ff
|
||||
|
||||
/* USB usage pages */
|
||||
#define USB_USAGEPAGE_GENERIC_DESKTOP 0x0001
|
||||
#define USB_USAGEPAGE_BUTTON 0x0009
|
||||
|
||||
/* USB usages for USAGE_PAGE_GENERIC_DESKTOP */
|
||||
#define USB_USAGE_GENERIC_POINTER 0x0001
|
||||
#define USB_USAGE_GENERIC_MOUSE 0x0002
|
||||
#define USB_USAGE_GENERIC_JOYSTICK 0x0004
|
||||
#define USB_USAGE_GENERIC_GAMEPAD 0x0005
|
||||
#define USB_USAGE_GENERIC_KEYBOARD 0x0006
|
||||
#define USB_USAGE_GENERIC_KEYPAD 0x0007
|
||||
#define USB_USAGE_GENERIC_MULTIAXISCONTROLLER 0x0008
|
||||
#define USB_USAGE_GENERIC_X 0x0030
|
||||
#define USB_USAGE_GENERIC_Y 0x0031
|
||||
#define USB_USAGE_GENERIC_Z 0x0032
|
||||
#define USB_USAGE_GENERIC_RX 0x0033
|
||||
#define USB_USAGE_GENERIC_RY 0x0034
|
||||
#define USB_USAGE_GENERIC_RZ 0x0035
|
||||
#define USB_USAGE_GENERIC_SLIDER 0x0036
|
||||
#define USB_USAGE_GENERIC_DIAL 0x0037
|
||||
#define USB_USAGE_GENERIC_WHEEL 0x0038
|
||||
#define USB_USAGE_GENERIC_HAT 0x0039
|
||||
|
||||
/* Bluetooth SIG assigned Company Identifiers
|
||||
https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/ */
|
||||
#define BLUETOOTH_VENDOR_AMAZON 0x0171
|
||||
|
||||
#define BLUETOOTH_PRODUCT_LUNA_CONTROLLER 0x0419
|
||||
|
||||
#endif /* usb_ids_h_ */
|
||||
@@ -78,9 +78,8 @@
|
||||
<string name="error_usb_prohibited">USB достъпът е забранен от администратора на вашето устройство. Проверете настройките на Knox или MDM.</string>
|
||||
<string name="audioconf_71surround">7.1 съраунд звук</string>
|
||||
<string name="audioconf_51surround">5.1 съраунд звук</string>
|
||||
<string name="videoformat_hevcauto">Автоматично</string>
|
||||
<string name="videoformat_auto">Автоматично</string>
|
||||
<string name="videoformat_hevcalways">Винаги използване на HEVC (може да крашне)</string>
|
||||
<string name="videoformat_hevcnever">Никога да не се използва HEVC</string>
|
||||
<string name="summary_frame_pacing">Посочете как да се балансира забавянето и плавността на видеото</string>
|
||||
<string name="title_frame_pacing">Стъпка на видео кадрите</string>
|
||||
<string name="pacing_balanced">Балансирано</string>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="resolution_1080p">1080p</string>
|
||||
<string name="resolution_1440p">1440p</string>
|
||||
<string name="videoformat_hevcauto">Automaticky</string>
|
||||
<string name="videoformat_auto">Automaticky</string>
|
||||
<string name="audioconf_71surround">7.1 prostorový zvuk</string>
|
||||
<string name="pacing_balanced">Vyvážené</string>
|
||||
<string name="pacing_smoothness">Preferovat plynulejší video (může výrazně zvýšit zpoždění)</string>
|
||||
@@ -244,7 +244,6 @@
|
||||
<string name="title_enable_hdr">Povolit HDR (experimentální)</string>
|
||||
<string name="summary_enable_hdr">Streamovat v HDR, pokud jej hra a GPU počítače podporují. HDR vyžaduje GPU GTX 1000 nebo novější.</string>
|
||||
<string name="videoformat_hevcalways">Vždy použít HEVC (může padat)</string>
|
||||
<string name="videoformat_hevcnever">Nikdy nepoužívat HEVC</string>
|
||||
<string name="title_frame_pacing">Frame pacing videa</string>
|
||||
<string name="summary_frame_pacing">Zvolte, jak vyvážit zpoždění videa a jeho plynulost</string>
|
||||
<string name="pacing_latency">Preferovat nejnižší zpoždění</string>
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<string name="conn_terminated_title">Verbindung beendet</string>
|
||||
<string name="conn_terminated_msg">Die Verbindung wurde beendet</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">IP-Adresse des GeForce Host</string>
|
||||
<string name="ip_hint">IP-Adresse des GeForce Hosts</string>
|
||||
<string name="searching_pc">Suche nach Hosts auf denen GeForce Experience aktiv ist…
|
||||
\n
|
||||
\nStelle sicher, dass GameStream in den GeForce Experience SHIELD-Einstellungen aktiviert ist.</string>
|
||||
@@ -218,9 +218,8 @@
|
||||
<string name="pcview_menu_header_offline">Offline</string>
|
||||
<string name="pcview_menu_header_online">Online</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Automatisch</string>
|
||||
<string name="videoformat_auto">Automatisch</string>
|
||||
<string name="videoformat_hevcalways">Immer HEVC verwenden (könnte Crashes verursachen)</string>
|
||||
<string name="videoformat_hevcnever">Nie HEVC verwenden</string>
|
||||
<string name="title_frame_pacing">Video Frame-Pacing</string>
|
||||
<string name="summary_frame_pacing">Lege fest, wie die Videolatenz und die flüssige Wiedergabe ausgeglichen werden sollen</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Natives Vollbild</string>
|
||||
@@ -262,4 +261,13 @@
|
||||
<string name="frame_conversion_error">Der Host-PC hat einen schwerwiegenden Videocodierungsfehler gemeldet.
|
||||
\n
|
||||
\nVersuchen Sie, den HDR-Modus zu deaktivieren, die Streaming-Auflösung zu ändern oder die Bildschirmauflösung des Host-PCs zu ändern.</string>
|
||||
<string name="title_native_fps_dialog">Native FPS Warnung</string>
|
||||
<string name="videoformat_av1always">Immer AV1 verwenden (Experimentell)</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Erlaube Benutzen von Gamepad Bewegungssensoren</string>
|
||||
<string name="videoformat_h264always">Immer H.264 verwenden</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="category_gamepad_settings">Gamepad Einstellungen</string>
|
||||
<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>
|
||||
</resources>
|
||||
@@ -83,7 +83,7 @@
|
||||
<string name="title_checkbox_stretch_video">Ajustar vídeo a pantalla completa</string>
|
||||
<string name="title_checkbox_disable_warnings">Desactivar mensajes de advertencia</string>
|
||||
<string name="summary_checkbox_disable_warnings">Desactivar mensajes de advertencia en pantalla durante la transmisión</string>
|
||||
<string name="category_audio_settings">Configuración de audio</string>
|
||||
<string name="category_audio_settings">Ajustes del audio</string>
|
||||
<string name="title_checkbox_multi_controller">Soporte para múltiples mandos</string>
|
||||
<string name="summary_checkbox_multi_controller">Si no está marcado, todos los mandos aparecen como uno solo</string>
|
||||
<string name="title_seekbar_deadzone">Ajustar zona muerta del stick analógico</string>
|
||||
@@ -106,12 +106,11 @@
|
||||
<string name="title_checkbox_host_audio">Reproducir audio en PC</string>
|
||||
<string name="summary_checkbox_host_audio">Reproducir audio en el ordenador y en este dispositivo</string>
|
||||
<string name="category_advanced_settings">Configuración avanzada</string>
|
||||
<string name="title_video_format">Cambiar configuración HEVC</string>
|
||||
<string name="summary_video_format">HEVC reduce el ancho de banda de vídeo, pero requiere un dispositivo reciente</string>
|
||||
<string name="title_video_format">Cambiar la configuración del códec</string>
|
||||
<string name="summary_video_format">Los códecs más recientes pueden reducir los requisitos del ancho de banda del vídeo si tu dispositivo los admite. Las selecciones de los códecs pueden ignorarse si no son compatibles con el software del host o la GPU.</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Automático (Recomendado)</string>
|
||||
<string name="videoformat_auto">Automático (Recomendado)</string>
|
||||
<string name="videoformat_hevcalways">Preferir HEVC</string>
|
||||
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
||||
<string name="nettest_title_done">Prueba de Red Completada</string>
|
||||
<string name="scut_not_paired">PC no emparejado</string>
|
||||
<string name="scut_invalid_uuid">El PC proporcionado no es válido</string>
|
||||
@@ -193,13 +192,13 @@
|
||||
<string name="applist_menu_hide_app">Esconder Aplicación</string>
|
||||
<string name="applist_connect_msg">Conectando al Equipo…</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Activar esta opción puede desconfigurar la función de clic derecho en algunos dispositivos inestables</string>
|
||||
<string name="text_native_res_dialog">Modos de resolución nativa no son oficialmente soportados por GeForce Experience, así que no se no se aplicarán por su cuenta en la pantalla del equipo anfitrión. Vas a necesitar ajustarlos manualmente en el juego.
|
||||
<string name="text_native_res_dialog">Es posible que la resolución nativa y/o los FPS no sean compatibles con el servidor de streaming. Es probable que tengas que configurar manualmente un modo de visualización personalizado para el PC host.
|
||||
\n
|
||||
\nSi eliges crear una resolución personalizada en el Panel de Control de Nvidia para ajustarse a la resolución de tu dispositivo, por favor considera haber leído y entendido la advertencia de NVIDIA respectivo a cualquier daño posible a tu monitor, inestabilidad del equipo, y otros problemas potencialmente posibles.
|
||||
\nSi decides crear una resolución personalizada en el Panel de control de NVIDIA para que coincida con la configuración de tu pantalla, asegúrate de haber leído y comprendido la advertencia de NVIDIA sobre posibles daños en el monitor, inestabilidad del PC y otros problemas potenciales.
|
||||
\n
|
||||
\nNo somos responsables de cualquier problema por haber creador una resolución personalizada en tu PC.
|
||||
\nNo nos hacemos responsables de ningún problema derivado de la creación de una resolución personalizada en tu PC.
|
||||
\n
|
||||
\nFinalmente, tu dispositivo o tu Pc anfitrión, podrían no soportar la transmisión a resolución nativa. Si no funciona en tu equipo, puede que solo no tengas suerte de momento.</string>
|
||||
\nEs posible que tu monitor no admita la configuración de pantalla necesaria. Si es así, puede intentar configurar un monitor virtual. Por último, si tu dispositivo o PC anfitrión no soporta streaming a una resolución o frecuencia de refresco específica, lamentablemente no tienes suerte.</string>
|
||||
<string name="resolution_prefix_native">Nativo</string>
|
||||
<string name="summary_audio_config_list">Activar sonido envolvente de 5.1 o 7.1 canales para sistemas de teatro en casa</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emular la vibración del mando con vibración del equipo</string>
|
||||
@@ -265,4 +264,18 @@
|
||||
<string name="summary_full_range">Esto provocará la pérdida de detalles en las áreas claras y oscuras si su dispositivo no muestra correctamente el contenido de video de rango completo.</string>
|
||||
<string name="pair_pairing_help">Si el hostal del ordenador ejecuta Sunshine, navegue a la interfaz de usuario web de Sunshine para ingresar el PIN.</string>
|
||||
<string name="pcview_menu_eol">Fin de servicio de NVIDIA GameStream</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="title_native_fps_dialog">Advertencia sobre FPS nativos</string>
|
||||
<string name="category_gamepad_settings">Ajustes del Gamepad</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Permitir el uso de los sensores de movimiento del gamepad</string>
|
||||
<string name="videoformat_av1always">Preferir AV1 (Experimental)</string>
|
||||
<string name="videoformat_h264always">Prefiero H.264</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Latencia de procesamiento del host mín/máx/promedio: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Fuerza la entrada del touchpad del gamepad para controlar el ratón del host, incluso cuando se emula un gamepad con touchpad.</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Controla siempre el ratón con el touchpad</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Permite a los hosts compatibles solicitar datos de los sensores de movimiento al emular un gamepad con los sensores de movimiento. La desactivación puede reducir ligeramente el consumo de energía y el uso de la red si los sensores de movimiento no se utilizan en el juego.</string>
|
||||
<string name="toast_controller_type_changed">El tipo del Gamepad puede cambiar debido a la emulación del sensor de movimiento</string>
|
||||
<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>
|
||||
</resources>
|
||||
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -18,7 +18,7 @@
|
||||
<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>
|
||||
<string name="nettest_text_waiting">Moonlight teste votre connexion réseau pour déterminer si NVIDIA GameStream est bloqué.
|
||||
<string name="nettest_text_waiting">Moonlight teste votre connexion réseau pour déterminer si les ports requis sont bloqués.
|
||||
\n
|
||||
\nCela peut prendre quelques secondes…</string>
|
||||
<string name="nettest_title_done">Test du réseau terminé</string>
|
||||
@@ -40,7 +40,7 @@
|
||||
<string name="pair_already_in_progress">Appariement déjà en cours</string>
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">L\'ordinateur est en ligne</string>
|
||||
<string name="wol_no_mac">Impossible de réveiller le PC car GFE n\'a pas envoyé d\'adresse MAC</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.
|
||||
@@ -59,7 +59,7 @@
|
||||
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. Assurez-vous que GeForce Experience soit mis à jour vers la dernière version sur votre PC. Essayez de régler les paramètres de diffusion si les plantages continuent.</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>
|
||||
@@ -77,9 +77,10 @@
|
||||
<string name="conn_terminated_title">Connexion terminée</string>
|
||||
<string name="conn_terminated_msg">La connexion a été interrompue</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Adresse IP de GeForce PC</string>
|
||||
<string name="searching_pc">Recherche de PC avec GameStream en cours…\n\n
|
||||
Assurez-vous que GameStream est activé dans les paramètres GeForce Experience SHIELD.</string>
|
||||
<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…
|
||||
\n
|
||||
\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>
|
||||
@@ -185,10 +186,10 @@
|
||||
<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="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 HEVC</string>
|
||||
<string name="summary_video_format">HEVC réduit les besoins en bande passante vidéo mais nécessite un périphérique très récent</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. HDR nécessite un GPU série GTX 1000 ou une version ultérieure.</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>
|
||||
@@ -201,21 +202,19 @@
|
||||
<string name="pcview_menu_header_online">En ligne</string>
|
||||
<string name="resolution_prefix_native">Native</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||
<string name="text_native_res_dialog">Les modes de résolution native ne sont pas officiellement supportées par GeForce Experience, l\'écran de votre hôte ne changera donc pas sa résolution. Vous devrez changer la résolution de chaque jeu dans les paramètres de celui-ci.
|
||||
<string name="text_native_res_dialog">La résolution native et/ou le FPS peuvent ne pas être pris en charge par le serveur de streaming. Vous devrez probablement configurer manuellement un mode d\'affichage personnalisé correspondant pour le PC hôte.
|
||||
\n
|
||||
\nSi vous créez une résolution personnalisée dans le panneau de contrôle NVIDIA identique à celle de votre appareil, gardez à l\'esprit les avertissement de NVIDIA en ce qui est des potentiels dégâts à votre moniteur, une instabilité générale, et encore d\'autres problèmes.
|
||||
\nSi vous choisissez de créer une résolution personnalisée dans le panneau de configuration NVIDIA pour correspondre aux paramètres de votre écran, assurez-vous d\'avoir lu et compris l\'avertissement de NVIDIA concernant les dommages possibles au moniteur, l\'instabilité du PC et d\'autres problèmes potentiels.
|
||||
\n
|
||||
\nNous ne sommes pas responsables des problèmes qui peuvent arriver suite à l\'utilisation de cette fonctionnalité.
|
||||
\nNous ne sommes pas responsables des problèmes résultant de la création d\'une résolution personnalisée sur votre PC.
|
||||
\n
|
||||
\nEnfin, votre appareil et/ou vôtre PC hôte peut ne pas supporter cette fonctionnalité. Si ça ne marche pas, on ne peut malheureusement rien y faire.</string>
|
||||
\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="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.
|
||||
\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.
|
||||
\n
|
||||
\nSi le problème persiste, essayez de réinstaller les pilotes de votre GPU ainsi que GeForce Experience.</string>
|
||||
\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="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>
|
||||
@@ -228,9 +227,8 @@
|
||||
<string name="audioconf_stereo">Stéréo</string>
|
||||
<string name="audioconf_51surround">Son surround 5.1</string>
|
||||
<string name="audioconf_71surround">Son surround 7.1</string>
|
||||
<string name="videoformat_hevcauto">Automatique (recommandé)</string>
|
||||
<string name="videoformat_auto">Automatique (recommandé)</string>
|
||||
<string name="videoformat_hevcalways">Préférez le HEVC</string>
|
||||
<string name="videoformat_hevcnever">N\'utilisez jamais HEVC</string>
|
||||
<string name="title_frame_pacing">Frame-pacing vidéo</string>
|
||||
<string name="summary_frame_pacing">Spécifiez comment équilibrer latence et fluidité de la vidéo</string>
|
||||
<string name="pacing_latency">Préférer une latence plus faible</string>
|
||||
@@ -264,4 +262,20 @@
|
||||
\nEssayez de désactiver le mode HDR, de changer la résolution du flux ou la résolution de votre PC hôte.</string>
|
||||
<string name="title_full_range">Forcer la vidéo sur toute la gamme de couleurs (expérimental)</string>
|
||||
<string name="summary_full_range">Ceci entraînera une perte de détails dans les zones claires et sombres si votre appareil n\'affiche pas correctement le contenu vidéo de la gamme complète de couleurs.</string>
|
||||
<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_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_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>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Émuler les capteurs de mouvement de la manette</string>
|
||||
</resources>
|
||||
@@ -4,10 +4,10 @@
|
||||
<string name="title_enable_post_stream_toast">A késleltetési üzenet megjelenítése streaming után</string>
|
||||
<string name="summary_enable_perf_overlay">Valós idejű adatfolyam-adat megjelenítése streaming közben</string>
|
||||
<string name="title_enable_perf_overlay">Teljesítmény statisztikák megjelenítése közvetítés közben</string>
|
||||
<string name="summary_enable_hdr">Streaming HDR, amikor a játék és a PC GPU támogatja. A HDR-hez GTX 1000 sorozatú vagy újabb verzió szükséges.</string>
|
||||
<string name="summary_enable_hdr">HDR streamelés, ha a játék és a PC GPU támogatja. A HDR-hez HEVC Main 10 kódolási támogatással rendelkező GPU szükséges.</string>
|
||||
<string name="title_enable_hdr">HDR engedélyezése (kísérleti)</string>
|
||||
<string name="summary_video_format">A HEVC csökkenti a video sávszélesség követelményeit, de újabb eszközt igényel</string>
|
||||
<string name="title_video_format">Módosítsa a HEVC beállításait</string>
|
||||
<string name="summary_video_format">Az újabb kodekek csökkenthetik a videó sávszélességigényét, ha a készülék támogatja őket. A codec-kiválasztások figyelmen kívül hagyhatók, ha a gazdaszoftver vagy a GPU nem támogatja őket.</string>
|
||||
<string name="title_video_format">Módosítsa a Kodek beállításait</string>
|
||||
<string name="summary_disable_frame_drop">Csökkentheti a mikrodadogást egyes eszközökön, de növelheti a késést</string>
|
||||
<string name="title_disable_frame_drop">Soha ne ejtse le a kereteket</string>
|
||||
<string name="summary_checkbox_disable_warnings">Streaming közben tiltsa le a képernyőn megjelenő csatlakozási figyelmeztető üzeneteket</string>
|
||||
@@ -72,13 +72,13 @@
|
||||
<string name="title_seekbar_bitrate">Videó bitráta</string>
|
||||
<string name="summary_fps_list">Növelje a gördülékenyebb videofolyamot. Csökkenjen a jobb teljesítmény érdekében az alsó kategóriás eszközökön.</string>
|
||||
<string name="title_fps_list">Videó képkockasebessége</string>
|
||||
<string name="text_native_res_dialog">A natív felbontási módokat a GeForce Experience hivatalosan nem támogatja, így maga nem állítja be a gazdagép kijelzőjének felbontását. A játék során manuálisan kell beállítania.
|
||||
<string name="text_native_res_dialog">Előfordulhat, hogy a streaming szerver nem támogatja a natív felbontást és/vagy FPS-t. Valószínűleg kézzel kell beállítania egy megfelelő egyéni megjelenítési módot a fogadó számítógépen.
|
||||
\n
|
||||
\nHa úgy dönt, hogy az NVIDIA vezérlőpultján egyedi felbontást hoz létre, hogy megfeleljen az eszköz felbontásának, kérjük, olvassa el és értette az NVIDIA figyelmeztetéseit a monitor esetleges károsodásával, a számítógép instabilitásával és más lehetséges problémákkal kapcsolatban.
|
||||
\nHa úgy dönt, hogy egyéni felbontást hoz létre az NVIDIA Vezérlőpultban a képernyő beállításainak megfelelően, kérjük, győződjön meg róla, hogy elolvasta és megértette az NVIDIA figyelmeztetését a monitor lehetséges károsodására, a számítógép instabilitására és más lehetséges problémákra vonatkozóan.
|
||||
\n
|
||||
\nNem vagyunk felelősek a PC-n egyedi felbontás létrehozásából eredő problémákért.
|
||||
\nNem vállalunk felelősséget a számítógépén egyéni felbontás létrehozásából eredő problémákért.
|
||||
\n
|
||||
\nVégül előfordulhat, hogy az eszköz vagy a fogadó PC nem támogatja a natív felbontású adatfolyamot. Ha a készülékén nem működik, sajnos csak nincs szerencséje.</string>
|
||||
\nElőfordulhat, hogy az Ön monitora nem támogatja a szükséges kijelzőkonfigurációt. Ebben az esetben megpróbálhat egy virtuális monitort beállítani. Végül, ha a készülék vagy a gazdaszámítógép nem támogatja a streaminget egy adott felbontáson vagy frissítési frekvencián, akkor sajnos nincs szerencséje.</string>
|
||||
<string name="title_native_res_dialog">Natív felbontás figyelmeztetés</string>
|
||||
<string name="summary_resolution_list">Növelje a kép tisztaságának növelése érdekében. Csökkenjen a jobb teljesítmény érdekében az alsó kategóriás eszközökön és a lassabb hálózatokon.</string>
|
||||
<string name="title_resolution_list">Videó felbontás</string>
|
||||
@@ -124,10 +124,10 @@
|
||||
<string name="lost_connection">Megszakadt a kapcsolat a PC-vel</string>
|
||||
<string name="no">Nem</string>
|
||||
<string name="yes">Igen</string>
|
||||
<string name="searching_pc">PC-k keresése futó GameStream segítségével ...
|
||||
<string name="searching_pc">A helyi hálózaton lévő PC-k keresése...
|
||||
\n
|
||||
\n Győződjön meg arról, hogy a GameStream engedélyezve van a GeForce Experience SHIELD beállításaiban.</string>
|
||||
<string name="ip_hint">A GeForce PC IP-címe</string>
|
||||
\nGyőződj meg róla, hogy a Sunshine fut a gazdaszámítógépen, vagy a GameStream engedélyezve van a GeForce Experience SHIELD beállításaiban.</string>
|
||||
<string name="ip_hint">A számítógép IP-címe</string>
|
||||
<string name="conn_terminated_msg">A kapcsolat megszakadt</string>
|
||||
<string name="conn_terminated_title">A kapcsolat megszűnt</string>
|
||||
<string name="conn_error_msg">Nem sikerült elindítani</string>
|
||||
@@ -139,9 +139,7 @@
|
||||
<string name="check_ports_msg">Ellenőrizze a tűzfal és a port-továbbítási szabályokat a port(ok)ra vonatkozóan:</string>
|
||||
<string name="early_termination_error">Valami nem sikerült a fogadó PC-n az adatfolyam indításakor.
|
||||
\n
|
||||
\nGyőződjön meg arról, hogy a fogadó PC-n nincs megnyitva DRM-védett tartalom. Megpróbálhatja újraindítani a gazdagépet is.
|
||||
\n
|
||||
\nHa a probléma továbbra is fennáll, próbálja meg újratelepíteni a GPU illesztőprogramokat és a GeForce Experience szoftvert.</string>
|
||||
\nGyőződjön meg arról, hogy a fogadó PC-n nincs megnyitva DRM-védett tartalom. Megpróbálhatja újraindítani a gazdagépet is.</string>
|
||||
<string name="no_frame_received_error">A hálózati kapcsolat nem működik megfelelően. Csökkentse a videó bitráta beállítását, vagy próbálkozzon gyorsabb kapcsolattal.</string>
|
||||
<string name="no_video_received_error">Nem kapott videót a gazdagéptől.</string>
|
||||
<string name="video_decoder_init_failed">A videó dekóder inicializálása nem sikerült. Előfordulhat, hogy készüléke nem támogatja a kiválasztott felbontást vagy képkockasebességet.</string>
|
||||
@@ -149,7 +147,7 @@
|
||||
<string name="error_usb_prohibited">Az USB-hozzáférést az eszköz rendszergazdája tiltja. Ellenőrizze a Knox vagy az MDM beállításait.</string>
|
||||
<string name="message_decoding_reset">Az eszköz videodekóderje továbbra is összeomlik a kiválasztott adatfolyam-beállításoknál. A streaming beállításait visszaállította az alapértelmezettre.</string>
|
||||
<string name="title_decoding_reset">Videó Beállítások Alapra</string>
|
||||
<string name="message_decoding_error">A Moonlight összeomlott, mert inkompatibilis volt az eszköz videó dekóderével. Győződjön meg arról, hogy a GeForce Experience frissítve van a számítógép legújabb verziójára. Próbálja meg módosítani a streaming beállításokat, ha az összeomlások továbbra is fennállnak.</string>
|
||||
<string name="message_decoding_error">A Moonlight összeomlott az eszköz videódekóderével való inkompatibilitás miatt. Próbálja meg módosítani a streaming-beállításokat, ha az összeomlások továbbra is fennállnak.</string>
|
||||
<string name="title_decoding_error">A videó dekóder összeomlott</string>
|
||||
<string name="error_404">A GFE HTTP 404 hibát adott vissza. Győződjön meg arról, hogy a számítógépen támogatott GPU fut. A távoli asztali szoftver használata szintén ezt a hibát okozhatja. Próbálja újraindítani a gépet, vagy telepítse újra a GFE-t.</string>
|
||||
<string name="conn_error_title">Csatlakozási hiba</string>
|
||||
@@ -165,7 +163,7 @@
|
||||
<string name="wol_fail">Nem sikerült elküldeni a Wake-On-LAN csomagokat</string>
|
||||
<string name="wol_waking_msg">Néhány másodpercbe telhet, mire a számítógép felébred. Ha nem, ellenőrizze, hogy megfelelően van-e konfigurálva a Wake-On-LAN számára.</string>
|
||||
<string name="wol_waking_pc">PC elindítása…</string>
|
||||
<string name="wol_no_mac">Nem lehet elindítani a PC-t, mert a GFE nem küldött MAC-címet</string>
|
||||
<string name="wol_no_mac">Nem lehet felébreszteni a számítógépet, mert nincs tárolt MAC-cím</string>
|
||||
<string name="wol_pc_online">A számítógép elérhető</string>
|
||||
<string name="pair_already_in_progress">A párosítás már folyamatban van</string>
|
||||
<string name="pairing">Párosítás…</string>
|
||||
@@ -185,9 +183,9 @@
|
||||
\n
|
||||
\nHa az interneten keresztül kíván közvetíteni, telepítse a Moonlight Internet Hosting Tool alkalmazást a számítógépére, és futtassa a mellékelt Internet Streaming Tester szoftvert a számítógép internetkapcsolatának ellenőrzéséhez.</string>
|
||||
<string name="nettest_title_done">Hálózati kapcsolat teszt kész</string>
|
||||
<string name="nettest_text_waiting">A Moonlight a hálózati kapcsolatot teszteli annak megállapítására, hogy az NVIDIA GameStream blokkolva van-e.
|
||||
<string name="nettest_text_waiting">A Moonlight teszteli a hálózati kapcsolatot, hogy megállapítsa, nem blokkoltak-e szükséges portokat.
|
||||
\n
|
||||
\nEz eltarthat néhány másodpercig …</string>
|
||||
\nEz néhány másodpercig eltarthat…</string>
|
||||
<string name="pcview_menu_test_network">Hálózati kapcsolat teszt</string>
|
||||
<string name="nettest_title_waiting">Hálózati kapcsolat ellenőrzése</string>
|
||||
<string name="pcview_menu_details">Részletek megtekintése</string>
|
||||
@@ -207,4 +205,58 @@
|
||||
<string name="scut_not_paired">PC nincs csatlakoztatva</string>
|
||||
<string name="scut_deleted_pc">PC eltávolítva</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Natív teljes képernyős</string>
|
||||
<string name="summary_setup_guide">Útmutató a játék-PC streamingre való beállításához</string>
|
||||
<string name="title_troubleshooting">Hibaelhárítási útmutató</string>
|
||||
<string name="title_checkbox_reduce_refresh_rate">A frissítési sebesség csökkentésének engedélyezése</string>
|
||||
<string name="summary_frame_pacing">A videók késleltetésének és simaságának egyensúlyának megadása</string>
|
||||
<string name="title_checkbox_enable_audiofx">Rendszeres kiegyenlítő támogatás engedélyezése</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
<string name="title_native_fps_dialog">Natív FPS figyelmeztetés</string>
|
||||
<string name="pacing_balanced">Kiegyensúlyozott</string>
|
||||
<string name="summary_full_range">Ez részletvesztést okoz a világos és sötét területeken, ha a készülék nem jeleníti meg megfelelően a teljes tartományú videotartalmat.</string>
|
||||
<string name="summary_privacy_policy">A Moonlight adatvédelmi szabályzatának megtekintése</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="pacing_smoothness">A legsimább videó előnyben részesítése (jelentősen növelheti a késleltetést)</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="category_help">Segítség</string>
|
||||
<string name="videoformat_av1always">AV1 előnyben részesítése (kísérleti)</string>
|
||||
<string name="audioconf_71surround">7.1 Térhatású hangzás</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream szolgáltatás vége</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Gamepad mozgásérzékelők használatának engedélyezése</string>
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="videoformat_auto">Automatikus (ajánlott)</string>
|
||||
<string name="pacing_balanced_alt">Kiegyensúlyozott FPS-korlátozással</string>
|
||||
<string name="frame_conversion_error">A fogadó számítógép végzetes videokódolási hibát jelentett.
|
||||
\n
|
||||
\nPróbálja meg letiltani a HDR módot, megváltoztatni a streaming felbontást, vagy megváltoztatni a host PC kijelzőjének felbontását.</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Kényszeríti a gamepad touchpad bevitelét a host egér vezérlésére, még akkor is, ha egy touchpaddal ellátott gamepadot emulál.</string>
|
||||
<string name="title_frame_pacing">Videó képkocka ütemezése</string>
|
||||
<string name="resolution_1440p">1440p</string>
|
||||
<string name="resolution_480p">480p</string>
|
||||
<string name="videoformat_hevcalways">HEVC előnyben részesítése</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="audioconf_51surround">5.1 Térhatású hangzás</string>
|
||||
<string name="summary_checkbox_enable_audiofx">Lehetővé teszi az audioeffektek működését streaming közben, de növelheti a hang késleltetését</string>
|
||||
<string name="fps_90">90 FPS</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Lehetővé teszi a támogatott hosztok számára, hogy mozgásérzékelős adatokat kérjenek, amikor mozgásérzékelőkkel ellátott gamepadot emulálnak. A letiltás némileg csökkentheti az energia- és hálózathasználatot, ha a játékban nem használnak mozgásérzékelőket.</string>
|
||||
<string name="resolution_1080p">1080p</string>
|
||||
<string name="summary_seekbar_deadzone">Megjegyzés: Egyes játékok nagyobb holtteret kényszeríthetnek ki, mint amire a Moonlight be van állítva.</string>
|
||||
<string name="audioconf_stereo">Sztereó</string>
|
||||
<string name="videoformat_h264always">Inkább H.264</string>
|
||||
<string name="title_privacy_policy">Adatvédelmi irányelvek</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="category_gamepad_settings">Gamepad beállítások</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="summary_troubleshooting">Tippek a gyakori streaming problémák diagnosztizálásához és javításához</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Távoli asztali egér mód</string>
|
||||
<string name="title_full_range">Teljeskörű videó erőltetése (kísérleti)</string>
|
||||
<string name="summary_checkbox_reduce_refresh_rate">Az alacsonyabb kijelzőfrissítési frekvencia energiát takaríthat meg némi további videokésleltetés árán</string>
|
||||
<string name="resolution_prefix_native_portrait">(Portré)</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Ezáltal az egérgyorsítás természetesebben viselkedik a távoli asztali használat során, de sok játékkal nem kompatibilis.</string>
|
||||
<string name="pair_pairing_help">Ha a számítógépen Sunshine fut, lépj a Sunshine webes felhasználói felületére a PIN-kód megadásához.</string>
|
||||
<string name="title_setup_guide">Telepítési útmutató</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Az egeret mindig az érintőpaddal vezérelje</string>
|
||||
<string name="resolution_prefix_native_landscape">(Tájkép)</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Host feldolgozási késleltetés min/max/átlag: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="pacing_latency">A legalacsonyabb késleltetés előnyben részesítése</string>
|
||||
</resources>
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="pcview_menu_send_wol">Kirim permintaan Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Hapus komputer</string>
|
||||
<string name="nettest_title_waiting">Menguji koneksi jaringan</string>
|
||||
<string name="nettest_text_waiting">Moonlight sedang menguji koneksi jaringan untuk mencari tahu apakah NVIDIA GameStream diblokir.
|
||||
<string name="nettest_text_waiting">Moonlight sedang menguji koneksi jaringan untuk mencari tahu apakah jalur diblokir.
|
||||
\n
|
||||
\nIni mungkin membutuhkan beberapa saat…</string>
|
||||
<string name="nettest_text_inconclusive">Uji koneksi jaringan tidak dapat dilakukan karena tidak ada server pengujian Moonlight yang bisa dijangkau. Cek koneksi Internet Anda atau coba lagi nanti.</string>
|
||||
@@ -93,4 +93,122 @@
|
||||
\n
|
||||
\nJika masalah berkelanjutan, coba install ulang GeForce Experience dan driver video grafis Anda.</string>
|
||||
<string name="help">Bantuan</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream End-of-Service</string>
|
||||
<string name="applist_menu_resume">Lanjutkan Sesi</string>
|
||||
<string name="applist_menu_quit_and_start">Keluar dari Game Saat Ini dan Mulai</string>
|
||||
<string name="applist_menu_quit">Keluar dari Sesi</string>
|
||||
<string name="applist_quit_confirmation">Anda yakin ingin keluar dari aplikasi yang sedang berjalan\? Semua data yang belum disimpan akan hilang.</string>
|
||||
<string name="applist_details_id">ID Aplikasi:</string>
|
||||
<string name="addpc_wrong_sitelocal">Alamat itu sepertinya salah. Anda harus menggunakan alamat IP publik perute untuk streaming melalui Internet.</string>
|
||||
<string name="category_basic_settings">Pengaturan dasar</string>
|
||||
<string name="title_fps_list">Kecepatan bingkai video</string>
|
||||
<string name="summary_fps_list">Tingkatkan untuk streaming video yang lebih lancar. Turunkan untuk kinerja yang lebih baik pada perangkat kelas bawah.</string>
|
||||
<string name="title_seekbar_bitrate">Kecepatan bit video</string>
|
||||
<string name="summary_seekbar_bitrate">Tingkatkan untuk kualitas gambar yang lebih baik. Kurangi untuk meningkatkan kinerja pada koneksi yang lebih lambat.</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Balikkan tombol wajah</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Mengalihkan tombol wajah A/B dan X/Y untuk gamepad dan kontrol di layar</string>
|
||||
<string name="title_only_l3r3">Hanya tampilkan L3 dan R3</string>
|
||||
<string name="dialog_title_reset_osc">Atur Ulang Tata Letak</string>
|
||||
<string name="dialog_text_reset_osc">Yakin ingin menghapus tata letak kontrol di layar yang tersimpan\?</string>
|
||||
<string name="toast_reset_osc_success">Kontrol di layar diatur ulang ke default</string>
|
||||
<string name="resolution_prefix_native_landscape">(Lanskap)</string>
|
||||
<string name="resolution_prefix_native_portrait">(Potret)</string>
|
||||
<string name="summary_checkbox_enable_audiofx">Mengizinkan efek audio berfungsi saat streaming, tetapi dapat meningkatkan latensi audio</string>
|
||||
<string name="category_input_settings">Pengaturan Masukan</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Gunakan layar sentuh sebagai trackpad</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Meniru dukungan gemuruh dengan getaran</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Ini dapat membuat akselerasi mouse berperilaku lebih alami untuk penggunaan desktop jarak jauh, tetapi tidak kompatibel dengan banyak game.</string>
|
||||
<string name="category_on_screen_controls_settings">Pengaturan Kontrol di Layar</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Tampilkan kontrol di layar</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Seni kotak yang lebih kecil di kisi aplikasi memungkinkan lebih banyak aplikasi terlihat di layar</string>
|
||||
<string name="title_checkbox_host_audio">Putar audio di PC</string>
|
||||
<string name="title_checkbox_enable_sops">Optimalkan pengaturan game</string>
|
||||
<string name="title_checkbox_disable_warnings">Nonaktifkan pesan peringatan</string>
|
||||
<string name="summary_checkbox_disable_warnings">Nonaktifkan pesan peringatan koneksi di layar saat streaming</string>
|
||||
<string name="error_unknown_host">Gagal menyelesaikan host</string>
|
||||
<string name="perf_overlay_dectime">Waktu decoding rata-rata: %1$.2f ms</string>
|
||||
<string name="category_host_settings">Pengaturan tuan rumah</string>
|
||||
<string name="frame_conversion_error">PC host melaporkan kesalahan penyandian video yang fatal.
|
||||
\n
|
||||
\nCoba nonaktifkan mode HDR, ubah resolusi streaming, atau ubah resolusi tampilan PC host Anda.</string>
|
||||
<string name="applist_menu_cancel">Membatalkan</string>
|
||||
<string name="applist_menu_details">Melihat rincian</string>
|
||||
<string name="applist_menu_scut">Buat Pintasan</string>
|
||||
<string name="applist_menu_hide_app">Sembunyikan Aplikasi</string>
|
||||
<string name="applist_refresh_title">Daftar Aplikasi</string>
|
||||
<string name="applist_refresh_msg">Menyegarkan aplikasi…</string>
|
||||
<string name="applist_quit_fail">Gagal untuk keluar</string>
|
||||
<string name="title_add_pc">Tambahkan PC Secara Manual</string>
|
||||
<string name="msg_add_pc">Menghubungkan ke PC…</string>
|
||||
<string name="addpc_fail">Tidak dapat terhubung ke komputer yang ditentukan. Pastikan port yang diperlukan diizinkan melalui firewall.</string>
|
||||
<string name="addpc_success">Berhasil menambahkan komputer</string>
|
||||
<string name="addpc_enter_ip">Anda harus memasukkan alamat IP</string>
|
||||
<string name="title_resolution_list">Resolusi video</string>
|
||||
<string name="summary_resolution_list">Tingkatkan untuk meningkatkan kejernihan gambar. Turunkan untuk kinerja yang lebih baik pada perangkat kelas bawah dan jaringan yang lebih lambat.</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||
<string name="title_checkbox_stretch_video">Regangkan video ke layar penuh</string>
|
||||
<string name="resolution_prefix_native">Asli</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Layar Penuh Asli</string>
|
||||
<string name="category_audio_settings">Pengaturan Audio</string>
|
||||
<string name="title_audio_config_list">Konfigurasi suara surround</string>
|
||||
<string name="title_checkbox_enable_audiofx">Aktifkan dukungan equalizer sistem</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">Jika diaktifkan, layar sentuh berfungsi seperti trackpad. Jika dinonaktifkan, layar sentuh langsung mengontrol kursor mouse.</string>
|
||||
<string name="title_checkbox_multi_controller">Deteksi kehadiran gamepad otomatis</string>
|
||||
<string name="summary_checkbox_multi_controller">Menghapus centang opsi ini memaksa gamepad untuk selalu ada</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Getarkan perangkat Anda untuk meniru gemuruh jika gamepad Anda tidak mendukungnya</string>
|
||||
<string name="title_seekbar_deadzone">Sesuaikan zona mati stik analog</string>
|
||||
<string name="title_checkbox_xb1_driver">Xbox 360/Satu driver gamepad USB</string>
|
||||
<string name="summary_checkbox_xb1_driver">Mengaktifkan driver USB bawaan untuk perangkat tanpa dukungan pengontrol Xbox asli</string>
|
||||
<string name="title_checkbox_usb_bind_all">Ganti dukungan gamepad Xbox asli</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Gunakan driver USB Moonlight untuk semua gamepad yang didukung, meskipun ada dukungan pengontrol Xbox asli</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Aktifkan tombol mouse mundur dan maju</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Mode mouse desktop jarak jauh</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Tampilkan hamparan pengontrol virtual di layar sentuh</string>
|
||||
<string name="title_checkbox_vibrate_osc">Aktifkan getaran</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Getarkan perangkat Anda untuk meniru gemuruh untuk kontrol di layar</string>
|
||||
<string name="summary_only_l3r3">Sembunyikan semua tombol virtual kecuali L3 dan R3</string>
|
||||
<string name="summary_reset_osc">Menyetel ulang semua kontrol di layar ke ukuran dan posisi default</string>
|
||||
<string name="title_osc_opacity">Ubah opasitas kontrol di layar</string>
|
||||
<string name="summary_osc_opacity">Jadikan kontrol di layar lebih/kurang transparan</string>
|
||||
<string name="dialog_title_osc_opacity">Ubah opasitas</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="category_ui_settings">Pengaturan UI</string>
|
||||
<string name="summary_checkbox_enable_pip">Mengizinkan streaming untuk dilihat (tetapi tidak dikontrol) saat melakukan banyak tugas</string>
|
||||
<string name="title_language_list">Bahasa</string>
|
||||
<string name="title_checkbox_small_icon_mode">Gunakan seni kotak kecil</string>
|
||||
<string name="summary_checkbox_host_audio">Putar audio dari komputer dan perangkat ini</string>
|
||||
<string name="category_advanced_settings">Pengaturan lanjutan</string>
|
||||
<string name="title_unlock_fps">Buka kunci semua frekuensi gambar yang memungkinkan</string>
|
||||
<string name="summary_unlock_fps">Streaming pada 90 atau 120 FPS dapat mengurangi latensi pada perangkat kelas atas, tetapi dapat menyebabkan kelambatan atau ketidakstabilan pada perangkat yang tidak dapat mendukungnya</string>
|
||||
<string name="title_checkbox_reduce_refresh_rate">Izinkan pengurangan kecepatan penyegaran</string>
|
||||
<string name="summary_checkbox_reduce_refresh_rate">Kecepatan refresh tampilan yang lebih rendah dapat menghemat daya dengan mengorbankan beberapa latensi video tambahan</string>
|
||||
<string name="applist_refresh_error_title">Kesalahan</string>
|
||||
<string name="pair_pairing_help">Jika PC host Anda menjalankan Sunshine, buka UI web Sunshine untuk memasukkan PIN.</string>
|
||||
<string name="applist_quit_app">Berhenti</string>
|
||||
<string name="perf_overlay_renderingfps">Frekuensi gambar rendering: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_netlatency">Rata-rata latensi jaringan: %1$d ms (variasi: %2$d ms)</string>
|
||||
<string name="perf_overlay_netdrops">Bingkai hilang oleh koneksi jaringan Anda: %1$.2f%%</string>
|
||||
<string name="applist_connect_msg">Menghubungkan ke PC…</string>
|
||||
<string name="applist_menu_tv_channel">Tambahkan ke Saluran</string>
|
||||
<string name="applist_refresh_error_msg">Gagal mendapatkan daftar aplikasi</string>
|
||||
<string name="applist_quit_success">Berhasil keluar</string>
|
||||
<string name="addpc_unknown_host">Tidak dapat menyelesaikan alamat PC. Pastikan Anda tidak salah ketik di alamat.</string>
|
||||
<string name="title_native_res_dialog">Peringatan Resolusi Asli</string>
|
||||
<string name="text_native_res_dialog">Mode resolusi asli tidak didukung secara resmi oleh GeForce Experience, sehingga tidak akan mengatur sendiri resolusi tampilan host. Anda harus mengaturnya secara manual saat bermain.
|
||||
\n
|
||||
\nJika Anda memilih untuk membuat resolusi khusus di Panel Kontrol NVIDIA agar sesuai dengan resolusi perangkat Anda, pastikan Anda telah membaca dan memahami peringatan NVIDIA terkait kemungkinan kerusakan monitor, ketidakstabilan PC, dan potensi masalah lainnya.
|
||||
\n
|
||||
\nKami tidak bertanggung jawab atas masalah apa pun yang diakibatkan oleh pembuatan resolusi khusus pada PC Anda.
|
||||
\n
|
||||
\nTerakhir, perangkat atau PC host Anda mungkin tidak mendukung streaming pada resolusi asli. Jika tidak berfungsi pada perangkat Anda, sayangnya Anda kurang beruntung.</string>
|
||||
<string name="summary_audio_config_list">Aktifkan suara surround 5.1 atau 7.1 untuk sistem home theater</string>
|
||||
<string name="summary_seekbar_deadzone">Catatan: Beberapa game dapat menerapkan zona mati yang lebih besar daripada yang dikonfigurasi untuk digunakan oleh Moonlight.</string>
|
||||
<string name="title_checkbox_mouse_emulation">Emulasi mouse melalui gamepad</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Menekan lama tombol Mulai akan mengalihkan gamepad ke mode mouse</string>
|
||||
<string name="title_reset_osc">Hapus tata letak kontrol di layar yang disimpan</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Mengaktifkan opsi ini dapat merusak klik kanan pada beberapa perangkat bermasalah</string>
|
||||
<string name="title_checkbox_enable_pip">Aktifkan mode pengamat Gambar-dalam-Gambar</string>
|
||||
<string name="summary_language_list">Bahasa yang digunakan untuk Moonlight</string>
|
||||
<string name="summary_checkbox_enable_sops">Izinkan GFE mengubah setelan game untuk streaming yang optimal</string>
|
||||
</resources>
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="pair_already_in_progress">Accoppiamento già in corso</string>
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">PC già avviato</string>
|
||||
<string name="wol_no_mac">Impossibile risvegliare il PC perché GFE non ha inviato nessun indirizzo MAC</string>
|
||||
<string name="wol_no_mac">Impossibile risvegliare il PC perché non è stato salvato nessun indirizzo MAC</string>
|
||||
<string name="wol_waking_pc">Risveglio PC…</string>
|
||||
<string name="wol_waking_msg">Il PC potrebbe impiegare qualche secondo per risvegliarsi.
|
||||
Se non succede niente, assicurati che l\'opzione Wake-On-LAN sia configurata correttamente.
|
||||
@@ -60,8 +60,9 @@
|
||||
<string name="conn_terminated_msg">La connessione è stata interrotta</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">Indirizzo IP del PC</string>
|
||||
<string name="searching_pc">Ricerca di PC con GameStream avviato…\n\n
|
||||
Assicurati che GameStream sia abilitato nelle impostazioni SHIELD di GeForce Experience.</string>
|
||||
<string name="searching_pc">Ricerca di PC nella rete locale…
|
||||
\n
|
||||
\n Assicurati che Sunshine sia avviato o che GameStream sia abilitato nelle impostazioni SHIELD di GeForce Experience.</string>
|
||||
<string name="yes">Sì</string>
|
||||
<string name="no">No</string>
|
||||
<string name="lost_connection">Connessione con il PC persa</string>
|
||||
@@ -133,10 +134,10 @@
|
||||
<string name="category_advanced_settings">Impostazioni avanzate</string>
|
||||
<string name="title_disable_frame_drop">Non saltare i fotogrammi</string>
|
||||
<string name="summary_disable_frame_drop">Potrebbe ridurre il micro-stuttering su alcuni dispositivi, ma può aumentare la latenza</string>
|
||||
<string name="title_video_format">Modifica impostazioni HEVC</string>
|
||||
<string name="summary_video_format">HEVC riduce i requisiti di larghezza di banda video ma richiede un dispositivo molto recente</string>
|
||||
<string name="title_video_format">Modifica impostazioni del codec</string>
|
||||
<string name="summary_video_format">I nuovi codec possono ridurre i requisiti di larghezza di banda video se il tuo dispositivo li supporta. La scelta del codec può essere ignorata se non è supportato dal software dell\'host o dalla GPU.</string>
|
||||
<string name="title_enable_hdr">Abilita HDR (sperimentale)</string>
|
||||
<string name="summary_enable_hdr">Utilizza l\'HDR quando il gioco e la scheda video del PC lo supportano. L\'HDR richiede una scheda video serie GTX 1000 o sucessive.</string>
|
||||
<string name="summary_enable_hdr">Utilizza l\'HDR quando il gioco e la scheda video del PC lo supportano. L\'HDR richiede una scheda video col supporto dell\'encoding HEVC Main 10.</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="pcview_menu_header_online">Online</string>
|
||||
<string name="scut_pc_not_found">PC non trovato</string>
|
||||
@@ -161,7 +162,7 @@
|
||||
<string name="perf_overlay_dectime">Tempo medio di decodifica: %1$.2f ms</string>
|
||||
<string name="perf_overlay_streamdetails">Flusso video: %1$s %2$.2f FPS</string>
|
||||
<string name="nettest_title_waiting">Prova della Connessione di Rete</string>
|
||||
<string name="nettest_text_waiting">Moonlight sta testando la tua connessione di rete per controllare se NVIDIA GameStream sia bloccato.
|
||||
<string name="nettest_text_waiting">Moonlight sta testando la tua connessione di rete per controllare se ogni porta richiesta sia bloccata.
|
||||
\n
|
||||
\nPotrebbero volerci alcuni secondi…</string>
|
||||
<string name="nettest_title_done">Test della Rete Completato</string>
|
||||
@@ -208,9 +209,8 @@
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">Surround 5.1</string>
|
||||
<string name="audioconf_71surround">Surround 7.1</string>
|
||||
<string name="videoformat_hevcauto">Automatico (Consigliato)</string>
|
||||
<string name="videoformat_auto">Automatico (Consigliato)</string>
|
||||
<string name="videoformat_hevcalways">Preferisci HEVC</string>
|
||||
<string name="videoformat_hevcnever">Non usare mai HEVC</string>
|
||||
<string name="title_frame_pacing">Bilanciamento frame video</string>
|
||||
<string name="summary_frame_pacing">Specifica come bilanciare il ritardo video e la fluidità</string>
|
||||
<string name="summary_enable_perf_overlay">Mostra informazioni real time sulla trasmissione</string>
|
||||
@@ -227,18 +227,16 @@
|
||||
<string name="no_frame_received_error">La tua connessione di rete non sta funzionando bene. Riduci il bitrate video o prova ad usare una connessione più veloce.</string>
|
||||
<string name="early_termination_error">Qualcosa è andato storto sul PC sorgente mentre la trasmissione veniva avviata.
|
||||
\n
|
||||
\nAssicurati di non avere nessun contenuto protetto da DRM aperto sul PC sorgente. Puoi anche provare a spengere e riaccendere il PC sorgente.
|
||||
\n
|
||||
\nSe il problema persiste, prova a installare di nuovo i driver della scheda video e GeForce Experience.</string>
|
||||
\nAssicurati di non avere nessun contenuto protetto da DRM aperto sul PC sorgente. Puoi anche provare a spengere e riaccendere il PC sorgente.</string>
|
||||
<string name="summary_unlock_fps">Trasmettere a 90 o 120 FPS potrebbe ridurre il ritardo su dispositivi di fascia alta, ma può provocare ritardi i instabilità sui dispositivi che non lo supportano</string>
|
||||
<string name="summary_enable_post_stream_toast">Molstra un messaggio con informazioni sulla latenza dopo che la trasmissione è conclusa</string>
|
||||
<string name="text_native_res_dialog">Le impostazioni di risoluzione nativa non sono ufficialmente supportate da GeForce Experience, quindi non cambierà automaticamente la risoluzione del monitor del computer sorgente. Dovrai cambiarla manualmente all\'interno del gioco.
|
||||
<string name="text_native_res_dialog">Le impostazioni di risoluzione nativa e/o di FPS possono non essere supportate dal server per lo streaming. Dovrai aggiungerle manualmente all\'interno delle impostazioni del PC o del server.
|
||||
\n
|
||||
\nSe scegli di create una risoluzione personalizzata nel Pannello di Controllo NVIDIA per copiare la risoluzione del tuo dispositivo, assicurati di aver letto e capito il messaggio di attenzione di NVIDIA a proposito dei possibili danni al monitor, all\'instabilità del PC e altri potenziali problemi.
|
||||
\nSe scegli di create una risoluzione personalizzata nel Pannello di Controllo NVIDIA per copiare la risoluzione dello schermo, assicurati di aver letto e capito il messaggio di attenzione di NVIDIA a proposito dei possibili danni al monitor, all\'instabilità del PC e altri potenziali problemi.
|
||||
\n
|
||||
\nNon saremo responsabili per qualsiasi problema risultante dalla creazione di una risoluzione personalizzata sul tuo PC.
|
||||
\n
|
||||
\nInfine, il tuo dispositivo o PC sorgente potrebbero non supportare la trasmissione alla risoluzione nativa. Se ciò non funzionasse sul tuo dispositivo, sfortunatamente non ci sono altre soluzioni.</string>
|
||||
\nPuò capitare che il tuo monitor potrebbe non supportare una risoluzione dello schermo richiesta. In questo caso, prova a impostare un monitor virtuale. Infine, se il tuo dispositivo o PC sorgente non supportano la trasmissione ad una specifica risoluzione dello schermo o della frequenza di aggiornamento, sfortunatamente non ci sono altre soluzioni.</string>
|
||||
<string name="perf_overlay_incomingfps">Frame rate in ingresso dalla rete: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_renderingfps">Frame rate renderizzato: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_netdrops">Frame scartati dalla tua connessione di rete: %1$.2f%%</string>
|
||||
@@ -265,4 +263,20 @@
|
||||
<string name="title_checkbox_reduce_refresh_rate">Consenti riduzione della frequenza di aggiornamento</string>
|
||||
<string name="summary_full_range">Ciò causerà la perdita di dettagli in aree chiare e scure se il dispositivo non visualizza correttamente i contenuti video a gamma completa.</string>
|
||||
<string name="title_full_range">Forza video full range (sperimentale)</string>
|
||||
<string name="title_native_fps_dialog">Avviso FPS nativi</string>
|
||||
<string name="videoformat_av1always">Preferisci AV1 (Sperimentale)</string>
|
||||
<string name="pcview_menu_eol">Terminazione del servizio NVIDIA GameStream</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Permetti l\'uso dei sensori giroscopici del gamepad</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Forza l\'input del touchpad del gamepad a controllare il mouse dell\'host, anche quando si sta emulando un gamepad col touchpad.</string>
|
||||
<string name="toast_controller_type_changed">Il tipo di gamepad potrebbe cambiare se è attiva l\'emulazione dei sensori giroscopici</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Abilita per gli host supportati la trasmissione dei dati dai sensori giroscopici quando si simula un gamepad con sensori giroscopici. Disabilitandolo può ridurre il consumo di batteria e la rete richiesta per lo stream se i sensori giroscopici non vengono utilizzati nel gioco.</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Usa i sensori giroscopici integrati nel tuo dispositivo se il tuo gamepad non possiede i sensori giroscopici o non sono compatibili con la tua versione Android.
|
||||
\nNota: Abilitare questa opzione farà apparire il tuo gamepad come un controller Playstation all\'host.</string>
|
||||
<string name="videoformat_h264always">Preferisci H.264</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="category_gamepad_settings">Impostazioni del gamepad</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Emula il supporto dei sensori giroscopici del gamepad</string>
|
||||
<string name="pair_pairing_help">Se il tuo PC host sta eseguendo Sunshine, vai nella pagina web locale di Sunshine ed inserisci il PIN.</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Controlla sempre il mouse col touchpad</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Latenza di codifica da parte dell\'host min/max/average: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="scut_deleted_pc">מחשב נמחק</string>
|
||||
<string name="scut_not_paired">מחשב לא מצורף</string>
|
||||
<string name="help_loading_msg">טוען עמוד עזרה…</string>
|
||||
<string name="pcview_menu_header_online">פעיל</string>
|
||||
<string name="pcview_menu_unpair_pc">הסר אימות</string>
|
||||
<string name="pcview_menu_details">הראה פרטים</string>
|
||||
<string name="nettest_text_waiting">מונלייט בודק את הרשת שלך ובודק אם ישנם פורטים הכרחיים חסומים
|
||||
\n
|
||||
\nהמתן כמה שניות…</string>
|
||||
<string name="wol_no_mac">לא מצליח להעיר את המחשב, אין כתובת MAC</string>
|
||||
<string name="scut_pc_not_found">מחשב לא נמצא</string>
|
||||
<string name="help_loading_title">עזרה</string>
|
||||
<string name="scut_invalid_uuid">המחשב אינו תואם</string>
|
||||
<string name="scut_invalid_app_id">האפליקציה אינה מתאימה</string>
|
||||
<string name="pcview_menu_header_offline">כבוי</string>
|
||||
<string name="pcview_menu_header_unknown">מרענן</string>
|
||||
<string name="pcview_menu_app_list">הראה את כל האפליקציות</string>
|
||||
<string name="pcview_menu_pair_pc">אמת מחשב</string>
|
||||
<string name="pcview_menu_send_wol">שלח פקודת \"Wake-On-LAN\"</string>
|
||||
<string name="pcview_menu_delete_pc">מחק מחשב</string>
|
||||
<string name="pcview_menu_test_network">בדוק חיבור רשת</string>
|
||||
<string name="pcview_menu_eol">סוף פעילות שירות NVIDIA GameStream</string>
|
||||
<string name="nettest_title_waiting">בודק חיבור רשת</string>
|
||||
<string name="nettest_title_done">בדיקת רשת הושלמה</string>
|
||||
<string name="nettest_text_inconclusive">בדיקת הרשת לא התבצעה בגלל שאין קישוריות לשרתי הבדיקה של מונלייט. בבקשה בדוק את החיבור לאינטרנט או נסה שוב מאוחר יותר.</string>
|
||||
<string name="nettest_text_failure">גישה של מונלייט לרשת חסומה במכשיר הנוכחי. הזרמה על גבי האינטרנט לא יכוה לעבוד כל עוד מונלייט מחובר לרשת הנוכחית.
|
||||
\n
|
||||
\nהפורטים הבאים חסומים:
|
||||
\n</string>
|
||||
<string name="nettest_text_blocked">חיבור הרשת הנוכחי חוסם את מונלייט. הזרמה על גבי האינטרנט אינה אפשרית כל עוד מונלייט מחובר לרשת הנוכחית.</string>
|
||||
<string name="pair_pc_offline">מחשב לא פעיל</string>
|
||||
<string name="pair_pairing_title">מחבר</string>
|
||||
<string name="pair_pairing_msg">אנא הזן את הקוד PIN הבא במחשב המארח:</string>
|
||||
<string name="pair_pairing_help">אם המחשב המארח פועל על Sunshine, נווט אל דף הניהול על מנת להזין קוד PIN.</string>
|
||||
<string name="pair_incorrect_pin">קוד PIN שגוי</string>
|
||||
<string name="pair_fail">חיבור נכשל</string>
|
||||
<string name="wol_pc_online">מחשב פעיל</string>
|
||||
<string name="wol_fail">נכשל לשלוח פקודת Wake-On-LAN</string>
|
||||
<string name="unpairing">מנתק חיבור…</string>
|
||||
<string name="unpair_success">ניתוק הושלם</string>
|
||||
<string name="unpair_fail">ניתוק נכשל</string>
|
||||
<string name="unpair_error">המחשב לא חובר</string>
|
||||
<string name="error_pc_offline">המחשב לא פעיל</string>
|
||||
<string name="error_unknown_host">נכשל לאתר את המארח</string>
|
||||
<string name="title_decoding_error">מפענח וידיאו קרס</string>
|
||||
<string name="unable_to_pin_shortcut">האפליקציה אינה מרשה יצירת קיצורי דרך נעוצים.</string>
|
||||
<string name="no_video_received_error">לא התקבל אות וידיאו מהמארח.</string>
|
||||
<string name="conn_client_latency">מהירות פיענוח פריים ממוצעת:</string>
|
||||
<string name="conn_error_title">שגיאת חיבור</string>
|
||||
<string name="conn_terminated_msg">החיבור הופסק</string>
|
||||
<string name="ip_hint">כתובת IP של המחשב המארח</string>
|
||||
<string name="title_details">פרטים</string>
|
||||
<string name="poor_connection_msg">חיבור חלש למחשב</string>
|
||||
<string name="perf_overlay_decoder">מפענח: %1$s</string>
|
||||
<string name="perf_overlay_incomingfps">פריימים לשניה מהרשת: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_netdrops">פריימים שנפלו בחיבור רשת: %1$.2f%%</string>
|
||||
<string name="perf_overlay_dectime">זמן פענוח ממוצע: %1$.2f ms</string>
|
||||
<string name="applist_connect_msg">מתחבר למחשב…</string>
|
||||
<string name="applist_menu_resume">חזור לשידור</string>
|
||||
<string name="applist_menu_quit_and_start">סגור משחק נוכחי והתחל</string>
|
||||
<string name="applist_menu_details">הראה פרטים</string>
|
||||
<string name="applist_menu_scut">צור קיצור דרך</string>
|
||||
<string name="applist_quit_app">יוצא</string>
|
||||
<string name="applist_quit_success">יציאה הושלמה בהצלחה</string>
|
||||
<string name="applist_details_id">מספר אפליקציה:</string>
|
||||
<string name="title_add_pc">הוספת מחשב ידנית</string>
|
||||
<string name="addpc_enter_ip">חייב להכניס כתובת IP</string>
|
||||
<string name="category_basic_settings">הגדרות בסיסיות</string>
|
||||
<string name="title_resolution_list">רזולוציית וידיאו</string>
|
||||
<string name="title_native_res_dialog">אזהרת רזולוצייה טבעית</string>
|
||||
<string name="title_fps_list">פריימים לשניה</string>
|
||||
<string name="wol_waking_msg">ייקחו כמה שניות להפעיל את המחשב. אם הוא לא, אנא וודא שהוא מוגדר נכון לפונקציית Wake-On-LAN.</string>
|
||||
<string name="nettest_text_success">הרשת שלך איננה חוסמת את מונלייט, בבקשה בדוק את הגדרות חומת האש במחשב המארח.
|
||||
\n
|
||||
\nאם אתה מנסה להזרים דרך האינטרנט, אנא התקן את הכל Moonlight Internet Hosting Tool על המחשב והפעל את כלי הבדיקה המצורף בכדי לבדוק את חיבור האינטרנט.</string>
|
||||
<string name="pairing">מאמת…</string>
|
||||
<string name="pair_pc_ingame">מחשב באמצע משחק. נא לצאת מהמשחק לפני ביצוע חיבור.</string>
|
||||
<string name="pair_already_in_progress">פעולת החיבור מתבצעת</string>
|
||||
<string name="wol_waking_pc">מעיר מחשב…</string>
|
||||
<string name="error_manager_not_running">שירות \"ניהול-מחשב\" לא פעיל. אנא חכה כמה שניות להפעלה מחדש של האפליקציה.</string>
|
||||
<string name="title_decoding_reset">הגדרות וידיאו אופסו</string>
|
||||
<string name="error_404">GFE החזיר שגיאת 404. אנא וודא שהמחשב עם כרטיס מסך נתמך. שימוש בתוכנת חיבור מרוחק יכולה לגרום לשגיאה זו. נסה להפעיל מחדש את המחשב או להתקין GFE.</string>
|
||||
<string name="error_usb_prohibited">גישה למכשירי USB נעולה על ידי מנהל המחשב. בדוק הגדרות knox או MDM.</string>
|
||||
<string name="message_decoding_error">מונלייט קרס עקב אי-תאימות עם המפענח. נסה לשנות את הגדרות ההזרמה אם הקריסות נמשכות.</string>
|
||||
<string name="message_decoding_reset">המפענח ממשיך לקרוס בהגדרות הנוכחיות. הגדרות ההזרמה אופסו לברירת המחדל.</string>
|
||||
<string name="video_decoder_init_failed">נכשלה טעינת מפענח הוידיאו. המכשיר שלך כנראה אינו תומך ברזולוציה או פריימים לשניה שנבחרו.</string>
|
||||
<string name="no_frame_received_error">חיבור הרשת של אינו מתפקד כראוי. הורד את הגדרות ה-Bitrate או נסה חיבור מהיר יותר.</string>
|
||||
<string name="check_ports_msg">בדוק את חומת האש וניהול פורטים עבור הפורטים הבאים:</string>
|
||||
<string name="conn_establishing_title">מתחיל חיבור</string>
|
||||
<string name="addpc_success">מחשב נוסף בהצלחה</string>
|
||||
<string name="early_termination_error">מששהו קרה במחשב המארח כשהחלה הזרמה.
|
||||
\n
|
||||
\nאנא וודא שאין תוכן מוגן DRM פתוח במחשב. אפשר לנסות להפעיל מחדש את המחשב.</string>
|
||||
<string name="slow_connection_msg">חיבור איטי למחשב
|
||||
\nהורד Bitrate</string>
|
||||
<string name="frame_conversion_error">המחשב המארח דיווח על שגיאת הצפנת וידיאו.
|
||||
\n
|
||||
\nנסה לבטל הגדרת HDR, החלפת רזולוציית הזרמה או לשנות את רזולוציית המחשב המארח.</string>
|
||||
<string name="conn_establishing_msg">מתחבר</string>
|
||||
<string name="conn_starting">מתחיל</string>
|
||||
<string name="conn_metered">אזהרה: החיבור הנוכחי הוא נמדד!</string>
|
||||
<string name="conn_terminated_title">החיבור הופסק</string>
|
||||
<string name="lost_connection">נאבד החיבור למחשב</string>
|
||||
<string name="delete_pc_msg">אתה בטוח שאתה רוצה להסיר מחשב זה\?</string>
|
||||
<string name="conn_client_latency_hw">מהירות פענוח חומרתי:</string>
|
||||
<string name="conn_error_msg">נכשל להפעיל</string>
|
||||
<string name="searching_pc">מחפש מחשבים ברשת המקומית שלך...
|
||||
\n
|
||||
\nוודא שסאנשיין או GeForce Experience פועלים.</string>
|
||||
<string name="yes">כן</string>
|
||||
<string name="no">לא</string>
|
||||
<string name="help">עזרה</string>
|
||||
<string name="perf_overlay_streamdetails">הזרמת וידיאו: %1$s %2$.2f FPS</string>
|
||||
<string name="perf_overlay_renderingfps">פריימים מרונדרים: %1$.2f FPS</string>
|
||||
<string name="applist_menu_hide_app">הסתר אפליקציה</string>
|
||||
<string name="perf_overlay_netlatency">מהירות תגובה ממוצעת: %1$d ms (שונות: %2$d ms)</string>
|
||||
<string name="applist_menu_quit">הפסק שידור</string>
|
||||
<string name="applist_menu_cancel">בטל</string>
|
||||
<string name="applist_refresh_error_msg">נכשל להשיג רשימת אפליקציות</string>
|
||||
<string name="applist_quit_fail">יציאה נכשלה</string>
|
||||
<string name="applist_menu_tv_channel">הוסף לערוץ</string>
|
||||
<string name="applist_refresh_title">רשימת אפליקציות</string>
|
||||
<string name="applist_refresh_msg">מרענן אפליקציות…</string>
|
||||
<string name="applist_refresh_error_title">שגיאה</string>
|
||||
<string name="applist_quit_confirmation">אתה בטוח שאתה רוצה לסגור את האפליקציה הנוכחית\? מידע שלא נשמר ייאבד.</string>
|
||||
<string name="msg_add_pc">מתחבר למחשב…</string>
|
||||
<string name="addpc_unknown_host">נכשל לאתר כתובת מחשב. נא לוודא שאין שגיאה בכתובת.</string>
|
||||
<string name="addpc_fail">לא ניתן להתחבר למחשב שנבחר. נא לבדוק שהפורטים הנחוצים פתוחים בחומת האש.</string>
|
||||
<string name="addpc_wrong_sitelocal">הכתובת לא נראת נכונה. צריך להשתמש בכתובת IP הציבורית בכדי להתחבר דרך האינטרנט.</string>
|
||||
<string name="summary_resolution_list">להגביר לשיפור איכות התמונה. להוריד לשיפור ביצועים על מערכות ישנות ורשתות איטיות.</string>
|
||||
<string name="text_native_res_dialog">רזולוציות טבעיות אינן נתמכות רשמית דרך Geforce Expereience, הרזולוציה לא מוגדרת במסך המארח. יש להגדירה ידנית בזמן משחק.
|
||||
\n
|
||||
\nיש לקרוא ולהבין את ההנחיות של NVIDIA לגבי אי יציבות ונזקים אם מגדירים רזולוציה מותאמת אישית דרך פאנל הניהול.
|
||||
\n
|
||||
\nמונלייט אינו אחראי לבעיות או נזקים שנגרמים כתוצאה משימוש ברזולוציה מותאמת אישית.
|
||||
\n
|
||||
\nהמכשיר שלך כנראה ואינו תומך ברזולוציה טבעית.</string>
|
||||
<string name="summary_seekbar_bitrate">הגבר לשיפור איכות התמונה. הנמך בכדי לשפר ביצועים על גבי חיבור רשת איטי.</string>
|
||||
<string name="summary_audio_config_list">הפעל קול היקפי בהגדרת 5.1 או 7.1 עבור מערכות קולנוע ביתי</string>
|
||||
<string name="summary_checkbox_enable_audiofx">אפשר לאפקטי סאונד לפעול בזמן הזרמה, יגרום להשהיית אודיו</string>
|
||||
<string name="conn_hardware_latency">זמן פענוח ממוצע:</string>
|
||||
<string name="summary_fps_list">הגבר להזרמת וידיאו חלקה יותר. הנמך לביצועים ויציבות במכשירים חלשים.</string>
|
||||
<string name="title_seekbar_bitrate">וידיאו ביטרייט</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">מגהביט</string>
|
||||
<string name="title_checkbox_stretch_video">מתחית וידיאו למסך מלא</string>
|
||||
<string name="resolution_prefix_native">טבעי</string>
|
||||
<string name="resolution_prefix_native_fullscreen">טבעי במסך מלא</string>
|
||||
<string name="category_audio_settings">הגדרות אודיו</string>
|
||||
<string name="title_audio_config_list">הגדרת קול היקפי (Surround sound)</string>
|
||||
<string name="title_checkbox_enable_audiofx">הפעל תמיכה באקולייזר</string>
|
||||
<string name="category_input_settings">הגדרות קלט</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">השתמש במסך מגע כמשטח מגע</string>
|
||||
</resources>
|
||||
@@ -1,13 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- PC view menu entries -->
|
||||
<string name="pcview_menu_app_list">ゲームリストを表示</string>
|
||||
<string name="pcview_menu_pair_pc">コンピュータとペアリング</string>
|
||||
<string name="pcview_menu_unpair_pc">ペアリングを解除r</string>
|
||||
<string name="pcview_menu_send_wol">Wake-On-LANリクエストを送信する</string>
|
||||
<string name="pcview_menu_delete_pc">コンピュータをリストから削除する</string>
|
||||
|
||||
<!-- Pair messages -->
|
||||
<string name="pairing">ペアリング中</string>
|
||||
<string name="pair_pc_offline">コンピュータはオフラインです</string>
|
||||
@@ -16,26 +14,22 @@
|
||||
<string name="pair_pairing_msg">ペアリングしたいコンピュータのPINコードを入力してください:</string>
|
||||
<string name="pair_incorrect_pin">PINコードが間違っています</string>
|
||||
<string name="pair_fail">ペアリングに失敗しました</string>
|
||||
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">コンピュータはオンラインです</string>
|
||||
<string name="wol_no_mac">GFEが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>
|
||||
|
||||
<!-- Unpair messages -->
|
||||
<string name="unpairing">ペアリングの解除中</string>
|
||||
<string name="unpair_success">ペアリングの解除に成功しました</string>
|
||||
<string name="unpair_fail">ペアリングの解除に失敗しました</string>
|
||||
<string name="unpair_error">このデバイスはペアリングされませんでした</string>
|
||||
|
||||
<!-- Errors -->
|
||||
<string name="error_pc_offline">コンピュータはオフラインです</string>
|
||||
<string name="error_manager_not_running">ComputerManagerサービスが動作していません。しばらく待つか、Moonlightを再起動してください</string>
|
||||
<string name="error_unknown_host">ホストが解決できません</string>
|
||||
<string name="error_404">GFEがHTTP 404を返しました。コンピュータでサポートされているGPUが動作しているか確認してください。リモートデスクトップソフトウェアでもこのエラーが発生する可能性があります。コンピュータを再起動するか、GFEを再インストールしてください</string>
|
||||
|
||||
<!-- Start application messages -->
|
||||
<string name="conn_establishing_title">接続を確立</string>
|
||||
<string name="conn_establishing_msg">接続を開始</string>
|
||||
@@ -48,14 +42,12 @@
|
||||
<string name="conn_error_msg">開始できません</string>
|
||||
<string name="conn_terminated_title">接続を終了</string>
|
||||
<string name="conn_terminated_msg">接続は終了しました</string>
|
||||
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">コンピュータのIPアドレス</string>
|
||||
<string name="searching_pc">コンピュータを検索中</string>
|
||||
<string name="yes">はい</string>
|
||||
<string name="no">いいえ</string>
|
||||
<string name="lost_connection">コンピュータとの接続が失われました</string>
|
||||
|
||||
<!-- AppList activity -->
|
||||
<string name="applist_menu_resume">セッションを続ける</string>
|
||||
<string name="applist_menu_quit">セッションを終了する</string>
|
||||
@@ -69,7 +61,6 @@
|
||||
<string name="applist_quit_success">ゲームを終了しました</string>
|
||||
<string name="applist_quit_fail">ゲームが終了できませんでした</string>
|
||||
<string name="applist_quit_confirmation">本当にゲームを終了しますか? 保存されていないデータは破棄されます</string>
|
||||
|
||||
<!-- Add computer manually activity -->
|
||||
<string name="title_add_pc">手動でコンピュータを追加する</string>
|
||||
<string name="msg_add_pc">コンピュータに接続中</string>
|
||||
@@ -77,7 +68,6 @@
|
||||
<string name="addpc_success">コンピュータの追加に成功しました</string>
|
||||
<string name="addpc_unknown_host">コンピュータのアドレスが解決できません。コンピュータのアドレスを確認してください</string>
|
||||
<string name="addpc_enter_ip">IPアドレスを入力してください</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<string name="category_basic_settings">基本的な設定</string>
|
||||
<string name="title_resolution_list">解像度とフレームレート</string>
|
||||
@@ -87,32 +77,26 @@
|
||||
<string name="title_checkbox_stretch_video">映像を全画面に拡大</string>
|
||||
<string name="title_checkbox_disable_warnings">警告を無効化</string>
|
||||
<string name="summary_checkbox_disable_warnings">ストリーミング中に画面に警告メッセージを表示しない</string>
|
||||
|
||||
<string name="category_audio_settings">音声</string>
|
||||
|
||||
<string name="title_checkbox_multi_controller">複数のゲームコントローラ</string>
|
||||
<string name="summary_checkbox_multi_controller">チェックを外すと、全てのゲームコントローラが単一の物として認識されます</string>
|
||||
<string name="title_seekbar_deadzone">アナログゲームコントローラのデッドゾーン</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Xbox 360/Oneコントローラ</string>
|
||||
<string name="summary_checkbox_xb1_driver">XboxゲームコントローラをサポートしないデバイスでXboxゲームコントローラ用のドライバを有効にします</string>
|
||||
|
||||
<string name="category_on_screen_controls_settings">オンスクリーンコントローラ</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">オンスクリーンコントローラ</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">タッチスクリーン上にオンスクリーンコントローラを表示します</string>
|
||||
|
||||
<string name="category_ui_settings">インターフェース</string>
|
||||
<string name="title_language_list">言語</string>
|
||||
<string name="summary_language_list">Moonlightで使用する言語</string>
|
||||
<string name="title_checkbox_small_icon_mode">小さなアイコン</string>
|
||||
<string name="summary_checkbox_small_icon_mode">グリッドで小さなアイコンを使用します</string>
|
||||
|
||||
<string name="category_host_settings">ホスト</string>
|
||||
<string name="title_checkbox_enable_sops">ゲーム設定の最適化</string>
|
||||
<string name="summary_checkbox_enable_sops">GFEがゲームの設定を最適化します</string>
|
||||
<string name="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>
|
||||
@@ -129,9 +113,28 @@
|
||||
<string name="toast_reset_osc_success">オンスクリーンコントローラをデフォルトに戻しました</string>
|
||||
<string name="title_checkbox_vibrate_osc">振動</string>
|
||||
<string name="summary_checkbox_vibrate_osc">コントローラの振動を真似します</string>
|
||||
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">安定している場合にHEVCを有効化</string>
|
||||
<string name="videoformat_hevcalways">HEVCを強制的に有効化(クラッシュする可能性があります)</string>
|
||||
<string name="videoformat_hevcnever">HEVCを無効化</string>
|
||||
</resources>
|
||||
<string name="scut_not_paired">コンピュータとペアリングされてません</string>
|
||||
<string name="scut_invalid_uuid">指定したコンピュータは有効ではないです</string>
|
||||
<string name="scut_invalid_app_id">指定したアプリは無効です</string>
|
||||
<string name="help_loading_msg">ヘルプページを読み込み中…</string>
|
||||
<string name="nettest_text_success">ネットワークは Moonlight をブロックしていません。接続に問題があるようでしたらコンピュータのファイアーウォールの設定を確認してください。
|
||||
\n
|
||||
\nインターネット上でゲームをストリームする場合は Moonlight Internet Hosting Tool をインストールして付属のInternet Streaming Tester をはしらせコンピュータの接続を確認してください。</string>
|
||||
<string name="nettest_text_inconclusive">Moonlight のコネクションテスト用のサーバーがアクセスできなかったためネットワークテストができませんでした。インターネットの接続を確認し、再度お試しください。</string>
|
||||
<string name="help_loading_title">ヘルプ表示</string>
|
||||
<string name="pcview_menu_header_unknown">リロード中</string>
|
||||
<string name="scut_deleted_pc">コンピュータを検知しました</string>
|
||||
<string name="scut_pc_not_found">コンピュータが見つかりませんでした</string>
|
||||
<string name="pcview_menu_header_offline">オフライン</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream はサービスが終了しています</string>
|
||||
<string name="nettest_text_waiting">Moonlight はポートがブロックされていないか確かめるためネットワーク接続をてすとしています。
|
||||
\n
|
||||
\n少々お待ちください…</string>
|
||||
<string name="pcview_menu_header_online">オンライン</string>
|
||||
<string name="pcview_menu_test_network">ネットワーク接続テスト</string>
|
||||
<string name="nettest_title_done">ネットワークテスト終了</string>
|
||||
<string name="pcview_menu_details">詳細を表示</string>
|
||||
<string name="nettest_title_waiting">ネットワーク接続テスト中</string>
|
||||
</resources>
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="pair_already_in_progress">페어링이 이미 진행중입니다</string>
|
||||
<!-- WOL messages -->
|
||||
<string name="wol_pc_online">컴퓨터가 온라인 상태입니다</string>
|
||||
<string name="wol_no_mac">Geforce Experience가 MAC 주소를 보내지 않아 PC를 켤 수 없습니다.</string>
|
||||
<string name="wol_no_mac">저장된 MAC 주소가 없기 때문에 PC를 켤 수 없습니다.</string>
|
||||
<string name="wol_waking_pc">PC를 깨우는 중…</string>
|
||||
<string name="wol_waking_msg">PC를 켜는 데에 약간의 시간이 걸립니다. PC가 켜지지 않으면, Wake-On-Lan이 설정되어있는지 확인하세요.</string>
|
||||
<string name="wol_fail">Wake-On-LAN 패킷을 보내는 데에 실패했습니다</string>
|
||||
@@ -52,9 +52,10 @@
|
||||
<string name="conn_terminated_title">연결 종료 됨</string>
|
||||
<string name="conn_terminated_msg">연결이 종료되었습니다</string>
|
||||
<!-- General strings -->
|
||||
<string name="ip_hint">GeForce PC의 IP 주소</string>
|
||||
<string name="searching_pc">GameStream이 실행중인 PC를 검색중…\n\n
|
||||
GameStream이 Geforce Experience 설정에서 활성화되어있는지 확인하세요.</string>
|
||||
<string name="ip_hint">호스트 PC의 IP 주소</string>
|
||||
<string name="searching_pc">로컬 네트워크의 호스트 PC를 검색중…
|
||||
\n
|
||||
\n 호스트 PC에서 Sunshine이 실행 중인지 또는 GeForce Experience SHIELD 설정에서 GameStream이 활성화되어 있는지 확인하십시오.</string>
|
||||
<string name="yes">예</string>
|
||||
<string name="no">아니오</string>
|
||||
<string name="lost_connection">PC 연결 끊김</string>
|
||||
@@ -90,8 +91,8 @@
|
||||
<string name="title_checkbox_disable_warnings">경고 메세지 끄기</string>
|
||||
<string name="summary_checkbox_disable_warnings">화면 상의 연결 경고 메세지를 스트리밍 중에 비활성화합니다.</string>
|
||||
<string name="category_audio_settings">오디오 설정</string>
|
||||
<string name="title_checkbox_multi_controller">다중 컨트롤러 지원</string>
|
||||
<string name="summary_checkbox_multi_controller">이 옵션을 선택하지 않으면 모든 컨트롤러가 하나로 표시됩니다</string>
|
||||
<string name="title_checkbox_multi_controller">자동 컨트롤러 유무 감지</string>
|
||||
<string name="summary_checkbox_multi_controller">이 옵션을 선택 취소하면 컨트롤러가 항상 표시됩니다</string>
|
||||
<string name="title_seekbar_deadzone">아날로그 스틱 데드존 설정</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Xbox 360/One 컨트롤러 드라이버</string>
|
||||
@@ -110,11 +111,11 @@
|
||||
<string name="title_checkbox_host_audio">PC에서 소리 재생</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">최신 코덱은 장치에서 지원하는 경우 비디오 대역폭 요구 사항을 낮출 수 있습니다. 호스트 소프트웨어 또는 GPU에서 지원하지 않는 경우 코덱 선택을 무시할 수 있습니다.</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="title_checkbox_enable_pip">PIP모드 활성화</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">게임 패드가 진동을 지원하지 않는 경우 장치를 진동 시켜 진동을 활성화합니다</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">컨트롤러가 진동을 지원하지 않는 경우 장치를 진동 시켜 진동을 활성화합니다</string>
|
||||
<string name="title_checkbox_vibrate_fallback">게임패드 진동을 장치에서 사용하기</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">활성화시 터치 스크린이 트랙 패드처럼 작동합니다. 비활성화 된 경우 터치 스크린처럼 작동합니다.</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">터치 스크린을 트랙 패드로 사용하기</string>
|
||||
@@ -124,13 +125,13 @@
|
||||
<string name="resolution_prefix_native">네이티브</string>
|
||||
<string name="summary_fps_list">높을수록 화면이 더 부드러워집니다. 저사양 기기에서는 낮추는것이 좋습니다.</string>
|
||||
<string name="title_fps_list">FPS 설정</string>
|
||||
<string name="text_native_res_dialog">1. 네이티브 해상도 모드는 GeForce Experience에서 공식적으로 지원되지 않으므로 호스트PC의 디스플레이 해상도는 변경되지 않습니다. 따라서 스트리밍 중에 수동으로 해상도를 변경해야합니다.
|
||||
<string name="text_native_res_dialog">네이티브 해상도 및 FPS는 스트리밍 서버에서 지원하지 않을 수 있습니다. 호스트 PC에 대해 일치하는 사용자 지정 디스플레이 모드를 수동으로 구성해야 할 수 있습니다.
|
||||
\n
|
||||
\n2. 장치 해상도와 일치하도록 NVIDIA 제어판에서 사용자 정의 해상도를 생성 할 경우 호스트 PC의 모니터 손상, 기타 잠재적 문제에 대한 NVIDIA의 경고를 읽고 이해했는지 확인하십시오.
|
||||
\n
|
||||
\n3. Moonlight는 PC에서 사용자 정의 해상도를 생성하여 발생하는 문제에 대해 책임을 지지 않습니다.
|
||||
\n화면 설정과 일치하도록 NVIDIA 제어판에서 사용자 정의 해상도를 생성 할 경우 모니터 손상, PC 불안정 및 기타 잠재적인 문제에 대한 NVIDIA의 경고를 읽고 이해했는지 확인하십시오.
|
||||
\n
|
||||
\n4. 장치 또는 호스트 PC가 네이티브 해상도의 스트리밍을 지원하지 않을 수 있습니다.</string>
|
||||
\nMoonlight는 PC에서 사용자 지정 해상도를 생성하여 발생하는 문제에 대해 책임을 지지 않습니다.
|
||||
\n
|
||||
\n모니터가 필요한 디스플레이 구성을 지원하지 않을 경우 가상 모니터 설정을 시도할 수 있습니다. 장치나 호스트 PC가 특정 해상도나 새로 고침 빈도로 스트리밍을 지원하지 않을 수 있습니다.</string>
|
||||
<string name="title_native_res_dialog">네이티브 해상도 주의사항</string>
|
||||
<string name="addpc_wrong_sitelocal">주소가 잘못된 것 같습니다. 인터넷을 통해 스트리밍하려면 라우터의 공용 IP 주소를 사용해야합니다.</string>
|
||||
<string name="applist_details_id">앱 ID:</string>
|
||||
@@ -151,16 +152,14 @@
|
||||
<string name="check_ports_msg">다음 포트의 방화벽 및 포트 포워딩 설정을 확인하십시오:</string>
|
||||
<string name="early_termination_error">스트림을 시작할 때 호스트 PC에서 문제가 발생했습니다.
|
||||
\n
|
||||
\n호스트 PC에 DRM으로 보호 된 콘텐츠가 열려 있지 않은지 확인하거나 호스트 PC를 재부팅하십시오 .
|
||||
\n
|
||||
\n문제가 지속되면 GPU 드라이버와 GeForce Experience를 다시 설치해보십시오.</string>
|
||||
\n호스트 PC에 DRM으로 보호 된 콘텐츠가 열려 있지 않은지 확인하거나 호스트 PC를 재부팅하십시오 .</string>
|
||||
<string name="no_frame_received_error">네트워크 연결이 불안정합니다. 비트레이트를 낮추거나 더 빠른 네트워크에 연결하십시오.</string>
|
||||
<string name="no_video_received_error">호스트로부터 비디오를 받지 못했습니다.</string>
|
||||
<string name="video_decoder_init_failed">비디오 디코더를 실행하지 못했습니다. 이 장치가 선택한 해상도 또는 프레임 속도를 지원하지 않을 수 있습니다.</string>
|
||||
<string name="error_usb_prohibited">기기 관리자에 의해 USB 액세스가 차단되었습니다. Knox 또는 MDM 설정을 확인하십시오.</string>
|
||||
<string name="message_decoding_reset">선택한 스트리밍 설정에서 장치의 비디오 디코더가 계속 문제가 발생합니다. 스트리밍 설정이 기본값으로 재설정되었습니다.</string>
|
||||
<string name="title_decoding_reset">비디오 설정 초기화</string>
|
||||
<string name="message_decoding_error">이 장치의 비디오 디코더와 호환되지 않아 Moonlight에서 오류가 발생했습니다. GeForce Experience가 PC의 최신 버전으로 업데이트되었는지 확인하십시오. 충돌이 계속되면 스트리밍 설정을 조정 해보십시오.</string>
|
||||
<string name="message_decoding_error">이 장치의 비디오 디코더와 호환되지 않아 Moonlight에서 오류가 발생했습니다. 충돌이 계속되면 스트리밍 설정을 조정 해보십시오.</string>
|
||||
<string name="title_decoding_error">비디오 디코더 오류</string>
|
||||
<string name="nettest_text_blocked">기기의 현재 네트워크가 Moonlight를 차단하고 있습니다. 이 네트워크에 연결되어 있으면 인터넷을 통한 스트리밍이 작동하지 않을 수 있습니다.</string>
|
||||
<string name="nettest_text_failure">기기의 현재 네트워크가 Moonlight를 차단하는 것 같습니다. 이 네트워크에 연결되어 있으면 인터넷을 통한 스트리밍이 작동하지 않을 수 있습니다.
|
||||
@@ -172,7 +171,7 @@
|
||||
\n
|
||||
\n인터넷을 통해 연결하려는 경우 PC에 Moonlight Internet Hosting Tool을 설치하고 Internet Streaming Tester를 실행하여 PC의 인터넷 연결을 확인하십시오.</string>
|
||||
<string name="nettest_title_done">네트워크 연결 테스트 완료</string>
|
||||
<string name="nettest_text_waiting">NVIDIA GameStream이 차단되었는지 확인하기 위해 네트워크 연결을 테스트하고 있습니다.
|
||||
<string name="nettest_text_waiting">Moonlight는 필요한 포트가 차단되었는지 확인하기 위해 네트워크 연결을 테스트하고 있습니다.
|
||||
\n
|
||||
\n잠시 기다려 주세요…</string>
|
||||
<string name="pcview_menu_header_unknown">상태 확인중</string>
|
||||
@@ -190,7 +189,7 @@
|
||||
<string name="title_enable_post_stream_toast">스트리밍 후 지연시간 정보 표시</string>
|
||||
<string name="title_enable_perf_overlay">스트리밍 중 성능 정보 표시</string>
|
||||
<string name="summary_enable_perf_overlay">스트리밍하는 동안 실시간 스트림 성능 정보 표시</string>
|
||||
<string name="summary_enable_hdr">게임 및 PC의 GPU가 HDR을 지원하는 경우 HDR을 활성화합니다. HDR에는 GTX 1000 시리즈 또는 그 이상의 GPU가 필요합니다.</string>
|
||||
<string name="summary_enable_hdr">게임 및 PC의 GPU가 HDR을 지원하는 경우 HDR을 활성화합니다. HDR에는 HEVC Main 10 인코딩을 지원하는 GPU가 필요합니다.</string>
|
||||
<string name="title_enable_hdr">HDR활성화 (실험용)</string>
|
||||
<string name="summary_disable_frame_drop">일부 장치에서 미세한 끊김 현상을 줄일 수 있지만 지연 시간이 늘어날 수 있습니다.</string>
|
||||
<string name="title_disable_frame_drop">프레임드랍 최적화</string>
|
||||
@@ -207,23 +206,22 @@
|
||||
<string name="title_reset_osc">가상 컨트롤러 배치 초기화</string>
|
||||
<string name="summary_only_l3r3">L3 및 R3을 제외한 모든 가상 버튼을 숨깁니다</string>
|
||||
<string name="title_only_l3r3">L3와 R3버튼만 표시하기</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">게임 패드 및 가상 컨트롤러의 A / B 와 X / Y 버튼을 바꿉니다</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">컨트롤러 및 가상 컨트롤러의 A / B 와 X / Y 버튼을 바꿉니다</string>
|
||||
<string name="summary_checkbox_vibrate_osc">가상 컨트롤러에서 장치를 진동하여 게임패드 진동을 구현합니다</string>
|
||||
<string name="title_checkbox_vibrate_osc">진동 활성화</string>
|
||||
<string name="title_checkbox_flip_face_buttons">버튼 바꾸기</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">이 옵션을 활성화하면 일부 장치에서 오른쪽 클릭에 문제가 있을 수 있습니다</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">마우스 사이드버튼 활성화</string>
|
||||
<string name="summary_checkbox_mouse_emulation">패드의 Start 버튼을 길게 누르면 게임 패드가 마우스 모드로 전환됩니다</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Xbox 컨트롤러를 기본으로 지원하는 경우에도 지원되는 모든 게임 패드에 Moonlight의 USB 드라이버를 사용합니다</string>
|
||||
<string name="title_checkbox_usb_bind_all">기본 Xbox 게임 패드 지원 무시</string>
|
||||
<string name="title_checkbox_mouse_emulation">게임패드를 마우스처럼 사용하기</string>
|
||||
<string name="summary_checkbox_mouse_emulation">패드의 Start 버튼을 길게 누르면 컨트롤러가 마우스 모드로 전환됩니다</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Xbox 컨트롤러를 기본으로 지원하는 경우에도 지원되는 모든 컨트롤러에 Moonlight의 USB 드라이버를 사용합니다</string>
|
||||
<string name="title_checkbox_usb_bind_all">기본 Xbox 컨트롤러 지원 무시</string>
|
||||
<string name="title_checkbox_mouse_emulation">컨트롤러를 마우스처럼 사용하기</string>
|
||||
<string name="perf_overlay_streamdetails">비디오 스트림 : %1$s %2$.2f FPS</string>
|
||||
<string name="unable_to_pin_shortcut">현재 런처에서는 바로가기 생성이 불가능합니다.</string>
|
||||
<string name="resolution_prefix_native_fullscreen">네이티브 (전체화면)</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">자동 (권장)</string>
|
||||
<string name="videoformat_auto">자동 (권장)</string>
|
||||
<string name="videoformat_hevcalways">HEVC 선호</string>
|
||||
<string name="videoformat_hevcnever">HEVC 사용하지 않기</string>
|
||||
<string name="summary_seekbar_deadzone">참고: 일부 게임은 이 설정값보다 더 큰 데드존이 적용되있을 수 있습니다.</string>
|
||||
<string name="resolution_1080p">1080p</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
@@ -264,4 +262,20 @@
|
||||
\nHDR 모드를 비활성화하거나 스트리밍 해상도를 변경하거나 호스트 PC의 디스플레이 해상도를 변경해 보십시오.</string>
|
||||
<string name="summary_full_range">밝기범위를 \"전체(0~255)\"로 설정합니다. 장치의 디스플레이가 \"제한(16~235)\" 범위로 출력하는 경우 밝기가 제대로 표현되지 않습니다.</string>
|
||||
<string name="title_full_range">전체 범위 비디오 활성화 (실험용)</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">컨트롤러 모션 센서 사용 허용</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">모션 센서가 있는 컨트롤러를 에뮬레이션할 때 지원되는 호스트가 모션 센서 데이터를 요청할 수 있습니다. 비활성화하면 게임에서 동작 센서를 사용하지 않는 경우 전원 및 네트워크 사용량이 약간 줄어들 수 있습니다.</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">터치패드로 컨트롤러를 에뮬레이션하는 경우에도 호스트 마우스를 제어하기 위해 컨트롤러 터치패드 입력을 강제합니다.</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream 지원 종료</string>
|
||||
<string name="pair_pairing_help">호스트 PC에서 Sunshine을 실행 중인 경우 Sunshine 웹 UI로 이동하여 PIN을 입력합니다.</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">호스트 처리 대기 시간 최소/최대/평균: %1$.1f/%2$.1f/%3$.1f ms</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_checkbox_gamepad_touchpad_as_mouse">항상 터치패드로 마우스 제어</string>
|
||||
<string name="videoformat_av1always">AV1 선호 (실험용)</string>
|
||||
<string name="videoformat_h264always">H.264 선호</string>
|
||||
<string name="toast_controller_type_changed">모션 센서 에뮬레이션으로 인해 컨트롤러 유형이 변경될 수 있습니다</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">연결된 컨트롤러 또는 기기의 Android 버전에서 컨트롤러 센서가 지원되지 않는 경우 장치에 내장된 모션 센서를 사용합니다.
|
||||
\n참고: 이 옵션을 활성화하면 사용 중인 컨트롤러가 호스트에서 PlayStation 컨트롤러로 나타날 수 있습니다.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">컨트롤러의 모션 센서 에뮬레이션 지원</string>
|
||||
</resources>
|
||||
@@ -223,7 +223,5 @@
|
||||
<string name="applist_menu_tv_channel">Toevoegen aan Kanaal</string>
|
||||
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Gebruik HEVC alleen als het stabiel is.</string>
|
||||
<string name="videoformat_hevcalways">Gebruik HEVC altijd (mogelijkheid tot crashes)</string>
|
||||
<string name="videoformat_hevcnever">Gebruik HEVC nooit</string>
|
||||
</resources>
|
||||
@@ -54,13 +54,12 @@
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="videoformat_hevcalways">Prefira HEVC</string>
|
||||
<string name="videoformat_hevcauto">Automático (recomendado)</string>
|
||||
<string name="videoformat_auto">Automático (recomendado)</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">5.1 Surround</string>
|
||||
<string name="audioconf_71surround">7.1 Surround</string>
|
||||
<string name="fps_90">90 FPS</string>
|
||||
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
||||
<string name="scut_deleted_pc">PC deletado</string>
|
||||
<string name="scut_not_paired">PC não pareado</string>
|
||||
<string name="help_loading_title">Ver Ajuda</string>
|
||||
|
||||
@@ -128,8 +128,7 @@
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">5.1 Surround</string>
|
||||
<string name="videoformat_hevcauto">Automático (recomendado)</string>
|
||||
<string name="videoformat_hevcnever">Nunca usar HEVC</string>
|
||||
<string name="videoformat_auto">Automático (recomendado)</string>
|
||||
<string name="title_frame_pacing">Ritmo de quadros</string>
|
||||
<string name="pacing_smoothness">Preferir vídeo mais suave (pode aumentar significativamente a latência)</string>
|
||||
<string name="summary_seekbar_deadzone">Nota: Alguns jogos podem impor uma zona morta maior do que o Moonlight está configurado para usar.</string>
|
||||
|
||||
@@ -196,7 +196,5 @@
|
||||
<string name="audioconf_51surround">Sunet Surround 5.1</string>
|
||||
<string name="audioconf_71surround">Sunet Surround 7.1</string>
|
||||
|
||||
<string name="videoformat_hevcauto">Folosește HEVC doar dacă e stabil</string>
|
||||
<string name="videoformat_hevcalways">Folosește HEVC mereu (se poate bloca)</string>
|
||||
<string name="videoformat_hevcnever">Nu folosi HEVC</string>
|
||||
</resources>
|
||||
|
||||
@@ -217,9 +217,8 @@
|
||||
<string name="audioconf_stereo">Стерео</string>
|
||||
<string name="audioconf_51surround">5.1 Объёмный звук</string>
|
||||
<string name="audioconf_71surround">7.1 Объёмный звук</string>
|
||||
<string name="videoformat_hevcauto">Автоматически</string>
|
||||
<string name="videoformat_auto">Автоматически</string>
|
||||
<string name="videoformat_hevcalways">Всегда использовать HEVC если доступно</string>
|
||||
<string name="videoformat_hevcnever">Никогда не использовать HEVC</string>
|
||||
<string name="pacing_latency">Минимальная задержка</string>
|
||||
<string name="pacing_balanced">Баланс</string>
|
||||
<string name="pacing_smoothness">Максимальная плавность (может значительно увеличить задержку)</string>
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="scut_deleted_pc">PC raderad</string>
|
||||
<string name="scut_not_paired">PC inte kopplad</string>
|
||||
<string name="scut_pc_not_found">PC inte hittad</string>
|
||||
<string name="scut_invalid_uuid">Den angivna PC:n är inte giltig</string>
|
||||
<string name="scut_invalid_app_id">Angiven App är inte giltlig</string>
|
||||
<string name="help_loading_title">Hjälpvisare</string>
|
||||
<string name="help_loading_msg">Laddar hjälpsida…</string>
|
||||
<string name="pcview_menu_header_online">Online</string>
|
||||
<string name="pcview_menu_header_offline">Offline</string>
|
||||
<string name="pcview_menu_header_unknown">Uppdaterar</string>
|
||||
<string name="pcview_menu_app_list">Visa alla appar</string>
|
||||
<string name="pcview_menu_pair_pc">Para ihop med PC</string>
|
||||
<string name="pcview_menu_unpair_pc">Koppla bort</string>
|
||||
<string name="pcview_menu_send_wol">Skicka begäran om Wake-On-LAN</string>
|
||||
<string name="pcview_menu_delete_pc">Radera PC</string>
|
||||
<string name="pcview_menu_test_network">Testa nätverksanslutning</string>
|
||||
<string name="pcview_menu_details">Visa detaljer</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream upphör att fungera</string>
|
||||
<string name="nettest_title_waiting">Testning av nätverksanslutning</string>
|
||||
<string name="nettest_text_waiting">Moonlight testar din nätverksanslutning för att avgöra om några nödvändiga portar är blockerade.
|
||||
\n
|
||||
\nDetta kan ta några sekunder…</string>
|
||||
<string name="pair_pc_ingame">Datorn är för närvarande i ett spel. Du måste stänga spelet innan fogning.</string>
|
||||
<string name="pairing">Fogar…</string>
|
||||
<string name="pair_pairing_title">Fogning</string>
|
||||
<string name="pair_pairing_msg">Ange följande PIN-kod på måldatorn:</string>
|
||||
<string name="pair_pairing_help">Om värddatorn kör Sunshine går du till Sunshine-webbgränssnittet för att ange PIN-koden.</string>
|
||||
<string name="pair_incorrect_pin">Felaktig PIN-kod</string>
|
||||
<string name="pair_fail">Fogning misslyckad</string>
|
||||
<string name="pair_already_in_progress">Fogning redan i utveckling</string>
|
||||
<string name="wol_pc_online">Datorn är online</string>
|
||||
<string name="wol_no_mac">Det går inte att väcka datorn eftersom det inte finns någon lagrad MAC-adress</string>
|
||||
<string name="wol_waking_pc">Väcker dator…</string>
|
||||
<string name="wol_waking_msg">Det kan ta några sekunder innan datorn vaknar upp. Om den inte gör det, kontrollera att den är korrekt konfigurerad för Wake-On-LAN.</string>
|
||||
<string name="wol_fail">Misslyckades med att skicka Wake-On-LAN-paket</string>
|
||||
<string name="unpairing">Bortkopplar…</string>
|
||||
<string name="unpair_success">Bortkoppling framgångsrik</string>
|
||||
<string name="unpair_fail">Misslyckad bortkoppling</string>
|
||||
<string name="unpair_error">Enheten blev inte fogad</string>
|
||||
<string name="error_pc_offline">Dator är offline</string>
|
||||
<string name="error_unknown_host">Misslyckades med att lösa värd</string>
|
||||
<string name="title_decoding_error">Videoavkodare brakade</string>
|
||||
<string name="message_decoding_error">Moonlight har brakat på grund av en inkompatibilitet med den här enhetens videodekoder. Försök att jämka streaminginställningarna om braket fortsätter.</string>
|
||||
<string name="title_decoding_reset">Återställning av videoinställningar</string>
|
||||
<string name="error_usb_prohibited">USB-åtkomst är förbjuden av enhetens administratör. Kontrollera dina Knox- eller MDM-inställningar.</string>
|
||||
<string name="unable_to_pin_shortcut">Din nuvarande lanseringsprogramvara tillåter inte att du skapar genvägar som är fastlåsta.</string>
|
||||
<string name="no_video_received_error">Ingen video har tagits emot från värden.</string>
|
||||
<string name="no_frame_received_error">Din nätverksanslutning fungerar inte bra. Minska inställningen för videobitrate eller prova en snabbare anslutning.</string>
|
||||
<string name="check_ports_msg">Kontrollera din brandvägg och dina regler för portvidarebefordran för port(er):</string>
|
||||
<string name="conn_establishing_title">Upprättar fogning</string>
|
||||
<string name="conn_establishing_msg">Startar fogning</string>
|
||||
<string name="conn_metered">Varning: Din aktiva nätverksfogning är mätbar!</string>
|
||||
<string name="conn_client_latency">Genomsnittlig latenstid för ramavkodning:</string>
|
||||
<string name="conn_client_latency_hw">Latency för hårdvaruavkodare:</string>
|
||||
<string name="conn_hardware_latency">Genomsnittlig latenstid för maskinvaruavkodning:</string>
|
||||
<string name="conn_starting">Börjar</string>
|
||||
<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="yes">Ja</string>
|
||||
<string name="no">Nej</string>
|
||||
<string name="lost_connection">Tappade fogning till dator</string>
|
||||
<string name="title_details">Detaljer</string>
|
||||
<string name="help">Hjälp</string>
|
||||
<string name="delete_pc_msg">Är du säker på att du vill ta bort den här datorn\?</string>
|
||||
<string name="slow_connection_msg">Långsam anslutning till datorn
|
||||
\nMinska din bithastighet</string>
|
||||
<string name="poor_connection_msg">Dålig anslutning till datorn</string>
|
||||
<string name="perf_overlay_streamdetails">Videoström: %1$s %2$.2f FPS</string>
|
||||
<string name="perf_overlay_decoder">Avkodare: %1$s</string>
|
||||
<string name="perf_overlay_incomingfps">Inkommande bildfrekvens från nätverket: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_renderingfps">Renderingens bildfrekvens: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_netdrops">Ramar som tappats av din nätverksanslutning: %1$.2f%%</string>
|
||||
<string name="perf_overlay_dectime">Genomsnittlig avkodningstid: %1$.2f ms</string>
|
||||
<string name="applist_connect_msg">Fogar till dator…</string>
|
||||
<string name="applist_menu_resume">Återuppta session</string>
|
||||
<string name="applist_menu_quit">Avsluta session</string>
|
||||
<string name="applist_menu_quit_and_start">Avsluta aktuellt spel och starta</string>
|
||||
<string name="applist_menu_cancel">Avbryt</string>
|
||||
<string name="applist_menu_details">Visa detaljer</string>
|
||||
<string name="applist_menu_scut">Skapa genväg</string>
|
||||
<string name="applist_menu_tv_channel">Lägg till i kanal</string>
|
||||
<string name="applist_menu_hide_app">Dölj appen</string>
|
||||
<string name="applist_refresh_title">Applista</string>
|
||||
<string name="applist_refresh_msg">Friskar upp appar…</string>
|
||||
<string name="applist_refresh_error_title">Fel</string>
|
||||
<string name="applist_refresh_error_msg">Misslyckades att få app lista</string>
|
||||
<string name="applist_quit_app">Avslutar</string>
|
||||
<string name="applist_quit_success">Framgångsrikt avslutad</string>
|
||||
<string name="applist_quit_confirmation">Är du säker på att du vill avsluta den pågående appen\? Alla osparade datamatrial kommer att gå förlorade.</string>
|
||||
<string name="title_add_pc">Lägg till en dator manuellt</string>
|
||||
<string name="msg_add_pc">Fogar till datorn…</string>
|
||||
<string name="addpc_fail">Det går inte att foga till den angivna datorn. Kontrollera att de nödvändiga portarna tillåts genom brandväggen.</string>
|
||||
<string name="addpc_success">Lyckades lägga till dator</string>
|
||||
<string name="addpc_unknown_host">Det går inte att lösa PC-adressen. Kontrollera att du inte har skrivit fel i adressen.</string>
|
||||
<string name="applist_details_id">Applikations identitet:</string>
|
||||
<string name="addpc_enter_ip">Du måste ange en IP-adress</string>
|
||||
<string name="addpc_wrong_sitelocal">Den adressen ser inte rätt ut. Du måste använda routerns offentliga IP-adress för att streama via Internet.</string>
|
||||
<string name="category_basic_settings">Grundinställningar</string>
|
||||
<string name="title_resolution_list">Videoupplösning</string>
|
||||
<string name="summary_resolution_list">Öka för att förbättra bildens tydlighet. Sänk för bättre prestanda på mindre avancerade enheter och långsammare nätverk.</string>
|
||||
<string name="title_fps_list">Videobildfrekvens</string>
|
||||
<string name="summary_fps_list">Öka för en jämnare videoström. Sänk för bättre prestanda på enheter med lägre prestanda.</string>
|
||||
<string name="title_seekbar_bitrate">Videobitrate</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbit/s</string>
|
||||
<string name="resolution_prefix_native">Ursprung</string>
|
||||
<string name="resolution_prefix_native_fullscreen">Ursprungshelskärm</string>
|
||||
<string name="resolution_prefix_native_landscape">(Landskap)</string>
|
||||
<string name="resolution_prefix_native_portrait">(Porträtt)</string>
|
||||
<string name="category_audio_settings">Ljudinställningar</string>
|
||||
<string name="title_audio_config_list">Konfiguration av surroundljud</string>
|
||||
<string name="title_checkbox_enable_audiofx">Aktivera stöd för systemets equalizer</string>
|
||||
<string name="category_input_settings">Inmatningsinställningar</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Använd pekskärmen som en styrplatta</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">Om den är aktiverad fungerar pekskärmen som en styrplatta. Om den är inaktiverad styr pekskärmen direkt muspekaren.</string>
|
||||
<string name="title_checkbox_multi_controller">Automatiskt upptäckande av närvarande spelkontroll</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Efterlikna stöd för rumble med vibrationer</string>
|
||||
<string name="summary_checkbox_vibrate_fallback">Vibrerar enheten för att efterlikna rumble om din spelplatta inte har stöd för det</string>
|
||||
<string name="summary_seekbar_deadzone">Observera: Vissa spel kan kräva en större dödzon än vad Moonlight är konfigurerat för att använda.</string>
|
||||
<string name="title_seekbar_deadzone">Jämka analogstickans dödzon</string>
|
||||
<string name="suffix_seekbar_deadzone">%</string>
|
||||
<string name="title_checkbox_xb1_driver">Drivrutin för Xbox 360/One USB-spelplatta</string>
|
||||
<string name="summary_checkbox_xb1_driver">Aktiverar en inbyggd USB-drivrutin för enheter som inte har stöd för Xbox-kontroller</string>
|
||||
<string name="title_checkbox_usb_bind_all">Behärska det ursprungliga stödet för Xbox-spelplatta</string>
|
||||
<string name="title_checkbox_mouse_emulation">Erterliknande av mus genom spelplatta</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Om du trycker länge på startknappen skiftar du spelplatta till musläge</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Sätt på musknapparna bakåt och framåt</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Skiftar ansiktsknapparna A/B och X/Y för spelplattor och kontroller på skärmen</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Skifta ansiktsknappar</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Musläget för fjärrskrivbord</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">Detta kan göra musacceleration mer naturligt för fjärrskrivbordsanvändning, men det är oförenligt med många spel.</string>
|
||||
<string name="category_on_screen_controls_settings">Inställningar för kontroller på skärmen</string>
|
||||
<string name="title_checkbox_vibrate_osc">Sätt på darrning</string>
|
||||
<string name="summary_checkbox_vibrate_osc">Darrar din enhet för att ge svar på skärmkontrollerna</string>
|
||||
<string name="title_only_l3r3">Visa bara L3 och R3</string>
|
||||
<string name="summary_only_l3r3">Dölj alla synliga knappar utom L3 och R3</string>
|
||||
<string name="title_reset_osc">Rensa sparad formgivning för kontroller på skärmen</string>
|
||||
<string name="dialog_title_reset_osc">Återställ formgivning</string>
|
||||
<string name="dialog_text_reset_osc">Är du säker på att du vill ta bort din sparade layout för skärmenheterna\?</string>
|
||||
<string name="toast_reset_osc_success">Kontroller på skärmen återställs till ursprungsinställningen</string>
|
||||
<string name="title_osc_opacity">Jämka genomskinligheten av skärmkontrollerna</string>
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="title_checkbox_enable_pip">Sätt på bild-i-bild-observatörsläge</string>
|
||||
<string name="title_language_list">Språk</string>
|
||||
<string name="summary_language_list">Språk att använda för Moonlight</string>
|
||||
<string name="title_checkbox_small_icon_mode">Använd liten omslagskonst</string>
|
||||
<string name="summary_checkbox_small_icon_mode">Mindre lådor i appgallret gör att fler appar syns på skärmen</string>
|
||||
<string name="category_host_settings">Värdinställningar</string>
|
||||
<string name="title_checkbox_enable_sops">Optimera spelinställningarna</string>
|
||||
<string name="summary_checkbox_enable_sops">Tillåt GFE att ändra spelinställningar för optimal strömning</string>
|
||||
<string name="title_checkbox_host_audio">Spela upp ljud på datorn</string>
|
||||
<string name="summary_checkbox_host_audio">Spela upp ljud från datorn och den här enheten</string>
|
||||
<string name="category_advanced_settings">Utvecklade inställningar</string>
|
||||
<string name="title_unlock_fps">Lås upp alla möjliga bildfrekvenser</string>
|
||||
<string name="title_checkbox_reduce_refresh_rate">Tillåt minskning av uppdateringsfrekvensen</string>
|
||||
<string name="title_checkbox_disable_warnings">Ta bort varningsmedelanden</string>
|
||||
<string name="summary_checkbox_disable_warnings">Ta bort varningsmeddelanden om inmatning på skärmen när du strömmar</string>
|
||||
<string name="title_disable_frame_drop">Tappa aldrig bildramar</string>
|
||||
<string name="summary_disable_frame_drop">Kan minska mikrohack på vissa enheter, men kan öka latensen</string>
|
||||
<string name="title_video_format">Ändra codec-inställningar</string>
|
||||
<string name="summary_video_format">Nyare codecs kan sänka videobandbreddskraven om din enhet stöder dem. Codec-val kan ignoreras om det inte stöds av värdprogramvaran eller GPU:n.</string>
|
||||
<string name="title_enable_hdr">Sätt på HDR (Prövning)</string>
|
||||
<string name="summary_enable_hdr">Strömma HDR när spelet och datorns GPU stöder det. HDR kräver en GPU med stöd för HEVC Main 10-kodning.</string>
|
||||
<string name="title_full_range">Tvinga video med fullt omfång (Prövning)</string>
|
||||
<string name="title_enable_perf_overlay">Visa prestandastatistik under ströming</string>
|
||||
<string name="summary_enable_perf_overlay">Visa information om strömningens duglighet i nutid medans du strömmar</string>
|
||||
<string name="summary_enable_post_stream_toast">Visa ett meddelande med information om latens när strömmen avslutas</string>
|
||||
<string name="category_help">Hjälp</string>
|
||||
<string name="title_setup_guide">Installationsguide</string>
|
||||
<string name="title_troubleshooting">Vägledning för felsökning</string>
|
||||
<string name="summary_troubleshooting">Visa gissningar för att utvärdera och åtgärda vanliga strömningsbeskymmer</string>
|
||||
<string name="title_privacy_policy">Integritetspolicy</string>
|
||||
<string name="summary_privacy_policy">Visa Moonlights integritetspolicy</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
<string name="resolution_480p">480p</string>
|
||||
<string name="resolution_720p">720p</string>
|
||||
<string name="resolution_1440p">1440p</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="fps_90">90 FPS</string>
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">5.1 surroundljud</string>
|
||||
<string name="audioconf_71surround">7.1 surroundljud</string>
|
||||
<string name="title_frame_pacing">Videorams fart</string>
|
||||
<string name="pacing_latency">Föredrar lägsta latenstid</string>
|
||||
<string name="pacing_balanced">Balanserad</string>
|
||||
<string name="pacing_balanced_alt">Balanserad med FPS-gräns</string>
|
||||
<string name="pacing_smoothness">Föredrar smidigast video (kan öka latensen avsevärt)</string>
|
||||
<string name="nettest_title_done">Nätverkstestet fullföljt</string>
|
||||
<string name="nettest_text_failure">Din enhets aktuella nätverksanslutning verkar blockera Moonlight. Streaming via Internet kanske inte fungerar när du är ansluten till det här nätverket.
|
||||
\n
|
||||
\nFöljande nätverksportar blockerades:
|
||||
\n</string>
|
||||
<string name="nettest_text_success">Ditt nätverk verkar inte blockera Moonlight. Om du fortfarande har problem med anslutningen kan du kontrollera datorns brandväggsinställningar.
|
||||
\n
|
||||
\nOm du försöker streama via Internet installerar du Moonlight Internet Hosting Tool på din dator och kör den medföljande Internet Streaming Tester för att kontrollera datorns Internetanslutning.</string>
|
||||
<string name="nettest_text_inconclusive">Nätverkstestet kunde inte utföras eftersom ingen av Moonlights servrar för anslutningstestning kunde nås. Kontrollera din internetanslutning eller försök igen senare.</string>
|
||||
<string name="nettest_text_blocked">Enhetens aktuella nätverksanslutning blockerar Moonlight. Streaming via Internet kanske inte fungerar när du är ansluten till det här nätverket.</string>
|
||||
<string name="pair_pc_offline">Dator är offline</string>
|
||||
<string name="error_manager_not_running">Tjänsten ComputerManager körs inte. Vänta några sekunder eller starta om programmet.</string>
|
||||
<string name="error_404">GFE returnerade ett HTTP 404-fel. Kontrollera att din dator har en GPU som stöds. Användning av fjärrskrivbordsprogram kan också orsaka det här felet. Försök att starta om maskinen eller installera om GFE.</string>
|
||||
<string name="message_decoding_reset">Enhetens videoavkodare fortsätter att braka vid de valda streaminginställningarna. Dina streaminginställningar har återställts till standardinställningen.</string>
|
||||
<string name="video_decoder_init_failed">Videodekodern misslyckades med att initialisera. Din enhet kanske inte stöder den valda upplösningen eller bildfrekvensen.</string>
|
||||
<string name="early_termination_error">Något gick fel på din värddator när du startade strömmen.
|
||||
\n
|
||||
\nKontrollera att du inte har något DRM-skyddat innehåll öppet på din värddator. Du kan också försöka starta om din värddator.</string>
|
||||
<string name="frame_conversion_error">Värddatorn rapporterade ett allvarligt fel i videokodningen.
|
||||
\n
|
||||
\nFörsök att inaktivera HDR-läget, ändra streamingupplösningen eller ändra värddatorns skärmupplösning.</string>
|
||||
<string name="ip_hint">IP-adress för värddatorn</string>
|
||||
<string name="searching_pc">Söker efter värddatorer i det lokala nätverket...
|
||||
\n
|
||||
\n Kontrollera att Sunshine körs på värddatorn eller att GameStream är aktiverat i inställningarna för GeForce Experience SHIELD.</string>
|
||||
<string name="perf_overlay_netlatency">Genomsnittlig nätverksfördröjning: %1$d ms (varians: %2$d ms)</string>
|
||||
<string name="applist_quit_fail">Misslyckades att avsluta</string>
|
||||
<string name="title_native_res_dialog">Varning för ursprunglig upplösning</string>
|
||||
<string name="text_native_res_dialog">Inbyggd upplösning och/eller FPS kanske inte stöds av streamingservern. Du kommer förmodligen att behöva konfigurera ett matchande anpassat visningsläge för värddatorn manuellt.
|
||||
\n
|
||||
\nOm du väljer att skapa en anpassad upplösning i NVIDIAs kontrollpanel för att matcha dina skärminställningar, se till att du har läst och förstått NVIDIAs varning om möjlig bildskärmsskada, PC-instabilitet och andra potentiella problem.
|
||||
\n
|
||||
\nVi är inte ansvariga för eventuella problem som uppstår av att skapa en anpassad upplösning på din PC.
|
||||
\n
|
||||
\nDet kan vara så att din bildskärm inte stöder en nödvändig bildskärmskonfiguration. Om så är fallet kan du försöka ställa in en virtuell skärm. Slutligen, om din enhet eller värddator inte stöder streaming med en specifik upplösning eller uppdateringsfrekvens, har du tyvärr ingen tur.</string>
|
||||
<string name="summary_seekbar_bitrate">Öka för bättre bildkvalitet. Minska för att förbättra prestandan på långsammare anslutningar.</string>
|
||||
<string name="title_checkbox_stretch_video">Sträck ut videon till helskärm</string>
|
||||
<string name="summary_audio_config_list">Aktivera 5.1 eller 7.1 surroundljud för hemmabiosystem</string>
|
||||
<string name="summary_checkbox_enable_audiofx">Ljudeffekter kan fungera under streaming, men kan öka ljudfördröjningen</string>
|
||||
<string name="summary_checkbox_multi_controller">Om du avmarkerar det här alternativet tvingas en spelplatta att alltid finnas med</string>
|
||||
<string name="summary_checkbox_usb_bind_all">Använd Moonlights USB-drivrutin för alla gamepads som stöds, även om det finns stöd för Xbox-kontroller i original</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Om du lägger till det här alternativet kan högerklickandet gå sönder på vissa felaktiga enheter</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Visa kontrollerna på skärmen</string>
|
||||
<string name="summary_checkbox_show_onscreen_controls">Visa en virtuell styrenhet på pekskärmen</string>
|
||||
<string name="summary_reset_osc">Återställ alla kontroller på skärmen till deras standard storlek och position</string>
|
||||
<string name="dialog_title_osc_opacity">Jämka genomskinligheten</string>
|
||||
<string name="summary_osc_opacity">Gör kontrollerna på skärmen mer/mindre genomskinliga</string>
|
||||
<string name="summary_checkbox_enable_pip">Gör det möjligt att se strömmen (men inte att styra den) medan du gör andra saker samtidigt</string>
|
||||
<string name="category_ui_settings">Inställningar för användargränssnittet</string>
|
||||
<string name="summary_unlock_fps">Streaming med 90 eller 120 FPS kan minska latenstiden på avancerade enheter, men kan orsaka fördröjning eller instabilitet på enheter som inte har stöd för det</string>
|
||||
<string name="summary_checkbox_reduce_refresh_rate">Lägre uppdateringsfrekvenser på skärmen kan spara ström på bekostnad av ytterligare videolatens</string>
|
||||
<string name="summary_full_range">Detta kan leda till förlust av detalj i ljusa och mörka områden om enheten inte visar videoinnehåll med fullt omfång på rätt sätt.</string>
|
||||
<string name="fps_120">120 FPS</string>
|
||||
<string name="title_enable_post_stream_toast">Visa meddelande om latenstid efter strömning</string>
|
||||
<string name="summary_setup_guide">Visa instruktioner om hur du utformar din speldator för strömning</string>
|
||||
<string name="resolution_1080p">1080p</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
<string name="summary_frame_pacing">Ange hur du ska balansera videofördröjning och jämnhet</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="title_native_fps_dialog">Native FPS varning</string>
|
||||
<string name="category_gamepad_settings">Spelkontroller inställningar</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Tillåt användning av spelkontrollens rörelsesensorer</string>
|
||||
<string name="videoformat_auto">Automatisk (Rekommenderad)</string>
|
||||
<string name="videoformat_av1always">Föredra AV1 (experimentell)</string>
|
||||
<string name="videoformat_hevcalways">Föredra HEVC</string>
|
||||
<string name="videoformat_h264always">Föredra H.264</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Värdbearbetningsfördröjning min/max/genomsnitt: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<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>
|
||||
</resources>
|
||||
@@ -218,9 +218,8 @@
|
||||
<string name="pcview_menu_header_offline">Поза мережею</string>
|
||||
<string name="pcview_menu_header_online">В мережі</string>
|
||||
<!-- Array strings -->
|
||||
<string name="videoformat_hevcauto">Автоматичний (рекомендовано)</string>
|
||||
<string name="videoformat_auto">Автоматичний (рекомендовано)</string>
|
||||
<string name="videoformat_hevcalways">Використовувати HEVC</string>
|
||||
<string name="videoformat_hevcnever">Ніколи не використовувати HEVC</string>
|
||||
<string name="title_frame_pacing">Швидкість кадрів відео</string>
|
||||
<string name="summary_frame_pacing">Укажіть баланс відео затримки та плавності</string>
|
||||
<string name="pacing_latency">Перевага найменшій затримці</string>
|
||||
|
||||
@@ -225,9 +225,7 @@
|
||||
<string name="audioconf_stereo">Stereo</string>
|
||||
<string name="audioconf_51surround">Âm thanh vòm 5.1</string>
|
||||
<string name="audioconf_71surround">Âm thanh vòm 7.1</string>
|
||||
<string name="videoformat_hevcauto">Chỉ sử dụng HEVC nếu ổn định</string>
|
||||
<string name="videoformat_hevcalways">Luôn sử dụng HEVC (có thể gây crash)</string>
|
||||
<string name="videoformat_hevcnever">Không bao giờ sử dụng HEVC</string>
|
||||
<string name="resolution_prefix_native_landscape">(Ngang)</string>
|
||||
<string name="frame_conversion_error">PC chủ đã gặp lỗi mã hoá video nghiêm trọng.
|
||||
\n
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
<string name="category_advanced_settings"> 高级设置 </string>
|
||||
<string name="title_disable_frame_drop"> 永不掉帧 </string>
|
||||
<string name="summary_disable_frame_drop"> 可能会减少在一些设备上的卡顿,但会增加延迟 </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="title_enable_hdr">启用 HDR (实验性)</string>
|
||||
<string name="summary_enable_hdr">当游戏和显卡支持时以HDR模式串流。 HDR需要显卡支持 HEVC Main 10 编码。</string>
|
||||
<string name="title_enable_perf_overlay"> 启用性能信息 </string>
|
||||
@@ -196,13 +196,13 @@
|
||||
<string name="pcview_menu_header_online">在线</string>
|
||||
<string name="resolution_prefix_native">本地</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||
<string name="text_native_res_dialog">本地分辨率模式不受GFE的官方支持,因此不会自动设置主机的显示分辨率。您需要在游戏中手动进行设置。
|
||||
<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="check_ports_msg">请检查您的防火墙和端口转发规则中的端口:</string>
|
||||
@@ -220,9 +220,8 @@
|
||||
<string name="audioconf_stereo">立体声</string>
|
||||
<string name="audioconf_51surround">5.1环绕声</string>
|
||||
<string name="audioconf_71surround">7.1环绕声</string>
|
||||
<string name="videoformat_hevcauto">自动(推荐)</string>
|
||||
<string name="videoformat_auto">自动(推荐)</string>
|
||||
<string name="videoformat_hevcalways">首选 HEVC</string>
|
||||
<string name="videoformat_hevcnever">不使用HEVC</string>
|
||||
<string name="title_frame_pacing">视频帧速调节</string>
|
||||
<string name="resolution_360p">360p</string>
|
||||
<string name="resolution_480p">480p</string>
|
||||
@@ -262,4 +261,18 @@
|
||||
<string name="title_full_range">强制完全动态范围视频 (实验性)</string>
|
||||
<string name="pair_pairing_help">如果你的主机运行的是 Sunshine,那请前往Sunshine的网页界面输入PIN码。</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream 终止服务</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">主机处理延迟最小值/最大值/平均值: %1$.1f/%2$.1f/%3$.1f ms</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_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="videoformat_av1always">首选 AV1(实验性)</string>
|
||||
<string name="videoformat_h264always">首选 H.264</string>
|
||||
<string name="toast_controller_type_changed">游戏手柄类型可能会因运动传感器模拟而改变</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">如果你连接的游戏手柄或 Android 版本不支持游戏手柄传感器,请使用设备的内置运动传感器。
|
||||
\n注意:启用此选项可能会导致您的游戏手柄在主机上被识别为 PlayStation 4控制器。</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">模拟游戏手柄运动传感器支持</string>
|
||||
</resources>
|
||||
@@ -166,8 +166,8 @@
|
||||
<string name="category_advanced_settings">進階設定</string>
|
||||
<string name="title_disable_frame_drop">永不丟失影格</string>
|
||||
<string name="summary_disable_frame_drop">可能會減少在一些裝置上的卡頓,但會增加延時</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">較新的轉碼器可以降低視訊頻寬需求 (若您的裝置支援)。如果主機軟體或 GPU 不支援,轉碼器選取項目可能會被忽略。</string>
|
||||
<string name="title_enable_hdr">啟用 HDR (實驗性)</string>
|
||||
<string name="summary_enable_hdr">在遊戲和 GPU 支援時以 HDR 模式串流,HDR 模式需要支援 HEVC Main 10 編碼的 GPU。</string>
|
||||
<string name="title_enable_perf_overlay">串流時顯示效能資訊</string>
|
||||
@@ -179,15 +179,15 @@
|
||||
<string name="suffix_osc_opacity">%</string>
|
||||
<string name="summary_osc_opacity">使螢幕控制按钮變得更透明/更不透明</string>
|
||||
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
|
||||
<string name="resolution_prefix_native">本機</string>
|
||||
<string name="text_native_res_dialog">本機解析度模式不受 GFE 的官方支援,因此不會自動設定主機的顯示解析度。您需要在遊戲中手動進行設定。
|
||||
<string name="resolution_prefix_native">原生</string>
|
||||
<string name="text_native_res_dialog">原生解析度或 FPS 可能不受串流伺服器支援,您可能需要為主機手動設定相符的自訂顯示模式。
|
||||
\n
|
||||
\n如果您選擇在 NVIDIA 控制面板中建立自訂解析度以符合裝置解析度,請確保您已閱讀並理解 NVIDIA 關於可能導致監視器損毀和電腦不穩定以及其他潛在問題的警告。
|
||||
\n如果您選擇在 NVIDIA 控制面板中建立自訂解析度以符合您的螢幕設定,請確保您已閱讀並理解 NVIDIA 關於可能導致監視器損毀和電腦不穩定以及其他潛在問題的警告。
|
||||
\n
|
||||
\n對於您在您的電腦上建立自訂解析度而導致的任何問題,我們概不負責。
|
||||
\n
|
||||
\n最後,您的裝置或主機電腦可能不支援以本機解析度串流。如果此模式在您的裝置上無法正常執行,只能說您運氣欠佳了。</string>
|
||||
<string name="title_native_res_dialog">本機解析度警告</string>
|
||||
\n您的顯示器可能不支援必要的顯示組態。如果是這樣,您可以嘗試設定虛擬監視器。最后,如果您的裝置或主機不支援以特定解析度或重新整理速率串流,只能說您運氣欠佳了。</string>
|
||||
<string name="title_native_res_dialog">原生解析度警告</string>
|
||||
<string name="applist_menu_hide_app">隱藏遊戲</string>
|
||||
<string name="check_ports_msg">檢查您的防火牆和通訊埠轉送規則中的通訊埠:</string>
|
||||
<string name="early_termination_error">您的主機電腦在開始串流時出了點問題。
|
||||
@@ -216,14 +216,13 @@
|
||||
<string name="pcview_menu_header_online">線上</string>
|
||||
<string name="perf_overlay_netlatency">平均網路延時:%1$d ms (抖動:%2$d ms)</string>
|
||||
<string name="perf_overlay_streamdetails">視訊串流:%1$s %2$.2f FPS</string>
|
||||
<string name="resolution_prefix_native_fullscreen">本機全螢幕</string>
|
||||
<string name="resolution_prefix_native_fullscreen">原生全螢幕</string>
|
||||
<!-- Array strings -->
|
||||
<string name="audioconf_stereo">立體聲</string>
|
||||
<string name="audioconf_51surround">5.1 環場音效</string>
|
||||
<string name="audioconf_71surround">7.1 環場音效</string>
|
||||
<string name="videoformat_hevcauto">自動 (建議)</string>
|
||||
<string name="videoformat_auto">自動 (建議)</string>
|
||||
<string name="videoformat_hevcalways">優先使用 HEVC</string>
|
||||
<string name="videoformat_hevcnever">不使用 HEVC</string>
|
||||
<string name="resolution_4k">4K</string>
|
||||
<string name="fps_30">30 FPS</string>
|
||||
<string name="fps_60">60 FPS</string>
|
||||
@@ -263,4 +262,18 @@
|
||||
<string name="summary_full_range">若您的裝置無法正確地顯示全範圍視訊內容,將會導致淺色區域和深色區域的細節遺失。</string>
|
||||
<string name="pair_pairing_help">若您的主機電腦正在執行 Sunshine,請導覽至 Sunshine 網頁 UI 並輸入 PIN 碼。</string>
|
||||
<string name="pcview_menu_eol">NVIDIA GameStream 終止服務</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_checkbox_gamepad_touchpad_as_mouse">一律使用觸摸板控制滑鼠</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">在使用動態感測器模擬手把時啟用支援的主機以要求動態感測器資料,若動態感測器未在遊戲中使用,停用後可能會輕微降低電力和網路使用量。</string>
|
||||
<string name="videoformat_h264always">偏好 H.264</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">主機處理延遲最小值/最大值/平均值:%1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">強制手把觸摸板輸入以控制主機滑鼠,即使在使用觸摸板模擬手把時。</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">一律使用手把動態感測器</string>
|
||||
<string name="videoformat_av1always">偏好 AV1 (實驗性)</string>
|
||||
<string name="toast_controller_type_changed">手把類型可能會因動態感測器模擬而變更</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">如果您連線的手把或 Android 版本不支援手把感測器,請使用裝置內建的動態感測器。
|
||||
\n注意:啟用此選項可能會導致您的手把在主機被辨識為 PlayStation 控制器。</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">模擬手把動態感測器支援</string>
|
||||
</resources>
|
||||
@@ -65,6 +65,9 @@
|
||||
<item>Ελληνικά</item>
|
||||
<item>Português do Brasil</item>
|
||||
<item>Čeština</item>
|
||||
<item>עִבְרִית</item>
|
||||
<item>Svenska</item>
|
||||
<item>Indonesia</item>
|
||||
</string-array>
|
||||
<string-array name="language_values" translatable="false">
|
||||
<item>default</item>
|
||||
@@ -87,15 +90,20 @@
|
||||
<item>el</item>
|
||||
<item>pt-BR</item>
|
||||
<item>cs</item>
|
||||
<item>iw</item>
|
||||
<item>sv</item>
|
||||
<item>in</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_format_names">
|
||||
<item>@string/videoformat_hevcauto</item>
|
||||
<item>@string/videoformat_auto</item>
|
||||
<item>@string/videoformat_av1always</item>
|
||||
<item>@string/videoformat_hevcalways</item>
|
||||
<item>@string/videoformat_hevcnever</item>
|
||||
<item>@string/videoformat_h264always</item>
|
||||
</string-array>
|
||||
<string-array name="video_format_values" translatable="false">
|
||||
<item>auto</item>
|
||||
<item>forceav1</item>
|
||||
<item>forceh265</item>
|
||||
<item>neverh265</item>
|
||||
</string-array>
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
<string name="perf_overlay_decoder">Decoder: %1$s</string>
|
||||
<string name="perf_overlay_incomingfps">Incoming frame rate from network: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_renderingfps">Rendering frame rate: %1$.2f FPS</string>
|
||||
<string name="perf_overlay_hostprocessinglatency">Host processing latency min/max/average: %1$.1f/%2$.1f/%3$.1f ms</string>
|
||||
<string name="perf_overlay_netdrops">Frames dropped by your network connection: %1$.2f%%</string>
|
||||
<string name="perf_overlay_netlatency">Average network latency: %1$d ms (variance: %2$d ms)</string>
|
||||
<string name="perf_overlay_dectime">Average decoding time: %1$.2f ms</string>
|
||||
@@ -146,7 +147,7 @@
|
||||
<string name="title_resolution_list">Video resolution</string>
|
||||
<string name="summary_resolution_list">Increase to improve image clarity. Decrease for better performance on lower end devices and slower networks.</string>
|
||||
<string name="title_native_res_dialog">Native Resolution Warning</string>
|
||||
<string name="text_native_res_dialog">Native resolution modes are not officially supported by GeForce Experience, so it will not set your host display resolution itself. You will need to set it manually while in game.\n\nIf you choose to create a custom resolution in NVIDIA Control Panel to match your device resolution, please ensure you have read and understood NVIDIA\'s warning regarding possible monitor damage, PC instability, and other potential problems.\n\nWe are not responsible for any problems resulting from creating a custom resolution on your PC.\n\nFinally, your device or host PC may not support streaming at native resolution. If it doesn\'t work on your device, you\'re just out of luck unfortunately.</string>
|
||||
<string name="text_native_res_dialog">Native resolution and/or FPS may not be supported by the streaming server. You will probably need to configure a matching custom display mode for the host PC manually.\n\nIf you choose to create a custom resolution in NVIDIA Control Panel to match your screen settings, please ensure you have read and understood NVIDIA\'s warning regarding possible monitor damage, PC instability, and other potential problems.\n\nWe are not responsible for any problems resulting from creating a custom resolution on your PC.\n\nIt may be that your monitor does not support a necessary display configuration. If so, you may try to set up a virtual monitor. Finally, if your device or host PC does not support streaming at a specific resolution or refresh rate, you\'re out of luck unfortunately.</string>
|
||||
<string name="title_fps_list">Video frame rate</string>
|
||||
<string name="summary_fps_list">Increase for a smoother video stream. Decrease for better performance on lower end devices.</string>
|
||||
<string name="title_seekbar_bitrate">Video bitrate</string>
|
||||
@@ -157,6 +158,8 @@
|
||||
<string name="resolution_prefix_native_fullscreen">Native Full-Screen</string>
|
||||
<string name="resolution_prefix_native_landscape">(Landscape)</string>
|
||||
<string name="resolution_prefix_native_portrait">(Portrait)</string>
|
||||
<string name="fps_suffix_fps">FPS</string>
|
||||
<string name="title_native_fps_dialog">Native FPS Warning</string>
|
||||
|
||||
<string name="category_audio_settings">Audio Settings</string>
|
||||
<string name="title_audio_config_list">Surround sound configuration</string>
|
||||
@@ -164,9 +167,7 @@
|
||||
<string name="title_checkbox_enable_audiofx">Enable system equalizer support</string>
|
||||
<string name="summary_checkbox_enable_audiofx">Allows audio effects to function while streaming, but may increase audio latency</string>
|
||||
|
||||
<string name="category_input_settings">Input Settings</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Use the touchscreen as a trackpad</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">If enabled, the touchscreen acts like a trackpad. If disabled, the touchscreen directly controls the mouse cursor.</string>
|
||||
<string name="category_gamepad_settings">Gamepad Settings</string>
|
||||
<string name="title_checkbox_multi_controller">Automatic gamepad presence detection</string>
|
||||
<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>
|
||||
@@ -180,12 +181,22 @@
|
||||
<string name="summary_checkbox_usb_bind_all">Use Moonlight\'s USB driver for all supported gamepads, even if native Xbox controller support is present</string>
|
||||
<string name="title_checkbox_mouse_emulation">Mouse emulation via gamepad</string>
|
||||
<string name="summary_checkbox_mouse_emulation">Long pressing the Start button will switch the gamepad into mouse mode</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Enable back and forward mouse buttons</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Enabling this option may break right clicking on some buggy devices</string>
|
||||
<string name="title_checkbox_flip_face_buttons">Flip face buttons</string>
|
||||
<string name="summary_checkbox_flip_face_buttons">Switches the face buttons A/B and X/Y for gamepads and the on-screen controls</string>
|
||||
<string name="title_checkbox_gamepad_touchpad_as_mouse">Always control mouse with touchpad</string>
|
||||
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Forces gamepad touchpad input to control the host mouse, even when emulating a gamepad with a touchpad.</string>
|
||||
<string name="title_checkbox_gamepad_motion_sensors">Allow use of gamepad motion sensors</string>
|
||||
<string name="summary_checkbox_gamepad_motion_sensors">Enables supported hosts to request motion sensor data when emulating a gamepad with motion sensors. Disabling may slightly reduce power and network usage if motion sensors are not being used in game.</string>
|
||||
<string name="title_checkbox_gamepad_motion_fallback">Emulate gamepad motion sensor support</string>
|
||||
<string name="summary_checkbox_gamepad_motion_fallback">Uses your device\'s built-in motion sensors if gamepad sensors are not supported by your connected gamepad or your Android version.\nNote: Enabling this option may cause your gamepad to appear as a PlayStation controller on the host.</string>
|
||||
|
||||
<string name="category_input_settings">Input Settings</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Use the touchscreen as a trackpad</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">If enabled, the touchscreen acts like a trackpad. If disabled, the touchscreen directly controls the mouse cursor.</string>
|
||||
<string name="title_checkbox_absolute_mouse_mode">Remote desktop mouse mode</string>
|
||||
<string name="summary_checkbox_absolute_mouse_mode">This can make mouse acceleration behave more naturally for remote desktop usage, but it is incompatible with many games.</string>
|
||||
<string name="title_checkbox_mouse_nav_buttons">Enable back and forward mouse buttons</string>
|
||||
<string name="summary_checkbox_mouse_nav_buttons">Enabling this option may break right clicking on some buggy devices</string>
|
||||
|
||||
<string name="category_on_screen_controls_settings">On-screen Controls Settings</string>
|
||||
<string name="title_checkbox_show_onscreen_controls">Show on-screen controls</string>
|
||||
@@ -227,8 +238,8 @@
|
||||
<string name="summary_checkbox_disable_warnings">Disable on-screen connection warning messages while streaming</string>
|
||||
<string name="title_disable_frame_drop">Never drop frames</string>
|
||||
<string name="summary_disable_frame_drop">May reduce micro-stuttering on some devices, but can increase latency</string>
|
||||
<string name="title_video_format">Change HEVC settings</string>
|
||||
<string name="summary_video_format">HEVC lowers video bandwidth requirements but requires a newer device</string>
|
||||
<string name="title_video_format">Change codec settings</string>
|
||||
<string name="summary_video_format">Newer codecs can lower video bandwidth requirements if your device supports them. Codec selections may be ignored if not supported by the host software or GPU.</string>
|
||||
<string name="title_enable_hdr">Enable HDR (Experimental)</string>
|
||||
<string name="summary_enable_hdr">Stream HDR when the game and PC GPU support it. HDR requires a GPU with HEVC Main 10 encoding support.</string>
|
||||
<string name="title_full_range">Force full range video (Experimental)</string>
|
||||
@@ -246,6 +257,9 @@
|
||||
<string name="title_privacy_policy">Privacy policy</string>
|
||||
<string name="summary_privacy_policy">View Moonlight\'s privacy policy</string>
|
||||
|
||||
<!-- Toasts -->
|
||||
<string name="toast_controller_type_changed">Gamepad type may be changed due to motion sensor emulation</string>
|
||||
|
||||
<!-- Array strings -->
|
||||
<string name="resolution_360p">360p</string>
|
||||
<string name="resolution_480p">480p</string>
|
||||
@@ -263,9 +277,10 @@
|
||||
<string name="audioconf_51surround">5.1 Surround Sound</string>
|
||||
<string name="audioconf_71surround">7.1 Surround Sound</string>
|
||||
|
||||
<string name="videoformat_hevcauto">Automatic (Recommended)</string>
|
||||
<string name="videoformat_auto">Automatic (Recommended)</string>
|
||||
<string name="videoformat_av1always">Prefer AV1 (Experimental)</string>
|
||||
<string name="videoformat_hevcalways">Prefer HEVC</string>
|
||||
<string name="videoformat_hevcnever">Never use HEVC</string>
|
||||
<string name="videoformat_h264always">Prefer H.264</string>
|
||||
|
||||
<string name="title_frame_pacing">Video frame pacing</string>
|
||||
<string name="summary_frame_pacing">Specify how to balance video latency and smoothness</string>
|
||||
|
||||
@@ -20,4 +20,7 @@
|
||||
<locale android:name="el"/>
|
||||
<locale android:name="pt-BR"/>
|
||||
<locale android:name="cs"/>
|
||||
<locale android:name="iw"/>
|
||||
<locale android:name="sv"/>
|
||||
<locale android:name="in"/>
|
||||
</locale-config>
|
||||
@@ -55,8 +55,8 @@
|
||||
android:summary="@string/summary_checkbox_enable_audiofx"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/category_input_settings"
|
||||
android:key="category_input_settings">
|
||||
<PreferenceCategory android:title="@string/category_gamepad_settings"
|
||||
android:key="category_gamepad_settings">
|
||||
<com.limelight.preferences.SeekBarPreference
|
||||
android:key="seekbar_deadzone"
|
||||
android:defaultValue="7"
|
||||
@@ -64,21 +64,11 @@
|
||||
android:summary="@string/summary_seekbar_deadzone"
|
||||
android:text="@string/suffix_seekbar_deadzone"
|
||||
android:title="@string/title_seekbar_deadzone"/>
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_touchscreen_trackpad"
|
||||
android:title="@string/title_checkbox_touchscreen_trackpad"
|
||||
android:summary="@string/summary_checkbox_touchscreen_trackpad"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_multi_controller"
|
||||
android:title="@string/title_checkbox_multi_controller"
|
||||
android:summary="@string/summary_checkbox_multi_controller"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_mouse_nav_buttons"
|
||||
android:title="@string/title_checkbox_mouse_nav_buttons"
|
||||
android:summary="@string/summary_checkbox_mouse_nav_buttons"
|
||||
android:defaultValue="false" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_usb_driver"
|
||||
android:title="@string/title_checkbox_xb1_driver"
|
||||
@@ -105,6 +95,34 @@
|
||||
android:title="@string/title_checkbox_flip_face_buttons"
|
||||
android:summary="@string/summary_checkbox_flip_face_buttons"
|
||||
android:defaultValue="false" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_gamepad_touchpad_as_mouse"
|
||||
android:title="@string/title_checkbox_gamepad_touchpad_as_mouse"
|
||||
android:summary="@string/summary_checkbox_gamepad_touchpad_as_mouse"
|
||||
android:defaultValue="false" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_gamepad_motion_sensors"
|
||||
android:title="@string/title_checkbox_gamepad_motion_sensors"
|
||||
android:summary="@string/summary_checkbox_gamepad_motion_sensors"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_gamepad_motion_fallback"
|
||||
android:title="@string/title_checkbox_gamepad_motion_fallback"
|
||||
android:summary="@string/summary_checkbox_gamepad_motion_fallback"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/category_input_settings"
|
||||
android:key="category_input_settings">
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_touchscreen_trackpad"
|
||||
android:title="@string/title_checkbox_touchscreen_trackpad"
|
||||
android:summary="@string/summary_checkbox_touchscreen_trackpad"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_mouse_nav_buttons"
|
||||
android:title="@string/title_checkbox_mouse_nav_buttons"
|
||||
android:summary="@string/summary_checkbox_mouse_nav_buttons"
|
||||
android:defaultValue="false" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_absolute_mouse_mode"
|
||||
android:title="@string/title_checkbox_absolute_mouse_mode"
|
||||
|
||||
@@ -110,6 +110,9 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
|
||||
break;
|
||||
}
|
||||
|
||||
// Note: The EvdevReader process already filters input events when grabbing
|
||||
// is not enabled, so we don't need to that here.
|
||||
|
||||
switch (event.type) {
|
||||
case EvdevEvent.EV_SYN:
|
||||
if (deltaX != 0 || deltaY != 0) {
|
||||
@@ -231,35 +234,8 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
super.enableCapture();
|
||||
if (!started) {
|
||||
// Start the handler thread if it's our first time
|
||||
// capturing
|
||||
handlerThread.start();
|
||||
started = true;
|
||||
}
|
||||
else {
|
||||
// This may be called on the main thread
|
||||
runInNetworkSafeContextSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Send a request to regrab if we're already capturing
|
||||
if (!shutdown && evdevOut != null) {
|
||||
try {
|
||||
evdevOut.write(REGRAB_REQUEST);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableCapture() {
|
||||
super.disableCapture();
|
||||
public void showCursor() {
|
||||
super.showCursor();
|
||||
// This may be called on the main thread
|
||||
runInNetworkSafeContextSynchronously(new Runnable() {
|
||||
@Override
|
||||
@@ -275,6 +251,39 @@ public class EvdevCaptureProvider extends InputCaptureProvider {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideCursor() {
|
||||
super.hideCursor();
|
||||
// This may be called on the main thread
|
||||
runInNetworkSafeContextSynchronously(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Send a request to regrab if we're already capturing
|
||||
if (started && !shutdown && evdevOut != null) {
|
||||
try {
|
||||
evdevOut.write(REGRAB_REQUEST);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableCapture() {
|
||||
if (!started) {
|
||||
// Start the handler thread if it's our first time
|
||||
// capturing
|
||||
handlerThread.start();
|
||||
started = true;
|
||||
}
|
||||
|
||||
// Call the superclass only after we've started the handler thread.
|
||||
// It will invoke hideCursor() when we call it.
|
||||
super.enableCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// We need to stop the process in this context otherwise
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.1'
|
||||
classpath 'com.android.tools.build:gradle:8.1.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
- Added option to stream at device native FPS
|
||||
- Added native PS4/PS5 controller support with motion events, LED, battery, and touchpad**
|
||||
- Added support for using device gyros to emulate gamepad motion sensors*
|
||||
- Added support for automatic controller type detection*
|
||||
- Added native stylus input passthrough*
|
||||
- Added experimental AV1 support*
|
||||
- Added host process latency to performance stats*
|
||||
- Increased gamepad limit to 16*
|
||||
- Added Ctrl+Alt+Shift+C key combo to toggle local mouse cursor
|
||||
- Added Ctrl+Alt+Shift+Q key combo to quit via keyboard
|
||||
- Fixed rumble support for devices with internal controllers (such as the Logitech G Cloud)
|
||||
- Fixed CVE-2023-42799, CVE-2023-42800, and CVE-2023-42801
|
||||
- Android 14 and ChromeOS support improvements
|
||||
|
||||
Items marked with * require Sunshine nightly builds (or v0.21, when released)
|
||||
Items marked with ** also require Android 12 or later and a recent Linux kernel for support.
|
||||
@@ -0,0 +1,5 @@
|
||||
- Added Select+L1 gamepad button combo to act as the touchpad button when emulating a PS4 controller using built-in device motion sensors
|
||||
- Disabled gamepad motion sensors by default on Android 12 as a workaround for an Android 12 bug that randomly crashes Moonlight
|
||||
- Fixed analog sticks not centering properly in rare cases
|
||||
- Adjusted bitrate handling of AV1 to be consistent with HEVC
|
||||
- Fixed handling of some unusual H.264 and HEVC streams
|
||||
@@ -7,11 +7,12 @@ Streaming performance may vary based on your client device and network setup. HD
|
||||
* Streams games purchased from any store
|
||||
* Works on your home network or over the Internet/LTE
|
||||
* Up to 4K 120 FPS HDR streaming with 7.1 surround sound
|
||||
* H.264, HEVC, and AV1 codec support (AV1 requires Sunshine and a supported host GPU)
|
||||
* Keyboard and mouse support (best with Android 8.0 or later)
|
||||
* Stylus/S-Pen support
|
||||
* Supports PS3/4/5, Xbox 360/One/Series, and Android gamepads
|
||||
* Force feedback support
|
||||
* Local co-op with up to 4 connected controllers
|
||||
* Local co-op with up to 16 connected controllers (max of 4 controllers with GFE)
|
||||
* Force feedback and gamepad motion sensor support
|
||||
* Mouse control via gamepad by long-pressing Start
|
||||
|
||||
'''Quick Setup Host Instructions for GeForce Experience (NVIDIA-only)'''
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
Reference in New Issue
Block a user