Compare commits

...

199 Commits

Author SHA1 Message Date
Cameron Gutman
f10085f552 Update to libopus v1.5.2
ARMv7 now compiled with floating point enabled
2024-07-27 17:09:42 -05:00
Cameron Gutman
eb7f0887bf Enable support for 16KB pages 2024-07-27 16:55:21 -05:00
Cameron Gutman
34a9132d60 Update to NDK r27 2024-07-27 16:44:01 -05:00
Cameron Gutman
24d3fb000a Update AGP and Gradle 2024-07-27 16:43:44 -05:00
ReenigneArcher
b7b6adaff7
feat(activity): allow PC Name and AppName for ShortcutTrampoline (#1387) 2024-07-27 16:23:23 -05:00
Matheus Vargem
85ed72802f
feat: Add Guide menu to on-screen virtual controller (#1265)
* Add `Guide Button` to OSC controller

In order to allow the `Guide Button` to be pressed without a physical gamepad, add the button to the On-screen virtual controller

Co-authored-by: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com>
2024-07-27 16:21:17 -05:00
Cameron Gutman
f54f8c83e7 Update to libopus v1.5.1 2024-03-17 22:53:24 -05:00
Cameron Gutman
124bfdf418 Bump all dependencies to latest versions
Most of these were blocked on min API level 21
2024-03-17 17:57:56 -05:00
Cameron Gutman
01507d9995 Enable BTI on ARMv8 2024-03-17 17:56:33 -05:00
Cameron Gutman
070c82bc44 Update to NDK 26c 2024-03-17 17:53:43 -05:00
Cameron Gutman
17df15293f Drop support for Jelly Bean and KitKat
NDK support for these is already gone
2024-03-17 17:43:42 -05:00
komurlu
6551076613
Add Vendor 8BitDo to Xbox360Controller (#1333)
8BitDo Ultimate Bluetooth Controller was not being recognized in XInput mode when using the dongle.
Adding 8BitDo's Vendor ID to SUPPORTED_VENDORS seems to fix it.
2024-02-27 22:49:33 -06:00
Cameron Gutman
1b1b100e63 Version 12.1 2024-02-27 22:45:27 -06:00
Cameron Gutman
e70014bb28 Merge remote-tracking branch 'origin/weblate' 2024-02-21 23:54:35 -06:00
Cameron Gutman
082cc84a71 Remove sustained performance mode
Our CPU usage is so low that it's doubtful we'd ever trigger thermal throttling.
2024-02-17 19:16:35 -06:00
Cameron Gutman
2ba7f0d989 Update to AGP 8.2.2 2024-02-17 18:54:59 -06:00
Cameron Gutman
9a7381b35f Update moonlight-common-c with RTSP encryption 2024-02-17 18:46:55 -06:00
Cameron Gutman
613ecfff44 Add Game Mode configuration 2024-02-17 18:46:28 -06:00
Vag Ko
f638548a02
Translated using Weblate (Greek)
Currently translated at 71.3% (179 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/el/
2024-02-12 22:02:05 +01:00
Jorys Paulin
224bab68bf
Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-02-10 21:02:03 +01:00
Jorys Paulin
6aca18bd76
Translated using Weblate (French)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-02-05 13:01:49 +01:00
Mike
3c58e2fbba
Translated using Weblate (Polish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/pl/
2024-01-30 21:01:56 +01:00
bittin1ddc447d824349b2
aaaebde05e
Translated using Weblate (Swedish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2024-01-24 07:01:52 +01:00
137615
8ff9f70bd7
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2024-01-23 05:01:53 +01:00
Vadym Nekhai
523ca862b9
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/uk/
2024-01-21 16:01:49 +01:00
gallegonovato
78b8d1e9f3
Translated using Weblate (Spanish)
Currently translated at 100.0% (251 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2024-01-21 16:01:48 +01:00
Anonymous
83c698b36d
Translated using Weblate (Chinese (Simplified))
Currently translated at 96.0% (241 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2024-01-20 04:03:09 +01:00
Anonymous
27fe37f221
Translated using Weblate (Romanian)
Currently translated at 60.9% (153 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ro/
2024-01-20 04:03:09 +01:00
Anonymous
3722106daf
Translated using Weblate (Dutch)
Currently translated at 70.1% (176 of 251 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/nl/
2024-01-20 04:03:08 +01:00
Cameron Gutman
3ea9ef1ef2 Merge remote-tracking branch 'origin/weblate' 2024-01-19 21:01:22 -06:00
Cameron Gutman
fcd27b48b2 Eat all exceptions from attempting to start ACTION_REQUEST_CHANNEL_BROWSABLE
Fixes #1302
2024-01-19 20:59:56 -06:00
Cameron Gutman
6ff37a17ec Tweak strings for rumble strength options 2024-01-19 20:51:13 -06:00
Cameron Gutman
f2c6e9e32e Update moonlight-common-c with finalized encryption changes 2024-01-19 19:19:00 -06:00
Alek Lefebvre
dbf1b88a3d
Adjust emulated rumble strength (#1288) 2024-01-19 19:12:21 -06:00
joaomacp
3aab9eb13b Analog stick for scrolling in mouse emulation mode 2024-01-15 15:45:00 -06:00
Cameron Gutman
3f9f8f7b3b Opt in for video encryption on platforms with fast AES implementations 2024-01-15 15:05:38 -06:00
Cameron Gutman
f7520ba40c Move encryption enablement logic into JNI code 2024-01-15 14:59:01 -06:00
Cameron Gutman
7b13f12817 Update moonlight-common-c with new encryption support 2024-01-15 14:54:59 -06:00
Jorys Paulin
57e19d75e2
Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2024-01-09 15:06:17 +00:00
Guillaume Zin
4330a223c6
Handle start+select as home button on Thrustmaster Score A gamepad (#1299) 2023-12-31 14:13:22 -06:00
Cameron Gutman
69387c32ad Display error codes when the connection is terminated 2023-12-30 21:14:22 -06:00
Cameron Gutman
a102ec4ee8 Fix inverted logic 2023-12-30 20:35:00 -06:00
Cameron Gutman
2a094437dd Don't override HDR color format for AV1 2023-12-30 20:33:31 -06:00
Cameron Gutman
4142907376 Don't consume special key combos that we don't handle 2023-12-30 19:50:36 -06:00
Cameron Gutman
e63dc9a93b Suppress bogus UnspecifiedRegisterReceiverFlag warning 2023-12-29 23:55:30 -06:00
Cameron Gutman
1fe19e912e Update moonlight-common-c for X-SS-Connect-Data support 2023-12-29 22:30:56 -06:00
Cameron Gutman
56ad48446e Bump AGP to 8.2.0 2023-12-29 22:29:18 -06:00
Cameron Gutman
a18aa26985 Update moonlight-common-c to remove per-codec bitrate adjustments 2023-12-03 22:20:30 -06:00
Cameron Gutman
5443cc014a Add support for ECDSA server keys 2023-11-29 22:37:12 -06:00
Cameron Gutman
7d77e1c1f2 Don't hardcode signature length 2023-11-29 22:32:00 -06:00
Cameron Gutman
ca82cd9752 Use generic PrivateKey type rather than RSAPrivateKey 2023-11-29 22:20:50 -06:00
bittin1ddc447d824349b2
dbd86bb861
Translated using Weblate (Swedish)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-11-25 05:08:16 +00:00
Cameron Gutman
0af56b4981 Remove roundIcon attribute
This should only be used if the round icon is actually different.
2023-11-24 21:02:50 -06:00
Cameron Gutman
f1be5365bb Version 12.0.2 2023-11-01 20:35:57 -05:00
Cameron Gutman
c356862ac1 Avoid unnecessary reinitialization of PS4/PS5 gamepads during stream exit
onInputDeviceChanged() is triggered by starting/stopping pointer capture, so we should
unregister our callbacks before that happens to avoid triggering several gamepad context
reinitializations right as the stream is exiting
2023-10-29 16:45:07 -05:00
Cameron Gutman
fc77322f59 Merge remote-tracking branch 'origin/weblate' 2023-10-29 15:51:59 -05:00
Cameron Gutman
032e944d49 Update moonlight-common-c with multi-homed host fix 2023-10-29 15:34:09 -05:00
Cameron Gutman
0da47da8d8 Move shortcut creation/updates off the main thread for the common cases
These caused quite a few ANRs due to long Binder calls in ShortcutManager.getDynamicShortcuts()
2023-10-26 00:24:44 -05:00
Cameron Gutman
ebfe843299 Don't process incoming input device requests from the host after we've stopped 2023-10-26 00:05:24 -05:00
Cameron Gutman
827d2362b7 Don't create LightsSessions for devices without an RGB LED 2023-10-25 23:53:35 -05:00
Cameron Gutman
4fa1eb4088 Fix max FPS detection on Lollipop and earlier 2023-10-25 23:47:40 -05:00
Cameron Gutman
885b59fd52 Fix NPE when receiving non-view-associated mouse events with absolute mouse mode enabled 2023-10-25 23:13:54 -05:00
Cameron Gutman
ff5d9f72aa Fix ANRs trying to get battery state during controller arrival 2023-10-25 23:13:11 -05:00
Marocco2
030bb91789
Translated using Weblate (Italian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2023-10-22 09:01:23 +00:00
Jorys Paulin
34788b2808
Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-10-19 06:09:40 +02:00
Cameron Gutman
abc4123c52 Version 12.0.1 2023-10-17 22:39:49 -05:00
Cameron Gutman
26f8c0842e Merge remote-tracking branch 'origin/weblate' 2023-10-16 23:57:21 -05:00
Cameron Gutman
d430d83ba8 Add clickpad button emulation combo (Select+L1) 2023-10-16 23:56:56 -05:00
Cameron Gutman
a52f189fb1 Update ShieldControllerExtensions to fix crash in getBatteryPercentage() 2023-10-16 23:55:39 -05:00
Cameron Gutman
dc1045b69e Don't lie to our own clickpad heuristics when overriding the controller type 2023-10-16 23:38:12 -05:00
Cameron Gutman
3a89dbf4ab Update moonlight-common-c 2023-10-16 23:17:08 -05:00
Cameron Gutman
d69b4eca1e Disable gamepad motion sensors by default on Android 12 due to an OS bug 2023-10-16 23:16:55 -05:00
Marocco2
568bba82f0
Translated using Weblate (Italian)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/it/
2023-10-16 04:19:16 +00:00
Smoukus
b52e6c88ec
Translated using Weblate (German)
Currently translated at 92.5% (224 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/de/
2023-10-16 04:19:14 +00:00
Cameron Gutman
720595091e Change AV1 bitrate multiplier to match HEVC 2023-10-15 12:49:42 -05:00
Cameron Gutman
fe929c8e58 Fix debug build assert 2023-10-13 23:23:42 -05:00
Cameron Gutman
9ecec1eb3c Add support for H.264/HEVC bitstreams with multiple sets of parameter set NALUs 2023-10-13 23:21:50 -05:00
Cameron Gutman
79532f6f14 Version 12.0 2023-10-13 23:02:46 -05:00
Cameron Gutman
b400ba385e Update moonlight-common-c 2023-10-12 00:33:55 -05:00
Cameron Gutman
9915007f30 Check for a null UsbManager object
Apparently this can happen on some (broken?) devices
2023-10-12 00:22:28 -05:00
Cameron Gutman
0168a55596 Propagate the controller number to the standalone DS4 touchpad device 2023-10-07 23:26:26 -05:00
Cameron Gutman
229eff49fb Consume unhandled gamepad mouse events to prevent duplicate mouse actions 2023-10-07 23:04:36 -05:00
Cameron Gutman
0e3b472f78 Fix DS4 clickpad button on devices that expose the touchpad as a mouse 2023-10-07 22:58:07 -05:00
Cameron Gutman
5f29b30d34 Fix DS4 clickpad button on Nvidia Shield (again) 2023-10-07 22:53:19 -05:00
Cameron Gutman
9480363362 Update fastlane metadata with new features 2023-10-07 21:07:53 -05:00
Cameron Gutman
5dd80edde4 Wait 1 second after input device reconfiguration to enable motion sensors 2023-10-07 21:07:02 -05:00
Cameron Gutman
2243cf2017 Rewrite NsdManagerDiscoveryAgent lifecycle to avoid listener reuse 2023-10-07 20:42:13 -05:00
Cameron Gutman
d7791c8543 Adjust default bitrate logic to match new Qt logic 2023-10-07 19:54:02 -05:00
Cameron Gutman
30822c1ba5 Only check for motion sensors on Sony or Nintendo gamepads on Android 12
This works around a bug in Android 12 that leads to random crashes when input devices change.
2023-10-07 19:07:15 -05:00
Cameron Gutman
d250f4dc60 Move battery updates to a background HandlerThread
They can cause long Binder transactions that lead to ANRs.
2023-10-07 00:49:03 -05:00
Cameron Gutman
bc27492206 Split ControllerHandler teardown into stop() and destroy() functions 2023-10-07 00:35:36 -05:00
Cameron Gutman
2b63203a5b Update moonlight-common-c 2023-10-06 23:12:21 -05:00
Cameron Gutman
dc9a26f57b Update to AGP 8.1.2 2023-10-06 23:11:41 -05:00
Jorys Paulin
6f2d7464ba
Translated using Weblate (French)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-09-30 19:01:03 +02:00
Jen Kung-chih
6996c101b4
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-09-24 23:00:42 +02:00
Cameron Gutman
99dc773c7a Merge remote-tracking branch 'origin/weblate' 2023-09-23 12:59:56 -04:00
Cameron Gutman
6ec3f9455a Update moonlight-common-c with frame corruption fixes 2023-09-23 12:58:57 -04:00
Cameron Gutman
6589a568e2 Add freeform window metadata for ChromeOS 2023-09-23 02:48:53 -04:00
Cameron Gutman
55da48e28c Remove USB options from settings page if USB host mode is not supported 2023-09-23 02:21:53 -04:00
Cameron Gutman
081cca48fb Implement cursor visibility and quit key shortcuts
Fixes #1255
2023-09-23 02:20:26 -04:00
137615
6b6a93725c
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-09-20 12:01:18 +00:00
137615
c280a52d33
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-09-20 12:01:17 +00:00
sanhoe
b659439f0b
Translated using Weblate (Korean)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2023-09-20 12:01:16 +00:00
gallegonovato
6453b3c45c
Translated using Weblate (Spanish)
Currently translated at 100.0% (242 of 242 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-09-20 12:01:15 +00:00
Cameron Gutman
978a879c43 Batch async control stream callbacks 2023-09-18 23:25:59 -05:00
Cameron Gutman
833ef3630b Invoke control stream callbacks on a separate thread 2023-09-17 15:00:21 -05:00
Cameron Gutman
024b8c93bc Merge remote-tracking branch 'origin/weblate' 2023-09-16 23:12:05 -05:00
Cameron Gutman
d32c4f86a7 Fix unguarded use of Lollipop API 2023-09-16 22:53:13 -05:00
Cameron Gutman
cafc4450b2 Override controller type when motion sensor emulation is enabled
Without this, the host will still select an Xbox controller even if it can't support motion sensors.
2023-09-16 22:48:38 -05:00
Cameron Gutman
7d69b53958 Tweak preference strings 2023-09-16 22:27:01 -05:00
Cameron Gutman
4d3e883e49 Correct sensors for device orientation 2023-09-16 22:26:11 -05:00
Cameron Gutman
8f9a687872 Add device sensor fallback option
Correction for device orientation is not implemented yet
2023-09-16 20:25:54 -05:00
Cameron Gutman
08d509d831 Use the device vibrator for devices with built-in gamepads 2023-09-16 19:14:22 -05:00
Cameron Gutman
b06dec8449 Fix detection of G Cloud gamepad as an internal controller 2023-09-16 19:09:40 -05:00
Cameron Gutman
28c93b934b Update moonlight-common-c 2023-09-16 16:03:52 -05:00
Cameron Gutman
394a57a26d Disable native touch passthrough for now 2023-09-16 15:59:07 -05:00
bittin1ddc447d824349b2
3856b57a6f
Translated using Weblate (Swedish)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-09-08 11:59:27 +02:00
Zan 1456
9a3a076890
Translated using Weblate (Hungarian)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/hu/
2023-09-08 11:59:26 +02:00
Cameron Gutman
314dfcddcf
Link to Sunshine 2023-09-03 18:05:00 -05:00
Cameron Gutman
1a85bda997 Update to AGP 8.1.1 2023-09-02 23:32:30 -05:00
Cameron Gutman
e8b30d5a88 Set KEY_PRIORITY during low latency option probing 2023-09-02 23:32:16 -05:00
Cameron Gutman
96bd1a7799 Update moonlight-common-c 2023-09-02 22:46:59 -05:00
sanhoe
cb0a1f13bc
Translated using Weblate (Korean)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ko/
2023-08-08 04:53:26 +02:00
Cameron Gutman
e92fdeef47 Fix RGB LED capability flag on Android 12 and 13 2023-08-03 23:02:11 -05:00
Cameron Gutman
62bae62386 Fix end of stream toast for AV1 2023-08-03 21:10:06 -05:00
Cameron Gutman
2636d79b86 Fix handling of ACTION_CANCEL for multi-pointer gestures 2023-08-03 02:29:55 -05:00
Cameron Gutman
c9c1ef91fd Fix mishandling ACTION_MOVE events for native pen/touch events 2023-07-27 23:15:26 -05:00
weng weng
ce7bba3e09
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hans/
2023-07-26 13:04:56 +02:00
S. MohammadMahdi Zamanian
bfd53f39bd
Added translation using Weblate (Persian) 2023-07-26 09:23:11 +02:00
Cameron Gutman
554fee037c Fix race condition when stopDiscovery() is called during onServiceFound()/onServiceLost() 2023-07-25 18:46:31 -05:00
Cameron Gutman
67b2853ef0 Add contact area and orientation for pen/touch events 2023-07-22 17:18:57 -05:00
Cameron Gutman
0e29e13d03 Use private API to detect clickpads on Android O and earlier 2023-07-22 14:34:27 -05:00
Jen Kung-chih
35f2a238e9
Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/zh_Hant/
2023-07-19 18:05:46 +02:00
Jorys Paulin
fcb34ab6ee
Translated using Weblate (French)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-07-13 11:51:59 +02:00
Cameron Gutman
3fbf682785 Pass gamepad touch input natively by default
Most devices will have a touchscreen which already provides mouse input
and Steam Input is can provide gamepad touchpad mouse control if desired.
2023-07-12 01:21:35 -05:00
Cameron Gutman
16086a6d3f Send the touchpad button on the gamepad even when using the touchpad for mouse control 2023-07-12 01:16:33 -05:00
Cameron Gutman
18b6aae381 Disable gamepad sensors while in PiP mode 2023-07-12 01:07:14 -05:00
Cameron Gutman
642c353164 Fix handling of onInputDeviceChanged when using sensors and lights
DS4 triggers this path when we release our pointer capture on activity pause
2023-07-12 00:32:28 -05:00
Cameron Gutman
42f64e5e88 Rename videoformat_hevcauto translations to videoformat_auto 2023-07-11 20:18:31 -05:00
Cameron Gutman
6af748b2cc Remove videoformat_hevcauto translations that still reference HEVC 2023-07-11 20:12:10 -05:00
Cameron Gutman
4fe97b69c7 Fix invalid format string 2023-07-11 20:10:52 -05:00
Cameron Gutman
04d46272dd Remove now unused videoformat_hevcnever string 2023-07-11 20:10:38 -05:00
Cameron Gutman
1c0290dc7a Merge remote-tracking branch 'origin/weblate' 2023-07-11 20:05:21 -05:00
Cameron Gutman
38588402e3 Use NsdManager for mDNS discovery on Android 14 2023-07-11 19:58:50 -05:00
Luna Jernberg
dfe3b8888d
Translated using Weblate (Swedish)
Currently translated at 99.5% (238 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-07-11 17:49:16 +02:00
ThomasTech
e8f4022f1e
Translated using Weblate (French)
Currently translated at 95.3% (228 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-07-11 17:49:15 +02:00
gallegonovato
e37bb32c82
Translated using Weblate (Spanish)
Currently translated at 100.0% (239 of 239 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/es/
2023-07-11 17:49:15 +02:00
Cameron Gutman
1f72c82acb Consolidate AV1 and HEVC options into a single preference 2023-07-09 15:04:26 -05:00
Cameron Gutman
e6876926a4 Add options to control gamepad touchpad and motion and reorganize input settings 2023-07-09 14:46:46 -05:00
Cameron Gutman
2b8a43ab13 Update locale selections to add Hebrew, Swedish, and Indonesian languages 2023-07-09 14:00:14 -05:00
Cameron Gutman
8737466368 Merge branch 'weblate' of github.com:moonlight-stream/moonlight-android 2023-07-09 13:47:07 -05:00
Cameron Gutman
83916fa43e Map the Menu key for keyboards 2023-07-08 23:21:19 -05:00
Cameron Gutman
1fe5a12a45 Update moonlight-common-c 2023-07-08 23:19:33 -05:00
Cameron Gutman
fa7f3115ed Add AV1 autoselection by performance point criteria 2023-07-07 23:09:05 -05:00
Cameron Gutman
4dc6143440 Override the stock DS4 touchpad button mapping for Shield devices
Nvidia's stock mapping treats the clickpad as a second select button.
2023-07-05 23:00:54 -05:00
Cameron Gutman
f1503aa56c Implement battery reporting for Shield controllers 2023-07-05 18:57:01 -05:00
Cameron Gutman
67f344b755 Move serverCodecModeSupport into SERVER_INFORMATION struct 2023-07-02 23:56:34 -05:00
Cameron Gutman
f1bcc217a9 Update to new HDR support option in moonlight-common-c 2023-07-02 23:48:19 -05:00
Cameron Gutman
458460515d Plumb AV1 preference and rework HEVC preference to match 2023-07-02 23:48:13 -05:00
Cameron Gutman
3a78095574 Initial implementation of AV1 2023-07-02 22:49:42 -05:00
Cameron Gutman
d6bbfa1af1 Fix unmapped paddle and share button presses 2023-07-02 20:32:57 -05:00
Cameron Gutman
4e1b778f31 Import some SDL code and use it for controller classification
Imported as of 4aee17b039981f2bb79892f3d3e3e17bd6b66530
2023-07-02 20:20:55 -05:00
Cameron Gutman
5f4496036c Don't use GameManager loading flag
This is meant to affect CPU throttling, which we don't need.
2023-07-02 19:08:58 -05:00
Cameron Gutman
d4079940b4 Implement controller LED and battery state extensions 2023-07-02 19:03:31 -05:00
Cameron Gutman
803ad116fb Pull in latest moonlight-common-c change 2023-06-28 17:28:41 -05:00
Cameron Gutman
27701eda49 Handle paddle buttons on Xbox Elite controllers 2023-06-28 17:28:25 -05:00
Cameron Gutman
71c831b02d Handle 2-direction d-pad key events 2023-06-28 17:22:05 -05:00
Cameron Gutman
0d72a0e009 Implement latest pen/touch protocol updates 2023-06-27 22:21:39 -05:00
Cameron Gutman
69a4502f90 Fix pen/touch coordinates when reported from the background touch view 2023-06-25 00:50:17 -05:00
Cameron Gutman
daaa7f4e63 Fix pen rotation values 2023-06-25 00:26:32 -05:00
Cameron Gutman
d1579e9b0d Support PS4/PS5 touchpad click on older kernels 2023-06-24 23:45:31 -05:00
Cameron Gutman
5890fff240 Add pen and touch events 2023-06-24 23:13:59 -05:00
Cameron Gutman
d6f6307050 Fix units of gyro motion and deduplicate sensor events 2023-06-24 23:12:28 -05:00
Cameron Gutman
6bf9c31860 Pull in updated moonlight-common-c pen/touch APIs 2023-06-24 21:29:44 -05:00
Cameron Gutman
a2e628f3f8 Add controller arrival metadata support 2023-06-24 20:23:43 -05:00
Cameron Gutman
8f5416ff31 Target Android 14 2023-06-24 19:38:34 -05:00
Cameron Gutman
db86f18133 Use new per-activity predictive back support on Android 14
We can't enable it on the Game activity, but we an use it for all other activities.
2023-06-24 19:38:07 -05:00
Cameron Gutman
419e4e656e Use an explicit intent for requesting USB permission 2023-06-24 19:37:12 -05:00
Cameron Gutman
eed4327d26 Add controller touchpad support 2023-06-24 19:09:10 -05:00
Cameron Gutman
5c6eaf2602 Add controller gyro and accelerometer support 2023-06-24 19:06:58 -05:00
Cameron Gutman
71169ed740 Add trigger rumble support 2023-06-24 17:59:10 -05:00
Cameron Gutman
dca8d93aa8 Add Share button mapping for Xbox Series X controller 2023-06-24 16:16:02 -05:00
Cameron Gutman
6cb152f602 Increase gamepad limit to 16 for Sunshine hosts 2023-06-24 16:15:00 -05:00
Cameron Gutman
ddefda3afa Plumb new Sunshine protocol extensions 2023-06-24 15:19:50 -05:00
Cameron Gutman
7f15f45beb Only display the host processing latency if it was present 2023-06-24 15:00:54 -05:00
Timothy Lusk
46f887efec Add host processing latency to performance stats overlay 2023-06-24 14:19:05 -05:00
semjon00
90afecd766 Add option to stream at device native FPS
Useful for phones with overclocked refresh rate
2023-06-24 14:16:49 -05:00
Cameron Gutman
388343c3ee Update to AGP 8.0.2 2023-06-24 14:15:38 -05:00
ns6089
c8df37e89e Compensate for choreographer vsync offset 2023-06-24 13:52:20 -05:00
Clxff H3r4ld0
cc85d5c343
Translated using Weblate (Indonesian)
Currently translated at 79.5% (183 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2023-05-27 17:50:51 +02:00
Jorys Paulin
f8437cdb8f
Translated using Weblate (French)
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/fr/
2023-05-21 16:51:09 +02:00
shakedex
c99a210905
Translated using Weblate (Hebrew)
Currently translated at 57.3% (132 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/he/
2023-04-30 10:50:54 +02:00
Yutaro Urata
e33673c9e9
Translated using Weblate (Japanese)
Currently translated at 51.7% (119 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/ja/
2023-04-30 10:50:53 +02:00
shakedex
79283e93cb
Translated using Weblate (Hebrew)
Currently translated at 50.4% (116 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/he/
2023-04-27 01:51:19 +02:00
shakedex
a60e85a3a4
Added translation using Weblate (Hebrew) 2023-04-25 23:56:54 +02:00
Simon Nilsson
80910ed38d
Translated using Weblate (Swedish)
Currently translated at 100.0% (230 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/sv/
2023-03-31 22:09:41 +02:00
Simon Nilsson
825a338474
Added translation using Weblate (Swedish) 2023-03-29 16:56:54 +02:00
Cameron Gutman
19b6e94824 Add horizontal scrolling in mouse emulation mode 2023-03-04 12:31:31 -06:00
Cliff Heraldo
6b7669bb75
Translated using Weblate (Indonesian)
Currently translated at 32.1% (74 of 230 strings)

Translation: Moonlight Game Streaming/moonlight-android
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-android/id/
2023-02-27 10:37:51 +01:00
111 changed files with 6693 additions and 2204 deletions

View File

@ -3,7 +3,7 @@
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/232a8tadrrn8jv0k/branch/master?svg=true)](https://ci.appveyor.com/project/cgutman/moonlight-android/branch/master)
[![Translation Status](https://hosted.weblate.org/widgets/moonlight/-/moonlight-android/svg-badge.svg)](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.

View File

@ -1,18 +1,18 @@
apply plugin: 'com.android.application'
android {
ndkVersion "23.2.8568313"
ndkVersion "27.0.12077973"
compileSdk 33
compileSdk 34
namespace 'com.limelight'
defaultConfig {
minSdk 16
targetSdk 33
minSdk 21
targetSdk 34
versionName "11.0"
versionCode = 306
versionName "12.1"
versionCode = 314
// 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
@ -132,12 +136,10 @@ android {
}
dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
implementation 'org.jcodec:jcodec:0.2.3'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'com.squareup.okio:okio:1.17.5'
// 3.5.8 requires minSdk 19, uses StandardCharsets.UTF_8 internally
implementation 'org.jmdns:jmdns:3.5.7'
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0'
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
implementation 'org.jcodec:jcodec:0.2.5'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'org.jmdns:jmdns:3.5.9'
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
}

View File

@ -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
@ -40,7 +50,6 @@
android:banner="@drawable/atv_banner"
android:appCategory="game"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:installLocation="auto"
android:gwpAsanMode="always"
android:localeConfig="@xml/locales_config"
@ -68,6 +77,11 @@
android:name="com.android.graphics.intervention.wm.allowDownscale"
android:value="false"/>
<!-- Game Mode configuration -->
<meta-data
android:name="android.game_mode_config"
android:resource="@xml/game_mode_config" />
<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
in each activity even though it is implied by targeting API 24+ -->
@ -75,7 +89,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 +110,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 +148,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 +180,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>

View File

@ -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;
@ -126,12 +127,15 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private int suppressPipRefCount = 0;
private String pcName;
private String appName;
private NvApp app;
private float desiredRefreshRate;
private InputCaptureProvider inputCaptureProvider;
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;
@ -143,8 +147,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private int requestedNotificationOverlayVisibility = View.GONE;
private TextView performanceOverlayView;
private ShortcutHelper shortcutHelper;
private MediaCodecDecoderRenderer decoderRenderer;
private boolean reportedCrash;
@ -193,14 +195,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// If we're going to use immersive mode, we want to have
// the entire screen
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
// Listen for UI visibility events
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
@ -315,10 +315,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
int httpsPort = Game.this.getIntent().getIntExtra(EXTRA_HTTPS_PORT, 0); // 0 is treated as unknown
int appId = Game.this.getIntent().getIntExtra(EXTRA_APP_ID, StreamConfiguration.INVALID_APP_ID);
String uniqueId = Game.this.getIntent().getStringExtra(EXTRA_UNIQUEID);
String uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
boolean appSupportsHdr = Game.this.getIntent().getBooleanExtra(EXTRA_APP_HDR, false);
byte[] derCertData = Game.this.getIntent().getByteArrayExtra(EXTRA_SERVER_CERT);
app = new NvApp(appName != null ? appName : "app", appId, appSupportsHdr);
X509Certificate serverCert = null;
try {
if (derCertData != null) {
@ -334,17 +335,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
return;
}
// Report this shortcut being used
ComputerDetails computer = new ComputerDetails();
computer.name = pcName;
computer.uuid = uuid;
shortcutHelper = new ShortcutHelper(this);
shortcutHelper.reportComputerShortcutUsed(computer);
if (appName != null) {
// This may be null if launched from the "Resume Session" PC context menu item
shortcutHelper.reportGameLaunched(computer, new NvApp(appName, appId, appSupportsHdr));
}
// Initialize the MediaCodec helper before creating the decoder
GlPreferences glPrefs = GlPreferences.readPreferences(this);
MediaCodecHelper.initialize(this, glPrefs.glRenderer);
@ -404,14 +394,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);
@ -456,19 +466,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
.setResolution(prefConfig.width, prefConfig.height)
.setLaunchRefreshRate(prefConfig.fps)
.setRefreshRate(chosenFrameRate)
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
.setApp(app)
.setBitrate(prefConfig.bitrate)
.setEnableSops(prefConfig.enableSops)
.enableLocalAudioPlayback(prefConfig.playHostAudio)
.setMaxPacketSize(1392)
.setRemoteConfiguration(StreamConfiguration.STREAM_CFG_AUTO) // NvConnection will perform LAN and VPN detection
.setHevcBitratePercentageMultiplier(75)
.setHevcSupported(decoderRenderer.isHevcSupported())
.setEnableHdr(willStreamHdr)
.setSupportedVideoFormats(supportedVideoFormats)
.setAttachedGamepadMask(gamepadMask)
.setClientRefreshRateX100((int)(displayRefreshRate * 100))
.setAudioConfiguration(prefConfig.audioConfiguration)
.setAudioEncryption(true)
.setColorSpace(decoderRenderer.getPreferredColorSpace())
.setColorRange(decoderRenderer.getPreferredColorRange())
.setPersistGamepadsAfterDisconnect(!prefConfig.multiController)
@ -483,7 +490,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
keyboardTranslator = new KeyboardTranslator();
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(controllerHandler, null);
inputManager.registerInputDeviceListener(keyboardTranslator, null);
// Initialize touch contexts
@ -498,12 +504,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
}
// Use sustained performance mode on N+ to ensure consistent
// CPU availability
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getWindow().setSustainedPerformanceMode(true);
}
if (prefConfig.onscreenController) {
// create virtual onscreen controller
virtualController = new VirtualController(controllerHandler,
@ -558,39 +558,19 @@ public class Game extends Activity implements SurfaceHolder.Callback,
}
if (desiredOrientation == Configuration.ORIENTATION_LANDSCAPE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else if (desiredOrientation == Configuration.ORIENTATION_PORTRAIT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
}
else {
// If we don't have a reason to lock to portrait or landscape, allow any orientation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
}
else {
// For regular displays, we always request landscape
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
}
@ -618,6 +598,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 +619,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);
}
@ -912,7 +898,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
displayRefreshRate = bestMode.getRefreshRate();
}
// On L, we can at least tell the OS that we want a refresh rate
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
float bestRefreshRate = display.getRefreshRate();
for (float candidate : display.getSupportedRefreshRates()) {
LimeLog.info("Examining refresh rate: "+candidate);
@ -936,19 +922,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Apply the refresh rate change
getWindow().setAttributes(windowLayoutParams);
}
else {
// Otherwise, the active display refresh rate is just
// whatever is currently in use.
displayRefreshRate = display.getRefreshRate();
}
// From 4.4 to 5.1 we can't ask for a 4K display mode, so we'll
// Until Marshmallow, we can't ask for a 4K display mode, so we'll
// need to hint the OS to provide one.
boolean aspectRatioMatch = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
// On KitKat and later (where we can use the whole screen via immersive mode), we'll
// calculate whether we need to scale by aspect ratio or not. If not, we'll use
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// We'll calculate whether we need to scale by aspect ratio. If not, we'll use
// setFixedSize so we can handle 4K properly. The only known devices that have
// >= 4K screens have exactly 4K screens, so we'll be able to hit this good path
// on these devices. On Marshmallow, we can start changing to 4K manually but no
@ -1003,8 +982,8 @@ public class Game extends Activity implements SurfaceHolder.Callback,
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
// Use immersive mode on 4.4+ or standard low profile on previous builds
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
else {
// Use immersive mode
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
@ -1013,11 +992,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
else {
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
}
};
@ -1040,16 +1014,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// that case here too.
if (isInMultiWindowMode) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Disable performance optimizations for foreground
getWindow().setSustainedPerformanceMode(false);
decoderRenderer.notifyVideoBackground();
}
else {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Enable performance optimizations for foreground
getWindow().setSustainedPerformanceMode(true);
decoderRenderer.notifyVideoForeground();
}
@ -1061,11 +1029,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
protected void onDestroy() {
super.onDestroy();
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
if (controllerHandler != null) {
inputManager.unregisterInputDeviceListener(controllerHandler);
controllerHandler.destroy();
}
if (keyboardTranslator != null) {
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
inputManager.unregisterInputDeviceListener(keyboardTranslator);
}
@ -1085,6 +1053,21 @@ public class Game extends Activity implements SurfaceHolder.Callback,
inputCaptureProvider.destroy();
}
@Override
protected void onPause() {
if (isFinishing()) {
// Stop any further input device notifications before we lose focus (and pointer capture)
if (controllerHandler != null) {
controllerHandler.stop();
}
// Ungrab input to prevent further input device notifications
setInputGrabState(false);
}
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
@ -1118,15 +1101,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 +1144,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 +1171,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 +1189,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,37 +1200,73 @@ 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);
}
// 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)) {
switch (androidKeyCode) {
case KeyEvent.KEYCODE_Z:
case KeyEvent.KEYCODE_Q:
case KeyEvent.KEYCODE_C:
// Remember that a special key combo was activated, so we can consume all key
// events until the modifiers come up
specialKeyCode = androidKeyCode;
waitingForAllModifiersUp = true;
return true;
grabComboDown = false;
return true;
default:
// This isn't a special combo that we consume on the client side
return false;
}
}
// Not a special combo
@ -1445,20 +1485,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)
@ -1512,7 +1832,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if (deltaX != 0 || deltaY != 0) {
if (prefConfig.absoluteMouseMode) {
conn.sendMouseMoveAsMousePosition(deltaX, deltaY, (short)view.getWidth(), (short)view.getHeight());
// NB: view may be null, but we can unconditionally use streamView because we don't need to adjust
// relative axis deltas for the position of the streamView within the parent's coordinate system.
conn.sendMouseMoveAsMousePosition(deltaX, deltaY, (short)streamView.getWidth(), (short)streamView.getHeight());
}
else {
conn.sendMouseMove(deltaX, deltaY);
@ -1545,6 +1867,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 +2013,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;
@ -1845,13 +2180,11 @@ public class Game extends Activity implements SurfaceHolder.Callback,
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent event) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Tell the OS not to buffer input events for us
//
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
view.requestUnbufferedDispatch(event);
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Tell the OS not to buffer input events for us
//
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
view.requestUnbufferedDispatch(event);
}
return handleMotionEvent(view, event);
@ -1949,6 +2282,9 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Let the display go to sleep now
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Stop processing controller input
controllerHandler.stop();
// Ungrab input
setInputGrabState(false);
@ -1986,7 +2322,16 @@ public class Game extends Activity implements SurfaceHolder.Callback,
break;
default:
message = getResources().getString(R.string.conn_terminated_msg);
String errorCodeString;
// We'll assume large errors are hex values
if (Math.abs(errorCode) > 1000) {
errorCodeString = Integer.toHexString(errorCode);
}
else {
errorCodeString = Integer.toString(errorCode);
}
message = getResources().getString(R.string.conn_terminated_msg) + "\n\n" +
getResources().getString(R.string.error_code_prefix) + " " + errorCodeString;
break;
}
}
@ -2073,6 +2418,17 @@ public class Game extends Activity implements SurfaceHolder.Callback,
hideSystemUi(1000);
}
});
// Report this shortcut being used (off the main thread to prevent ANRs)
ComputerDetails computer = new ComputerDetails();
computer.name = pcName;
computer.uuid = Game.this.getIntent().getStringExtra(EXTRA_PC_UUID);
ShortcutHelper shortcutHelper = new ShortcutHelper(this);
shortcutHelper.reportComputerShortcutUsed(computer);
if (appName != null) {
// This may be null if launched from the "Resume Session" PC context menu item
shortcutHelper.reportGameLaunched(computer, app);
}
}
@Override
@ -2104,12 +2460,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) {
@ -2258,14 +2631,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
hideSystemUi(2000);
}
// This flag is only set on 4.4+
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT &&
(visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
hideSystemUi(2000);
}
// This flag is only set before 4.4+
else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT &&
(visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
else if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
hideSystemUi(2000);
}
}

View File

@ -260,6 +260,11 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
updateComputer(details);
}
});
// Add a launcher shortcut for this PC (off the main thread to prevent ANRs)
if (details.pairState == PairState.PAIRED) {
shortcutHelper.createAppViewShortcutForOnlineHost(details);
}
}
}
});
@ -720,11 +725,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
}
}
// Add a launcher shortcut for this PC
if (details.pairState == PairState.PAIRED) {
shortcutHelper.createAppViewShortcutForOnlineHost(details);
}
if (existingEntry != null) {
// Replace the information in the existing entry
existingEntry.details = details;

View File

@ -8,19 +8,26 @@ import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import com.limelight.computers.ComputerDatabaseManager;
import com.limelight.computers.ComputerManagerListener;
import com.limelight.computers.ComputerManagerService;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvApp;
import com.limelight.nvstream.http.NvHTTP;
import com.limelight.nvstream.http.PairingManager;
import com.limelight.nvstream.wol.WakeOnLanSender;
import com.limelight.utils.CacheHelper;
import com.limelight.utils.Dialog;
import com.limelight.utils.ServerHelper;
import com.limelight.utils.SpinnerDialog;
import com.limelight.utils.UiHelper;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ShortcutTrampoline extends Activity {
@ -33,6 +40,7 @@ public class ShortcutTrampoline extends Activity {
private SpinnerDialog blockingLoadSpinner;
private ComputerManagerService.ComputerManagerBinder managerBinder;
private final ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
final ComputerManagerService.ComputerManagerBinder localBinder =
@ -214,9 +222,9 @@ public class ShortcutTrampoline extends Activity {
}
};
protected boolean validateInput(String uuidString, String appIdString) {
// Validate UUID
if (uuidString == null) {
protected boolean validateInput(String uuidString, String appIdString, String nameString) {
// Validate PC UUID/Name
if (uuidString == null && nameString == null) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
@ -224,14 +232,25 @@ public class ShortcutTrampoline extends Activity {
return false;
}
try {
UUID.fromString(uuidString);
} catch (IllegalArgumentException ex) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
if (uuidString != null && !uuidString.isEmpty()) {
try {
UUID.fromString(uuidString);
} catch (IllegalArgumentException ex) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
}
} else {
// UUID is null, so fallback to Name
if (nameString == null || nameString.isEmpty()) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_uuid),
true);
return false;
}
}
// Validate App ID (if provided)
@ -255,24 +274,93 @@ public class ShortcutTrampoline extends Activity {
super.onCreate(savedInstanceState);
UiHelper.notifyNewRootView(this);
ComputerDatabaseManager dbManager = new ComputerDatabaseManager(this);
ComputerDetails _computer = null;
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
// PC arguments, both are optional, but at least one must be provided
uuidString = getIntent().getStringExtra(AppView.UUID_EXTRA);
String nameString = getIntent().getStringExtra(AppView.NAME_EXTRA);
if (validateInput(uuidString, appIdString)) {
if (appIdString != null && !appIdString.isEmpty()) {
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
Integer.parseInt(appIdString),
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
// App arguments, both are optional, but one must be provided in order to start an app
String appIdString = getIntent().getStringExtra(Game.EXTRA_APP_ID);
String appNameString = getIntent().getStringExtra(Game.EXTRA_APP_NAME);
if (!validateInput(uuidString, appIdString, nameString)) {
// Invalid input, so just return
return;
}
if (uuidString == null || uuidString.isEmpty()) {
// Use nameString to find the corresponding UUID
_computer = dbManager.getComputerByName(nameString);
if (_computer == null) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_pc_not_found),
true);
return;
}
// Bind to the computer manager service
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
Service.BIND_AUTO_CREATE);
uuidString = _computer.uuid;
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
getResources().getString(R.string.applist_connect_msg), true);
// Set the AppView UUID intent, since it wasn't provided
setIntent(new Intent(getIntent()).putExtra(AppView.UUID_EXTRA, uuidString));
}
if (appIdString != null && !appIdString.isEmpty()) {
app = new NvApp(getIntent().getStringExtra(Game.EXTRA_APP_NAME),
Integer.parseInt(appIdString),
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
}
else if (appNameString != null && !appNameString.isEmpty()) {
// Use appNameString to find the corresponding AppId
try {
int appId = -1;
String rawAppList = CacheHelper.readInputStreamToString(CacheHelper.openCacheFileForInput(getCacheDir(), "applist", uuidString));
if (rawAppList.isEmpty()) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
List<NvApp> applist = NvHTTP.getAppListByReader(new StringReader(rawAppList));
for (NvApp _app : applist) {
if (_app.getAppName().equals(appNameString)) {
appId = _app.getAppId();
break;
}
}
if (appId < 0) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
setIntent(new Intent(getIntent()).putExtra(Game.EXTRA_APP_ID, appId));
app = new NvApp(
appNameString,
appId,
getIntent().getBooleanExtra(Game.EXTRA_APP_HDR, false));
} catch (IOException | XmlPullParserException e) {
Dialog.displayDialog(ShortcutTrampoline.this,
getResources().getString(R.string.conn_error_title),
getResources().getString(R.string.scut_invalid_app_id),
true);
return;
}
}
// Bind to the computer manager service
bindService(new Intent(this, ComputerManagerService.class), serviceConnection,
Service.BIND_AUTO_CREATE);
blockingLoadSpinner = SpinnerDialog.displayDialog(this, getResources().getString(R.string.conn_establishing_title),
getResources().getString(R.string.applist_connect_msg), true);
}
@Override

