Compare commits

..
495 Commits
Author SHA1 Message Date
Cameron Gutman b23a36908c Add EGLFS GBM and Wayland support to AppImage 2022-04-09 18:23:09 -05:00
Cameron Gutman e3a7b54f90 Use EGL fences to reduce video latency 2022-04-08 19:28:22 -05:00
Cameron Gutman 81d5e7f014 Wait for the VDPAU output surface to be idle in waitToRender() 2022-04-07 22:16:52 -05:00
Cameron Gutman 9790c218dc Wait on the display link callback before rendering to reduce latency 2022-04-07 22:08:43 -05:00
Cameron Gutman 6d3d51553b Wait on our D3D11 swapchain before rendering to reduce latency 2022-04-07 21:46:48 -05:00
Cameron Gutman 474591c6a5 Use a separate callback to indicate EOS instead of renderFrame() 2022-04-07 21:30:20 -05:00
Cameron Gutman 5de0dc2713 Disable the decoder selection options when HDR is enabled 2022-04-05 20:09:09 -05:00
Cameron Gutman 57a34a7abb Update README.md 2022-04-05 19:56:20 -05:00
Cameron Gutman 54517bda1b Switch back to upstream SDL 2022-04-05 00:59:58 -05:00
Cameron Gutman 4291e15b60 Use NDC helpers in D3D11VA renderer 2022-04-05 00:57:14 -05:00
Cameron Gutman 940ae6406b Add helper functions to perform NDC transformations 2022-04-05 00:50:04 -05:00
Cameron Gutman 6a0cf4bfd3 Fix some #if -> #ifdefs 2022-04-05 00:26:13 -05:00
Cameron Gutman fee6f75223 Fix VAAPIRenderer build error with neither HAVE_EGL nor HAVE_DRM defined 2022-04-05 00:24:00 -05:00
Cameron Gutman 8c93b2d54c Fix VAAPIRenderer build error with HAVE_DRM but not HAVE_EGL 2022-04-04 19:40:31 -05:00
Cameron Gutman 09ed82db65 Fix build with HAVE_MMAL 2022-04-02 16:16:40 -05:00
Cameron Gutman a56cb0e88a Don't waste time retrying the same renderer again 2022-04-02 16:14:04 -05:00
Cameron Gutman 9acf5ff0ef Update workaround to prevent deadlock with h264_mmal 2022-04-02 16:06:39 -05:00
Cameron Gutman 64a7790aed Patch SDL to work around GLX crash 2022-04-02 15:50:32 -05:00
Cameron Gutman 9a5134ffcf Use QString not QByteArray for string equality 2022-04-02 15:49:07 -05:00
Cameron Gutman 1d2c4d0843 Prepare for v4.0.0 2022-04-01 19:18:51 -05:00
Cameron Gutman efad34be62 Set SDL_MOUSE_AUTO_CAPTURE=0 since we manage mouse capture ourselves 2022-03-31 23:54:58 -05:00
Cameron Gutman 52761ade87 Update SDL_ttf to 81f9e9b 2022-03-31 23:30:59 -05:00
Cameron Gutman e6b816e776 Update SDL in AppImage 2022-03-30 23:31:01 -05:00
Cameron Gutman 6d3bcba5d0 Update SDL, SDL_ttf, and FreeType
SDL -> 2c04df8
SDL_ttf -> 80d909 (Windows)
FreeType -> 3f83da (Windows)
2022-03-30 23:27:40 -05:00
Cameron Gutman 2e7ffa606b Fix missing DLL in ARM64 builds 2022-03-30 22:43:31 -05:00
Cameron Gutman 055cae90b8 Only apply the AMD color range workaround to new drivers
Applying it to older drivers introduces the very same issues it's meant to fix
2022-03-30 22:43:08 -05:00
Cameron Gutman 23acf92803 Update SDL_GameControllerDB 2022-03-30 22:07:33 -05:00
Cameron Gutman 91ee7d76eb Rerun lupdate and lrelease 2022-03-30 22:07:11 -05:00
Cameron Gutman 570888e2b8 Merge remote-tracking branch 'origin/weblate' 2022-03-30 22:06:02 -05:00
sanhoe 282f27f0c8 Translated using Weblate (Korean)
Currently translated at 100.0% (193 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ko/
2022-03-30 18:10:36 +02:00
Cameron Gutman 98376ade45 Update SDL to cbdb67b 2022-03-29 22:39:09 -05:00
Cameron Gutman 9682968b55 Fix FFmpeg URL for AppImage 2022-03-29 21:34:34 -05:00
Cameron Gutman 877cb5f1b0 Update SDL2, SDL_ttf, and FFmpeg in AppImage build 2022-03-29 21:03:35 -05:00
Cameron Gutman 6972573a6e Add pointer lock key combo
Fixes #737
2022-03-29 18:26:09 -05:00
Cameron Gutman 742f1b1283 Prefer hevc_nvv4l2 over hevc_nvmpi 2022-03-26 22:54:54 -05:00
The Great Wizard Azkali 0b127a2f3b Add support for h264_nvv4l2 and hevc_nvv4l2 (#745)
* Add support for h264_nvv4l2

A new implementation of nvv4l2 decoder has been made by @CTCaer and will be released in thr next switchroot (Linux for Nintendo Switch) update. This implementation of ffmpeg can also be used by other Jetson boards. A repository will be soon hosted so Jetson users can install it.
Prior to the new implementation distribution, we add it to the project who currently use nvmpi implementation.

* Add support for hevc_nvv4l2

Following previous PR, add hevc support as well.
2022-03-26 22:02:00 -05:00
Wen-haur Chiu a6057835a8 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (193 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2022-03-25 18:11:42 +01:00
CorteX c32794477e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (193 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2022-03-23 06:58:35 +01:00
reloxx13 999ac60bda Translated using Weblate (German)
Currently translated at 100.0% (193 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/de/
2022-03-21 09:59:13 +01:00
bruh bca4b832a8 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (193 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/vi/
2022-03-19 22:58:21 +01:00
Cameron Gutman 2fc1dda232 Partially revert e64b15d and b85d5b8
These changes cause excessive window recreation using the Flatpak on Nvidia with Wayland
2022-03-19 14:50:38 -05:00
Cameron Gutman 99495cff90 Add logging for cases where color range/encoding cannot be set 2022-03-19 13:12:41 -05:00
Caio Gabriel 795962a4ba Translated using Weblate (Portuguese (Brazil))
Currently translated at 7.7% (15 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/pt_BR/
2022-03-18 22:29:44 +01:00
Caio Gabriel 7bde9f447a Translated using Weblate (Portuguese (Brazil))
Currently translated at 7.7% (15 of 193 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/pt_BR/
2022-03-18 20:05:48 +01:00
Cameron Gutman b45c3e3c7f Tweak wording on the keep awake option 2022-03-16 21:59:06 -05:00
Cameron Gutman ce2a01fc59 Allow the screensaver toggle to work even if running on an embedded platform 2022-03-16 21:57:03 -05:00
Cameron Gutman edeea65c3e Rerun lupdate and lrelease 2022-03-16 21:51:17 -05:00
Cameron Gutman 6e8ee94b91 Merge remote-tracking branch 'origin/weblate' 2022-03-16 21:49:44 -05:00
Cameron Gutman 97d8274911 Add option to allow PC to sleep while streaming 2022-03-16 21:48:56 -05:00
Cameron Gutman 73d84dc13f Update SDL and OpenSSL prebuilts 2022-03-15 22:30:55 -05:00
Cameron Gutman f32501d498 Update moonlight-common-c 2022-03-15 21:22:44 -05:00
Cameron Gutman 9c289c3fe9 Update SDL_GameControllerDB 2022-03-15 21:22:21 -05:00
Cameron Gutman 2a610584ee Fix handling of line continuations in FFmpeg logs (for real this time) 2022-03-11 19:15:36 -06:00
sanhoe 8e06421567 Translated using Weblate (Korean)
Currently translated at 100.0% (191 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ko/
2022-03-10 18:59:01 +01:00
Wen-haur Chiu 57dc3725f5 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (191 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2022-03-09 15:58:49 +01:00
Cameron Gutman d6ef8945f5 Replace Deviare In-Proc with Microsoft Detours 2022-03-08 20:58:40 -06:00
Cameron Gutman e078a8b7b6 Don't recreate the decoder while the window is minimized
Fixes #726
2022-03-06 15:21:43 -06:00
Cameron Gutman a6395b9025 Fix short UI hang when manually stopping the stream after losing connection with the host 2022-03-06 13:11:36 -06:00
Cameron Gutman 6c0983d77c Reset the audio device if it enters a failed state
Fixes #734
2022-03-05 16:50:06 -06:00
Cameron Gutman 4ae39f2bd5 Properly synchronize rumble with gamepad removal 2022-03-05 13:32:38 -06:00
bruh 71fc701809 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (191 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/vi/
2022-03-02 11:57:09 +01:00
Aurora Robb Kristiansen d418921e4b Translated using Weblate (Norwegian Bokmål)
Currently translated at 73.2% (140 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nb_NO/
2022-02-28 11:55:22 +01:00
Cameron Gutman 4b83b022d3 Remove unnecessary assert 2022-02-25 22:47:20 -06:00
Cameron Gutman 8b13e5b47e Update AppImage to libva 2.14 2022-02-25 22:46:52 -06:00
Benjamín Bustos 0bfd565bda Translated using Weblate (Spanish)
Currently translated at 100.0% (191 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2022-02-23 16:56:13 +01:00
Emanuele Conti 2224a558ee Translated using Weblate (Italian)
Currently translated at 100.0% (191 of 191 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/it/
2022-02-22 15:56:43 +01:00
Cameron Gutman 93c02fb43a Print GPU info in D3D11VA renderer 2022-02-20 22:10:18 -06:00
Cameron Gutman 93ee51cabb Integrate new languages from Weblate 2022-02-20 14:15:08 -06:00
Cameron Gutman cd6ba554a4 Merge remote-tracking branch 'origin/weblate' 2022-02-20 13:44:11 -06:00
Cameron Gutman 89aa2be358 Rerun lupdate and lrelease 2022-02-20 13:41:48 -06:00
Cameron Gutman da261246b9 Change HDR to be a separate option like other clients 2022-02-19 11:21:06 -06:00
Cameron Gutman 4d3e09f4a0 Raise minimum custom resolution to 256x256 2022-02-19 10:47:25 -06:00
Cameron Gutman 9add6b3696 Add DXVA2 quirk for AMD GPUs to fix color range on the latest drivers 2022-02-17 00:35:33 -06:00
Cameron Gutman ef037e18d0 Add colorspace and color range override options 2022-02-17 00:26:56 -06:00
Cameron Gutman 36db791516 Refactor D3D11 shaders to reduce duplicated code 2022-02-16 19:38:18 -06:00
Emanuele Conti 25d2ea5e94 Translated using Weblate (Italian)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/it/
2022-02-16 13:57:22 +01:00
Jorys Paulin 34f2d18f27 Translated using Weblate (French)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2022-02-16 13:57:21 +01:00
Aurora Robb Kristiansen 4935c846aa Translated using Weblate (Norwegian Bokmål)
Currently translated at 73.0% (138 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nb_NO/
2022-02-14 01:57:01 +01:00
Cameron Gutman b1f980c216 Fix handling of line continuations in FFmpeg logs 2022-02-13 16:06:04 -06:00
Cameron Gutman 738f64c903 Use FP32 for position and texcoords
We need that extra precision for sampling large textures
2022-02-13 13:41:39 -06:00
Emanuele Conti 7235663447 Translated using Weblate (Italian)
Currently translated at 46.0% (87 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/it/
2022-02-11 11:55:30 +01:00
Emanuele Conti 9d78c416f7 Translated using Weblate (Italian)
Currently translated at 44.9% (85 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/it/
2022-02-10 10:57:51 +01:00
Cameron Gutman 9a64c026ea Use optimized pixel shaders for the normal SDR and HDR colorspaces 2022-02-09 20:46:02 -06:00
Cameron Gutman be2af1d17a Add environment variables to configure DXVA2 and D3D11VA options 2022-02-08 22:27:27 -06:00
Cameron Gutman b21131a466 Use FP16 in the D3D11 shaders 2022-02-08 21:43:25 -06:00
Emanuele Conti 41c5126472 Translated using Weblate (Italian)
Currently translated at 39.6% (75 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/it/
2022-02-08 18:54:36 +01:00
Cameron Gutman b96cb1abaf Remove per-app HDR support check
It doesn't seem to make a difference anymore whether it's supported or not.
GFE seems happy to enter HDR mode anyway.
2022-02-07 20:02:19 -06:00
Emanuele Conti 20143606e2 Added translation using Weblate (Italian) 2022-02-07 09:27:18 +01:00
Cameron Gutman 1d79bcc657 Disable waitable swapchains in full-screen mode 2022-02-06 00:28:59 -06:00
Cameron Gutman e8b4494fc3 Add an extra buffer for DirectFlip 2022-02-05 23:22:07 -06:00
Cameron Gutman 2518208c5c Don't set fullScreenDesc fields to prevent entering "proxy" full-screen mode 2022-02-05 19:32:05 -06:00
Cameron Gutman 918fea7d4b Precompute the aspect ratio stretch to avoid having to change viewports twice each frame 2022-02-05 15:44:37 -06:00
Cameron Gutman 4dc07bf63f Don't render the alignment padding area 2022-02-05 15:23:29 -06:00
Cameron Gutman 04a0aca221 Create SRVs for all textures in the pool during initialization 2022-02-05 14:49:08 -06:00
Cameron Gutman 1942e72474 Only bind the constant buffer once 2022-02-05 14:15:35 -06:00
Cameron Gutman f256407789 Implement D3D11VA video rendering 2022-02-04 21:51:34 -06:00
Cameron Gutman 67612f607e WIP: D3D11VA support
Overlays work, but drawing the actual video is unimplemented
2022-02-03 19:45:07 -06:00
Wh1t3st4r 7274c42126 Translated using Weblate (Portuguese)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/pt/
2022-02-01 16:52:52 +01:00
Wh1t3st4r e288402e88 Added translation using Weblate (Portuguese (Brazil)) 2022-01-31 16:08:53 +01:00
Cameron Gutman 76bd4a1c7b Don't set the HDR metadata blob if we don't have one 2022-01-30 22:57:53 -06:00
Cameron Gutman 13dbad6f35 Fix build with old libdrm headers 2022-01-30 22:56:22 -06:00
Cameron Gutman cf089fdfe9 Add support for HDR with VAAPI using DRM frontend renderer 2022-01-29 18:16:39 -06:00
Cameron Gutman 9755e31fa2 Refactor VAAPI surface export check into separate function 2022-01-29 17:45:36 -06:00
Cameron Gutman 3fcf31d009 Improve robustness of EGL retry logic for 10-bit color 2022-01-29 01:12:38 -06:00
Cameron Gutman 1cbdd0e675 Display the HDR option if the platform has a decoder that supports it 2022-01-29 00:59:04 -06:00
Cameron Gutman e0fd84d6f5 Fix build with old libdrm headers 2022-01-29 00:28:46 -06:00
Cameron Gutman 443720c3de Plumb HDR metadata into DRM renderer 2022-01-28 22:40:07 -06:00
Cameron Gutman 254526a213 Plumb HDR mode information to the decoders 2022-01-28 22:10:50 -06:00
Cameron Gutman ad0afb5fc9 Prefer direct rendering when using HDR 2022-01-27 22:36:49 -06:00
Cameron Gutman e64b15d2a7 Rework how we deal with window re-creation for EGLRenderer
Previously we opted to just lie to SDL and tell it that the current
GL context is actually GLES 3.0 when it wasn't. This meant that
we avoided our window being recreated for GLES usage on Wayland
and KMSDRM, but that meant our 10-bit color change didn't apply
either. I suspect this hackery is what led EGLRenderer to get
stuck in a state where SDL_CreateRenderer() always failed.

Now SDL will recreate our window once to configure a compatible GL
API for our renderer. If that fails, we'll move on to a different
renderer (which may recreate the window again).
2022-01-27 21:49:03 -06:00
Cameron Gutman cdc3352318 Ensure SDL also uses X11 if Qt is using X11 2022-01-26 19:00:41 -06:00
Cameron Gutman 2416618b34 Don't require 2 bits of alpha for 10-bit color 2022-01-26 18:55:56 -06:00
GeraltOfTrivia c951d77a52 Translated using Weblate (Greek)
Currently translated at 96.2% (182 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/el/
2022-01-25 17:53:11 +01:00
GeraltOfTrivia 759ddc0b4b Added translation using Weblate (Greek) 2022-01-24 16:49:31 +01:00
Cameron Gutman a0709bec51 Improve debugging and add missing break 2022-01-23 21:12:32 -06:00
Cameron Gutman f5bc4e7a24 Add color properties to DRM renderer 2022-01-23 21:03:56 -06:00
Cameron Gutman b4665b6e5a Pick a 10-bit DRM overlay for Main10 streaming 2022-01-23 19:19:16 -06:00
Cameron Gutman b85d5b8822 Enable P010 surface export from VAAPI to EGL 2022-01-23 18:33:30 -06:00
Cameron Gutman 12ad75a6b0 Move hybrid decode detection logic into a central location 2022-01-23 15:41:33 -06:00
Cameron Gutman af92fe6ad1 Fix Apple silicon CPU check 2022-01-23 13:01:20 -06:00
Cameron Gutman fcf7ed4faa Only use the VT rasterization workaround on Apple silicon 2022-01-22 20:25:50 -06:00
Cameron Gutman a58649fd10 Update Windows and macOS to FFmpeg 5.0 2022-01-22 13:44:05 -06:00
Cameron Gutman ee5918cf4e Revert "Add workaround for duplicate size changed events on Wayland"
Skipping size changed events can cause EGLRenderer to get stuck in
a state where it can't reset itself properly. This seems to happen
consistently when starting a maximized stream then transitioning
to full-screen.

This reverts commit e1b3f90f8b.
2022-01-22 12:29:44 -06:00
Wh1t3st4r d7de3301ed Translated using Weblate (Portuguese)
Currently translated at 76.7% (145 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/pt/
2022-01-22 07:20:29 +01:00
Wh1t3st4r bd1988c775 Added translation using Weblate (Portuguese) 2022-01-22 00:51:36 +01:00
Faiq Chilmi 474010b31d Translated using Weblate (Hindi)
Currently translated at 18.5% (35 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/hi/
2022-01-21 15:52:46 +01:00
Cameron Gutman dd941154d6 Fix EGL renderer overlay rendering with SDL_ttf 2.0.18
Fixes #721
2022-01-20 18:02:44 -06:00
WoweePaw cbb53745f6 Translated using Weblate (German)
Currently translated at 99.4% (188 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/de/
2022-01-20 15:09:46 +01:00
Faiq Chilmi 3dff62e0cf Added translation using Weblate (Hindi) 2022-01-20 15:09:46 +01:00
Cameron Gutman 719024ec01 Prepare for v3.2.0 release 2022-01-18 18:33:23 -06:00
Cameron Gutman f0659b4f3c Fix random crash on stream start with renderers that require test frames 2022-01-18 18:19:28 -06:00
Cameron Gutman a649f2736f Rerun lupdate and lrelease 2022-01-18 18:07:17 -06:00
Cameron Gutman 046ccb1dee Merge remote-tracking branch 'origin/weblate' 2022-01-18 18:05:42 -06:00
Tygo T d340556c28 Translated using Weblate (Dutch)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nl/
2022-01-19 01:04:10 +01:00
Wout Rombouts 32250db126 Translated using Weblate (Dutch)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nl/
2022-01-19 01:04:10 +01:00
Cameron Gutman cb8c30db2e Add workaround for keyboard and UTF-8 events interfering with each other 2022-01-17 21:56:39 -06:00
Cameron Gutman dacd5a9e3d Discard stale gamepad events when enabling gamepad navigation 2022-01-17 19:49:52 -06:00
Cameron Gutman 859d8b96a7 Don't use duplicate resize workaround on SDL 2.0.21+ 2022-01-17 19:25:43 -06:00
Cameron Gutman 02981e3cee Update SDL to pick up HIDAPI deadzone fix 2022-01-17 19:23:42 -06:00
Cameron Gutman 49892b3ce8 Only use SDL_WaitEventTimeout() on SDL 2.0.18+ 2022-01-17 16:59:45 -06:00
Cameron Gutman b223e7ec36 Update SDL_GameControllerDB 2022-01-17 15:57:36 -06:00
Cameron Gutman 0926337c1d Rerun lupdate and lrelease 2022-01-17 15:56:39 -06:00
Cameron Gutman 346e72a678 Merge remote-tracking branch 'origin/weblate' 2022-01-17 15:55:12 -06:00
Wout Rombouts d612e47b62 Translated using Weblate (Dutch)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nl/
2022-01-17 22:54:04 +01:00
Cameron Gutman c138cbf994 Fix Windows build 2022-01-17 15:47:36 -06:00
Cameron Gutman dfe275ab67 Avoid consuming stale data during/after decoder reset 2022-01-17 15:26:00 -06:00
Cameron Gutman d6cfbdb273 Rewrite FFmpeg decoder to use pull model
This allows us to keep asynchronous decoders like MMAL and V4L2M2M fed
while we're waiting for output frames. Behavior for synchronous decoders
should be identical.

Continuing to feed new data while waiting for output frames is crucial for
acceptable performance on 1080p video on the Raspberry Pi using V4L2M2M,
since it allows the decode and copy operations to be pipelined.
2022-01-17 15:06:12 -06:00
Cameron Gutman 8a27fa7bb5 Convert NeedsIdr member into an atomic variable with a getter 2022-01-17 14:30:12 -06:00
Cameron Gutman b9a6fb1fe5 Add workaround for AVSampleBufferDisplayLayer colorspace and artifacting issues
Fixes #493
2022-01-15 14:44:08 -06:00
Cameron Gutman 4b6194e15e Add chroma location buffer attachment 2022-01-15 12:17:31 -06:00
Cameron Gutman e1b3f90f8b Add workaround for duplicate size changed events on Wayland 2022-01-14 23:36:21 -06:00
Wen-haur Chiu c5cc0b8c59 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2022-01-13 12:56:43 +01:00
bruh 5c849ec666 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/vi/
2022-01-13 12:56:42 +01:00
Eric c2a30cbe19 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2022-01-13 12:56:42 +01:00
Cameron Gutman 31eddd8da0 Remove superfluous colorspace check 2022-01-13 01:19:17 -06:00
Cameron Gutman abf2a14ee6 Handle colorspace changes in SDL renderer 2022-01-13 01:16:09 -06:00
Cameron Gutman e555874485 Refactor WiX bundle description of VCRedist package 2022-01-12 19:14:59 -06:00
Cameron Gutman a7aef8f147 Use new WiX 3.14 variable instead of BuildLabEx hack for ARM64 detection 2022-01-12 19:14:44 -06:00
Cameron Gutman 5b8c11f1a9 Update and rebuild all dependencies with Xcode 13 and VS 2022
macOS minimum target version is now 10.14 Mojave

Updates:
OpenSSL 1.1.1m
SDL 2.0.20
libopus 12a356

https://github.com/cgutman/moonlight-deps 5cd31601c3362562b52d8124dfc33029506d1744
2022-01-11 20:49:11 -06:00
Cameron Gutman 645040c943 Update AppImage to SDL 2.0.20 2022-01-10 20:03:47 -06:00
Cameron Gutman fcc5ea348c Remove old FFmpeg build scripts
Superseded by https://github.com/cgutman/moonlight-deps
2022-01-10 19:49:41 -06:00
Héctor 3fbb45448f Translated using Weblate (Spanish)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2022-01-10 20:56:47 +01:00
Cameron Gutman 8a83289709 Switch to VS2022 build image 2022-01-09 21:55:41 -06:00
Cameron Gutman 08175de069 Fix incorrect colorspace in MMAL renderer 2022-01-09 17:04:38 -06:00
Cameron Gutman 808933cd70 Use DT files to get status of FKMS and rpivid 2022-01-09 16:44:20 -06:00
Cameron Gutman 384dd2adab Prefer a render node in indirect rendering mode 2022-01-08 18:39:12 -06:00
Jorys Paulin 4a37952b41 Translated using Weblate (French)
Currently translated at 100.0% (189 of 189 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2022-01-08 09:55:55 +01:00
lyashenko.v 1046d264d8 Fixed not working frame pacing on macOS 2022-01-06 23:23:00 -06:00
Cameron Gutman bb235ab1ae Rerun lupdate and lrelease 2022-01-06 23:19:16 -06:00
Cameron Gutman ef88b83727 Merge remote-tracking branch 'origin/weblate' 2022-01-06 23:15:48 -06:00
Cameron Gutman 5612e9864e Fix handling of some validation scenarios
- HEVC forced with no host or client hw support
- H.264 forced with no client hw support
- Client has hw HEVC only and host only supports H.264
- Client has no hw decode at all
2022-01-06 23:15:19 -06:00
Cameron Gutman 8302187dee Remove superfluous availability checks 2022-01-06 23:05:18 -06:00
Cameron Gutman 77d07c7c4d Fix incorrect error message when only HEVC decode is available but HEVC encode is not 2022-01-06 22:08:43 -06:00
Cameron Gutman b2265080fd Allow HEVC decoders to satisfy hardware decoding check if H.264 is unavailable 2022-01-06 22:07:31 -06:00
Cameron Gutman 0d70bd9ac0 Add (untested) VAAPI support for CCS planes on Tiger Lake
See https://github.com/intel/media-driver/issues/1210
2022-01-05 21:09:08 -06:00
Cameron Gutman 8f63d59b81 Correct comment to avoid confusion 2022-01-04 22:00:46 -06:00
Cameron Gutman 0395c0cc95 Revert "Revert "Don't attempt to use direct rendering without DRM master""
The correct fix was 154b5b6ded.

This reverts commit 8219dbef6f.
2022-01-04 21:59:02 -06:00
Cameron Gutman 72065412a3 Don't allow copyback rendering on RPi by default 2022-01-04 20:35:17 -06:00
Jorys Paulin 7af2cdd0ef Translated using Weblate (French)
Currently translated at 100.0% (187 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2022-01-03 11:52:50 +01:00
Cameron Gutman 67c801c4e7 Use av_frame_copy_props() to copy metadata 2022-01-02 17:38:58 -06:00
Cameron Gutman f7c8ad4c5a Fail render frame test for unsupported pixel formats 2022-01-02 15:03:49 -06:00
Cameron Gutman 61092b34de Properly handle mismatched pitch between frame and texture 2022-01-02 14:35:14 -06:00
Cameron Gutman 1e9e96fb8c Small code cleanup for hwframe code 2022-01-02 13:58:37 -06:00
Cameron Gutman 17d1ced07c Add support for mapping hwframes 2022-01-02 13:41:36 -06:00
Cameron Gutman a26ced04ff Add support for negotiating non-default transfer formats for hwframes 2022-01-01 22:15:43 -06:00
Cameron Gutman 154b5b6ded Fix fallback to SDL read-back for DRM contexts when !HAVE_EGL 2022-01-01 20:44:29 -06:00
Cameron Gutman 8219dbef6f Revert "Don't attempt to use direct rendering without DRM master"
We support indirect rendering via SDL, even if EGL is unavailable.

This reverts commit 6145913068.
2022-01-01 20:37:04 -06:00
Cameron Gutman 3da724e76a Fix and enhance the Full KMS check 2021-12-28 17:13:54 -06:00
Cameron Gutman 1616d237ae Avoid h264_v4l2m2m by default on RPi builds 2021-12-28 16:28:04 -06:00
Nikita Epifanov 3d21facc9f Translated using Weblate (Russian)
Currently translated at 100.0% (187 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ru/
2021-12-24 19:53:18 +01:00
Héctor fead2a08a3 Translated using Weblate (Spanish)
Currently translated at 96.2% (180 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-12-20 18:52:37 +01:00
Cameron Gutman d8acf24af0 Don't use SdlRenderer with MMAL 2021-12-19 20:58:50 -06:00
Cameron Gutman 97412b3c79 Display warnings about Full KMS mode and HEVC on the Pi 4 2021-12-19 20:33:48 -06:00
Cameron Gutman 6145913068 Don't attempt to use direct rendering without DRM master 2021-12-19 20:32:15 -06:00
Cameron Gutman e56bb6785f Change display mode when using KMSDRM backend 2021-12-18 21:07:35 -06:00
Cameron Gutman 6d63d6c54a Rerun lupdate and lrelease 2021-12-15 20:52:48 -06:00
Cameron Gutman 6e8a103e70 Merge remote-tracking branch 'origin/weblate' 2021-12-15 20:50:15 -06:00
Cameron Gutman 00d3530f64 Don't try VDPAU on XWayland by default 2021-12-15 20:49:12 -06:00
Cameron Gutman 1e6ca18193 Fix error checking in decode test 2021-12-15 17:33:28 -06:00
Cameron Gutman 5a32992497 Try to learn if decoders support retrying avcodec_receive_frame() 2021-12-14 20:41:27 -06:00
李俊緯 79ba00a2f4 Translated using Weblate (Chinese (Traditional))
Currently translated at 84.4% (158 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-12-14 11:53:41 +01:00
bruh fdfaf8ec70 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (187 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/vi/
2021-12-14 11:53:41 +01:00
Héctor 162c58b697 Translated using Weblate (Spanish)
Currently translated at 60.9% (114 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-12-14 11:53:41 +01:00
Allan Nordhøy 75959ca692 Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.5% (132 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nb_NO/
2021-12-14 11:53:40 +01:00
Eric 06fbcd19c8 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (187 of 187 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2021-12-14 11:53:40 +01:00
Cameron Gutman 36e0468a99 Optimize CUDA GL interop and provide fallback 2021-12-13 21:41:00 -06:00
Cameron Gutman c4d85cf928 Don't show HDR option if we know it's unsupported 2021-12-12 17:43:20 -06:00
Cameron Gutman daf8495acb Fix excessive high-res scroll speed on newer GFE versions 2021-12-12 16:50:22 -06:00
Cameron Gutman 9999ded933 Quiet down log spam for asynchronous decoders 2021-12-11 18:37:39 -06:00
Cameron Gutman 80128e8293 Properly support asynchronous decoders that return multiple frames at a time 2021-12-11 18:15:49 -06:00
Cameron Gutman 9579b2c85e Enable Spanish and Traditional Chinese language options 2021-12-11 14:32:38 -06:00
Cameron Gutman eb7f184848 Rerun lupdate and lrelease 2021-12-11 14:32:12 -06:00
Cameron Gutman 71b21920e2 Merge remote-tracking branch 'origin/weblate' 2021-12-11 14:24:07 -06:00
Cameron Gutman 91b787a5be Update SDL and switch to arch-specific headers on Windows
SDL -> e2ade2b
2021-12-11 14:06:26 -06:00
Cameron Gutman 11f659aadb Update Visual C++ Runtime installers 2021-12-11 13:28:48 -06:00
Cameron Gutman 0870dd15a8 Fix improper null termination when stripping clipboard text 2021-12-10 02:04:19 -06:00
Héctor 7cd52041d8 Translated using Weblate (Spanish)
Currently translated at 53.2% (99 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-12-09 17:52:51 +01:00
Cameron Gutman f2bcb49478 Update dependencies for AppImage
SDL -> 2.0.18
nv-codec-headers -> 8.1.24.13
FFmpeg -> 4.4.1
2021-12-06 23:03:53 -06:00
Cameron Gutman 60a4bda94f Switch macOS builds to Qt 6 2021-12-06 22:54:55 -06:00
Cameron Gutman 54cfc46500 Fix VDPAU on X11 2021-12-06 20:42:51 -06:00
Cameron Gutman c09559ade5 Don't try to initialize VDPAU on Wayland 2021-12-06 19:38:28 -06:00
Cameron Gutman 3e9aea1f7a Optimize CUDA support to avoid roundtrip to CPU memory 2021-12-06 18:23:40 -06:00
Cameron Gutman f0c292f508 Update SDL_GameControllerDB 2021-12-03 12:52:23 +03:00
Cameron Gutman 1444ba2c35 Use attached Layout attached properties to set tool button size 2021-12-03 12:24:31 +03:00
Cameron Gutman fac4c85133 Revert "Fix toolbar button size on Qt 6.2"
Breaks running with Qt 5.9

This reverts commit 84ea483b4c.
2021-12-03 12:17:25 +03:00
Cameron Gutman 97a09e0571 Send UTF-8 clipboard text directly rather than emulating keystrokes 2021-12-03 11:32:58 +03:00
Cameron Gutman c7121516c1 Remove workaround for window occlusion issue fixed in SDL 2.0.18 2021-11-29 23:13:50 +03:00
Cameron Gutman 56a5fbf63b Fix get_buffer2() thread-safety warning with FFmpeg 4.4 2021-11-29 19:45:28 +03:00
Cameron Gutman 80604a752b Set SDL_HINT_APP_NAME for SDL 2.0.18 2021-11-27 17:28:01 +03:00
Cameron Gutman 3fe6e18609 Use SDL_GameControllerHasRumble() on SDL 2.0.18 2021-11-27 17:06:02 +03:00
Cameron Gutman 47f3f30d83 Add high resolution scrolling support with SDL 2.0.18 2021-11-27 06:59:16 +03:00
Cameron Gutman 085a904970 Fix false warning when building without libva-x11 or libva-wayland 2021-11-25 17:52:54 +03:00
Cameron Gutman 0fa7723f51 Fix build without libva-x11 2021-11-25 17:51:08 +03:00
Cameron Gutman 84ea483b4c Fix toolbar button size on Qt 6.2 2021-11-25 12:26:29 +03:00
Cameron Gutman 4de3aa96b6 Add YUV colorspace and color range attributes to EGLImage 2021-11-19 01:15:33 -06:00
Cameron Gutman 1193943228 Re-add comment on color_range comparison 2021-11-19 00:56:46 -06:00
Cameron Gutman 2959faca0c Fix colorspace transitions in EGLRenderer 2021-11-19 00:54:59 -06:00
Cameron Gutman d0df4fa3a0 Fix handling of HDR colorspace transitions in VT renderer 2021-11-19 00:28:15 -06:00
liyu 0a301dd2f9 enables H265 HDR option and adds PQ transforeFunction to render HDR stream on macOS 10.13+ 2021-11-18 23:42:44 -06:00
Cameron Gutman 43e3679297 Revert "Disable the EGL render thread on Wayland"
This reverts commit dcc567ebda.
2021-11-15 21:33:28 -06:00
Cameron Gutman 0455063854 Fix driver version check for Intel's updated version schema in 100 and newer drivers
Fixes #673
2021-11-13 20:44:10 -06:00
Cameron Gutman 12d90d77c7 Fix unintentionally concatenated strings 2021-11-08 19:47:01 -06:00
Cameron Gutman 61d7749aaf Update pre-built dependencies
SDL -> 7f308ab
OpenSSL -> 1.1.1l
FFmpeg -> 4.4.1
2021-11-04 22:49:30 -05:00
曹恩逢 69fb4a0c37 Translated using Weblate (Chinese (Traditional))
Currently translated at 77.9% (145 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-11-01 07:34:45 +01:00
Cameron Gutman d2c9f058f8 Add names to session threads 2021-10-24 16:22:49 -05:00
Cameron Gutman acaa3afa0f Rerun lupdate and lrelease 2021-10-06 21:14:21 -05:00
Cameron Gutman 3c58e21cbf Merge remote-tracking branch 'origin/weblate' 2021-10-06 21:12:14 -05:00
曹恩逢 9d3c5b9bc6 Translated using Weblate (Chinese (Traditional))
Currently translated at 76.8% (143 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-10-07 04:07:30 +02:00
Eric ce34358d46 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2021-10-07 04:07:29 +02:00
Cameron Gutman 278bcec238 Integrate new languages 2021-10-06 21:03:02 -05:00
Cameron Gutman 128f458848 Merge remote-tracking branch 'origin/weblate' 2021-10-06 20:15:11 -05:00
Cameron Gutman 7ae2bcd6db Update AppImage to libva 2.13 2021-10-06 20:13:05 -05:00
Luna Jernberg 130f252f97 Translated using Weblate (Swedish)
Currently translated at 31.7% (59 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/sv/
2021-10-06 13:05:00 +02:00
SWZ d339e05a3b Added translation using Weblate (Swedish) 2021-10-01 20:57:41 +02:00
Jorys Paulin 933f4813aa Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-09-25 11:38:59 +02:00
BOYI LIN f14e71c1d6 Translated using Weblate (Chinese (Traditional))
Currently translated at 38.1% (71 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-08-27 17:33:01 +02:00
Mert d78dbd7b0f Translated using Weblate (Turkish)
Currently translated at 8.0% (15 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/tr/
2021-08-24 02:37:31 +02:00
Cameron Gutman 71a6ef6eba Update SDL to 402b86f in AppImage 2021-08-15 15:23:05 -05:00
Cameron Gutman 4873862d16 Use SDL_WaitEventTimeout() on SDL 2.0.16 2021-08-15 15:16:51 -05:00
Cameron Gutman 425efe3d72 Switch to SDL audio backend by default on Windows and macOS 2021-08-15 14:58:29 -05:00
Cameron Gutman 666dc13c01 Use SDL's new support for keyboard grab on macOS 2021-08-15 14:54:26 -05:00
Cameron Gutman 267f9f5759 Update SDL to 402b86f for Windows and macOS 2021-08-15 14:47:10 -05:00
Cameron Gutman c8d8c00f84 Update Visual C++ Runtime installers 2021-08-15 12:17:09 -05:00
Cameron Gutman dcc567ebda Disable the EGL render thread on Wayland 2021-07-31 17:24:18 -05:00
LiuAnnan a199a3ccc3 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.4% (185 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2021-07-30 08:34:39 +02:00
Cameron Gutman 8159e07427 Ensure our GL context is always current 2021-07-28 20:31:22 -05:00
Nikita Epifanov 32d70758c5 Translated using Weblate (Russian)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ru/
2021-07-23 10:32:32 +02:00
Jorys Paulin 3a9e284f29 Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-07-19 17:34:21 +02:00
Cameron Gutman c658daeac6 Remove unneccessary EVP_get_digestbyname() invocation
This causes problems with pre-OpenSSL 1.1.0 clients that don't
call OpenSSL_add_all_algorithms() during initialization. This
is known to affect Steam Link on firmware 815.
2021-07-17 20:32:50 -05:00
Jorys Paulin f605169b15 Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-07-15 15:33:00 +02:00
Cameron Gutman f82b495bcc Switch to the new Sectigo certificate 2021-07-14 21:09:48 -05:00
Tygo T 33b44a87c5 Translated using Weblate (Dutch)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nl/
2021-07-06 14:33:19 +02:00
Gerard Joling a88d994fcb Translated using Weblate (Dutch)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nl/
2021-07-05 13:48:27 +02:00
Gerard Joling dd9224d9a6 Added translation using Weblate (Dutch) 2021-07-05 10:39:15 +02:00
Cameron Gutman 48728efee0 Add support for dynamic HTTPS port 2021-07-03 00:00:27 -05:00
Cameron Gutman 043c55ae66 Add missing changes to fix build 2021-07-02 23:54:17 -05:00
Cameron Gutman fa3f822cf1 Rework handling of addresses to allow alternate HTTP ports 2021-07-02 23:34:54 -05:00
Cameron Gutman 5afab126b3 Refactor NvPairingManager, NvComputer, and NvHTTP to reduce passing of addresses 2021-07-02 17:14:48 -05:00
Cameron Gutman bee8378795 Pass RTSP session URL to moonlight-common-c for dynamic ports 2021-07-02 01:51:08 -05:00
Cameron Gutman cbd42f4a58 Log launch, resume, and quit responses 2021-07-02 01:18:57 -05:00
Furkan 3333fd7fc8 Added translation using Weblate (Turkish) 2021-07-01 17:52:59 +02:00
DankXylese 142258b4b5 Translated using Weblate (Ukrainian)
Currently translated at 1.6% (3 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/uk/
2021-06-30 13:32:33 +02:00
DankXylese 01213b58ba Added translation using Weblate (Ukrainian) 2021-06-29 12:59:43 +02:00
wkopiaspupn 51df7032bb Translated using Weblate (Chinese (Traditional))
Currently translated at 35.4% (66 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-06-27 14:32:49 +02:00
wkopiaspupn c033ce5ecf Translated using Weblate (Chinese (Traditional))
Currently translated at 1.6% (3 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hant/
2021-06-26 13:33:38 +02:00
wkopiaspupn bfaf57cfd0 Added translation using Weblate (Chinese (Traditional)) 2021-06-26 13:31:04 +02:00
Cameron Gutman 6c523570e5 Prepare for v3.1.4 2021-06-25 20:39:30 -05:00
Cameron Gutman 047e5bdd81 Update AppImage to libva 2.12 2021-06-24 21:47:01 -05:00
Cameron Gutman 6b1559d397 Update moonlight-common-c to fix audio problems with old GFE and Sunshine versions 2021-06-21 19:26:08 -05:00
WALKTHROUGH RAYMAND LEGENDS a3167b8152 Translated using Weblate (Hungarian)
Currently translated at 2.1% (4 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/hu/
2021-06-15 14:32:39 +02:00
Cameron Gutman cbeb23f16a Adjust Steam Link icon size to 116x116 2021-06-13 16:53:03 -05:00
WALKTHROUGH RAYMAND LEGENDS b4a6512784 Added translation using Weblate (Hungarian) 2021-06-13 21:47:33 +02:00
Cameron Gutman 1af2742013 Update moonlight-common-c to fix spurious exit of fast audio recovery mode on startup 2021-06-13 11:20:28 -05:00
Cameron Gutman 8048938158 Fix Linux build 2021-06-12 16:12:46 -05:00
Cameron Gutman 3689c7f982 Don't enable input capture if the window can't be foregrounded 2021-06-12 13:59:13 -05:00
Cameron Gutman 96c7057fee Update moonlight-common-c to avoid qwave.dll dependency 2021-06-12 12:21:55 -05:00
Cameron Gutman df7c4c82a9 Update moonlight-common-c with performance optimizations 2021-06-09 23:23:47 -05:00
Cameron Gutman 18d8db338b Update moonlight-common-c 2021-06-08 20:19:39 -05:00
Cameron Gutman 9637639e31 Update moonlight-common-c with audio FEC support 2021-06-04 18:46:36 -05:00
Héctor 17abe8f164 Translated using Weblate (Spanish)
Currently translated at 35.4% (66 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-05-27 21:33:27 +02:00
Cameron Gutman badaaece04 Update moonlight-common-c 2021-05-25 20:39:53 -05:00
Cameron Gutman 56119eebae Adapt to constification of AVCodec in FFmpeg master 2021-05-24 23:27:31 -05:00
Cameron Gutman c17c8e2a2c Remove receive time from performance overlay
It is largely superseded by network latency
2021-05-22 13:59:14 -05:00
Cameron Gutman e45a60f2ed Save RTT in VIDEO_STATS so it can be logged on disconnect 2021-05-22 13:57:12 -05:00
Cameron Gutman ebe9356937 Integrate Thai and Korean translations 2021-05-22 13:44:45 -05:00
Cameron Gutman 0094305299 Merge remote-tracking branch 'origin/weblate' 2021-05-22 13:33:20 -05:00
NicolasS b27050d3bf Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-05-22 18:32:19 +02:00
Jorys Paulin d941e596ad Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-05-22 18:32:19 +02:00
sanhoe ddaec92da5 Translated using Weblate (Korean)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ko/
2021-05-21 16:14:30 +02:00
sanhoe 1c0a4c92a8 Translated using Weblate (Korean)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ko/
2021-05-20 21:45:31 +02:00
sanhoe 383c00afbd Added translation using Weblate (Korean) 2021-05-20 16:32:05 +02:00
Krit789 d3b2bff8ad Translated using Weblate (Thai)
Currently translated at 41.9% (78 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/th/
2021-05-18 00:32:49 +02:00
Cameron Gutman 77aaa6141d Update moonlight-common-c to avoid excessive ENet retransmissions when RTT variance is 0 2021-05-16 15:40:38 -05:00
Krit789 2bb1af61d0 Added translation using Weblate (Thai) 2021-05-16 21:58:44 +02:00
Cameron Gutman 40b29472b3 Update moonlight-common-c with more accurate RTTs, minRequiredFecPackets, and input queue draining 2021-05-16 14:46:57 -05:00
Cameron Gutman 5d5029de59 Increase limit for the --fps option 2021-05-16 14:45:53 -05:00
Cameron Gutman cc96e6a222 Rebase AppImage on Ubuntu Bionic and Qt 5.15.2 2021-05-16 12:45:34 -05:00
Cameron Gutman 581c9438ca Add network latency to stats overlay 2021-05-15 14:40:31 -05:00
Cameron Gutman 54bd427f26 Integrate Japanese and Vietnamese translations 2021-05-13 00:24:00 -05:00
Cameron Gutman c55d184195 Rerun lupdate-pro and lrelease-pro 2021-05-13 00:13:58 -05:00
Cameron Gutman b279f94789 Merge remote-tracking branch 'origin/weblate' 2021-05-13 00:06:47 -05:00
bruh f3a897e99a Translated using Weblate (Vietnamese)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/vi/
2021-05-13 07:04:50 +02:00
bruh 392b1b5904 Added translation using Weblate (Vietnamese) 2021-05-12 07:36:31 +02:00
grtw2116 4daa8066a6 Translated using Weblate (Japanese)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ja/
2021-05-10 07:33:45 +02:00
NicolasS 8a89951286 Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-05-08 07:28:33 +02:00
grtw2116 c41ed55291 Added translation using Weblate (Japanese) 2021-05-08 07:28:33 +02:00
Cameron Gutman caba0499d7 Prepare for v3.1.3 2021-05-07 19:07:52 -05:00
Cameron Gutman 13deacfc3b Fix Spanish translation args 2021-05-07 18:56:08 -05:00
Cameron Gutman 7231085456 Run lupdate-pro and lrelease-pro 2021-05-06 17:26:26 -05:00
Cameron Gutman 663bb4aa10 Merge remote-tracking branch 'origin/weblate' 2021-05-06 17:24:39 -05:00
Cameron Gutman 18721b4542 Improve sanity checking and logging for unsupported GFE versions 2021-05-06 17:18:47 -05:00
NicolasS 19232722e2 Translated using Weblate (French)
Currently translated at 100.0% (186 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-05-05 22:32:11 +02:00
Cameron Gutman d2eca68484 Update moonlight-common-c to attempt to fix audio latency issues 2021-05-04 10:22:29 -05:00
Héctor 091167478e Translated using Weblate (Spanish)
Currently translated at 23.6% (44 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-05-04 10:32:11 +02:00
Cameron Gutman 547b8abc56 Prepare for v3.1.2 release 2021-05-03 17:38:14 -05:00
Héctor dbfac45d59 Translated using Weblate (Spanish)
Currently translated at 17.7% (33 of 186 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-05-03 09:32:23 +02:00
Cameron Gutman 086f6de867 Work around broken package repositories in AppVeyor 2021-05-02 14:49:07 -05:00
Cameron Gutman 0f93091848 Update SDL_GameControllerDB 2021-05-02 10:56:50 -05:00
Cameron Gutman ac19f62ed9 Never display placeholder text for an app collector game
Fixes #567
2021-05-02 10:39:25 -05:00
Cameron Gutman 8fcef63890 Don't waste time performing extra decoder initializations for EGL when it's not supported 2021-04-30 20:52:09 -05:00
Cameron Gutman 34cd2c1afa Run lupdate-pro and lrelease-pro 2021-04-30 20:09:15 -05:00
Cameron Gutman 5d1a19d49c Merge remote-tracking branch 'origin/weblate' 2021-04-30 20:07:59 -05:00
Cameron Gutman 2fbb320539 Refuse to stream if Moonlight is known incompatible with the host GFE version 2021-04-30 20:05:49 -05:00
Cameron Gutman b50e5ed7e6 Fix keyboard grab on X11
Fixes #584
2021-04-30 18:17:15 -05:00
Cameron Gutman 26c82ca72c Don't enable vsync on test decoders 2021-04-30 18:12:56 -05:00
Cameron Gutman f8a8a431a8 Revert warn_off removal
There are still a bunch of unused parameter warnings with GCC/Clang
2021-04-29 21:22:59 -05:00
Cameron Gutman fd27867195 Update moonlight-common-c and remove warn_off config option 2021-04-29 18:05:40 -05:00
Cameron Gutman 5e2a627795 Update moonlight-common-c with RTSP handshake retry logic 2021-04-28 17:38:59 -05:00
Cameron Gutman e081401c2d Update moonlight-common-c for multi-FEC support and audio latency fix 2021-04-26 22:51:46 -05:00
Cameron Gutman e62a268aac Avoid audio encryption on Steam Link for performance reasons 2021-04-23 19:49:03 -05:00
Cameron Gutman 140a9e5191 Enable audio stream encryption 2021-04-23 18:55:10 -05:00
Cameron Gutman 51b5f8046f Disable HTTP/2 on host PC connections for GFE 3.22 2021-04-19 18:41:01 -05:00
Cameron Gutman 91b965d1aa Update moonlight-common-c 2021-04-18 19:34:12 -05:00
Cameron Gutman f8faccee59 Remove qt5-devel which doesn't exist in Fedora 34 2021-04-17 11:11:37 -05:00
shower 6ac46a36a7 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (184 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2021-04-17 13:27:02 +02:00
Héctor 27572ba4bc Translated using Weblate (Spanish)
Currently translated at 16.3% (30 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-04-15 22:27:01 +02:00
Cameron Gutman 21be832161 Prepare for v3.1.1 release 2021-04-09 21:07:05 -05:00
Cameron Gutman 5769632793 Update moonlight-common-c for initial GFE 3.22 compatibility 2021-04-09 20:18:47 -05:00
Cameron Gutman 9efd959ed8 Merge branch 'weblate' 2021-04-09 20:17:39 -05:00
Cameron Gutman 5c72afe17e Run lupdate-pro and lrelease-pro 2021-04-04 20:45:57 -05:00
a dc24319333 Translated using Weblate (Russian)
Currently translated at 100.0% (184 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ru/
2021-04-05 03:42:34 +02:00
Jorys Paulin 1acbdf94aa Translated using Weblate (French)
Currently translated at 100.0% (184 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-04-05 03:42:33 +02:00
Cameron Gutman 44229dfe51 Update translations
- Add RU and ES to resources.qrc and app.pro
- Rerun lupdate-pro and lrelease-pro
2021-04-04 10:25:06 -05:00
a 13206227d9 Translated using Weblate (Russian)
Currently translated at 100.0% (184 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ru/
2021-04-04 17:03:35 +02:00
Cameron Gutman e3e8a57df6 Update to OpenSSL 1.1.1k and FFmpeg 4.3.2 2021-03-31 20:27:33 -05:00
Cameron Gutman 7afff80984 Update moonlight-common-c to pick up AMF HEVC parsing fix 2021-03-31 20:07:45 -05:00
Cameron Gutman 500522418e Fix AppImage build 2021-03-28 16:07:20 -05:00
a 5ccac5a5c3 Translated using Weblate (Russian)
Currently translated at 45.1% (83 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/ru/
2021-03-28 14:29:40 +02:00
Héctor 69822f4401 Translated using Weblate (Spanish)
Currently translated at 11.4% (21 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/es/
2021-03-28 14:29:39 +02:00
reloxx13 f290cfbd35 Translated using Weblate (German)
Currently translated at 100.0% (184 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/de/
2021-03-28 14:29:39 +02:00
Cameron Gutman fae30f59ce Add attribution for Cloudsmith 2021-03-27 12:40:51 -05:00
a a15f303c0a Added translation using Weblate (Russian) 2021-03-26 05:05:09 +01:00
Cameron Gutman 5e85038d78 Update AppImage to libva 2.11 2021-03-25 22:17:51 -05:00
Héctor 4e7b35c54e Added translation using Weblate (Spanish) 2021-03-25 09:04:18 +01:00
Cameron Gutman 48dde310ae Add Norwegian Bokmål to the build 2021-03-24 20:40:22 -05:00
Cameron Gutman 6b041e7657 Run lrelease-pro 2021-03-24 20:39:52 -05:00
Cameron Gutman 69576ee1e1 Run lupdate-pro 2021-03-24 20:39:39 -05:00
Cameron Gutman bd3105f62e Merge remote-tracking branch 'origin/weblate' 2021-03-24 20:28:24 -05:00
Cameron Gutman 02e3f0e71b Add missing declaration 2021-03-22 23:32:00 -05:00
Cameron Gutman 74bf981f3d Ensure hwframe read-back works in SDL renderer 2021-03-22 23:15:14 -05:00
Cameron Gutman 32f0678692 Only pass modifiers array if DRM_MODE_FB_MODIFIERS is set 2021-03-22 22:52:06 -05:00
Cameron Gutman e74753bec1 Allow fallback from EGL to direct on EGLImage export failure 2021-03-22 22:51:29 -05:00
Cameron Gutman 4a8c9ad17f Add support for 4-plane frames 2021-03-22 00:46:04 -05:00
Cameron Gutman 0c6c882f50 Fix attribute buffer overflow for fully planar YUV formats 2021-03-22 00:14:06 -05:00
Cameron Gutman 579f25c1ba Add missing EGL_DMA_BUF_PLANE2 definitions 2021-03-22 00:02:03 -05:00
Cameron Gutman d5eb5c8816 Fix build with EGL 1.4 headers 2021-03-21 23:59:35 -05:00
Cameron Gutman 26d04b5f9c Render DRM-PRIME frames as opaque images
We can't always assume they are NV12. Even if they _are_ NV12,
they may have DRM format modifiers that are incompatible with
simply assuming linear Y and UV buffers (such as tiling).
2021-03-21 23:23:12 -05:00
Cameron Gutman a0b9684504 Continue refactoring for non-NV12 support in EGLRenderer 2021-03-21 21:43:57 -05:00
Cameron Gutman 402b6d1f0c Begin refactoring for non-NV12 support in EGLRenderer 2021-03-21 19:20:52 -05:00
Cameron Gutman e87a5fa354 Pass DRM format modifiers to FB creation 2021-03-21 17:54:10 -05:00
Allan Nordhøy 63574f643e Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.1% (129 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nb_NO/
2021-03-21 10:36:54 +01:00
Cameron Gutman 1d6b1020c3 Translated using Weblate (French)
Currently translated at 73.9% (136 of 184 strings)

Translation: Moonlight Game Streaming/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-03-21 06:29:36 +01:00
Allan Nordhøy 96337a3230 Translated using Weblate (Norwegian Bokmål)
Currently translated at 16.3% (30 of 184 strings)

Translation: moonlight/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/nb_NO/
2021-03-21 02:33:56 +01:00
reloxx13 950c59d8b4 Translated using Weblate (German)
Currently translated at 100.0% (184 of 184 strings)

Translation: moonlight/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/de/
2021-03-21 02:33:56 +01:00
Allan Nordhøy 9cfd095281 Added translation using Weblate (Norwegian Bokmål) 2021-03-21 02:33:56 +01:00
Anonymous 996e049863 Translated using Weblate (Chinese (Simplified))
Currently translated at 96.1% (177 of 184 strings)

Translation: moonlight/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/zh_Hans/
2021-03-21 02:33:56 +01:00
Anonymous 6e42817c3e Translated using Weblate (French)
Currently translated at 74.4% (137 of 184 strings)

Translation: moonlight/moonlight-qt
Translate-URL: https://hosted.weblate.org/projects/moonlight/moonlight-qt/fr/
2021-03-21 02:33:56 +01:00
Cameron Gutman 7758344a57 Fix Weblate badge 2021-03-20 18:12:04 -05:00
Cameron Gutman b5df566b6b Add Weblate links to readme
Closes #539
2021-03-20 18:11:15 -05:00
Cameron Gutman e21fd19a70 Prepare for v3.1.0 release 2021-03-14 11:30:21 -05:00
Cameron Gutman 98672c8e44 Allow remote desktop mouse mode in embedded mode
It can be easier to control the mouse on the desktop that way
2021-03-13 16:58:58 -06:00
Cameron Gutman 2e92f0640b Update SDL_GameControllerDB 2021-03-13 15:50:01 -06:00
Cameron Gutman d6b314f573 Add option to build for embedded environments 2021-03-13 15:20:58 -06:00
Cameron Gutman d7a150ffa8 Only enable capture mode list if capture toggle is enabled 2021-03-13 14:59:32 -06:00
Cameron Gutman 955da6be30 Enable Gallium VAAPI driver on VAAPI 1.x 2021-03-13 14:37:13 -06:00
Cameron Gutman b5f8e6738a Move LANG_DE to the end of the Language enum 2021-03-09 20:13:55 -06:00
reloxx13 d7fa8c9795 Add german translation (#536)
* add german translation

* add german to language list

* donttranslate language names. always use the native name.

* add compiled german translation file

* german translation handling

* add german to getSuffixFromLanguage

* update german string and translation

* update all language files with new strings

* typo

* compile

* more typos and fixes for german
2021-03-09 20:10:36 -06:00
Cameron Gutman acb7a5b3c8 Fix XCB out-of-sequence abort after switching to non-threaded Qt renderer 2021-03-07 16:48:10 -06:00
Cameron Gutman 783a57ef89 Use separate thread for streaming on X11 and Wayland 2021-03-07 12:15:42 -06:00
Cameron Gutman d33ccce683 Hold a reference to the underlying DMA-BUFs until the next frame 2021-03-07 12:01:25 -06:00
Cameron Gutman d722bf10b9 Don't use glFinish() with KMSDRM backend 2021-03-07 11:23:31 -06:00
Cameron Gutman 41337475a2 Update SDL_GameControllerDB 2021-03-06 14:29:55 -06:00
Cameron Gutman f504a069d7 Update VCRedist version for VC 16.9 2021-03-05 17:51:26 -06:00
Cameron Gutman 96f79688dd Use av_packet_alloc() instead of av_init_packet()
sizeof(AVPacket) may be deprecated from ABI in the near future
2021-03-05 17:47:04 -06:00
Cameron Gutman c330898aeb Add workaround for AppView breaking after changing language at runtime 2021-03-05 17:44:31 -06:00
Cameron Gutman 94952cf0a4 Update issue template 2021-03-03 01:39:55 -06:00
Cameron Gutman a3c249abe9 Don't load the app label asynchronously 2021-03-02 19:03:09 -06:00
Cameron Gutman c26562fab8 Fix Steam Link build 2021-03-02 18:57:16 -06:00
Cameron Gutman b7cbd99212 Fix tooltip display in app grid 2021-03-02 18:35:50 -06:00
Cameron Gutman b53ef35a85 Improve loading speed of PC and app grids 2021-03-02 18:32:56 -06:00
Cameron Gutman 1ebb5fefb1 Address Clazy warnings 2021-03-02 18:14:15 -06:00
Cameron Gutman 164b3edd41 Fix viewport size on High DPI Wayland systems
Fixes #533
2021-03-01 22:47:14 -06:00
Cameron Gutman 819ea36cca Hack to fix build on AppVeyor 2021-02-28 16:47:39 -06:00
Cameron Gutman 088c9b9e4e Stop single-arch binary build before extracting dSYM 2021-02-28 16:02:50 -06:00
Cameron Gutman ab25a9b8ee Add Universal binary support to build script 2021-02-28 15:49:59 -06:00
Cameron Gutman b2aea9f8f0 Revert change to only fire special combos on key up 2021-02-28 15:06:46 -06:00
Cameron Gutman 5399b95936 Fix update checker on macOS with Qt 6.0 builds 2021-02-28 14:33:20 -06:00
Cameron Gutman 1d5c120748 Add support for specifying minimum kernel versions in the update manifest 2021-02-28 14:27:29 -06:00
jmt-gh 6be7301e69 Stats overlay controller combo (#495)
* Update gamepad.cpp

add gamepad combo to toggle stats overlay

* typo fixes
2021-02-27 17:03:52 -06:00
Maximiliano Bertacchini fff9f2b17d Add numpad Enter handlers (Keys.onEnterPressed) (#516) 2021-02-27 17:01:22 -06:00
Cameron Gutman 87a7d2e45c Add setting to only capture system keys in full-screen 2021-02-27 16:47:38 -06:00
Cameron Gutman 58803ef40d Update SDL to e561ce3 and OpenSSL to 1.1.1j 2021-02-27 13:08:21 -06:00
Cameron Gutman b27ca993aa Add support for system key capture in windowed mode on macOS 2021-02-26 21:43:47 -06:00
Cameron Gutman 28ecc6bcbf Remove old Qt Multimedia audio renderer 2021-02-25 23:23:08 -06:00
Cameron Gutman 30c5e3f237 Fix window icons on Wayland 2021-02-25 23:20:21 -06:00
Cameron Gutman 6a25a3a3d0 Don't require DRM master for SDL KMSDRM backend 2021-02-25 22:27:20 -06:00
Cameron Gutman 9a84c0ae30 Update AppImage to official SDL Git repo 2021-02-25 22:00:35 -06:00
Cameron Gutman 133cc5457d Use SDL_CaptureMouse() on macOS and Linux too 2021-02-08 18:30:22 -06:00
Cameron Gutman 05e4c5b507 Move clipboard processing to a separate thread to avoid blocking the main thread during pastes 2021-02-07 17:18:35 -06:00
Cameron Gutman 8372717a09 Improve Unicode support for some common characters 2021-02-07 16:00:00 -06:00
Cameron Gutman 5f3f2a96fd Improve detection of having no clipboard text 2021-02-07 13:53:03 -06:00
Cameron Gutman b83c6f0c28 Add support for pasting clipboard text 2021-02-07 13:46:38 -06:00
Cameron Gutman 36dc0f3e3c Use mouse capture for Win32 instead of our global mouse state hack 2021-02-07 12:38:57 -06:00
Cameron Gutman b4edde6f90 Disable Qt 6 threaded renderer on Windows
They switched from non-threaded to threaded by default in Qt 6
2021-02-07 11:21:47 -06:00
Cameron Gutman 395eb5581c Cache results of WMUtils::isRunningX11() and WMUtils::isRunningWayland() 2021-02-07 11:03:53 -06:00
Cameron Gutman 6dab251055 Don't overwrite window mode settings when switching between WM and non-WM environments 2021-02-07 10:49:29 -06:00
Cameron Gutman 3bd6a6a614 Fullscreen is no longer required for passing system keyboard shortcuts 2021-02-06 20:15:58 -06:00
Cameron Gutman 93d21a0d1d Fix EGLImage leak when not using a hwaccel backend 2021-02-06 17:59:05 -06:00
Cameron Gutman 2c2a73e320 Fix build and require SDL 2.0.15 to hook 2021-02-06 17:07:21 -06:00
Cameron Gutman a88a3c9ea3 Allow SDL to render with KMSDRM backend while Qt is also using DRM 2021-02-06 16:32:54 -06:00
Cameron Gutman e4df70cd56 Use the async connect thread on all platforms
It turned out that the cause of the random crashes was the threaded renderer
that we now turn off.
2021-02-06 15:14:15 -06:00
Cameron Gutman 90f7d35150 Always use a non-threaded renderer
This ensures we can block Qt's rendering as needed to synchronize with SDL
2021-02-06 14:58:30 -06:00
Cameron Gutman 75b19a60c1 Fix build on macOS and keyboard grab bugs 2021-02-06 11:29:18 -06:00
Cameron Gutman 9fc921f49f Use SDL's keyboard grab support now that it's been upstreamed 2021-02-05 00:13:20 -06:00
Cameron Gutman 4b9e90ac72 Update SDL for Windows and macOS to Hg 60b9ce4ee73e
https://github.com/cgutman/moonlight-deps/commit/ad955430988be24fd379a6152642c7ce4053bc7f
2021-02-04 20:51:33 -06:00
Cameron Gutman 36dd6c83e0 Fix assert failure when using v4l2m2m with EGL 2021-02-04 20:38:18 -06:00
Cameron Gutman d790313221 Use the existing install of Qt on macOS in CI 2021-02-04 19:39:58 -06:00
Cameron Gutman c3895f06c0 Fix handling of preferred/compatible pixel formats with EGLRenderer and VAAPI/DRM backends 2021-02-04 19:39:18 -06:00
Cameron Gutman 76e81fa651 Add windowed support for MMAL 2021-02-03 20:57:39 -06:00
Cameron Gutman d63a1b0eb0 Handle custom hwaccel decoders 2021-02-02 19:45:22 -06:00
Cameron Gutman 4dffac3c78 Ask for NV12 buffers for DRMRenderer 2021-02-02 19:40:06 -06:00
Cameron Gutman 88391b0274 Use the decoder's supported pix_fmts to select a suitable renderer 2021-02-02 19:05:27 -06:00
Cameron Gutman c3cea0238e Fix build with old EGL 1.5 headers without EGL_EGL_PROTOTYPES 2021-01-31 21:42:56 -06:00
Cameron Gutman 5bf4266973 Fix build with old Mesa EGL headers 2021-01-31 18:41:53 -06:00
Cameron Gutman ed57c54d06 Move EGL definitions into renderer.h to try to fix build on Armbian 2021-01-31 17:01:11 -06:00
Cameron Gutman 01936e000e Fix Steam Link bundle build 2021-01-31 16:27:38 -06:00
Cameron Gutman 80137848dc Add DMA-BUF export compatibility with EGL 1.4 2021-01-31 16:24:31 -06:00
Cameron Gutman 149575e0c4 Don't retranslate if the language didn't change 2021-01-31 15:28:00 -06:00
Cameron Gutman 6a66b462ce Allow DRMRenderer to be used for indirect rendering 2021-01-31 15:19:19 -06:00
Cameron Gutman 1e31f6fe77 Fix initialization of DRM backend with X running 2021-01-31 15:03:40 -06:00
Cameron Gutman f173b3ff09 Attempt to fix AppImage and Steam Link build errors 2021-01-31 14:48:42 -06:00
Cameron Gutman baffab62ce Fix uninitialized variable warning 2021-01-31 12:58:19 -06:00
Cameron Gutman d141cec2a8 Fix mangled macOS libraries after transition to submodule 2021-01-31 12:23:52 -06:00
Cameron Gutman df87ac3810 Update SDL in AppImage to Hg d75deb75464a 2021-01-31 12:13:20 -06:00
Cameron Gutman 46960ce0a4 Remove side-by-side support for Qt 5.9 on Steam Link 2021-01-31 12:08:15 -06:00
Cameron Gutman 522206b0bc Use shallow-cloned submodule for prebuilts 2021-01-31 11:50:41 -06:00
Cameron Gutman 24d60dd3ab Remove prebuilt binaries 2021-01-31 11:40:41 -06:00
Cameron Gutman dbfdc2fd14 Share DRM FD and GBM device with SDL
Depends on https://hg.libsdl.org/SDL/rev/d75deb75464a
2021-01-30 21:11:52 -06:00
Cameron Gutman a97912e297 Print the error when querying EGL_EXTENSIONS fails 2021-01-30 20:13:20 -06:00
Cameron Gutman cedba501ee Query the frontend renderer to determine fullscreen-only limitations 2021-01-30 17:57:34 -06:00
Cameron Gutman ac947d3bda Add EGLImage export support to DRMRenderer 2021-01-30 17:52:23 -06:00
Cameron Gutman 243ba371b3 Initialize a DRM hardware context for hwaccel usage 2021-01-30 16:33:58 -06:00
Cameron Gutman 3af24eafbb Build fixes 2021-01-30 12:53:57 -06:00
Cameron Gutman 69b6022afe Add language selection option in settings
Fixes #501
2021-01-30 12:14:31 -06:00
Cameron Gutman 1cd66419d4 Remember desired cursor hide state
Fixes #511
2021-01-30 11:08:01 -06:00
WLongandWLong 5309a02f6d Add simplified Chinese language (#506)
* 添加qml_zh_cn.ts

* 更新部分翻译

* 优化部分文字描述

* 优化部分文字描述

* 恢复README.md

Co-authored-by: WLong <a101084@126.com>
2021-01-30 10:10:36 -06:00
Cameron Gutman 541784382a Add support for AV_HWDEVICE_TYPE_DRM hwaccels 2021-01-30 10:00:01 -06:00
Cameron Gutman 2a7fae2c82 Revert "Add logic to try LibreELEC's out-of-tree stateless V4L2 decoders"
v4l2request is a hwaccel not a decoder

This reverts commit ed3a5448b1.
2021-01-29 20:30:01 -06:00
Cameron Gutman ed3a5448b1 Add logic to try LibreELEC's out-of-tree stateless V4L2 decoders 2021-01-29 20:19:27 -06:00
Cameron Gutman 2eb4769bbc Only trigger special key combos when all keys are up 2021-01-24 13:02:42 -06:00
Cameron Gutman 02019000df Ctrl+Alt+Shift+Down Arrow is a reserved key combo on GNOME, so switch to Ctrl+Alt+Shift+D 2021-01-21 23:05:48 -06:00
Cameron Gutman 6262f51c96 Key capture is supported on Wayland with latest SDL Hg 2021-01-21 21:07:54 -06:00
Cameron Gutman d38ff5759a Add Ctrl+Alt+Shift+Down Arrow shortcut to minimize 2021-01-21 19:39:17 -06:00
Cameron Gutman f6de2e4dd3 Revert "Disable the system keyboard capture option on Wayland"
SDL now supports keyboard grab with https://hg.libsdl.org/SDL/rev/b0e13627c656

This reverts commit bc10fd0aba.
2021-01-20 21:43:16 -06:00
Cameron Gutman 3959f447d4 Fix detection of x64 architecture on some machines 2021-01-17 12:58:08 -06:00
877 changed files with 29378 additions and 198638 deletions
+11 -2
View File
@@ -1,10 +1,12 @@
---
name: Bug report
about: Ask for help on Discord before reporting a bug
about: Follow the troubleshooting guide before reporting a bug
---
**READ ME FIRST!**
This issue tracker is not the right place to ask for troubleshooting help if you're not able to connect or stream at all. For those requests, please use the #pc-help channel on our Discord server where there are many more people who can help (or direct you back here if it looks like a Moonlight bug after all). https://moonlight-stream.org/discord
If you're here because something basic is not working (like gamepad input, video, or similar), it's probably something specific to your setup, so make sure you've gone through the Troubleshooting Guide first: https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting
If you still have trouble with basic functionality after following the guide, join our Discord server where there are many other volunteers who can help (or direct you back here if it looks like a Moonlight bug after all). https://moonlight-stream.org/discord
**Describe the bug**
A clear and concise description of what the bug is.
@@ -26,14 +28,21 @@ List the games you've tried that exhibit the issue. To see if the issue is game-
- If so, which settings have been changed?
- Does the problem still occur after reverting settings back to default?
**Gamepad-related issues (please complete if problem is gamepad-related)**
- Do you have any gamepads connected to your host PC directly?
- Does the problem still remain if you stream the desktop and use https://html5gamepad.com to test your gamepad?
- Instructions for streaming the desktop can be found here: https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide
**Client PC details (please complete the following information)**
- OS: [e.g. Windows 10 1809]
- Moonlight Version: [e.g. v0.9.0]
- GPU: [e.g. Intel HD Graphics 520]
**Server PC details (please complete the following information)**
- OS: [e.g. Windows 10 1809]
- GeForce Experience version: [e.g. 3.16.0.140]
- Nvidia GPU driver: [e.g. 417.35]
- Antivirus and firewall software: [e.g. Windows Defender and Windows Firewall]
**Moonlight Logs (please attach)**
- On Windows, `Moonlight-###.log` files can be found in `%TEMP%`. Simply type that into the File Explorer path field to navigate there.
+4
View File
@@ -13,3 +13,7 @@
[submodule "h264bitstream/h264bitstream"]
path = h264bitstream/h264bitstream
url = https://github.com/aizvorski/h264bitstream.git
[submodule "libs"]
path = libs
url = https://github.com/cgutman/moonlight-qt-prebuilts.git
shallow = true
+4 -1
View File
@@ -12,8 +12,11 @@ contains(QT_ARCH, i386) {
contains(QT_ARCH, x86_64) {
LIBS += -L$$PWD/../libs/windows/lib/x64
}
contains(QT_ARCH, arm64) {
LIBS += -L$$PWD/../libs/windows/lib/arm64
}
LIBS += -lNktHookLib
LIBS += -ldetours
DEFINES += ANTIHOOKING_LIBRARY
SOURCES += antihookingprotection.cpp
HEADERS += antihookingprotection.h
+45 -22
View File
@@ -1,6 +1,9 @@
#include "antihookingprotection.h"
#include <NktHookLib.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <detours.h>
typedef HMODULE (WINAPI *LoadLibraryAFunc)(LPCSTR lpLibFileName);
typedef HMODULE (WINAPI *LoadLibraryWFunc)(LPCWSTR lpLibFileName);
@@ -12,25 +15,35 @@ class AntiHookingProtection
public:
static void enable()
{
#ifdef QT_DEBUG
s_HookManager.SetEnableDebugOutput(true);
#endif
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
HINSTANCE kernel32Handle = NktHookLibHelpers::GetModuleBaseAddress(L"kernel32.dll");
SIZE_T hookId;
s_RealLoadLibraryA = LoadLibraryA;
DetourAttach(&(PVOID&)s_RealLoadLibraryA, LoadLibraryAHook);
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryA,
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryA"),
(LPVOID)AntiHookingProtection::LoadLibraryAHook);
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryW,
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryW"),
(LPVOID)AntiHookingProtection::LoadLibraryWHook);
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExA,
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExA"),
(LPVOID)AntiHookingProtection::LoadLibraryExAHook);
s_HookManager.Hook(&hookId, (LPVOID*)&s_RealLoadLibraryExW,
NktHookLibHelpers::GetProcedureAddress(kernel32Handle, "LoadLibraryExW"),
(LPVOID)AntiHookingProtection::LoadLibraryExWHook);
s_RealLoadLibraryW = LoadLibraryW;
DetourAttach(&(PVOID&)s_RealLoadLibraryW, LoadLibraryWHook);
s_RealLoadLibraryExA = LoadLibraryExA;
DetourAttach(&(PVOID&)s_RealLoadLibraryExA, LoadLibraryExAHook);
s_RealLoadLibraryExW = LoadLibraryExW;
DetourAttach(&(PVOID&)s_RealLoadLibraryExW, LoadLibraryExWHook);
DetourTransactionCommit();
}
static void disable()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)s_RealLoadLibraryA, LoadLibraryAHook);
DetourDetach(&(PVOID&)s_RealLoadLibraryW, LoadLibraryWHook);
DetourDetach(&(PVOID&)s_RealLoadLibraryExA, LoadLibraryExAHook);
DetourDetach(&(PVOID&)s_RealLoadLibraryExW, LoadLibraryExWHook);
DetourTransactionCommit();
}
private:
@@ -124,7 +137,6 @@ private:
return s_RealLoadLibraryExW(lpLibFileName, hFile, dwFlags);
}
static CNktHookLib s_HookManager;
static LoadLibraryAFunc s_RealLoadLibraryA;
static LoadLibraryWFunc s_RealLoadLibraryW;
static LoadLibraryExAFunc s_RealLoadLibraryExA;
@@ -139,7 +151,7 @@ private:
L"SS2OSD.dll", // ASUS Sonic Studio 2
L"Nahimic2OSD.dll",
L"NahimicMSIOSD.dll",
L"nhAsusPhoebusOSD.dll" // ASUS Phoebus
L"nhAsusPhoebusOSD.dll", // ASUS Phoebus
// This DLL has been seen in several crash reports. Some Googling
// suggests it's highly unstable and causes issues in many games.
@@ -209,7 +221,6 @@ private:
};
};
CNktHookLib AntiHookingProtection::s_HookManager;
LoadLibraryAFunc AntiHookingProtection::s_RealLoadLibraryA;
LoadLibraryWFunc AntiHookingProtection::s_RealLoadLibraryW;
LoadLibraryExAFunc AntiHookingProtection::s_RealLoadLibraryExA;
@@ -218,14 +229,26 @@ LoadLibraryExWFunc AntiHookingProtection::s_RealLoadLibraryExW;
AH_EXPORT void AntiHookingDummyImport() {}
extern "C"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DetourRestoreAfterWith();
AntiHookingProtection::enable();
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
// Ignore DLL_PROCESS_DETACH on process exit. No need to waste time
// unhooking everything if the whole process is being destroyed.
if (lpvReserved == NULL) {
AntiHookingProtection::disable();
}
break;
}
return TRUE;
+18 -8
View File
@@ -1,21 +1,23 @@
# Moonlight PC
[Moonlight PC](https://moonlight-stream.org) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built to run on Windows, Mac, and Linux. This client is the successor to [Moonlight Chrome](https://github.com/moonlight-stream/moonlight-chrome) for streaming on PC.
[Moonlight PC](https://moonlight-stream.org) is an open source PC client for NVIDIA GameStream, as used by the NVIDIA Shield.
Moonlight also has mobile versions for [Android](https://github.com/moonlight-stream/moonlight-android) and [iOS](https://github.com/moonlight-stream/moonlight-ios).
You can follow development on our [Discord server](https://moonlight-stream.org/discord).
You can follow development on our [Discord server](https://moonlight-stream.org/discord) and help translate Moonlight into your language on [Weblate](https://hosted.weblate.org/projects/moonlight/moonlight-qt/).
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/glj5cxqwy2w3bglv/branch/master?svg=true)](https://ci.appveyor.com/project/cgutman/moonlight-qt/branch/master)
[![Downloads](https://img.shields.io/github/downloads/moonlight-stream/moonlight-qt/total)](https://github.com/moonlight-stream/moonlight-qt/releases)
[![Translation Status](https://hosted.weblate.org/widgets/moonlight/-/moonlight-qt/svg-badge.svg)](https://hosted.weblate.org/projects/moonlight/moonlight-qt/)
## Features
- Hardware accelerated video decoding on Windows, Mac, and Linux
- Supports streaming at up to 120 FPS (high refresh rate monitor recommended)
- Supports streaming at 720p, 1080p, 1440p, 4K, and the client PC's native screen resolution
- HDR streaming support
- 7.1 surround sound audio support
- Support for both pointer capture (for games) and direct mouse control (for remote desktop)
- Support for passing system-wide keyboard shortcuts like Alt+Tab to the host in fullscreen mode
- Support for passing system-wide keyboard shortcuts like Alt+Tab to the host
- Direct touchscreen mouse control
- HEVC support for better image quality at reduced bandwidth
- Gamepad support with force feedback for up to 4 players
@@ -28,6 +30,12 @@ You can follow development on our [Discord server](https://moonlight-stream.org/
- [Raspberry Pi 4](https://github.com/moonlight-stream/moonlight-docs/wiki/Installing-Moonlight-Qt-on-Raspberry-Pi-4)
- [NVIDIA Jetson and Nintendo Switch (Ubuntu L4T)](https://github.com/moonlight-stream/moonlight-docs/wiki/Installing-Moonlight-Qt-on-Linux4Tegra-(L4T)-Ubuntu)
#### Special Thanks
[![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith&style=flat-square)](https://cloudsmith.com)
Hosting for Moonlight's Raspberry Pi and L4T package repositories is graciously provided for free by [Cloudsmith](https://cloudsmith.com).
## Building
### Windows Build Requirements
@@ -36,12 +44,12 @@ You can follow development on our [Discord server](https://moonlight-stream.org/
* [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) (Community edition is fine)
* Select **MSVC 2019** option during Qt installation. MinGW is not supported.
* [7-Zip](https://www.7-zip.org/) (only if building installers for non-development PCs)
* [WiX Toolset](https://wixtoolset.org/releases/) v3.11 or later (only if building installers for non-development PCs)
* [WiX Toolset](https://wixtoolset.org/releases/v3-14-0-5722/) v3.14.0.5722 or later (only if building installers for non-development PCs)
### macOS Build Requirements
* Qt 5.15 SDK or later
* macOS High Sierra (10.13) or later
* Xcode 11
* Qt 6.2 SDK or later
* macOS Mojave (10.14) or later
* Xcode 13
* [create-dmg](https://github.com/sindresorhus/create-dmg) (only if building DMGs for use on non-development Macs)
### Linux/Unix Build Requirements
@@ -49,7 +57,7 @@ You can follow development on our [Discord server](https://moonlight-stream.org/
* GCC or Clang
* Install the required packages:
* Debian/Ubuntu: `libegl1-mesa-dev libgl1-mesa-dev libopus-dev libqt5svg5-dev libsdl2-dev libsdl2-ttf-dev libssl-dev libavcodec-dev libva-dev libvdpau-dev libxkbcommon-dev qt5-default qt5-qmake qtbase5-dev qtdeclarative5-dev qtquickcontrols2-5-dev wayland-protocols qml-module-qtquick-controls2 qml-module-qtquick-layouts qml-module-qtquick-window2 qml-module-qtquick2`
* RedHat/Fedora: `openssl-devel qt5-devel SDL2-devel ffmpeg-devel qt5-qtquickcontrols2-devel libva-devel libvdpau-devel opus-devel pulseaudio-libs-devel alsa-lib-devel SDL2_ttf-devel`
* RedHat/Fedora: `openssl-devel SDL2-devel SDL2_ttf-devel ffmpeg-devel qt5-qtsvg-devel qt5-qtquickcontrols2-devel libva-devel libvdpau-devel opus-devel pulseaudio-libs-devel alsa-lib-devel`
* FFmpeg 4.0+ is required to build. If your distro doesn't package FFmpeg 4.0 or later, you can build and install it from source on https://ffmpeg.org/
### Steam Link Build Requirements
@@ -68,6 +76,8 @@ You can follow development on our [Discord server](https://moonlight-stream.org/
* For macOS builds, use `scripts/generate-dmg.sh`. Execute this script from the root of the repository and ensure Qt's `bin` folder is in your `$PATH`.
* For Steam Link builds, run `scripts/build-steamlink-app.sh` from the root of the repository.
* To build from the command line for development use, run `qmake moonlight-qt.pro` then `make debug` or `make release`
* To create an embedded build for a single-purpose device, use `qmake "CONFIG+=embedded" moonlight-qt.pro` and build normally.
* This build will lack windowed mode, Discord/Help links, and other features that don't make sense on an embedded device.
## Contribute
1. Fork us
+1 -1
View File
@@ -17,7 +17,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>LSMinimumSystemVersion</key>
<string>10.13</string>
<string>10.14</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
+66 -16
View File
@@ -33,19 +33,21 @@ DEFINES += QT_DEPRECATED_WARNINGS
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
win32 {
INCLUDEPATH += $$PWD/../libs/windows/include
contains(QT_ARCH, i386) {
LIBS += -L$$PWD/../libs/windows/lib/x86
INCLUDEPATH += $$PWD/../libs/windows/include/x86
}
contains(QT_ARCH, x86_64) {
LIBS += -L$$PWD/../libs/windows/lib/x64
INCLUDEPATH += $$PWD/../libs/windows/include/x64
}
contains(QT_ARCH, arm64) {
LIBS += -L$$PWD/../libs/windows/lib/arm64
INCLUDEPATH += $$PWD/../libs/windows/include/arm64
}
LIBS += ws2_32.lib winmm.lib dxva2.lib ole32.lib gdi32.lib user32.lib d3d9.lib dwmapi.lib dbghelp.lib qwave.lib
INCLUDEPATH += $$PWD/../libs/windows/include
LIBS += ws2_32.lib winmm.lib dxva2.lib ole32.lib gdi32.lib user32.lib d3d9.lib dwmapi.lib dbghelp.lib
}
macx {
INCLUDEPATH += $$PWD/../libs/mac/include
@@ -88,6 +90,11 @@ unix:!macx {
PKGCONFIG += libdrm
CONFIG += libdrm
}
packagesExist(ffnvcodec) {
PKGCONFIG += ffnvcodec
CONFIG += cuda
}
}
packagesExist(wayland-client) {
@@ -101,14 +108,14 @@ unix:!macx {
}
}
win32 {
LIBS += -llibssl -llibcrypto -lSDL2 -lSDL2_ttf -lavcodec -lavutil -lopus
LIBS += -llibssl -llibcrypto -lSDL2 -lSDL2_ttf -lavcodec -lavutil -lopus -ldxgi -ld3d11
CONFIG += ffmpeg
}
win32:!winrt {
CONFIG += soundio discord-rpc
}
macx {
LIBS += -lssl -lcrypto -lavcodec.58 -lavutil.56 -lopus -framework SDL2 -framework SDL2_ttf
LIBS += -lssl -lcrypto -lavcodec.59 -lavutil.57 -lopus -framework SDL2 -framework SDL2_ttf
LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreGraphics -framework CoreMedia -framework AppKit -framework Metal
# For libsoundio
@@ -118,6 +125,7 @@ macx {
}
SOURCES += \
backend/nvaddress.cpp \
backend/nvapp.cpp \
main.cpp \
backend/computerseeker.cpp \
@@ -131,6 +139,7 @@ SOURCES += \
cli/commandlineparser.cpp \
cli/quitstream.cpp \
cli/startstream.cpp \
settings/compatfetcher.cpp \
settings/mappingfetcher.cpp \
settings/streamingpreferences.cpp \
streaming/input/abstouch.cpp \
@@ -154,7 +163,9 @@ SOURCES += \
wm.cpp
HEADERS += \
backend/nvaddress.h \
backend/nvapp.h \
settings/compatfetcher.h \
settings/mappingfetcher.h \
utils.h \
backend/computerseeker.h \
@@ -192,7 +203,6 @@ ffmpeg {
SOURCES += \
streaming/video/ffmpeg.cpp \
streaming/video/ffmpeg-renderers/sdlvid.cpp \
streaming/video/ffmpeg-renderers/cuda.cpp \
streaming/video/ffmpeg-renderers/pacer/pacer.cpp \
streaming/video/ffmpeg-renderers/pacer/nullthreadedvsyncsource.cpp
@@ -200,7 +210,6 @@ ffmpeg {
streaming/video/ffmpeg.h \
streaming/video/ffmpeg-renderers/renderer.h \
streaming/video/ffmpeg-renderers/sdlvid.h \
streaming/video/ffmpeg-renderers/cuda.h \
streaming/video/ffmpeg-renderers/pacer/pacer.h \
streaming/video/ffmpeg-renderers/pacer/nullthreadedvsyncsource.h
}
@@ -250,6 +259,19 @@ libdrm {
DEFINES += HAVE_DRM
SOURCES += streaming/video/ffmpeg-renderers/drm.cpp
HEADERS += streaming/video/ffmpeg-renderers/drm.h
linux {
message(Master hooks enabled)
SOURCES += masterhook.c
LIBS += -ldl
}
}
cuda {
message(CUDA support enabled)
DEFINES += HAVE_CUDA
SOURCES += streaming/video/ffmpeg-renderers/cuda.cpp
HEADERS += streaming/video/ffmpeg-renderers/cuda.h
}
config_EGL {
message(EGL renderer selected)
@@ -264,7 +286,7 @@ config_EGL {
config_SL {
message(Steam Link build configuration selected)
DEFINES += STEAM_LINK HAVE_SLVIDEO HAVE_SLAUDIO
DEFINES += EMBEDDED_BUILD STEAM_LINK HAVE_SLVIDEO HAVE_SLAUDIO
LIBS += -lSLVideo -lSLAudio
SOURCES += \
@@ -274,15 +296,20 @@ config_SL {
streaming/video/slvid.h \
streaming/audio/renderers/slaud.h
}
win32 {
HEADERS += streaming/video/ffmpeg-renderers/dxutil.h
}
win32:!winrt {
message(DXVA2 renderer selected)
message(DXVA2 and D3D11VA renderers selected)
SOURCES += \
streaming/video/ffmpeg-renderers/dxva2.cpp \
streaming/video/ffmpeg-renderers/d3d11va.cpp \
streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp
HEADERS += \
streaming/video/ffmpeg-renderers/dxva2.h \
streaming/video/ffmpeg-renderers/d3d11va.h \
streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h
}
macx {
@@ -307,13 +334,38 @@ discord-rpc {
LIBS += -ldiscord-rpc
DEFINES += HAVE_DISCORD
}
embedded {
message(Embedded build)
DEFINES += EMBEDDED_BUILD
}
RESOURCES += \
resources.qrc \
qml.qrc
TRANSLATIONS += \
languages/qml_fr.ts
languages/qml_zh_cn.ts \
languages/qml_de.ts \
languages/qml_fr.ts \
languages/qml_nb_NO.ts \
languages/qml_ru.ts \
languages/qml_es.ts \
languages/qml_ja.ts \
languages/qml_vi.ts \
languages/qml_th.ts \
languages/qml_ko.ts \
languages/qml_hu.ts \
languages/qml_nl.ts \
languages/qml_sv.ts \
languages/qml_tr.ts \
languages/qml_uk.ts \
languages/qml_zh_Hant.ts \
languages/qml_el.ts \
languages/qml_hi.ts \
languages/qml_it.ts \
languages/qml_pt.ts \
languages/qml_pt_BR.ts
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
@@ -352,13 +404,11 @@ INCLUDEPATH += $$PWD/../h264bitstream/h264bitstream
DEPENDPATH += $$PWD/../h264bitstream/h264bitstream
!winrt {
contains(QT_ARCH, i386)|contains(QT_ARCH, x86_64) {
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/release/ -lAntiHooking
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/debug/ -lAntiHooking
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/release/ -lAntiHooking
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../AntiHooking/debug/ -lAntiHooking
INCLUDEPATH += $$PWD/../AntiHooking
DEPENDPATH += $$PWD/../AntiHooking
}
INCLUDEPATH += $$PWD/../AntiHooking
DEPENDPATH += $$PWD/../AntiHooking
}
unix:!macx: {
+66 -35
View File
@@ -15,8 +15,8 @@ AutoUpdateChecker::AutoUpdateChecker(QObject *parent) :
// Allow HTTP redirects
m_Nam.setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
connect(&m_Nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(handleUpdateCheckRequestFinished(QNetworkReply*)));
connect(&m_Nam, &QNetworkAccessManager::finished,
this, &AutoUpdateChecker::handleUpdateCheckRequestFinished);
QString currentVersion(VERSION_STR);
qDebug() << "Current Moonlight version:" << currentVersion;
@@ -63,11 +63,41 @@ QString AutoUpdateChecker::getPlatform()
return QStringLiteral("steamlink");
#elif defined(APP_IMAGE)
return QStringLiteral("appimage");
#elif defined(Q_OS_DARWIN) && QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Qt 6 changed this from 'osx' to 'macos'. Use the old one
// to be consistent (and not require another entry in the manifest).
return QStringLiteral("osx");
#else
return QSysInfo::productType();
#endif
}
int AutoUpdateChecker::compareVersion(QVector<int>& version1, QVector<int>& version2) {
for (int i = 0;; i++) {
int v1Val = 0;
int v2Val = 0;
// Treat missing decimal places as 0
if (i < version1.count()) {
v1Val = version1[i];
}
if (i < version2.count()) {
v2Val = version2[i];
}
if (i >= version1.count() && i >= version2.count()) {
// Equal versions
return 0;
}
if (v1Val < v2Val) {
return -1;
}
else if (v1Val > v2Val) {
return 1;
}
}
}
void AutoUpdateChecker::handleUpdateCheckRequestFinished(QNetworkReply* reply)
{
Q_ASSERT(reply->isFinished());
@@ -119,46 +149,47 @@ void AutoUpdateChecker::handleUpdateCheckRequestFinished(QNetworkReply* reply)
if (updateObj["arch"] == QSysInfo::buildCpuArchitecture() &&
updateObj["platform"] == getPlatform()) {
// Check the kernel version minimum if one exists
if (updateObj.contains("kernel_version_at_least") && updateObj["kernel_version_at_least"].isString()) {
QVector<int> requiredVersionQuad;
QVector<int> actualVersionQuad;
QString requiredVersion = updateObj["kernel_version_at_least"].toString();
QString actualVersion = QSysInfo::kernelVersion();
parseStringToVersionQuad(requiredVersion, requiredVersionQuad);
parseStringToVersionQuad(actualVersion, actualVersionQuad);
if (compareVersion(actualVersionQuad, requiredVersionQuad) < 0) {
qDebug() << "Skipping manifest entry due to kernel version (" << actualVersion << "<" << requiredVersion << ")";
continue;
}
}
qDebug() << "Found update manifest match for current platform";
QString latestVersion = updateObj["version"].toString();
qDebug() << "Latest version of Moonlight for this platform is:" << latestVersion;
QVector<int> latestVersionQuad;
parseStringToVersionQuad(latestVersion, latestVersionQuad);
for (int i = 0;; i++) {
int latestVer = 0;
int currentVer = 0;
// Treat missing decimal places as 0
if (i < latestVersionQuad.count()) {
latestVer = latestVersionQuad[i];
}
if (i < m_CurrentVersionQuad.count()) {
currentVer = m_CurrentVersionQuad[i];
}
if (i >= latestVersionQuad.count() && i >= m_CurrentVersionQuad.count()) {
break;
}
if (currentVer < latestVer) {
qDebug() << "Update available";
emit onUpdateAvailable(updateObj["version"].toString(),
updateObj["browser_url"].toString());
return;
}
else if (currentVer > latestVer) {
qDebug() << "Update manifest version lower than current version";
return;
}
int res = compareVersion(m_CurrentVersionQuad, latestVersionQuad);
if (res < 0) {
// m_CurrentVersionQuad < latestVersionQuad
qDebug() << "Update available";
emit onUpdateAvailable(updateObj["version"].toString(),
updateObj["browser_url"].toString());
return;
}
else if (res > 0) {
qDebug() << "Update manifest version lower than current version";
return;
}
else {
qDebug() << "Update manifest version equal to current version";
return;
}
qDebug() << "Update manifest version equal to current version";
return;
}
}
else {
@@ -166,8 +197,8 @@ void AutoUpdateChecker::handleUpdateCheckRequestFinished(QNetworkReply* reply)
}
}
qWarning() << "No entry in update manifest found for current platform: "
<< QSysInfo::buildCpuArchitecture() << getPlatform();
qWarning() << "No entry in update manifest found for current platform:"
<< QSysInfo::buildCpuArchitecture() << getPlatform() << QSysInfo::kernelVersion();
}
else {
qWarning() << "Update checking failed with error: " << reply->error();
+2
View File
@@ -20,6 +20,8 @@ private slots:
private:
void parseStringToVersionQuad(QString& string, QVector<int>& version);
int compareVersion(QVector<int>& version1, QVector<int>& version2);
QString getPlatform();
QVector<int> m_CurrentVersionQuad;
+3 -3
View File
@@ -46,8 +46,8 @@ public:
m_Computer(computer),
m_App(app)
{
connect(this, SIGNAL(boxArtFetchCompleted(NvComputer*,NvApp,QUrl)),
boxArtManager, SLOT(handleBoxArtLoadComplete(NvComputer*,NvApp,QUrl)));
connect(this, &NetworkBoxArtLoadTask::boxArtFetchCompleted,
boxArtManager, &BoxArtManager::handleBoxArtLoadComplete);
}
signals:
@@ -106,7 +106,7 @@ void BoxArtManager::handleBoxArtLoadComplete(NvComputer* computer, NvApp app, QU
QUrl BoxArtManager::loadBoxArtFromNetwork(NvComputer* computer, int appId)
{
NvHTTP http(computer->activeAddress, computer->serverCert);
NvHTTP http(computer);
QString cachePath = getFilePathForBoxArt(computer, appId);
QImage image;
+47 -33
View File
@@ -27,9 +27,9 @@ public:
}
private:
bool tryPollComputer(QString address, bool& changed)
bool tryPollComputer(NvAddress address, bool& changed)
{
NvHTTP http(address, m_Computer->serverCert);
NvHTTP http(address, 0, m_Computer->serverCert);
QString serverInfo;
try {
@@ -38,7 +38,7 @@ private:
return false;
}
NvComputer newState(address, serverInfo, QSslCertificate());
NvComputer newState(http, serverInfo);
// Ensure the machine that responded is the one we intended to contact
if (m_Computer->uuid != newState.uuid) {
@@ -52,9 +52,7 @@ private:
bool updateAppList(bool& changed)
{
Q_ASSERT(m_Computer->activeAddress != nullptr);
NvHTTP http(m_Computer->activeAddress, m_Computer->serverCert);
NvHTTP http(m_Computer);
QVector<NvApp> appList;
@@ -88,7 +86,7 @@ private:
if (tryPollComputer(address, stateChanged)) {
if (!wasOnline) {
qInfo() << m_Computer->name << "is now online at" << m_Computer->activeAddress;
qInfo() << m_Computer->name << "is now online at" << m_Computer->activeAddress.toString();
}
online = true;
break;
@@ -146,7 +144,8 @@ private:
ComputerManager::ComputerManager(QObject *parent)
: QObject(parent),
m_PollingRef(0),
m_MdnsBrowser(nullptr)
m_MdnsBrowser(nullptr),
m_CompatFetcher(nullptr)
{
QSettings settings;
@@ -159,12 +158,15 @@ ComputerManager::ComputerManager(QObject *parent)
}
settings.endArray();
// Fetch latest compatibility data asynchronously
m_CompatFetcher.start();
// To quit in a timely manner, we must block additional requests
// after we receive the aboutToQuit() signal. This is neccessary
// because NvHTTP uses aboutToQuit() to abort requests in progres
// while quitting, however this is a one time signal - additional
// requests would not be aborted and block termination.
connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(handleAboutToQuit()));
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &ComputerManager::handleAboutToQuit);
}
ComputerManager::~ComputerManager()
@@ -302,8 +304,8 @@ void ComputerManager::startPollingComputer(NvComputer* computer)
if (!pollingEntry->isActive()) {
PcMonitorThread* thread = new PcMonitorThread(computer);
connect(thread, SIGNAL(computerStateChanged(NvComputer*)),
this, SLOT(handleComputerStateChanged(NvComputer*)));
connect(thread, &PcMonitorThread::computerStateChanged,
this, &ComputerManager::handleComputerStateChanged);
pollingEntry->setActiveThread(thread);
thread->start();
}
@@ -322,7 +324,7 @@ void ComputerManager::handleMdnsServiceResolved(MdnsPendingComputer* computer,
// address may not be reachable (if the user hasn't installed the IPv6 helper yet
// or if this host lacks outbound IPv6 capability). We want to add IPv6 even if
// it's not currently reachable.
addNewHost(address.toString(), true, v6Global);
addNewHost(NvAddress(address, computer->port()), true, NvAddress(v6Global, computer->port()));
added = true;
break;
}
@@ -336,8 +338,7 @@ void ComputerManager::handleMdnsServiceResolved(MdnsPendingComputer* computer,
if (address.isInSubnet(QHostAddress("fe80::"), 10) ||
address.isInSubnet(QHostAddress("fec0::"), 10) ||
address.isInSubnet(QHostAddress("fc00::"), 7)) {
addNewHost(address.toString(), true, v6Global);
added = true;
addNewHost(NvAddress(address, computer->port()), true, NvAddress(v6Global, computer->port()));
break;
}
}
@@ -418,7 +419,7 @@ void ComputerManager::deleteHost(NvComputer* computer)
void ComputerManager::renameHost(NvComputer* computer, QString name)
{
{
QWriteLocker(&computer->lock);
QWriteLocker lock(&computer->lock);
computer->name = name;
computer->hasCustomName = true;
@@ -467,7 +468,7 @@ signals:
private:
void run()
{
NvPairingManager pairingManager(m_Computer->activeAddress);
NvPairingManager pairingManager(m_Computer);
try {
NvPairingManager::PairState result = pairingManager.pair(m_Computer->appVersion, m_Pin, m_Computer->serverCert);
@@ -523,7 +524,7 @@ signals:
private:
void run()
{
NvHTTP http(m_Computer->activeAddress, m_Computer->serverCert);
NvHTTP http(m_Computer);
try {
if (m_Computer->currentGameId != 0) {
@@ -589,12 +590,24 @@ void ComputerManager::stopPollingAsync()
}
}
void ComputerManager::addNewHostManually(QString address)
{
QUrl url = QUrl::fromUserInput(address);
if (url.isValid() && !url.host().isEmpty()) {
// If there wasn't a port specified, use the default
addNewHost(NvAddress(url.host(), url.port(DEFAULT_HTTP_PORT)), false);
}
else {
emit computerAddCompleted(false, false);
}
}
class PendingAddTask : public QObject, public QRunnable
{
Q_OBJECT
public:
PendingAddTask(ComputerManager* computerManager, QString address, QHostAddress mdnsIpv6Address, bool mdns)
PendingAddTask(ComputerManager* computerManager, NvAddress address, NvAddress mdnsIpv6Address, bool mdns)
: m_ComputerManager(computerManager),
m_Address(address),
m_MdnsIpv6Address(mdnsIpv6Address),
@@ -658,15 +671,15 @@ private:
void run()
{
NvHTTP http(m_Address, QSslCertificate());
NvHTTP http(m_Address, 0, QSslCertificate());
qInfo() << "Processing new PC at" << m_Address << "from" << (m_Mdns ? "mDNS" : "user") << m_MdnsIpv6Address;
qInfo() << "Processing new PC at" << m_Address.toString() << "from" << (m_Mdns ? "mDNS" : "user") << "with IPv6 address" << m_MdnsIpv6Address.toString();
// Perform initial serverinfo fetch over HTTP since we don't know which cert to use
QString serverInfo = fetchServerInfo(http);
if (serverInfo.isEmpty() && !m_MdnsIpv6Address.isNull()) {
// Retry using the global IPv6 address if the IPv4 or link-local IPv6 address fails
http.setAddress(m_MdnsIpv6Address.toString());
http.setAddress(m_MdnsIpv6Address);
serverInfo = fetchServerInfo(http);
}
if (serverInfo.isEmpty()) {
@@ -674,7 +687,7 @@ private:
}
// Create initial newComputer using HTTP serverinfo with no pinned cert
NvComputer* newComputer = new NvComputer(http.address(), serverInfo, QSslCertificate());
NvComputer* newComputer = new NvComputer(http, serverInfo);
// Check if we have a record of this host UUID to pull the pinned cert
NvComputer* existingComputer;
@@ -688,13 +701,14 @@ private:
// Fetch serverinfo again over HTTPS with the pinned cert
if (existingComputer != nullptr) {
Q_ASSERT(http.httpsPort() != 0);
serverInfo = fetchServerInfo(http);
if (serverInfo.isEmpty()) {
return;
}
// Update the polled computer with the HTTPS information
NvComputer httpsComputer(http.address(), serverInfo, QSslCertificate());
NvComputer httpsComputer(http, serverInfo);
newComputer->update(httpsComputer);
}
@@ -708,11 +722,11 @@ private:
}
// Get the WAN IP address using STUN if we're on mDNS over IPv4
if (QHostAddress(newComputer->localAddress).protocol() == QAbstractSocket::IPv4Protocol) {
if (QHostAddress(newComputer->localAddress.address()).protocol() == QAbstractSocket::IPv4Protocol) {
quint32 addr;
int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr);
if (err == 0) {
newComputer->remoteAddress = QHostAddress(qFromBigEndian(addr)).toString();
newComputer->setRemoteAddress(QHostAddress(qFromBigEndian(addr)));
}
else {
qWarning() << "STUN failed to get WAN address:" << err;
@@ -720,15 +734,15 @@ private:
}
if (!m_MdnsIpv6Address.isNull()) {
Q_ASSERT(m_MdnsIpv6Address.protocol() == QAbstractSocket::IPv6Protocol);
newComputer->ipv6Address = m_MdnsIpv6Address.toString();
Q_ASSERT(QHostAddress(m_MdnsIpv6Address.address()).protocol() == QAbstractSocket::IPv6Protocol);
newComputer->ipv6Address = m_MdnsIpv6Address;
}
}
else {
newComputer->manualAddress = m_Address;
}
QHostAddress hostAddress(m_Address);
QHostAddress hostAddress(m_Address.address());
bool addressIsSiteLocalV4 =
hostAddress.isInSubnet(QHostAddress("10.0.0.0"), 8) ||
hostAddress.isInSubnet(QHostAddress("172.16.0.0"), 12) ||
@@ -753,7 +767,7 @@ private:
// Tell our client if something changed
if (changed) {
qInfo() << existingComputer->name << "is now at" << existingComputer->activeAddress;
qInfo() << existingComputer->name << "is now at" << existingComputer->activeAddress.toString();
emit computerStateChanged(existingComputer);
}
}
@@ -774,7 +788,7 @@ private:
int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr);
if (err == 0) {
lock.relock();
newComputer->remoteAddress = QHostAddress(qFromBigEndian(addr)).toString();
newComputer->setRemoteAddress(QHostAddress(qFromBigEndian(addr)));
lock.unlock();
}
else {
@@ -794,12 +808,12 @@ private:
}
ComputerManager* m_ComputerManager;
QString m_Address;
QHostAddress m_MdnsIpv6Address;
NvAddress m_Address;
NvAddress m_MdnsIpv6Address;
bool m_Mdns;
};
void ComputerManager::addNewHost(QString address, bool mdns, QHostAddress mdnsIpv6Address)
void ComputerManager::addNewHost(NvAddress address, bool mdns, NvAddress mdnsIpv6Address)
{
// Punt to a worker thread to avoid stalling the
// UI while waiting for serverinfo query to complete
+13 -2
View File
@@ -2,6 +2,7 @@
#include "nvcomputer.h"
#include "nvpairingmanager.h"
#include "settings/compatfetcher.h"
#include <qmdnsengine/server.h>
#include <qmdnsengine/cache.h>
@@ -23,6 +24,7 @@ public:
explicit MdnsPendingComputer(QMdnsEngine::Server* server,
const QMdnsEngine::Service& service)
: m_Hostname(service.hostname()),
m_Port(service.port()),
m_Server(server),
m_Resolver(nullptr)
{
@@ -40,6 +42,11 @@ public:
return m_Hostname;
}
uint16_t port()
{
return m_Port;
}
private slots:
void handleResolvedTimeout()
{
@@ -70,10 +77,11 @@ private:
m_Resolver = new QMdnsEngine::Resolver(m_Server, m_Hostname);
connect(m_Resolver, &QMdnsEngine::Resolver::resolved,
this, &MdnsPendingComputer::handleResolvedAddress);
QTimer::singleShot(2000, this, SLOT(handleResolvedTimeout()));
QTimer::singleShot(2000, this, &MdnsPendingComputer::handleResolvedTimeout);
}
QByteArray m_Hostname;
uint16_t m_Port;
QMdnsEngine::Server* m_Server;
QMdnsEngine::Resolver* m_Resolver;
QVector<QHostAddress> m_Addresses;
@@ -168,7 +176,9 @@ public:
Q_INVOKABLE void stopPollingAsync();
Q_INVOKABLE void addNewHost(QString address, bool mdns, QHostAddress mdnsIpv6Address = QHostAddress());
Q_INVOKABLE void addNewHostManually(QString address);
void addNewHost(NvAddress address, bool mdns, NvAddress mdnsIpv6Address = NvAddress());
void pairHost(NvComputer* computer, QString pin);
@@ -214,4 +224,5 @@ private:
QMdnsEngine::Browser* m_MdnsBrowser;
QMdnsEngine::Cache m_MdnsCache;
QVector<MdnsPendingComputer*> m_PendingResolution;
CompatFetcher m_CompatFetcher;
};
+3 -3
View File
@@ -20,7 +20,7 @@ void ComputerSeeker::start(int timeout)
// if m_ComputerName is UUID, or the name that doesn't resolve to an IP
// address) and by polling it using mDNS, hopefully one of these methods
// would find the host
m_ComputerManager->addNewHost(m_ComputerName, false);
m_ComputerManager->addNewHostManually(m_ComputerName);
m_ComputerManager->startPolling();
}
@@ -44,8 +44,8 @@ bool ComputerSeeker::matchComputer(NvComputer *computer) const
return true;
}
for (const QString& addr : computer->uniqueAddresses()) {
if (addr.toLower() == value) {
for (const NvAddress& addr : computer->uniqueAddresses()) {
if (addr.address().toLower() == value || addr.toString().toLower() == value) {
return true;
}
}
+4 -1
View File
@@ -143,7 +143,10 @@ QSslKey
IdentityManager::getSslKey()
{
if (m_CachedSslKey.isNull()) {
BIO* bio = BIO_new_mem_buf(m_CachedPrivateKey.data(), -1);
// This seemingly useless const_cast is required for old OpenSSL headers
// where BIO_new_mem_buf's parameter is not declared const like those on
// the Steam Link hardware.
BIO* bio = BIO_new_mem_buf(const_cast<char*>(m_CachedPrivateKey.constData()), -1);
THROW_BAD_ALLOC_IF_NULL(bio);
EVP_PKEY* pk = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
+65
View File
@@ -0,0 +1,65 @@
#include "nvaddress.h"
#include <QHostAddress>
NvAddress::NvAddress()
{
setAddress(nullptr);
setPort(0);
}
NvAddress::NvAddress(QString addr, uint16_t port)
{
setAddress(addr);
setPort(port);
}
NvAddress::NvAddress(QHostAddress addr, uint16_t port)
{
setAddress(addr);
setPort(port);
}
uint16_t NvAddress::port() const
{
return m_Port;
}
QString NvAddress::address() const
{
return m_Address;
}
void NvAddress::setPort(uint16_t port)
{
m_Port = port;
}
void NvAddress::setAddress(QString addr)
{
m_Address = addr;
}
void NvAddress::setAddress(QHostAddress addr)
{
m_Address = addr.toString();
}
bool NvAddress::isNull() const
{
return m_Address.isEmpty();
}
QString NvAddress::toString() const
{
if (m_Address.isEmpty()) {
return "<NULL>";
}
if (QHostAddress(m_Address).protocol() == QAbstractSocket::IPv6Protocol) {
return QString("[%1]:%2").arg(m_Address).arg(m_Port);
}
else {
return QString("%1:%2").arg(m_Address).arg(m_Port);
}
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <QHostAddress>
#define DEFAULT_HTTP_PORT 47989
#define DEFAULT_HTTPS_PORT 47984
class NvAddress
{
public:
NvAddress();
explicit NvAddress(QString addr, uint16_t port);
explicit NvAddress(QHostAddress addr, uint16_t port);
uint16_t port() const;
void setPort(uint16_t port);
QString address() const;
void setAddress(QString addr);
void setAddress(QHostAddress addr);
bool isNull() const;
QString toString() const;
bool operator==(const NvAddress& other) const
{
return m_Address == other.m_Address &&
m_Port == other.m_Port;
}
bool operator!=(const NvAddress& other) const
{
return !operator==(other);
}
private:
QString m_Address;
uint16_t m_Port;
};
+76 -27
View File
@@ -1,5 +1,6 @@
#include "nvcomputer.h"
#include "nvapp.h"
#include "settings/compatfetcher.h"
#include <QUdpSocket>
#include <QHostInfo>
@@ -10,9 +11,13 @@
#define SER_UUID "uuid"
#define SER_MAC "mac"
#define SER_LOCALADDR "localaddress"
#define SER_LOCALPORT "localport"
#define SER_REMOTEADDR "remoteaddress"
#define SER_REMOTEPORT "remoteport"
#define SER_MANUALADDR "manualaddress"
#define SER_MANUALPORT "manualport"
#define SER_IPV6ADDR "ipv6address"
#define SER_IPV6PORT "ipv6port"
#define SER_APPLIST "apps"
#define SER_SRVCERT "srvcert"
#define SER_CUSTOMNAME "customname"
@@ -23,13 +28,18 @@ NvComputer::NvComputer(QSettings& settings)
this->uuid = settings.value(SER_UUID).toString();
this->hasCustomName = settings.value(SER_CUSTOMNAME).toBool();
this->macAddress = settings.value(SER_MAC).toByteArray();
this->localAddress = settings.value(SER_LOCALADDR).toString();
this->remoteAddress = settings.value(SER_REMOTEADDR).toString();
this->ipv6Address = settings.value(SER_IPV6ADDR).toString();
this->manualAddress = settings.value(SER_MANUALADDR).toString();
this->localAddress = NvAddress(settings.value(SER_LOCALADDR).toString(),
settings.value(SER_LOCALPORT, QVariant(DEFAULT_HTTP_PORT)).toUInt());
this->remoteAddress = NvAddress(settings.value(SER_REMOTEADDR).toString(),
settings.value(SER_REMOTEPORT, QVariant(DEFAULT_HTTP_PORT)).toUInt());
this->ipv6Address = NvAddress(settings.value(SER_IPV6ADDR).toString(),
settings.value(SER_IPV6PORT, QVariant(DEFAULT_HTTP_PORT)).toUInt());
this->manualAddress = NvAddress(settings.value(SER_MANUALADDR).toString(),
settings.value(SER_MANUALPORT, QVariant(DEFAULT_HTTP_PORT)).toUInt());
this->serverCert = QSslCertificate(settings.value(SER_SRVCERT).toByteArray());
int appCount = settings.beginReadArray(SER_APPLIST);
this->appList.reserve(appCount);
for (int i = 0; i < appCount; i++) {
settings.setArrayIndex(i);
@@ -39,7 +49,6 @@ NvComputer::NvComputer(QSettings& settings)
settings.endArray();
sortAppList();
this->activeAddress = nullptr;
this->currentGameId = 0;
this->pairState = PS_UNKNOWN;
this->state = CS_UNKNOWN;
@@ -49,6 +58,16 @@ NvComputer::NvComputer(QSettings& settings)
this->serverCodecModeSupport = 0;
this->pendingQuit = false;
this->gpuModel = nullptr;
this->isSupportedServerVersion = true;
this->externalPort = this->remoteAddress.port();
this->activeHttpsPort = 0;
}
void NvComputer::setRemoteAddress(QHostAddress address)
{
Q_ASSERT(this->externalPort != 0);
this->remoteAddress = NvAddress(address, this->externalPort);
}
void NvComputer::serialize(QSettings& settings) const
@@ -59,10 +78,14 @@ void NvComputer::serialize(QSettings& settings) const
settings.setValue(SER_CUSTOMNAME, hasCustomName);
settings.setValue(SER_UUID, uuid);
settings.setValue(SER_MAC, macAddress);
settings.setValue(SER_LOCALADDR, localAddress);
settings.setValue(SER_REMOTEADDR, remoteAddress);
settings.setValue(SER_IPV6ADDR, ipv6Address);
settings.setValue(SER_MANUALADDR, manualAddress);
settings.setValue(SER_LOCALADDR, localAddress.address());
settings.setValue(SER_LOCALPORT, localAddress.port());
settings.setValue(SER_REMOTEADDR, remoteAddress.address());
settings.setValue(SER_REMOTEPORT, remoteAddress.port());
settings.setValue(SER_IPV6ADDR, ipv6Address.address());
settings.setValue(SER_IPV6PORT, ipv6Address.port());
settings.setValue(SER_MANUALADDR, manualAddress.address());
settings.setValue(SER_MANUALPORT, manualAddress.port());
settings.setValue(SER_SRVCERT, serverCert.toPem());
// Avoid deleting an existing applist if we couldn't get one
@@ -84,9 +107,9 @@ void NvComputer::sortAppList()
});
}
NvComputer::NvComputer(QString address, QString serverInfo, QSslCertificate serverCert)
NvComputer::NvComputer(NvHTTP& http, QString serverInfo)
{
this->serverCert = serverCert;
this->serverCert = http.serverCert();
this->hasCustomName = false;
this->name = NvHTTP::getXmlString(serverInfo, "hostname");
@@ -98,7 +121,7 @@ NvComputer::NvComputer(QString address, QString serverInfo, QSslCertificate serv
QString newMacString = NvHTTP::getXmlString(serverInfo, "mac");
if (newMacString != "00:00:00:00:00:00") {
QStringList macOctets = newMacString.split(':');
for (QString macOctet : macOctets) {
for (const QString& macOctet : macOctets) {
this->macAddress.append((char) macOctet.toInt(nullptr, 16));
}
}
@@ -127,21 +150,41 @@ NvComputer::NvComputer(QString address, QString serverInfo, QSslCertificate serv
});
// We can get an IPv4 loopback address if we're using the GS IPv6 Forwarder
this->localAddress = NvHTTP::getXmlString(serverInfo, "LocalIP");
if (this->localAddress.startsWith("127.")) {
this->localAddress = QString();
this->localAddress = NvAddress(NvHTTP::getXmlString(serverInfo, "LocalIP"), http.httpPort());
if (this->localAddress.address().startsWith("127.")) {
this->localAddress = NvAddress();
}
QString httpsPort = NvHTTP::getXmlString(serverInfo, "HttpsPort");
if (httpsPort.isEmpty() || (this->activeHttpsPort = httpsPort.toUShort()) == 0) {
this->activeHttpsPort = DEFAULT_HTTPS_PORT;
}
// This is an extension which is not present in GFE. It is present for Sunshine to be able
// to support dynamic HTTP WAN ports without requiring the user to manually enter the port.
QString remotePortStr = NvHTTP::getXmlString(serverInfo, "ExternalPort");
if (remotePortStr.isEmpty() || (this->externalPort = remotePortStr.toUShort()) == 0) {
this->externalPort = DEFAULT_HTTP_PORT;
}
QString remoteAddress = NvHTTP::getXmlString(serverInfo, "ExternalIP");
if (!remoteAddress.isEmpty()) {
this->remoteAddress = NvAddress(remoteAddress, this->externalPort);
}
else {
this->remoteAddress = NvAddress();
}
this->remoteAddress = NvHTTP::getXmlString(serverInfo, "ExternalIP");
this->pairState = NvHTTP::getXmlString(serverInfo, "PairStatus") == "1" ?
PS_PAIRED : PS_NOT_PAIRED;
this->currentGameId = NvHTTP::getCurrentGame(serverInfo);
this->appVersion = NvHTTP::getXmlString(serverInfo, "appversion");
this->gfeVersion = NvHTTP::getXmlString(serverInfo, "GfeVersion");
this->gpuModel = NvHTTP::getXmlString(serverInfo, "gputype");
this->activeAddress = address;
this->activeAddress = http.address();
this->state = NvComputer::CS_ONLINE;
this->pendingQuit = false;
this->isSupportedServerVersion = CompatFetcher::isGfeVersionSupported(this->gfeVersion);
}
bool NvComputer::wake()
@@ -173,7 +216,10 @@ bool NvComputer::wake()
// Add the addresses that we know this host to be
// and broadcast addresses for this link just in
// case the host has timed out in ARP entries.
QVector<QString> addressList = uniqueAddresses();
QVector<QString> addressList;
for (const NvAddress& addr : uniqueAddresses()) {
addressList.append(addr.address());
}
addressList.append("255.255.255.255");
// Try to broadcast on all available NICs
@@ -234,14 +280,14 @@ bool NvComputer::wake()
bool NvComputer::isReachableOverVpn()
{
if (activeAddress.isEmpty()) {
if (activeAddress.isNull()) {
return false;
}
QTcpSocket s;
s.setProxy(QNetworkProxy::NoProxy);
s.connectToHost(activeAddress, 47984);
s.connectToHost(activeAddress.address(), activeAddress.port());
if (s.waitForConnected(3000)) {
Q_ASSERT(!s.localAddress().isNull());
@@ -327,9 +373,9 @@ bool NvComputer::updateAppList(QVector<NvApp> newAppList) {
return true;
}
QVector<QString> NvComputer::uniqueAddresses() const
QVector<NvAddress> NvComputer::uniqueAddresses() const
{
QVector<QString> uniqueAddressList;
QVector<NvAddress> uniqueAddressList;
// Start with addresses correctly ordered
uniqueAddressList.append(activeAddress);
@@ -340,7 +386,7 @@ QVector<QString> NvComputer::uniqueAddresses() const
// Prune duplicates (always giving precedence to the first)
for (int i = 0; i < uniqueAddressList.count(); i++) {
if (uniqueAddressList[i].isEmpty()) {
if (uniqueAddressList[i].isNull()) {
uniqueAddressList.remove(i);
i--;
continue;
@@ -396,10 +442,12 @@ bool NvComputer::update(NvComputer& that)
ASSIGN_IF_CHANGED(name);
}
ASSIGN_IF_CHANGED_AND_NONEMPTY(macAddress);
ASSIGN_IF_CHANGED_AND_NONEMPTY(localAddress);
ASSIGN_IF_CHANGED_AND_NONEMPTY(remoteAddress);
ASSIGN_IF_CHANGED_AND_NONEMPTY(ipv6Address);
ASSIGN_IF_CHANGED_AND_NONEMPTY(manualAddress);
ASSIGN_IF_CHANGED_AND_NONNULL(localAddress);
ASSIGN_IF_CHANGED_AND_NONNULL(remoteAddress);
ASSIGN_IF_CHANGED_AND_NONNULL(ipv6Address);
ASSIGN_IF_CHANGED_AND_NONNULL(manualAddress);
ASSIGN_IF_CHANGED(activeHttpsPort);
ASSIGN_IF_CHANGED(externalPort);
ASSIGN_IF_CHANGED(pairState);
ASSIGN_IF_CHANGED(serverCodecModeSupport);
ASSIGN_IF_CHANGED(currentGameId);
@@ -407,6 +455,7 @@ bool NvComputer::update(NvComputer& that)
ASSIGN_IF_CHANGED(state);
ASSIGN_IF_CHANGED(gfeVersion);
ASSIGN_IF_CHANGED(appVersion);
ASSIGN_IF_CHANGED(isSupportedServerVersion);
ASSIGN_IF_CHANGED(maxLumaPixelsHEVC);
ASSIGN_IF_CHANGED(gpuModel);
ASSIGN_IF_CHANGED_AND_NONNULL(serverCert);
+16 -7
View File
@@ -1,6 +1,7 @@
#pragma once
#include "nvhttp.h"
#include "nvaddress.h"
#include <QThread>
#include <QReadWriteLock>
@@ -21,10 +22,13 @@ private:
bool pendingQuit;
public:
explicit NvComputer(QString address, QString serverInfo, QSslCertificate serverCert);
explicit NvComputer(NvHTTP& http, QString serverInfo);
explicit NvComputer(QSettings& settings);
void
setRemoteAddress(QHostAddress);
bool
update(NvComputer& that);
@@ -34,7 +38,7 @@ public:
bool
isReachableOverVpn();
QVector<QString>
QVector<NvAddress>
uniqueAddresses() const;
void
@@ -57,7 +61,8 @@ public:
// Ephemeral traits
ComputerState state;
PairState pairState;
QString activeAddress;
NvAddress activeAddress;
uint16_t activeHttpsPort;
int currentGameId;
QString gfeVersion;
QString appVersion;
@@ -65,12 +70,13 @@ public:
int maxLumaPixelsHEVC;
int serverCodecModeSupport;
QString gpuModel;
bool isSupportedServerVersion;
// Persisted traits
QString localAddress;
QString remoteAddress;
QString ipv6Address;
QString manualAddress;
NvAddress localAddress;
NvAddress remoteAddress;
NvAddress ipv6Address;
NvAddress manualAddress;
QByteArray macAddress;
QString name;
bool hasCustomName;
@@ -80,4 +86,7 @@ public:
// Synchronization
mutable QReadWriteLock lock;
private:
uint16_t externalPort;
};
+81 -19
View File
@@ -1,4 +1,4 @@
#include "nvhttp.h"
#include "nvcomputer.h"
#include <Limelight.h>
#include <QDebug>
@@ -18,15 +18,14 @@
#define RESUME_TIMEOUT_MS 30000
#define QUIT_TIMEOUT_MS 30000
NvHTTP::NvHTTP(QString address, QSslCertificate serverCert) :
NvHTTP::NvHTTP(NvAddress address, uint16_t httpsPort, QSslCertificate serverCert) :
m_ServerCert(serverCert)
{
m_BaseUrlHttp.setScheme("http");
m_BaseUrlHttps.setScheme("https");
m_BaseUrlHttp.setPort(47989);
m_BaseUrlHttps.setPort(47984);
setAddress(address);
setHttpsPort(httpsPort);
// Never use a proxy server
QNetworkProxy noProxy(QNetworkProxy::NoProxy);
@@ -35,26 +34,54 @@ NvHTTP::NvHTTP(QString address, QSslCertificate serverCert) :
connect(&m_Nam, &QNetworkAccessManager::sslErrors, this, &NvHTTP::handleSslErrors);
}
NvHTTP::NvHTTP(NvComputer* computer) :
NvHTTP(computer->activeAddress, computer->activeHttpsPort, computer->serverCert)
{
}
void NvHTTP::setServerCert(QSslCertificate serverCert)
{
m_ServerCert = serverCert;
}
void NvHTTP::setAddress(QString address)
void NvHTTP::setAddress(NvAddress address)
{
Q_ASSERT(!address.isEmpty());
Q_ASSERT(!address.isNull());
m_Address = address;
m_BaseUrlHttp.setHost(address);
m_BaseUrlHttps.setHost(address);
m_BaseUrlHttp.setHost(address.address());
m_BaseUrlHttps.setHost(address.address());
m_BaseUrlHttp.setPort(address.port());
}
QString NvHTTP::address()
void NvHTTP::setHttpsPort(uint16_t port)
{
m_BaseUrlHttps.setPort(port);
}
NvAddress NvHTTP::address()
{
return m_Address;
}
QSslCertificate NvHTTP::serverCert()
{
return m_ServerCert;
}
uint16_t NvHTTP::httpPort()
{
return m_BaseUrlHttp.port();
}
uint16_t NvHTTP::httpsPort()
{
return m_BaseUrlHttps.port();
}
QVector<int>
NvHTTP::parseQuad(QString quad)
{
@@ -67,7 +94,8 @@ NvHTTP::parseQuad(QString quad)
}
QStringList parts = quad.split(".");
for (int i = 0; i < 4; i++)
ret.reserve(parts.length());
for (int i = 0; i < parts.length(); i++)
{
ret.append(parts.at(i).toInt());
}
@@ -97,8 +125,8 @@ NvHTTP::getServerInfo(NvLogLevel logLevel, bool fastFail)
{
QString serverInfo;
// Check if we have a pinned cert for this host yet
if (!m_ServerCert.isNull())
// Check if we have a pinned cert and HTTPS port for this host yet
if (!m_ServerCert.isNull() && httpsPort() != 0)
{
try
{
@@ -133,13 +161,26 @@ NvHTTP::getServerInfo(NvLogLevel logLevel, bool fastFail)
}
else
{
// Only use HTTP prior to pairing
// Only use HTTP prior to pairing or fetching HTTPS port
serverInfo = openConnectionToString(m_BaseUrlHttp,
"serverinfo",
nullptr,
fastFail ? FAST_FAIL_TIMEOUT_MS : REQUEST_TIMEOUT_MS,
logLevel);
verifyResponseStatus(serverInfo);
// Populate the HTTPS port
uint16_t httpsPort = getXmlString(serverInfo, "HttpsPort").toUShort();
if (httpsPort == 0) {
httpsPort = DEFAULT_HTTPS_PORT;
}
setHttpsPort(httpsPort);
// If we just needed to determine the HTTPS port, we'll try again over
// HTTPS now that we have the port number
if (!m_ServerCert.isNull()) {
return getServerInfo(logLevel, fastFail);
}
}
return serverInfo;
@@ -150,7 +191,8 @@ NvHTTP::launchApp(int appId,
PSTREAM_CONFIGURATION streamConfig,
bool sops,
bool localAudio,
int gamepadMask)
int gamepadMask,
QString& rtspSessionUrl)
{
int riKeyId;
@@ -180,12 +222,16 @@ NvHTTP::launchApp(int appId,
"&gcmap="+QString::number(gamepadMask),
LAUNCH_TIMEOUT_MS);
qInfo() << "Launch response:" << response;
// Throws if the request failed
verifyResponseStatus(response);
rtspSessionUrl = getXmlString(response, "sessionUrl0");
}
void
NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig)
NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig, QString& rtspSessionUrl)
{
int riKeyId;
@@ -200,8 +246,12 @@ NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig)
"&surroundAudioInfo="+QString::number(SURROUNDAUDIOINFO_FROM_AUDIO_CONFIGURATION(streamConfig->audioConfiguration)),
RESUME_TIMEOUT_MS);
qInfo() << "Resume response:" << response;
// Throws if the request failed
verifyResponseStatus(response);
rtspSessionUrl = getXmlString(response, "sessionUrl0");
}
void
@@ -213,6 +263,8 @@ NvHTTP::quitApp()
nullptr,
QUIT_TIMEOUT_MS);
qInfo() << "Quit response:" << response;
// Throws if the request failed
verifyResponseStatus(response);
@@ -329,6 +381,8 @@ NvHTTP::verifyResponseStatus(QString xml)
}
}
}
throw GfeHttpResponseException(-1, "Malformed GFE XML (missing root element)");
}
QImage
@@ -391,7 +445,7 @@ void NvHTTP::handleSslErrors(QNetworkReply* reply, const QList<QSslError>& error
return;
}
for (auto error : errors) {
for (const QSslError& error : errors) {
if (m_ServerCert != error.certificate()) {
ignoreErrors = false;
break;
@@ -434,6 +488,9 @@ NvHTTP::openConnection(QUrl baseUrl,
int timeoutMs,
NvLogLevel logLevel)
{
// Port must be set
Q_ASSERT(baseUrl.port(0) != 0);
// Build a URL for the request
QUrl url(baseUrl);
url.setPath("/" + command);
@@ -450,6 +507,11 @@ NvHTTP::openConnection(QUrl baseUrl,
// Add our client certificate
request.setSslConfiguration(IdentityManager::get()->getSslConfig());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Disable HTTP/2 (GFE 3.22 doesn't like it) and Qt 6 enables it by default
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, false);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) && QT_VERSION < QT_VERSION_CHECK(5, 15, 1) && !defined(QT_NO_BEARERMANAGEMENT)
// HACK: Set network accessibility to work around QTBUG-80947 (introduced in Qt 5.14.0 and fixed in Qt 5.15.1)
QT_WARNING_PUSH
@@ -462,10 +524,10 @@ NvHTTP::openConnection(QUrl baseUrl,
// Run the request with a timeout if requested
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), &loop, SLOT(quit()));
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit);
if (timeoutMs) {
QTimer::singleShot(timeoutMs, &loop, SLOT(quit()));
QTimer::singleShot(timeoutMs, &loop, &QEventLoop::quit);
}
if (logLevel >= NvLogLevel::NVLL_VERBOSE) {
qInfo() << "Executing request:" << url.toString();
+21 -6
View File
@@ -2,6 +2,7 @@
#include "identitymanager.h"
#include "nvapp.h"
#include "nvaddress.h"
#include <Limelight.h>
@@ -9,6 +10,8 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
class NvComputer;
class NvDisplayMode
{
public:
@@ -23,6 +26,7 @@ public:
int height;
int refreshRate;
};
Q_DECLARE_TYPEINFO(NvDisplayMode, Q_PRIMITIVE_TYPE);
class GfeHttpResponseException : public std::exception
{
@@ -105,7 +109,9 @@ public:
NVLL_VERBOSE
};
explicit NvHTTP(QString address, QSslCertificate serverCert);
explicit NvHTTP(NvAddress address, uint16_t httpsPort, QSslCertificate serverCert);
explicit NvHTTP(NvComputer* computer);
static
int
@@ -137,9 +143,16 @@ public:
void setServerCert(QSslCertificate serverCert);
void setAddress(QString address);
void setAddress(NvAddress address);
void setHttpsPort(uint16_t port);
QString address();
NvAddress address();
QSslCertificate serverCert();
uint16_t httpPort();
uint16_t httpsPort();
static
QVector<int>
@@ -149,14 +162,16 @@ public:
quitApp();
void
resumeApp(PSTREAM_CONFIGURATION streamConfig);
resumeApp(PSTREAM_CONFIGURATION streamConfig,
QString& rtspSessionUrl);
void
launchApp(int appId,
PSTREAM_CONFIGURATION streamConfig,
bool sops,
bool localAudio,
int gamepadMask);
int gamepadMask,
QString& rtspSessionUrl);
QVector<NvApp>
getAppList();
@@ -181,7 +196,7 @@ private:
int timeoutMs,
NvLogLevel logLevel);
QString m_Address;
NvAddress m_Address;
QNetworkAccessManager m_Nam;
QSslCertificate m_ServerCert;
};
+4 -8
View File
@@ -11,8 +11,8 @@
#define REQUEST_TIMEOUT_MS 5000
NvPairingManager::NvPairingManager(QString address) :
m_Http(address, QSslCertificate())
NvPairingManager::NvPairingManager(NvComputer* computer) :
m_Http(computer)
{
QByteArray cert = IdentityManager::get()->getCertificate();
BIO *bio = BIO_new_mem_buf(cert.data(), -1);
@@ -167,11 +167,7 @@ NvPairingManager::signMessage(const QByteArray& message)
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
THROW_BAD_ALLOC_IF_NULL(ctx);
const EVP_MD *md = EVP_get_digestbyname("SHA256");
THROW_BAD_ALLOC_IF_NULL(md);
EVP_DigestInit_ex(ctx, md, NULL);
EVP_DigestSignInit(ctx, NULL, md, NULL, m_PrivateKey);
EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, m_PrivateKey);
EVP_DigestSignUpdate(ctx, reinterpret_cast<unsigned char*>(const_cast<char*>(message.data())), message.length());
size_t signatureLength = 0;
@@ -215,7 +211,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC
QByteArray salt = generateRandomBytes(16);
QByteArray saltedPin = saltPin(salt, pin);
QByteArray aesKey = QCryptographicHash::hash(saltedPin, hashAlgo).data();
QByteArray aesKey = QCryptographicHash::hash(saltedPin, hashAlgo).constData();
aesKey.truncate(16);
QString getCert = m_Http.openConnectionToString(m_Http.m_BaseUrlHttp,
+1 -1
View File
@@ -17,7 +17,7 @@ public:
ALREADY_IN_PROGRESS
};
explicit NvPairingManager(QString address);
explicit NvPairingManager(NvComputer* computer);
~NvPairingManager();
+63 -8
View File
@@ -14,7 +14,7 @@
SystemProperties::SystemProperties()
{
versionString = QString(VERSION_STR);
hasWindowManager = WMUtils::isRunningWindowManager();
hasDesktopEnvironment = WMUtils::isRunningDesktopEnvironment();
isRunningWayland = WMUtils::isRunningWayland();
isRunningXWayland = isRunningWayland && QGuiApplication::platformName() == "xcb";
QString nativeArch = QSysInfo::currentCpuArchitecture();
@@ -55,12 +55,8 @@ SystemProperties::SystemProperties()
friendlyNativeArchName = nativeArch.toUpper();
}
#ifndef STEAM_LINK
// Assume we can probably launch a browser if we're in a GUI environment
hasBrowser = hasWindowManager;
#else
hasBrowser = false;
#endif
hasBrowser = hasDesktopEnvironment;
#ifdef HAVE_DISCORD
hasDiscordIntegration = true;
@@ -91,7 +87,36 @@ QRect SystemProperties::getNativeResolution(int displayIndex)
return monitorNativeResolutions.value(displayIndex);
}
class QuerySdlVideoThread : public QThread
{
public:
QuerySdlVideoThread(SystemProperties* me) :
QThread(nullptr),
m_Me(me) {}
void run() override
{
m_Me->querySdlVideoInfoInternal();
}
SystemProperties* m_Me;
};
void SystemProperties::querySdlVideoInfo()
{
if (WMUtils::isRunningX11() || WMUtils::isRunningWayland()) {
// Use a separate thread to temporarily initialize SDL
// video to avoid stomping on Qt's X11 and OGL state.
QuerySdlVideoThread thread(this);
thread.start();
thread.wait();
}
else {
querySdlVideoInfoInternal();
}
}
void SystemProperties::querySdlVideoInfoInternal()
{
hasHardwareAcceleration = false;
@@ -103,7 +128,8 @@ void SystemProperties::querySdlVideoInfo()
}
// Update display related attributes (max FPS, native resolution, etc).
refreshDisplays();
// We call the internal variant because we're already in a safe thread context.
refreshDisplaysInternal();
SDL_Window* testWindow = SDL_CreateWindow("", 0, 0, 1280, 720,
SDL_WINDOW_HIDDEN | StreamUtils::getPlatformWindowFlags());
@@ -122,14 +148,43 @@ void SystemProperties::querySdlVideoInfo()
}
}
Session::getDecoderInfo(testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, maximumResolution);
Session::getDecoderInfo(testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, supportsHdr, maximumResolution);
SDL_DestroyWindow(testWindow);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
class RefreshDisplaysThread : public QThread
{
public:
RefreshDisplaysThread(SystemProperties* me) :
QThread(nullptr),
m_Me(me) {}
void run() override
{
m_Me->refreshDisplaysInternal();
}
SystemProperties* m_Me;
};
void SystemProperties::refreshDisplays()
{
if (WMUtils::isRunningX11() || WMUtils::isRunningWayland()) {
// Use a separate thread to temporarily initialize SDL
// video to avoid stomping on Qt's X11 and OGL state.
RefreshDisplaysThread thread(this);
thread.start();
thread.wait();
}
else {
refreshDisplaysInternal();
}
}
void SystemProperties::refreshDisplaysInternal()
{
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+9 -2
View File
@@ -7,6 +7,9 @@ class SystemProperties : public QObject
{
Q_OBJECT
friend class QuerySdlVideoThread;
friend class RefreshDisplaysThread;
public:
SystemProperties();
@@ -16,13 +19,14 @@ public:
Q_PROPERTY(bool isRunningXWayland MEMBER isRunningXWayland CONSTANT)
Q_PROPERTY(bool isWow64 MEMBER isWow64 CONSTANT)
Q_PROPERTY(QString friendlyNativeArchName MEMBER friendlyNativeArchName CONSTANT)
Q_PROPERTY(bool hasWindowManager MEMBER hasWindowManager CONSTANT)
Q_PROPERTY(bool hasDesktopEnvironment MEMBER hasDesktopEnvironment CONSTANT)
Q_PROPERTY(bool hasBrowser MEMBER hasBrowser CONSTANT)
Q_PROPERTY(bool hasDiscordIntegration MEMBER hasDiscordIntegration CONSTANT)
Q_PROPERTY(QString unmappedGamepads MEMBER unmappedGamepads NOTIFY unmappedGamepadsChanged)
Q_PROPERTY(int maximumStreamingFrameRate MEMBER maximumStreamingFrameRate CONSTANT)
Q_PROPERTY(QSize maximumResolution MEMBER maximumResolution CONSTANT)
Q_PROPERTY(QString versionString MEMBER versionString CONSTANT)
Q_PROPERTY(bool supportsHdr MEMBER supportsHdr CONSTANT)
Q_INVOKABLE void refreshDisplays();
Q_INVOKABLE QRect getDesktopResolution(int displayIndex);
@@ -33,6 +37,8 @@ signals:
private:
void querySdlVideoInfo();
void querySdlVideoInfoInternal();
void refreshDisplaysInternal();
bool hasHardwareAcceleration;
bool rendererAlwaysFullScreen;
@@ -40,7 +46,7 @@ private:
bool isRunningXWayland;
bool isWow64;
QString friendlyNativeArchName;
bool hasWindowManager;
bool hasDesktopEnvironment;
bool hasBrowser;
bool hasDiscordIntegration;
QString unmappedGamepads;
@@ -49,5 +55,6 @@ private:
QList<QRect> monitorDesktopResolutions;
QList<QRect> monitorNativeResolutions;
QString versionString;
bool supportsHdr;
};
+18 -11
View File
@@ -52,7 +52,7 @@ public:
void handleUnknownOptions()
{
if (unknownOptionNames().length()) {
if (!unknownOptionNames().isEmpty()) {
showError(QString("Unknown options: %1").arg(unknownOptionNames().join(", ")));
}
}
@@ -264,6 +264,11 @@ StreamCommandLineParser::StreamCommandLineParser()
{"software", StreamingPreferences::VDS_FORCE_SOFTWARE},
{"hardware", StreamingPreferences::VDS_FORCE_HARDWARE},
};
m_CaptureSysKeysModeMap = {
{"never", StreamingPreferences::CSK_OFF},
{"fullscreen", StreamingPreferences::CSK_FULLSCREEN},
{"always", StreamingPreferences::CSK_ALWAYS},
};
}
StreamCommandLineParser::~StreamCommandLineParser()
@@ -307,7 +312,8 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
parser.addToggleOption("background-gamepad", "background gamepad input");
parser.addToggleOption("reverse-scroll-direction", "inverted scroll direction");
parser.addToggleOption("swap-gamepad-buttons", "swap A/B and X/Y gamepad buttons (Nintendo-style)");
parser.addToggleOption("capture-system-keys", "capture system key combos in fullscreen mode");
parser.addToggleOption("keep-awake", "prevent display sleep while streaming");
parser.addChoiceOption("capture-system-keys", "capture system key combos", m_CaptureSysKeysModeMap.keys());
parser.addChoiceOption("video-codec", "video codec", m_VideoCodecMap.keys());
parser.addChoiceOption("video-decoder", "video decoder", m_VideoDecoderMap.keys());
@@ -320,25 +326,21 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
// Resolve display's width and height
QRegularExpression resolutionRexExp("^(720|1080|1440|4K|resolution)$");
QStringList resoOptions = parser.optionNames().filter(resolutionRexExp);
bool displaySet = resoOptions.length();
bool displaySet = !resoOptions.isEmpty();
if (displaySet) {
QString name = resoOptions.last();
if (name == "720") {
preferences->width = 1280;
preferences->height = 720;
displaySet = true;
} else if (name == "1080") {
preferences->width = 1920;
preferences->height = 1080;
displaySet = true;
} else if (name == "1440") {
preferences->width = 2560;
preferences->height = 1440;
displaySet = true;
} else if (name == "4K") {
preferences->width = 3840;
preferences->height = 2160;
displaySet = true;
} else if (name == "resolution") {
auto resolution = parser.getResolutionOptionValue(name);
preferences->width = resolution.first;
@@ -349,8 +351,8 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
// Resolve --fps option
if (parser.isSet("fps")) {
preferences->fps = parser.getIntOption("fps");
if (!inRange(preferences->fps, 30, 120)) {
parser.showError("FPS must be in range: 30 - 120");
if (!inRange(preferences->fps, 30, 240)) {
parser.showError("FPS must be in range: 30 - 240");
}
}
@@ -422,8 +424,13 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference
// Resolve --swap-gamepad-buttons and --no-swap-gamepad-buttons options
preferences->swapFaceButtons = parser.getToggleOptionValue("swap-gamepad-buttons", preferences->swapFaceButtons);
// Resolve --capture-system-keys and --no-capture-system-keys options
preferences->captureSysKeys = parser.getToggleOptionValue("capture-system-keys", preferences->captureSysKeys);
// Resolve --keep-awake and --no-keep-awake options
preferences->keepAwake = parser.getToggleOptionValue("keep-awake", preferences->keepAwake);
// Resolve --capture-system-keys option
if (parser.isSet("capture-system-keys")) {
preferences->captureSysKeysMode = mapValue(m_CaptureSysKeysModeMap, parser.getChoiceOptionValue("capture-system-keys"));
}
// Resolve --video-codec option
if (parser.isSet("video-codec")) {
+1
View File
@@ -53,4 +53,5 @@ private:
QMap<QString, StreamingPreferences::AudioConfig> m_AudioConfigMap;
QMap<QString, StreamingPreferences::VideoCodecConfig> m_VideoCodecMap;
QMap<QString, StreamingPreferences::VideoDecoderSelection> m_VideoDecoderMap;
QMap<QString, StreamingPreferences::CaptureSysKeysMode> m_CaptureSysKeysModeMap;
};
@@ -15,7 +15,7 @@
<li>Hardware accelerated video decoding with VAAPI, VDPAU, and NVDEC support</li>
<li>7.1 surround sound audio support</li>
<li>Support for both pointer capture (for games) and direct mouse control (for remote desktop)</li>
<li>Support for passing system-wide keyboard shortcuts like Alt+Tab to the host in fullscreen mode on X11</li>
<li>Support for passing system-wide keyboard shortcuts like Alt+Tab to the host</li>
<li>Direct touchscreen mouse control</li>
<li>HEVC support for better video compression efficiency</li>
<li>Gamepad support with force feedback for up to 4 players</li>
@@ -36,6 +36,113 @@
</screenshots>
<releases>
<release version="4.0.0" date="2022-04-02">
<description>
<p>New features:</p>
<ul>
<li>Added a new key combo for locking the mouse cursor to the window (Ctrl+Alt+Shift+L)</li>
<li>Added an option to avoid keeping the client display awake while streaming</li>
</ul>
<p>Behavior Changes:</p>
<ul>
<li>HDR streaming is now a separate option rather than being part of the Video Codec override dropdown</li>
<li>HDR streaming is no longer restricted to apps that are certified by NVIDIA as compatible with GameStream HDR. Some newer games may require an HDR display or EDID emulator dongle connected to your host PC for HDR options to be available.</li>
</ul>
<p>Bugfixes:</p>
<ul>
<li>Fixed loss of all audio if the active audio device is unplugged while streaming</li>
<li>Fixed the GUI being unresponsive after manually quitting when connection to the host is lost</li>
<li>Fixed a rare crash if a controller disconnects right as rumble is starting</li>
<li>Fixed text rendering on the overlay UI when using SDL_ttf 2.0.18 on Linux</li>
<li>Updated included gamepad mappings</li>
<li>Updated community-contributed translations from Weblate</li>
</ul>
</description>
</release>
<release version="3.2.0" date="2022-01-18">
<description>
<p>New features:</p>
<ul>
<li>Reduced CPU usage while streaming</li>
<li>Non-ASCII characters are now supported when pasting clipboard data to the host</li>
<li>Added support for zero-copy NVDEC rendering for Nvidia Wayland systems</li>
<li>Significantly improved performance with asynchronous decoders like V4L2M2M on Linux</li>
<li>Added support for color compression planes on newer Intel systems when using VAAPI decoding</li>
<li>Added support for copy-back rendering in non-default pixel formats (like the Raspberry Pi SAND format)</li>
</ul>
<p>Bugfixes:</p>
<ul>
<li>Fixed unexpected GUI input after using the gamepad quit combo</li>
<li>Updated included gamepad mappings</li>
<li>Updated community-contributed translations from Weblate</li>
</ul>
</description>
</release>
<release version="3.1.4" date="2021-06-25">
<description>
<p>Changes:</p>
<ul>
<li>Added network latency statistics to the performance overlay</li>
<li>Improved audio quality on unreliable connections (requires GeForce Experience 3.19 or later)</li>
<li>Reduced video frame drops on unreliable connections (requires GeForce Experience 3.22 or later)</li>
<li>Updated community-contributed translations from Weblate</li>
</ul>
</description>
</release>
<release version="3.1.3" date="2021-05-07">
<description>
<p>Changes:</p>
<ul>
<li>Fixed an issue that could cause excessive audio latency on some connections</li>
<li>Updated community-contributed translations from Weblate</li>
</ul>
</description>
</release>
<release version="3.1.2" date="2021-05-03">
<description>
<p>Changes:</p>
<ul>
<li>Improved connection reliability and performance with GeForce Experience 3.22</li>
<li>Added support for audio encryption with GeForce Experience 3.22</li>
<li>Added compatibility update checks for future versions of GeForce Experience</li>
<li>Fixed keyboard capture on X11</li>
<li>Updated community-contributed translations from Weblate</li>
</ul>
</description>
</release>
<release version="3.1.1" date="2021-04-09">
<description>
<p>Changes:</p>
<ul>
<li>Added support for streaming from GeForce Experience 3.22</li>
<li>Added support for AMF-encoded HEVC streams from servers like Sunshine and OpenStream</li>
<li>Added new community-contributed translations from Weblate</li>
<li>Fixed KMSDRM rendering with buffer modifiers on embedded devices</li>
</ul>
</description>
</release>
<release version="3.1.0" date="2021-03-14">
<description>
<p>New features:</p>
<ul>
<li>System keyboard shortcuts (Alt+Tab, Super key, Ctrl+Shift+Esc, etc.) can now be (optionally) captured in windowed mode</li>
<li>System keyboard shortcuts can now be captured under Wayland</li>
<li>Added support for typing the client's clipboard text on the host by pressing Ctrl+Alt+Shift+V</li>
<li>Added Ctrl+Alt+Shift+D key combo to minimize the streaming window</li>
<li>Added Ctrl+Alt+Shift+C key combo to show the local cursor while streaming in remote desktop mouse mode</li>
<li>Added Select+L1+R1+X gamepad button combo to toggle performance overlay</li>
<li>Added translations for Simplified Chinese and German</li>
<li>Added a language selector on the settings page</li>
</ul>
<p>Bugfixes:</p>
<ul>
<li>Improved performance of loading the app grid</li>
<li>Fixed video scaling in High DPI mode on Wayland</li>
<li>Fixed window icons on Wayland</li>
<li>Fixed number pad enter key functionality in the UI</li>
</ul>
</description>
</release>
<release version="3.0.0" date="2021-01-17">
<description>
<p>New features:</p>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 13 KiB

+1 -11
View File
@@ -5,19 +5,9 @@
# pairing data will be lost each reboot.
HOME=/usr/local/moonlight
# For a seamless transition across the Qt 5.9 -> Qt 5.14 boundary,
# we bundle binaries built with both Qt 5.9 and Qt 5.14 and pick
# the correct one at runtime.
if [ -d "/usr/local/Qt-5.14.1" ]; then
BIN="moonlight"
else
BIN="moonlight59"
fi
# Renice PE_Single_CPU which seems to host A/V stuff
renice -10 -p $(pidof PE_Single_CPU)
# Renice Moonlight itself to avoid preemption by background tasks
# Write output to a logfile in /tmp
echo Launching $BIN
exec nice -n -10 ./bin/$BIN > /tmp/moonlight.log
exec nice -n -10 ./bin/moonlight > /tmp/moonlight.log
+136 -100
View File
@@ -73,6 +73,9 @@ CenteredGridView {
width: 220; height: 287;
grid: appGrid
property alias appContextMenu: appContextMenuLoader.item
property alias appNameText: appNameTextLoader.item
// Dim the app if it's hidden
opacity: model.hidden ? 0.4 : 1.0
@@ -85,9 +88,14 @@ CenteredGridView {
source: model.boxart
onSourceSizeChanged: {
if ((sourceSize.width == 130 && sourceSize.height == 180) || // GFE 2.0 placeholder image
(sourceSize.width == 628 && sourceSize.height == 888) || // GFE 3.0 placeholder image
(sourceSize.width == 200 && sourceSize.height == 266)) // Our no_app_image.png
// Nearly all of Nvidia's official box art does not match the dimensions of placeholder
// images, however the one known exeception is Overcooked. Therefore, we only execute
// the image size checks if this is not an app collector game. We know the officially
// supported games all have box art, so this check is not required.
if (!model.isAppCollectorGame &&
((sourceSize.width == 130 && sourceSize.height == 180) || // GFE 2.0 placeholder image
(sourceSize.width == 628 && sourceSize.height == 888) || // GFE 3.0 placeholder image
(sourceSize.width == 200 && sourceSize.height == 266))) // Our no_app_image.png
{
isPlaceholder = true
}
@@ -104,81 +112,94 @@ CenteredGridView {
ToolTip.text: model.name
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: (parent.hovered || parent.highlighted) && (!appNameText.visible || appNameText.truncated)
ToolTip.visible: (parent.hovered || parent.highlighted) && (!appNameText || appNameText.truncated)
}
ToolButton {
id: resumeButton
anchors.horizontalCenterOffset: appIcon.isPlaceholder ? -47 : 0
anchors.verticalCenterOffset: appIcon.isPlaceholder ? -75 : -60
anchors.centerIn: appIcon
visible: model.running
implicitWidth: 125
implicitHeight: 125
Loader {
active: model.running
asynchronous: true
anchors.fill: appIcon
Image {
source: "qrc:/res/baseline-play_circle_filled_white-48px.svg"
anchors.centerIn: parent
sourceSize {
width: 75
height: 75
sourceComponent: Item {
ToolButton {
anchors.horizontalCenterOffset: appIcon.isPlaceholder ? -47 : 0
anchors.verticalCenterOffset: appIcon.isPlaceholder ? -75 : -60
anchors.centerIn: parent
implicitWidth: 125
implicitHeight: 125
Image {
source: "qrc:/res/baseline-play_circle_filled_white-48px.svg"
anchors.centerIn: parent
sourceSize {
width: 75
height: 75
}
}
onClicked: {
launchOrResumeSelectedApp(true)
}
ToolTip.text: qsTr("Resume Game")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
ToolButton {
anchors.horizontalCenterOffset: appIcon.isPlaceholder ? 47 : 0
anchors.verticalCenterOffset: appIcon.isPlaceholder ? -75 : 60
anchors.centerIn: parent
implicitWidth: 125
implicitHeight: 125
Image {
source: "qrc:/res/baseline-cancel-24px.svg"
anchors.centerIn: parent
sourceSize {
width: 75
height: 75
}
}
onClicked: {
doQuitGame()
}
ToolTip.text: qsTr("Quit Game")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
}
onClicked: {
launchOrResumeSelectedApp(true)
}
ToolTip.text: qsTr("Resume Game")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
ToolButton {
id: quitButton
anchors.horizontalCenterOffset: appIcon.isPlaceholder ? 47 : 0
anchors.verticalCenterOffset: appIcon.isPlaceholder ? -75 : 60
anchors.centerIn: appIcon
visible: model.running
implicitWidth: 125
implicitHeight: 125
Loader {
id: appNameTextLoader
active: appIcon.isPlaceholder
Image {
source: "qrc:/res/baseline-cancel-24px.svg"
anchors.centerIn: parent
sourceSize {
width: 75
height: 75
}
}
// This loader is not asynchronous to avoid noticeable differences
// in the time in which the text loads for each game.
onClicked: {
doQuitGame()
}
ToolTip.text: qsTr("Quit Game")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
Label {
id: appNameText
visible: appIcon.isPlaceholder
text: model.name
width: appIcon.width
height: model.running ? 175 : appIcon.height
leftPadding: 20
rightPadding: 20
anchors.left: appIcon.left
anchors.right: appIcon.right
anchors.bottom: appIcon.bottom
font.pointSize: 22
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
elide: Text.ElideRight
sourceComponent: Label {
id: appNameText
text: model.name
font.pointSize: 22
leftPadding: 20
rightPadding: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
elide: Text.ElideRight
}
}
function launchOrResumeSelectedApp(quitExistingApp)
@@ -245,6 +266,17 @@ CenteredGridView {
}
}
Keys.onEnterPressed: {
// Open the app context menu if activated via the gamepad or keyboard
// for running games. If the game isn't running, the above onClicked
// method will handle the launch.
if (model.running) {
// This will be keyboard/gamepad driven so use
// open() instead of popup()
appContextMenu.open()
}
}
Keys.onMenuPressed: {
// This will be keyboard/gamepad driven so use open() instead of popup()
appContextMenu.open()
@@ -256,44 +288,48 @@ CenteredGridView {
quitAppDialog.open()
}
NavigableMenu {
id: appContextMenu
NavigableMenuItem {
parentMenu: appContextMenu
text: model.running ? qsTr("Resume Game") : qsTr("Launch Game")
onTriggered: launchOrResumeSelectedApp(true)
}
NavigableMenuItem {
parentMenu: appContextMenu
text: qsTr("Quit Game")
onTriggered: doQuitGame()
visible: model.running
}
NavigableMenuItem {
parentMenu: appContextMenu
checkable: true
checked: model.directLaunch
text: qsTr("Direct Launch")
onTriggered: appModel.setAppDirectLaunch(model.index, !model.directLaunch)
enabled: !model.hidden
Loader {
id: appContextMenuLoader
asynchronous: true
sourceComponent: NavigableMenu {
id: appContextMenu
NavigableMenuItem {
parentMenu: appContextMenu
text: model.running ? qsTr("Resume Game") : qsTr("Launch Game")
onTriggered: launchOrResumeSelectedApp(true)
}
NavigableMenuItem {
parentMenu: appContextMenu
text: qsTr("Quit Game")
onTriggered: doQuitGame()
visible: model.running
}
NavigableMenuItem {
parentMenu: appContextMenu
checkable: true
checked: model.directLaunch
text: qsTr("Direct Launch")
onTriggered: appModel.setAppDirectLaunch(model.index, !model.directLaunch)
enabled: !model.hidden
ToolTip.text: qsTr("Launch this app immediately when the host is selected, bypassing the app selection grid.")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
NavigableMenuItem {
parentMenu: appContextMenu
checkable: true
checked: model.hidden
text: qsTr("Hide Game")
onTriggered: appModel.setAppHidden(model.index, !model.hidden)
enabled: model.hidden || (!model.running && !model.directLaunch)
ToolTip.text: qsTr("Launch this app immediately when the host is selected, bypassing the app selection grid.")
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
}
NavigableMenuItem {
parentMenu: appContextMenu
checkable: true
checked: model.hidden
text: qsTr("Hide Game")
onTriggered: appModel.setAppHidden(model.index, !model.hidden)
enabled: model.hidden || (!model.running && !model.directLaunch)
ToolTip.text: qsTr("Hide this game from the app grid. To access hidden games, right-click on the host and choose %1.").arg(qsTr("View All Apps"))
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
ToolTip.text: qsTr("Hide this game from the app grid. To access hidden games, right-click on the host and choose %1.").arg(qsTr("View All Apps"))
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
}
}
}
}
+3
View File
@@ -21,4 +21,7 @@ ItemDelegate {
Keys.onReturnPressed: {
clicked()
}
Keys.onEnterPressed: {
clicked()
}
}
+4
View File
@@ -22,6 +22,10 @@ MenuItem {
triggered()
}
Keys.onEnterPressed: {
triggered()
}
Keys.onEscapePressed: {
parentMenu.close()
}
+4
View File
@@ -56,6 +56,10 @@ NavigableDialog {
accept()
}
Keys.onEnterPressed: {
accept()
}
Keys.onEscapePressed: {
reject()
}
+6 -2
View File
@@ -1,5 +1,6 @@
import QtQuick 2.0
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
ToolButton {
property string iconSource
@@ -20,13 +21,16 @@ ToolButton {
// This determines the size of the Material highlight. We increase it
// from the default because we use larger than normal icons for TV readability.
background.width: (parent.height - parent.anchors.bottomMargin - parent.anchors.topMargin) * 0.60
background.height: (parent.height - parent.anchors.bottomMargin - parent.anchors.topMargin) * 0.60
Layout.preferredHeight: parent.height
Keys.onReturnPressed: {
clicked()
}
Keys.onEnterPressed: {
clicked()
}
Keys.onRightPressed: {
nextItemInFocusChain(true).forceActiveFocus(Qt.TabFocus)
}
+60 -45
View File
@@ -113,6 +113,8 @@ CenteredGridView {
width: 300; height: 320;
grid: pcGrid
property alias pcContextMenu : pcContextMenuLoader.item
Image {
id: pcIcon
anchors.horizontalCenter: parent.horizontalCenter
@@ -160,61 +162,70 @@ CenteredGridView {
elide: Text.ElideRight
}
NavigableMenu {
id: pcContextMenu
MenuItem {
text: qsTr("PC Status: %1").arg(model.online ? qsTr("Online") : qsTr("Offline"))
font.bold: true
enabled: false
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("View All Apps")
onTriggered: {
var component = Qt.createComponent("AppView.qml")
var appView = component.createObject(stackView, {"computerIndex": index, "objectName": model.name, "showHiddenGames": true})
stackView.push(appView)
Loader {
id: pcContextMenuLoader
asynchronous: true
sourceComponent: NavigableMenu {
id: pcContextMenu
MenuItem {
text: qsTr("PC Status: %1").arg(model.online ? qsTr("Online") : qsTr("Offline"))
font.bold: true
enabled: false
}
visible: model.online && model.paired
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Wake PC")
onTriggered: computerModel.wakeComputer(index)
visible: !model.online && model.wakeable
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Test Network")
onTriggered: {
computerModel.testConnectionForComputer(index)
testConnectionDialog.open()
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("View All Apps")
onTriggered: {
var component = Qt.createComponent("AppView.qml")
var appView = component.createObject(stackView, {"computerIndex": index, "objectName": model.name, "showHiddenGames": true})
stackView.push(appView)
}
visible: model.online && model.paired
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Wake PC")
onTriggered: computerModel.wakeComputer(index)
visible: !model.online && model.wakeable
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Test Network")
onTriggered: {
computerModel.testConnectionForComputer(index)
testConnectionDialog.open()
}
}
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Rename PC")
onTriggered: {
renamePcDialog.pcIndex = index
renamePcDialog.originalName = model.name
renamePcDialog.open()
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Rename PC")
onTriggered: {
renamePcDialog.pcIndex = index
renamePcDialog.originalName = model.name
renamePcDialog.open()
}
}
}
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Delete PC")
onTriggered: {
deletePcDialog.pcIndex = index
// get confirmation first, actual closing is called from the dialog
deletePcDialog.open()
NavigableMenuItem {
parentMenu: pcContextMenu
text: qsTr("Delete PC")
onTriggered: {
deletePcDialog.pcIndex = index
// get confirmation first, actual closing is called from the dialog
deletePcDialog.open()
}
}
}
}
onClicked: {
if (model.online) {
if (model.paired) {
if (!model.serverSupported) {
errorDialog.text = qsTr("The version of GeForce Experience on %1 is not supported by this build of Moonlight. You must update Moonlight to stream from %1.").arg(model.name)
errorDialog.helpText = ""
errorDialog.open()
}
else if (model.paired) {
// go to game view
var component = Qt.createComponent("AppView.qml")
var appView = component.createObject(stackView, {"computerIndex": index, "objectName": model.name})
@@ -379,6 +390,10 @@ CenteredGridView {
Keys.onReturnPressed: {
renamePcDialog.accept()
}
Keys.onEnterPressed: {
renamePcDialog.accept()
}
}
}
}
+329 -55
View File
@@ -345,7 +345,7 @@ Flickable {
maximumLength: 5
inputMethodHints: Qt.ImhDigitsOnly
placeholderText: resolutionListModel.get(resolutionComboBox.currentIndex).video_width
validator: IntValidator{bottom:128; top:8192}
validator: IntValidator{bottom:256; top:8192}
focus: true
onTextChanged: {
@@ -358,6 +358,10 @@ Flickable {
Keys.onReturnPressed: {
customResolutionDialog.accept()
}
Keys.onEnterPressed: {
customResolutionDialog.accept()
}
}
Label {
@@ -370,7 +374,7 @@ Flickable {
maximumLength: 5
inputMethodHints: Qt.ImhDigitsOnly
placeholderText: resolutionListModel.get(resolutionComboBox.currentIndex).video_height
validator: IntValidator{bottom:128; top:8192}
validator: IntValidator{bottom:256; top:8192}
onTextChanged: {
// standardButton() was added in Qt 5.10, so we must check for it first
@@ -382,6 +386,10 @@ Flickable {
Keys.onReturnPressed: {
customResolutionDialog.accept()
}
Keys.onEnterPressed: {
customResolutionDialog.accept()
}
}
}
}
@@ -519,12 +527,17 @@ Flickable {
text: qsTr("Display mode")
font.pointSize: 12
wrapMode: Text.Wrap
visible: SystemProperties.hasWindowManager
visible: SystemProperties.hasDesktopEnvironment
}
AutoResizingComboBox {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
if (!visible) {
// Do nothing if the control won't even be visible
return
}
// Set the recommended option based on the OS
for (var i = 0; i < windowModeListModel.count; i++) {
var thisWm = windowModeListModel.get(i).val;
@@ -537,22 +550,20 @@ Flickable {
currentIndex = 0
if (SystemProperties.hasWindowManager && !SystemProperties.rendererAlwaysFullScreen) {
var savedWm = StreamingPreferences.windowMode
for (var i = 0; i < windowModeListModel.count; i++) {
var thisWm = windowModeListModel.get(i).val;
if (savedWm === thisWm) {
currentIndex = i
break
}
}
var savedWm = StreamingPreferences.windowMode
for (var i = 0; i < windowModeListModel.count; i++) {
var thisWm = windowModeListModel.get(i).val;
if (savedWm === thisWm) {
currentIndex = i
break
}
}
activated(currentIndex)
}
id: windowModeComboBox
visible: SystemProperties.hasWindowManager
visible: SystemProperties.hasDesktopEnvironment
enabled: !SystemProperties.rendererAlwaysFullScreen
hoverEnabled: true
textRole: "text"
@@ -697,7 +708,7 @@ Flickable {
width: parent.width
text: qsTr("Mute audio stream when Moonlight is not the active window")
font.pointSize: 12
visible: SystemProperties.hasWindowManager
visible: SystemProperties.hasDesktopEnvironment
checked: StreamingPreferences.muteOnFocusLoss
onCheckedChanged: {
StreamingPreferences.muteOnFocusLoss = checked
@@ -724,37 +735,175 @@ Flickable {
Label {
width: parent.width
id: uiDisplayModeTitle
text: qsTr("GUI display mode")
id: languageTitle
text: qsTr("Language")
font.pointSize: 12
wrapMode: Text.Wrap
visible: SystemProperties.hasWindowManager
}
AutoResizingComboBox {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
if (SystemProperties.hasWindowManager) {
var saved_uidisplaymode = StreamingPreferences.uiDisplayMode
currentIndex = 0
for (var i = 0; i < uiDisplayModeListModel.count; i++) {
var el_uidisplaymode = uiDisplayModeListModel.get(i).val;
if (saved_uidisplaymode === el_uidisplaymode) {
currentIndex = i
break
}
var saved_language = StreamingPreferences.language
currentIndex = 0
for (var i = 0; i < languageListModel.count; i++) {
var el_language = languageListModel.get(i).val;
if (saved_language === el_language) {
currentIndex = i
break
}
}
else {
// Full-screen is always selected when there is no window manager
currentIndex = 2
activated(currentIndex)
}
id: languageComboBox
textRole: "text"
model: ListModel {
id: languageListModel
ListElement {
text: qsTr("Automatic")
val: StreamingPreferences.LANG_AUTO
}
ListElement {
text: "Deutsch" // German
val: StreamingPreferences.LANG_DE
}
ListElement {
text: "English"
val: StreamingPreferences.LANG_EN
}
ListElement {
text: "Français" // French
val: StreamingPreferences.LANG_FR
}
ListElement {
text: "简体中文" // Simplified Chinese
val: StreamingPreferences.LANG_ZH_CN
}
ListElement {
text: "Norwegian Bokmål"
val: StreamingPreferences.LANG_NB_NO
}
ListElement {
text: "русский" // Russian
val: StreamingPreferences.LANG_RU
}
ListElement {
text: "Español" // Spanish
val: StreamingPreferences.LANG_ES
}
ListElement {
text: "日本語" // Japanese
val: StreamingPreferences.LANG_JA
}
ListElement {
text: "Tiếng Việt" // Vietnamese
val: StreamingPreferences.LANG_VI
}
ListElement {
text: "ภาษาไทย" // Thai
val: StreamingPreferences.LANG_TH
}
ListElement {
text: "한국어" // Korean
val: StreamingPreferences.LANG_KO
}
/* ListElement {
text: "Magyar" // Hungarian
val: StreamingPreferences.LANG_HU
} */
ListElement {
text: "Nederlands" // Dutch
val: StreamingPreferences.LANG_NL
}
ListElement {
text: "Svenska" // Swedish
val: StreamingPreferences.LANG_SV
}
/* ListElement {
text: "Türkçe" // Turkish
val: StreamingPreferences.LANG_TR
} */
/* ListElement {
text: "Українська" // Ukrainian
val: StreamingPreferences.LANG_UK
} */
ListElement {
text: "繁体字" // Traditional Chinese
val: StreamingPreferences.LANG_ZH_HANT
}
ListElement {
text: "Português" // Portuguese
val: StreamingPreferences.LANG_PT
}
/* ListElement {
text: "Português do Brasil" // Brazilian Portuguese
val: StreamingPreferences.LANG_PT_BR
} */
ListElement {
text: "Ελληνικά" // Greek
val: StreamingPreferences.LANG_EL
}
ListElement {
text: "Italiano" // Italian
val: StreamingPreferences.LANG_IT
}
/* ListElement {
text: "हिन्दी, हिंदी" // Hindi
val: StreamingPreferences.LANG_HI
} */
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
// Retranslating is expensive, so only do it if the language actually changed
var new_language = languageListModel.get(currentIndex).val
if (StreamingPreferences.language !== new_language) {
StreamingPreferences.language = languageListModel.get(currentIndex).val
if (!StreamingPreferences.retranslate()) {
ToolTip.show(qsTr("You must restart Moonlight for this change to take effect"), 5000)
}
else {
// Force the back operation to pop any AppView pages that exist.
// The AppView stops working after retranslate() for some reason.
window.clearOnBack = true
}
}
}
}
Label {
width: parent.width
id: uiDisplayModeTitle
text: qsTr("GUI display mode")
font.pointSize: 12
wrapMode: Text.Wrap
visible: SystemProperties.hasDesktopEnvironment
}
AutoResizingComboBox {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
if (!visible) {
// Do nothing if the control won't even be visible
return
}
var saved_uidisplaymode = StreamingPreferences.uiDisplayMode
currentIndex = 0
for (var i = 0; i < uiDisplayModeListModel.count; i++) {
var el_uidisplaymode = uiDisplayModeListModel.get(i).val;
if (saved_uidisplaymode === el_uidisplaymode) {
currentIndex = i
break
}
}
activated(currentIndex)
}
id: uiDisplayModeComboBox
visible: SystemProperties.hasWindowManager
visible: SystemProperties.hasDesktopEnvironment
textRole: "text"
model: ListModel {
id: uiDisplayModeListModel
@@ -804,6 +953,22 @@ Flickable {
ToolTip.visible: hovered
ToolTip.text: qsTr("Updates your Discord status to display the name of the game you're streaming.")
}
CheckBox {
id: keepAwakeCheck
width: parent.width
text: qsTr("Keep the display awake while streaming")
font.pointSize: 12
checked: StreamingPreferences.keepAwake
onCheckedChanged: {
StreamingPreferences.keepAwake = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
ToolTip.text: qsTr("Prevents the screensaver from starting or the display from going to sleep while streaming.")
}
}
}
}
@@ -833,7 +998,6 @@ Flickable {
width: parent.width
text: qsTr("Optimize mouse for remote desktop instead of games")
font.pointSize: 12
visible: SystemProperties.hasWindowManager
checked: StreamingPreferences.absoluteMouseMode
onCheckedChanged: {
StreamingPreferences.absoluteMouseMode = checked
@@ -847,25 +1011,79 @@ Flickable {
qsTr("NOTE: Due to a bug in GeForce Experience, this option may not work properly if your host PC has multiple monitors.")
}
CheckBox {
id: captureSysKeysCheck
hoverEnabled: true
Row {
spacing: 5
width: parent.width
text: qsTr("Capture system keyboard shortcuts ") +
(!SystemProperties.isRunningWayland ? qsTr("while streaming in fullscreen") :
qsTr("(unsupported on Wayland)"))
font.pointSize: 12
enabled: SystemProperties.hasWindowManager && !SystemProperties.isRunningWayland
checked: (StreamingPreferences.captureSysKeys || !SystemProperties.hasWindowManager) && !SystemProperties.isRunningWayland
onCheckedChanged: {
StreamingPreferences.captureSysKeys = checked
CheckBox {
id: captureSysKeysCheck
hoverEnabled: true
text: qsTr("Capture system keyboard shortcuts")
font.pointSize: 12
enabled: SystemProperties.hasDesktopEnvironment
checked: StreamingPreferences.captureSysKeysMode !== StreamingPreferences.CSK_OFF || !SystemProperties.hasDesktopEnvironment
ToolTip.delay: 1000
ToolTip.timeout: 10000
ToolTip.visible: hovered
ToolTip.text: qsTr("This enables the capture of system-wide keyboard shortcuts like Alt+Tab that would normally be handled by the client OS while streaming.") + "\n\n" +
qsTr("NOTE: Certain keyboard shortcuts like Ctrl+Alt+Del on Windows cannot be intercepted by any application, including Moonlight.")
}
ToolTip.delay: 1000
ToolTip.timeout: 10000
ToolTip.visible: hovered
ToolTip.text: qsTr("This enables the capture of system-wide keyboard shortcuts like Alt+Tab that would normally be handled by the client OS while streaming in fullscreen.") + "\n\n" +
qsTr("NOTE: Certain keyboard shortcuts like Ctrl+Alt+Del on Windows cannot be intercepted by any application, including Moonlight.")
AutoResizingComboBox {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
if (!visible) {
// Do nothing if the control won't even be visible
return
}
var saved_syskeysmode = StreamingPreferences.captureSysKeysMode
currentIndex = 0
for (var i = 0; i < captureSysKeysModeListModel.count; i++) {
var el_syskeysmode = captureSysKeysModeListModel.get(i).val;
if (saved_syskeysmode === el_syskeysmode) {
currentIndex = i
break
}
}
activated(currentIndex)
}
enabled: captureSysKeysCheck.checked && captureSysKeysCheck.enabled
textRole: "text"
model: ListModel {
id: captureSysKeysModeListModel
ListElement {
text: qsTr("in fullscreen")
val: StreamingPreferences.CSK_FULLSCREEN
}
ListElement {
text: qsTr("always")
val: StreamingPreferences.CSK_ALWAYS
}
}
function updatePref() {
if (!enabled) {
StreamingPreferences.captureSysKeysMode = StreamingPreferences.CSK_OFF
}
else {
StreamingPreferences.captureSysKeysMode = captureSysKeysModeListModel.get(currentIndex).val
}
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated: {
updatePref()
}
// This handles transition of the checkbox state
onEnabledChanged: {
updatePref()
}
}
}
CheckBox {
@@ -980,7 +1198,7 @@ Flickable {
width: parent.width
text: qsTr("Process gamepad input when Moonlight is in the background")
font.pointSize: 12
visible: SystemProperties.hasWindowManager
visible: SystemProperties.hasDesktopEnvironment
checked: StreamingPreferences.backgroundGamepad
onCheckedChanged: {
StreamingPreferences.backgroundGamepad = checked
@@ -1070,6 +1288,7 @@ Flickable {
id: decoderComboBox
textRole: "text"
enabled: !enableHdr.checked
model: ListModel {
id: decoderListModel
ListElement {
@@ -1086,9 +1305,26 @@ Flickable {
}
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val
onActivated: {
if (enabled) {
StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val
}
}
// This handles the state of the enableHdr checkbox changing
onEnabledChanged: {
if (enabled) {
StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val
}
else {
StreamingPreferences.videoDecoderSelection = StreamingPreferences.VDS_AUTO
}
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered && !enabled
ToolTip.text: qsTr("Enabling HDR overrides manual decoder selections.")
}
Label {
@@ -1103,7 +1339,11 @@ Flickable {
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
var saved_vcc = StreamingPreferences.videoCodecConfig
// Default to Automatic (relevant if HDR is enabled,
// where we will match none of the codecs in the list)
currentIndex = 0
for(var i = 0; i < codecListModel.count; i++) {
var el_vcc = codecListModel.get(i).val;
if (saved_vcc === el_vcc) {
@@ -1111,11 +1351,13 @@ Flickable {
break
}
}
activated(currentIndex)
}
id: codecComboBox
textRole: "text"
enabled: !enableHdr.checked
model: ListModel {
id: codecListModel
ListElement {
@@ -1130,15 +1372,47 @@ Flickable {
text: qsTr("HEVC (H.265)")
val: StreamingPreferences.VCC_FORCE_HEVC
}
/*ListElement {
text: qsTr("HEVC HDR (Experimental)")
val: StreamingPreferences.VCC_FORCE_HEVC_HDR
}*/
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
StreamingPreferences.videoCodecConfig = codecListModel.get(currentIndex).val
if (enabled) {
StreamingPreferences.videoCodecConfig = codecListModel.get(currentIndex).val
}
}
// This handles the state of the enableHdr checkbox changing
onEnabledChanged: {
if (enabled) {
StreamingPreferences.videoCodecConfig = codecListModel.get(currentIndex).val
}
else {
StreamingPreferences.videoCodecConfig = StreamingPreferences.VCC_FORCE_HEVC_HDR
}
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered && !enabled
ToolTip.text: qsTr("Enabling HDR overrides manual codec selections.")
}
CheckBox {
id: enableHdr
width: parent.width
text: qsTr("Enable HDR (Experimental)")
font.pointSize: 12
enabled: SystemProperties.supportsHdr
checked: enabled && StreamingPreferences.videoCodecConfig == StreamingPreferences.VCC_FORCE_HEVC_HDR
// Updating StreamingPreferences.videoCodecConfig is handled above
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
ToolTip.text: enabled ?
qsTr("The stream will be HDR-capable, but some games may require an HDR monitor on your host PC to enable HDR mode.")
:
qsTr("HDR streaming is not supported on this PC.")
}
CheckBox {
+4
View File
@@ -103,7 +103,10 @@ Item {
streamSegueErrorDialog.open()
}
}
}
function sessionReadyForDeletion()
{
// Garbage collect the Session object since it's pretty heavyweight
// and keeps other libraries (like SDL_TTF) around until it is deleted.
session = null
@@ -130,6 +133,7 @@ Item {
session.displayLaunchWarning.connect(displayLaunchWarning)
session.quitStarting.connect(quitStarting)
session.sessionFinished.connect(sessionFinished)
session.readyForDeletion.connect(sessionReadyForDeletion)
// Kick off the stream
spinnerTimer.start()
+3
View File
@@ -91,6 +91,8 @@ QVariant AppModel::data(const QModelIndex &index, int role) const
return app.id;
case DirectLaunchRole:
return app.directLaunch;
case AppCollectorGameRole:
return app.isAppCollectorGame;
default:
return QVariant();
}
@@ -106,6 +108,7 @@ QHash<int, QByteArray> AppModel::roleNames() const
names[HiddenRole] = "hidden";
names[AppIdRole] = "appid";
names[DirectLaunchRole] = "directLaunch";
names[AppCollectorGameRole] = "appCollectorGame";
return names;
}
+2 -1
View File
@@ -17,7 +17,8 @@ class AppModel : public QAbstractListModel
BoxArtRole,
HiddenRole,
AppIdRole,
DirectLaunchRole
DirectLaunchRole,
AppCollectorGameRole,
};
public:
+3
View File
@@ -42,6 +42,8 @@ QVariant ComputerModel::data(const QModelIndex& index, int role) const
return !computer->macAddress.isEmpty();
case StatusUnknownRole:
return computer->state == NvComputer::CS_UNKNOWN;
case ServerSupportedRole:
return computer->isSupportedServerVersion;
default:
return QVariant();
}
@@ -68,6 +70,7 @@ QHash<int, QByteArray> ComputerModel::roleNames() const
names[BusyRole] = "busy";
names[WakeableRole] = "wakeable";
names[StatusUnknownRole] = "statusUnknown";
names[ServerSupportedRole] = "serverSupported";
return names;
}
+2 -1
View File
@@ -14,7 +14,8 @@ class ComputerModel : public QAbstractListModel
PairedRole,
BusyRole,
WakeableRole,
StatusUnknownRole
StatusUnknownRole,
ServerSupportedRole
};
public:
+27 -7
View File
@@ -12,13 +12,18 @@ import SdlGamepadKeyNavigation 1.0
ApplicationWindow {
property bool pollingActive: false
// Set by SettingsView to force the back operation to pop all
// pages except the initial view. This is required when doing
// a retranslate() because AppView breaks for some reason.
property bool clearOnBack: false
id: window
visible: true
width: 1280
height: 600
visibility: {
if (SystemProperties.hasWindowManager) {
if (SystemProperties.hasDesktopEnvironment) {
if (StreamingPreferences.uiDisplayMode == StreamingPreferences.UI_WINDOWED) return "Windowed"
else if (StreamingPreferences.uiDisplayMode == StreamingPreferences.UI_MAXIMIZED) return "Maximized"
else if (StreamingPreferences.uiDisplayMode == StreamingPreferences.UI_FULLSCREEN) return "FullScreen"
@@ -31,6 +36,17 @@ ApplicationWindow {
// it will never insert a line break and just extend on forever.
ToolTip.toolTip.contentWidth: ToolTip.toolTip.implicitContentWidth < 400 ? ToolTip.toolTip.implicitContentWidth : 400
function goBack() {
if (clearOnBack) {
// Pop all items except the first one
stackView.pop(null)
clearOnBack = false
}
else {
stackView.pop()
}
}
StackView {
id: stackView
initialItem: initialView
@@ -46,7 +62,7 @@ ApplicationWindow {
Keys.onEscapePressed: {
if (depth > 1) {
stackView.pop()
goBack()
}
else {
quitConfirmationDialog.open()
@@ -55,7 +71,7 @@ ApplicationWindow {
Keys.onBackPressed: {
if (depth > 1) {
stackView.pop()
goBack()
}
else {
quitConfirmationDialog.open()
@@ -199,7 +215,7 @@ ApplicationWindow {
}
RowLayout {
spacing: 20
spacing: 10
anchors.leftMargin: 10
anchors.rightMargin: 10
anchors.fill: parent
@@ -210,7 +226,7 @@ ApplicationWindow {
iconSource: "qrc:/res/arrow_left.svg"
onClicked: stackView.pop()
onClicked: goBack()
Keys.onDownPressed: {
stackView.currentItem.forceActiveFocus(Qt.TabFocus)
@@ -396,7 +412,7 @@ ApplicationWindow {
ErrorMessageDialog {
id: noHwDecoderDialog
text: qsTr("No functioning hardware accelerated H.264 video decoder was detected by Moonlight. " +
text: qsTr("No functioning hardware accelerated video decoder was detected by Moonlight. " +
"Your streaming performance may be severely degraded in this configuration.")
helpText: qsTr("Click the Help button for more information on solving this problem.")
helpUrl: "https://github.com/moonlight-stream/moonlight-docs/wiki/Fixing-Hardware-Decoding-Problems"
@@ -477,7 +493,7 @@ ApplicationWindow {
onAccepted: {
if (editText.text) {
ComputerManager.addNewHost(editText.text.trim(), false)
ComputerManager.addNewHostManually(editText.text.trim())
}
}
@@ -495,6 +511,10 @@ ApplicationWindow {
Keys.onReturnPressed: {
addPcDialog.accept()
}
Keys.onEnterPressed: {
addPcDialog.accept()
}
}
}
}
+15 -1
View File
@@ -12,10 +12,11 @@
SdlGamepadKeyNavigation::SdlGamepadKeyNavigation()
: m_Enabled(false),
m_UiNavMode(false),
m_FirstPoll(false),
m_LastAxisNavigationEventTime(0)
{
m_PollingTimer = new QTimer(this);
connect(m_PollingTimer, SIGNAL(timeout()), this, SLOT(onPollingTimerFired()));
connect(m_PollingTimer, &QTimer::timeout, this, &SdlGamepadKeyNavigation::onPollingTimerFired);
}
SdlGamepadKeyNavigation::~SdlGamepadKeyNavigation()
@@ -62,6 +63,9 @@ void SdlGamepadKeyNavigation::enable()
}
}
// Flush events on the first poll
m_FirstPoll = true;
// Poll every 50 ms for a new joystick event
m_PollingTimer->start(50);
@@ -91,6 +95,16 @@ void SdlGamepadKeyNavigation::onPollingTimerFired()
SDL_Event event;
StreamingPreferences prefs;
// Discard any pending button events on the first poll to avoid picking up
// stale input data from the stream session (like the quit combo).
if (m_FirstPoll) {
SDL_PumpEvents();
SDL_FlushEvent(SDL_CONTROLLERBUTTONDOWN);
SDL_FlushEvent(SDL_CONTROLLERBUTTONUP);
m_FirstPoll = false;
}
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
+1
View File
@@ -34,5 +34,6 @@ private:
QList<SDL_GameController*> m_Gamepads;
bool m_Enabled;
bool m_UiNavMode;
bool m_FirstPoll;
Uint32 m_LastAxisNavigationEventTime;
};
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+505 -222
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
+49 -24
View File
@@ -11,7 +11,6 @@
#include <QCursor>
#include <QElapsedTimer>
#include <QFile>
#include<QTranslator>
// Don't let SDL hook our main function, since Qt is already
// doing the same thing. This needs to be before any headers
@@ -23,7 +22,7 @@
#include "streaming/video/ffmpeg.h"
#endif
#if defined(Q_OS_WIN32) && defined(Q_PROCESSOR_X86)
#if defined(Q_OS_WIN32)
#include "antihookingprotection.h"
#elif defined(Q_OS_LINUX)
#include <openssl/ssl.h>
@@ -168,12 +167,22 @@ void ffmpegLogToDiskHandler(void* ptr, int level, const char* fmt, va_list vl)
return;
}
// We need to use the *previous* printPrefix value to determine whether to
// print the prefix this time. av_log_format_line() will set the printPrefix
// value to indicate whether the prefix should be printed *next time*.
bool shouldPrefixThisMessage = printPrefix != 0;
av_log_format_line(ptr, level, fmt, vl, lineBuffer, sizeof(lineBuffer), &printPrefix);
QTime logTime = QTime::fromMSecsSinceStartOfDay(s_LoggerTime.elapsed());
QString txt = QString("%1 - FFmpeg: %2").arg(logTime.toString()).arg(lineBuffer);
logToLoggerStream(txt);
if (shouldPrefixThisMessage) {
QTime logTime = QTime::fromMSecsSinceStartOfDay(s_LoggerTime.elapsed());
QString txt = QString("%1 - FFmpeg: %2").arg(logTime.toString()).arg(lineBuffer);
logToLoggerStream(txt);
}
else {
QString txt = QString(lineBuffer);
logToLoggerStream(txt);
}
}
#endif
@@ -289,10 +298,9 @@ int main(int argc, char *argv[])
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
#endif
#if defined(Q_OS_WIN32) && defined(Q_PROCESSOR_X86)
#if defined(Q_OS_WIN32)
// Force AntiHooking.dll to be statically imported and loaded
// by ntdll on x86/x64 platforms by calling a dummy function.
// AntiHooking.dll is not currently built for ARM64.
// by ntdll on Win32 platforms by calling a dummy function.
AntiHookingDummyImport();
#elif defined(Q_OS_LINUX)
// Force libssl.so to be directly linked to our binary, so
@@ -351,14 +359,16 @@ int main(int argc, char *argv[])
}
#endif
#if defined(Q_OS_DARWIN) && QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (!qEnvironmentVariableIsSet("QSG_RHI_BACKEND")) {
// The Metal backend in Qt 6.0.0 causes really strange issues transitioning to
// full-screen in our SDL window (hangs in SDL's Cocoa_SetWindowFullscreenSpace())
// and breaks drawing our status updates in the StreamSegue, so use OpenGL like
// Qt 5 does until we figure out the cause of these issues.
qputenv("QSG_RHI_BACKEND", "opengl");
}
#if !defined(Q_OS_WIN32) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Moonlight requires the non-threaded renderer because we depend
// on being able to control the render thread by blocking in the
// main thread (and pumping events from the main thread when needed).
// That doesn't work with the threaded renderer which causes all
// sorts of odd behavior depending on the platform.
//
// NB: Windows defaults to the "windows" non-threaded render loop on
// Qt 5 and the threaded render loop on Qt 6.
qputenv("QSG_RENDER_LOOP", "basic");
#endif
// We don't want system proxies to apply to us
@@ -394,6 +404,9 @@ int main(int argc, char *argv[])
// future KMSDRM platforms that use SDL for rendering.
SDL_SetHint(SDL_HINT_VIDEO_DOUBLE_BUFFER, "1");
// We use MMAL to render on Raspberry Pi, so we do not require DRM master.
SDL_SetHint("SDL_KMSDRM_REQUIRE_DRM_MASTER", "0");
// Use Direct3D 9Ex to avoid a deadlock caused by the D3D device being reset when
// the user triggers a UAC prompt. This option controls the software/SDL renderer.
// The DXVA2 renderer uses Direct3D 9Ex itself directly.
@@ -438,9 +451,15 @@ int main(int argc, char *argv[])
// the mouse motion exactly how it was given to us.
SDL_SetHint("SDL_MOUSE_RELATIVE_SCALING", "0");
// Set our app name for SDL to use with PulseAudio. This matches what we provide
// as our app name to libsoundio too.
// Set our app name for SDL to use with PulseAudio and PipeWire. This matches what we
// provide as our app name to libsoundio too. On SDL 2.0.18+, SDL_APP_NAME is also used
// for screensaver inhibitor reporting.
SDL_SetHint("SDL_AUDIO_DEVICE_APP_NAME", "Moonlight");
SDL_SetHint("SDL_APP_NAME", "Moonlight");
// We handle capturing the mouse ourselves when it leaves the window, so we don't need
// SDL doing it for us behind our backs.
SDL_SetHint("SDL_MOUSE_AUTO_CAPTURE", "0");
#ifdef QT_DEBUG
// Allow thread naming using exceptions on debug builds. SDL doesn't use SEH
@@ -451,15 +470,16 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QTranslator translator;
qDebug() << "Translation loaded:" << translator.load(QString(":/languages/qml_") + QLocale::system().name());
app.installTranslator(&translator);
// Apply the initial translation based on user preference
StreamingPreferences prefs;
prefs.retranslate();
// After the QGuiApplication is created, the platform stuff will be initialized
// and we can set the SDL video driver to match Qt.
if (WMUtils::isRunningWayland() && QGuiApplication::platformName() == "xcb") {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Detected XWayland. This will probably break hardware decoding! Try running with QT_QPA_PLATFORM=wayland or switch to X11.");
qputenv("SDL_VIDEODRIVER", "x11");
}
else if (QGuiApplication::platformName().startsWith("wayland")) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Detected Wayland");
@@ -499,6 +519,11 @@ int main(int argc, char *argv[])
app.setWindowIcon(QIcon(":/res/moonlight.svg"));
#endif
// This is necessary to show our icon correctly on Wayland
app.setDesktopFileName("com.moonlight_stream.Moonlight.desktop");
qputenv("SDL_VIDEO_WAYLAND_WMCLASS", "com.moonlight_stream.Moonlight");
qputenv("SDL_VIDEO_X11_WMCLASS", "com.moonlight_stream.Moonlight");
// Register our C++ types for QML
qmlRegisterType<ComputerModel>("ComputerModel", 1, 0, "ComputerModel");
qmlRegisterType<AppModel>("AppModel", 1, 0, "AppModel");
@@ -525,8 +550,8 @@ int main(int argc, char *argv[])
});
qmlRegisterSingletonType<StreamingPreferences>("StreamingPreferences", 1, 0,
"StreamingPreferences",
[](QQmlEngine*, QJSEngine*) -> QObject* {
return new StreamingPreferences();
[](QQmlEngine* qmlEngine, QJSEngine*) -> QObject* {
return new StreamingPreferences(qmlEngine);
});
// Create the identity manager on the main thread
+146
View File
@@ -0,0 +1,146 @@
// This file contains hooks for several functions that allow
// Qt and SDL to more or less share DRM master ownership.
//
// This technique requires Linux v5.8 or later, or for Moonlight
// to run as root (with CAP_SYS_ADMIN). Prior to Linux v5.8,
// DRM_IOCTL_DROP_MASTER required CAP_SYS_ADMIN, which prevents
// our trick from working (without root, that is).
//
// The specific kernel change required to run without root is:
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=45bc3d26c95a8fc63a7d8668ca9e57ef0883351c
#define _GNU_SOURCE
#include <SDL.h>
#include <dlfcn.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
// We require SDL 2.0.15+ to hook because it supports sharing
// the DRM FD with our code. This avoids having multiple DRM FDs
// in flight at the same time which would significantly complicate
// the logic here because we'd need to figure out exactly which FD
// should be the master at any given time. With the position of our
// hooks, that is definitely not trivial.
#if SDL_VERSION_ATLEAST(2, 0, 15)
// Qt's DRM master FD grabbed by our hook
int g_QtDrmMasterFd = -1;
struct stat64 g_DrmMasterStat;
// The DRM master FD created for SDL
int g_SdlDrmMasterFd = -1;
// This hook will handle legacy DRM rendering
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
drmModeModeInfoPtr mode)
{
// Grab the first DRM FD that makes it in here. This will be the Qt
// EGLFS backend's DRM FD, which we will need later.
if (g_QtDrmMasterFd == -1) {
g_QtDrmMasterFd = fd;
fstat64(g_QtDrmMasterFd, &g_DrmMasterStat);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Captured Qt EGLFS DRM master fd (legacy): %d",
g_QtDrmMasterFd);
}
// Call into the real thing
return ((typeof(drmModeSetCrtc)*)dlsym(RTLD_NEXT, "drmModeSetCrtc"))(fd, crtcId, bufferId, x, y, connectors, count, mode);
}
// This hook will handle atomic DRM rendering
int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req,
uint32_t flags, void *user_data)
{
// Grab the first DRM FD that makes it in here. This will be the Qt
// EGLFS backend's DRM FD, which we will need later.
if (g_QtDrmMasterFd == -1) {
g_QtDrmMasterFd = fd;
fstat64(g_QtDrmMasterFd, &g_DrmMasterStat);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Captured Qt EGLFS DRM master fd (atomic): %d",
g_QtDrmMasterFd);
}
// Call into the real thing
return ((typeof(drmModeAtomicCommit)*)dlsym(RTLD_NEXT, "drmModeAtomicCommit"))(fd, req, flags, user_data);
}
// This hook will handle SDL's open() on the DRM device. We just need to
// hook this variant of open(), since that's what SDL uses. When we see
// the open a FD for the same card as the Qt DRM master FD, we'll drop
// master on the Qt FD to allow the new FD to have master.
int open(const char *pathname, int flags)
{
// Call the real thing to do the open operation
int fd = ((typeof(open)*)dlsym(RTLD_NEXT, "open"))(pathname, flags);
// If the file was successfully opened and we have a DRM master FD,
// check if the FD we just opened is a DRM device.
if (fd >= 0 && g_QtDrmMasterFd != -1) {
if (strncmp(pathname, "/dev/dri/card", 13) == 0) {
// It's a DRM device, but is it _our_ DRM device?
struct stat64 fdstat;
fstat64(fd, &fdstat);
if (g_DrmMasterStat.st_dev == fdstat.st_dev &&
g_DrmMasterStat.st_ino == fdstat.st_ino) {
// It is our device. Time to do the magic!
// This code assumes SDL only ever opens a single FD
// for a given DRM device.
SDL_assert(g_SdlDrmMasterFd == -1);
// Drop master on Qt's FD so we can pick it up for SDL.
if (drmDropMaster(g_QtDrmMasterFd) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to drop master on Qt DRM FD: %d",
errno);
// Hope for the best
return fd;
}
// We are not allowed to call drmSetMaster() without CAP_SYS_ADMIN,
// but since we just dropped the master, we can become master by
// simply creating a new FD. Let's do it.
close(fd);
fd = ((typeof(open)*)dlsym(RTLD_NEXT, "open"))(pathname, flags);
g_SdlDrmMasterFd = fd;
}
}
}
return fd;
}
// Our close() hook handles restoring DRM master to the Qt FD
// after SDL closes its DRM FD.
int close(int fd)
{
// Call the real thing
int ret = ((typeof(close)*)dlsym(RTLD_NEXT, "close"))(fd);
if (ret == 0) {
// If we just closed the SDL DRM master FD, restore master
// to the Qt DRM FD. This works because the Qt DRM master FD
// was master once before, so we can set it as master again
// using drmSetMaster() without CAP_SYS_ADMIN.
if (g_SdlDrmMasterFd != -1 && fd == g_SdlDrmMasterFd) {
if (drmSetMaster(g_QtDrmMasterFd) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to restore master to Qt DRM FD: %d",
errno);
}
g_SdlDrmMasterFd = -1;
}
}
return ret;
}
#endif
+50 -2
View File
@@ -17,15 +17,63 @@
<file>res/baseline-error_outline-24px.svg</file>
<file>res/baseline-check_circle_outline-24px.svg</file>
<file>res/Discord-Logo-White.svg</file>
<file>languages/qml_de.ts</file>
<file>languages/qml_de.qm</file>
<file>languages/qml_fr.ts</file>
<file>languages/qml_fr.qm</file>
<file>languages/qml_zh_cn.ts</file>
<file>languages/qml_zh_cn.qm</file>
<file>languages/qml_nb_NO.ts</file>
<file>languages/qml_nb_NO.qm</file>
<file>languages/qml_ru.ts</file>
<file>languages/qml_ru.qm</file>
<file>languages/qml_es.ts</file>
<file>languages/qml_es.qm</file>
<file>languages/qml_ja.ts</file>
<file>languages/qml_ja.qm</file>
<file>languages/qml_vi.ts</file>
<file>languages/qml_vi.qm</file>
<file>languages/qml_th.ts</file>
<file>languages/qml_th.qm</file>
<file>languages/qml_ko.ts</file>
<file>languages/qml_ko.qm</file>
<file>languages/qml_hu.ts</file>
<file>languages/qml_hu.qm</file>
<file>languages/qml_nl.ts</file>
<file>languages/qml_nl.qm</file>
<file>languages/qml_sv.ts</file>
<file>languages/qml_sv.qm</file>
<file>languages/qml_tr.ts</file>
<file>languages/qml_tr.qm</file>
<file>languages/qml_uk.ts</file>
<file>languages/qml_uk.qm</file>
<file>languages/qml_zh_Hant.ts</file>
<file>languages/qml_zh_Hant.qm</file>
<file>languages/qml_el.ts</file>
<file>languages/qml_el.qm</file>
<file>languages/qml_hi.ts</file>
<file>languages/qml_hi.qm</file>
<file>languages/qml_it.ts</file>
<file>languages/qml_it.qm</file>
<file>languages/qml_pt.ts</file>
<file>languages/qml_pt.qm</file>
<!-- Don't include pt_BR until it is more complete -->
<!--file>languages/qml_pt_BR.qm</file-->
<!--file>languages/qml_pt_BR.ts</file-->
</qresource>
<qresource prefix="/data">
<file alias="gamecontrollerdb.txt">SDL_GameControllerDB/gamecontrollerdb.txt</file>
<file alias="ModeSeven.ttf">ModeSeven.ttf</file>
<file alias="egl.frag">shaders/egl.frag</file>
<file alias="egl.vert">shaders/egl.vert</file>
<file alias="egl_nv12.frag">shaders/egl_nv12.frag</file>
<file alias="egl_nv12.vert">shaders/egl_nv12.vert</file>
<file alias="egl_opaque.frag">shaders/egl_opaque.frag</file>
<file alias="egl_opaque.vert">shaders/egl_opaque.vert</file>
<file alias="egl_overlay.frag">shaders/egl_overlay.frag</file>
<file alias="egl_overlay.vert">shaders/egl_overlay.vert</file>
<file alias="d3d11_vertex.fxc">shaders/d3d11_vertex.fxc</file>
<file alias="d3d11_overlay_pixel.fxc">shaders/d3d11_overlay_pixel.fxc</file>
<file alias="d3d11_genyuv_pixel.fxc">shaders/d3d11_genyuv_pixel.fxc</file>
<file alias="d3d11_bt601lim_pixel.fxc">shaders/d3d11_bt601lim_pixel.fxc</file>
<file alias="d3d11_bt2020lim_pixel.fxc">shaders/d3d11_bt2020lim_pixel.fxc</file>
</qresource>
</RCC>
+137
View File
@@ -0,0 +1,137 @@
#include "compatfetcher.h"
#include "path.h"
#include <QNetworkReply>
#include <QSettings>
#define COMPAT_VERSION "v1"
#define COMPAT_KEY "latestsupportedversion-"
CompatFetcher::CompatFetcher(QObject *parent) :
QObject(parent),
m_Nam(this)
{
// Never communicate over HTTP
m_Nam.setStrictTransportSecurityEnabled(true);
// Allow HTTP redirects
m_Nam.setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
connect(&m_Nam, &QNetworkAccessManager::finished,
this, &CompatFetcher::handleCompatInfoFetched);
}
void CompatFetcher::start()
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) && QT_VERSION < QT_VERSION_CHECK(5, 15, 1) && !defined(QT_NO_BEARERMANAGEMENT)
// HACK: Set network accessibility to work around QTBUG-80947 (introduced in Qt 5.14.0 and fixed in Qt 5.15.1)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
m_Nam.setNetworkAccessible(QNetworkAccessManager::Accessible);
QT_WARNING_POP
#endif
QUrl url("https://moonlight-stream.org/compatibility/" COMPAT_VERSION);
QNetworkRequest request(url);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
request.setAttribute(QNetworkRequest::Http2AllowedAttribute, true);
#else
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
#endif
// We'll get a callback when this is finished
m_Nam.get(request);
}
bool CompatFetcher::isGfeVersionSupported(QString gfeVersion)
{
QSettings settings;
if (gfeVersion.trimmed().isEmpty()) {
// If we don't have a GFE version, just allow it
return true;
}
QString latestSupportedVersion = settings.value(COMPAT_KEY COMPAT_VERSION).toString();
if (latestSupportedVersion.isEmpty()) {
// We don't have compat data yet, so just assume it's supported
return true;
}
QStringList latestSupportedVersionQuad = latestSupportedVersion.split('.');
QStringList gfeVersionQuad = gfeVersion.split('.');
if (gfeVersionQuad.count() <= 1) {
qWarning() << "Failed to parse GFE version:" << gfeVersion;
return true;
}
if (latestSupportedVersionQuad.count() <= 1) {
qWarning() << "Failed to parse latest supported version:" << latestSupportedVersion;
return true;
}
for (int i = 0;; i++) {
int actualVerVal = 0;
int latestSupportedVal = 0;
// Treat missing decimal places as 0
if (i < gfeVersionQuad.count()) {
bool ok;
actualVerVal = gfeVersionQuad[i].toInt(&ok);
if (!ok || actualVerVal < 0) {
// Return true to be safe
qWarning() << "Failed to parse GFE version:" << gfeVersion;
return true;
}
}
if (i < latestSupportedVersionQuad.count()) {
bool ok;
latestSupportedVal = latestSupportedVersionQuad[i].toInt(&ok);
if (!ok || latestSupportedVal < 0) {
// Return true to be safe
qWarning() << "Failed to parse latest supported version:" << latestSupportedVersion;
return true;
}
}
if (i >= gfeVersionQuad.count() && i >= latestSupportedVersionQuad.count()) {
// Equal versions - this is fine
return true;
}
if (actualVerVal < latestSupportedVal) {
// Actual version is lower than latest supported - this is fine
return true;
}
else if (actualVerVal > latestSupportedVal) {
// Actual version is greater than latest supported - this is bad
qWarning() << "GFE version" << gfeVersion << "is not supported by this version of Moonlight";
return false;
}
}
}
void CompatFetcher::handleCompatInfoFetched(QNetworkReply* reply)
{
Q_ASSERT(reply->isFinished());
if (reply->error() == QNetworkReply::NoError) {
// Queue the reply for deletion
reply->deleteLater();
QString version = QString(reply->readAll()).trimmed();
QSettings settings;
settings.setValue(COMPAT_KEY COMPAT_VERSION, version);
qInfo() << "Latest supported GFE server:" << version;
}
else {
qWarning() << "Failed to download latest compatibility data:" << reply->error();
reply->deleteLater();
}
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include <QObject>
#include <QNetworkAccessManager>
class CompatFetcher : public QObject
{
Q_OBJECT
public:
explicit CompatFetcher(QObject *parent = nullptr);
void start();
static bool isGfeVersionSupported(QString gfeVersion);
private slots:
void handleCompatInfoFetched(QNetworkReply* reply);
private:
QNetworkAccessManager m_Nam;
};
+2 -2
View File
@@ -13,8 +13,8 @@ MappingFetcher::MappingFetcher(QObject *parent) :
// Allow HTTP redirects
m_Nam.setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
connect(&m_Nam, SIGNAL(finished(QNetworkReply*)),
this, SLOT(handleMappingListFetched(QNetworkReply*)));
connect(&m_Nam, &QNetworkAccessManager::finished,
this, &MappingFetcher::handleMappingListFetched);
}
void MappingFetcher::start()
+1 -1
View File
@@ -41,7 +41,7 @@ MappingManager::MappingManager()
#else
.split('\n', QString::SkipEmptyParts);
#endif
for (QString sdlMapping : sdlMappings) {
for (const QString& sdlMapping : sdlMappings) {
SdlGamepadMapping mapping(sdlMapping);
addMapping(mapping);
}
+129 -3
View File
@@ -1,6 +1,11 @@
#include "streamingpreferences.h"
#include <QSettings>
#include <QTranslator>
#include <QCoreApplication>
#include <QLocale>
#include <QtDebug>
#define SER_STREAMSETTINGS "streamsettings"
#define SER_WIDTH "width"
@@ -36,11 +41,21 @@
#define SER_REVERSESCROLL "reversescroll"
#define SER_SWAPFACEBUTTONS "swapfacebuttons"
#define SER_CAPTURESYSKEYS "capturesyskeys"
#define SER_KEEPAWAKE "keepawake"
#define SER_LANGUAGE "language"
#define CURRENT_DEFAULT_VER 1
StreamingPreferences::StreamingPreferences(QObject *parent)
: QObject(parent)
: QObject(parent),
m_QmlEngine(nullptr)
{
reload();
}
StreamingPreferences::StreamingPreferences(QQmlEngine *qmlEngine, QObject *parent)
: QObject(parent),
m_QmlEngine(qmlEngine)
{
reload();
}
@@ -81,7 +96,9 @@ void StreamingPreferences::reload()
backgroundGamepad = settings.value(SER_BACKGROUNDGAMEPAD, false).toBool();
reverseScrollDirection = settings.value(SER_REVERSESCROLL, false).toBool();
swapFaceButtons = settings.value(SER_SWAPFACEBUTTONS, false).toBool();
captureSysKeys = settings.value(SER_CAPTURESYSKEYS, false).toBool();
keepAwake = settings.value(SER_KEEPAWAKE, true).toBool();
captureSysKeysMode = static_cast<CaptureSysKeysMode>(settings.value(SER_CAPTURESYSKEYS,
static_cast<int>(CaptureSysKeysMode::CSK_OFF)).toInt());
audioConfig = static_cast<AudioConfig>(settings.value(SER_AUDIOCFG,
static_cast<int>(AudioConfig::AC_STEREO)).toInt());
videoCodecConfig = static_cast<VideoCodecConfig>(settings.value(SER_VIDEOCFG,
@@ -95,6 +112,8 @@ void StreamingPreferences::reload()
uiDisplayMode = static_cast<UIDisplayMode>(settings.value(SER_UIDISPLAYMODE,
static_cast<int>(settings.value(SER_STARTWINDOWED, true).toBool() ? UIDisplayMode::UI_WINDOWED
: UIDisplayMode::UI_MAXIMIZED)).toInt());
language = static_cast<Language>(settings.value(SER_LANGUAGE,
static_cast<int>(Language::LANG_AUTO)).toInt());
// Perform default settings updates as required based on last default version
@@ -108,6 +127,112 @@ void StreamingPreferences::reload()
}
}
bool StreamingPreferences::retranslate()
{
static QTranslator* translator = nullptr;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
if (m_QmlEngine != nullptr) {
// Dynamic retranslation is not supported until Qt 5.10
return false;
}
#endif
QTranslator* newTranslator = new QTranslator();
QString languageSuffix = getSuffixFromLanguage(language);
// Remove the old translator, even if we can't load a new one.
// Otherwise we'll be stuck with the old translated values instead
// of defaulting to English.
if (translator != nullptr) {
QCoreApplication::removeTranslator(translator);
delete translator;
translator = nullptr;
}
if (newTranslator->load(QString(":/languages/qml_") + languageSuffix)) {
qInfo() << "Successfully loaded translation for " << languageSuffix;
translator = newTranslator;
QCoreApplication::installTranslator(translator);
}
else {
qInfo() << "No translation available for " << languageSuffix;
delete newTranslator;
}
if (m_QmlEngine != nullptr) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
// This is a dynamic retranslation from the settings page.
// We have to kick the QML engine into reloading our text.
m_QmlEngine->retranslate();
#else
// Unreachable below Qt 5.10 due to the check above
Q_ASSERT(false);
#endif
}
else {
// This is a translation from a non-QML context, which means
// it is probably app startup. There's nothing to refresh.
}
return true;
}
QString StreamingPreferences::getSuffixFromLanguage(StreamingPreferences::Language lang)
{
switch (lang)
{
case LANG_DE:
return "de";
case LANG_EN:
return "en";
case LANG_FR:
return "fr";
case LANG_ZH_CN:
return "zh_cn";
case LANG_NB_NO:
return "nb_NO";
case LANG_RU:
return "ru";
case LANG_ES:
return "es";
case LANG_JA:
return "ja";
case LANG_VI:
return "vi";
case LANG_TH:
return "th";
case LANG_KO:
return "ko";
case LANG_HU:
return "hu";
case LANG_NL:
return "nl";
case LANG_SV:
return "sv";
case LANG_TR:
return "tr";
case LANG_UK:
return "uk";
case LANG_ZH_HANT:
return "zh_Hant";
case LANG_PT:
return "pt";
case LANG_PT_BR:
return "pt_BR";
case LANG_EL:
return "el";
case LANG_IT:
return "it";
case LANG_HI:
return "hi";
case LANG_AUTO:
default:
return QLocale::system().name();
}
}
void StreamingPreferences::save()
{
QSettings settings;
@@ -136,13 +261,14 @@ void StreamingPreferences::save()
settings.setValue(SER_VIDEODEC, static_cast<int>(videoDecoderSelection));
settings.setValue(SER_WINDOWMODE, static_cast<int>(windowMode));
settings.setValue(SER_UIDISPLAYMODE, static_cast<int>(uiDisplayMode));
settings.setValue(SER_LANGUAGE, static_cast<int>(language));
settings.setValue(SER_DEFAULTVER, CURRENT_DEFAULT_VER);
settings.setValue(SER_SWAPMOUSEBUTTONS, swapMouseButtons);
settings.setValue(SER_MUTEONFOCUSLOSS, muteOnFocusLoss);
settings.setValue(SER_BACKGROUNDGAMEPAD, backgroundGamepad);
settings.setValue(SER_REVERSESCROLL, reverseScrollDirection);
settings.setValue(SER_SWAPFACEBUTTONS, swapFaceButtons);
settings.setValue(SER_CAPTURESYSKEYS, captureSysKeys);
settings.setValue(SER_CAPTURESYSKEYS, captureSysKeysMode);
}
int StreamingPreferences::getDefaultBitrate(int width, int height, int fps)
+57 -3
View File
@@ -2,6 +2,7 @@
#include <QObject>
#include <QRect>
#include <QQmlEngine>
class StreamingPreferences : public QObject
{
@@ -9,6 +10,7 @@ class StreamingPreferences : public QObject
public:
StreamingPreferences(QObject *parent = nullptr);
StreamingPreferences(QQmlEngine *qmlEngine, QObject *parent = nullptr);
Q_INVOKABLE static int
getDefaultBitrate(int width, int height, int fps);
@@ -58,6 +60,45 @@ public:
};
Q_ENUM(UIDisplayMode)
// New entries must go at the end of the enum
// to avoid renumbering existing entries (which
// would affect existing user preferences).
enum Language
{
LANG_AUTO,
LANG_EN,
LANG_FR,
LANG_ZH_CN,
LANG_DE,
LANG_NB_NO,
LANG_RU,
LANG_ES,
LANG_JA,
LANG_VI,
LANG_TH,
LANG_KO,
LANG_HU,
LANG_NL,
LANG_SV,
LANG_TR,
LANG_UK,
LANG_ZH_HANT,
LANG_PT,
LANG_PT_BR,
LANG_EL,
LANG_IT,
LANG_HI,
};
Q_ENUM(Language);
enum CaptureSysKeysMode
{
CSK_OFF,
CSK_FULLSCREEN,
CSK_ALWAYS,
};
Q_ENUM(CaptureSysKeysMode);
Q_PROPERTY(int width MEMBER width NOTIFY displayModeChanged)
Q_PROPERTY(int height MEMBER height NOTIFY displayModeChanged)
Q_PROPERTY(int fps MEMBER fps NOTIFY displayModeChanged)
@@ -87,7 +128,11 @@ public:
Q_PROPERTY(bool backgroundGamepad MEMBER backgroundGamepad NOTIFY backgroundGamepadChanged)
Q_PROPERTY(bool reverseScrollDirection MEMBER reverseScrollDirection NOTIFY reverseScrollDirectionChanged)
Q_PROPERTY(bool swapFaceButtons MEMBER swapFaceButtons NOTIFY swapFaceButtonsChanged)
Q_PROPERTY(bool captureSysKeys MEMBER captureSysKeys NOTIFY captureSysKeysChanged)
Q_PROPERTY(bool keepAwake MEMBER keepAwake NOTIFY keepAwakeChanged)
Q_PROPERTY(CaptureSysKeysMode captureSysKeysMode MEMBER captureSysKeysMode NOTIFY captureSysKeysModeChanged)
Q_PROPERTY(Language language MEMBER language NOTIFY languageChanged);
Q_INVOKABLE bool retranslate();
// Directly accessible members for preferences
int width;
@@ -113,7 +158,7 @@ public:
bool backgroundGamepad;
bool reverseScrollDirection;
bool swapFaceButtons;
bool captureSysKeys;
bool keepAwake;
int packetSize;
AudioConfig audioConfig;
VideoCodecConfig videoCodecConfig;
@@ -121,6 +166,8 @@ public:
WindowMode windowMode;
WindowMode recommendedFullScreenMode;
UIDisplayMode uiDisplayMode;
Language language;
CaptureSysKeysMode captureSysKeysMode;
signals:
void displayModeChanged();
@@ -149,6 +196,13 @@ signals:
void backgroundGamepadChanged();
void reverseScrollDirectionChanged();
void swapFaceButtonsChanged();
void captureSysKeysChanged();
void captureSysKeysModeChanged();
void keepAwakeChanged();
void languageChanged();
private:
QString getSuffixFromLanguage(Language lang);
QQmlEngine* m_QmlEngine;
};
+6
View File
@@ -0,0 +1,6 @@
fxc /T vs_4_0_level_9_3 /Fo d3d11_vertex.fxc d3d11_vertex.hlsl
fxc /T ps_4_0_level_9_3 /Fo d3d11_overlay_pixel.fxc d3d11_overlay_pixel.hlsl
fxc /T ps_4_0_level_9_3 /Fo d3d11_genyuv_pixel.fxc d3d11_genyuv_pixel.hlsl
fxc /T ps_4_0_level_9_3 /Fo d3d11_bt601lim_pixel.fxc d3d11_bt601lim_pixel.hlsl
fxc /T ps_4_0_level_9_3 /Fo d3d11_bt2020lim_pixel.fxc d3d11_bt2020lim_pixel.hlsl
Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
#include "d3d11_video_pixel_start.hlsli"
static const min16float3x3 cscMatrix =
{
1.1644, 1.1644, 1.1644,
0.0, -0.1874, 2.1418,
1.6781, -0.6505, 0.0,
};
static const min16float3 offsets =
{
16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0
};
#include "d3d11_video_pixel_end.hlsli"
Binary file not shown.

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