View File

@ -26,51 +26,41 @@ public class AndroidAudioRenderer implements AudioRenderer {
}
private AudioTrack createAudioTrack(int channelConfig, int sampleRate, int bufferSize, boolean lowLatency) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate,
channelConfig,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
AudioTrack.MODE_STREAM);
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME);
AudioFormat format = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(sampleRate)
.setChannelMask(channelConfig)
.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Use FLAG_LOW_LATENCY on L through N
if (lowLatency) {
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
.setAudioFormat(format)
.setAudioAttributes(attributesBuilder.build())
.setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(bufferSize);
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
if (lowLatency) {
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
}
return trackBuilder.build();
}
else {
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME);
AudioFormat format = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(sampleRate)
.setChannelMask(channelConfig)
.build();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Use FLAG_LOW_LATENCY on L through N
if (lowLatency) {
attributesBuilder.setFlags(AudioAttributes.FLAG_LOW_LATENCY);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AudioTrack.Builder trackBuilder = new AudioTrack.Builder()
.setAudioFormat(format)
.setAudioAttributes(attributesBuilder.build())
.setTransferMode(AudioTrack.MODE_STREAM)
.setBufferSizeInBytes(bufferSize);
// Use PERFORMANCE_MODE_LOW_LATENCY on O and later
if (lowLatency) {
trackBuilder.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY);
}
return trackBuilder.build();
}
else {
return new AudioTrack(attributesBuilder.build(),
format,
bufferSize,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE);
}
return new AudioTrack(attributesBuilder.build(),
format,
bufferSize,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE);
}
}
@ -91,20 +81,10 @@ public class AndroidAudioRenderer implements AudioRenderer {
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
case 8:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
// in 5.0, so just hardcode the constant so we can work on Lollipop.
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
}
else {
// On KitKat and lower, creation of the AudioTrack will fail if we specify
// CHANNEL_OUT_SIDE_LEFT or CHANNEL_OUT_SIDE_RIGHT. That leaves us with
// the old CHANNEL_OUT_7POINT1 which uses left-of-center and right-of-center
// speakers instead of side-left and side-right. This non-standard layout
// is probably not what the user wants, but we don't really have a choice.
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1;
}
// AudioFormat.CHANNEL_OUT_7POINT1_SURROUND isn't available until Android 6.0,
// yet the CHANNEL_OUT_SIDE_LEFT and CHANNEL_OUT_SIDE_RIGHT constants were added
// in 5.0, so just hardcode the constant so we can work on Lollipop.
channelConfig = 0x000018fc; // AudioFormat.CHANNEL_OUT_7POINT1_SURROUND
break;
default:
LimeLog.severe("Decoder returned unhandled channel count");

View File

@ -12,12 +12,12 @@ import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Calendar;
@ -48,7 +48,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
private final File keyFile;
private X509Certificate cert;
private RSAPrivateKey key;
private PrivateKey key;
private byte[] pemCertBytes;
private static final Object globalCryptoLock = new Object();
@ -94,7 +94,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
pemCertBytes = certBytes;
KeyFactory keyFactory = KeyFactory.getInstance("RSA", bcProvider);
key = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
key = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
} catch (CertificateException e) {
// May happen if the cert is corrupt
LimeLog.warning("Corrupted certificate");
@ -144,7 +144,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
try {
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(bcProvider).build(keyPair.getPrivate());
cert = new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(sigGen));
key = (RSAPrivateKey) keyPair.getPrivate();
key = keyPair.getPrivate();
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -215,7 +215,7 @@ public class AndroidCryptoProvider implements LimelightCryptoProvider {
}
}
public RSAPrivateKey getClientPrivateKey() {
public PrivateKey getClientPrivateKey() {
// Use a lock here to ensure only one guy will be generating or loading
// the certificate and key at a time
synchronized (globalCryptoLock) {

View File

@ -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;

View File

@ -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,19 @@ public class AndroidNativePointerCaptureProvider extends AndroidPointerIconCaptu
}
@Override
public void enableCapture() {
super.enableCapture();
public void showCursor() {
super.showCursor();
// It is important to unregister the listener *before* releasing pointer capture,
// because releasing pointer capture can cause an onInputDeviceChanged() callback
// for devices with a touchpad (like a DS4 controller).
inputManager.unregisterInputDeviceListener(this);
targetView.releasePointerCapture();
}
@Override
public void hideCursor() {
super.hideCursor();
// Listen for device events to enable/disable capture
inputManager.registerInputDeviceListener(this, null);
@ -74,16 +85,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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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() {

View File

@ -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);

View File

@ -1,5 +1,6 @@
package com.limelight.binding.input.driver;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
@ -42,7 +43,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 +160,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) {
@ -204,28 +211,22 @@ public class UsbDriverService extends Service implements UsbDriverListener {
}
public static boolean isRecognizedInputDevice(UsbDevice device) {
// On KitKat and later, we can determine if this VID and PID combo
// matches an existing input device and defer to the built-in controller
// support in that case. Prior to KitKat, we'll always return true to be safe.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
if (inputDev.getVendorId() == device.getVendorId() &&
inputDev.getProductId() == device.getProductId()) {
return true;
}
// Determine if this VID and PID combo matches an existing input device
// and defer to the built-in controller support in that case.
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
return false;
}
else {
return true;
if (inputDev.getVendorId() == device.getVendorId() &&
inputDev.getProductId() == device.getProductId()) {
return true;
}
}
return false;
}
public static boolean kernelSupportsXboxOne() {
@ -280,8 +281,9 @@ public class UsbDriverService extends Service implements UsbDriverListener {
((!kernelSupportsXbox360W() || claimAllAvailable) && Xbox360WirelessDongle.canClaimDevice(device));
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
private void start() {
if (started) {
if (started || usbManager == null) {
return;
}

View File

@ -39,6 +39,7 @@ public class Xbox360Controller extends AbstractXboxController {
0x20d6, // PowerA
0x24c6, // PowerA
0x2f24, // GameSir
0x2dc8, // 8BitDo
};
public static boolean canClaimDevice(UsbDevice device) {
@ -156,4 +157,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
}
}

View File

@ -89,28 +89,26 @@ public class Xbox360WirelessDongle extends AbstractController {
public boolean start() {
int controllerIndex = 0;
// On KitKat, there is a controller number associated with input devices.
// On Android, there is a controller number associated with input devices.
// We can use this to approximate the likely controller number. This won't
// be completely accurate because there's no guarantee the order of interfaces
// matches the order that devices were enumerated by xpad, but it's probably
// better than nothing.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
for (int id : InputDevice.getDeviceIds()) {
InputDevice inputDev = InputDevice.getDevice(id);
if (inputDev == null) {
// Device was removed while looping
continue;
}
// Newer xpad versions use a special product ID (0x02a1) for controllers
// rather than copying the product ID of the dongle itself.
if (inputDev.getVendorId() == device.getVendorId() &&
(inputDev.getProductId() == device.getProductId() ||
inputDev.getProductId() == 0x02a1) &&
inputDev.getControllerNumber() > 0) {
controllerIndex = inputDev.getControllerNumber() - 1;
break;
}
// Newer xpad versions use a special product ID (0x02a1) for controllers
// rather than copying the product ID of the dongle itself.
if (inputDev.getVendorId() == device.getVendorId() &&
(inputDev.getProductId() == device.getProductId() ||
inputDev.getProductId() == 0x02a1) &&
inputDev.getControllerNumber() > 0) {
controllerIndex = inputDev.getControllerNumber() - 1;
break;
}
}
@ -142,4 +140,9 @@ public class Xbox360WirelessDongle extends AbstractController {
public void rumble(short lowFreqMotor, short highFreqMotor) {
// Unreachable.
}
@Override
public void rumbleTriggers(short leftTrigger, short rightTrigger) {
// Unreachable.
}
}

View File

@ -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;

View File

@ -185,6 +185,10 @@ public class VirtualControllerConfigurationLoader {
private static final int START_BACK_WIDTH = 12;
private static final int START_BACK_HEIGHT = 7;
// Make the Guide Menu be in the center of START and BACK menu
private static final int GUIDE_X = START_X-BACK_X;
private static final int GUIDE_Y = START_BACK_Y;
public static void createDefaultLayout(final VirtualController controller, final Context context) {
DisplayMetrics screen = context.getResources().getDisplayMetrics();
@ -333,6 +337,16 @@ public class VirtualControllerConfigurationLoader {
);
}
if(config.showGuideButton){
controller.addElement(createDigitalButton(VirtualControllerElement.EID_GDB,
ControllerPacket.SPECIAL_BUTTON_FLAG, 0, 1, "GUIDE", -1, controller, context),
screenScale(GUIDE_X, height)+ rightDisplacement,
screenScale(GUIDE_Y, height),
screenScale(START_BACK_WIDTH, height),
screenScale(START_BACK_HEIGHT, height)
);
}
controller.setOpacity(config.oscOpacity);
}

View File

@ -35,6 +35,7 @@ public abstract class VirtualControllerElement extends View {
public static final int EID_RS = 13;
public static final int EID_LSB = 14;
public static final int EID_RSB = 15;
public static final int EID_GDB = 16;
protected VirtualController virtualController;
protected final int elementId;

View File

@ -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 {
@ -374,9 +471,8 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, refreshRate);
}
// Adaptive playback can also be enabled by the whitelist on pre-KitKat devices
// so we don't fill these pre-KitKat
if (adaptivePlayback && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// Populate keys for adaptive playback
if (adaptivePlayback) {
videoFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, initialWidth);
videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, initialHeight);
}
@ -389,7 +485,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
// If the stream is HDR-capable, the decoder will detect transitions in color standards
// rather than us hardcoding them into the MediaFormat.
if (getActiveVideoFormat() != MoonBridge.VIDEO_FORMAT_H265_MAIN10) {
if ((getActiveVideoFormat() & MoonBridge.VIDEO_FORMAT_MASK_10BIT) == 0) {
// Set color format keys when not in HDR mode, since we know they won't change
videoFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
switch (getPreferredColorSpace()) {
@ -447,10 +543,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 +643,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 +977,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 +1395,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 +1412,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 +1434,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 +1451,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 +1467,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 +1748,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 +1791,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 +1876,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 +1901,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;

View File

@ -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,53 +591,42 @@ 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;
}
public static boolean decoderSupportsFusedIdrFrame(MediaCodecInfo decoderInfo, String mimeType) {
// If adaptive playback is supported, we can submit new CSD together with a keyframe
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) {
LimeLog.info("Decoder supports fused IDR frames (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
return false;
}
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
// Possibly enable adaptive playback on KitKat and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
LimeLog.info("Decoder blacklisted for adaptive playback");
return false;
}
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
LimeLog.info("Decoder blacklisted for adaptive playback");
return false;
}
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
// This will make getCapabilities() return that adaptive playback is supported
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{
// This will make getCapabilities() return that adaptive playback is supported
LimeLog.info("Adaptive playback supported (FEATURE_AdaptivePlayback)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
return false;
@ -691,14 +691,18 @@ public class MediaCodecHelper {
return isDecoderInList(refFrameInvalidationHevcPrefixes, decoderInfo.getName());
}
public static boolean decoderIsWhitelistedForHevc(MediaCodecInfo decoderInfo) {
// Google didn't have official support for HEVC (or more importantly, a CTS test) until
// Lollipop. I've seen some MediaTek devices on 4.4 crash when attempting to use HEVC,
// so I'm restricting HEVC usage to Lollipop and higher.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
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) {
//
// Software decoders are terrible and we never want to use them.
// We want to catch decoders like:
@ -737,20 +741,39 @@ public class MediaCodecHelper {
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() {
LinkedList<MediaCodecInfo> infoList = new LinkedList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
Collections.addAll(infoList, mcl.getCodecInfos());
}
else {
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
infoList.add(MediaCodecList.getCodecInfoAt(i));
}
}
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
Collections.addAll(infoList, mcl.getCodecInfos());
return infoList;
}

View File

@ -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;
}

View File

@ -190,6 +190,35 @@ public class ComputerDatabaseManager {
}
}
/**
* Get a computer by name
* NOTE: It is perfectly valid for multiple computers to have the same name,
* this function will only return the first one it finds.
* Consider using getComputerByUUID instead.
* @param name The name of the computer
* @see ComputerDatabaseManager#getComputerByUUID(String) for alternative.
* @return The computer details, or null if no computer with that name exists
*/
public ComputerDetails getComputerByName(String name) {
try (final Cursor c = computerDb.query(
COMPUTER_TABLE_NAME, null, COMPUTER_NAME_COLUMN_NAME+"=?",
new String[]{ name }, null, null, null)
) {
if (!c.moveToFirst()) {
// No matching computer
return null;
}
return getComputerFromCursor(c);
}
}
/**
* Get a computer by UUID
* @param uuid The UUID of the computer
* @see ComputerDatabaseManager#getComputerByName(String) for alternative.
* @return The computer details, or null if no computer with that UUID exists
*/
public ComputerDetails getComputerByUUID(String uuid) {
try (final Cursor c = computerDb.query(
COMPUTER_TABLE_NAME, null, COMPUTER_UUID_COLUMN_NAME+"=?",

View File

@ -341,57 +341,53 @@ public class ComputerManagerService extends Service {
// Acquire the default network lock since we could be changing global process state
defaultNetworkLock.lock();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// On Lollipop or later, we can bind our process to the underlying interface
// to ensure our STUN request goes out on that interface or not at all (which is
// preferable to getting a VPN endpoint address back).
Network[] networks = connMgr.getAllNetworks();
for (Network net : networks) {
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
if (netCaps != null) {
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// This network looks like an underlying multicast-capable transport,
// so let's guess that it's probably where our mDNS response came from.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (connMgr.bindProcessToNetwork(net)) {
boundToNetwork = true;
break;
}
}
else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
// On Lollipop or later, we can bind our process to the underlying interface
// to ensure our STUN request goes out on that interface or not at all (which is
// preferable to getting a VPN endpoint address back).
Network[] networks = connMgr.getAllNetworks();
for (Network net : networks) {
NetworkCapabilities netCaps = connMgr.getNetworkCapabilities(net);
if (netCaps != null) {
if (!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
!netCaps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
// This network looks like an underlying multicast-capable transport,
// so let's guess that it's probably where our mDNS response came from.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (connMgr.bindProcessToNetwork(net)) {
boundToNetwork = true;
break;
}
} else if (ConnectivityManager.setProcessDefaultNetwork(net)) {
boundToNetwork = true;
break;
}
}
}
}
}
// Perform the STUN request if we're not on a VPN or if we bound to a network
if (!activeNetworkIsVpn || boundToNetwork) {
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
if (stunResolvedAddress != null) {
// We don't know for sure what the external port is, so we will have to guess.
// When we contact the PC (if we haven't already), it will update the port.
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
// Perform the STUN request if we're not on a VPN or if we bound to a network
if (!activeNetworkIsVpn || boundToNetwork) {
String stunResolvedAddress = NvConnection.findExternalAddressForMdns("stun.moonlight-stream.org", 3478);
if (stunResolvedAddress != null) {
// We don't know for sure what the external port is, so we will have to guess.
// When we contact the PC (if we haven't already), it will update the port.
details.remoteAddress = new ComputerDetails.AddressTuple(stunResolvedAddress, details.guessExternalPort());
}
}
}
// Unbind from the network
if (boundToNetwork) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connMgr.bindProcessToNetwork(null);
// Unbind from the network
if (boundToNetwork) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connMgr.bindProcessToNetwork(null);
} else {
ConnectivityManager.setProcessDefaultNetwork(null);
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ConnectivityManager.setProcessDefaultNetwork(null);
}
}
// Unlock the network state
if (activeNetworkIsVpn) {
defaultNetworkLock.unlock();
// Unlock the network state
if (activeNetworkIsVpn) {
defaultNetworkLock.unlock();
}
}
}

View File

@ -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;

View File

@ -28,14 +28,8 @@ public class DiskAssetLoader {
public DiskAssetLoader(Context context) {
this.cacheDir = context.getCacheDir();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.isLowRamDevice =
((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
}
else {
// Use conservative low RAM behavior on very old devices
this.isLowRamDevice = true;
}
this.isLowRamDevice =
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice();
}
public boolean checkCacheExists(CachedAppAssetLoader.LoaderTuple tuple) {

View File

@ -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;

View File

@ -198,7 +198,7 @@ public class NvConnection {
}
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
switch (activeNetworkInfo.getType()) {
@ -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,15 +427,13 @@ 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.getHevcBitratePercentageMultiplier(),
context.streamConfig.getSupportedVideoFormats(),
context.streamConfig.getClientRefreshRateX100(),
context.streamConfig.getEncryptionFlags(),
context.riKey.getEncoded(), ib.array(),
context.videoCapabilities,
context.streamConfig.getColorSpace(),
@ -486,7 +486,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)
@ -497,17 +497,6 @@ public class NvConnection {
}
}
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 +527,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);

View File

@ -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);
}

View File

@ -22,9 +22,7 @@ public class StreamConfiguration {
private int maxPacketSize;
private int remote;
private MoonBridge.AudioConfiguration audioConfiguration;
private boolean supportsHevc;
private int hevcBitratePercentageMultiplier;
private boolean enableHdr;
private int supportedVideoFormats;
private int attachedGamepadMask;
private int encryptionFlags;
private int colorRange;
@ -85,16 +83,6 @@ public class StreamConfiguration {
return this;
}
public StreamConfiguration.Builder setHevcBitratePercentageMultiplier(int multiplier) {
config.hevcBitratePercentageMultiplier = multiplier;
return this;
}
public StreamConfiguration.Builder setEnableHdr(boolean enableHdr) {
config.enableHdr = enableHdr;
return this;
}
public StreamConfiguration.Builder setAttachedGamepadMask(int attachedGamepadMask) {
config.attachedGamepadMask = attachedGamepadMask;
return this;
@ -120,23 +108,13 @@ public class StreamConfiguration {
return this;
}
public StreamConfiguration.Builder setAudioEncryption(boolean enable) {
if (enable) {
config.encryptionFlags |= MoonBridge.ENCFLG_AUDIO;
}
else {
config.encryptionFlags &= ~MoonBridge.ENCFLG_AUDIO;
}
return this;
}
public StreamConfiguration.Builder setAudioConfiguration(MoonBridge.AudioConfiguration audioConfig) {
config.audioConfiguration = audioConfig;
return this;
}
public StreamConfiguration.Builder setHevcSupported(boolean supportsHevc) {
config.supportsHevc = supportsHevc;
public StreamConfiguration.Builder setSupportedVideoFormats(int supportedVideoFormats) {
config.supportedVideoFormats = supportedVideoFormats;
return this;
}
@ -168,8 +146,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 +198,8 @@ public class StreamConfiguration {
return audioConfiguration;
}
public boolean getHevcSupported() {
return supportsHevc;
}
public int getHevcBitratePercentageMultiplier() {
return hevcBitratePercentageMultiplier;
}
public boolean getEnableHdr() {
return enableHdr;
public int getSupportedVideoFormats() {
return supportedVideoFormats;
}
public int getAttachedGamepadMask() {
@ -245,10 +214,6 @@ public class StreamConfiguration {
return clientRefreshRateX100;
}
public int getEncryptionFlags() {
return encryptionFlags;
}
public int getColorRange() {
return colorRange;
}

View File

@ -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();

View File

@ -1,11 +1,11 @@
package com.limelight.nvstream.http;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
public interface LimelightCryptoProvider {
X509Certificate getClientCertificate();
RSAPrivateKey getClientPrivateKey();
PrivateKey getClientPrivateKey();
byte[] getPemEncodedClientCertificate();
String encodeBase64String(byte[] data);
}

View File

@ -50,6 +50,7 @@ import com.limelight.BuildConfig;
import com.limelight.LimeLog;
import com.limelight.nvstream.ConnectionContext;
import com.limelight.nvstream.http.PairingManager.PairState;
import com.limelight.nvstream.jni.MoonBridge;
import okhttp3.ConnectionPool;
import okhttp3.HttpUrl;
@ -402,16 +403,7 @@ public class NvHTTP {
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
// TLS 1.2 is not enabled by default prior to Android 5.0, so we'll need a custom
// SSLSocketFactory in order to connect to GFE 3.20.4 which requires TLSv1.2 or later.
// We don't just always use TLSv12SocketFactory because explicitly specifying TLS versions
// prevents later TLS versions from being negotiated even if client and server otherwise
// support them.
return client.newBuilder().sslSocketFactory(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?
sc.getSocketFactory() : new TLSv12SocketFactory(sc),
trustManager).build();
return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException(e);
}
@ -594,6 +586,12 @@ public class NvHTTP {
}
}
/**
* Get an app by ID
* @param appId The ID of the app
* @see #getAppByName(String) for alternative.
* @return app details, or null if no app with that ID exists
*/
public NvApp getAppById(int appId) throws IOException, XmlPullParserException {
LinkedList<NvApp> appList = getAppList();
for (NvApp appFromList : appList) {
@ -604,10 +602,15 @@ public class NvHTTP {
return null;
}
/* NOTE: Only use this function if you know what you're doing.
* It's totally valid to have two apps named the same thing,
* or even nothing at all! Look apps up by ID if at all possible
* using the above function */
/**
* Get an app by name
* NOTE: It is perfectly valid for multiple apps to have the same name,
* this function will only return the first one it finds.
* Consider using getAppById instead.
* @param appName The name of the app
* @see #getAppById(int) for alternative.
* @return app details, or null if no app with that name exists
*/
public NvApp getAppByName(String appName) throws IOException, XmlPullParserException {
LinkedList<NvApp> appList = getAppList();
for (NvApp appFromList : appList) {
@ -784,7 +787,8 @@ public class NvHTTP {
"&surroundAudioInfo=" + context.streamConfig.getAudioConfiguration().getSurroundAudioInfo() +
"&remoteControllersBitmap=" + context.streamConfig.getAttachedGamepadMask() +
"&gcmap=" + context.streamConfig.getAttachedGamepadMask() +
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0));
"&gcpersist="+(context.streamConfig.getPersistGamepadsAfterDisconnect() ? 1 : 0) +
MoonBridge.getLaunchUrlQueryParameters());
if ((verb.equals("launch") && !getXmlString(xmlStr, "gamesession", true).equals("0") ||
(verb.equals("resume") && !getXmlString(xmlStr, "resume", true).equals("0")))) {
// sessionUrl0 will be missing for older GFE versions
@ -812,62 +816,4 @@ public class NvHTTP {
return true;
}
// Based on example code from https://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/
private static class TLSv12SocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSv12SocketFactory(SSLContext context) {
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSv12OnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSv12OnSocket(Socket socket) {
if (socket instanceof SSLSocket) {
// TLS 1.2 is not enabled by default prior to Android 5.0. We must enable it
// explicitly to ensure we can communicate with GFE 3.20.4 which blocks TLS 1.0.
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.2"});
}
return socket;
}
}
}

View File

@ -99,9 +99,20 @@ public class PairingManager {
return saltedPin;
}
private static Signature getSha256SignatureInstanceForKey(Key key) throws NoSuchAlgorithmException {
switch (key.getAlgorithm()) {
case "RSA":
return Signature.getInstance("SHA256withRSA");
case "EC":
return Signature.getInstance("SHA256withECDSA");
default:
throw new NoSuchAlgorithmException("Unhandled key algorithm: " + key.getAlgorithm());
}
}
private static boolean verifySignature(byte[] data, byte[] signature, Certificate cert) {
try {
Signature sig = Signature.getInstance("SHA256withRSA");
Signature sig = PairingManager.getSha256SignatureInstanceForKey(cert.getPublicKey());
sig.initVerify(cert.getPublicKey());
sig.update(data);
return sig.verify(signature);
@ -113,12 +124,10 @@ public class PairingManager {
private static byte[] signData(byte[] data, PrivateKey key) {
try {
Signature sig = Signature.getInstance("SHA256withRSA");
Signature sig = PairingManager.getSha256SignatureInstanceForKey(key);
sig.initSign(key);
sig.update(data);
byte[] signature = new byte[256];
sig.sign(signature, 0, signature.length);
return signature;
return sig.sign();
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
e.printStackTrace();
throw new RuntimeException(e);
@ -245,7 +254,7 @@ public class PairingManager {
// Get the server's signed secret
byte[] serverSecretResp = hexToBytes(NvHTTP.getXmlString(secretResp, "pairingsecret", true));
byte[] serverSecret = Arrays.copyOfRange(serverSecretResp, 0, 16);
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, 272);
byte[] serverSignature = Arrays.copyOfRange(serverSecretResp, 16, serverSecretResp.length);
// Ensure the authenticity of the data
if (!verifySignature(serverSecret, serverSignature, serverCert)) {

View File

@ -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
}

View File

@ -14,13 +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 ENCFLG_NONE = 0;
public static final int ENCFLG_AUDIO = 1;
public static final int ENCFLG_ALL = 0xFFFFFFFF;
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 BUFFER_TYPE_PICDATA = 0;
public static final int BUFFER_TYPE_SPS = 1;
@ -40,6 +40,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 +76,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 +216,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 +308,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,14 +339,11 @@ 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 hevcBitratePercentageMultiplier,
int audioConfiguration, int supportedVideoFormats,
int clientRefreshRateX100,
int encryptionFlags,
byte[] riAesKey, byte[] riAesIv,
int videoCapabilities,
int colorSpace, int colorRange);
@ -297,15 +361,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 +408,13 @@ public class MoonBridge {
// The RTT is in the top 32 bits, and the RTT variance is in the bottom 32 bits
public static native long getEstimatedRttInfo();
public static native String getLaunchUrlQueryParameters();
public static native byte guessControllerType(int vendorId, int productId);
public static native boolean guessControllerHasPaddles(int vendorId, int productId);
public static native boolean guessControllerHasShareButton(int vendorId, int productId);
public static native void init();
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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;
}
}

View File

@ -13,7 +13,6 @@ import com.limelight.R;
import static com.limelight.binding.input.virtual_controller.VirtualControllerConfigurationLoader.OSC_PREFERENCE;
public class ConfirmDeleteOscPreference extends DialogPreference {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@ -26,7 +25,6 @@ public class ConfirmDeleteOscPreference extends DialogPreference {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ConfirmDeleteOscPreference(Context context) {
super(context);
}

View File

@ -11,12 +11,10 @@ import android.provider.Settings;
import android.util.AttributeSet;
public class LanguagePreference extends ListPreference {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public LanguagePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

View File

@ -10,6 +10,19 @@ import android.view.Display;
import com.limelight.nvstream.jni.MoonBridge;
public class PreferenceConfiguration {
public enum FormatOption {
AUTO,
FORCE_AV1,
FORCE_HEVC,
FORCE_H264,
};
public enum AnalogStickForScrolling {
NONE,
RIGHT,
LEFT
}
private static final String LEGACY_RES_FPS_PREF_STRING = "list_resolution_fps";
private static final String LEGACY_ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround";
@ -31,16 +44,19 @@ public class PreferenceConfiguration {
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
private static final String SHOW_GUIDE_BUTTON_PREF_STRING = "checkbox_show_guide_button";
private static final String LEGACY_DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
private static final String ENABLE_HDR_PREF_STRING = "checkbox_enable_hdr";
private static final String ENABLE_PIP_PREF_STRING = "checkbox_enable_pip";
private static final String ENABLE_PERF_OVERLAY_STRING = "checkbox_enable_perf_overlay";
private static final String BIND_ALL_USB_STRING = "checkbox_usb_bind_all";
private static final String MOUSE_EMULATION_STRING = "checkbox_mouse_emulation";
private static final String ANALOG_SCROLLING_PREF_STRING = "analog_scrolling";
private static final String MOUSE_NAV_BUTTONS_STRING = "checkbox_mouse_nav_buttons";
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
private static final String VIBRATE_OSC_PREF_STRING = "checkbox_vibrate_osc";
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
private static final String VIBRATE_FALLBACK_STRENGTH_PREF_STRING = "seekbar_vibrate_fallback_strength";
private static final String FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
private static final String LATENCY_TOAST_PREF_STRING = "checkbox_enable_post_stream_toast";
@ -49,6 +65,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,17 +81,21 @@ 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 SHOW_GUIDE_BUTTON_DEFAULT = true;
private static final boolean DEFAULT_ENABLE_HDR = false;
private static final boolean DEFAULT_ENABLE_PIP = false;
private static final boolean DEFAULT_ENABLE_PERF_OVERLAY = false;
private static final boolean DEFAULT_BIND_ALL_USB = false;
private static final boolean DEFAULT_MOUSE_EMULATION = true;
private static final String DEFAULT_ANALOG_STICK_FOR_SCROLLING = "right";
private static final boolean DEFAULT_MOUSE_NAV_BUTTONS = false;
private static final boolean DEFAULT_UNLOCK_FPS = false;
private static final boolean DEFAULT_VIBRATE_OSC = true;
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
private static final int DEFAULT_VIBRATE_FALLBACK_STRENGTH = 100;
private static final boolean DEFAULT_FLIP_FACE_BUTTONS = false;
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
@ -82,10 +105,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 +124,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;
@ -110,16 +132,19 @@ public class PreferenceConfiguration {
public boolean smallIconMode, multiController, usbDriver, flipFaceButtons;
public boolean onscreenController;
public boolean onlyL3R3;
public boolean showGuideButton;
public boolean enableHdr;
public boolean enablePip;
public boolean enablePerfOverlay;
public boolean enableLatencyToast;
public boolean bindAllUsb;
public boolean mouseEmulation;
public AnalogStickForScrolling analogStickForScrolling;
public boolean mouseNavButtons;
public boolean unlockFps;
public boolean vibrateOsc;
public boolean vibrateFallbackToDevice;
public int vibrateFallbackToDeviceStrength;
public boolean touchscreenTrackpad;
public MoonBridge.AudioConfiguration audioConfiguration;
public int framePacing;
@ -127,6 +152,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 +261,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 +346,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;
}
}
@ -339,6 +399,21 @@ public class PreferenceConfiguration {
}
}
private static AnalogStickForScrolling getAnalogStickForScrollingValue(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String str = prefs.getString(ANALOG_SCROLLING_PREF_STRING, DEFAULT_ANALOG_STICK_FOR_SCROLLING);
if (str.equals("right")) {
return AnalogStickForScrolling.RIGHT;
}
else if (str.equals("left")) {
return AnalogStickForScrolling.LEFT;
}
else {
return AnalogStickForScrolling.NONE;
}
}
public static void resetStreamingSettings(Context context) {
// We consider resolution, FPS, bitrate, HDR, and video format as "streaming settings" here
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@ -458,6 +533,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) {
@ -478,6 +562,8 @@ public class PreferenceConfiguration {
config.videoFormat = getVideoFormatValue(context);
config.framePacing = getFramePacingValue(context);
config.analogStickForScrolling = getAnalogStickForScrollingValue(context);
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
config.oscOpacity = prefs.getInt(OSC_OPACITY_PREF_STRING, DEFAULT_OPACITY);
@ -494,6 +580,7 @@ public class PreferenceConfiguration {
config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER);
config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT);
config.onlyL3R3 = prefs.getBoolean(ONLY_L3_R3_PREF_STRING, ONLY_L3_R3_DEFAULT);
config.showGuideButton = prefs.getBoolean(SHOW_GUIDE_BUTTON_PREF_STRING, SHOW_GUIDE_BUTTON_DEFAULT);
config.enableHdr = prefs.getBoolean(ENABLE_HDR_PREF_STRING, DEFAULT_ENABLE_HDR) && !isShieldAtvFirmwareWithBrokenHdr();
config.enablePip = prefs.getBoolean(ENABLE_PIP_PREF_STRING, DEFAULT_ENABLE_PIP);
config.enablePerfOverlay = prefs.getBoolean(ENABLE_PERF_OVERLAY_STRING, DEFAULT_ENABLE_PERF_OVERLAY);
@ -503,6 +590,7 @@ public class PreferenceConfiguration {
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
config.vibrateFallbackToDeviceStrength = prefs.getInt(VIBRATE_FALLBACK_STRENGTH_PREF_STRING, DEFAULT_VIBRATE_FALLBACK_STRENGTH);
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
config.enableLatencyToast = prefs.getBoolean(LATENCY_TOAST_PREF_STRING, DEFAULT_LATENCY_TOAST);
@ -510,6 +598,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;
}

View File

@ -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,30 @@ public class StreamSettings extends Activity {
addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false);
}
private void addNativeFrameRateEntry(float framerate) {
int frameRateRounded = Math.round(framerate);
if (frameRateRounded == 0) {
return;
}
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.FPS_PREF_STRING);
String fpsValue = Integer.toString(frameRateRounded);
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 +293,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 ||
@ -283,26 +333,29 @@ public class StreamSettings extends Activity {
(PreferenceCategory) findPreference("category_help");
screen.removePreference(category);
}*/
PreferenceCategory category_gamepad_settings =
(PreferenceCategory) findPreference("category_gamepad_settings");
// Remove the vibration options if the device can't vibrate
if (!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
PreferenceCategory category =
(PreferenceCategory) findPreference("category_input_settings");
category.removePreference(findPreference("checkbox_vibrate_fallback"));
category_gamepad_settings.removePreference(findPreference("checkbox_vibrate_fallback"));
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
// The entire OSC category may have already been removed by the touchscreen check above
category = (PreferenceCategory) findPreference("category_onscreen_controls");
PreferenceCategory category = (PreferenceCategory) findPreference("category_onscreen_controls");
if (category != null) {
category.removePreference(findPreference("checkbox_vibrate_osc"));
}
}
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O ||
!((Vibrator)getActivity().getSystemService(Context.VIBRATOR_SERVICE)).hasAmplitudeControl() ) {
// Remove the vibration strength selector of the device doesn't have amplitude control
category_gamepad_settings.removePreference(findPreference("seekbar_vibrate_fallback_strength"));
}
int maxSupportedFps = 0;
Display display = getActivity().getWindowManager().getDefaultDisplay();
float maxSupportedFps = display.getRefreshRate();
// Hide non-supported resolution/FPS combinations
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Display display = getActivity().getWindowManager().getDefaultDisplay();
int maxSupportedResW = 0;
// Add a native resolution with any insets included for users that don't want content
@ -370,7 +423,7 @@ public class StreamSettings extends Activity {
}
if (candidate.getRefreshRate() > maxSupportedFps) {
maxSupportedFps = (int)candidate.getRefreshRate();
maxSupportedFps = candidate.getRefreshRate();
}
}
@ -458,30 +511,15 @@ public class StreamSettings extends Activity {
// Never remove 720p
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// On Android 4.2 and later, we can get the true metrics via the
// getRealMetrics() function (unlike the lies that getWidth() and getHeight()
// tell to us).
else {
// We can get the true metrics via the getRealMetrics() function (unlike the lies
// that getWidth() and getHeight() tell to us).
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
display.getRealMetrics(metrics);
int width = Math.max(metrics.widthPixels, metrics.heightPixels);
int height = Math.min(metrics.widthPixels, metrics.heightPixels);
addNativeResolutionEntries(width, height, false);
}
else {
// On Android 4.1, we have to resort to reflection to invoke hidden APIs
// to get the real screen dimensions.
Display display = getActivity().getWindowManager().getDefaultDisplay();
try {
Method getRawHeightFunc = Display.class.getMethod("getRawHeight");
Method getRawWidthFunc = Display.class.getMethod("getRawWidth");
int width = (Integer) getRawWidthFunc.invoke(display);
int height = (Integer) getRawHeightFunc.invoke(display);
addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false);
} catch (Exception e) {
e.printStackTrace();
}
}
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
// We give some extra room in case the FPS is rounded down
@ -508,50 +546,31 @@ public class StreamSettings extends Activity {
}
// Never remove 30 FPS or 60 FPS
}
// Android L introduces proper 7.1 surround sound support. Remove the 7.1 option
// for earlier versions of Android to prevent AudioTrack initialization issues.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
LimeLog.info("Excluding 7.1 surround sound option based on OS");
removeValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "71", new Runnable() {
@Override
public void run() {
setValue(PreferenceConfiguration.AUDIO_CONFIG_PREF_STRING, "51");
}
});
}
addNativeFrameRateEntry(maxSupportedFps);
// Android L introduces the drop duplicate behavior of releaseOutputBuffer()
// that the unlock FPS option relies on to not massively increase latency.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
LimeLog.info("Excluding unlock FPS toggle based on OS");
PreferenceCategory category =
(PreferenceCategory) findPreference("category_advanced_settings");
category.removePreference(findPreference("checkbox_unlock_fps"));
}
else {
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// HACK: We need to let the preference change succeed before reinitializing to ensure
// it's reflected in the new layout.
final Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
// Ensure the activity is still open when this timeout expires
StreamSettings settingsActivity = (StreamSettings)SettingsFragment.this.getActivity();
if (settingsActivity != null) {
settingsActivity.reloadSettings();
}
findPreference(PreferenceConfiguration.UNLOCK_FPS_STRING).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// HACK: We need to let the preference change succeed before reinitializing to ensure
// it's reflected in the new layout.
final Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
// Ensure the activity is still open when this timeout expires
StreamSettings settingsActivity = (StreamSettings) SettingsFragment.this.getActivity();
if (settingsActivity != null) {
settingsActivity.reloadSettings();
}
}, 500);
}
}, 500);
// Allow the original preference change to take place
return true;
}
});
}
// Allow the original preference change to take place
return true;
}
});
// Remove HDR preference for devices below Nougat
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
@ -561,7 +580,6 @@ public class StreamSettings extends Activity {
category.removePreference(findPreference("checkbox_enable_hdr"));
}
else {
Display display = getActivity().getWindowManager().getDefaultDisplay();
Display.HdrCapabilities hdrCaps = display.getHdrCapabilities();
// We must now ensure our display is compatible with HDR10
@ -571,6 +589,7 @@ public class StreamSettings extends Activity {
for (int hdrType : hdrCaps.getSupportedHdrTypes()) {
if (hdrType == Display.HdrCapabilities.HDR_TYPE_HDR10) {
foundHdr10 = true;
break;
}
}
}
@ -632,6 +651,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);

View File

@ -21,7 +21,6 @@ public class WebLauncherPreference extends Preference {
initialize(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WebLauncherPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(attrs);

View File

@ -30,6 +30,6 @@ public class AdapterFragment extends Fragment {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
callbacks.receiveAbsListView((AbsListView) getView().findViewById(R.id.fragmentView));
callbacks.receiveAbsListView(getView().findViewById(R.id.fragmentView));
}
}

View File

@ -30,7 +30,6 @@ public class StreamView extends SurfaceView {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public StreamView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View File

@ -20,7 +20,7 @@ public class NetHelper {
}
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
return activeNetworkInfo.getType() == ConnectivityManager.TYPE_VPN;

View File

@ -2,15 +2,12 @@ package com.limelight.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Build;
import com.limelight.AppView;
import com.limelight.ShortcutTrampoline;
import com.limelight.R;
import com.limelight.nvstream.http.ComputerDetails;
import com.limelight.nvstream.http.NvApp;

View File

@ -53,7 +53,11 @@ public class TvChannelHelper {
intent.putExtra(TvContract.EXTRA_CHANNEL_ID, getChannelId(computer.uuid));
try {
context.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
} catch (Exception ignored) {
// ActivityNotFoundException is the only officially documented
// exception that can result from this call. However some buggy
// devices throw others.
// See https://github.com/moonlight-stream/moonlight-android/issues/1302
}
}
}

View File

@ -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.

View File

@ -1,4 +1,7 @@
# Application.mk for Moonlight
# Our minimum version is Android 4.1
APP_PLATFORM := android-16
# Our minimum version is Android 5.0
APP_PLATFORM := android-21
# We support 16KB pages
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true

View File

@ -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 \
@ -54,7 +55,11 @@ endif
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto
LOCAL_STATIC_LIBRARIES := libopus libssl libcrypto cpufeatures
LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
LOCAL_BRANCH_PROTECTION := standard
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)

View File

@ -0,0 +1 @@
Static libraries were built from https://github.com/cgutman/moonlight-mobile-deps using AppVeyor CI

View File

@ -8,6 +8,8 @@
#include <opus_multistream.h>
#include <android/log.h>
#include <cpu-features.h>
static OpusMSDecoder* Decoder;
static OPUS_MULTISTREAM_CONFIGURATION OpusConfig;
@ -33,6 +35,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 +85,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 +99,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 +167,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 +188,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 +355,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,19 +423,42 @@ static CONNECTION_LISTENER_CALLBACKS BridgeConnListenerCallbacks = {
.rumble = BridgeClRumble,
.connectionStatusUpdate = BridgeClConnectionStatusUpdate,
.setHdrMode = BridgeClSetHdrMode,
.rumbleTriggers = BridgeClRumbleTriggers,
.setMotionEventState = BridgeClSetMotionEventState,
.setControllerLED = BridgeClSetControllerLED,
};
static bool
hasFastAes() {
if (android_getCpuCount() <= 2) {
return false;
}
switch (android_getCpuFamily()) {
case ANDROID_CPU_FAMILY_ARM:
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_AES);
case ANDROID_CPU_FAMILY_ARM64:
return !!(android_getCpuFeatures() & ANDROID_CPU_ARM64_FEATURE_AES);
case ANDROID_CPU_FAMILY_X86:
case ANDROID_CPU_FAMILY_X86_64:
return !!(android_getCpuFeatures() & ANDROID_CPU_X86_FEATURE_AES_NI);
case ANDROID_CPU_FAMILY_MIPS:
case ANDROID_CPU_FAMILY_MIPS64:
return false;
default:
// Assume new architectures will all have crypto acceleration (RISC-V will)
return true;
}
}
JNIEXPORT jint JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass clazz,
jstring address, jstring appVersion, jstring gfeVersion,
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 hevcBitratePercentageMultiplier,
jint audioConfiguration, jint supportedVideoFormats,
jint clientRefreshRateX100,
jint encryptionFlags,
jbyteArray riAesKey, jbyteArray riAesIv,
jint videoCapabilities,
jint colorSpace, jint colorRange) {
@ -402,6 +467,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,11 +477,9 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
.packetSize = packetSize,
.streamingRemotely = streamingRemotely,
.audioConfiguration = audioConfiguration,
.supportsHevc = supportsHevc,
.enableHdr = enableHdr,
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
.supportedVideoFormats = supportedVideoFormats,
.clientRefreshRateX100 = clientRefreshRateX100,
.encryptionFlags = encryptionFlags,
.encryptionFlags = ENCFLG_AUDIO,
.colorSpace = colorSpace,
.colorRange = colorRange
};
@ -430,6 +494,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jclass c
BridgeVideoRendererCallbacks.capabilities = videoCapabilities;
// Enable all encryption features if the platform has fast AES support
if (hasFastAes()) {
streamConfig.encryptionFlags = ENCFLG_ALL;
}
int ret = LiStartConnection(&serverInfo,
&streamConfig,
&BridgeConnListenerCallbacks,

View File

@ -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)
};

View File

@ -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

View File

@ -1,100 +0,0 @@
ANDROID_API_TARGET=21
PARALLEL_JOBS=$(nproc)
rm -r ./android
mkdir android
function build_one
{
PREFIX=$(pwd)/android/$CPU
SYSROOT=$NDK/platforms/android-$ANDROID_API_TARGET/arch-$SYSROOT_CPU
TOOLCHAIN_PATH=$NDK/toolchains/$TOOLCHAIN_DIR/prebuilt/linux-x86_64
export PATH=$PATH:$TOOLCHAIN_PATH/bin
./configure \
--build=x86_64-unknown-linux-gnu \
--host=$TOOLCHAIN_BIN_PREFIX \
--target=$TOOLCHAIN_BIN_PREFIX \
CFLAGS="--sysroot=$SYSROOT -O2 $ADDI_CFLAGS" \
$ADDI_CONFIGURE_FLAGS
make clean
make -j$PARALLEL_JOBS
mkdir android/$CPU
cp .libs/libopus.a android/$CPU
}
function build_mips
{
CPU=mips
SYSROOT_CPU=mips
TOOLCHAIN_BIN_PREFIX=mipsel-linux-android
TOOLCHAIN_DIR=mipsel-linux-android-4.9
ADDI_CFLAGS="-mips32 -mhard-float -EL -mno-dsp"
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
build_one
}
function build_mips64
{
CPU=mips64
SYSROOT_CPU=mips64
TOOLCHAIN_BIN_PREFIX=mips64el-linux-android
TOOLCHAIN_DIR=mips64el-linux-android-4.9
ADDI_CFLAGS="-mips64r6"
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point
build_one
}
function build_x86
{
CPU=x86
SYSROOT_CPU=x86
TOOLCHAIN_BIN_PREFIX=i686-linux-android
TOOLCHAIN_DIR=x86-4.9
ADDI_CFLAGS="-march=i686 -mtune=atom -mstackrealign -msse -msse2 -msse3 -mssse3 -mfpmath=sse -m32"
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
build_one
}
function build_x86_64
{
CPU=x86_64
SYSROOT_CPU=x86_64
TOOLCHAIN_BIN_PREFIX=x86_64-linux-android
TOOLCHAIN_DIR=x86_64-4.9
ADDI_CFLAGS="-msse -msse2 -msse3 -mssse3 -msse4 -msse4.1 -msse4.2 -mpopcnt -m64"
ADDI_CONFIGURE_FLAGS="" # floating point for SSE optimizations
build_one
}
function build_armv7
{
CPU=arm
SYSROOT_CPU=arm
TOOLCHAIN_BIN_PREFIX=arm-linux-androideabi
TOOLCHAIN_DIR=arm-linux-androideabi-4.9
ADDI_CFLAGS="-marm -mfpu=vfpv3-d16"
ADDI_LDFLAGS=""
ADDI_CONFIGURE_FLAGS="--enable-fixed-point" # fixed point for NEON, EDSP, Media
build_one
}
# ARMv8 doesn't currently have assembly in the opus project. We still use fixed point
# anyway in the hopes that it will be more performant even without assembly.
function build_armv8
{
CPU=aarch64
SYSROOT_CPU=arm64
TOOLCHAIN_BIN_PREFIX=aarch64-linux-android
TOOLCHAIN_DIR=aarch64-linux-android-4.9
ADDI_CFLAGS=""
ADDI_LDFLAGS=""
ADDI_CONFIGURE_FLAGS="--enable-fixed-point"
build_one
}
build_mips
build_mips64
build_x86
build_x86_64
build_armv7
build_armv8

View File

@ -103,7 +103,7 @@ extern "C" {
* @endcode
*
* where opus_encoder_get_size() returns the required size for the encoder state. Note that
* future versions of this code may change the size, so no assuptions should be made about it.
* future versions of this code may change the size, so no assumptions should be made about it.
*
* The encoder state is always continuous in memory and only a shallow copy is sufficient
* to copy it (e.g. memcpy())
@ -198,7 +198,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @param [in] application <tt>int</tt>: Coding mode (one of @ref OPUS_APPLICATION_VOIP, @ref OPUS_APPLICATION_AUDIO, or @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
* can switch to a lower audio bandwidth or number of channels if the bitrate
@ -222,7 +222,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @param [in] application <tt>int</tt>: Coding mode (one of OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO, or OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @retval #OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_encoder_init(
@ -357,7 +357,7 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
* error = opus_decoder_init(dec, Fs, channels);
* @endcode
* where opus_decoder_get_size() returns the required size for the decoder state. Note that
* future versions of this code may change the size, so no assuptions should be made about it.
* future versions of this code may change the size, so no assumptions should be made about it.
*
* The decoder state is always continuous in memory and only a shallow copy is sufficient
* to copy it (e.g. memcpy())
@ -398,6 +398,21 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
*/
typedef struct OpusDecoder OpusDecoder;
/** Opus DRED decoder.
* This contains the complete state of an Opus DRED decoder.
* It is position independent and can be freely copied.
* @see opus_dred_decoder_create,opus_dred_decoder_init
*/
typedef struct OpusDREDDecoder OpusDREDDecoder;
/** Opus DRED state.
* This contains the complete state of an Opus DRED packet.
* It is position independent and can be freely copied.
* @see opus_dred_create,opus_dred_init
*/
typedef struct OpusDRED OpusDRED;
/** Gets the size of an <code>OpusDecoder</code> structure.
* @param [in] channels <tt>int</tt>: Number of channels.
* This must be 1 or 2.
@ -511,6 +526,101 @@ OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NON
*/
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
/** Gets the size of an <code>OpusDREDDecoder</code> structure.
* @returns The size in bytes.
*/
OPUS_EXPORT int opus_dred_decoder_get_size(void);
/** Allocates and initializes an OpusDREDDecoder state.
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_EXPORT OpusDREDDecoder *opus_dred_decoder_create(int *error);
/** Initializes an <code>OpusDREDDecoder</code> state.
* @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be initialized.
*/
OPUS_EXPORT int opus_dred_decoder_init(OpusDREDDecoder *dec);
/** Frees an <code>OpusDREDDecoder</code> allocated by opus_dred_decoder_create().
* @param[in] dec <tt>OpusDREDDecoder*</tt>: State to be freed.
*/
OPUS_EXPORT void opus_dred_decoder_destroy(OpusDREDDecoder *dec);
/** Perform a CTL function on an Opus DRED decoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @param dred_dec <tt>OpusDREDDecoder*</tt>: DRED Decoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls or
* @ref opus_decoderctls.
* @see opus_genericctls
* @see opus_decoderctls
*/
OPUS_EXPORT int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...);
/** Gets the size of an <code>OpusDRED</code> structure.
* @returns The size in bytes.
*/
OPUS_EXPORT int opus_dred_get_size(void);
/** Allocates and initializes a DRED state.
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_EXPORT OpusDRED *opus_dred_alloc(int *error);
/** Frees an <code>OpusDRED</code> allocated by opus_dred_create().
* @param[in] dec <tt>OpusDRED*</tt>: State to be freed.
*/
OPUS_EXPORT void opus_dred_free(OpusDRED *dec);
/** Decode an Opus DRED packet.
* @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @param [in] data <tt>char*</tt>: Input payload
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
* @param [in] max_dred_samples <tt>opus_int32</tt>: Maximum number of DRED samples that may be needed (if available in the packet).
* @param [in] sampling_rate <tt>opus_int32</tt>: Sampling rate used for max_dred_samples argument. Needs not match the actual sampling rate of the decoder.
* @param [out] dred_end <tt>opus_int32*</tt>: Number of non-encoded (silence) samples between the DRED timestamp and the last DRED sample.
* @param [in] defer_processing <tt>int</tt>: Flag (0 or 1). If set to one, the CPU-intensive part of the DRED decoding is deferred until opus_dred_process() is called.
* @returns Offset (positive) of the first decoded DRED samples, zero if no DRED is present, or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing) OPUS_ARG_NONNULL(1);
/** Finish decoding an Opus DRED packet. The function only needs to be called if opus_dred_parse() was called with defer_processing=1.
* The source and destination will often be the same DRED state.
* @param [in] dred_dec <tt>OpusDRED*</tt>: DRED Decoder state
* @param [in] src <tt>OpusDRED*</tt>: Source DRED state to start the processing from.
* @param [out] dst <tt>OpusDRED*</tt>: Destination DRED state to store the updated state after processing.
* @returns @ref opus_errorcodes
*/
OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
/** Decode audio from an Opus DRED packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel to decode in \a pcm.
* frame_size <b>must</b> be a multiple of 2.5 ms.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
/** Decode audio from an Opus DRED packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(float)
* @param [in] frame_size Number of samples per channel to decode in \a pcm.
* frame_size <b>must</b> be a multiple of 2.5 ms.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size);
/** Parse an opus packet into one or more frames.
* Opus_decode will perform this operation internally so most applications do
* not need to use this function.
@ -583,6 +693,14 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
/** Checks whether an Opus packet has LBRR.
* @param [in] packet <tt>char*</tt>: Opus packet
* @param [in] len <tt>opus_int32</tt>: Length of packet
* @returns 1 is LBRR is present, 0 otherwise
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len);
/** Gets the number of samples of an Opus packet.
* @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
* @param [in] packet <tt>char*</tt>: Opus packet

View File

@ -1,342 +0,0 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008-2012 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file opus_custom.h
@brief Opus-Custom reference implementation API
*/
#ifndef OPUS_CUSTOM_H
#define OPUS_CUSTOM_H
#include "opus_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CUSTOM_MODES
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
#else
# define OPUS_CUSTOM_EXPORT
# ifdef OPUS_BUILD
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
# else
# define OPUS_CUSTOM_EXPORT_STATIC
# endif
#endif
/** @defgroup opus_custom Opus Custom
* @{
* Opus Custom is an optional part of the Opus specification and
* reference implementation which uses a distinct API from the regular
* API and supports frame sizes that are not normally supported.\ Use
* of Opus Custom is discouraged for all but very special applications
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
* (for either complexity or latency reasons) and where interoperability
* is less important.
*
* In addition to the interoperability limitations the use of Opus custom
* disables a substantial chunk of the codec and generally lowers the
* quality available at a given bitrate. Normally when an application needs
* a different frame size from the codec it should buffer to match the
* sizes but this adds a small amount of delay which may be important
* in some very low latency applications. Some transports (especially
* constant rate RF transports) may also work best with frames of
* particular durations.
*
* Libopus only supports custom modes if they are enabled at compile time.
*
* The Opus Custom API is similar to the regular API but the
* @ref opus_encoder_create and @ref opus_decoder_create calls take
* an additional mode parameter which is a structure produced by
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
* must create a mode using the same sample rate (fs) and frame size
* (frame size) so these parameters must either be signaled out of band
* or fixed in a particular implementation.
*
* Similar to regular Opus the custom modes support on the fly frame size
* switching, but the sizes available depend on the particular frame size in
* use. For some initial frame sizes on a single on the fly size is available.
*/
/** Contains the state of an encoder. One encoder state is needed
for each stream. It is initialized once at the beginning of the
stream. Do *not* re-initialize the state for every frame.
@brief Encoder state
*/
typedef struct OpusCustomEncoder OpusCustomEncoder;
/** State of the decoder. One decoder state is needed for each stream.
It is initialized once at the beginning of the stream. Do *not*
re-initialize the state for every frame.
@brief Decoder state
*/
typedef struct OpusCustomDecoder OpusCustomDecoder;
/** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialized
with exactly the same mode, otherwise the output will be
corrupted.
@brief Mode configuration
*/
typedef struct OpusCustomMode OpusCustomMode;
/** Creates a new mode struct. This will be passed to an encoder or
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
* decoders that use it are destroyed as well.
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
* @return A newly created mode
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
/** Destroys a mode struct. Only call this after all encoders and
* decoders using this mode are destroyed as well.
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
/* Encoder */
/** Gets the size of an OpusCustomEncoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
# ifdef CUSTOM_MODES
/** Initializes a previously allocated encoder state
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
OpusCustomEncoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
# endif
#endif
/** Creates a new encoder state. Each stream needs its own encoder
* state (can't be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created encoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an encoder state.
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynamic range. There must be exactly
* frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
OpusCustomEncoder *st,
const float *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
* There must be exactly frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
OpusCustomEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom encoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_encoderctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
/* Decoder */
/** Gets the size of an OpusCustomDecoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
/** Initializes a previously allocated decoder state
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
OpusCustomDecoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
#endif
/** Creates a new decoder state. Each stream needs its own decoder state (can't
* be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
* stream (must be the same characteristics as used for the encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created decoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an decoder state.
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
/** Decode an opus custom frame with floating point output
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(float)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
float *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an opus custom frame
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
opus_int16 *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom decoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_genericctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_CUSTOM_H */

View File

@ -64,7 +64,7 @@ extern "C" {
/**Export control for opus functions */
#ifndef OPUS_EXPORT
# if defined(WIN32)
# if defined(_WIN32)
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
# define OPUS_EXPORT __declspec(dllexport)
# else
@ -168,15 +168,33 @@ extern "C" {
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
#define OPUS_GET_IN_DTX_REQUEST 4049
#define OPUS_SET_DRED_DURATION_REQUEST 4050
#define OPUS_GET_DRED_DURATION_REQUEST 4051
#define OPUS_SET_DNN_BLOB_REQUEST 4052
/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */
/** Defines for the presence of extended APIs. */
#define OPUS_HAVE_OPUS_PROJECTION_H
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
#ifdef DISABLE_PTR_CHECK
/* Disable checks to prevent ubsan from complaining about NULL checks
in test_opus_api. */
#define __opus_check_int_ptr(ptr) (ptr)
#define __opus_check_uint_ptr(ptr) (ptr)
#define __opus_check_uint8_ptr(ptr) (ptr)
#define __opus_check_val16_ptr(ptr) (ptr)
#define __opus_check_void_ptr(ptr) (ptr)
#else
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
#define __opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr)))
#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
#define __opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x))
#endif
/** @endcond */
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
@ -481,7 +499,8 @@ extern "C" {
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
* <dt>1</dt><dd>Enable inband FEC.</dd>
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
@ -490,7 +509,8 @@ extern "C" {
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
* <dt>1</dt><dd>Inband FEC enabled.</dd>
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
@ -617,6 +637,18 @@ extern "C" {
* @hideinitializer */
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
* @hideinitializer */
#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
* @hideinitializer */
#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, __opus_check_int_ptr(x)
/** Provide external DNN weights from binary object (only when explicitly built without the weights)
* @hideinitializer */
#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, __opus_check_void_ptr(data), __opus_check_int(len)
/**@}*/
/** @defgroup opus_genericctls Generic CTLs
@ -715,6 +747,16 @@ extern "C" {
* </dl>
* @hideinitializer */
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
/** Gets the DTX state of the encoder.
* Returns whether the last encoded frame was either a comfort noise update
* during DTX or not encoded because of DTX.
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>The encoder is not in DTX.</dd>
* <dt>1</dt><dd>The encoder is in DTX.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
/**@}*/

View File

@ -143,7 +143,7 @@ extern "C" {
* <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
* channel ordering</a>. A decoder may wish to apply an additional permutation
* to the mapping the encoder used to achieve a different output channel
* order (e.g. for outputing in WAV order).
* order (e.g. for outputting in WAV order).
*
* Each multistream packet contains an Opus packet for each stream, and all of
* the Opus packets in a single multistream packet must have the same

View File

@ -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;
}

View File

@ -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);

@ -1 +1 @@
Subproject commit b77072d39984019b4234d9f2adc3b673b6d57812
Subproject commit 8af4562af672dd6b9ed28553ead172984fd9a683

View File

@ -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
@ -160,3 +211,51 @@ Java_com_limelight_nvstream_jni_MoonBridge_getEstimatedRttInfo(JNIEnv *env, jcla
return ((uint64_t)rtt << 32U) | variance;
}
JNIEXPORT jstring JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_getLaunchUrlQueryParameters(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, LiGetLaunchUrlQueryParameters());
}
JNIEXPORT jbyte JNICALL
Java_com_limelight_nvstream_jni_MoonBridge_guessControllerType(JNIEnv *env, jclass clazz, jint vendorId, jint productId) {
unsigned int unDeviceID = MAKE_CONTROLLER_ID(vendorId, productId);
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);
}

View File

@ -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_ */

View File

@ -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>

View File

@ -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>

View File

@ -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,18 @@
<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>
<string name="title_analog_scrolling">Verwenden Sie zum Scrollen einen Analogstick</string>
<string name="summary_analog_scrolling">Wählen Sie einen Analogstick aus, der zum scrollen im Mausemulationsmodus verwendet werden soll</string>
<string name="analogscroll_none">Keine (beide Sticks bewegen die Maus)</string>
<string name="analogscroll_right">Rechter Analogstick</string>
<string name="analogscroll_left">Linker Analogstick</string>
</resources>

View File

@ -112,7 +112,8 @@
<string name="scut_not_paired">Ο υπολογιστής δεν έχει συζευχθεί</string>
<string name="pcview_menu_header_offline">Εκτός σύνδεσης</string>
<string name="pcview_menu_test_network">Δοκιμή σύνδεσης δικτύου</string>
<string name="nettest_text_waiting">Το Moonlight δοκιμάζει τη σύνδεση δικτύου σας για να καθορίσει εάν το NVIDIA GameStream είναι αποκλεισμένο.
<string name="nettest_text_waiting">Το Moonlight δοκιμάζει τη σύνδεση δικτύου σας για να διαπιστώσει εάν κάποια θύρα είναι αποκλεισμένη.
\n
\n
\nΑυτό μπορεί να πάρει μερικά δευτερόλεπτα…</string>
<string name="pair_fail">Η σύζευξη απέτυχε</string>
@ -205,4 +206,10 @@
<string name="title_video_format">Αλλαγή ρυθμίσεων HEVC</string>
<string name="title_enable_post_stream_toast">Εμφάνιση μηνύματος λανθάνοντος χρόνου μετά τη ροή</string>
<string name="summary_video_format">Το HEVC μειώνει τις απαιτήσεις εύρους ζώνης βίντεο, αλλά απαιτεί μια νεότερη συσκευή</string>
<string name="error_code_prefix">Κωδικός σφάλματος:</string>
<string name="frame_conversion_error">Ο υπολογιστής φιλοξενίας ανέφερε ένα σφάλμα κωδικοποίησης βίντεο.
\n
\nΔοκιμάστε να απενεργοποιήσετε τη λειτουργία HDR, να αλλάξετε την ανάλυση ροής ή να αλλάξετε την ανάλυση οθόνης του υπολογιστή φιλοξενίας.</string>
<string name="pcview_menu_eol">Λήξη Υποστήριξης NVIDA GameStream</string>
<string name="pair_pairing_help">Εάν ο υπολογιστής οικοδεσπότης χρησιμοποιεί το Sunshine, πλοηγηθείτε στην διαδικτυακή διεπαφή χρήστη του Sunshine για να εισάγετε το PIN.</string>
</resources>

View File

@ -45,7 +45,7 @@
<string name="conn_error_title">Error de conexión</string>
<string name="conn_error_msg">Fallo al iniciar</string>
<string name="conn_terminated_title">Conexión finalizada</string>
<string name="conn_terminated_msg">La conexión ha finalizando</string>
<string name="conn_terminated_msg">La conexión ha finalizado.</string>
<!-- General strings -->
<string name="ip_hint">Dirección IP del host del ordenador</string>
<string name="searching_pc">Buscando el hostal del PC en tu red local...
@ -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,27 @@
<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>
<string name="analogscroll_none">Ninguno (ambos joysticks mueven el mouse)</string>
<string name="analogscroll_right">Joystick analógico derecho</string>
<string name="analogscroll_left">Joystick analógico izquierdo</string>
<string name="title_analog_scrolling">Usa un joystick analógico para hacer scroll</string>
<string name="summary_analog_scrolling">Selecciona un joystick analógico para scroll cuando la emulación del mouse está habilitada</string>
<string name="error_code_prefix">Código del error:</string>
<string name="title_seekbar_vibrate_fallback_strength">Ajustar la intensidad del ruido emulado</string>
<string name="summary_seekbar_vibrate_fallback_strength">Amplifica o reduce la intensidad de la vibración de tu dispositivo</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
</resources>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View File

@ -10,79 +10,78 @@
<string name="help_loading_title">Visionneuse d\'aide</string>
<string name="help_loading_msg">Chargement de la page d\'aide…</string>
<!-- PC view menu entries -->
<string name="pcview_menu_app_list">Afficher la liste des jeux</string>
<string name="pcview_menu_pair_pc">Appairer avec PC</string>
<string name="pcview_menu_app_list">Afficher toutes les applis</string>
<string name="pcview_menu_pair_pc">Appairer avec ce PC</string>
<string name="pcview_menu_unpair_pc">Désappairer</string>
<string name="pcview_menu_send_wol">Envoyer la requête Wake-On-LAN</string>
<string name="pcview_menu_delete_pc">Supprimer PC</string>
<string name="pcview_menu_send_wol">Envoyer une requête Wake-On-LAN</string>
<string name="pcview_menu_delete_pc">Supprimer le PC</string>
<string name="pcview_menu_details">Voir les détails</string>
<!-- Network test strings -->
<string name="nettest_title_waiting">Test de la connexion réseau</string>
<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>
<string name="nettest_text_success">Votre réseau ne semble pas bloquer Moonlight. Si vous avez encore de la difficulté à vous connecter, vérifiez les paramètres du pare-feu de votre PC.\n\nSi vous essayez de diffuser sur Internet, installez l\'outil d\'hébergement Internet Moonlight sur votre PC et exécutez le testeur de streaming Internet inclus pour vérifier la connexion Internet de votre PC.</string>
<string name="nettest_text_inconclusive">Le test réseau na pas pu être effectué car aucun des serveurs de test de connexion Moonlight nétait accessible. Vérifiez votre connexion Internet ou réessayez plus tard.</string>
<string name="nettest_text_failure">La connexion réseau actuelle de votre appareil semble bloquer Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsquil est connecté à ce réseau.
<string name="nettest_text_success">Votre réseau ne semble pas bloquer Moonlight. Si vous avez encore des difficultés à vous connecter, vérifiez les paramètres du pare-feu de votre PC.
\n
\nSi vous essayez de streamer depuis Internet, installez l\'outil Moonlight Internet Hosting Tool sur votre PC et exécutez le testeur de streaming Internet inclus pour vérifier la connexion Internet de votre PC.</string>
<string name="nettest_text_inconclusive">Le test réseau n\'a pas pu être effectué car aucun des serveurs de test de connexion de Moonlight n\'était accessible. Vérifiez votre connexion Internet ou réessayez plus tard.</string>
<string name="nettest_text_failure">La connexion réseau actuelle de votre appareil semble bloquer Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsque vous êtes connecté à ce réseau.
\n
\nLes ports réseau suivants ont été bloqués:
\n</string>
<string name="nettest_text_blocked">La connexion réseau actuelle de votre appareil bloque Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsquil est connecté à ce réseau.</string>
<string name="nettest_text_blocked">La connexion réseau actuelle de votre appareil bloque Moonlight. Le streaming sur Internet peut ne pas fonctionner lorsque vous êtes connecté à ce réseau.</string>
<!-- Pair messages -->
<string name="pairing">Appariement…</string>
<string name="pair_pc_offline">L\'ordinateur est hors ligne</string>
<string name="pair_pc_ingame">L\'ordinateur est actuellement dans un jeu. Vous devez fermer le jeu avant l\'appariement.</string>
<string name="pair_pc_ingame">L\'ordinateur est actuellement dans un jeu. Vous devez fermer le jeu avant lappairage.</string>
<string name="pair_pairing_title">Appariement</string>
<string name="pair_pairing_msg">SVP entrer le code PIN suivant sur le PC concerné:</string>
<string name="pair_pairing_msg">Veuillez saisir le code PIN suivant sur le PC cible:</string>
<string name="pair_incorrect_pin">Code PIN incorrect</string>
<string name="pair_fail">Échec de l\'appariement</string>
<string name="pair_already_in_progress">Appariement déjà en cours</string>
<!-- 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.
</string>
<string name="wol_waking_msg">Votre PC peut prendre quelques secondes pour démarrer. S\'il ne démarre toujours pas, assurez-vous qu\'il est correctement configuré pour le Wake-On-LAN.</string>
<string name="wol_fail">Échec de l\'envoi des paquets Wake-On-LAN</string>
<!-- Unpair messages -->
<string name="unpairing">Désappariage…</string>
<string name="unpair_success">Désapparié avec succès</string>
<string name="unpair_fail">Échec de désappariement</string>
<string name="unpair_error">Le périphérique n\'a pas été appareillé</string>
<string name="unpair_fail">Échec du désappairage</string>
<string name="unpair_error">Le périphérique n\'est appareillé</string>
<!-- Errors -->
<string name="error_pc_offline">L\'ordinateur est déconnecté</string>
<string name="error_manager_not_running">Le service ComputerManager n\'est pas en cours d\'exécution. Veuillez patienter quelques secondes ou redémarrer l\'application.</string>
<string name="error_pc_offline">L\'ordinateur est hors ligne</string>
<string name="error_manager_not_running">Le service ComputerManager n\'est pas en cours d\'exécution. Veuillez attendre quelques secondes ou redémarrez l\'application.</string>
<string name="error_unknown_host">Échec de la résolution de l\'hôte</string>
<string name="error_404">GFE renvoi une erreur HTTP 404. Assurez-vous que votre PC exécute un GPU pris en charge.
L\'utilisation d\'un logiciel de bureau à distance peut également provoquer cette erreur. Essayez de redémarrer votre machine ou de réinstaller GFE.
</string>
<string name="title_decoding_error">Le décodeur vidéo s\'est écrasé</string>
<string name="message_decoding_error">Moonlight s\'est arrêté en raison d\'une incompatibilité avec le décodeur vidéo de cet appareil. 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="title_decoding_reset">Paramètres vidéo réinitialiser</string>
<string name="message_decoding_reset">Le décodeur vidéo de votre appareil continue de planter avec les paramètres de diffusion sélectionnés. Vos paramètres de diffusion ont été réinitialisés par défaut.</string>
<string name="error_usb_prohibited">L\'accès USB est interdit par votre appareil. Vérifiez vos paramètres Knox ou MDM.</string>
<string name="unable_to_pin_shortcut">Votre lanceur actuel ne permet pas de créer des raccourcis épinglés.</string>
<string name="error_404">GFE renvoie une erreur HTTP 404. Assurez-vous que votre PC possède un GPU pris en charge. L\'utilisation d\'un logiciel de bureau à distance peut également provoquer cette erreur. Essayez de redémarrer votre machine ou de réinstaller GFE.</string>
<string name="title_decoding_error">Le décodeur vidéo a planté</string>
<string name="message_decoding_error">Moonlight a planté en raison d\'une incompatibilité avec le décodeur vidéo de cet appareil. Essayez d\'ajuster les paramètres de streaming si les plantages continuent.</string>
<string name="title_decoding_reset">Réinitialiser les paramètres vidéo</string>
<string name="message_decoding_reset">Le décodeur vidéo de votre appareil continue de planter avec les paramètres de streaming sélectionnés. Vos paramètres de streaming ont été réinitialisés à ceux par défaut.</string>
<string name="error_usb_prohibited">L\'accès USB est interdit par l\'administrateur de votre appareil. Vérifiez vos paramètres Knox ou MDM.</string>
<string name="unable_to_pin_shortcut">Votre launcher actuel ne permet pas de créer des raccourcis épinglés.</string>
<!-- Start application messages -->
<string name="conn_establishing_title">Établissement de la connexion</string>
<string name="conn_establishing_msg">Démarrage de la connection</string>
<string name="conn_metered">Attention: Votre connexion réseau active est mesurée!</string>
<string name="conn_metered">Attention: Votre connexion réseau active est limitée!</string>
<string name="conn_client_latency">Latence moyenne de décodage de trame:</string>
<string name="conn_client_latency_hw">Latence du décodeur matériel:</string>
<string name="conn_hardware_latency">Latence moyenne du décodage matériel:</string>
<string name="conn_starting">Démarrage</string>
<string name="conn_error_title">Erreur de connexion</string>
<string name="conn_error_msg">Impossible de démarrer</string>
<string name="conn_terminated_title">Connexion terminée</string>
<string name="conn_terminated_msg">La connexion a été interrompue</string>
<string name="conn_terminated_title">Connexion interrompue</string>
<string name="conn_terminated_msg">La connexion a été interrompue.</string>
<!-- General strings -->
<string name="ip_hint">Adresse IP 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>
<string name="lost_connection">Connexion perdue avec le PC</string>
<string name="title_details">Détails</string>
<string name="help">Aide</string>
<string name="delete_pc_msg">Êtes-vous sûr de vouloir supprimer ce PC\?</string>
@ -95,105 +94,105 @@
<string name="perf_overlay_dectime">Temps moyen de décodage : %1$.2f ms</string>
<!-- AppList activity -->
<string name="applist_connect_msg">Connexion au PC…</string>
<string name="applist_menu_resume">Reprise de la session</string>
<string name="applist_menu_resume">Reprendre la session</string>
<string name="applist_menu_quit">Quitter la session</string>
<string name="applist_menu_quit_and_start">Quitter le jeu actuel et démarrer</string>
<string name="applist_menu_cancel">Annuler</string>
<string name="applist_menu_details">Voir les détails</string>
<string name="applist_menu_scut">Créer un raccourci</string>
<string name="applist_menu_tv_channel">Ajouter à la chaîne</string>
<string name="applist_menu_tv_channel">Ajouter à la liste de chaînes</string>
<string name="applist_refresh_title">Liste des applications</string>
<string name="applist_refresh_msg">Actualisation des applications…</string>
<string name="applist_refresh_error_title">Erreur</string>
<string name="applist_refresh_error_msg">Impossible d\'obtenir la liste des applications</string>
<string name="applist_quit_app">Fermeture</string>
<string name="applist_quit_success">Fermeture avec succès</string>
<string name="applist_quit_success">Application fermée avec succès</string>
<string name="applist_quit_fail">Échec de la fermeture</string>
<string name="applist_quit_confirmation">Voulez-vous vraiment quitter l\'application en cours d\'exécution\? Toutes les données non enregistrées seront perdues.</string>
<string name="applist_details_id">ID de l\'appli :</string>
<!-- Add computer manually activity -->
<string name="title_add_pc">Ajouter un PC manuellement</string>
<string name="msg_add_pc">Connexion au PC…</string>
<string name="addpc_fail">Impossible de se connecter à l\'ordinateur spécifié. Assurez-vous que les ports requis sont autorisés par le pare-feu.</string>
<string name="addpc_success">Ajouté avec succès de l\'ordinateur</string>
<string name="addpc_unknown_host">Impossible de résoudre l\'adresse du PC. Assurez-vous que vous n\'avez pas fait une faute de frappe dans l\'adresse.</string>
<string name="addpc_fail">Impossible de se connecter à l\'ordinateur spécifié. Assurez-vous que les ports requis sont autorisés via le pare-feu.</string>
<string name="addpc_success">Ordinateur ajouté avec succès</string>
<string name="addpc_unknown_host">Impossible de résoudre l\'adresse du PC. Assurez-vous que vous n\'avez pas fait de faute de frappe dans l\'adresse.</string>
<string name="addpc_enter_ip">Vous devez entrer une adresse IP</string>
<string name="addpc_wrong_sitelocal">Cette adresse ne semble pas correcte. Vous devez utiliser l\'adresse IP publique de votre routeur pour la diffusion en continu sur Internet..</string>
<string name="addpc_wrong_sitelocal">Cette adresse ne semble pas correcte. Vous devez utiliser l\'adresse IP publique de votre routeur pour le streaming depuis Internet.</string>
<!-- Preferences -->
<string name="category_basic_settings">Paramètres de base</string>
<string name="title_resolution_list">Résolution vidéo</string>
<string name="summary_resolution_list">Le réglage de valeurs trop élevées pour votre appareil peut provoquer un retard ou un plantage.</string>
<string name="summary_resolution_list">Augmentez pour une meilleure clarté de l\'image. Réduisez pour de meilleures performances sur les appareils bas de gamme et les réseaux lents.</string>
<string name="title_fps_list">Fréquence d\'images vidéo</string>
<string name="summary_fps_list">Augmenter pour un flux vidéo plus lisse. Diminution pour de meilleures performances sur les périphériques bas de gamme.</string>
<string name="title_seekbar_bitrate">Sélectionnez le bitrate vidéo à obtenir</string>
<string name="summary_seekbar_bitrate">Bitrate inférieur pour réduire la saccade. Augmentez le bitrate pour augmenter la qualité de l\'image.</string>
<string name="title_checkbox_stretch_video">Étirez la vidéo en plein écran</string>
<string name="summary_fps_list">Augmentez pour un flux vidéo plus fluide. Diminuez pour de meilleures performances sur les appareils bas de gamme.</string>
<string name="title_seekbar_bitrate">Bitrate vidéo</string>
<string name="summary_seekbar_bitrate">Augmentez-le pour une meilleure qualité dimage. Diminuez-le pour améliorer les performances sur les connexions plus lentes.</string>
<string name="title_checkbox_stretch_video">Étirer la vidéo en plein écran</string>
<string name="title_checkbox_disable_warnings">Désactiver les messages d\'avertissement</string>
<string name="title_checkbox_enable_pip">Activer le mode observateur dans l\'image</string>
<string name="summary_checkbox_enable_pip">Permet de visualiser le flux (sans le contrôleur) tout en multitâche</string>
<string name="title_checkbox_enable_pip">Activer le mode observateur</string>
<string name="summary_checkbox_enable_pip">Permet de visualiser le stream (sans le contrôler) tout en utilisant une autre appli</string>
<string name="category_audio_settings">Paramètres audio</string>
<string name="title_audio_config_list">Configuration son surround</string>
<string name="summary_audio_config_list">Activer le son surround 5.1 ou 7.1 pour les systèmes home cinéma</string>
<string name="category_input_settings">Paramètres d\'entrée</string>
<string name="title_checkbox_touchscreen_trackpad">Utilisez l\'écran tactile comme trackpad</string>
<string name="summary_checkbox_touchscreen_trackpad">S\'il est activé, l\'écran tactile agit comme un trackpad. S\'il est désactivé, l\'écran tactile contrôle directement le curseur de la souris.</string>
<string name="title_checkbox_multi_controller">Forcer la présence d\'un contrôleur</string>
<string name="summary_checkbox_multi_controller">Lorsqu\'elle n\'est pas cochée, tous les contrôleurs sont regroupés</string>
<string name="title_checkbox_vibrate_fallback">Emuler support vibration de secours</string>
<string name="summary_checkbox_vibrate_fallback">Emuler des tremblements si votre manette ne le prend pas en charge</string>
<string name="title_checkbox_touchscreen_trackpad">Utiliser l\'écran tactile comme trackpad</string>
<string name="summary_checkbox_touchscreen_trackpad">Si activé, l\'écran tactile agit comme un trackpad. Si désactivé, l\'écran tactile contrôle directement le curseur de la souris.</string>
<string name="title_checkbox_multi_controller">Forcer la présence d\'une manette</string>
<string name="summary_checkbox_multi_controller">Décocher cette option force une manette à toujours être présente</string>
<string name="title_checkbox_vibrate_fallback">Émuler les vibrations de la manette avec l\'appareil</string>
<string name="summary_checkbox_vibrate_fallback">Fait vibrer votre appareil pour émuler les vibrations de la manette si elle ne le supporte pas</string>
<string name="title_seekbar_deadzone">Régler la zone morte du stick analogique</string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Pilote de contrôleur Xbox 360/One</string>
<string name="summary_checkbox_xb1_driver">Active un pilote USB intégré pour les périphériques sans prise en charge du contrôleur Xbox natif</string>
<string name="title_checkbox_usb_bind_all">Ignorer le support du contrôleur Android</string>
<string name="summary_checkbox_usb_bind_all">Force le pilote USB de Moonlight à prendre en charge tous les gamepads Xbox pris en charge</string>
<string name="title_checkbox_mouse_emulation">Emulation de la souris via le gamepad</string>
<string name="title_checkbox_xb1_driver">Pilote USB pour manette Xbox 360/One</string>
<string name="summary_checkbox_xb1_driver">Active un pilote USB intégré pour les appareils qui ne prennent pas nativement en charge les manettes Xbox</string>
<string name="title_checkbox_usb_bind_all">Remplacer le support natif des manettes Xbox</string>
<string name="summary_checkbox_usb_bind_all">Utilise le pilote USB de Moonlight pour toutes les manettes prises en charge, même si l\'appareil supporte nativement celles-ci</string>
<string name="title_checkbox_mouse_emulation">Émuler la souris avec la manette</string>
<string name="summary_checkbox_mouse_emulation">Appuyez longuement sur le bouton Start pour faire basculer la manette en mode souris</string>
<string name="title_checkbox_mouse_nav_buttons">Activer les boutons de la souris arrière et avant</string>
<string name="summary_checkbox_mouse_nav_buttons">L\' activation de cette option peut casser le clic droit sur certains appareils bogués</string>
<string name="title_checkbox_flip_face_buttons">Boutons de face inversé</string>
<string name="summary_checkbox_flip_face_buttons">Commute les boutons de face A/B et X/Y pour les manettes de jeu et les commandes à l\'écran</string>
<string name="category_on_screen_controls_settings">Paramètres des contrôles à l\'écran</string>
<string name="title_checkbox_flip_face_buttons">Inverser les boutons en façade</string>
<string name="summary_checkbox_flip_face_buttons">Commute les boutons de face A/B et X/Y pour les manettes et les commandes à l\'écran</string>
<string name="category_on_screen_controls_settings">Paramètres des commandes à l\'écran</string>
<string name="title_checkbox_show_onscreen_controls">Afficher les commandes à l\'écran</string>
<string name="summary_checkbox_show_onscreen_controls">Afficher la superposition du contrôleur virtuel sur l\'écran tactile</string>
<string name="summary_checkbox_show_onscreen_controls">Affiche une manette virtuelle sur l\'écran tacile</string>
<string name="title_checkbox_vibrate_osc">Activer les vibrations</string>
<string name="summary_checkbox_vibrate_osc">Emuler des tremblements des commandes à l\'écran</string>
<string name="title_only_l3r3">Montre seulement L3 et R3</string>
<string name="summary_only_l3r3">Cacher tout sauf L3 et R3</string>
<string name="title_reset_osc">Effacer la disposition des commandes à l\'écran sauvegardée</string>
<string name="summary_checkbox_vibrate_osc">Fait vibrer votre appareil pour émuler les vibrations des commandes à l\'écran</string>
<string name="title_only_l3r3">Montrer seulement L3 et R3</string>
<string name="summary_only_l3r3">Cacher tous les boutons sauf L3 et R3</string>
<string name="title_reset_osc">Réinitialiser la disposition des commandes</string>
<string name="summary_reset_osc">Rétablit la taille et la position par défaut de tous les contrôles à l\'écran</string>
<string name="dialog_title_reset_osc">Réinitialiser la mise en page</string>
<string name="dialog_text_reset_osc">Êtes-vous sûr de vouloir supprimer la disposition des commandes à l\'écran que vous avez sauvegardée\?</string>
<string name="toast_reset_osc_success">Les contrôles à l\'écran sont réinitialisés</string>
<string name="dialog_title_reset_osc">Réinitialiser la disposition</string>
<string name="dialog_text_reset_osc">Êtes-vous sûr de vouloir supprimer votre disposition de commandes à l\'écran?</string>
<string name="toast_reset_osc_success">Les contrôles à l\'écran ont été réinitialisés</string>
<string name="title_osc_opacity">Modifier l\'opacité des contrôles à l\'écran</string>
<string name="summary_osc_opacity">Rendre les contrôles à l\'écran plus/moins transparents</string>
<string name="dialog_title_osc_opacity">Modifiez l\'opacité</string>
<string name="summary_osc_opacity">Permet de rendre les contrôles à l\'écran plus ou moins transparents</string>
<string name="dialog_title_osc_opacity">Modifier l\'opacité</string>
<string name="suffix_osc_opacity">%</string>
<string name="category_ui_settings">Paramètres de l\'interface utilisateur</string>
<string name="title_language_list">Langue</string>
<string name="summary_language_list">Langue à utiliser pour Moonlight</string>
<string name="title_checkbox_small_icon_mode">Utiliser des petites icônes</string>
<string name="summary_checkbox_small_icon_mode">Utilisez les petites icônes dans les éléments de la grille pour permettre plus d\'éléments à l\'écran</string>
<string name="summary_checkbox_small_icon_mode">Des icônes plus petites permettent d\'afficher plus d\'applications en même temps</string>
<string name="category_host_settings">Paramètres de l\'hôte</string>
<string name="title_checkbox_enable_sops">Optimiser les paramètres de jeu</string>
<string name="summary_checkbox_enable_sops">Autoriser GFE à modifier les paramètres de jeu pour une diffusion optimale</string>
<string name="title_checkbox_enable_sops">Optimiser les paramètres du jeu</string>
<string name="summary_checkbox_enable_sops">Autoriser GFE à modifier les paramètres du jeu pour un streaming optimal</string>
<string name="title_checkbox_host_audio">Jouer l\'audio sur le PC</string>
<string name="summary_checkbox_host_audio">Lire l\'audio de l\'ordinateur et de ce périphérique</string>
<string name="summary_checkbox_host_audio">Lire l\'audio sur l\'ordinateur et sur cet appareil</string>
<string name="category_advanced_settings">Réglages avancés</string>
<string name="title_unlock_fps">Débloquez toutes les fréquences d\'images possibles</string>
<string name="summary_unlock_fps">Le streaming à 90 ou 120 FPS peut réduire la latence sur les appareils haut de gamme, mais peut entraîner un décalage ou une instabilité sur les appareils qui ne peuvent pas le prendre en charge</string>
<string name="summary_checkbox_disable_warnings">Désactiver les messages d\'avertissement de connexion à l\'écran pendant la diffusion</string>
<string name="title_disable_frame_drop">Ne jamais laisser tomber les frames</string>
<string name="title_unlock_fps">Débloquer toutes les fréquences d\'images possibles</string>
<string name="summary_unlock_fps">Le streaming à 90 ou 120 FPS peut réduire la latence sur les appareils haut de gamme, mais peut entraîner un décalage ou une instabilité sur les appareils qui ne le supporte pas</string>
<string name="summary_checkbox_disable_warnings">Désactive les messages d\'avertissement sur la connexion pendant le stream</string>
<string name="title_disable_frame_drop">Ne jamais perdre d\'images</string>
<string name="summary_disable_frame_drop">Peut réduire les micro-saccades sur certains appareils, mais peut augmenter la latence</string>
<string name="title_video_format">Modifier les paramètres 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="title_enable_perf_overlay">Activer la superposition de performance</string>
<string name="summary_enable_perf_overlay">Afficher une superposition à l\'écran avec des informations de performance en temps réel pendant la lecture en continu</string>
<string name="title_enable_post_stream_toast">Afficher le message de latence après la diffusion en continu</string>
<string name="summary_enable_post_stream_toast">Afficher un message dinformations de latence après la fin du flux</string>
<string name="no_video_received_error">Aucune vidéo reçue depuis l\'hôte.</string>
<string name="summary_enable_hdr">Streamer en HDR lorsque le jeu et le GPU du PC le prennent en charge. Le HDR nécessite un GPU pouvant encoder en HEVC Main 10.</string>
<string name="title_enable_perf_overlay">Afficher les statistiques de peformance lors du stream</string>
<string name="summary_enable_perf_overlay">Affiche des informations sur les performances du stream en temps réel pendant le stream</string>
<string name="title_enable_post_stream_toast">Afficher la latence moyenne après un stream</string>
<string name="summary_enable_post_stream_toast">Affiche un message dinformation sur la latence après la fin du stream</string>
<string name="no_video_received_error">Aucune vidéo reçue de l\'hôte.</string>
<string name="video_decoder_init_failed">Le décodeur vidéo n\'a pas pu démarrer. Vérifiez que votre appareil supporte la résolution ou la fréquence d\'images choisie.</string>
<string name="pcview_menu_test_network">Tester la connection réseau</string>
<string name="pcview_menu_header_unknown">Actualisation</string>
@ -201,22 +200,20 @@
<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>
<string name="title_native_res_dialog">Avertissement résolution native</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 sur la résolution native</string>
<string name="applist_menu_hide_app">Cacher l\'application</string>
<string name="check_ports_msg">Vérifiez vos règles de pare-feu pour les ports suivants :</string>
<string name="early_termination_error">Quelque chose s\'est mal passé sur votre PC hôte en démarrant le flux.
<string name="early_termination_error">Quelque chose s\'est mal passé sur votre PC hôte en démarrant le stream.
\n
\nVérifiez qu\'aucune application utilisant un DRM n\'est ouverte sur votre PC hôte. Vous pouvez aussi essayer de redémarrer votre PC hôte.
\n
\nSi le problème persiste, essayez de réinstaller les pilotes de votre GPU ainsi que GeForce Experience.</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>
\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 réseau ne fonctionne pas bien. Baissez votre débit ou utilisez une connexion plus rapide.</string>
<string name="resolution_prefix_native_fullscreen">Plein-écran natif</string>
<string name="perf_overlay_netlatency">Latence réseau moyenne : %1$d ms (variance : %2$d ms)</string>
<string name="perf_overlay_streamdetails">Stream vidéo : %1$s %2$.2f FPS</string>
@ -228,9 +225,8 @@
<string name="audioconf_stereo">Stéréo</string>
<string name="audioconf_51surround">Son surround 5.1</string>
<string name="audioconf_71surround">Son surround 7.1</string>
<string name="videoformat_hevcauto">Automatique (recommandé)</string>
<string name="videoformat_hevcalways">Préférez le HEVC</string>
<string name="videoformat_hevcnever">N\'utilisez jamais HEVC</string>
<string name="videoformat_auto">Automatique (recommandé)</string>
<string name="videoformat_hevcalways">Préférer HEVC</string>
<string name="title_frame_pacing">Frame-pacing vidéo</string>
<string name="summary_frame_pacing">Spécifiez comment équilibrer latence et fluidité de la vidéo</string>
<string name="pacing_latency">Préférer une latence plus faible</string>
@ -247,12 +243,12 @@
<string name="title_troubleshooting">Guide de dépannage</string>
<string name="title_privacy_policy">Politique de confidentialité</string>
<string name="summary_privacy_policy">Voir la politique de confidentialité de Moonlight</string>
<string name="summary_setup_guide">Afficher les instructions sur la façon de configurer votre PC de jeu pour le streaming</string>
<string name="summary_troubleshooting">Afficher des conseils pour diagnostiquer et résoudre les problèmes de streaming courants</string>
<string name="summary_setup_guide">Voir les instructions sur la façon de configurer votre PC de jeu pour le streaming</string>
<string name="summary_troubleshooting">Voir des conseils pour diagnostiquer et résoudre les problèmes de streaming courants</string>
<string name="pacing_balanced_alt">Équilibré avec limite FPS</string>
<string name="title_checkbox_absolute_mouse_mode">Mode souris pour bureau à distance</string>
<string name="summary_seekbar_deadzone">Remarque : Certains jeux peuvent imposer une zone morte plus grande que celle que Moonlight est configuré pour utiliser.</string>
<string name="summary_checkbox_absolute_mouse_mode">Cela peut rendre l\'accélération de la souris plus naturelle pour l\'utilisation du bureau à distance, mais elle est incompatible avec de nombreux jeux.</string>
<string name="summary_checkbox_absolute_mouse_mode">Cela peut rendre l\'accélération de la souris plus naturelle pour l\'utilisation du bureau à distance, mais il est incompatible avec de nombreux jeux.</string>
<string name="resolution_prefix_native_landscape">(Paysage)</string>
<string name="resolution_prefix_native_portrait">(Portrait)</string>
<string name="title_checkbox_reduce_refresh_rate">Autoriser la réduction du taux de rafraîchissement</string>
@ -261,7 +257,32 @@
<string name="title_checkbox_enable_audiofx">Activer le support de l\'égalisateur système</string>
<string name="frame_conversion_error">Le PC hôte a signalé une erreur d\'encodage fatale.
\n
\nEssayez de désactiver le mode HDR, de changer la résolution du flux ou la résolution de votre PC hôte.</string>
\nEssayez de désactiver le mode HDR, de changer la résolution du stream ou la résolution de votre PC hôte.</string>
<string name="title_full_range">Forcer la vidéo sur toute la gamme de couleurs (expérimental)</string>
<string name="summary_full_range">Ceci entraînera une perte de détails dans les zones claires et sombres si votre appareil n\'affiche pas correctement le contenu vidéo de la gamme complète de couleurs.</string>
<string name="summary_full_range">Cela causera une perte de détails dans les zones claires et sombres si votre appareil n\'affiche pas correctement la vidéo avec une gamme de couleurs complète.</string>
<string name="pcview_menu_eol">NVIDIA GameStream : fin de service</string>
<string name="pair_pairing_help">Si votre PC hôte utilise Sunshine, accédez à l\'interface web de Sunshine pour saisir le code PIN.</string>
<string name="category_gamepad_settings">Paramètres manette</string>
<string name="perf_overlay_hostprocessinglatency">Latence de traitement de l\'hôte min/max/moyenne : %1$.1f/%2$.1f/%3$.1f ms</string>
<string name="fps_suffix_fps">FPS</string>
<string name="title_native_fps_dialog">Avertissement sur le FPS natif</string>
<string name="title_checkbox_gamepad_motion_sensors">Autoriser l\'utilisation des capteurs de mouvement de la manette</string>
<string name="videoformat_av1always">Préférer AV1 (expérimental)</string>
<string name="videoformat_h264always">Préférer H.264</string>
<string name="title_checkbox_gamepad_touchpad_as_mouse">Toujours controller la souris avec le pavé tactile</string>
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Force le pavé tactile de la manette à contrôler la souris de l\'hôte, même quand une manette avec pavé tactile est émulée.</string>
<string name="summary_checkbox_gamepad_motion_sensors">Permet aux hôtes pris en charge de demander les données du capteur de mouvement lors de l\'émulation d\'une manette compatible. Désactiver ce paramètre peut réduire légèrement l\'utilisation de la batterie et du réseau si les capteurs de mouvement ne sont pas utilisés en jeu.</string>
<string name="toast_controller_type_changed">Le type de manette peut être différent dû à l\'émulation du capteur de mouvement</string>
<string name="summary_checkbox_gamepad_motion_fallback">Utilise les capteurs de mouvement de votre appareil si la manette connéctée n\'en a pas, ou qu\'ils ne sont pas pris en charge par votre version d\'Android.
\nRemarque: activer cette option peut faire apparaître votre manette côté hôte comme une manette PlayStation.</string>
<string name="title_checkbox_gamepad_motion_fallback">Émuler les capteurs de mouvement de la manette</string>
<string name="title_analog_scrolling">Utiliser un stick analogique pour faire défiler</string>
<string name="summary_analog_scrolling">Séléctionner un stick analogique à utiliser pour faire défiler lors de l\'émulation de la souris</string>
<string name="analogscroll_none">Aucun (les deux sticks déplacent la souris)</string>
<string name="analogscroll_right">Stick analogique droit</string>
<string name="analogscroll_left">Stick analogique gauche</string>
<string name="error_code_prefix">Code d\'erreur:</string>
<string name="title_seekbar_vibrate_fallback_strength">Ajuster l\'intensité de la vibration émulée</string>
<string name="summary_seekbar_vibrate_fallback_strength">Amplifie ou réduit l\'intensité de la vibration sur votre appareil</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
</resources>

View File

@ -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>

View File

@ -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>

View File

@ -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.
@ -33,7 +33,7 @@
<string name="unpairing">Disaccoppiamento…</string>
<string name="unpair_success">Disaccoppiato con successo</string>
<string name="unpair_fail">Disaccoppiamento fallito</string>
<string name="unpair_error">PC non accoppiato</string>
<string name="unpair_error">Il dispositivo non è stato accoppiato</string>
<!-- Errors -->
<string name="error_pc_offline">PC offline</string>
<string name="error_manager_not_running">Il servizio ComputerManager non è avviato. Attendi qualche secondo o riavvia l\'applicazione.</string>
@ -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"></string>
<string name="no">No</string>
<string name="lost_connection">Connessione con il PC persa</string>
@ -90,7 +91,7 @@
<string name="addpc_wrong_sitelocal">Quell\'indirizzo non sembra corretto. È necessario utilizzare l\'indirizzo IP pubblico del router per lo streaming su Internet.</string>
<!-- Preferences -->
<string name="category_basic_settings">Impostazioni generali</string>
<string name="title_resolution_list">Risoluzione e FPS</string>
<string name="title_resolution_list">Risoluzione video</string>
<string name="summary_resolution_list">Aumentare per migliorare la nitidezza dell\'immagine. Diminuire per aumentare le prestazioni su dispositivi di fascia più bassa e reti più lente.</string>
<string name="title_seekbar_bitrate">Velocità di trasmissione video</string>
<string name="summary_seekbar_bitrate">Aumentare per migliorare la qualità dell\'immagine. Diminuire per aumentare le prestazioni su reti più lente.</string>
@ -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>

View File

@ -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>

View File

@ -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>
<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>

View File

@ -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화면 설정과 일치하도록 NVIDIA 제어판에서 사용자 정의 해상도를 생성 할 경우 모니터 손상, PC 불안정 및 기타 잠재적 문제에 대한 NVIDIA의 경고를 읽고 이해했는지 확인하십시오.
\n
\n3. Moonlight는 PC에서 사용자 정 해상도를 생성하여 발생하는 문제에 대해 책임을 지지 않습니다.
\nMoonlight는 PC에서 사용자 정 해상도를 생성하여 발생하는 문제에 대해 책임을 지지 않습니다.
\n
\n4. 장치 또는 호스트 PC가 네이티브 해상도의 스트리밍을 지원하지 않을 수 있습니다.</string>
\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>

View File

@ -221,9 +221,6 @@
<string name="perf_overlay_netdrops">Frames overgeslagen door uw netwerkverbinding: %1$.2f%%</string>
<string name="perf_overlay_dectime">Gemiddelde decodeertijd: %1$.2f ms</string>
<string name="applist_menu_tv_channel">Toevoegen aan Kanaal</string>
<!-- Array strings -->
<string name="videoformat_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>

View File

@ -4,4 +4,272 @@
<string name="scut_pc_not_found">PC nie znaleziony</string>
<string name="pcview_menu_header_unknown">Odświeżanie</string>
<string name="scut_not_paired">PC niesparowany</string>
<string name="check_ports_msg">Sprawdź zaporę sieciową i reguły przekierowania portów:</string>
<string name="conn_establishing_title">Nawiązywanie połączenia</string>
<string name="conn_establishing_msg">Uruchamianie połączenia</string>
<string name="title_details">Szczegóły</string>
<string name="searching_pc">Wyszukiwanie komputerów-hostów w sieci lokalnej...
\n
\nUpewnij się, że aplikacja Sunshine jest uruchomiona na komputerze-hoście lub funkcja GameStream jest włączona w ustawieniach aplikacji GeForce Experience SHIELD.</string>
<string name="yes">Tak</string>
<string name="title_audio_config_list">Konfiguracja dźwięku przestrzennego</string>
<string name="summary_audio_config_list">Włączenie dźwięku przestrzennego 5.1 lub 7.1 dla systemów kina domowego</string>
<string name="summary_checkbox_mouse_emulation">Długie naciśnięcie przycisku Start spowoduje przełączenie gamepada w tryb myszy</string>
<string name="error_code_prefix">Kod błędu:</string>
<string name="help">Pomoc</string>
<string name="delete_pc_msg">Czy na pewno chcesz usunąć ten komputer?</string>
<string name="slow_connection_msg">Wolne połączenie z komputerem
\nZmniejsz szybkość transmisji</string>
<string name="poor_connection_msg">Słabe połączenie z komputerem</string>
<string name="perf_overlay_streamdetails">Strumień wideo: %1$s %2$.2f FPS</string>
<string name="perf_overlay_decoder">Dekoder: %1$s</string>
<string name="perf_overlay_incomingfps">Przychodząca liczba klatek na sekundę z sieci: %1$.2f FPS</string>
<string name="applist_menu_quit_and_start">Zakończ bieżącą grę i uruchom</string>
<string name="applist_menu_scut">Utwórz skrót</string>
<string name="applist_menu_tv_channel">Dodaj do kanału</string>
<string name="applist_refresh_title">Lista aplikacji</string>
<string name="applist_refresh_error_msg">Nie udało się pobrać listy aplikacji</string>
<string name="applist_quit_app">Rezygnacja</string>
<string name="applist_quit_success">Zakończono z powodzeniem</string>
<string name="applist_quit_fail">Nie udało się zakończyć</string>
<string name="applist_quit_confirmation">Czy na pewno chcesz zamknąć uruchomioną aplikację? Wszystkie niezapisane dane zostaną utracone.</string>
<string name="applist_details_id">App ID:</string>
<string name="title_add_pc">Dodaj komputer ręcznie</string>
<string name="msg_add_pc">Podłączanie do komputera…</string>
<string name="addpc_unknown_host">Nie można określić adresu komputera. Upewnij się, że nie popełniłeś literówki w adresie.</string>
<string name="addpc_wrong_sitelocal">Ten adres nie wygląda prawidłowo. Do przesyłania strumieniowego przez Internet należy używać publicznego adresu IP routera.</string>
<string name="title_resolution_list">Rozdzielczość wideo</string>
<string name="summary_resolution_list">Zwiększ, aby poprawić klarowność obrazu. Zmniejsz, aby uzyskać lepszą wydajność na słabszych urządzeniach i wolniejszych połączeniach sieciowych.</string>
<string name="title_native_res_dialog">Ostrzeżenie o rozdzielczości natywnej</string>
<string name="title_fps_list">Częstotliwość odświeżania wideo</string>
<string name="summary_fps_list">Zwiększ, aby uzyskać płynniejszy strumień wideo. Zmniejsz, aby uzyskać lepszą wydajność na słabszych urządzeniach.</string>
<string name="summary_seekbar_bitrate">Zwiększ, aby uzyskać lepszą jakość obrazu. Zmniejsz, aby poprawić wydajność na wolniejszych połączeniach.</string>
<string name="suffix_seekbar_bitrate_mbps">Mbps</string>
<string name="title_checkbox_stretch_video">Rozciągnięcie wideo do pełnego ekranu</string>
<string name="resolution_prefix_native">Natywna</string>
<string name="title_native_fps_dialog">Ostrzeżenie o natywnym FPS</string>
<string name="title_checkbox_enable_audiofx">Włącz obsługę korektora systemowego</string>
<string name="category_gamepad_settings">Ustawienia gamepada</string>
<string name="title_checkbox_multi_controller">Automatyczne wykrywanie obecności gamepada</string>
<string name="summary_checkbox_enable_audiofx">Umożliwia działanie efektów audio podczas przesyłania strumieniowego, ale może zwiększyć opóźnienie dźwięku</string>
<string name="title_checkbox_vibrate_fallback">Emuluj wsparcie dudnienia za pomocą wibracji</string>
<string name="title_seekbar_vibrate_fallback_strength">Regulacja intensywności emulowanego dudnienia</string>
<string name="summary_seekbar_vibrate_fallback_strength">Wzmocnienie lub zmniejszenie intensywności wibracji na urządzeniu</string>
<string name="summary_checkbox_multi_controller">Odznaczenie tej opcji wymusza, by gamepad był zawsze obecny</string>
<string name="summary_checkbox_vibrate_fallback">Wibruje urządzenie, aby naśladować dudnienie, jeśli gamepad go nie obsługuje</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
<string name="title_seekbar_deadzone">Regulacja strefy martwej drążka analogowego</string>
<string name="summary_seekbar_deadzone">Uwaga: Niektóre gry mogą wymuszać większą strefę martwą niż ta, do której skonfigurowany jest Moonlight.</string>
<string name="suffix_seekbar_deadzone">%</string>
<string name="title_checkbox_xb1_driver">Sterownik USB gamepada Xbox 360/One</string>
<string name="title_checkbox_usb_bind_all">Zastąpienie natywnej obsługi gamepada Xbox</string>
<string name="title_checkbox_mouse_emulation">Emulacja myszy za pomocą gamepada</string>
<string name="title_checkbox_flip_face_buttons">Zamiana przycisków akcji A/B/X/Y</string>
<string name="summary_checkbox_xb1_driver">Włącza wbudowany sterownik USB dla urządzeń bez natywnej obsługi kontrolera Xbox</string>
<string name="summary_checkbox_usb_bind_all">Użyj sterownika USB Moonlight dla wszystkich obsługiwanych gamepadów, nawet jeśli natywna obsługa kontrolera Xbox jest obecna</string>
<string name="title_checkbox_gamepad_touchpad_as_mouse">Zawsze kontroluj mysz za pomocą touchpada</string>
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Wymusza sterowanie myszą za pomocą touchpada gamepada, nawet w przypadku emulacji gamepada z touchpadem.</string>
<string name="title_checkbox_gamepad_motion_sensors">Zezwalaj na korzystanie z czujników ruchu gamepada</string>
<string name="summary_checkbox_gamepad_motion_sensors">Umożliwia obsługiwanym hostom żądanie danych z czujników ruchu podczas emulacji gamepada z czujnikami ruchu. Wyłączenie może nieznacznie zmniejszyć zużycie energii i sieci, jeśli czujniki ruchu nie są używane w grze.</string>
<string name="title_checkbox_gamepad_motion_fallback">Emulacja obsługi czujnika ruchu gamepada</string>
<string name="category_input_settings">Ustawienia wejścia</string>
<string name="title_checkbox_touchscreen_trackpad">Używanie ekranu dotykowego jako gładzika</string>
<string name="summary_checkbox_touchscreen_trackpad">Jeśli opcja ta jest włączona, ekran dotykowy działa jak gładzik. Jeśli jest wyłączony, ekran dotykowy bezpośrednio steruje kursorem myszy.</string>
<string name="title_checkbox_absolute_mouse_mode">Tryb myszy dla pulpitu zdalnego</string>
<string name="title_checkbox_mouse_nav_buttons">Włączanie przycisków myszy wstecz i dalej</string>
<string name="category_on_screen_controls_settings">Ustawienia sterowania na ekranie</string>
<string name="title_checkbox_show_onscreen_controls">Wyświetlanie ustawień sterowania na ekranie</string>
<string name="summary_checkbox_show_onscreen_controls">Wyświetlanie nakładki wirtualnego kontrolera na ekranie dotykowym</string>
<string name="title_checkbox_vibrate_osc">Włącz wibracje</string>
<string name="summary_checkbox_mouse_nav_buttons">Włączenie tej opcji może uniemożliwić kliknięcie prawym przyciskiem myszy na niektórych problematycznych urządzeniach</string>
<string name="summary_checkbox_vibrate_osc">Wibruje urządzenie, aby naśladować dudnienie przy ustawieniach sterowania na ekranie</string>
<string name="title_only_l3r3">Pokaż tylko L3 i R3</string>
<string name="summary_only_l3r3">Ukryj wszystkie przyciski wirtualne z wyjątkiem L3 i R3</string>
<string name="title_reset_osc">Wyczyść zapisany układ elementów sterujących na ekranie</string>
<string name="toast_reset_osc_success">Przywrócenie domyślnych ustawień elementów sterujących na ekranie</string>
<string name="title_osc_opacity">Zmiana krycia elementów sterujących na ekranie</string>
<string name="summary_osc_opacity">Zwiększanie/zmniejszanie przezroczystości elementów sterujących na ekranie</string>
<string name="dialog_title_osc_opacity">Zmiana krycia</string>
<string name="suffix_osc_opacity">%</string>
<string name="category_ui_settings">Ustawienia interfejsu użytkownika</string>
<string name="title_checkbox_enable_pip">Włącz tryb obserwatora obrazu w obrazie</string>
<string name="summary_reset_osc">Przywraca domyślny rozmiar i położenie wszystkich elementów sterujących na ekranie</string>
<string name="title_language_list">Język</string>
<string name="summary_language_list">Język używany w Moonlight</string>
<string name="category_host_settings">Ustawienia hosta</string>
<string name="summary_checkbox_small_icon_mode">Mniejsze ramki w siatce aplikacji pozwalają na wyświetlanie większej liczby aplikacji na ekranie</string>
<string name="title_checkbox_enable_sops">Optymalizacja ustawień gry</string>
<string name="summary_checkbox_enable_sops">Zezwalanie GFE na modyfikowanie ustawień gry w celu optymalnego streamowania</string>
<string name="title_checkbox_host_audio">Odtwarzanie dźwięku na komputerze</string>
<string name="summary_checkbox_host_audio">Odtwarzanie dźwięku z komputera i tego urządzenia</string>
<string name="category_advanced_settings">Ustawienia zaawansowane</string>
<string name="title_unlock_fps">Odblokuj wszystkie możliwe liczby klatek na sekundę</string>
<string name="title_checkbox_reduce_refresh_rate">Zezwalaj na zmniejszenie częstotliwości odświeżania</string>
<string name="summary_checkbox_reduce_refresh_rate">Niższe częstotliwości odświeżania wyświetlacza mogą oszczędzać energię kosztem dodatkowych opóźnień wideo</string>
<string name="summary_unlock_fps">Przesyłanie strumieniowe w 90 lub 120 klatkach na sekundę może zmniejszyć opóźnienia na urządzeniach wysokiej klasy, ale może powodować opóźnienia lub niestabilność na urządzeniach, które nie są w stanie tego obsłużyć</string>
<string name="title_checkbox_disable_warnings">Wyłączanie komunikatów ostrzegawczych</string>
<string name="summary_checkbox_disable_warnings">Wyłączanie wyświetlanych na ekranie komunikatów ostrzegawczych o połączeniu podczas przesyłania strumieniowego</string>
<string name="title_disable_frame_drop">Nigdy nie porzucaj klatek</string>
<string name="title_video_format">Zmiana ustawień kodeka</string>
<string name="summary_video_format">Nowsze kodeki mogą obniżyć wymagania dotyczące przepustowości wideo, jeśli urządzenie je obsługuje. Wybrane kodeki mogą zostać zignorowane, jeśli nie są obsługiwane przez oprogramowanie hosta lub procesor graficzny.</string>
<string name="summary_disable_frame_drop">Może zmniejszyć mikroprzycięcia na niektórych urządzeniach, ale może zwiększyć opóźnienia</string>
<string name="title_enable_hdr">Włącz HDR (eksperymentalnie)</string>
<string name="summary_enable_hdr">Przesyłaj strumieniowo HDR, gdy gra i procesor graficzny komputera obsługują tę funkcję. HDR wymaga GPU z obsługą kodowania HEVC Main 10.</string>
<string name="title_full_range">Wymuś pełny zakres wideo (eksperymentalne)</string>
<string name="summary_enable_perf_overlay">Wyświetlanie informacji o wydajności strumienia w czasie rzeczywistym podczas strumieniowania</string>
<string name="title_enable_post_stream_toast">Wyświetlanie komunikatu o opóźnieniu po przesyłaniu strumieniowym</string>
<string name="summary_full_range">Spowoduje to utratę szczegółów w jasnych i ciemnych obszarach, jeśli urządzenie nie wyświetla prawidłowo treści wideo w pełnym zakresie.</string>
<string name="summary_enable_post_stream_toast">Wyświetlanie komunikatu informującego o opóźnieniu po zakończeniu strumienia</string>
<string name="title_setup_guide">Instrukcja konfiguracji</string>
<string name="title_privacy_policy">Polityka prywatności</string>
<string name="summary_privacy_policy">Zobacz politykę prywatności Moonlight</string>
<string name="resolution_360p">360p</string>
<string name="resolution_720p">720p</string>
<string name="toast_controller_type_changed">Typ gamepada może zostać zmieniony z powodu emulacji czujnika ruchu</string>
<string name="resolution_4k">4K</string>
<string name="fps_30">30 FPS</string>
<string name="fps_60">60 FPS</string>
<string name="fps_90">90 FPS</string>
<string name="fps_120">120 FPS</string>
<string name="videoformat_h264always">Preferowany H.264</string>
<string name="pacing_balanced_alt">Zrównoważone z limitem FPS</string>
<string name="pacing_smoothness">Preferowanie najbardziej płynnego wideo (może znacznie zwiększyć opóźnienie)</string>
<string name="title_analog_scrolling">Użyj drążka analogowego do przewijania</string>
<string name="summary_analog_scrolling">Wybór drążka analogowego do przewijania w trybie emulacji myszy</string>
<string name="analogscroll_none">Brak (oba drążki poruszają myszą)</string>
<string name="analogscroll_right">Prawy drążek analogowy</string>
<string name="analogscroll_left">Lewy drążek analogowy</string>
<string name="scut_invalid_app_id">Podana aplikacja jest niepoprawna</string>
<string name="scut_invalid_uuid">Podany PC jest niepoprawny</string>
<string name="pcview_menu_delete_pc">Usuń PC</string>
<string name="pcview_menu_test_network">Test połączenia sieciowego</string>
<string name="pcview_menu_details">Wyświetl szczegóły</string>
<string name="nettest_title_done">Test sieci zakończony</string>
<string name="nettest_text_failure">Bieżące połączenie sieciowe urządzenia wydaje się blokować Moonlight. Przesyłanie strumieniowe przez Internet może nie działać podczas połączenia z tą siecią.
\n
\nNastępujące porty sieciowe zostały zablokowane:
\n</string>
<string name="nettest_text_blocked">Bieżące połączenie sieciowe urządzenia blokuje Moonlight. Przesyłanie strumieniowe przez Internet może nie działać podczas połączenia z tą siecią.</string>
<string name="pair_pairing_title">Parowanie</string>
<string name="pair_pc_offline">Komputer jest offline</string>
<string name="pair_incorrect_pin">Nieprawidłowy kod PIN</string>
<string name="pair_fail">Parowanie nie powiodło się</string>
<string name="pair_already_in_progress">Parowanie jest już w toku</string>
<string name="wol_pc_online">Komputer jest online</string>
<string name="wol_no_mac">Nie można wybudzić komputera, ponieważ nie ma zapisanego adresu MAC</string>
<string name="wol_waking_pc">Uruchamianie PC…</string>
<string name="wol_waking_msg">Uruchomienie komputera może potrwać kilka sekund. Jeśli tak się nie stanie, upewnij się, że jest prawidłowo skonfigurowany do Wake-On-LAN.</string>
<string name="unpair_fail">Rozparowanie nie powiodło się</string>
<string name="unpair_error">Urządzenie nie zostało sparowane</string>
<string name="error_pc_offline">Komputer jest offline</string>
<string name="error_unknown_host">Nie udało się zlokalizować hosta</string>
<string name="message_decoding_error">Moonlight uległ awarii z powodu niezgodności z dekoderem wideo tego urządzenia. Spróbuj dostosować ustawienia przesyłania strumieniowego jeśli awarie będą się powtarzać.</string>
<string name="error_404">GFE zwrócił błąd HTTP 404. Upewnij się, że w Twoim komputerze działa obsługiwany procesor graficzny. Używanie oprogramowania pulpitu zdalnego może również powodować ten błąd. Spróbuj ponownie uruchomić komputer lub ponownie zainstalować GFE.</string>
<string name="title_decoding_reset">Reset ustawień wideo</string>
<string name="error_usb_prohibited">Dostęp USB jest zabroniony przez administratora urządzenia. Sprawdź ustawienia Knox lub MDM.</string>
<string name="video_decoder_init_failed">Nie udało się zainicjować dekodera wideo. Urządzenie może nie obsługiwać wybranej rozdzielczości lub liczby klatek na sekundę.</string>
<string name="early_termination_error">Coś poszło nie tak na komputerze hosta podczas uruchamiania transmisji.
\n
\nUpewnij się, że na komputerze hosta nie masz otwartej żadnej zawartości zabezpieczonej DRM. Możesz także spróbować ponownie uruchomić komputer hosta.</string>
<string name="conn_error_msg">Nie udało się uruchomić</string>
<string name="conn_terminated_msg">Połączenie zostało przerwane.</string>
<string name="perf_overlay_renderingfps">Liczba klatek na sekundę renderowania: %1$.2f FPS</string>
<string name="applist_refresh_error_title">Błąd</string>
<string name="applist_refresh_msg">Odświeżanie aplikacji…</string>
<string name="addpc_enter_ip">Należy wprowadzić adres IP</string>
<string name="category_audio_settings">Ustawienia audio</string>
<string name="title_frame_pacing">Tempo klatek wideo</string>
<string name="pacing_balanced">Zrównoważone</string>
<string name="no">Nie</string>
<string name="applist_menu_quit">Zakończenie sesji</string>
<string name="title_seekbar_bitrate">Szybkość transmisji wideo</string>
<string name="summary_checkbox_flip_face_buttons">Przełącza przyciski A/B i X/Y dla gamepadów i elementów sterujących na ekranie</string>
<string name="category_help">Pomoc</string>
<string name="resolution_480p">480p</string>
<string name="pair_pairing_msg">Wprowadź następujący kod PIN na komputerze docelowym:</string>
<string name="pair_pairing_help">Jeśli na komputerze hosta działa Sunshine, przejdź do interfejsu użytkownika Sunshine aby wprowadzić kod PIN.</string>
<string name="unpairing">Rozparowywanie…</string>
<string name="unpair_success">Rozparowano z powodzeniem</string>
<string name="unable_to_pin_shortcut">Obecny program uruchamiający nie pozwala na tworzenie przypiętych skrótów.</string>
<string name="conn_client_latency">Średnie opóźnienie dekodowania ramki:</string>
<string name="conn_client_latency_hw">opóźnienie dekodera sprzętowego:</string>
<string name="conn_metered">Ostrzeżenie: Aktywne połączenie sieciowe jest taryfowe!</string>
<string name="conn_hardware_latency">Średnie opóźnienie dekodowania sprzętowego:</string>
<string name="conn_starting">Uruchamianie</string>
<string name="conn_error_title">Błąd połączenia</string>
<string name="lost_connection">Utrata połączenia z komputerem</string>
<string name="dialog_title_reset_osc">Reset układu</string>
<string name="dialog_text_reset_osc">Czy na pewno chcesz usunąć zapisany układ kontrolek ekranowych?</string>
<string name="summary_checkbox_enable_pip">Umożliwia wyświetlanie strumienia (ale nie sterowanie nim) podczas pracy wielozadaniowej</string>
<string name="title_checkbox_small_icon_mode">Używaj małe ramki</string>
<string name="title_enable_perf_overlay">Wyświetlanie statystyk wydajności podczas przesyłania strumieniowego</string>
<string name="summary_troubleshooting">Zobacz wskazówki dotyczące diagnozowania i naprawiania typowych problemów z transmisją strumieniową</string>
<string name="audioconf_51surround">5.1 Surround Sound</string>
<string name="audioconf_71surround">7.1 Surround Sound</string>
<string name="videoformat_hevcalways">Preferowany HEVC</string>
<string name="summary_frame_pacing">Określenie sposobu równoważenia opóźnienia i płynności wideo</string>
<string name="pacing_latency">Preferowane najniższe opóźnienia</string>
<string name="perf_overlay_hostprocessinglatency">Opóźnienie przetwarzania hosta min/max/średnia: %1$.1f/%2$.1f/%3$.1f ms</string>
<string name="perf_overlay_netlatency">Średnie opóźnienie sieci: %1$d ms (wariancja: %2$d ms)</string>
<string name="applist_connect_msg">Podłączanie do komputera…</string>
<string name="applist_menu_resume">Wznowienie sesji</string>
<string name="perf_overlay_netdrops">Ramki porzucone przez połączenie sieciowe: %1$.2f%%</string>
<string name="perf_overlay_dectime">Średni czas dekodowania: %1$.2f ms</string>
<string name="addpc_success">Dodano komputer z powodzeniem</string>
<string name="resolution_prefix_native_landscape">(Panoramiczny)</string>
<string name="resolution_prefix_native_fullscreen">Natywny pełny ekran</string>
<string name="resolution_prefix_native_portrait">(Portretowy)</string>
<string name="resolution_1080p">1080p</string>
<string name="help_loading_msg">Ładowanie strony pomocy…</string>
<string name="pcview_menu_header_online">Online</string>
<string name="pcview_menu_header_offline">Offline</string>
<string name="pcview_menu_app_list">Wyświetl wszystkie aplikacje</string>
<string name="help_loading_title">Przeglądarka pomocy</string>
<string name="pcview_menu_pair_pc">Sparuj z PC</string>
<string name="pcview_menu_unpair_pc">Rozparuj</string>
<string name="pcview_menu_send_wol">Wyślij żądanie Wake-On-LAN</string>
<string name="nettest_text_waiting">Moonlight testuje połączenie sieciowe w celu ustalenia, czy wymagane porty są zablokowane.
\n
\nMoże to potrwać kilka sekund…</string>
<string name="pairing">Parowanie…</string>
<string name="pair_pc_ingame">Komputer jest obecnie w trakcie gry. Przed sparowaniem należy zamknąć grę.</string>
<string name="nettest_text_success">Wygląda na to, że sieć nie blokuje Moonlight. Jeśli nadal masz problemy z połączeniem, sprawdź ustawienia zapory sieciowej na swoim komputerze.
\n
\nJeśli próbujesz przesyłać strumieniowo przez Internet, zainstaluj narzędzie Moonlight Internet Hosting Tool na swoim komputerze i uruchom dołączony tester przesyłania strumieniowego przez Internet, aby sprawdzić połączenie internetowe komputera.</string>
<string name="pcview_menu_eol">Zakończenie usług NVIDIA GameStream</string>
<string name="nettest_text_inconclusive">Nie można było wykonać testu sieci ponieważ żaden z serwerów testujących połączenie Moonlight nie był osiągalny. Sprawdź połączenie internetowe lub spróbuj ponownie później.</string>
<string name="nettest_title_waiting">Testowanie połączenia sieciowego</string>
<string name="wol_fail">Nie udało się wysłać pakietów Wake-On-LAN</string>
<string name="error_manager_not_running">Usługa ComputerManager nie jest uruchomiona. Poczekaj kilka sekund lub uruchom ponownie aplikację.</string>
<string name="title_decoding_error">Awaria dekodera wideo</string>
<string name="message_decoding_reset">Dekoder wideo urządzenia nadal ulega awarii przy wybranych ustawieniach przesyłania strumieniowego. Ustawienia przesyłania strumieniowego zostały zresetowane do wartości domyślnych.</string>
<string name="no_video_received_error">Brak sygnału wideo od hosta.</string>
<string name="no_frame_received_error">Połączenie sieciowe nie działa prawidłowo. Zmniejsz ustawienie szybkości transmisji wideo lub wypróbuj szybsze połączenie.</string>
<string name="frame_conversion_error">Komputer host zgłosił krytyczny błąd kodowania wideo.
\n
\nSpróbuj wyłączyć tryb HDR, zmienić rozdzielczość przesyłania strumieniowego lub rozdzielczość wyświetlacza komputera hosta.</string>
<string name="conn_terminated_title">Połączenie zakończone</string>
<string name="ip_hint">Adres IP komputera hosta</string>
<string name="applist_menu_cancel">Anuluj</string>
<string name="applist_menu_hide_app">Ukryj aplikację</string>
<string name="applist_menu_details">Wyświetl szczegóły</string>
<string name="addpc_fail">Nie można połączyć się z określonym komputerem. Upewnij się, że wymagane porty są dozwolone przez zaporę sieciową.</string>
<string name="category_basic_settings">Ustawienia podstawowe</string>
<string name="text_native_res_dialog">Natywna rozdzielczość i/lub liczba klatek na sekundę mogą nie być obsługiwane przez serwer streamingu. Prawdopodobnie konieczne będzie ręczne skonfigurowanie odpowiedniego niestandardowego trybu wyświetlania dla komputera hosta.
\n
\nJeśli zdecydujesz się utworzyć niestandardową rozdzielczość w panelu sterowania NVIDIA aby dopasować ustawienia ekranu, upewnij się, że przeczytałeś i zrozumiałeś ostrzeżenie firmy NVIDIA dotyczące możliwego uszkodzenia monitora, niestabilności komputera i innych potencjalnych problemów.
\n
\nNie ponosimy odpowiedzialności za jakiekolwiek problemy wynikające z utworzenia niestandardowej rozdzielczości na komputerze.
\n
\nMoże się zdarzyć, że monitor nie obsługuje wymaganej konfiguracji wyświetlania. W takim przypadku można spróbować skonfigurować monitor wirtualny. Jeśli urządzenie lub komputer hosta nie obsługuje przesyłania strumieniowego w określonej rozdzielczości lub częstotliwości odświeżania, niestety nie masz szczęścia.</string>
<string name="fps_suffix_fps">FPS</string>
<string name="summary_checkbox_gamepad_motion_fallback">Używa wbudowanych czujników ruchu urządzenia, jeśli czujniki gamepada nie są obsługiwane przez podłączony gamepad lub wersję systemu Android.
\nUwaga: Włączenie tej opcji może spowodować, że gamepad będzie wyświetlany na hoście jako kontroler PlayStation.</string>
<string name="summary_checkbox_absolute_mouse_mode">Może to sprawić, że akceleracja myszy będzie zachowywać się bardziej naturalnie podczas korzystania ze zdalnego pulpitu, ale jest niekompatybilna z wieloma grami.</string>
<string name="title_troubleshooting">Przewodnik rozwiązywania problemów</string>
<string name="resolution_1440p">1440p</string>
<string name="audioconf_stereo">Stereo</string>
<string name="videoformat_auto">Automatycznie (zalecane)</string>
<string name="videoformat_av1always">Preferowany AV1 (eksperymentalny)</string>
<string name="summary_setup_guide">Wyświetl instrukcje, jak skonfigurować komputer do gier do streamowania</string>
</resources>

View File

@ -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>
@ -250,4 +249,9 @@
\n
\nTente desativar o modo HDR, alterar a resolução de streaming ou alterar a resolução do PC host.</string>
<string name="summary_full_range">Isso causará perda de detalhes em áreas claras e escuras se o seu dispositivo não exibir corretamente todo o conteúdo de vídeo em cores.</string>
<string name="analogscroll_none">Nenhum (ambos os sticks movem o rato)</string>
<string name="analogscroll_right">Stick analógico direito</string>
<string name="analogscroll_left">Stick analógico esquerdo</string>
<string name="title_analog_scrolling">Usar um stick analógico para fazer scroll</string>
<string name="summary_analog_scrolling">Selecciona um stick analógico para fazer scroll quando a emulação de rato está ativada</string>
</resources>

View File

@ -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>
@ -250,4 +249,9 @@
<string name="resolution_480p">480p</string>
<string name="resolution_720p">720p</string>
<string name="summary_frame_pacing">Especifique o equilíbrio entre latência e suavidade do vídeo</string>
<string name="analogscroll_none">Nenhum (ambos os sticks movem o rato)</string>
<string name="analogscroll_right">Stick analógico direito</string>
<string name="analogscroll_left">Stick analógico esquerdo</string>
<string name="title_analog_scrolling">Usar um stick analógico para fazer scroll</string>
<string name="summary_analog_scrolling">Selecciona um stick analógico para fazer scroll quando a emulação de rato está ativada</string>
</resources>

View File

@ -6,11 +6,9 @@
<string name="scut_pc_not_found">PC negăsit</string>
<string name="scut_invalid_uuid">PC-ul este invalid</string>
<string name="scut_invalid_app_id">Aplicația este invalidă</string>
<!-- Help strings -->
<string name="help_loading_title">Ajutor</string>
<string name="help_loading_msg">Se încarcă pagina de ajutor…</string>
<!-- PC view menu entries -->
<string name="pcview_menu_app_list">Vezi lista de jocuri</string>
<string name="pcview_menu_pair_pc">Împerechează PC-ul</string>
@ -18,7 +16,6 @@
<string name="pcview_menu_send_wol">Trimite o cerere Wake-On-LAN</string>
<string name="pcview_menu_delete_pc">Șterge PC</string>
<string name="pcview_menu_details">Vezi detalii</string>
<!-- Pair messages -->
<string name="pairing">Se împerechează…</string>
<string name="pair_pc_offline">PC-ul nu este accesibil</string>
@ -28,20 +25,17 @@
<string name="pair_incorrect_pin">PIN-ul este greșit</string>
<string name="pair_fail">Împerecherea a eșuat</string>
<string name="pair_already_in_progress">Împerecherea este deja în curs</string>
<!-- WOL messages -->
<string name="wol_pc_online">PC-ul este accesibil</string>
<string name="wol_no_mac">Nu s-a putut porni PC-ul deoarece GFE nu a comunicat o adresa MAC</string>
<string name="wol_waking_pc">Se pornește PC-ul…</string>
<string name="wol_waking_msg">Poate dura puțin până PC-ul pornește. Dacă nu pornește, verifică dacă este configurat corect pentru Wake-On-LAN.</string>
<string name="wol_fail">Nu s-au putut trimite pachetele Wake-On-LAN</string>
<!-- Unpair messages -->
<string name="unpairing">Desperecherechere…</string>
<string name="unpair_success">Desperecherechere efectuată cu succes</string>
<string name="unpair_fail">Desperecherea a eșuat</string>
<string name="unpair_error">Dispozitivul nu este împerecheat</string>
<!-- Errors -->
<string name="error_pc_offline">PC-ul este inaccesibil</string>
<string name="error_manager_not_running">Serviciul ComputerManager nu este pornit. Te rugăm să aștepți câteva secunde sau să repornești aplicația.</string>
@ -56,7 +50,6 @@
<string name="error_usb_prohibited">Accesul USB este interzis de către administratorul dispozitivului. Verifică setarile Knox sau MDM.</string>
<string name="unable_to_pin_shortcut">Launcher-ul tău curent nu permite crearea de scurtături fixate.</string>
<string name="video_decoder_init_failed">Inițializarea decodorului video a eșuat. Este posibil ca acest dispozitiv să nu suporte rezoluția sau rata cadrelor selectată.</string>
<!-- Start application messages -->
<string name="conn_establishing_title">Se stabilește conexiunea</string>
<string name="conn_establishing_msg">Se pornește conexiunea</string>
@ -69,7 +62,6 @@
<string name="conn_error_msg">Pornirea a eșuat</string>
<string name="conn_terminated_title">Conexiunea închisă</string>
<string name="conn_terminated_msg">Conexiunea a fost terminată</string>
<!-- General strings -->
<string name="ip_hint">Adresa IP a PC-ului cu GFE</string>
<string name="searching_pc">Se caută PC-uri cu GameStream activat…\n\n
@ -87,7 +79,6 @@
<string name="perf_overlay_renderingfps">Rata de afisare a cadrelor: %1$.2f FPS</string>
<string name="perf_overlay_netdrops">Cadre pierdute de rețea: %1$.2f%%</string>
<string name="perf_overlay_dectime">Timpul mediu de decodare: %1$.2f ms</string>
<!-- AppList activity -->
<string name="applist_connect_msg">Se conectează la PC…</string>
<string name="applist_menu_resume">Continuă Sesiunea</string>
@ -106,7 +97,6 @@
<string name="applist_quit_fail">Nu s-a putut închide lista</string>
<string name="applist_quit_confirmation">Sigur dorești să închizi aplicația curentă? Toate datele nesalvate vor fi pierdute.</string>
<string name="applist_details_id">ID-ul aplicației:</string>
<!-- Add computer manually activity -->
<string name="title_add_pc">Adaugă PC manual</string>
<string name="msg_add_pc">Conectare în curs…</string>
@ -115,7 +105,6 @@
<string name="addpc_unknown_host">Nu am putut identifica adresa PC-ului. Asigură-te că ai introdus-o corect.</string>
<string name="addpc_enter_ip">Trebuie să introduci o adresa IP</string>
<string name="addpc_wrong_sitelocal">Adresa introdusă nu pare corectă. Pentru conectare prin Internet, este nevoie de adresa publică a routerului.</string>
<!-- Preferences -->
<string name="category_basic_settings">Setări de bază</string>
<string name="title_resolution_list">Rezolutia video</string>
@ -131,11 +120,9 @@
<string name="summary_checkbox_disable_warnings">Dezactivează mesajele de avertizare privind rețeaua în timpul conexiunii</string>
<string name="title_checkbox_enable_pip">Activează modul Picture-In-Picture</string>
<string name="summary_checkbox_enable_pip">Permite vizualizarea (dar nu și controlul) când efectuezi multitasking</string>
<string name="category_audio_settings">Setări Audio</string>
<string name="title_audio_config_list">Configurarea sunetului surround</string>
<string name="summary_audio_config_list">Activeaza sunetul 5.1 sau 7.1 pentru sisteme home-theater</string>
<string name="category_input_settings">Setări de control</string>
<string name="title_checkbox_multi_controller">Detectează automat prezența controllerelor.</string>
<string name="summary_checkbox_multi_controller">Dezactivarea acestei opțiuni implică prezența constantă a unui controller</string>
@ -151,7 +138,6 @@
<string name="summary_checkbox_mouse_emulation">Apăsarea lungă pe butonul Start schimba modul de operare a controllerului în modul mouse.</string>
<string name="title_checkbox_mouse_nav_buttons">Activează butoanele de înainte și înapoi ale mousului</string>
<string name="summary_checkbox_mouse_nav_buttons">Această opțiune poate afecta click dreapta pentru unele dispozitive problematice.</string>
<string name="category_on_screen_controls_settings">Setări ale controalelor pe ecran</string>
<string name="title_checkbox_show_onscreen_controls">Afișează controale pe ecran</string>
<string name="summary_checkbox_show_onscreen_controls">Afișează un controller virtual pe ecran</string>
@ -168,19 +154,16 @@
<string name="summary_osc_opacity">Ajustează gradul de transparență al controalelor de pe ecran</string>
<string name="dialog_title_osc_opacity">Modifică opacitatea</string>
<string name="suffix_osc_opacity">%</string>
<string name="category_ui_settings">Setari UI</string>
<string name="title_language_list">Limba (Language)</string>
<string name="summary_language_list">Limba folosită de către Moonlight</string>
<string name="title_checkbox_small_icon_mode">Folosește iconițe mici</string>
<string name="summary_checkbox_small_icon_mode">Iconițele folosite în grile vor fi mici pentru a încăpea mai multe odata</string>
<string name="category_host_settings">Setările PC-ului gazdă</string>
<string name="title_checkbox_enable_sops">Optimizarea setărilor de joc</string>
<string name="summary_checkbox_enable_sops">Permite GFE să modifice setările jocurilor pentru experiența optimă</string>
<string name="title_checkbox_host_audio">Redă audio si pe PC</string>
<string name="summary_checkbox_host_audio">Sunetul se va auzi atat pe acest dispozitiv cât și pe PC</string>
<string name="category_advanced_settings">Setări avansate</string>
<string name="title_disable_frame_drop">Nu pierde cadre intenționat</string>
<string name="summary_disable_frame_drop">Poate să reducă micro-stuttering pe anumite device-uri, dar s-ar putea să crească latența</string>
@ -190,13 +173,9 @@
<string name="summary_enable_hdr">Folosește HDR daca aplicația si placa video suportă. Necesită o placa video seria GTX 1000 sau mai nouă.</string>
<string name="title_enable_perf_overlay">Activează statisticile de performanță</string>
<string name="summary_enable_perf_overlay">Afișează în timp real statisticile de performanță ale conexiunii.</string>
<!-- Array strings -->
<string name="audioconf_stereo">Stereo</string>
<string name="audioconf_51surround">Sunet Surround 5.1</string>
<string name="audioconf_71surround">Sunet Surround 7.1</string>
<string name="videoformat_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>

View File

@ -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>

View File

@ -0,0 +1,275 @@
<?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">Förbindelsen avbröts.</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>
<string name="toast_controller_type_changed">Spelkontroll-typ kan ändras på grund av rörelsesensoremulering</string>
<string name="summary_checkbox_gamepad_motion_fallback">Använder enhetens inbyggda rörelsesensorer om spelkontrollsensorer inte stöds av din anslutna spelkontroll eller din Android-version.
\nObs: Om du aktiverar det här alternativet kan din spelkontroll visas som en PlayStation-kontroller på värden.</string>
<string name="title_checkbox_gamepad_motion_fallback">Emulera spelkontroll rörelsesensor stöd</string>
<string name="error_code_prefix">Felkod:</string>
<string name="summary_analog_scrolling">Välj en analog spak för att scrolla när du är i musemuleringsläge</string>
<string name="analogscroll_none">Ingen (båda spakarna flyttar musen)</string>
<string name="analogscroll_left">Vänster analogspak</string>
<string name="title_seekbar_vibrate_fallback_strength">Justera intensiteten på emulerat skakande</string>
<string name="summary_seekbar_vibrate_fallback_strength">Förstärk eller reducera vibrationsintensiteten på din enhet</string>
<string name="analogscroll_right">Höger analogspak</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
<string name="title_analog_scrolling">Använd en analog spak för att bläddra</string>
</resources>

View File

@ -16,7 +16,7 @@
<string name="pair_fail">Створення пари не вдалося</string>
<!-- WOL messages -->
<string name="wol_pc_online">Пристрій у мережі</string>
<string name="wol_no_mac">Неможливо розбудити пристрій бо GFE не відправило MAC адреса</string>
<string name="wol_no_mac">Не вдається розбудити ПК, оскільки немає збереженої MAC-адреси</string>
<string name="wol_waking_pc">Пробудження пристрою…</string>
<string name="wol_waking_msg">Пробудження пристрою може зайняти кілька секунд. Якщо цього не відбувається, упевніться що Wake-On-LAN налаштований правильно.</string>
<string name="wol_fail">Помилка при відправці Wake-On-LAN пакетів</string>
@ -41,12 +41,12 @@
<string name="conn_error_title">Помилка з\'єднання</string>
<string name="conn_error_msg">Запуск не вдався</string>
<string name="conn_terminated_title">З\'єднання припинено</string>
<string name="conn_terminated_msg">З\'єднання перервано</string>
<string name="conn_terminated_msg">З’єднання було розірване.</string>
<!-- General strings -->
<string name="ip_hint">IP-адреса пристрою з GeForce</string>
<string name="searching_pc">Пошук пристроїв із запущеним GameStream
<string name="ip_hint">IP-адреса головного ПК</string>
<string name="searching_pc">Пошук головного ПК у локальній мережі
\n
\n Переконайтеся що GameStream увімкнений в налаштуваннях GeForce Experience в розділі SHIELD.</string>
\nПереконайтеся, що Sunshine запущено на вашому головному ПК або GameStream увімкнено в налаштуваннях GeForce Experience SHIELD.</string>
<string name="yes">Так</string>
<string name="no">Ні</string>
<string name="lost_connection">З\'єднання з пристроєм втрачено</string>
@ -100,8 +100,8 @@
<string name="title_checkbox_host_audio">Програвати звук на пристрої хоста</string>
<string name="summary_checkbox_host_audio">Програвати звук на пристроях хоста та клієнта</string>
<string name="category_advanced_settings">Розширені налаштування</string>
<string name="title_video_format">Змінити налаштування HEVC</string>
<string name="summary_video_format">HEVC знижує вимоги мережі, даючи можливість транслювати на повільних мережах але, вимагає нового пристрою з підтримкою цієї системи</string>
<string name="title_video_format">Змінити налаштування кодека</string>
<string name="summary_video_format">Нові кодеки можуть знизити вимоги до пропускної здатності відео, якщо ваш пристрій їх підтримує. Вибрані кодеки можуть ігноруватися, якщо вони не підтримуються програмним забезпеченням хоста або графічним процесором.</string>
<string name="category_on_screen_controls_settings">Налаштування екранних ґудзиків</string>
<string name="title_checkbox_show_onscreen_controls">Показувати екранні ґудзики</string>
<string name="summary_checkbox_show_onscreen_controls">Відображати віртуальні ґудзики контролера на екрані</string>
@ -115,7 +115,7 @@
<string name="help">Допомога</string>
<string name="applist_connect_msg">Підключення до пристрою…</string>
<string name="title_decoding_error">Збій відео розцифрувача</string>
<string name="message_decoding_error">Стався збій Moonlight через несумітність з відео розцифрувачем даного пристрою. Спробуйте змінити налаштування трансляції якщо збої продовжуватимуться.</string>
<string name="message_decoding_error">Moonlight аварійно завершив роботу через несумісність із відеодекодером цього пристрою. Спробуйте налаштувати параметри потокового передавання, якщо збої триватимуть.</string>
<string name="title_decoding_reset">Налаштування відео скинуті</string>
<string name="message_decoding_reset">Відео розцифрувач вашого пристрою продовжує давати збої з поточними налаштуваннями трансляції. Налаштування трансляції були скинуті до значень за замовчуванням.</string>
<string name="error_usb_prohibited">USB доступ заборонений адміністратором пристрою. Перевірте налаштування Knox або MDM.</string>
@ -134,16 +134,16 @@
<string name="title_disable_frame_drop">Ніколи не пропускати кадри</string>
<string name="summary_disable_frame_drop">Може зменшити мікрозависання на деяких пристроях але, також збільшити затримку</string>
<string name="title_enable_hdr">Увімкнути HDR (Експериментально)</string>
<string name="summary_enable_hdr">Транслювати в HDR якщо гра та відео карта на пристрої хоста підтримують це. HDR вимагає відеокарти серії GTX 1000 або новіше.</string>
<string name="summary_enable_hdr">Транслювати в HDR, якщо це підтримується грою та графічним процесором ПК. Для HDR потрібен графічний процесор із підтримкою кодування HEVC Main 10.</string>
<string name="title_checkbox_vibrate_osc">Увімкнути вібрацію</string>
<string name="title_fps_list">Частота кадрів</string>
<string name="applist_menu_details">Деталі</string>
<string name="applist_menu_details">Переглянути деталі</string>
<string name="applist_menu_scut">Створити ярлик</string>
<string name="category_input_settings">Налаштування введення</string>
<string name="title_checkbox_touchscreen_trackpad">Використовувати сенсорний екран як пальцевід</string>
<string name="summary_checkbox_touchscreen_trackpad">Якщо увімкнено, сенсорний екран працює як ноутбуковий пальцевід. Якщо вимкнено, безпосередньо керує вказівником миші.</string>
<string name="delete_pc_msg">Ви впевнені що хочете видалити цей пристрій\?</string>
<string name="pcview_menu_details">Деталі</string>
<string name="pcview_menu_details">Переглянути деталі</string>
<string name="poor_connection_msg">Слабке з\'єднання з пристроєм</string>
<string name="title_details">Деталі</string>
<string name="title_enable_perf_overlay">Увімкнути відображення статистики</string>
@ -176,24 +176,22 @@
<string name="suffix_osc_opacity">%</string>
<string name="title_enable_post_stream_toast">Статистика затримки після трансляції</string>
<string name="summary_enable_post_stream_toast">Показувати статистику затримки після закінчення трансляції</string>
<string name="early_termination_error">Щось пішло не так на пристрої хоста при початку трансляції.
<string name="early_termination_error">Щось пішло не так на вашому головному ПК під час запуску потоку.
\n
\nПереконайтеся, що на головному ПК немає відкритого вмісту, захищеного DRM. Ви також можете спробувати перезавантажити головний ПК.
\n
\nЯкщо проблема не зникає, спробуйте перевстановити драйвери GPU та GeForce Experience.</string>
\nПереконайтеся, що на головному ПК немає відкритого вмісту, захищеного DRM. Ви також можете спробувати перезавантажити головний ПК.</string>
<string name="nettest_text_success">Схоже що ваша мережа не блокує Moonlight. Якщо у вас й надалі проблеми з підключенням, перевірте налаштування брандмауера.
\n
\nЯкщо ви намагаєтеся транслювати через Інтернет, встановіть на своєму пристрої Moonlight Internet Hosting Tool, та запустіть випробування мережі щоб перевірити ваше з\'єднання до Інтернету.</string>
<string name="resolution_prefix_native_fullscreen">Рідний повноекранний</string>
<string name="resolution_prefix_native">Рідна</string>
<string name="suffix_seekbar_bitrate_mbps">Мб/с</string>
<string name="text_native_res_dialog">Режими рідної роздільної здатності не підтримуються офіційно через GeForce Experience, і тому не змінять роздільну здатність хоста на ту що в клієнта автоматично. Вам потрібно буде виставити її самостійно у грі.
<string name="text_native_res_dialog">Власна роздільна здатність і/або FPS можуть не підтримуватися потоковим сервером. Ймовірно, вам доведеться вручну налаштувати відповідний спеціальний режим відображення для головного ПК.
\n
\nЯкщо ви вирішили створити власну роздільну здатність у панелі керування NVIDIA переконайтеся, що ви прочитали та зрозуміли попередження NVIDIA щодо можливих пошкоджень монітора, нестабільності пристрою та інших потенційних проблем.
\nЯкщо ви вирішили вказати спеціальну роздільну здатність на панелі керування NVIDIA відповідно до налаштувань екрана, переконайтеся, що ви прочитали та зрозуміли попередження NVIDIA щодо можливого пошкодження монітора, нестабільної роботи ПК та інших потенційних проблем.
\n
\nМи не несемо відповідальності за будь-які проблеми, спричинені створенням власних роздільних здатностей на ваших пристроях.
\nМи не несемо відповідальності за будь-які проблеми, що виникли в результаті встановлення власної роздільної здатності на вашому ПК.
\n
\nЗрештою, пристрої клієнта чи хоста можуть не підтримувати трансляції рідною роздільною здатністю. Якщо це не працює на вашому пристрої, вам на жаль просто не пощастило.</string>
\nМожливо, ваш монітор не підтримує необхідну конфігурацію дисплея. Якщо так, ви можете спробувати налаштувати віртуальний монітор. Врешті-решт, якщо ваш пристрій або хост-комп’ютер не підтримує потокове передавання з певною роздільною здатністю чи частотою оновлення, вам, на жаль, не пощастило.</string>
<string name="title_native_res_dialog">Застереження про рідну роздільну здатність</string>
<string name="applist_menu_hide_app">Сховати застосунок</string>
<string name="perf_overlay_netlatency">Середня затримка мережі: %1$d мс (розбіжність %2$d мс)</string>
@ -209,18 +207,17 @@
\n</string>
<string name="nettest_text_inconclusive">Не вдалося перевірити мережу, тому що усі мережо-перевірочні сервери Moonlight недосяжні. Перевірте ваше з\'єднання з інтернетом та спробуйте знову.</string>
<string name="nettest_title_done">Перевірка мережі завершена</string>
<string name="nettest_text_waiting">Moonlight перевіряє мережеве з\'єднання щоб визначити чи заблокований NVIDIA GameStream.
<string name="nettest_text_waiting">Moonlight перевіряє ваше мережеве з’єднання, щоб визначити, чи заблоковані необхідні порти.
\n
\nЦе займе кілька секунд…</string>
\nЦе може зайняти кілька секунд…</string>
<string name="nettest_title_waiting">Перевіряємо з\'єднання</string>
<string name="pcview_menu_test_network">Перевірити мережеве з\'єднання</string>
<string name="pcview_menu_header_unknown">Оновлення</string>
<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>
@ -261,4 +258,29 @@
\nСпробуйте вимкнути режим HDR, змінити роздільну здатність потокового відео або змінити роздільну здатність дисплея головного комп\'ютера.</string>
<string name="title_full_range">Сила повного спектру відео (експериментальна)</string>
<string name="summary_full_range">Це може призвести до втрати деталей у світлих і темних областях, якщо пристрій не відображає належним чином весь діапазон відеоконтенту.</string>
<string name="pair_pairing_help">Якщо на вашому комп’ютері встановлений Sunshine, перейдіть до веб-інтерфейсу користувача Sunshine, щоб ввести PIN-код.</string>
<string name="error_code_prefix">Код помилки:</string>
<string name="title_seekbar_vibrate_fallback_strength">Налаштування інтенсивності вібро</string>
<string name="summary_seekbar_vibrate_fallback_strength">Посилюйте або зменшуйте інтенсивність вібрації пристрою</string>
<string name="title_checkbox_gamepad_motion_fallback">Емуляція підтримки датчика руху геймпада</string>
<string name="videoformat_av1always">Використовувати AV1 (експериментальний)</string>
<string name="videoformat_h264always">Використовувати H.264</string>
<string name="fps_suffix_fps">FPS</string>
<string name="title_native_fps_dialog">Попередження рідного FPS</string>
<string name="category_gamepad_settings">Налаштування геймпада</string>
<string name="title_analog_scrolling">Використовувати аналоговий стік для прокручування</string>
<string name="summary_analog_scrolling">Виберіть аналоговий стік для прокручування під час режиму емуляції миші</string>
<string name="analogscroll_none">Немає (обидва стіка пересувають мишу)</string>
<string name="analogscroll_right">Аналоговий стік праворуч</string>
<string name="analogscroll_left">Аналоговий стік ліворуч</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
<string name="title_checkbox_gamepad_touchpad_as_mouse">Завжди керувати мишею за допомогою сенсорної панелі</string>
<string name="summary_checkbox_gamepad_touchpad_as_mouse">Примусове використання сенсорної панелі геймпада для керування основною мишею, навіть якщо емулюється геймпад із сенсорною панеллю.</string>
<string name="title_checkbox_gamepad_motion_sensors">Дозволити використовувати датчики руху геймпада</string>
<string name="summary_checkbox_gamepad_motion_sensors">Дозволяє підтримуваним хостам запитувати дані датчиків руху під час емуляції геймпада з датчиками руху. Якщо в грі не використовуються датчики руху, вимкнення може дещо зменшити енергоспоживання та використання мережі.</string>
<string name="summary_checkbox_gamepad_motion_fallback">Використовує вбудовані датчики руху вашого пристрою, якщо датчики геймпада не підтримуються підключеним геймпадом або вашою версією Android.
\nПримітка. Якщо ввімкнути цей параметр, ваш геймпад може відображатися як контролер PlayStation на хості.</string>
<string name="toast_controller_type_changed">Тип геймпада може бути змінений через емуляцію датчика руху</string>
<string name="pcview_menu_eol">Закриття сервісів NVIDIA GameStream</string>
<string name="perf_overlay_hostprocessinglatency">Затримка обробки хостом мін./макс./середня: %1$.1f/%2$.1f/%3$.1f мс</string>
</resources>

View File

@ -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

View File

@ -58,7 +58,7 @@
<string name="conn_error_title"> 连接错误 </string>
<string name="conn_error_msg"> 启动失败 </string>
<string name="conn_terminated_title"> 连接终结 </string>
<string name="conn_terminated_msg"> 连接已被终结 </string>
<string name="conn_terminated_msg">连接已被终结.</string>
<!-- General strings -->
<string name="ip_hint">串流电脑的IP地址</string>
<string name="searching_pc">在你的本地网络中搜索串流主机PC...
@ -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,27 @@
<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>
<string name="error_code_prefix">错误代码:</string>
<string name="title_seekbar_vibrate_fallback_strength">调整模拟震动强度</string>
<string name="suffix_seekbar_vibrate_fallback_strength"></string>
<string name="title_analog_scrolling">使用摇杆控制鼠标移动</string>
<string name="analogscroll_left">左摇杆</string>
<string name="analogscroll_right">右摇杆</string>
<string name="summary_analog_scrolling">在鼠标模式下选择用哪个摇杆控制鼠标移动</string>
<string name="summary_seekbar_vibrate_fallback_strength">增强或减弱设备的震动强度</string>
<string name="analogscroll_none">默认 (两个摇杆都控制鼠标)</string>
</resources>

View File

@ -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>

View File

@ -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>
@ -112,4 +120,15 @@
<item>cap-fps</item>
<item>smoothness</item>
</string-array>
<string-array name="analog_scrolling_names">
<item>@string/analogscroll_none</item>
<item>@string/analogscroll_right</item>
<item>@string/analogscroll_left</item>
</string-array>
<string-array name="analog_scrolling_values" translatable="false">
<item>none</item>
<item>right</item>
<item>left</item>
</string-array>
</resources>

View File

@ -90,7 +90,8 @@
<string name="conn_error_title">Connection Error</string>
<string name="conn_error_msg">Failed to start</string>
<string name="conn_terminated_title">Connection Terminated</string>
<string name="conn_terminated_msg">The connection was terminated</string>
<string name="conn_terminated_msg">The connection was terminated.</string>
<string name="error_code_prefix">Error code:</string>
<!-- General strings -->
<string name="ip_hint">IP address of host PC</string>
@ -108,6 +109,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 +148,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 +159,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,13 +168,14 @@
<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>
<string name="summary_checkbox_vibrate_fallback">Vibrates your device to emulate rumble if your gamepad does not support it</string>
<string name="title_seekbar_vibrate_fallback_strength">Adjust emulated rumble intensity</string>
<string name="summary_seekbar_vibrate_fallback_strength">Amplify or reduce the vibration intensity on your device</string>
<string name="suffix_seekbar_vibrate_fallback_strength">%</string>
<string name="title_seekbar_deadzone">Adjust analog stick deadzone</string>
<string name="summary_seekbar_deadzone">Note: Some games can enforce a larger deadzone than what Moonlight is configured to use.</string>
<string name="suffix_seekbar_deadzone">%</string>
@ -180,12 +185,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>
@ -194,6 +209,8 @@
<string name="summary_checkbox_vibrate_osc">Vibrates your device to emulate rumble for the on-screen controls</string>
<string name="title_only_l3r3">Only show L3 and R3</string>
<string name="summary_only_l3r3">Hide all virtual buttons except L3 and R3</string>
<string name="title_show_guide_button">Show Guide Button</string>
<string name="summary_show_guide_button">Show the guide button on screen</string>
<string name="title_reset_osc">Clear saved on-screen controls layout</string>
<string name="summary_reset_osc">Resets all on-screen controls to their default size and position</string>
<string name="dialog_title_reset_osc">Reset Layout</string>
@ -227,8 +244,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 +263,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 +283,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>
@ -273,4 +294,10 @@
<string name="pacing_balanced">Balanced</string>
<string name="pacing_balanced_alt">Balanced with FPS limit</string>
<string name="pacing_smoothness">Prefer smoothest video (may significantly increase latency)</string>
<string name="title_analog_scrolling">Use an analog stick to scroll</string>
<string name="summary_analog_scrolling">Select an analog stick to scroll when in mouse emulation mode</string>
<string name="analogscroll_none">None (both sticks move the mouse)</string>
<string name="analogscroll_right">Right analog stick</string>
<string name="analogscroll_left">Left analog stick</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More