Full Code of LizardByte/Sunshine for AI

master 4bd461cf8247 cached
452 files
3.7 MB
984.4k tokens
2054 symbols
1 requests
Download .txt
Showing preview only (3,930K chars total). Download the full file or copy to clipboard to get everything.
Repository: LizardByte/Sunshine
Branch: master
Commit: 4bd461cf8247
Files: 452
Total size: 3.7 MB

Directory structure:
gitextract_mnfxyeca/

├── .clang-format
├── .dockerignore
├── .flake8
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── config.yml
│   ├── copilot-instructions.md
│   ├── dependabot.yml
│   ├── matchers/
│   │   ├── copr-ci.json
│   │   ├── docker.json
│   │   ├── gcc-strip3.json
│   │   └── gcc.json
│   ├── semantic.yml
│   └── workflows/
│       ├── _codeql.yml
│       ├── _common-lint.yml
│       ├── _release-notifier.yml
│       ├── _update-changelog.yml
│       ├── _update-docs.yml
│       ├── _update-flathub-repo.yml
│       ├── _update-homebrew-repo.yml
│       ├── _update-pacman-repo.yml
│       ├── _update-winget-repo.yml
│       ├── ci-archlinux.yml
│       ├── ci-bundle.yml
│       ├── ci-copr.yml
│       ├── ci-flatpak.yml
│       ├── ci-freebsd.yml
│       ├── ci-homebrew.yml
│       ├── ci-linux.yml
│       ├── ci-macos.yml
│       ├── ci-windows.yml
│       ├── ci.yml
│       ├── localize.yml
│       ├── release-notifier-moonlight.yml
│       └── update-pages.yml
├── .gitignore
├── .gitmodules
├── .prettierrc.json
├── .readthedocs.yaml
├── .rstcheck.cfg
├── CMakeLists.txt
├── DOCKER_README.md
├── LICENSE
├── NOTICE
├── README.md
├── cmake/
│   ├── FindLIBCAP.cmake
│   ├── FindLIBDRM.cmake
│   ├── FindLibva.cmake
│   ├── FindSystemd.cmake
│   ├── FindUdev.cmake
│   ├── FindWayland.cmake
│   ├── compile_definitions/
│   │   ├── common.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── dependencies/
│   │   ├── Boost_Sunshine.cmake
│   │   ├── FindOpus.cmake
│   │   ├── common.cmake
│   │   ├── ffmpeg.cmake
│   │   ├── glad.cmake
│   │   ├── libevdev_Sunshine.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── nlohmann_json.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── macros/
│   │   ├── common.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── packaging/
│   │   ├── common.cmake
│   │   ├── freebsd_custom_cpack.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   ├── windows.cmake
│   │   ├── windows_nsis.cmake
│   │   ├── windows_wix.cmake
│   │   └── wix_resources/
│   │       ├── patch.xml
│   │       └── sunshine-installer.wxs
│   ├── prep/
│   │   ├── build_version.cmake
│   │   ├── constants.cmake
│   │   ├── init.cmake
│   │   ├── options.cmake
│   │   └── special_package_configuration.cmake
│   └── targets/
│       ├── common.cmake
│       ├── linux.cmake
│       ├── macos.cmake
│       ├── unix.cmake
│       └── windows.cmake
├── codecov.yml
├── crowdin.yml
├── docker/
│   ├── clion-toolchain.dockerfile
│   ├── debian-trixie.dockerfile
│   ├── ubuntu-22.04.dockerfile
│   └── ubuntu-24.04.dockerfile
├── docs/
│   ├── Doxyfile
│   ├── api.js
│   ├── api.md
│   ├── app_examples.md
│   ├── awesome_sunshine.md
│   ├── building.md
│   ├── changelog.md
│   ├── configuration.js
│   ├── configuration.md
│   ├── contributing.md
│   ├── doc-styles.css
│   ├── gamestream_migration.md
│   ├── getting_started.md
│   ├── guides.md
│   ├── legal.md
│   ├── maintainers/
│   │   ├── README.md
│   │   └── release.md
│   ├── performance_tuning.md
│   ├── third_party_packages.md
│   └── troubleshooting.md
├── gh-pages-template/
│   ├── .readthedocs.yaml
│   ├── _config.yml
│   ├── _data/
│   │   ├── clients.yml
│   │   └── features.yml
│   └── index.html
├── package.json
├── packaging/
│   ├── linux/
│   │   ├── AppImage/
│   │   │   ├── AppRun
│   │   │   └── dev.lizardbyte.app.Sunshine.desktop
│   │   ├── Arch/
│   │   │   ├── PKGBUILD
│   │   │   └── sunshine.install
│   │   ├── app-dev.lizardbyte.app.Sunshine.service.in
│   │   ├── copr/
│   │   │   └── Sunshine.spec
│   │   ├── dev.lizardbyte.app.Sunshine.desktop
│   │   ├── dev.lizardbyte.app.Sunshine.metainfo.xml
│   │   ├── dev.lizardbyte.app.Sunshine.terminal.desktop
│   │   ├── flatpak/
│   │   │   ├── README.md
│   │   │   ├── apps.json
│   │   │   ├── dev.lizardbyte.app.Sunshine.desktop
│   │   │   ├── dev.lizardbyte.app.Sunshine.yml
│   │   │   ├── exceptions.json
│   │   │   ├── flathub.json
│   │   │   ├── modules/
│   │   │   │   ├── avahi.json
│   │   │   │   ├── boost.json
│   │   │   │   ├── cuda.json
│   │   │   │   ├── ffmpeg.json
│   │   │   │   ├── libevdev.json
│   │   │   │   ├── miniupnpc.json
│   │   │   │   ├── nlohmann_json.json
│   │   │   │   ├── numactl.json
│   │   │   │   └── xvfb/
│   │   │   │       ├── xvfb-run
│   │   │   │       └── xvfb.json
│   │   │   └── scripts/
│   │   │       ├── additional-install.sh
│   │   │       ├── remove-additional-install.sh
│   │   │       └── sunshine.sh
│   │   └── patches/
│   │       ├── aarch64/
│   │       │   ├── cuda-12-math_functions.patch
│   │       │   └── cuda-13-math_functions.patch
│   │       └── x86_64/
│   │           ├── cuda-12-math_functions.patch
│   │           └── cuda-13-math_functions.patch
│   └── sunshine.rb
├── pyproject.toml
├── scripts/
│   ├── _locale.py
│   ├── icons/
│   │   └── convert_and_pack.sh
│   ├── linux_build.sh
│   ├── macos_build.sh
│   └── update_clang_format.py
├── src/
│   ├── audio.cpp
│   ├── audio.h
│   ├── cbs.cpp
│   ├── cbs.h
│   ├── config.cpp
│   ├── config.h
│   ├── confighttp.cpp
│   ├── confighttp.h
│   ├── crypto.cpp
│   ├── crypto.h
│   ├── display_device.cpp
│   ├── display_device.h
│   ├── entry_handler.cpp
│   ├── entry_handler.h
│   ├── file_handler.cpp
│   ├── file_handler.h
│   ├── globals.cpp
│   ├── globals.h
│   ├── httpcommon.cpp
│   ├── httpcommon.h
│   ├── input.cpp
│   ├── input.h
│   ├── logging.cpp
│   ├── logging.h
│   ├── main.cpp
│   ├── main.h
│   ├── move_by_copy.h
│   ├── network.cpp
│   ├── network.h
│   ├── nvenc/
│   │   ├── nvenc_base.cpp
│   │   ├── nvenc_base.h
│   │   ├── nvenc_colorspace.h
│   │   ├── nvenc_config.h
│   │   ├── nvenc_d3d11.cpp
│   │   ├── nvenc_d3d11.h
│   │   ├── nvenc_d3d11_native.cpp
│   │   ├── nvenc_d3d11_native.h
│   │   ├── nvenc_d3d11_on_cuda.cpp
│   │   ├── nvenc_d3d11_on_cuda.h
│   │   ├── nvenc_encoded_frame.h
│   │   ├── nvenc_utils.cpp
│   │   └── nvenc_utils.h
│   ├── nvhttp.cpp
│   ├── nvhttp.h
│   ├── platform/
│   │   ├── common.h
│   │   ├── linux/
│   │   │   ├── audio.cpp
│   │   │   ├── cuda.cpp
│   │   │   ├── cuda.cu
│   │   │   ├── cuda.h
│   │   │   ├── graphics.cpp
│   │   │   ├── graphics.h
│   │   │   ├── input/
│   │   │   │   ├── inputtino.cpp
│   │   │   │   ├── inputtino_common.h
│   │   │   │   ├── inputtino_gamepad.cpp
│   │   │   │   ├── inputtino_gamepad.h
│   │   │   │   ├── inputtino_keyboard.cpp
│   │   │   │   ├── inputtino_keyboard.h
│   │   │   │   ├── inputtino_mouse.cpp
│   │   │   │   ├── inputtino_mouse.h
│   │   │   │   ├── inputtino_pen.cpp
│   │   │   │   ├── inputtino_pen.h
│   │   │   │   ├── inputtino_touch.cpp
│   │   │   │   └── inputtino_touch.h
│   │   │   ├── kmsgrab.cpp
│   │   │   ├── misc.cpp
│   │   │   ├── misc.h
│   │   │   ├── portalgrab.cpp
│   │   │   ├── publish.cpp
│   │   │   ├── vaapi.cpp
│   │   │   ├── vaapi.h
│   │   │   ├── wayland.cpp
│   │   │   ├── wayland.h
│   │   │   ├── wlgrab.cpp
│   │   │   ├── x11grab.cpp
│   │   │   └── x11grab.h
│   │   ├── macos/
│   │   │   ├── av_audio.h
│   │   │   ├── av_audio.m
│   │   │   ├── av_img_t.h
│   │   │   ├── av_video.h
│   │   │   ├── av_video.m
│   │   │   ├── display.mm
│   │   │   ├── input.cpp
│   │   │   ├── microphone.mm
│   │   │   ├── misc.h
│   │   │   ├── misc.mm
│   │   │   ├── nv12_zero_device.cpp
│   │   │   ├── nv12_zero_device.h
│   │   │   └── publish.cpp
│   │   └── windows/
│   │       ├── PolicyConfig.h
│   │       ├── audio.cpp
│   │       ├── display.h
│   │       ├── display_base.cpp
│   │       ├── display_ram.cpp
│   │       ├── display_vram.cpp
│   │       ├── display_wgc.cpp
│   │       ├── input.cpp
│   │       ├── keylayout.h
│   │       ├── misc.cpp
│   │       ├── misc.h
│   │       ├── nvprefs/
│   │       │   ├── driver_settings.cpp
│   │       │   ├── driver_settings.h
│   │       │   ├── nvapi_opensource_wrapper.cpp
│   │       │   ├── nvprefs_common.cpp
│   │       │   ├── nvprefs_common.h
│   │       │   ├── nvprefs_interface.cpp
│   │       │   ├── nvprefs_interface.h
│   │       │   ├── undo_data.cpp
│   │       │   ├── undo_data.h
│   │       │   ├── undo_file.cpp
│   │       │   └── undo_file.h
│   │       ├── publish.cpp
│   │       ├── utf_utils.cpp
│   │       ├── utf_utils.h
│   │       └── windows.rc
│   ├── process.cpp
│   ├── process.h
│   ├── round_robin.h
│   ├── rswrapper.c
│   ├── rswrapper.h
│   ├── rtsp.cpp
│   ├── rtsp.h
│   ├── stat_trackers.cpp
│   ├── stat_trackers.h
│   ├── stream.cpp
│   ├── stream.h
│   ├── sync.h
│   ├── system_tray.cpp
│   ├── system_tray.h
│   ├── task_pool.h
│   ├── thread_pool.h
│   ├── thread_safe.h
│   ├── upnp.cpp
│   ├── upnp.h
│   ├── utility.h
│   ├── uuid.h
│   ├── video.cpp
│   ├── video.h
│   ├── video_colorspace.cpp
│   └── video_colorspace.h
├── src_assets/
│   ├── bsd/
│   │   └── misc/
│   │       ├── +POST_INSTALL
│   │       └── +PRE_DEINSTALL
│   ├── common/
│   │   └── assets/
│   │       └── web/
│   │           ├── Checkbox.vue
│   │           ├── Navbar.vue
│   │           ├── PlatformLayout.vue
│   │           ├── ResourceCard.vue
│   │           ├── SimpleIcon.vue
│   │           ├── ThemeToggle.vue
│   │           ├── apps.html
│   │           ├── config.html
│   │           ├── configs/
│   │           │   └── tabs/
│   │           │       ├── Advanced.vue
│   │           │       ├── AudioVideo.vue
│   │           │       ├── ContainerEncoders.vue
│   │           │       ├── Files.vue
│   │           │       ├── General.vue
│   │           │       ├── Inputs.vue
│   │           │       ├── Network.vue
│   │           │       ├── audiovideo/
│   │           │       │   ├── AdapterNameSelector.vue
│   │           │       │   ├── DisplayDeviceOptions.vue
│   │           │       │   ├── DisplayModesSettings.vue
│   │           │       │   └── DisplayOutputSelector.vue
│   │           │       └── encoders/
│   │           │           ├── AmdAmfEncoder.vue
│   │           │           ├── IntelQuickSyncEncoder.vue
│   │           │           ├── NvidiaNvencEncoder.vue
│   │           │           ├── SoftwareEncoder.vue
│   │           │           ├── VAAPIEncoder.vue
│   │           │           └── VideotoolboxEncoder.vue
│   │           ├── featured.html
│   │           ├── index.html
│   │           ├── init.js
│   │           ├── locale.js
│   │           ├── password.html
│   │           ├── pin.html
│   │           ├── platform-i18n.js
│   │           ├── public/
│   │           │   └── assets/
│   │           │       ├── css/
│   │           │       │   └── sunshine.css
│   │           │       └── locale/
│   │           │           ├── bg.json
│   │           │           ├── cs.json
│   │           │           ├── de.json
│   │           │           ├── en.json
│   │           │           ├── en_GB.json
│   │           │           ├── en_US.json
│   │           │           ├── es.json
│   │           │           ├── fr.json
│   │           │           ├── hu.json
│   │           │           ├── it.json
│   │           │           ├── ja.json
│   │           │           ├── ko.json
│   │           │           ├── pl.json
│   │           │           ├── pt.json
│   │           │           ├── pt_BR.json
│   │           │           ├── ru.json
│   │           │           ├── sv.json
│   │           │           ├── tr.json
│   │           │           ├── uk.json
│   │           │           ├── vi.json
│   │           │           ├── zh.json
│   │           │           └── zh_TW.json
│   │           ├── sunshine_version.js
│   │           ├── template_header.html
│   │           ├── theme.js
│   │           ├── troubleshooting.html
│   │           └── welcome.html
│   ├── linux/
│   │   ├── assets/
│   │   │   ├── apps.json
│   │   │   └── shaders/
│   │   │       └── opengl/
│   │   │           ├── ConvertUV.frag
│   │   │           ├── ConvertUV.vert
│   │   │           ├── ConvertY.frag
│   │   │           ├── Scene.frag
│   │   │           └── Scene.vert
│   │   └── misc/
│   │       ├── 60-sunshine.conf
│   │       ├── 60-sunshine.rules
│   │       └── postinst
│   ├── macos/
│   │   └── assets/
│   │       └── apps.json
│   └── windows/
│       ├── assets/
│       │   ├── apps.json
│       │   └── shaders/
│       │       └── directx/
│       │           ├── convert_yuv420_packed_uv_type0_ps.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_ps_linear.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_vs.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps_linear.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_vs.hlsl
│       │           ├── convert_yuv420_planar_y_ps.hlsl
│       │           ├── convert_yuv420_planar_y_ps_linear.hlsl
│       │           ├── convert_yuv420_planar_y_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_planar_y_vs.hlsl
│       │           ├── convert_yuv444_packed_ayuv_ps.hlsl
│       │           ├── convert_yuv444_packed_ayuv_ps_linear.hlsl
│       │           ├── convert_yuv444_packed_vs.hlsl
│       │           ├── convert_yuv444_packed_y410_ps.hlsl
│       │           ├── convert_yuv444_packed_y410_ps_linear.hlsl
│       │           ├── convert_yuv444_packed_y410_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv444_planar_ps.hlsl
│       │           ├── convert_yuv444_planar_ps_linear.hlsl
│       │           ├── convert_yuv444_planar_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv444_planar_vs.hlsl
│       │           ├── cursor_ps.hlsl
│       │           ├── cursor_ps_normalize_white.hlsl
│       │           ├── cursor_vs.hlsl
│       │           └── include/
│       │               ├── base_vs.hlsl
│       │               ├── base_vs_types.hlsl
│       │               ├── common.hlsl
│       │               ├── convert_base.hlsl
│       │               ├── convert_linear_base.hlsl
│       │               ├── convert_perceptual_quantizer_base.hlsl
│       │               ├── convert_yuv420_packed_uv_ps_base.hlsl
│       │               ├── convert_yuv420_planar_y_ps_base.hlsl
│       │               └── convert_yuv444_ps_base.hlsl
│       └── misc/
│           ├── autostart/
│           │   └── autostart-service.bat
│           ├── firewall/
│           │   ├── add-firewall-rule.bat
│           │   └── delete-firewall-rule.bat
│           ├── migration/
│           │   └── migrate-config.bat
│           ├── path/
│           │   └── update-path.bat
│           ├── service/
│           │   ├── install-service.bat
│           │   └── uninstall-service.bat
│           └── sunshine-setup.ps1
├── tests/
│   ├── CMakeLists.txt
│   ├── fixtures/
│   │   └── http/
│   │       ├── hello-redirect.txt
│   │       └── hello.txt
│   ├── integration/
│   │   ├── test_config_consistency.cpp
│   │   ├── test_external_commands.cpp
│   │   └── test_locale_consistency.cpp
│   ├── tests_common.h
│   ├── tests_environment.h
│   ├── tests_events.h
│   ├── tests_log_checker.h
│   ├── tests_main.cpp
│   └── unit/
│       ├── platform/
│       │   ├── test_common.cpp
│       │   └── windows/
│       │       └── test_utf_utils.cpp
│       ├── test_audio.cpp
│       ├── test_confighttp.cpp
│       ├── test_display_device.cpp
│       ├── test_entry_handler.cpp
│       ├── test_file_handler.cpp
│       ├── test_http_pairing.cpp
│       ├── test_httpcommon.cpp
│       ├── test_logging.cpp
│       ├── test_mouse.cpp
│       ├── test_network.cpp
│       ├── test_process.cpp
│       ├── test_rswrapper.cpp
│       ├── test_stream.cpp
│       └── test_video.cpp
├── third-party/
│   ├── .clang-format-ignore
│   └── nvfbc/
│       ├── NvFBC.h
│       └── helper_math.h
├── tools/
│   ├── CMakeLists.txt
│   ├── audio.cpp
│   ├── dxgi.cpp
│   └── sunshinesvc.cpp
└── vite.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
# This file is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: BlockIndent
AlignConsecutiveAssignments: None
AlignEscapedNewlines: DontAlign
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: true
AlignTrailingComments: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: false
BinPackParameters: false
BracedInitializerIndentWidth: 2
BraceWrapping:
  AfterCaseLabel: false
  AfterClass: false
  AfterControlStatement: Never
  AfterEnum: false
  AfterExternBlock: true
  AfterFunction: false
  AfterNamespace: false
  AfterObjCDeclaration: false
  AfterUnion: false
  BeforeCatch: true
  BeforeElse: true
  IndentBraces: false
  SplitEmptyFunction: false
  SplitEmptyRecord: true
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Always
ExperimentalAutoDetectBinPacking: true
FixNamespaceComments: true
IncludeBlocks: Regroup
IndentAccessModifiers: false
IndentCaseBlocks: true
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: true
IndentPPDirectives: BeforeHash
IndentWidth: 2
IndentWrappedFunctionNames: true
InsertBraces: true
InsertNewlineAtEOF: true
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Never
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: Never
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 1
PenaltyBreakString: 1
PenaltyBreakFirstLessLess: 0
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 100000000
PointerAlignment: Right
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveSemicolon: false
SeparateDefinitionBlocks: Always
SortIncludes: CaseInsensitive
SortUsingDeclarations: Lexicographic
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: false
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInLineCommentPrefix:
  Maximum: 3
  Minimum: 1
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 2
UseTab: Never


================================================
FILE: .dockerignore
================================================
# ignore hidden files
.*

# do not ignore .git, needed for versioning
!/.git

# do not ignore .rstcheck.cfg, needed to test building docs
!/.rstcheck.cfg

# ignore repo directories and files
docker/
gh-pages-template/
scripts/
tools/
crowdin.yml

# don't ignore linux build script
!scripts/linux_build.sh

# ignore dev directories
build/
cmake-*/
venv/

# ignore artifacts
artifacts/


================================================
FILE: .flake8
================================================
[flake8]
filename =
    *.py
max-line-length = 120
extend-exclude =
    .venv/
    venv/


================================================
FILE: .gitattributes
================================================
# ensure Linux specific files are checked out with LF line endings
Dockerfile text eol=lf
*.dockerfile text eol=lf
*flatpak-lint-*.json text eol=lf
*.sh text eol=lf


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
---
name: Bug Report
description: Create a bug report to help us improve.
body:
  - type: markdown
    attributes:
      value: >
        **THIS IS NOT THE PLACE TO ASK FOR SUPPORT!**
        Please use our [Support Center](https://app.lizardbyte.dev/support) for support issues.
        Non actionable bug reports will be LOCKED and CLOSED!
  - type: checkboxes
    attributes:
      label: Is there an existing issue for this?
      description: Please search to see if an issue already exists for the bug you encountered.
      options:
        - label: I have searched the existing issues
  - type: checkboxes
    attributes:
      label: Is your issue described in the documentation?
      description: Please read our [documentation](https://docs.lizardbyte.dev/projects/sunshine)
      options:
        - label: I have read the documentation
  - type: dropdown
    attributes:
      label: Is your issue present in the latest beta/pre-release?
      description: Please test the latest [pre-release](https://github.com/LizardByte/Sunshine/releases).
      options:
        - "I didn't read the issue template"
        - "I'm too lazy to test"
        - "This issue is present in the latest pre-release"
  - type: textarea
    id: description
    attributes:
      label: Describe the Bug
      description: |
        A clear and concise description of the bug, list the reproduction steps.
        :warning: Errors in log messages are NOT bugs. Read the message and fix what it's telling you. :warning:
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected to happen.
  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: Add any other context about the bug here.
  - type: dropdown
    id: os
    attributes:
      label: Host Operating System
      description: What version operating system are you running the software on?
      options:
        - Docker
        - FreeBSD
        - Linux
        - macOS
        - Windows
        - other, n/a
    validations:
      required: true
  - type: input
    id: os-version
    attributes:
      label: Operating System Version
      description: Provide the version of the operating system. Additionally a build number would be helpful.
    validations:
      required: true
  - type: dropdown
    id: os-architecture
    attributes:
      label: Architecture
      options:
        - amd64/x86_64
        - arm64/aarch64
        - other, n/a
    validations:
      required: true
  - type: dropdown
    id: package_type
    attributes:
      label: Package
      description: The package you installed
      options:
        - Linux - AppImage
        - Linux - AUR (Third Party)
        - Linux - deb
        - Linux - Docker
        - Linux - Fedora Copr
        - Linux - flathub/flatpak
        - Linux - Homebrew
        - Linux - LizardByte/pacman-repo
        - Linux - nixpkgs (Third Party)
        - Linux - pkg.tar.zst
        - Linux - solus (Third Party)
        - Linux - Unraid (Third Party)
        - macOS - dmg
        - macOS - Homebrew
        - Windows - Chocolatey (Third Party)
        - Windows - exe installer
        - Windows - msi installer (recommended)
        - Windows - portable (NOT recommended)
        - Windows - Scoop (Third Party)
        - Windows - Winget
        - other (not listed)
        - other (self built)
        - other (fork of this repo)
        - n/a
    validations:
      required: true
  - type: dropdown
    id: graphics_type
    attributes:
      label: GPU Type
      description: The type of the installed graphics card.
      options:
        - AMD
        - Apple Silicon
        - Intel
        - NVIDIA
        - Qualcomm (mediafoundation)
        - none (software encoding)
        - n/a
    validations:
      required: true
  - type: input
    id: graphics_model
    attributes:
      label: GPU Model
      description: The model of the installed graphics card.
    validations:
      required: true
  - type: input
    id: graphics_driver
    attributes:
      label: GPU Driver/Mesa Version
      description: The driver/mesa version of the installed graphics card.
    validations:
      required: true
  - type: dropdown
    id: capture_method
    attributes:
      label: Capture Method
      description: The capture method being used.
      options:
        - AVCaptureScreen (macOS)
        - KMS (Linux)
        - NvFBC (Linux)
        - wlroots (Linux)
        - X11 (Linux)
        - XDG Portal Grab (Linux)
        - Desktop Duplication API (Windows)
        - Windows.Graphics.Capture (Windows)
    validations:
      required: false
  - type: textarea
    id: apps
    attributes:
      label: Apps
      description: |
        If this is an issue with launching a game or app, please copy and paste your `apps.json` file.
      render: json
    validations:
      required: false
  - type: textarea
    id: logs
    attributes:
      label: Log output
      description: |
        Copy and paste logs from web-ui troubleshooting page.
        This will be automatically formatted into code, so no need for backticks.
        :warning: If full logs are not provided, the issue will be closed! :warning:
      render: shell
    validations:
      required: false
  - type: input
    id: logs_link
    attributes:
      label: Online logs
      description: |
        If logs are too long to include in the field above,
        create a [gist](https://gist.github.com/) of the logs and paste the link here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
---
# This file is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

blank_issues_enabled: false
contact_links:
  - name: Discussions
    url: https://github.com/orgs/LizardByte/discussions
    about: Community discussions
  - name: Questions
    url: https://github.com/orgs/LizardByte/discussions
    about: Ask questions
  - name: Feature Requests
    url: https://github.com/orgs/LizardByte/discussions
    about: Request new features
  - name: Support Center
    url: https://app.lizardbyte.dev/support
    about: Official LizardByte support


================================================
FILE: .github/copilot-instructions.md
================================================
On Windows we use msys2 and ucrt64 to compile.
You need to prefix commands with `C:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -c`.

Prefix build directories with `cmake-build-`.

The test executable is named `test_sunshine` and will be located inside the `tests` directory within
the build directory.

The project uses gtest as a test framework.

Always follow the style guidelines defined in .clang-format for c/c++ code.


================================================
FILE: .github/dependabot.yml
================================================
---
# This file is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "0 1 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10

  - package-ecosystem: "docker"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "30 1 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10

  - package-ecosystem: "github-actions"
    directories:
      - "/"
      - "/.github/actions/*"
      - "/actions/*"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "0 2 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10
    groups:
      docker-actions:
        applies-to: version-updates
        patterns:
          - "docker/*"
      github-actions:
        applies-to: version-updates
        patterns:
          - "actions/*"
          - "github/*"
      lizardbyte-actions:
        applies-to: version-updates
        patterns:
          - "LizardByte/*"

  - package-ecosystem: "gitsubmodule"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "30 2 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10

  - package-ecosystem: "npm"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "0 3 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10
    groups:
      dev-dependencies:
        applies-to: version-updates
        dependency-type: "development"

  - package-ecosystem: "nuget"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "30 3 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10

  - package-ecosystem: "pip"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "0 4 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 10
    groups:
      pytest-dependencies:
        applies-to: version-updates
        patterns:
          - "pytest*"

  - package-ecosystem: "rust-toolchain"
    directory: "/"
    rebase-strategy: disabled
    schedule:
      interval: "cron"
      cronjob: "30 4 * * *"
      timezone: "America/New_York"
    open-pull-requests-limit: 1


================================================
FILE: .github/matchers/copr-ci.json
================================================
{
  "problemMatcher": [
    {
      "owner": "copr-ci-gcc",
      "pattern": [
        {
          "regexp": "^/?(?:[^/]+/){5}([^:]+):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      ]
    }
  ]
}


================================================
FILE: .github/matchers/docker.json
================================================
{
  "problemMatcher": [
    {
      "owner": "docker-gcc",
      "pattern": [
        {
          "regexp": "^(?:#\\d+\\s+\\d+\\.\\d+\\s+)?/?(?:[^/]+/){2}([^:]+):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      ]
    }
  ]
}


================================================
FILE: .github/matchers/gcc-strip3.json
================================================
{
  "problemMatcher": [
    {
      "owner": "gcc-strip3",
      "pattern": [
        {
          "regexp": "^/?(?:[^/]+/){3}([^:]+):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      ]
    }
  ]
}


================================================
FILE: .github/matchers/gcc.json
================================================
{
  "problemMatcher": [
    {
      "owner": "gcc",
      "pattern": [
        {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      ]
    },
    {
      "owner": "doxygen",
      "pattern": [
        {
          "regexp": "^.*?([A-Za-z]:[\\\\/][^:]+|[\\\\/][^:]+):(\\d+): ([a-zA-Z]+): (.+)$",
          "file": 1,
          "line": 2,
          "severity": 3,
          "message": 4
        }
      ]
    }
  ]
}


================================================
FILE: .github/semantic.yml
================================================
---
# This file is centrally managed in https://github.com/<organization>/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# This is the configuration file for https://github.com/Ezard/semantic-prs

enabled: true
titleOnly: true  # We only use the PR title as we squash and merge
commitsOnly: false
titleAndCommits: false
anyCommit: false
allowMergeCommits: false
allowRevertCommits: false
targetUrl: https://docs.lizardbyte.dev/latest/developers/contributing.html#creating-a-pull-request


================================================
FILE: .github/workflows/_codeql.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

name: CodeQL
permissions: {}

on:
  pull_request:
  push:
    branches:
      - master
  schedule:
    - cron: '00 12 * * 0'  # every Sunday at 12:00 UTC

concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  call-codeql:
    name: CodeQL
    uses: LizardByte/.github/.github/workflows/__call-codeql.yml@master
    if: ${{ github.repository != 'LizardByte/.github' }}
    permissions:
      actions: read
      contents: read
      security-events: write


================================================
FILE: .github/workflows/_common-lint.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

name: common lint
permissions: {}

on:
  pull_request:

concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  lint:
    name: Common Lint
    uses: LizardByte/.github/.github/workflows/__call-common-lint.yml@master
    if: ${{ github.repository != 'LizardByte/.github' }}
    permissions:
      contents: read
      pull-requests: read


================================================
FILE: .github/workflows/_release-notifier.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# Create a blog post for a new release and open a PR to the blog repo

name: Release Notifications
permissions: {}

on:
  release:
    types:
      - released  # this triggers when a release is published, but does not include pre-releases or drafts

jobs:
  update-blog:
    name: Update blog
    uses: LizardByte/.github/.github/workflows/__call-release-notifier.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions:
      contents: read
    with:
      gh_name: ${{ vars.GH_BOT_NAME }}
    secrets:
      GH_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/_update-changelog.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

name: Update changelog
permissions: {}

on:
  release:
    types:
      - created
      - edited
      - deleted
  workflow_dispatch:

concurrency:
  group: "${{ github.workflow }}"
  cancel-in-progress: true

jobs:
  update-changelog:
    name: Update Changelog
    uses: LizardByte/.github/.github/workflows/__call-update-changelog.yml@master
    if: >-
      github.repository_owner == 'LizardByte' &&
      (github.event_name == 'workflow_dispatch' ||
      (!github.event.release.prerelease && !github.event.release.draft))
    permissions:
      contents: read
    secrets:
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/_update-docs.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# To use, add the `rtd` repository label to identify repositories that should trigger this workflow.
# If the project slug is not the repository name, add a repository variable named `READTHEDOCS_SLUG` with the value of
# the ReadTheDocs project slug.

# Update readthedocs on release events.

name: Update docs
permissions: {}

on:
  release:
    types:
      - created
      - edited
      - deleted

concurrency:
  group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
  cancel-in-progress: true

jobs:
  update-docs:
    name: Update docs
    uses: LizardByte/.github/.github/workflows/__call-update-docs.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions: {}
    with:
      readthedocs_slug: ${{ vars.READTHEDOCS_SLUG }}
    secrets:
      READTHEDOCS_TOKEN: ${{ secrets.READTHEDOCS_TOKEN }}


================================================
FILE: .github/workflows/_update-flathub-repo.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# To use, add the `flathub-pkg` repository label to identify repositories that should trigger this workflow.

# Update Flathub on release events.

name: Update Flathub repo
permissions: {}

on:
  release:
    types:
      - released

concurrency:
  group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
  cancel-in-progress: true

jobs:
  update-flathub-repo:
    name: Update Flathub Repo
    uses: LizardByte/.github/.github/workflows/__call-update-flathub-repo.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions:
      contents: read
    with:
      gh_name: ${{ vars.GH_BOT_NAME }}
    secrets:
      GH_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/_update-homebrew-repo.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# To use, add the `homebrew-pkg` repository label to identify repositories that should trigger this workflow.

# Update Homebrew on release events.

name: Update Homebrew repo
permissions: {}

on:
  release:
    types:
      - released

concurrency:
  group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
  cancel-in-progress: true

jobs:
  update-homebrew-repo:
    name: Update Homebrew repo
    uses: LizardByte/.github/.github/workflows/__call-update-homebrew-repo.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions:
      contents: read
    with:
      gh_username: ${{ vars.GH_BOT_NAME }}
    secrets:
      GH_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/_update-pacman-repo.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# To use, add the `pacman-pkg` repository label to identify repositories that should trigger this workflow.

# Update pacman repo on release events.

name: Update pacman repo
permissions: {}

on:
  release:
    types:
      - released

concurrency:
  group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
  cancel-in-progress: true

jobs:
  update-pacman-repo:
    name: Update pacman repo
    uses: LizardByte/.github/.github/workflows/__call-update-pacman-repo.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions:
      contents: read
    with:
      gh_name: ${{ vars.GH_BOT_NAME }}
    secrets:
      GH_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/_update-winget-repo.yml
================================================
---
# This workflow is centrally managed in https://github.com/LizardByte/.github/
# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in
# the above-mentioned repo.

# To use, add the `winget-pkg` repository label to identify repositories that should trigger this workflow.

# Update Winget on release events.

name: Update Winget repo
permissions: {}

on:
  release:
    types:
      - released

concurrency:
  group: "${{ github.workflow }}-${{ github.event.release.tag_name }}"
  cancel-in-progress: true

jobs:
  update-winget-repo:
    name: Update Winget repo
    uses: LizardByte/.github/.github/workflows/__call-update-winget-repo.yml@master
    if: github.repository_owner == 'LizardByte'
    permissions:
      contents: read
    with:
      gh_name: ${{ vars.GH_BOT_NAME }}
    secrets:
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}


================================================
FILE: .github/workflows/ci-archlinux.yml
================================================
---
name: CI-Archlinux
permissions: {}

on:
  workflow_call:
    inputs:
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string

jobs:
  build_archlinux:
    name: Archlinux
    env:
      _use_cuda: true
      _run_unit_tests: true
      _support_headless_testing: true
      BRANCH: ${{ github.head_ref || github.ref_name }}
      BUILD_VERSION: ${{ inputs.release_version }}
      CLONE_URL: ${{ github.event.repository.clone_url }}
      COMMIT: ${{ inputs.release_commit }}
    permissions:
      contents: read
    runs-on: ubuntu-latest
    container:
      image: archlinux/archlinux:base-devel
      options: --cpus 4 --memory 8g
    steps:

      - name: Update keyring
        shell: bash
        run: |
          # Update keyring to avoid signature errors, and update system
          pacman -Syy --disable-download-timeout --needed --noconfirm \
            archlinux-keyring
          pacman -Syu --disable-download-timeout --noconfirm
          pacman -Scc --noconfirm

      - name: Setup builder user
        shell: bash
        run: |
          # arch prevents running makepkg as root
          useradd -m builder
          echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

      - name: Patch build flags
        shell: bash
        run: |
          # shellcheck disable=SC2016
          sed -i 's,#MAKEFLAGS="-j2",MAKEFLAGS="-j$(nproc)",g' /etc/makepkg.conf

      - name: Install dependencies
        shell: bash
        run: |
          pacman -Syu --disable-download-timeout --needed --noconfirm \
            base-devel \
            cmake \
            cuda \
            git \
            namcap \
            xorg-server-xvfb
          pacman -Scc --noconfirm

      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Fix workspace permissions
        shell: bash
        run: |
          # Give builder user ownership of the workspace
          chown -R builder:builder "${GITHUB_WORKSPACE}"

      - name: Configure PKGBUILD
        shell: bash
        run: |
          # Calculate sub_version
          sub_version=""
          if [[ "${BRANCH}" != "master" ]]; then
            sub_version=".r${COMMIT}"
          fi

          # Configure PKGBUILD file (as root)
          mkdir -p build
          cd build
          cmake \
            -DSUNSHINE_CONFIGURE_ONLY=ON \
            -DSUNSHINE_CONFIGURE_PKGBUILD=ON \
            -DSUNSHINE_SUB_VERSION="${sub_version}" \
            ..

          # Make sure builder can read from build directory
          chmod -R a+rX "${GITHUB_WORKSPACE}/build"

      - name: Prepare PKGBUILD Package
        shell: bash
        run: |
          # Create pkg directory and move files (as root)
          mkdir -p pkg
          mv build/PKGBUILD pkg/
          mv build/sunshine.install pkg/

          # Change ownership to builder
          chown -R builder:builder pkg

          # Run makepkg as builder user
          cd pkg
          sudo -u builder makepkg --printsrcinfo | tee .SRCINFO

          # create a PKGBUILD archive
          cd ..
          tar -czf sunshine.pkg.tar.gz -C pkg .

      - name: Build PKGBUILD
        env:
          DISPLAY: :1
        id: build
        shell: bash
        working-directory: pkg
        run: |
          # Add problem matcher
          echo "::add-matcher::.github/matchers/gcc.json"

          source /etc/profile  # ensure cuda is in the PATH

          # Run Xvfb for headless testing
          Xvfb "${DISPLAY}" -screen 0 1024x768x24 &

          # Check PKGBUILD
          sudo -u builder namcap -i PKGBUILD

          # Export PKGBUILD options so they're available to makepkg
          export _use_cuda="${_use_cuda}"
          export _run_unit_tests="${_run_unit_tests}"
          export _support_headless_testing="${_support_headless_testing}"

          # Build the package as builder user (pass through environment variables)
          sudo -u builder env \
            _use_cuda="${_use_cuda}" \
            _run_unit_tests="${_run_unit_tests}" \
            _support_headless_testing="${_support_headless_testing}" \
            makepkg -si --noconfirm

          # Remove debug package
          rm -f sunshine-debug*.pkg.tar.zst

          # Remove problem matcher
          echo "::remove-matcher owner=gcc::"

      - name: Upload coverage artifact
        if: >-
          always() &&
          (steps.build.outcome == 'success' || steps.build.outcome == 'failure')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-Archlinux
          path: |
            pkg/src/build/coverage.xml
            pkg/src/build/tests/test_results.xml
          if-no-files-found: error

      - name: Copy Artifacts
        shell: bash
        run: |
          # create artifacts directory
          mkdir -p artifacts

          # Copy built packages to artifacts
          cp pkg/sunshine*.pkg.tar.zst artifacts/
          cp sunshine.pkg.tar.gz artifacts/

          # List artifacts
          ls -la artifacts/

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-Archlinux
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-bundle.yml
================================================
---
name: CI-Bundle
permissions: {}

on:
  workflow_call:
    secrets:
      CODECOV_TOKEN:
        required: false

jobs:
  bundle_analysis:
    permissions:
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Setup node
        id: node
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f  # v6.3.0

      - name: Install npm dependencies
        run: npm install --ignore-scripts

      - name: Debug install
        if: always()
        run: cat "${HOME}/.npm/_logs/*-debug-0.log" || true

      - name: Build
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
        run: npm run build


================================================
FILE: .github/workflows/ci-copr.yml
================================================
---
name: CI-Copr
permissions: {}

on:
  release:
    types:
      - prereleased
      - released
  workflow_call:
    secrets:
      COPR_BETA_WEBHOOK_TOKEN:
        required: false
      COPR_STABLE_WEBHOOK_TOKEN:
        required: false
      COPR_CLI_CONFIG:
        required: false
      GH_BOT_TOKEN:
        required: false
      VIRUSTOTAL_API_KEY:
        required: false

concurrency:
  group: "_${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  call-copr-ci:
    permissions:
      contents: read
    uses: LizardByte/copr-ci/.github/workflows/copr-ci.yml@master
    with:
      copr_pr_webhook_token: "05fc9b07-a19b-4f83-89b2-ae1e7e0b5282"
      github_org_owner: LizardByte
      copr_ownername: lizardbyte
      auto_update_package: true
      job_timeout: 90
    secrets:
      COPR_BETA_WEBHOOK_TOKEN: ${{ secrets.COPR_BETA_WEBHOOK_TOKEN }}
      COPR_STABLE_WEBHOOK_TOKEN: ${{ secrets.COPR_STABLE_WEBHOOK_TOKEN }}
      COPR_CLI_CONFIG: ${{ secrets.COPR_CLI_CONFIG }}

  release:
    name: Release
    if:
      github.event_name == 'release' &&
      startsWith(github.repository, 'LizardByte/') &&
      github.event.release.prerelease == true
    needs:
      - call-copr-ci
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          path: artifacts
          pattern: build-*
          merge-multiple: true

      - name: Debug artifacts
        run: ls -l artifacts

      - name: Update GitHub Release
        uses: LizardByte/actions/actions/release_create@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          allowUpdates: true
          body: ${{ github.event.release.body }}
          deleteOtherPreReleases: false
          generateReleaseNotes: false
          name: ${{ github.event.release.name }}
          prerelease: true
          tag: ${{ github.event.release.tag_name }}
          token: ${{ secrets.GITHUB_TOKEN }}  # use built-in token to avoid repeating workflow triggers
          virustotal_api_key: ${{ secrets.VIRUSTOTAL_API_KEY }}


================================================
FILE: .github/workflows/ci-flatpak.yml
================================================
---
name: CI-Flatpak
permissions: {}

on:
  workflow_call:
    inputs:
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string

jobs:
  build_linux_flatpak:
    name: ${{ matrix.arch }}
    env:
      APP_ID: dev.lizardbyte.app.Sunshine
      MATRIX_ARCH: ${{ matrix.arch }}
      NODE_VERSION: "20"
      PLATFORM_VERSION: "24.08"
    permissions:
      contents: read
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: x86_64
            runner: ubuntu-22.04
          - arch: aarch64
            runner: ubuntu-22.04-arm
    steps:
      - name: More space
        if: matrix.arch == 'x86_64'
        uses: LizardByte/actions/actions/more_space@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          analyze-space-savings: true
          clean-all: true

      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          submodules: recursive

      - name: Setup node
        id: node
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f  # v6.3.0
        with:
          node-version: ${{ env.NODE_VERSION }}

      - name: Install npm dependencies
        run: npm install --ignore-scripts --package-lock-only

      - name: Debug package-lock.json
        run: cat package-lock.json

      - name: Setup python
        id: python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405  # v6.2.0
        with:
          python-version: '3.14'

      - name: Setup Dependencies Linux Flatpak
        run: |
          python -m pip install ".[flatpak]"

          sudo apt-get update -y
          sudo apt-get install -y \
            cmake \
            flatpak

          sudo su "$(whoami)" -c "flatpak --user remote-add --if-not-exists flathub \
            https://flathub.org/repo/flathub.flatpakrepo
          "

          sudo su "$(whoami)" -c "flatpak --user install -y flathub \
            org.flatpak.Builder \
            org.freedesktop.Platform/${MATRIX_ARCH}/${PLATFORM_VERSION} \
            org.freedesktop.Sdk/${MATRIX_ARCH}/${PLATFORM_VERSION} \
            org.freedesktop.Sdk.Extension.node${NODE_VERSION}/${MATRIX_ARCH}/${PLATFORM_VERSION} \
          "

          flatpak run org.flatpak.Builder --version

      - name: flatpak node generator
        # https://github.com/flatpak/flatpak-builder-tools/blob/master/node/README.md
        run: flatpak-node-generator npm package-lock.json

      - name: Debug generated-sources.json
        run: cat generated-sources.json

      - name: flatpak pip generator
        # generates glad-dependencies.json for PyPI build-time dependencies (e.g. jinja2 for glad)
        run: |
          python \
            ./packaging/linux/flatpak/deps/flatpak-builder-tools/pip/flatpak-pip-generator.py \
            --runtime="org.freedesktop.Sdk//${PLATFORM_VERSION}" \
            --output glad-dependencies \
            --build-only \
            --requirements-file=./third-party/glad/requirements.txt

          # Copy generated pip sources into build dir alongside the manifest
          cp glad-dependencies.json build/

      - name: Cache Flatpak build
        uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7  # v5.0.4
        with:
          path: ./build/.flatpak-builder
          key: flatpak-${{ matrix.arch }}-${{ github.sha }}
          restore-keys: |
            flatpak-${{ matrix.arch }}-

      - name: Configure Flatpak Manifest
        env:
          INPUT_RELEASE_VERSION: ${{ inputs.release_version }}
          INPUT_RELEASE_COMMIT: ${{ inputs.release_commit }}
          REPOSITORY_CLONE_URL: ${{ github.event.repository.clone_url }}
        run: |
          # variables for manifest
          branch="${GITHUB_REF}"
          build_version="${INPUT_RELEASE_VERSION}"
          commit="${INPUT_RELEASE_COMMIT}"
          clone_url="${REPOSITORY_CLONE_URL}"

          if [ "${GITHUB_EVENT_NAME}" == "push" ]; then
            echo "This is a PUSH event"
            branch="${GITHUB_REF_NAME}"
          fi

          echo "Branch: ${branch}"
          echo "Commit: ${commit}"
          echo "Clone URL: ${clone_url}"

          export BRANCH=${branch}
          export BUILD_VERSION=${build_version}
          export CLONE_URL=${clone_url}
          export COMMIT=${commit}

          mkdir -p build
          mkdir -p artifacts

          cmake -DGITHUB_CLONE_URL="${clone_url}" \
            -B build \
            -S . \
            -DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \
            -DSUNSHINE_CONFIGURE_ONLY=ON

      - name: Debug Manifest
        working-directory: build
        run: cat "${APP_ID}.yml"

      - name: Build Linux Flatpak
        working-directory: build
        run: |
          echo "::add-matcher::.github/matchers/gcc-strip3.json"
          sudo su "$(whoami)" -c "flatpak run org.flatpak.Builder \
            --arch=${MATRIX_ARCH} \
            --force-clean \
            --repo=repo \
            --sandbox \
            --stop-at=cuda build-sunshine ${APP_ID}.yml"
          cp -r .flatpak-builder copy-of-flatpak-builder
          sudo su "$(whoami)" -c "flatpak run org.flatpak.Builder \
            --arch=${MATRIX_ARCH} \
            --force-clean \
            --repo=repo \
            --sandbox \
            build-sunshine ${APP_ID}.yml"
          rm -rf .flatpak-builder
          mv copy-of-flatpak-builder .flatpak-builder
          sudo su "$(whoami)" -c "flatpak build-bundle \
            --arch=${MATRIX_ARCH} \
            ./repo \
            ../artifacts/sunshine_${MATRIX_ARCH}.flatpak ${APP_ID}"
          sudo su "$(whoami)" -c "flatpak build-bundle \
            --runtime \
            --arch=${MATRIX_ARCH} \
            ./repo \
            ../artifacts/sunshine_debug_${MATRIX_ARCH}.flatpak ${APP_ID}.Debug"
          echo "::remove-matcher owner=gcc-strip3::"

      - name: Lint Flatpak
        working-directory: build
        run: |
          exceptions_file="${GITHUB_WORKSPACE}/packaging/linux/flatpak/exceptions.json"

          echo "Linting flatpak manifest"
          flatpak run --command=flatpak-builder-lint org.flatpak.Builder \
            --exceptions \
            --user-exceptions "${exceptions_file}" \
            manifest \
            "${APP_ID}.yml"

          echo "Linting flatpak repo"
          # TODO: add arg
          # --mirror-screenshots-url=https://dl.flathub.org/media \
          flatpak run --command=flatpak-builder-lint org.flatpak.Builder \
            --exceptions \
            --user-exceptions "${exceptions_file}" \
            repo \
            repo

      - name: Package Flathub repo archive
        # copy files required to generate the Flathub repo
        if: matrix.arch == 'x86_64'
        run: |
          mkdir -p flathub/modules
          cp "./build/generated-sources.json" "./flathub/"
          cp "./build/glad-dependencies.json" "./flathub/"
          cp "./build/package-lock.json" "./flathub/"
          cp "./build/${APP_ID}.yml" "./flathub/"
          cp "./build/${APP_ID}.metainfo.xml" "./flathub/"
          cp "./packaging/linux/flatpak/README.md" "./flathub/"
          cp "./packaging/linux/flatpak/flathub.json" "./flathub/"
          cp -r "./packaging/linux/flatpak/modules/." "./flathub/modules/"
          # submodules will need to be handled in the workflow that creates the PR

          # create the archive
          tar -czf ./artifacts/flathub.tar.gz -C ./flathub .

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-Linux-Flatpak-${{ matrix.arch }}
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-freebsd.yml
================================================
---
name: CI-FreeBSD
permissions: {}

on:
  workflow_call:
    inputs:
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string

env:
  BRANCH: ${{ github.head_ref || github.ref_name }}
  BUILD_VERSION: ${{ inputs.release_version }}
  COMMIT: ${{ inputs.release_commit }}
  FREEBSD_CLANG_VERSION: 19

jobs:
  setup-matrix:
    name: Setup Build Matrix
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.generate-matrix.outputs.matrix }}
    permissions: {}
    steps:
      - name: Generate Matrix
        id: generate-matrix
        shell: bash
        run: |
          # Base matrix with amd64 build
          matrix='{
            "include": [
              {
                "bsd_release": "14.3",
                "arch": "x86_64",
                "cmake_processor": "amd64",
                "runner": "ubuntu-latest"
              }
            ]
          }'

          # Add aarch64 build only if not a pull request event
          if [[ "${{ github.event_name }}" != "pull_request" ]]; then
            matrix=$(echo "$matrix" | jq '.include += [{
              "bsd_release": "14.3",
              "arch": "aarch64",
              "cmake_processor": "aarch64",
              "runner": "ubuntu-latest"
            }]')
          fi

          # Use heredoc for multiline JSON output
          {
            echo "matrix<<EOF"
            echo "$matrix"
            echo "EOF"
          } >> "${GITHUB_OUTPUT}"

          echo "Generated matrix:"
          echo "$matrix" | jq .

  build_freebsd:
    name: ${{ matrix.cmake_processor }}-${{ matrix.bsd_release }}
    runs-on: ubuntu-latest
    needs: setup-matrix
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup-matrix.outputs.matrix) }}
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          submodules: recursive

      - name: Get Processor Count
        id: processor_count
        shell: bash
        run: |
          PROCESSOR_COUNT=$(nproc)
          echo "PROCESSOR_COUNT=${PROCESSOR_COUNT}" >> "${GITHUB_OUTPUT}"
          echo "PROCESSOR_COUNT: $PROCESSOR_COUNT"

      - name: Setup FreeBSD
        uses: vmactions/freebsd-vm@4807432c7cab1c3f97688665332c0b932062d31f  # v1.4.3
        with:
          arch: ${{ matrix.arch }}
          cpu: ${{ steps.processor_count.outputs.PROCESSOR_COUNT }}
          envs: 'BRANCH BUILD_VERSION COMMIT'
          # TODO: there is no libcap for freebsd... we need graphics/libdrm if we find a way to use libcap
          # TODO: docs are off because doxygen is too old: https://www.freshports.org/devel/doxygen/ must be >= 1.10
          prepare: |
            set -e

            pkg update
            pkg upgrade -y
            pkg install -y \
              audio/opus \
              audio/pulseaudio \
              devel/boost-all \
              devel/cmake-core \
              devel/evdev-proto \
              devel/git \
              devel/libayatana-appindicator \
              devel/libevdev \
              devel/libnotify \
              devel/llvm${{ env.FREEBSD_CLANG_VERSION }} \
              devel/ninja \
              devel/pkgconf \
              ftp/curl \
              graphics/libdrm \
              graphics/wayland \
              lang/python314 \
              multimedia/libva \
              multimedia/pipewire \
              net/miniupnpc \
              ports-mgmt/pkg \
              security/openssl \
              shells/bash \
              www/npm \
              x11/libX11 \
              x11/libxcb \
              x11/libXfixes \
              x11/libXrandr \
              x11/libXtst \
              x11-servers/xorg-server

            # create symlink for shebang bash compatibility
            ln -s /usr/local/bin/bash /bin/bash

            # setup python
            ln -s /usr/local/bin/python3.14 /usr/local/bin/python
            python -m ensurepip
          release: ${{ matrix.bsd_release }}
          run: |
            set -e
            # install glad deps and gcvor
            python -m pip install ".[glad,test]"

            # fix git safe.directory issues
            git config --global --add safe.directory "*"
          sync: nfs  # sshfs is used for build-deps; however it's much slower than nfs

      - name: Configure
        shell: freebsd {0}
        run: |
          set -e
          cd "${GITHUB_WORKSPACE}"

          cc_path="$(which clang${{ env.FREEBSD_CLANG_VERSION }})"
          cxx_path="$(which clang++${{ env.FREEBSD_CLANG_VERSION }})"

          export CC="${cc_path}"
          export CXX="${cxx_path}"

          mkdir -p build
          cmake \
            -B build \
            -G Ninja \
            -S . \
            -DBUILD_DOCS=OFF \
            -DBUILD_WERROR=OFF \
            -DCMAKE_BUILD_TYPE=Release \
            -DCMAKE_INSTALL_PREFIX=/usr/local \
            -DSUNSHINE_ASSETS_DIR=share/assets \
            -DSUNSHINE_EXECUTABLE_PATH=/usr/local/bin/sunshine \
            -DSUNSHINE_ENABLE_CUDA=OFF \
            -DSUNSHINE_ENABLE_DRM=OFF \
            -DSUNSHINE_ENABLE_PORTAL=ON \
            -DSUNSHINE_ENABLE_WAYLAND=ON \
            -DSUNSHINE_ENABLE_X11=ON \
            -DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
            -DSUNSHINE_PUBLISHER_WEBSITE="https://app.lizardbyte.dev" \
            -DSUNSHINE_PUBLISHER_ISSUE_URL="https://app.lizardbyte.dev/support"

      - name: Build
        shell: freebsd {0}
        run: |
          set -e
          cd "${GITHUB_WORKSPACE}"
          ninja -C build

      - name: Package
        shell: freebsd {0}
        run: |
          set -e
          cd "${GITHUB_WORKSPACE}"

          mkdir -p artifacts

          cd build
          cpack -G FREEBSD

          # move compiled files to artifacts
          mv ./cpack_artifacts/Sunshine.pkg \
            ../artifacts/Sunshine-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}.pkg

      - name: Debug
        if: always()
        shell: bash
        working-directory: build/cpack_artifacts/_CPack_Packages/FreeBSD/FREEBSD/Sunshine
        run: |
          echo "FreeBSD CPack Debug"
          echo "===== Staging Directory Contents ====="
          ls -la
          echo ""
          echo "===== +MANIFEST Content ====="
          cat +MANIFEST
          echo ""

          # use tar to print the contents of the pkg
          cd "${GITHUB_WORKSPACE}/artifacts"
          echo "===== Package Contents ====="
          tar -tvf Sunshine-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}.pkg
          echo ""
          echo "===== Package Statistics ====="
          echo -n "Total files in package: "
          tar -tf Sunshine-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}.pkg 2>&1 | wc -l
          echo ""
          echo "Package file size:"
          ls -lh Sunshine-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}.pkg

      - name: Test
        id: test
        shell: freebsd {0}
        run: |
          set -e
          cd "${GITHUB_WORKSPACE}/build/tests"

          export DISPLAY=:1
          Xvfb ${DISPLAY} -screen 0 1024x768x24 &
          XVFB_PID=$!

          ./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml

          kill ${XVFB_PID}

      - name: Generate gcov report
        id: test_report
        # any except canceled or skipped
        if: >-
          always() &&
          (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
        shell: freebsd {0}
        run: |
          cd "${GITHUB_WORKSPACE}/build"
          python -m gcovr . -r ../src \
            --exclude-noncode-lines \
            --exclude-throw-branches \
            --exclude-unreachable-branches \
            --verbose \
            --xml-pretty \
            -o coverage.xml

      - name: Upload coverage artifact
        if: >-
          always() &&
          (steps.test_report.outcome == 'success')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}
          path: |
            build/coverage.xml
            build/tests/test_results.xml
          if-no-files-found: error

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-FreeBSD-${{ matrix.bsd_release }}-${{ matrix.cmake_processor }}
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-homebrew.yml
================================================
---
name: CI-Homebrew
permissions: {}

on:
  workflow_call:
    inputs:
      git_username:
        required: true
        type: string
      publish_release:
        required: true
        type: string
      release_commit:
        required: true
        type: string
      release_tag:
        required: true
        type: string
      release_version:
        required: true
        type: string
    secrets:
      GH_TOKEN:
        required: true
      GIT_EMAIL:
        required: true

jobs:
  build_homebrew:
    name: ${{ matrix.os_name }}-${{ matrix.os_version }}${{ matrix.release == true && ' (Release)' || '' }}
    permissions:
      contents: read
    runs-on: ${{ matrix.os_name }}-${{ matrix.os_version }}
    strategy:
      fail-fast: false
      matrix:
        include:
          # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
          # while GitHub has larger macOS runners, they are not available for our repos :(
          - os_name: "macos"
            os_version: "14"
          - os_name: "macos"
            os_version: "15"
          - os_name: "macos"
            os_version: "26"
          - os_name: "ubuntu"
            os_version: "22.04"
          - os_name: "ubuntu"
            os_version: "latest"
            release: true  # this job will only configure the formula for release, no validation
    steps:
      - name: More space
        if: runner.os == 'Linux'
        uses: LizardByte/actions/actions/more_space@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          analyze-space-savings: true
          clean-all: true
          safe-packages: brew

      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Configure formula
        env:
          INPUT_RELEASE_VERSION: ${{ inputs.release_version }}
          INPUT_RELEASE_COMMIT: ${{ inputs.release_commit }}
          INPUT_RELEASE_TAG: ${{ inputs.release_tag }}
          MATRIX_RELEASE: ${{ matrix.release }}
          PR_CLONE_URL: ${{ github.event.pull_request.head.repo.clone_url }}
          PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
          PR_DEFAULT_BRANCH: ${{ github.event.pull_request.head.repo.default_branch }}
          REPOSITORY_CLONE_URL: ${{ github.event.repository.clone_url }}
          REPOSITORY_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
        run: |
          # variables for formula
          branch="${GITHUB_HEAD_REF}"
          build_version="${INPUT_RELEASE_VERSION}"
          clone_url="${REPOSITORY_CLONE_URL}"
          commit="${INPUT_RELEASE_COMMIT}"
          default_branch="${REPOSITORY_DEFAULT_BRANCH}"
          tag="${GITHUB_REF_NAME}"

          if [ "${GITHUB_EVENT_NAME}" == "push" ]; then
            echo "This is a PUSH event"
            if [ "${MATRIX_RELEASE}" == "true" ]; then
              # we will publish the formula with the release tag
              tag="${INPUT_RELEASE_TAG}"
            fi
          elif [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then
            echo "This is a PR event"
            clone_url=${PR_CLONE_URL}
            branch="${PR_HEAD_REF}"
            default_branch="${PR_DEFAULT_BRANCH}"
            tag="${PR_HEAD_REF}"
          fi

          echo "Branch: ${branch}"
          echo "Clone URL: ${clone_url}"
          echo "Tag: ${tag}"

          export BRANCH=${branch}
          export BUILD_VERSION=${build_version}
          export CLONE_URL=${clone_url}
          export COMMIT=${commit}
          export TAG=${tag}

          mkdir -p build
          cmake \
            -B build \
            -S . \
            -DGITHUB_DEFAULT_BRANCH="${default_branch}" \
            -DSUNSHINE_CONFIGURE_HOMEBREW=ON \
            -DSUNSHINE_CONFIGURE_ONLY=ON

          # copy formula to artifacts
          mkdir -p homebrew
          cp -f ./build/sunshine.rb ./homebrew/sunshine.rb

          # testing
          cat ./homebrew/sunshine.rb

      - name: Upload Artifacts
        if: matrix.release
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-Homebrew
          path: homebrew/
          if-no-files-found: error

      - name: Setup Xvfb
        if: matrix.release != true && runner.os == 'Linux'
        run: |
          sudo apt-get update -y
          sudo apt-get install -y \
            xvfb

          export DISPLAY=:1
          Xvfb ${DISPLAY} -screen 0 1024x768x24 &

          echo "DISPLAY=${DISPLAY}" >> "${GITHUB_ENV}"

      - run: echo "::add-matcher::.github/matchers/gcc-strip3.json"
      - name: Validate Homebrew Formula
        id: test
        if: matrix.release != true
        uses: LizardByte/actions/actions/release_homebrew@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          actionlint_config: "---\n# empty config"
          formula_file: ${{ github.workspace }}/homebrew/sunshine.rb
          git_email: ${{ secrets.GIT_EMAIL }}
          git_username: ${{ inputs.git_username }}
          publish: false
          token: ${{ secrets.GH_TOKEN }}
          validate: true
      - run: echo "::remove-matcher owner=gcc-strip3::"

      - name: Upload coverage artifact
        if: >-
          always() &&
          matrix.release != true &&
          (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-Homebrew-${{ matrix.os_name }}-${{ matrix.os_version }}
          path: |
            ${{ steps.test.outputs.testpath }}/coverage.xml
            ${{ steps.test.outputs.testpath }}/tests/test_results.xml
          if-no-files-found: error

      - name: Patch homebrew formula
        # create beta version of the formula
        # don't run this on macOS, as the sed command fails
        if: matrix.release
        run: |
          # variables
          formula_file="homebrew/sunshine-beta.rb"

          # rename the file
          mv homebrew/sunshine.rb $formula_file

          # update the formula
          sed -i 's/class Sunshine < Formula/class SunshineBeta < Formula/' $formula_file
          sed -i 's/conflicts_with "sunshine-beta"/conflicts_with "sunshine"/' $formula_file
          sed -i '/^  version .*$/d' $formula_file

          # update livecheck to check for latest stable or pre-release
          # shellcheck disable=SC1004
          sed -i '/strategy :github_latest do |json, regex|/,/^    end$/c\
              strategy :github_releases do |json, regex|\
                json.map do |release|\
                  next if release["draft"]\
          \
                  match = release["tag_name"]&.match(regex)\
                  next if match.blank?\
          \
                  match[1]\
                end\
              end' $formula_file

          # print new file
          echo "New formula:"
          cat $formula_file

      - name: Upload Artifacts (Beta)
        if: matrix.release
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: beta-Homebrew
          path: homebrew/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-linux.yml
================================================
---
name: CI-Linux
permissions: {}

on:
  workflow_call:
    inputs:
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string

jobs:
  build_linux:
    name: ${{ matrix.name }}
    env:
      APP_ID: dev.lizardbyte.app.Sunshine
      VERSION: ${{ inputs.release_version }}
    permissions:
      contents: read
    runs-on: ubuntu-${{ matrix.dist }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: AppImage
            EXTRA_ARGS: '--appimage-build'
            dist: 22.04
    steps:
      - name: More space
        uses: LizardByte/actions/actions/more_space@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          analyze-space-savings: true
          clean-all: true

      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          submodules: recursive

      - name: Setup Dependencies Linux
        timeout-minutes: 5
        run: |
          # create the artifacts directory
          mkdir -p artifacts

          # allow libfuse2 for appimage on 22.04+
          sudo add-apt-repository universe

          sudo apt-get install -y \
            libdrm-dev \
            libfuse2 \
            libgl-dev \
            libwayland-dev \
            libx11-xcb-dev \
            libxcb-dri3-dev \
            libxfixes-dev

      - name: Build latest libva
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        timeout-minutes: 5
        run: |
          gh release download --archive=tar.gz --repo=intel/libva
          tar xzf libva-*.tar.gz && rm libva-*.tar.gz
          cd libva-*
          ./autogen.sh --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu \
            --enable-drm \
            --enable-x11 \
            --enable-glx \
            --enable-wayland \
            --without-legacy
          make -j "$(nproc)"
          sudo make install
          cd .. && rm -rf libva-*

      - name: Build Linux
        env:
          BRANCH: ${{ github.head_ref || github.ref_name }}
          BUILD_VERSION: ${{ inputs.release_version }}
          COMMIT: ${{ inputs.release_commit }}
        run: |
          chmod +x ./scripts/linux_build.sh
          echo "::add-matcher::.github/matchers/gcc.json"
          ./scripts/linux_build.sh \
            --publisher-name="${GITHUB_REPOSITORY_OWNER}" \
            --publisher-website="https://app.lizardbyte.dev" \
            --publisher-issue-url="https://app.lizardbyte.dev/support" \
            --skip-cleanup \
            --skip-package \
            --ubuntu-test-repo ${{ matrix.EXTRA_ARGS }}
          echo "::remove-matcher owner=gcc::"

      - name: Package Linux - AppImage
        if: matrix.name == 'AppImage'
        working-directory: build
        run: |
          # install sunshine to the DESTDIR
          DESTDIR=AppDir ninja install

          # custom AppRun file
          cp -f ../packaging/linux/AppImage/AppRun ./AppDir/
          chmod +x ./AppDir/AppRun

          # variables
          DESKTOP_FILE="${DESKTOP_FILE:-${APP_ID}.desktop}"
          ICON_FILE="${ICON_FILE:-sunshine.png}"

          # AppImage
          # https://docs.appimage.org/packaging-guide/index.html
          wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
          chmod +x linuxdeploy-x86_64.AppImage

          # https://github.com/linuxdeploy/linuxdeploy-plugin-gtk
          sudo apt-get install libgtk-3-dev librsvg2-dev -y
          wget -q https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh
          chmod +x linuxdeploy-plugin-gtk.sh
          export DEPLOY_GTK_VERSION=3

          ./linuxdeploy-x86_64.AppImage \
            --appdir ./AppDir \
            --plugin gtk \
            --executable ./sunshine \
            --icon-file "../$ICON_FILE" \
            --desktop-file "./$DESKTOP_FILE" \
            --output appimage

          # move
          mv Sunshine*.AppImage ../artifacts/sunshine.AppImage

          # permissions
          chmod +x ../artifacts/sunshine.AppImage

      - name: Delete CUDA
        # free up space on the runner
        run: |
          rm -rf ./build/cuda

      - name: Verify AppImage
        if: matrix.name == 'AppImage'
        run: |
          wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage
          chmod +x appimagelint-x86_64.AppImage

          ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage

      - name: Install test deps
        run: |
          sudo apt-get update -y
          sudo apt-get install -y \
            x11-xserver-utils \
            xvfb

          # clean apt cache
          sudo apt-get clean
          sudo rm -rf /var/lib/apt/lists/*

      - name: Setup python
        id: python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405  # v6.2.0
        with:
          python-version: '3.14'

      - name: Run tests
        id: test
        working-directory: build/tests
        run: |
          export DISPLAY=:1
          Xvfb ${DISPLAY} -screen 0 1024x768x24 &
          sleep 5  # give Xvfb time to start

          ./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml

      - name: Generate gcov report
        id: test_report
        # any except canceled or skipped
        if: >-
          always() &&
          (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
        working-directory: build
        run: |
          ${{ steps.python.outputs.python-path }} -m pip install "..[test]"
          ${{ steps.python.outputs.python-path }} -m gcovr --gcov-executable "gcov-${GCC_VERSION}" . -r ../src \
            --exclude-noncode-lines \
            --exclude-throw-branches \
            --exclude-unreachable-branches \
            --verbose \
            --xml-pretty \
            -o coverage.xml

      - name: Upload coverage artifact
        if: >-
          always() &&
          (steps.test_report.outcome == 'success')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-Linux-${{ matrix.name }}
          path: |
            build/coverage.xml
            build/tests/test_results.xml
          if-no-files-found: error

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-Linux-${{ matrix.name }}
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-macos.yml
================================================
---
name: CI-macOS
permissions: {}

on:
  workflow_call:
    inputs:
      publish_release:
        required: true
        type: string
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string
    secrets:
      # email address
      APPLE_ID:
        required: false
      # 10-character Team ID
      APPLE_TEAM_ID:
        required: false
      # app-specific password in APPLE_ID's account that must be named "notarytool"
      # https://support.apple.com/en-us/102654
      APPLE_NOTARYTOOL_PASSWORD:
        required: false
      # Developer ID Application: Full Name (TEAMIDHERE)
      APPLE_CODESIGN_IDENTITY:
        required: false
      # pkcs12 export from Xcode in base64
      APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64:
        required: false
      # pkcs12 password added by Xcode export
      APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD:
        required: false

env:
  BRANCH: ${{ github.head_ref || github.ref_name }}
  BUILD_VERSION: ${{ inputs.release_version }}
  COMMIT: ${{ inputs.release_commit }}

jobs:
  build_dmg:
    name: ${{ matrix.name }}
    permissions:
      contents: read
    runs-on: ${{ matrix.os }}
    outputs:
      notarytool_submission_id_arm64: ${{ steps.notarize_submit.outputs.submission_id_arm64 }}
      notarytool_submission_id_x86_64: ${{ steps.notarize_submit.outputs.submission_id_x86_64 }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: "macos-14"
            name: "macOS-arm64"
            arch: "arm64"
          - os: "macos-15-intel"
            name: "macOS-x86_64"
            arch: "x86_64"
    steps:
      - name: Install Apple certificate
        uses: apple-actions/import-codesign-certs@fe74d46e82474f87e1ba79832ad28a4013d0e33a  # v6.1.0
        if: inputs.publish_release == 'true'
        with:
          p12-file-base64: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
          p12-password: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}

      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          submodules: recursive

      - name: Install dependencies
        timeout-minutes: 5
        run: |
          brew install --force \
            cmake \
            doxygen \
            graphviz \
            node \
            pkgconf \
            icu4c@78 \
            miniupnpc \
            openssl@3 \
            opus

      - name: Configure
        env:
          APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
        run: |
          mkdir -p build
          cmake \
            -B build \
            -S . \
            -DBUILD_WERROR=ON \
            -DCMAKE_BUILD_TYPE=Release \
            -DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3 2>/dev/null)" \
            -DOpus_ROOT_DIR="$(brew --prefix opus 2>/dev/null)" \
            -DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
            -DSUNSHINE_PUBLISHER_WEBSITE="https://app.lizardbyte.dev" \
            -DSUNSHINE_PUBLISHER_ISSUE_URL="https://app.lizardbyte.dev/support" \
            -DAPPLE_CODESIGN_IDENTITY="${APPLE_CODESIGN_IDENTITY}"

      - name: Build
        run: |
          echo "::add-matcher::.github/matchers/gcc.json"
          cmake --build build -j "$(sysctl -n hw.ncpu)"
          echo "::remove-matcher owner=gcc::"

      - name: Package DMG
        env:
          APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
          MATRIX_NAME: ${{ matrix.name }}
          SHOULD_SIGN: ${{ inputs.publish_release }}
        run: |
          # build DMG and sign everything (see cmake/packaging/macos.cmake)
          # cpack can rarely fail with "hdiutil: create failed - Resource busy"
          # so let's allow 1 retry
          if ! cpack -G DragNDrop --config build/CPackConfig.cmake; then
            echo "cpack failed, retrying once with verbose..."
            if ! cpack -G DragNDrop --config build/CPackConfig.cmake --verbose; then
              echo "cpack failed again. Aborting."
              exit 1
            fi
          fi

          mkdir -p artifacts
          cp "build/cpack_artifacts/Sunshine.dmg" "artifacts/Sunshine-${MATRIX_NAME}.dmg"

      - name: Submit for notarization
        id: notarize_submit
        if: inputs.publish_release == 'true'
        env:
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          APPLE_NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_NOTARYTOOL_PASSWORD }}
          MATRIX_ARCH: ${{ matrix.arch }}
        run: |
          # Notarizing allows the signed .app to run on any Mac with no prompts.
          # If you don't notarize, users must jump through the "Open Anyway" hoop as well as run
          # `xattr -cr /Applications/Sunshine.app` to remove quarantine.
          if [[ -n "${APPLE_NOTARYTOOL_PASSWORD}" ]]; then
            submission_id=$(xcrun notarytool submit build/cpack_artifacts/Sunshine.dmg \
              --apple-id "${APPLE_ID}" \
              --team-id "${APPLE_TEAM_ID}" \
              --password "${APPLE_NOTARYTOOL_PASSWORD}" \
              --output-format json \
              | jq -r '.id')
            echo "Submission ID: ${submission_id}"
            echo "submission_id_${MATRIX_ARCH}=${submission_id}" >> "${GITHUB_OUTPUT}"
          fi

      - name: Test
        id: test
        working-directory: build/tests
        run: ./test_sunshine --gtest_color=yes --gtest_output=xml:test_results.xml

      - name: Generate gcov report
        id: test_report
        # any except canceled or skipped
        if: >-
          always() &&
          (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
        working-directory: build
        run: |
          python -m pip install "..[test]"
          python -m gcovr . -r ../src \
            --exclude-noncode-lines \
            --exclude-throw-branches \
            --exclude-unreachable-branches \
            --xml-pretty \
            -j "$(sysctl -n hw.ncpu)" \
            -o coverage.xml

      - name: Upload coverage artifact
        if: >-
          always() &&
          (steps.test_report.outcome == 'success')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-${{ matrix.name }}
          path: |
            build/coverage.xml
            build/tests/test_results.xml
          if-no-files-found: error

      - name: Set artifact prefix
        id: artifact_prefix
        env:
          INPUTS_PUBLISH_RELEASE: ${{ inputs.publish_release }}
        run: |
          if [[ "${INPUTS_PUBLISH_RELEASE}" == "true" ]]; then
            echo "prefix=unsigned" >> "${GITHUB_OUTPUT}"
          else
            echo "prefix=build" >> "${GITHUB_OUTPUT}"
          fi

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: ${{ steps.artifact_prefix.outputs.prefix }}-${{ matrix.name }}
          path: artifacts/
          if-no-files-found: error

  notarize_dmg:
    name: Notarize ${{ matrix.name }}
    needs: build_dmg
    if: inputs.publish_release == 'true'
    permissions:
      contents: read
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: "macos-14"
            name: "macOS-arm64"
            arch: "arm64"
          - os: "macos-15-intel"
            name: "macOS-x86_64"
            arch: "x86_64"
    steps:
      - name: Install Apple certificate
        uses: apple-actions/import-codesign-certs@fe74d46e82474f87e1ba79832ad28a4013d0e33a  # v6.1.0
        with:
          p12-file-base64: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
          p12-password: ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}

      - name: Download DMG artifact
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          name: unsigned-${{ matrix.name }}
          path: artifacts

      - name: Wait for notarization and staple
        env:
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          APPLE_NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_NOTARYTOOL_PASSWORD }}
          MATRIX_NAME: ${{ matrix.name }}
          SUBMISSION_ID: ${{ matrix.arch == 'arm64'
            && needs.build_dmg.outputs.notarytool_submission_id_arm64
            || needs.build_dmg.outputs.notarytool_submission_id_x86_64 }}
        run: |
          if [[ -z "${SUBMISSION_ID}" ]]; then
            echo "No submission ID found; skipping notarization wait."
            exit 0
          fi

          echo "Polling notarization status for submission: ${SUBMISSION_ID}"
          while true; do
            status=$(xcrun notarytool info "${SUBMISSION_ID}" \
              --apple-id "${APPLE_ID}" \
              --team-id "${APPLE_TEAM_ID}" \
              --password "${APPLE_NOTARYTOOL_PASSWORD}" \
              --output-format json \
              | jq -r '.status')
            echo "Current status: ${status}"
            if [[ "${status}" == "Accepted" ]]; then
              echo "Notarization accepted."
              break
            elif [[ "${status}" == "Invalid" || "${status}" == "Rejected" ]]; then
              echo "Notarization failed with status: ${status}"
              # Print the full log for debugging
              xcrun notarytool log "${SUBMISSION_ID}" \
                --apple-id "${APPLE_ID}" \
                --team-id "${APPLE_TEAM_ID}" \
                --password "${APPLE_NOTARYTOOL_PASSWORD}"
              exit 1
            fi
            echo "Status is '${status}', waiting 30 seconds before retrying..."
            sleep 30
          done

          xcrun stapler staple -v "artifacts/Sunshine-${MATRIX_NAME}.dmg"

      - name: Upload stapled artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-${{ matrix.name }}
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci-windows.yml
================================================
---
name: CI-Windows
permissions: {}

on:
  workflow_call:
    inputs:
      # Azure Artifact Signing account name
      azure_signing_account:
        required: false
        type: string
        default: ''
      # Azure Artifact Signing certificate profile name
      azure_signing_cert_profile:
        required: false
        type: string
        default: ''
      # Azure Artifact Signing account endpoint
      # e.g. https://<region>.codesigning.azure.net
      azure_signing_endpoint:
        required: false
        type: string
        default: ''
      publish_release:
        required: true
        type: string
      release_commit:
        required: true
        type: string
      release_version:
        required: true
        type: string
    secrets:
      # Azure Client ID (App Registration) for Artifact Signing
      AZURE_CLIENT_ID:
        required: false
      # Azure Client Secret for Artifact Signing
      AZURE_CLIENT_SECRET:
        required: false
      # Azure Tenant ID for Artifact Signing
      AZURE_TENANT_ID:
        required: false

jobs:
  build_windows:
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: msys2 {0}
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Windows-AMD64
            os: windows-2022
            arch: x86_64
            msystem: ucrt64
            toolchain: ucrt-x86_64
          - name: Windows-ARM64
            os: windows-11-arm
            arch: aarch64
            msystem: clangarm64
            toolchain: clang-aarch64
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          submodules: recursive

      - name: Setup Dependencies Windows
        # if a dependency needs to be pinned, see https://github.com/LizardByte/build-deps/pull/186
        uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda  # v2.30.0
        with:
          msystem: ${{ matrix.msystem }}
          update: true
          install: >-
            wget

      - name: Update Windows dependencies
        env:
          # MSYSTEM is a built-in environment variable of MSYS2.
          # Do not use this environment variable name.
          MATRIX_MSYSTEM: ${{ matrix.msystem }}
          TOOLCHAIN: ${{ matrix.toolchain }}
        shell: msys2 {0}
        run: |
          # variables
          declare -A pinned_deps

          # dependencies
          dependencies=(
            "git"
            "mingw-w64-${TOOLCHAIN}-boost"
            "mingw-w64-${TOOLCHAIN}-cmake"
            "mingw-w64-${TOOLCHAIN}-cppwinrt"
            "mingw-w64-${TOOLCHAIN}-curl-winssl"
            "mingw-w64-${TOOLCHAIN}-gcc"
            "mingw-w64-${TOOLCHAIN}-graphviz"
            "mingw-w64-${TOOLCHAIN}-miniupnpc"
            "mingw-w64-${TOOLCHAIN}-nlohmann-json"
            "mingw-w64-${TOOLCHAIN}-onevpl"
            "mingw-w64-${TOOLCHAIN}-openssl"
            "mingw-w64-${TOOLCHAIN}-opus"
            "mingw-w64-${TOOLCHAIN}-toolchain"
          )

          if [[ "${MATRIX_MSYSTEM}" == "ucrt64" ]]; then
            dependencies+=(
              "mingw-w64-${TOOLCHAIN}-MinHook"
              "mingw-w64-${TOOLCHAIN}-nsis"
              "mingw-w64-${TOOLCHAIN}-nodejs"
            )
          fi

          # do not modify below this line

          ignore_packages=()
          tarballs=""
          for pkg in "${!pinned_deps[@]}"; do
            ignore_packages+=("${pkg}")
            version="${pinned_deps[$pkg]}"
            tarball="${pkg}-${version}-any.pkg.tar.zst"

            # download working version
            wget "https://repo.msys2.org/mingw/${MATRIX_MSYSTEM}/${tarball}"

            tarballs="${tarballs} ${tarball}"
          done

          # Create the ignore string for pacman
          ignore_list=$(IFS=,; echo "${ignore_packages[*]}")

          # install pinned dependencies
          if [ -n "${tarballs}" ]; then
            pacman -U --noconfirm "${tarballs}"
          fi

          # Only add --ignore if we have packages to ignore
          if [ -n "${ignore_list}" ]; then
            pacman -Syu --noconfirm --ignore="${ignore_list}" "${dependencies[@]}"
          else
            pacman -Syu --noconfirm "${dependencies[@]}"
          fi

      - name: Install Doxygen
        # GCC compiled doxygen has issues when running graphviz
        env:
          DOXYGEN_VERSION: "1.11.0"
        shell: pwsh
        run: |
          # Set version variables
          $doxy_ver = $env:DOXYGEN_VERSION
          $_doxy_ver = $doxy_ver.Replace(".", "_")

          # Download the Doxygen installer
          Invoke-WebRequest -Uri `
            "https://github.com/doxygen/doxygen/releases/download/Release_${_doxy_ver}/doxygen-${doxy_ver}-setup.exe" `
            -OutFile "doxygen-setup.exe"

          # Run the installer
          Start-Process `
            -FilePath .\doxygen-setup.exe `
            -ArgumentList `
              '/VERYSILENT' `
          -Wait `
          -NoNewWindow

          # Clean up
          Remove-Item -Path doxygen-setup.exe

      - name: Setup dotnet  # needed for wix
        uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7  # v5.2.0
        with:
          dotnet-version: '10.x'

      - name: Setup NodeJS
        # Clang compiled NodeJS has issues when running rollup webpack
        if: matrix.msystem != 'ucrt64'
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f  # v6.3.0
        with:
          node-version: 'lts/*'

      - name: NodeJS Path
        if: matrix.msystem != 'ucrt64'
        shell: pwsh
        run: |
          # get NodeJS PATH
          $NODEJS_BINARY_PATH = (Get-Command node).Source
          $NODEJS_PATH = Split-Path -Path "$NODEJS_BINARY_PATH" -Parent

          # setup environment variables
          echo "NODEJS_PATH=$NODEJS_PATH" >> $env:GITHUB_ENV

          # step output
          echo "nodejs-path=$NODEJS_PATH"
          echo "nodejs-path=$NODEJS_PATH" >> $env:GITHUB_OUTPUT

      - name: Setup python
        id: setup-python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405  # v6.2.0
        with:
          python-version: '3.14'

      - name: Python Path
        id: python-path
        shell: msys2 {0}
        run: |
          # replace backslashes with double backslashes
          python_path=$(echo "${{ steps.setup-python.outputs.python-path }}" | sed 's/\\/\\\\/g')

          # step output
          echo "python-path=${python_path}"
          echo "python-path=${python_path}" >> "${GITHUB_OUTPUT}"

      - name: Build Windows
        shell: msys2 {0}
        env:
          # MSYSTEM is a built-in environment variable of MSYS2.
          # Do not use this environment variable name.
          MATRIX_MSYSTEM: ${{ matrix.msystem }}
          BRANCH: ${{ github.head_ref || github.ref_name }}
          BUILD_VERSION: ${{ inputs.release_version }}
          COMMIT: ${{ inputs.release_commit }}
        run: |
          # setup NodeJS PATH
          if [[ "${MATRIX_MSYSTEM}" != "ucrt64" ]]; then
            NODEJS_PATH=$(cygpath "$NODEJS_PATH")
            export PATH="$PATH:$NODEJS_PATH"
          fi

          mkdir -p build
          cmake \
            -B build \
            -G Ninja \
            -S . \
            -DBUILD_WERROR=ON \
            -DCMAKE_BUILD_TYPE=RelWithDebInfo \
            -DSUNSHINE_ASSETS_DIR=assets \
            -DSUNSHINE_PUBLISHER_NAME="${GITHUB_REPOSITORY_OWNER}" \
            -DSUNSHINE_PUBLISHER_WEBSITE="https://app.lizardbyte.dev" \
            -DSUNSHINE_PUBLISHER_ISSUE_URL="https://app.lizardbyte.dev/support"
          echo "::add-matcher::.github/matchers/gcc.json"
          ninja -C build
          echo "::remove-matcher owner=gcc::"

      - name: Sign Windows executables
        # ARM64 is not currently supported, see https://github.com/Azure/artifact-signing-action/issues/92
        if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' && matrix.name != 'Windows-ARM64'
        uses: azure/trusted-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346  # v1.1.0
        with:
          azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
          azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
          azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          certificate-profile-name: ${{ inputs.azure_signing_cert_profile }}
          endpoint: ${{ inputs.azure_signing_endpoint }}
          files: |
            ${{ github.workspace }}/build/sunshine.exe
            ${{ github.workspace }}/build/tools/audio-info.exe
            ${{ github.workspace }}/build/tools/dxgi-info.exe
            ${{ github.workspace }}/build/tools/sunshinesvc.exe
          files-folder: src_assets/windows
          files-folder-filter: ps1
          files-folder-recurse: true
          signing-account-name: ${{ inputs.azure_signing_account }}

      - name: Package Windows
        shell: msys2 {0}
        run: |
          mkdir -p artifacts
          cd build

          # package
          cpack -G NSIS
          cpack -G WIX
          cpack -G ZIP

          # move
          mv ./cpack_artifacts/Sunshine.exe ../artifacts/Sunshine-${{ matrix.name }}-installer.exe
          mv ./cpack_artifacts/Sunshine.msi ../artifacts/Sunshine-${{ matrix.name }}-installer.msi
          mv ./cpack_artifacts/Sunshine.zip ../artifacts/Sunshine-${{ matrix.name }}-portable.zip

      - name: Sign Windows installers
        # ARM64 is not currently supported, see https://github.com/Azure/artifact-signing-action/issues/92
        if: inputs.publish_release == 'true' && inputs.azure_signing_account != '' && matrix.name != 'Windows-ARM64'
        uses: azure/trusted-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346  # v1.1.0
        with:
          azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
          azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
          azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          certificate-profile-name: ${{ inputs.azure_signing_cert_profile }}
          endpoint: ${{ inputs.azure_signing_endpoint }}
          files-folder: artifacts
          files-folder-filter: exe,msi
          files-folder-recurse: false
          signing-account-name: ${{ inputs.azure_signing_account }}

      - name: Debug nsis
        if: always()
        shell: msys2 {0}
        run: cat ./build/cpack_artifacts/_CPack_Packages/win64/NSIS/NSISOutput.log || true

      - name: Debug wix
        if: always()
        shell: msys2 {0}
        run: cat ./build/cpack_artifacts/_CPack_Packages/win64/WIX/wix.log || true

      - name: Run tests
        id: test
        shell: msys2 {0}
        working-directory: build/tests
        run: ./test_sunshine.exe --gtest_color=yes --gtest_output=xml:test_results.xml

      - name: Generate gcov report
        id: test_report
        # any except canceled or skipped
        if: >-
          always() &&
          (steps.test.outcome == 'success' || steps.test.outcome == 'failure')
        shell: msys2 {0}
        working-directory: build
        run: |
          ${{ steps.python-path.outputs.python-path }} -m pip install "..[test]"
          ${{ steps.python-path.outputs.python-path }} -m gcovr . -r ../src \
            --exclude-noncode-lines \
            --exclude-throw-branches \
            --exclude-unreachable-branches \
            --verbose \
            --xml-pretty \
            -o coverage.xml

      - name: Upload coverage artifact
        if: >-
          always() &&
          (steps.test_report.outcome == 'success')
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: coverage-${{ matrix.name }}
          path: |
            build/coverage.xml
            build/tests/test_results.xml
          if-no-files-found: error

      - name: Package Windows Debug Info
        shell: pwsh
        working-directory: build
        run: |
          # use .dbg file extension for binaries to avoid confusion with real packages
          Get-ChildItem -File -Recurse | `
            % { Rename-Item -Path $_.PSPath -NewName $_.Name.Replace(".exe",".dbg") }

          # save the binaries with debug info
          7z -r `
            "-xr!CMakeFiles" `
            "-xr!cpack_artifacts" `
            a "../artifacts/Sunshine-${{ matrix.name }}-debuginfo.7z" "*.dbg"

      - name: Upload Artifacts
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: build-${{ matrix.name }}
          path: artifacts/
          if-no-files-found: error


================================================
FILE: .github/workflows/ci.yml
================================================
---
name: CI
permissions: {}

on:
  pull_request:
  push:
    branches:
      - master
  workflow_dispatch:

concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  github-env:
    name: GitHub Env Debug
    permissions:
      contents: read
    uses: LizardByte/.github/.github/workflows/__call-github-env.yml@master

  release-setup:
    name: Release Setup
    outputs:
      publish_release: ${{ steps.release-setup.outputs.publish_release }}
      release_body: ${{ steps.release-setup.outputs.release_body }}
      release_commit: ${{ steps.release-setup.outputs.release_commit }}
      release_generate_release_notes: ${{ steps.release-setup.outputs.release_generate_release_notes }}
      release_tag: ${{ steps.release-setup.outputs.release_tag }}
      release_version: ${{ steps.release-setup.outputs.release_version }}
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Release Setup
        id: release-setup
        uses: LizardByte/actions/actions/release_setup@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

  build-docker:
    name: Docker
    needs: release-setup
    permissions:
      contents: read
      packages: write
    uses: LizardByte/.github/.github/workflows/__call-docker.yml@master
    with:
      docker_hub_username: ${{ vars.DOCKER_HUB_USERNAME }}
      gh_bot_name: ${{ vars.GH_BOT_NAME }}
      maximize_build_space: true
      publish_release: ${{ needs.release-setup.outputs.publish_release }}
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_tag: ${{ needs.release-setup.outputs.release_tag }}
      release_version: ${{ needs.release-setup.outputs.release_version }}
    secrets:
      DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
      DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
      GH_BOT_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  build-freebsd:
    name: FreeBSD
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-freebsd.yml
    with:
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}

  build-homebrew:
    name: Homebrew
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-homebrew.yml
    with:
      git_username: ${{ vars.GH_BOT_NAME }}
      publish_release: ${{ needs.release-setup.outputs.publish_release }}
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_tag: ${{ needs.release-setup.outputs.release_tag }}
      release_version: ${{ needs.release-setup.outputs.release_version }}
    secrets:
      GH_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
      GIT_EMAIL: ${{ secrets.GH_BOT_EMAIL }}

  build-macos:
    name: macOS
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-macos.yml
    with:
      publish_release: ${{ needs.release-setup.outputs.publish_release }}
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}
    secrets:
      APPLE_ID: ${{ secrets.APPLE_ID }}
      APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
      APPLE_NOTARYTOOL_PASSWORD: ${{ secrets.APPLE_NOTARYTOOL_PASSWORD }}
      APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
      APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64: >-
        ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
      APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD: >-
        ${{ secrets.APPLE_DEVELOPER_ID_APPLICATION_CERTIFICATE_P12_PASSWORD }}

  build-linux:
    name: Linux
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-linux.yml
    with:
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}

  build-archlinux:
    name: Archlinux
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-archlinux.yml
    with:
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}

  build-linux-copr:
    name: Linux Copr
    if: github.event_name != 'push'  # releases are handled directly in ci-copr.yml
    needs: release-setup
    permissions:
      contents: write  # needed to update releases
    uses: ./.github/workflows/ci-copr.yml
    secrets:
      COPR_BETA_WEBHOOK_TOKEN: ${{ secrets.COPR_BETA_WEBHOOK_TOKEN }}
      COPR_STABLE_WEBHOOK_TOKEN: ${{ secrets.COPR_STABLE_WEBHOOK_TOKEN }}
      COPR_CLI_CONFIG: ${{ secrets.COPR_CLI_CONFIG }}

  build-linux-flatpak:
    name: Linux Flatpak
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-flatpak.yml
    with:
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}

  build-windows:
    name: Windows
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-windows.yml
    with:
      azure_signing_account: ${{ vars.AZURE_SIGNING_ACCOUNT }}
      azure_signing_cert_profile: ${{ vars.AZURE_SIGNING_CERT_PROFILE }}
      azure_signing_endpoint: ${{ vars.AZURE_SIGNING_ENDPOINT }}
      publish_release: ${{ needs.release-setup.outputs.publish_release }}
      release_commit: ${{ needs.release-setup.outputs.release_commit }}
      release_version: ${{ needs.release-setup.outputs.release_version }}
    secrets:
      AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
      AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
      AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}

  bundle-analysis:
    name: Bundle Analysis
    needs: release-setup
    permissions:
      contents: read
    uses: ./.github/workflows/ci-bundle.yml
    secrets:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

  coverage:
    name: Coverage-${{ matrix.name }}
    if: >-
      always() &&
      !cancelled() &&
      startsWith(github.repository, 'LizardByte/')
    needs:
      - build-freebsd
      - build-linux
      - build-archlinux
      - build-linux-flatpak
      - build-macos
      - build-homebrew
      - build-windows
    permissions:
      contents: read
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: FreeBSD-14.3-amd64
            coverage: true
            pr: true
          - name: FreeBSD-14.3-aarch64
            coverage: true
            pr: false
          - name: Linux-AppImage
            coverage: true
            pr: true
          - name: Archlinux
            coverage: true
            pr: true
          - name: macOS-arm64
            coverage: true
            pr: true
          - name: macOS-x86_64
            coverage: true
            pr: true
          - name: Homebrew-macos-14
            coverage: false
            pr: true
          - name: Homebrew-macos-15
            coverage: false
            pr: true
          - name: Homebrew-macos-26
            coverage: false
            pr: true
          - name: Homebrew-ubuntu-22.04
            coverage: true
            pr: true
          - name: Windows-AMD64
            coverage: true
            pr: true
          - name: Windows-ARM64
            coverage: true
            pr: true
    steps:
      - name: Should run
        id: should_run
        run: |
          should_run="false"
          if [ "${GITHUB_EVENT_NAME}" != "pull_request" ] || [ ${{ matrix.pr }} == "true" ]; then
            should_run="true"
          fi
          echo "SHOULD_RUN=${should_run}" >> "${GITHUB_OUTPUT}"

      - name: Checkout
        if: steps.should_run.outputs.SHOULD_RUN == 'true'
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Download coverage artifact
        if: steps.should_run.outputs.SHOULD_RUN == 'true'
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          name: coverage-${{ matrix.name }}
          path: _coverage

      - name: Upload test coverage
        if: |
          steps.should_run.outputs.SHOULD_RUN == 'true'  &&
          matrix.coverage != false
        uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad  # v5.5.3
        with:
          disable_search: true
          fail_ci_if_error: true
          files: ./_coverage/coverage.xml
          report_type: coverage
          flags: ${{ matrix.name }}
          token: ${{ secrets.CODECOV_TOKEN }}
          verbose: true

      - name: Upload test results
        if: steps.should_run.outputs.SHOULD_RUN == 'true'
        uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad  # v5.5.3
        with:
          disable_search: true
          fail_ci_if_error: true
          files: ./_coverage/tests/test_results.xml
          report_type: test_results
          flags: ${{ matrix.name }}
          token: ${{ secrets.CODECOV_TOKEN }}
          verbose: true

  release:
    name: Release
    if:
      needs.release-setup.outputs.publish_release == 'true' &&
      startsWith(github.repository, 'LizardByte/')
    needs:
      - release-setup
      - build-archlinux
      - build-docker
      - build-freebsd
      - build-homebrew
      - build-linux
      - build-linux-flatpak
      - build-macos
      - build-windows
    permissions:
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          path: artifacts
          pattern: build-*
          merge-multiple: true

      - name: Debug artifacts
        run: ls -l artifacts

      - name: Create/Update GitHub Release
        uses: LizardByte/actions/actions/release_create@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          allowUpdates: false
          body: ${{ needs.release-setup.outputs.release_body }}
          generateReleaseNotes: ${{ needs.release-setup.outputs.release_generate_release_notes }}
          name: ${{ needs.release-setup.outputs.release_tag }}
          prerelease: true
          tag: ${{ needs.release-setup.outputs.release_tag }}
          token: ${{ secrets.GH_BOT_TOKEN }}
          virustotal_api_key: ${{ secrets.VIRUSTOTAL_API_KEY }}

  release-homebrew-beta:
    name: Release Homebrew Beta
    if:
      needs.release-setup.outputs.publish_release == 'true' &&
      startsWith(github.repository, 'LizardByte/')
    needs:
      - release-setup
      - build-homebrew
      - release
    permissions:
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Download homebrew artifacts
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          name: beta-Homebrew
          path: homebrew

      - name: Upload Homebrew Beta Formula
        uses: LizardByte/actions/actions/release_homebrew@70bb8d394d1c92f6113aeec6ae9cc959a5763d15  # v2026.227.200013
        with:
          actionlint_config: "---\n# empty config"
          formula_file: ${{ github.workspace }}/homebrew/sunshine-beta.rb
          git_email: ${{ secrets.GH_BOT_EMAIL }}
          git_username: ${{ vars.GH_BOT_NAME }}
          publish: true
          token: ${{ secrets.GH_BOT_TOKEN }}
          validate: false


================================================
FILE: .github/workflows/localize.yml
================================================
---
name: localize
permissions: {}

on:
  push:
    branches:
      - master
    paths:
      - '.github/workflows/localize.yml'
      - 'src/**'
      - 'locale/sunshine.po'
  workflow_dispatch:

env:
  FILE: ./locale/sunshine.po

jobs:
  localize:
    name: Update Localization
    permissions:
      contents: read
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Install Python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405  # v6.2.0
        with:
          python-version: '3.14'

      - name: Set up Python Dependencies
        run: |
          python -m pip install --upgrade pip setuptools
          python -m pip install ".[locale]"

      - name: Set up xgettext
        run: |
          sudo apt-get update -y && \
          sudo apt-get --reinstall install -y \
          gettext

      - name: Update Strings
        run: |
          new_file=true

          # first, try to remove existing file as xgettext does not remove unused translations
          if [ -f "${FILE}" ];
          then
              rm "${FILE}"
              new_file=false
          fi
          echo "NEW_FILE=${new_file}" >> "${GITHUB_ENV}"

          # extract the new strings
          python ./scripts/_locale.py --extract

      - name: git diff
        if: env.NEW_FILE == 'false'
        run: |
          # disable the pager
          git config --global pager.diff false

          # print the git diff
          git diff locale/sunshine.po

          # set the variable with minimal output, replacing `\t` with ` `
          OUTPUT=$(git diff --numstat locale/sunshine.po | sed -e "s#\t# #g")
          echo "GIT_DIFF=${OUTPUT}" >> "${GITHUB_ENV}"

      - name: git reset
        # only run if a single line changed (date/time) and file already existed
        if: >-
          env.GIT_DIFF == '1 1 locale/sunshine.po' &&
          env.NEW_FILE == 'false'
        run: |
          git reset --hard

      - name: Get current date
        id: date
        run: echo "date=$(date +'%Y-%m-%d')" >> "${GITHUB_OUTPUT}"

      - name: Create/Update Pull Request
        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0  # v8.1.0
        with:
          add-paths: |
            locale/*.po
          token: ${{ secrets.GH_BOT_TOKEN }}  # must trigger PR tests
          commit-message: "chore(l10n): new babel updates"
          branch: localize/update
          delete-branch: true
          base: master
          title: "chore(l10n): new babel updates"
          body: |
            Update report
            - Updated ${{ steps.date.outputs.date }}
            - Auto-generated by [create-pull-request][1]

            [1]: https://github.com/peter-evans/create-pull-request
          labels: |
            babel
            l10n


================================================
FILE: .github/workflows/release-notifier-moonlight.yml
================================================
---
name: Release Notifications (Moonlight)
permissions: {}

on:
  release:
    types:
      - released  # this triggers when a release is published, but does not include prereleases or drafts

jobs:
  discord:
    if: github.repository_owner == 'LizardByte'
    runs-on: ubuntu-latest
    permissions: {}
    steps:
      - name: Check if latest GitHub release
        id: check-release
        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd  # v8.0.0
        with:
          script: |
            const latestRelease = await github.rest.repos.getLatestRelease({
              owner: context.repo.owner,
              repo: context.repo.repo
            });

            core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name);

      - name: discord
        if: steps.check-release.outputs.isLatestRelease == 'true'
        uses: sarisia/actions-status-discord@eb045afee445dc055c18d3d90bd0f244fd062708  # v1.16.0
        with:
          avatar_url: ${{ vars.ORG_LOGO_URL }}256
          color: 0x${{ vars.COLOR_HEX_GREEN }}
          description: ${{ github.event.release.body }}
          nodetail: true
          nofail: false
          title: ${{ github.event.repository.name }} ${{ github.ref_name }} Released
          username: ${{ vars.DISCORD_USERNAME }}
          webhook: ${{ secrets.DISCORD_RELEASE_WEBHOOK_MOONLIGHT }}


================================================
FILE: .github/workflows/update-pages.yml
================================================
---
name: Build GH-Pages
permissions: {}

on:
  pull_request:
  push:
    branches:
      - master
  workflow_dispatch:

concurrency:
  group: "${{ github.workflow }}-${{ github.ref }}"
  cancel-in-progress: true

jobs:
  prep:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Upload artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f  # v7.0.0
        with:
          name: prep
          path: gh-pages-template/
          if-no-files-found: error
          include-hidden-files: true
          retention-days: 1

  call-jekyll-build:
    needs: prep
    permissions:
      contents: read
    uses: LizardByte/LizardByte.github.io/.github/workflows/jekyll-build.yml@master
    secrets:
      GH_BOT_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_BOT_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
    with:
      clean_gh_pages: true
      gh_bot_name: ${{ vars.GH_BOT_NAME }}
      site_artifact: 'prep'
      target_branch: 'gh-pages'


================================================
FILE: .gitignore
================================================
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

# JetBrains IDE
.idea/

# VSCode IDE
.vscode/

# build directories
build/
cmake-*/
docs/doxyconfig*

# npm
node_modules/
package-lock.json

# Translations
*.mo
*.pot

# Dummy macOS files
.DS_Store

# Python
*.pyc
venv/


================================================
FILE: .gitmodules
================================================
[submodule "packaging/linux/flatpak/deps/flatpak-builder-tools"]
	path = packaging/linux/flatpak/deps/flatpak-builder-tools
	url = https://github.com/flatpak/flatpak-builder-tools.git
	branch = master
[submodule "packaging/linux/flatpak/deps/shared-modules"]
	path = packaging/linux/flatpak/deps/shared-modules
	url = https://github.com/flathub/shared-modules.git
	branch = master
[submodule "third-party/build-deps"]
	path = third-party/build-deps
	url = https://github.com/LizardByte/build-deps.git
	branch = master
[submodule "third-party/doxyconfig"]
	path = third-party/doxyconfig
	url = https://github.com/LizardByte/doxyconfig.git
	branch = master
[submodule "third-party/glad"]
	path = third-party/glad
	url = https://github.com/Dav1dde/glad.git
[submodule "third-party/googletest"]
	path = third-party/googletest
	url = https://github.com/google/googletest.git
	branch = main
[submodule "third-party/inputtino"]
	path = third-party/inputtino
	url = https://github.com/games-on-whales/inputtino.git
	branch = stable
[submodule "third-party/libdisplaydevice"]
	path = third-party/libdisplaydevice
	url = https://github.com/LizardByte/libdisplaydevice.git
	branch = master
[submodule "third-party/moonlight-common-c"]
	path = third-party/moonlight-common-c
	url = https://github.com/moonlight-stream/moonlight-common-c.git
	branch = master
[submodule "third-party/nanors"]
	path = third-party/nanors
	url = https://github.com/sleepybishop/nanors.git
	branch = master
[submodule "third-party/nv-codec-headers"]
	path = third-party/nv-codec-headers
	url = https://github.com/FFmpeg/nv-codec-headers.git
	branch = sdk/12.0
[submodule "third-party/nvapi"]
	path = third-party/nvapi
	url = https://github.com/NVIDIA/nvapi.git
	branch = main
[submodule "third-party/Simple-Web-Server"]
	path = third-party/Simple-Web-Server
	url = https://github.com/LizardByte-infrastructure/Simple-Web-Server.git
	branch = master
[submodule "third-party/TPCircularBuffer"]
	path = third-party/TPCircularBuffer
	url = https://github.com/michaeltyson/TPCircularBuffer.git
	branch = master
[submodule "third-party/tray"]
	path = third-party/tray
	url = https://github.com/LizardByte/tray.git
	branch = master
[submodule "third-party/ViGEmClient"]
	path = third-party/ViGEmClient
	url = https://github.com/LizardByte/Virtual-Gamepad-Emulation-Client.git
	branch = master
[submodule "third-party/wayland-protocols"]
	path = third-party/wayland-protocols
	url = https://github.com/LizardByte-infrastructure/wayland-protocols.git
	branch = main
[submodule "third-party/wlr-protocols"]
	path = third-party/wlr-protocols
	url = https://github.com/LizardByte-infrastructure/wlr-protocols.git
	branch = master


================================================
FILE: .prettierrc.json
================================================
{}

================================================
FILE: .readthedocs.yaml
================================================
---
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
  os: ubuntu-24.04
  tools:
    python: "miniconda-latest"
  commands:
    - |
      if [ -f readthedocs_build.sh ]; then
        doxyconfig_dir="."
      else
        doxyconfig_dir="./third-party/doxyconfig"
      fi
      chmod +x "${doxyconfig_dir}/readthedocs_build.sh"
      export DOXYCONFIG_DIR="${doxyconfig_dir}"
      "${doxyconfig_dir}/readthedocs_build.sh"

# using conda, we can get newer doxygen and graphviz than ubuntu provide
# https://github.com/readthedocs/readthedocs.org/issues/8151#issuecomment-890359661
conda:
  environment: third-party/doxyconfig/environment.yml

submodules:
  include: all
  recursive: true


================================================
FILE: .rstcheck.cfg
================================================
# configuration file for rstcheck, an rst linting tool
# https://rstcheck.readthedocs.io/en/latest/usage/config

[rstcheck]
ignore_directives =
    doxygenfile,
    include,
    mdinclude,
    tab,
    todo,


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.20)
# `CMAKE_CUDA_ARCHITECTURES` requires 3.18
# `set_source_files_properties` requires 3.18
# `cmake_path(CONVERT ... TO_NATIVE_PATH_LIST ...)` requires 3.20
# todo - set this conditionally

project(Sunshine VERSION 0.0.0
        DESCRIPTION "Self-hosted game stream host for Moonlight"
        HOMEPAGE_URL "https://app.lizardbyte.dev/Sunshine")

set(PROJECT_LICENSE "GPL-3.0-only")

set(PROJECT_FQDN "dev.lizardbyte.app.Sunshine")

set(PROJECT_BRIEF_DESCRIPTION "GameStream host for Moonlight")  # must be <= 35 characters

set(PROJECT_LONG_DESCRIPTION "Offering low latency, cloud gaming server capabilities with support for AMD, Intel, \
and Nvidia GPUs for hardware encoding. Software encoding is also available. You can connect to Sunshine from any \
Moonlight client on a variety of devices. A web UI is provided to allow configuration, and client pairing, from \
your favorite web browser. Pair from the local server or any mobile device.")

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    message(STATUS "Setting build type to 'Release' as none was specified.")
    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
    set(FREEBSD ON)
endif()

# set the module path, used for includes
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

# export compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# set version info for this build
include(${CMAKE_MODULE_PATH}/prep/build_version.cmake)

# cmake build flags
include(${CMAKE_MODULE_PATH}/prep/options.cmake)

# initial prep
include(${CMAKE_MODULE_PATH}/prep/init.cmake)

# configure special package files, such as sunshine.desktop, Flatpak manifest, Portfile , etc.
include(${CMAKE_MODULE_PATH}/prep/special_package_configuration.cmake)

# Exit early if END_BUILD is ON, i.e. when only generating package manifests
if(${END_BUILD})
    return()
endif()

# project constants
include(${CMAKE_MODULE_PATH}/prep/constants.cmake)

# load macros
include(${CMAKE_MODULE_PATH}/macros/common.cmake)

# load dependencies
include(${CMAKE_MODULE_PATH}/dependencies/common.cmake)

# setup compile definitions
include(${CMAKE_MODULE_PATH}/compile_definitions/common.cmake)

# target definitions
include(${CMAKE_MODULE_PATH}/targets/common.cmake)

# packaging
include(${CMAKE_MODULE_PATH}/packaging/common.cmake)


================================================
FILE: DOCKER_README.md
================================================
# Docker

## Important note
Starting with v0.18.0, tag names have changed. You may no longer use `latest`, `master`, `vX.X.X`.

## Build your own containers
This image provides a method for you to easily use the latest Sunshine release in your own docker projects. It is not
intended to use as a standalone container at this point, and should be considered experimental.

```dockerfile
ARG SUNSHINE_VERSION=latest
ARG SUNSHINE_OS=ubuntu-22.04
FROM lizardbyte/sunshine:${SUNSHINE_VERSION}-${SUNSHINE_OS}

# install Steam, Wayland, etc.

ENTRYPOINT steam && sunshine
```

### SUNSHINE_VERSION
- `latest`, `master`, `vX.X.X`
- commit hash

### SUNSHINE_OS
Sunshine images are available with the following tag suffixes, based on their respective base images.

- `debian-bookworm`
- `ubuntu-22.04`
- `ubuntu-24.04`

### Tags
You must combine the `SUNSHINE_VERSION` and `SUNSHINE_OS` to determine the tag to pull. The format should be
`<SUNSHINE_VERSION>-<SUNSHINE_OS>`. For example, `latest-ubuntu-24.04`.

See all our available tags on [docker hub](https://hub.docker.com/r/lizardbyte/sunshine/tags) or
[ghcr](https://github.com/LizardByte/Sunshine/pkgs/container/sunshine/versions) for more info.

## Where used
This is a list of docker projects using Sunshine. Something missing? Let us know about it!

- [Games on Whales](https://games-on-whales.github.io)

## Port and Volume mappings
Examples are below of the required mappings. The configuration file will be saved to `/config` in the container.

### Using docker run
Create and run the container (substitute your `<values>`):

```bash
docker run -d \
  --device /dev/dri/ \
  --name=<image_name> \
  --restart=unless-stopped \
  --ipc=host \
  -e PUID=<uid> \
  -e PGID=<gid> \
  -e TZ=<timezone> \
  -v <path to data>:/config \
  -p 47984-47990:47984-47990/tcp \
  -p 48010:48010 \
  -p 47998-48000:47998-48000/udp \
  <image>
```

### Using docker-compose
Create a `docker-compose.yml` file with the following contents (substitute your `<values>`):

```yaml
version: '3'
services:
  <image_name>:
    image: <image>
    container_name: sunshine
    restart: unless-stopped
    volumes:
      - <path to data>:/config
    environment:
      - PUID=<uid>
      - PGID=<gid>
      - TZ=<timezone>
    ipc: host
    ports:
      - "47984-47990:47984-47990/tcp"
      - "48010:48010"
      - "47998-48000:47998-48000/udp"
```

### Using podman run
Create and run the container (substitute your `<values>`):

```bash
podman run -d \
  --device /dev/dri/ \
  --name=<image_name> \
  --restart=unless-stopped \
  --userns=keep-id \
  -e PUID=<uid> \
  -e PGID=<gid> \
  -e TZ=<timezone> \
  -v <path to data>:/config \
  -p 47984-47990:47984-47990/tcp \
  -p 48010:48010 \
  -p 47998-48000:47998-48000/udp \
  <image>
```

### Parameters
You must substitute the `<values>` with your own settings.

Parameters are split into two halves separated by a colon. The left side represents the host and the right side the
container.

**Example:** `-p external:internal` - This shows the port mapping from internal to external of the container.
Therefore `-p 47990:47990` would expose port `47990` from inside the container to be accessible from the host's IP on
port `47990` (e.g. `http://<host_ip>:47990`). The internal port must be `47990`, but the external port may be changed
(e.g. `-p 8080:47990`). All the ports listed in the `docker run` and `docker-compose` examples are required.


| Parameter                   | Function             | Example Value      | Required |
|-----------------------------|----------------------|--------------------|----------|
| `-p <port>:47990`           | Web UI Port          | `47990`            | True     |
| `-v <path to data>:/config` | Volume mapping       | `/home/sunshine`   | True     |
| `-e PUID=<uid>`             | User ID              | `1001`             | False    |
| `-e PGID=<gid>`             | Group ID             | `1001`             | False    |
| `-e TZ=<timezone>`          | Lookup [TZ value][1] | `America/New_York` | False    |

For additional configuration, it is recommended to reference the *Games on Whales*
[sunshine config](https://github.com/games-on-whales/gow/blob/2e442292d79b9d996f886b8a03d22b6eb6bddf7b/compose/streamers/sunshine.yml).

[1]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

#### User / Group Identifiers:
When using data volumes (-v flags) permissions issues can arise between the host OS and the container. To avoid this
issue you can specify the user PUID and group PGID. Ensure the data volume directory on the host is owned by the same
user you specify.

In this instance `PUID=1001` and `PGID=1001`. To find yours use id user as below:

```bash
$ id dockeruser
uid=1001(dockeruser) gid=1001(dockergroup) groups=1001(dockergroup)
```

If you want to change the PUID or PGID after the image has been built, it will require rebuilding the image.

## Supported Architectures

Specifying `lizardbyte/sunshine:latest-<SUNSHINE_OS>` or `ghcr.io/lizardbyte/sunshine:latest-<SUNSHINE_OS>` should
retrieve the correct image for your architecture.

The architectures supported by these images are shown in the table below.

| tag suffix      | amd64/x86_64 | arm64/aarch64 |
|-----------------|--------------|---------------|
| debian-bookworm | ✅            | ✅             |
| ubuntu-22.04    | ✅            | ✅             |
| ubuntu-24.04    | ✅            | ✅             |

<div class="section_buttons">

| Previous                       |                                                 Next |
|:-------------------------------|-----------------------------------------------------:|
| [Changelog](docs/changelog.md) | [Third-Party Packages](docs/third_party_packages.md) |

</div>

<details style="display: none;">
  <summary></summary>
  [TOC]
</details>


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: NOTICE
================================================
©2018 Valve Corporation. Steam and the Steam logo are trademarks and/or
registered trademarks of Valve Corporation in the U.S. and/or other countries. All
rights reserved.

================================================
FILE: README.md
================================================
<div align="center">
  <img src="sunshine.png"  alt="Sunshine icon"/>
  <h1 align="center">Sunshine</h1>
  <h4 align="center">Self-hosted game stream host for Moonlight.</h4>
</div>

<div align="center">
  <a href="https://github.com/LizardByte/Sunshine"><img src="https://img.shields.io/github/stars/lizardbyte/sunshine.svg?logo=github&style=for-the-badge" alt="GitHub stars"></a>
  <a href="https://github.com/LizardByte/Sunshine/releases/latest"><img src="https://img.shields.io/github/downloads/lizardbyte/sunshine/total.svg?style=for-the-badge&logo=github" alt="GitHub Releases"></a>
  <a href="https://hub.docker.com/r/lizardbyte/sunshine"><img src="https://img.shields.io/docker/pulls/lizardbyte/sunshine.svg?style=for-the-badge&logo=docker" alt="Docker"></a>
  <a href="https://github.com/LizardByte/Sunshine/pkgs/container/sunshine"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fipitio.github.io%2Fbackage%2FLizardByte%2FSunshine%2Fsunshine.json&query=%24.downloads&label=ghcr%20pulls&style=for-the-badge&logo=github" alt="GHCR"></a>
  <a href="https://flathub.org/apps/dev.lizardbyte.app.Sunshine"><img src="https://img.shields.io/flathub/downloads/dev.lizardbyte.app.Sunshine?style=for-the-badge&logo=flathub" alt="Flathub installs"></a>
  <a href="https://flathub.org/apps/dev.lizardbyte.app.Sunshine"><img src="https://img.shields.io/flathub/v/dev.lizardbyte.app.Sunshine?style=for-the-badge&logo=flathub" alt="Flathub Version"></a>
  <a href="https://github.com/microsoft/winget-pkgs/tree/master/manifests/l/LizardByte/Sunshine"><img src="https://img.shields.io/winget/v/LizardByte.Sunshine?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHuSURBVFhH7ZfNTtRQGIYZiMDwN/IrCAqIhMSNKxcmymVwG+5dcDVsWHgDrtxwCYQVl+BChzDEwSnPY+eQ0sxoOz1mQuBNnpyvTdvz9jun5/SrjfxnJUkyQbMEz2ELduF1l0YUA3QyTrMAa2AnPtyOXsELeAYNyKtV2EC3k3lYgTOwg09ghy/BTp7CKBRV844BOpmmMV2+ySb4BmInG7AKY7AHH+EYqqhZo9PPBG/BVDlOizAD/XQFmnoPXzxRQX8M/CCYS48L6RIc4ygGHK9WGg9HZSZMUNRPVwNJGg5Hg2Qgqh4N3FsDsb6EmgYm07iwwvUxstdxJTwgmILf4CfZ6bb5OHANX8GN5x20IVxnG8ge94pt2xpwU3GnCwayF4Q2G2vgFLzHndFzQdk4q77nNfCdwL28qNyMtmEf3A1/QV5FjDiPWo5jrwf8TWZChTlgJvL4F9QL50/A43qVidTvLcuoM2wDQ1+IkgefgUpLcYwMVBqCKNJA2b0gKNocOIITOIef8C/F/CdMbh/GklynsSawKLHS8d9/B1x2LUqsfFyy3TMsWj5A1cLkotDbYO4JjWWZlZEGv8EbOIR1CAVN2eG8W5oNKgxaeC6DmTJjZs7ixUxpznLPLT+v4sXpoMLcLI3mzFSonDXIEI/M3QCIO4YuimBJ/gAAAABJRU5ErkJggg==" alt="Winget Version"></a>
  <a href="https://gurubase.io/g/sunshine"><img src="https://img.shields.io/badge/Gurubase-Ask%20Guru-ef1a1b?style=for-the-badge&logo=data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDIBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIABgAGAMBIgACEQEDEQH/xAGiAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgsQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+gEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoLEQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AOLqSO3mlilljido4QGkYDIQEgAn05IH41seFo7aS+uRKlrJci2Y2cd2QImlyOGyQPu7sA8ZxXapAlvpThbPRkv7nTQWhDoIZZRc/XaSAOmcZGOnFfP06XMr3P17F5iqE+Tl1uuvf9Lde55dRW74pit4r61EcdtFdG2U3kVqQY0lyeBgkD5duQOASawqykuV2O6jV9rTU0rXLNjf3Om3QubSXy5QCudoYEEYIIOQR7GnahqV3qk6zXk3mOqhFAUKqqOyqAAByeAKqUUXdrFezhz89lfv1+8KKKKRZ//Z" alt="Gurubase"></a>
  <a href="https://github.com/LizardByte/Sunshine/actions/workflows/ci.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/sunshine/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (CI)"></a>
  <a href="https://github.com/LizardByte/Sunshine/actions/workflows/localize.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/sunshine/localize.yml.svg?branch=master&label=localize%20build&logo=github&style=for-the-badge" alt="GitHub Workflow Status (localize)"></a>
  <a href="https://docs.lizardbyte.dev/projects/sunshine"><img src="https://img.shields.io/readthedocs/sunshinestream.svg?label=Docs&style=for-the-badge&logo=readthedocs" alt="Read the Docs"></a>
  <a href="https://codecov.io/gh/LizardByte/Sunshine"><img src="https://img.shields.io/codecov/c/gh/LizardByte/Sunshine?token=SMGXQ5NVMJ&style=for-the-badge&logo=codecov&label=codecov" alt="Codecov"></a>
</div>

## ℹ️ About

Sunshine is a self-hosted game stream host for Moonlight.
Offering low-latency, cloud gaming server capabilities with support for AMD, Intel, and Nvidia GPUs for hardware
encoding. Software encoding is also available. You can connect to Sunshine from any Moonlight client on a variety of
devices. A web UI is provided to allow configuration, and client pairing, from your favorite web browser. Pair from
the local server or any mobile device.

LizardByte has the full documentation hosted on [Read the Docs](https://docs.lizardbyte.dev/projects/sunshine)

* [Stable Docs](https://docs.lizardbyte.dev/projects/sunshine/latest/)
* [Beta Docs](https://docs.lizardbyte.dev/projects/sunshine/master/)

## 🎮 Feature Compatibility

<table>
    <caption id="feature_compatibility">Platform Feature Support</caption>
    <tr>
        <th>Feature</th>
        <th>FreeBSD</th>
        <th>Linux</th>
        <th>macOS</th>
        <th>Windows</th>
    </tr>
    <tr>
        <td colspan="5" align="center"><b>Gamepad Emulation</b><br>
        What type of gamepads can be emulated on the host.<br>
        Clients may support other gamepads.
        </td>
    </tr>
    <tr>
        <td>DualShock / DS4 (PlayStation 4)</td>
        <td>➖</td>
        <td>➖</td>
        <td>❌</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>DualSense / DS5 (PlayStation 5)</td>
        <td>❌</td>
        <td>✅</td>
        <td>❌</td>
        <td>❌</td>
    </tr>
    <tr>
        <td>Nintendo Switch Pro</td>
        <td>✅</td>
        <td>✅</td>
        <td>❌</td>
        <td>❌</td>
    </tr>
    <tr>
        <td>Xbox 360</td>
        <td>➖</td>
        <td>➖</td>
        <td>❌</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>Xbox One/Series</td>
        <td>✅</td>
        <td>✅</td>
        <td>❌</td>
        <td>❌</td>
    </tr>
    <tr>
        <td colspan="5" align="center"><b>GPU Encoding</b></td>
    </tr>
    <tr>
        <td>AMD/AMF</td>
        <td>✅ (vaapi)</td>
        <td>✅ (vaapi)</td>
        <td>✅ (Video Toolbox)</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>Intel QuickSync</td>
        <td>✅ (vaapi)</td>
        <td>✅ (vaapi)</td>
        <td>✅ (Video Toolbox)</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>NVIDIA NVENC</td>
        <td>✅ (vaapi)</td>
        <td>✅ (vaapi)</td>
        <td>✅ (Video Toolbox)</td>
        <td>✅</td>
    </tr>
    <tr>
        <td colspan="5" align="center"><b>Screen Capture</b></td>
    </tr>
    <tr>
        <td>DXGI</td>
        <td>➖</td>
        <td>➖</td>
        <td>➖</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>KMS</td>
        <td>❌</td>
        <td>✅</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>NVIDIA NvFBC</td>
        <td>➖</td>
        <td>🟡</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>&nbsp;&nbsp;↳ X11 Support</td>
        <td>➖</td>
        <td>✅</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>&nbsp;&nbsp;↳ Wayland Support</td>
        <td>➖</td>
        <td>❌</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>Video Toolbox</td>
        <td>➖</td>
        <td>➖</td>
        <td>✅</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>Wayland</td>
        <td>✅</td>
        <td>✅</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
    <tr>
        <td>Windows.Graphics.Capture</td>
        <td>➖</td>
        <td>➖</td>
        <td>➖</td>
        <td>🟡</td>
    </tr>
    <tr>
        <td>&nbsp;&nbsp;↳ Portable</td>
        <td>➖</td>
        <td>➖</td>
        <td>➖</td>
        <td>✅</td>
    </tr>
    <tr>
        <td>&nbsp;&nbsp;↳ Service</td>
        <td>➖</td>
        <td>➖</td>
        <td>➖</td>
        <td>❌</td>
    </tr>
    <tr>
        <td>X11</td>
        <td>✅</td>
        <td>✅</td>
        <td>➖</td>
        <td>➖</td>
    </tr>
</table>

**Legend:** ✅ Supported | 🟡 Partial Support | ❌ Not Yet Supported | ➖ Not Applicable

## 🖥️ System Requirements

> [!WARNING]
> These tables are a work in progress. Do not purchase hardware based on this information.

<table>
    <caption id="minimum_requirements">Minimum Requirements</caption>
    <tr>
        <th>Component</th>
        <th>Requirement</th>
    </tr>
    <tr>
        <td rowspan="3">GPU</td>
        <td>AMD: VCE 1.0 or higher, see: <a href="https://github.com/obsproject/obs-amd-encoder/wiki/Hardware-Support">obs-amd hardware support</a></td>
    </tr>
    <tr>
        <td>
            Intel:<br>
            &nbsp;&nbsp;FreeBSD/Linux: VAAPI-compatible, see: <a href="https://www.intel.com/content/www/us/en/developer/articles/technical/linuxmedia-vaapi.html">VAAPI hardware support</a><br>
            &nbsp;&nbsp;Windows: Skylake or newer with QuickSync encoding support
        </td>
    </tr>
    <tr>
        <td>Nvidia: NVENC enabled cards, see: <a href="https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new">nvenc support matrix</a></td>
    </tr>
    <tr>
        <td rowspan="2">CPU</td>
        <td>AMD: Ryzen 3 or higher</td>
    </tr>
    <tr>
        <td>Intel: Core i3 or higher</td>
    </tr>
    <tr>
        <td>RAM</td>
        <td>4GB or more</td>
    </tr>
    <tr>
        <td rowspan="6">OS</td>
        <td>FreeBSD: 14.3+</td>
    </tr>
    <tr>
        <td>Linux/Debian: 13+ (trixie)</td>
    </tr>
    <tr>
        <td>Linux/Fedora: 41+</td>
    </tr>
    <tr>
        <td>Linux/Ubuntu: 22.04+ (jammy)</td>
    </tr>
    <tr>
        <td>macOS: 14+</td>
    </tr>
    <tr>
        <td>Windows: 11+ (Windows Server does not support virtual gamepads)</td>
    </tr>
    <tr>
        <td rowspan="2">Network</td>
        <td>Host: 5GHz, 802.11ac</td>
    </tr>
    <tr>
        <td>Client: 5GHz, 802.11ac</td>
    </tr>
</table>

<table>
    <caption id="4k_suggestions">4k Suggestions</caption>
    <tr>
        <th>Component</th>
        <th>Requirement</th>
    </tr>
    <tr>
        <td rowspan="3">GPU</td>
        <td>AMD: Video Coding Engine 3.1 or higher</td>
    </tr>
    <tr>
        <td>
            Intel:<br>
            &nbsp;&nbsp;FreeBSD/Linux: HD Graphics 510 or higher<br>
            &nbsp;&nbsp;Windows: Skylake or newer with QuickSync encoding support
        </td>
    </tr>
    <tr>
        <td>
            Nvidia:<br>
            &nbsp;&nbsp;FreeBSD/Linux: GeForce RTX 2000 series or higher<br>
            &nbsp;&nbsp;Windows: Geforce GTX 1080 or higher
        </td>
    </tr>
    <tr>
        <td rowspan="2">CPU</td>
        <td>AMD: Ryzen 5 or higher</td>
    </tr>
    <tr>
        <td>Intel: Core i5 or higher</td>
    </tr>
    <tr>
        <td rowspan="2">Network</td>
        <td>Host: CAT5e ethernet or better</td>
    </tr>
    <tr>
        <td>Client: CAT5e ethernet or better</td>
    </tr>
</table>

<table>
    <caption id="hdr_suggestions">HDR Suggestions</caption>
    <tr>
        <th>Component</th>
        <th>Requirement</th>
    </tr>
    <tr>
        <td rowspan="3">GPU</td>
        <td>AMD: Video Coding Engine 3.4 or higher</td>
    </tr>
    <tr>
        <td>Intel: HD Graphics 730 or higher</td>
    </tr>
    <tr>
        <td>Nvidia: Pascal-based GPU (GTX 10-series) or higher</td>
    </tr>
    <tr>
        <td rowspan="2">CPU</td>
        <td>AMD: Ryzen 5 or higher</td>
    </tr>
    <tr>
        <td>Intel: Core i5 or higher</td>
    </tr>
    <tr>
        <td rowspan="2">Network</td>
        <td>Host: CAT5e ethernet or better</td>
    </tr>
    <tr>
        <td>Client: CAT5e ethernet or better</td>
    </tr>
</table>

## ❓ Support

Our support methods are listed in our [LizardByte Docs](https://docs.lizardbyte.dev/latest/about/support.html).

## 💲 Sponsors and Supporters

<p align="center">
  <img src='https://cdn.jsdelivr.net/gh/LizardByte/contributors@dist/sponsors.svg' alt="Sponsors"/>
</p>

## 👥 Contributors

Thank you to all the contributors who have helped make Sunshine better!

### GitHub

<p align="center">
  <img src='https://cdn.jsdelivr.net/gh/LizardByte/contributors@dist/github.Sunshine.svg' alt="GitHub contributors"/>
</p>

### CrowdIn

<p align="center">
  <img src='https://cdn.jsdelivr.net/gh/LizardByte/contributors@dist/crowdin.606145.svg' alt="CrowdIn contributors"/>
</p>

<div class="section_buttons">

| Previous |                                       Next |
|:---------|-------------------------------------------:|
|          | [Getting Started](docs/getting_started.md) |

</div>

<details style="display: none;">
  <summary></summary>
  [TOC]
</details>


================================================
FILE: cmake/FindLIBCAP.cmake
================================================
# - Try to find Libcap
# Once done this will define
#
#  LIBCAP_FOUND - system has Libcap
#  LIBCAP_INCLUDE_DIRS - the Libcap include directory
#  LIBCAP_LIBRARIES - the libraries needed to use Libcap
#  LIBCAP_DEFINITIONS - Compiler switches required for using Libcap

# Use pkg-config to get the directories and then use these values
# in the find_path() and find_library() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBCAP libcap)

set(LIBCAP_DEFINITIONS ${PC_LIBCAP_CFLAGS})

find_path(LIBCAP_INCLUDE_DIRS sys/capability.h PATHS ${PC_LIBCAP_INCLUDEDIR} ${PC_LIBCAP_INCLUDE_DIRS})
find_library(LIBCAP_LIBRARIES NAMES libcap.so PATHS ${PC_LIBCAP_LIBDIR} ${PC_LIBCAP_LIBRARY_DIRS})
mark_as_advanced(LIBCAP_INCLUDE_DIRS LIBCAP_LIBRARIES)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBCAP REQUIRED_VARS LIBCAP_LIBRARIES LIBCAP_INCLUDE_DIRS)


================================================
FILE: cmake/FindLIBDRM.cmake
================================================
# - Try to find Libdrm
# Once done this will define
#
#  LIBDRM_FOUND - system has Libdrm
#  LIBDRM_INCLUDE_DIRS - the Libdrm include directory
#  LIBDRM_LIBRARIES - the libraries needed to use Libdrm
#  LIBDRM_DEFINITIONS - Compiler switches required for using Libdrm

# Use pkg-config to get the directories and then use these values
# in the find_path() and find_library() calls
find_package(PkgConfig)
pkg_check_modules(PC_LIBDRM libdrm)

set(LIBDRM_DEFINITIONS ${PC_LIBDRM_CFLAGS})

find_path(LIBDRM_INCLUDE_DIRS drm.h PATHS ${PC_LIBDRM_INCLUDEDIR} ${PC_LIBDRM_INCLUDE_DIRS} PATH_SUFFIXES libdrm)
find_library(LIBDRM_LIBRARIES NAMES libdrm.so PATHS ${PC_LIBDRM_LIBDIR} ${PC_LIBDRM_LIBRARY_DIRS})
mark_as_advanced(LIBDRM_INCLUDE_DIRS LIBDRM_LIBRARIES)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBDRM REQUIRED_VARS LIBDRM_LIBRARIES LIBDRM_INCLUDE_DIRS)


================================================
FILE: cmake/FindLibva.cmake
================================================
# - Try to find Libva
# This module defines the following variables:
#
# * LIBVA_FOUND - The component was found
# * LIBVA_INCLUDE_DIRS - The component include directory
# * LIBVA_LIBRARIES - The component library Libva
# * LIBVA_DRM_LIBRARIES - The component library Libva DRM

# Use pkg-config to get the directories and then use these values in the
# find_path() and find_library() calls
# cmake-format: on

find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
    pkg_check_modules(_LIBVA libva)
    pkg_check_modules(_LIBVA_DRM libva-drm)
endif()

find_path(
        LIBVA_INCLUDE_DIR
        NAMES va/va.h va/va_drm.h
        HINTS ${_LIBVA_INCLUDE_DIRS}
        PATHS /usr/include /usr/local/include /opt/local/include)

find_library(
        LIBVA_LIB
        NAMES ${_LIBVA_LIBRARIES} libva
        HINTS ${_LIBVA_LIBRARY_DIRS}
        PATHS /usr/lib /usr/local/lib /opt/local/lib)

find_library(
        LIBVA_DRM_LIB
        NAMES ${_LIBVA_DRM_LIBRARIES} libva-drm
        HINTS ${_LIBVA_DRM_LIBRARY_DIRS}
        PATHS /usr/lib /usr/local/lib /opt/local/lib)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libva REQUIRED_VARS LIBVA_INCLUDE_DIR LIBVA_LIB LIBVA_DRM_LIB)
mark_as_advanced(LIBVA_INCLUDE_DIR LIBVA_LIB LIBVA_DRM_LIB)

if(LIBVA_FOUND)
    set(LIBVA_INCLUDE_DIRS ${LIBVA_INCLUDE_DIR})
    set(LIBVA_LIBRARIES ${LIBVA_LIB})
    set(LIBVA_DRM_LIBRARIES ${LIBVA_DRM_LIB})

    if(NOT TARGET Libva::va)
        if(IS_ABSOLUTE "${LIBVA_LIBRARIES}")
            add_library(Libva::va UNKNOWN IMPORTED)
            set_target_properties(Libva::va PROPERTIES IMPORTED_LOCATION "${LIBVA_LIBRARIES}")
        else()
            add_library(Libva::va INTERFACE IMPORTED)
            set_target_properties(Libva::va PROPERTIES IMPORTED_LIBNAME "${LIBVA_LIBRARIES}")
        endif()

        set_target_properties(Libva::va PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIRS}")
    endif()

    if(NOT TARGET Libva::drm)
        if(IS_ABSOLUTE "${LIBVA_DRM_LIBRARIES}")
            add_library(Libva::drm UNKNOWN IMPORTED)
            set_target_properties(Libva::drm PROPERTIES IMPORTED_LOCATION "${LIBVA_DRM_LIBRARIES}")
        else()
            add_library(Libva::drm INTERFACE IMPORTED)
            set_target_properties(Libva::drm PROPERTIES IMPORTED_LIBNAME "${LIBVA_DRM_LIBRARIES}")
        endif()

        set_target_properties(Libva::drm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBVA_INCLUDE_DIRS}")
    endif()

endif()


================================================
FILE: cmake/FindSystemd.cmake
================================================
# - Try to find Systemd
# Once done this will define
#
# SYSTEMD_FOUND - system has systemd
# SYSTEMD_USER_UNIT_INSTALL_DIR - the systemd system unit install directory
# SYSTEMD_SYSTEM_UNIT_INSTALL_DIR - the systemd user unit install directory
# SYSTEMD_MODULES_LOAD_DIR - the systemd modules-load.d directory

IF (NOT WIN32)

    find_package(PkgConfig QUIET)
    if(PKG_CONFIG_FOUND)
        pkg_check_modules(SYSTEMD "systemd")
    endif()

    if (SYSTEMD_FOUND)
        execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
            --variable=systemd_user_unit_dir systemd
            OUTPUT_STRIP_TRAILING_WHITESPACE
            OUTPUT_VARIABLE SYSTEMD_USER_UNIT_INSTALL_DIR)

        execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
            --variable=systemd_system_unit_dir systemd
            OUTPUT_STRIP_TRAILING_WHITESPACE
            OUTPUT_VARIABLE SYSTEMD_SYSTEM_UNIT_INSTALL_DIR)

        execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
            --variable=modules_load_dir systemd
            OUTPUT_STRIP_TRAILING_WHITESPACE
            OUTPUT_VARIABLE SYSTEMD_MODULES_LOAD_DIR)

        mark_as_advanced(
                SYSTEMD_USER_UNIT_INSTALL_DIR
                SYSTEMD_SYSTEM_UNIT_INSTALL_DIR
                SYSTEMD_MODULES_LOAD_DIR
        )

    endif ()

ENDIF ()


================================================
FILE: cmake/FindUdev.cmake
================================================
# - Try to find Udev
# Once done this will define
#
# UDEV_FOUND - system has udev
# UDEV_RULES_INSTALL_DIR - the udev rules install directory
# UDEVADM_EXECUTABLE - path to udevadm executable
# UDEV_VERSION - version of udev/systemd

if(NOT WIN32)
    find_package(PkgConfig QUIET)
    if(PKG_CONFIG_FOUND)
        pkg_check_modules(UDEV "udev")
    endif()

    if(UDEV_FOUND)
        if(UDEV_VERSION)
            message(STATUS "Found udev/systemd version: ${UDEV_VERSION}")
        else()
            message(WARNING "Could not determine udev/systemd version")
            set(UDEV_VERSION "0")
        endif()

        execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE}
            --variable=udev_dir udev
            OUTPUT_STRIP_TRAILING_WHITESPACE
            OUTPUT_VARIABLE UDEV_RULES_INSTALL_DIR)

        set(UDEV_RULES_INSTALL_DIR "${UDEV_RULES_INSTALL_DIR}/rules.d")

        mark_as_advanced(UDEV_RULES_INSTALL_DIR)

        # Check if udevadm is available
        find_program(UDEVADM_EXECUTABLE udevadm
            PATHS /usr/bin /bin /usr/sbin /sbin
            DOC "Path to udevadm executable")
        mark_as_advanced(UDEVADM_EXECUTABLE)

        # Handle version requirements
        if(Udev_FIND_VERSION)
            if(UDEV_VERSION VERSION_LESS Udev_FIND_VERSION)
                set(UDEV_FOUND FALSE)
                if(Udev_FIND_REQUIRED)
                    message(FATAL_ERROR "Udev version ${UDEV_VERSION} less than required version ${Udev_FIND_VERSION}")
                else()
                    message(STATUS "Udev version ${UDEV_VERSION} less than required version ${Udev_FIND_VERSION}")
                endif()
            else()
                message(STATUS "Udev version ${UDEV_VERSION} meets requirement (>= ${Udev_FIND_VERSION})")
            endif()
        endif()
    endif()
endif()


================================================
FILE: cmake/FindWayland.cmake
================================================
# Try to find Wayland on a Unix system
#
# This will define:
#
#   WAYLAND_FOUND        - True if Wayland is found
#   WAYLAND_LIBRARIES    - Link these to use Wayland
#   WAYLAND_INCLUDE_DIRS - Include directory for Wayland
#   WAYLAND_DEFINITIONS  - Compiler flags for using Wayland
#
# In addition the following more fine grained variables will be defined:
#
#   Wayland_Client_FOUND  WAYLAND_CLIENT_INCLUDE_DIRS  WAYLAND_CLIENT_LIBRARIES
#   Wayland_Server_FOUND  WAYLAND_SERVER_INCLUDE_DIRS  WAYLAND_SERVER_LIBRARIES
#   Wayland_EGL_FOUND     WAYLAND_EGL_INCLUDE_DIRS     WAYLAND_EGL_LIBRARIES
#   Wayland_Cursor_FOUND  WAYLAND_CURSOR_INCLUDE_DIRS  WAYLAND_CURSOR_LIBRARIES
#
# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
#               2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

IF (NOT WIN32)

    # Use pkg-config to get the directories and then use these values
    # in the find_path() and find_library() calls
    find_package(PkgConfig)
    PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor)

    set(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS})

    find_path(WAYLAND_CLIENT_INCLUDE_DIRS NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
    find_library(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client   HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
    if(WAYLAND_CLIENT_INCLUDE_DIRS AND WAYLAND_CLIENT_LIBRARIES)
        set(Wayland_Client_FOUND TRUE)  # cmake-lint: disable=C0103
    else()
        set(Wayland_Client_FOUND FALSE)  # cmake-lint: disable=C0103
    endif()
    mark_as_advanced(WAYLAND_CLIENT_INCLUDE_DIRS WAYLAND_CLIENT_LIBRARIES)

    find_path(WAYLAND_CURSOR_INCLUDE_DIRS NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
    find_library(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor   HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
    if(WAYLAND_CURSOR_INCLUDE_DIRS AND WAYLAND_CURSOR_LIBRARIES)
        set(Wayland_Cursor_FOUND TRUE)  # cmake-lint: disable=C0103
    else()
        set(Wayland_Cursor_FOUND FALSE)  # cmake-lint: disable=C0103
    endif()
    mark_as_advanced(WAYLAND_CURSOR_INCLUDE_DIRS WAYLAND_CURSOR_LIBRARIES)

    find_path(WAYLAND_EGL_INCLUDE_DIRS    NAMES wayland-egl.h    HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
    find_library(WAYLAND_EGL_LIBRARIES    NAMES wayland-egl      HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
    if(WAYLAND_EGL_INCLUDE_DIRS AND WAYLAND_EGL_LIBRARIES)
        set(Wayland_EGL_FOUND TRUE)  # cmake-lint: disable=C0103
    else()
        set(Wayland_EGL_FOUND FALSE)  # cmake-lint: disable=C0103
    endif()
    mark_as_advanced(WAYLAND_EGL_INCLUDE_DIRS WAYLAND_EGL_LIBRARIES)

    find_path(WAYLAND_SERVER_INCLUDE_DIRS NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS})
    find_library(WAYLAND_SERVER_LIBRARIES NAMES wayland-server   HINTS ${PKG_WAYLAND_LIBRARY_DIRS})
    if(WAYLAND_SERVER_INCLUDE_DIRS AND WAYLAND_SERVER_LIBRARIES)
        set(Wayland_Server_FOUND TRUE)  # cmake-lint: disable=C0103
    else()
        set(Wayland_Server_FOUND FALSE)  # cmake-lint: disable=C0103
    endif()
    mark_as_advanced(WAYLAND_SERVER_INCLUDE_DIRS WAYLAND_SERVER_LIBRARIES)

    set(WAYLAND_INCLUDE_DIRS ${WAYLAND_CLIENT_INCLUDE_DIRS} ${WAYLAND_SERVER_INCLUDE_DIRS}
            ${WAYLAND_EGL_INCLUDE_DIRS} ${WAYLAND_CURSOR_INCLUDE_DIRS})
    set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES}
            ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES})
    mark_as_advanced(WAYLAND_INCLUDE_DIRS WAYLAND_LIBRARIES)

    list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIRS)

    include(FindPackageHandleStandardArgs)

    find_package_handle_standard_args(Wayland REQUIRED_VARS WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIRS HANDLE_COMPONENTS)

ENDIF ()


================================================
FILE: cmake/compile_definitions/common.cmake
================================================
# common compile definitions
# this file will also load platform specific definitions

list(APPEND SUNSHINE_COMPILE_OPTIONS -Wall -Wno-sign-compare)
# Wall - enable all warnings
# Werror - treat warnings as errors
# Wno-maybe-uninitialized/Wno-uninitialized - disable warnings for maybe uninitialized variables
# Wno-sign-compare - disable warnings for signed/unsigned comparisons
# Wno-restrict - disable warnings for memory overlap
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    # GCC specific compile options

    # GCC 12 and higher will complain about maybe-uninitialized
    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
        list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-maybe-uninitialized)

        # Disable the bogus warning that may prevent compilation (only for GCC 12).
        # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651.
        if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13)
            list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-restrict)
        endif()
    endif()

    # GCC 15 will complain about uninitialized variables in some cases (Simple-Web-Server)
    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
        list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-uninitialized)
    endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    # Clang specific compile options

    # Clang doesn't actually complain about this this, so disabling for now
    # list(APPEND SUNSHINE_COMPILE_OPTIONS -Wno-uninitialized)
endif()
if(BUILD_WERROR)
    list(APPEND SUNSHINE_COMPILE_OPTIONS -Werror)
endif()

# setup assets directory
if(NOT SUNSHINE_ASSETS_DIR)
    set(SUNSHINE_ASSETS_DIR "assets")
endif()

# platform specific compile definitions
if(WIN32)
    include(${CMAKE_MODULE_PATH}/compile_definitions/windows.cmake)
elseif(UNIX)
    include(${CMAKE_MODULE_PATH}/compile_definitions/unix.cmake)

    if(APPLE)
        include(${CMAKE_MODULE_PATH}/compile_definitions/macos.cmake)
    else()
        include(${CMAKE_MODULE_PATH}/compile_definitions/linux.cmake)
    endif()
endif()

include_directories(BEFORE SYSTEM "${CMAKE_SOURCE_DIR}/third-party/nv-codec-headers/include")
file(GLOB NVENC_SOURCES CONFIGURE_DEPENDS "src/nvenc/*.cpp" "src/nvenc/*.h")
list(APPEND PLATFORM_TARGET_FILES ${NVENC_SOURCES})

set(SUNSHINE_TARGET_FILES
        "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Input.h"
        "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Rtsp.h"
        "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/RtspParser.c"
        "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/src/Video.h"
        "${CMAKE_SOURCE_DIR}/third-party/tray/src/tray.h"
        "${CMAKE_SOURCE_DIR}/src/upnp.cpp"
        "${CMAKE_SOURCE_DIR}/src/upnp.h"
        "${CMAKE_SOURCE_DIR}/src/cbs.cpp"
        "${CMAKE_SOURCE_DIR}/src/utility.h"
        "${CMAKE_SOURCE_DIR}/src/uuid.h"
        "${CMAKE_SOURCE_DIR}/src/config.h"
        "${CMAKE_SOURCE_DIR}/src/config.cpp"
        "${CMAKE_SOURCE_DIR}/src/display_device.h"
        "${CMAKE_SOURCE_DIR}/src/display_device.cpp"
        "${CMAKE_SOURCE_DIR}/src/entry_handler.cpp"
        "${CMAKE_SOURCE_DIR}/src/entry_handler.h"
        "${CMAKE_SOURCE_DIR}/src/file_handler.cpp"
        "${CMAKE_SOURCE_DIR}/src/file_handler.h"
        "${CMAKE_SOURCE_DIR}/src/globals.cpp"
        "${CMAKE_SOURCE_DIR}/src/globals.h"
        "${CMAKE_SOURCE_DIR}/src/logging.cpp"
        "${CMAKE_SOURCE_DIR}/src/logging.h"
        "${CMAKE_SOURCE_DIR}/src/main.cpp"
        "${CMAKE_SOURCE_DIR}/src/main.h"
        "${CMAKE_SOURCE_DIR}/src/crypto.cpp"
        "${CMAKE_SOURCE_DIR}/src/crypto.h"
        "${CMAKE_SOURCE_DIR}/src/nvhttp.cpp"
        "${CMAKE_SOURCE_DIR}/src/nvhttp.h"
        "${CMAKE_SOURCE_DIR}/src/httpcommon.cpp"
        "${CMAKE_SOURCE_DIR}/src/httpcommon.h"
        "${CMAKE_SOURCE_DIR}/src/confighttp.cpp"
        "${CMAKE_SOURCE_DIR}/src/confighttp.h"
        "${CMAKE_SOURCE_DIR}/src/rtsp.cpp"
        "${CMAKE_SOURCE_DIR}/src/rtsp.h"
        "${CMAKE_SOURCE_DIR}/src/stream.cpp"
        "${CMAKE_SOURCE_DIR}/src/stream.h"
        "${CMAKE_SOURCE_DIR}/src/video.cpp"
        "${CMAKE_SOURCE_DIR}/src/video.h"
        "${CMAKE_SOURCE_DIR}/src/video_colorspace.cpp"
        "${CMAKE_SOURCE_DIR}/src/video_colorspace.h"
        "${CMAKE_SOURCE_DIR}/src/input.cpp"
        "${CMAKE_SOURCE_DIR}/src/input.h"
        "${CMAKE_SOURCE_DIR}/src/audio.cpp"
        "${CMAKE_SOURCE_DIR}/src/audio.h"
        "${CMAKE_SOURCE_DIR}/src/platform/common.h"
        "${CMAKE_SOURCE_DIR}/src/process.cpp"
        "${CMAKE_SOURCE_DIR}/src/process.h"
        "${CMAKE_SOURCE_DIR}/src/network.cpp"
        "${CMAKE_SOURCE_DIR}/src/network.h"
        "${CMAKE_SOURCE_DIR}/src/move_by_copy.h"
        "${CMAKE_SOURCE_DIR}/src/system_tray.cpp"
        "${CMAKE_SOURCE_DIR}/src/system_tray.h"
        "${CMAKE_SOURCE_DIR}/src/task_pool.h"
        "${CMAKE_SOURCE_DIR}/src/thread_pool.h"
        "${CMAKE_SOURCE_DIR}/src/thread_safe.h"
        "${CMAKE_SOURCE_DIR}/src/sync.h"
        "${CMAKE_SOURCE_DIR}/src/round_robin.h"
        "${CMAKE_SOURCE_DIR}/src/stat_trackers.h"
        "${CMAKE_SOURCE_DIR}/src/stat_trackers.cpp"
        "${CMAKE_SOURCE_DIR}/src/rswrapper.h"
        "${CMAKE_SOURCE_DIR}/src/rswrapper.c"
        ${PLATFORM_TARGET_FILES})

if(NOT SUNSHINE_ASSETS_DIR_DEF)
    set(SUNSHINE_ASSETS_DIR_DEF "${SUNSHINE_ASSETS_DIR}")
endif()
list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_ASSETS_DIR="${SUNSHINE_ASSETS_DIR_DEF}")

list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_TRAY=${SUNSHINE_TRAY})

# Publisher metadata
list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_PUBLISHER_NAME="${SUNSHINE_PUBLISHER_NAME}")
list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_PUBLISHER_WEBSITE="${SUNSHINE_PUBLISHER_WEBSITE}")
list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_PUBLISHER_ISSUE_URL="${SUNSHINE_PUBLISHER_ISSUE_URL}")

include_directories(BEFORE "${CMAKE_SOURCE_DIR}")

include_directories(
        BEFORE
        SYSTEM
        "${CMAKE_SOURCE_DIR}/third-party"
        "${CMAKE_SOURCE_DIR}/third-party/moonlight-common-c/enet/include"
        "${CMAKE_SOURCE_DIR}/third-party/nanors"
        "${CMAKE_SOURCE_DIR}/third-party/nanors/deps/obl"
        ${OPENSSL_INCLUDE_DIR}
        ${Opus_INCLUDE_DIR}
        ${FFMPEG_INCLUDE_DIRS}
        ${Boost_INCLUDE_DIRS}  # has to be the last, or we get runtime error on macOS ffmpeg encoder
)

list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
        ${MINIUPNP_LIBRARIES}
        ${CMAKE_THREAD_LIBS_INIT}
        enet
        libdisplaydevice::display_device
        nlohmann_json::nlohmann_json
        ${Opus_LIBRARY}
        ${FFMPEG_LIBRARIES}
        ${Boost_LIBRARIES}
        ${OPENSSL_LIBRARIES}
        ${PLATFORM_LIBRARIES})


================================================
FILE: cmake/compile_definitions/linux.cmake
================================================
# linux specific compile definitions

if(FREEBSD)
    add_compile_definitions(SUNSHINE_PLATFORM="freebsd")
else()
    add_compile_definitions(SUNSHINE_PLATFORM="linux")
endif()

# AppImage
if(${SUNSHINE_BUILD_APPIMAGE})
    # use relative assets path for AppImage
    string(REPLACE "${CMAKE_INSTALL_PREFIX}" ".${CMAKE_INSTALL_PREFIX}" SUNSHINE_ASSETS_DIR_DEF ${SUNSHINE_ASSETS_DIR})
endif()

# cuda
set(CUDA_FOUND OFF)
if(${SUNSHINE_ENABLE_CUDA})
    include(CheckLanguage)
    check_language(CUDA)

    if(CMAKE_CUDA_COMPILER)
        set(CUDA_FOUND ON)
        enable_language(CUDA)

        message(STATUS "CUDA Compiler Version: ${CMAKE_CUDA_COMPILER_VERSION}")
        set(CMAKE_CUDA_ARCHITECTURES "")

        # https://docs.nvidia.com/cuda/archive/12.0.0/cuda-compiler-driver-nvcc/index.html
        if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
            list(APPEND CMAKE_CUDA_ARCHITECTURES 75 80 86 87 89 90)
        else()
            message(FATAL_ERROR
                    "Sunshine requires a minimum CUDA Compiler version of 12.0.
                    Found version: ${CMAKE_CUDA_COMPILER_VERSION}"
            )
        endif()

        # https://docs.nvidia.com/cuda/archive/12.8.0/cuda-compiler-driver-nvcc/index.html
        if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8)
            list(APPEND CMAKE_CUDA_ARCHITECTURES 100 101 120)
        endif()

        # https://docs.nvidia.com/cuda/archive/12.9.0/cuda-compiler-driver-nvcc/index.html
        if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.9)
            list(APPEND CMAKE_CUDA_ARCHITECTURES 103 121)
        endif()

        # https://docs.nvidia.com/cuda/archive/13.0.0/cuda-compiler-driver-nvcc/index.html
        if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0)
            list(REMOVE_ITEM CMAKE_CUDA_ARCHITECTURES 101)
            list(APPEND CMAKE_CUDA_ARCHITECTURES 110)
        else()
            list(APPEND CMAKE_CUDA_ARCHITECTURES 50 52 53 60 61 62 70 72)
        endif()

        # sort the architectures
        list(SORT CMAKE_CUDA_ARCHITECTURES COMPARE NATURAL)

        # message(STATUS "CUDA NVCC Flags: ${CUDA_NVCC_FLAGS}")
        message(STATUS "CUDA Architectures: ${CMAKE_CUDA_ARCHITECTURES}")
    elseif(${CUDA_FAIL_ON_MISSING})
        message(FATAL_ERROR
                "CUDA not found.
                If this is intentional, set '-DSUNSHINE_ENABLE_CUDA=OFF' or '-DCUDA_FAIL_ON_MISSING=OFF'"
        )
    endif()
endif()
if(CUDA_FOUND)
    include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/third-party/nvfbc")
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.h"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.cu"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/cuda.cpp"
            "${CMAKE_SOURCE_DIR}/third-party/nvfbc/NvFBC.h")

    add_compile_definitions(SUNSHINE_BUILD_CUDA)
endif()

# libdrm is required for both DRM (KMS) and Wayland
if(${SUNSHINE_ENABLE_DRM} OR ${SUNSHINE_ENABLE_WAYLAND})
    find_package(LIBDRM REQUIRED)
else()
    set(LIBDRM_FOUND OFF)
endif()
if(LIBDRM_FOUND)
    include_directories(SYSTEM ${LIBDRM_INCLUDE_DIRS})
    list(APPEND PLATFORM_LIBRARIES ${LIBDRM_LIBRARIES})
endif()

# drm
if(${SUNSHINE_ENABLE_DRM})
    find_package(LIBCAP REQUIRED)
else()
    set(LIBCAP_FOUND OFF)
endif()
if(LIBDRM_FOUND AND LIBCAP_FOUND)
    add_compile_definitions(SUNSHINE_BUILD_DRM)
    include_directories(SYSTEM ${LIBCAP_INCLUDE_DIRS})
    list(APPEND PLATFORM_LIBRARIES ${LIBCAP_LIBRARIES})
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/kmsgrab.cpp")
    list(APPEND SUNSHINE_DEFINITIONS EGL_NO_X11=1)
endif()

# evdev
include(dependencies/libevdev_Sunshine)

# vaapi
if(${SUNSHINE_ENABLE_VAAPI})
    find_package(Libva REQUIRED)
else()
    set(LIBVA_FOUND OFF)
endif()
if(LIBVA_FOUND)
    add_compile_definitions(SUNSHINE_BUILD_VAAPI)
    include_directories(SYSTEM ${LIBVA_INCLUDE_DIR})
    list(APPEND PLATFORM_LIBRARIES ${LIBVA_LIBRARIES} ${LIBVA_DRM_LIBRARIES})
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/vaapi.h"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/vaapi.cpp")
endif()

# wayland
if(${SUNSHINE_ENABLE_WAYLAND})
    find_package(Wayland REQUIRED)
else()
    set(WAYLAND_FOUND OFF)
endif()
if(WAYLAND_FOUND)
    add_compile_definitions(SUNSHINE_BUILD_WAYLAND)

    if(NOT SUNSHINE_SYSTEM_WAYLAND_PROTOCOLS)
        set(WAYLAND_PROTOCOLS_DIR "${CMAKE_SOURCE_DIR}/third-party/wayland-protocols")
    else()
        pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
        pkg_check_modules(WAYLAND_PROTOCOLS wayland-protocols REQUIRED)
    endif()

    GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/xdg-output" xdg-output-unstable-v1)
    GEN_WAYLAND("${WAYLAND_PROTOCOLS_DIR}" "unstable/linux-dmabuf" linux-dmabuf-unstable-v1)
    GEN_WAYLAND("${CMAKE_SOURCE_DIR}/third-party/wlr-protocols" "unstable" wlr-screencopy-unstable-v1)

    include_directories(
            SYSTEM
            ${WAYLAND_INCLUDE_DIRS}
            ${CMAKE_BINARY_DIR}/generated-src
    )

    list(APPEND PLATFORM_LIBRARIES ${WAYLAND_LIBRARIES} gbm)
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/wlgrab.cpp"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/wayland.h"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/wayland.cpp")
endif()

# x11
if(${SUNSHINE_ENABLE_X11})
    find_package(X11 REQUIRED)
else()
    set(X11_FOUND OFF)
endif()
if(X11_FOUND)
    add_compile_definitions(SUNSHINE_BUILD_X11)
    include_directories(SYSTEM ${X11_INCLUDE_DIR})
    list(APPEND PLATFORM_LIBRARIES ${X11_LIBRARIES})
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.h"
            "${CMAKE_SOURCE_DIR}/src/platform/linux/x11grab.cpp")
endif()

# XDG portal
if(${SUNSHINE_ENABLE_PORTAL})
    pkg_check_modules(GIO gio-2.0 gio-unix-2.0 REQUIRED)
    pkg_check_modules(PIPEWIRE libpipewire-0.3 REQUIRED)
else()
    set(GIO_FOUND OFF)
    set(PIPEWIRE_FOUND OFF)
endif()
if(PIPEWIRE_FOUND)
    add_compile_definitions(SUNSHINE_BUILD_PORTAL)
    include_directories(SYSTEM ${GIO_INCLUDE_DIRS} ${PIPEWIRE_INCLUDE_DIRS})
    list(APPEND PLATFORM_LIBRARIES ${GIO_LIBRARIES} ${PIPEWIRE_LIBRARIES})
    list(APPEND PLATFORM_TARGET_FILES
            "${CMAKE_SOURCE_DIR}/src/platform/linux/portalgrab.cpp")
endif()

if(NOT ${CUDA_FOUND}
        AND NOT ${WAYLAND_FOUND}
        AND NOT ${X11_FOUND}
        AND NOT ${PIPEWIRE_FOUND}
        AND NOT (${LIBDRM_FOUND} AND ${LIBCAP_FOUND})
        AND NOT ${LIBVA_FOUND})
    message(FATAL_ERROR "Couldn't find either cuda, libva, pipewire, wayland, x11, or (libdrm and libcap)")
endif()

# tray icon
if(${SUNSHINE_ENABLE_TRAY})
    pkg_check_modules(APPINDICATOR ayatana-appindicator3-0.1)
    if(APPINDICATOR_FOUND)
        list(APPEND SUNSHINE_DEFINITIONS TRAY_AYATANA_APPINDICATOR=1)
    else()
        pkg_check_modules(APPINDICATOR appindicator3-0.1)
        if(APPINDICATOR_FOUND)
            list(APPEND SUNSHINE_DEFINITIONS TRAY_LEGACY_APPINDICATOR=1)
        endif ()
    endif()
    pkg_check_modules(LIBNOTIFY libnotify)
    if(NOT APPINDICATOR_FOUND OR NOT LIBNOTIFY_FOUND)
        message(STATUS "APPINDICATOR_FOUND: ${APPINDICATOR_FOUND}")
        message(STATUS "LIBNOTIFY_FOUND: ${LIBNOTIFY_FOUND}")
        message(FATAL_ERROR "Couldn't find either appindicator or libnotify")
    else()
        include_directories(SYSTEM ${APPINDICATOR_INCLUDE_DIRS} ${LIBNOTIFY_INCLUDE_DIRS})
        link_directories(${APPINDICATOR_LIBRARY_DIRS} ${LIBNOTIFY_LIBRARY_DIRS})

        list(APPEND PLATFORM_TARGET_FILES "${CMAKE_SOURCE_DIR}/third-party/tray/src/tray_linux.c")
        list(APPEND SUNSHINE_EXTERNAL_LIBRARIES ${APPINDICATOR_LIBRARIES} ${LIBNOTIFY_LIBRARIES})
    endif()

    set(SUNSHINE_TRAY_PREFIX "${PROJECT_FQDN}")
    list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_TRAY_PREFIX="${SUNSHINE_TRAY_PREFIX}")
else()
    set(SUNSHINE_TRAY 0)
    message(STATUS "Tray icon disabled")
endif()

# These need to be set before adding the inputtino subdirectory in order for them to be picked up
set(LIBEVDEV_CUSTOM_INCLUDE_DIR "${EVDEV_INCLUDE_DIR}")
set(LIBEVDEV_CUSTOM_LIBRARY "${EVDEV_LIBRARY}")
if(FREEBSD)
    set(USE_UHID OFF)
endif()

add_subdirectory("${CMAKE_SOURCE_DIR}/third-party/inputtino")
list(APPEND SUNSHINE_EXTERNAL_LIBRARIES inputtino::libinputtino)
file(GLOB_RECURSE INPUTTINO_SOURCES
        ${CMAKE_SOURCE_DIR}/src/platform/linux/input/inputtino*.h
        ${CMAKE_SOURCE_DIR}/src/platform/linux/input/inputtino*.cpp)
list(APPEND PLATFORM_TARGET_FILES ${INPUTTINO_SOURCES})

# build libevdev before the libinputtino target
if(EXTERNAL_PROJECT_LIBEVDEV_USED)
    add_dependencies(libinputtino libevdev)
endif()

# AppImage and Flatpak
if (${SUNSHINE_BUILD_APPIMAGE})
    list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_BUILD_APPIMAGE=1)
endif ()
if (${SUNSHINE_BUILD_FLATPAK})
    list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_BUILD_FLATPAK=1)
endif ()

list(APPEND PLATFORM_TARGET_FILES
        "${CMAKE_SOURCE_DIR}/src/platform/linux/publish.cpp"
        "${CMAKE_SOURCE_DIR}/src/platform/linux/graphics.h"
        "${CMAKE_SOURCE_DIR}/src/platform/linux/graphics.cpp"
        "${CMAKE_SOURCE_DIR}/src/platform/linux/misc.h"
        "${CMAKE_SOURCE_DIR}/src/platform/linux/misc.cpp"
        "${CMAKE_SOURCE_DIR}/src/platform/linux/audio.cpp")

list(APPEND PLATFORM_LIBRARIES
        dl
        pulse
        pulse-simple)

list(APPEND SUNSHINE_EXTERNAL_LIBRARIES glad)


================================================
FILE: cmake/compile_definitions/macos.cmake
================================================
# macos specific compile definitions

add_compile_definitions(SUNSHINE_PLATFORM="macos")

if (SUNSHINE_BUILD_HOMEBREW)
    set(SUNSHINE_ASSETS_DIR "${CMAKE_INSTALL_PREFIX}/${SUNSHINE_ASSETS_DIR}")
else()
    # Bundle layout for macOS app builds
    set(SUNSHINE_ASSETS_DIR "${CMAKE_PROJECT_NAME}.app/Contents/Resources/assets")
    set(SUNSHINE_ASSETS_DIR_DEF "../Resources/assets")
endif()

set(MACOS_LINK_DIRECTORIES
        /opt/homebrew/lib
        /opt/local/lib
        /usr/local/lib)

foreach(dir ${MACOS_LINK_DIRECTORIES})
    if(EXISTS ${dir})
        link_directories(${dir})
    endif()
endforeach()

if(NOT BOOST_USE_STATIC AND NOT FETCH_CONTENT_BOOST_USED)
    ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK)
endif()

list(APPEND SUNSHINE_EXTERNAL_LIBRARIES
        ${APP_KIT_LIBRARY}
        ${APP_SERVICES_LIBRARY}
        ${AV_FOUNDATION_LIBRARY}
        ${CORE_MEDIA_LIBRARY}
        ${CORE_VIDEO_LIBRARY}
        ${FOUNDATION_LIBRARY}
        ${VIDEO_TOOLBOX_LIBRARY})

set(APPLE_PLIST_TEMPLATE "${SUNSHINE_SOURCE_ASSETS_DIR}/macos/build/Info.plist.in")
set(APPLE_PLIST_FILE "${CMAKE_BINARY_DIR}/Info.plist")
configure_file("${APPLE_PLIST_TEMPLATE}" "${APPLE_PLIST_FILE}" @ONLY)

set(PLATFORM_TARGET_FILES
        "${CMAKE_SOURCE_DIR}/src/platform/macos/av_audio.h"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/av_audio.m"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/av_img_t.h"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/av_video.h"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/av_video.m"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/display.mm"
        "${CMAKE_SOURCE_DIR}/src/platform/macos/input.cpp"
        "${CMAKE_SOURCE_DIR}/src/platf
Download .txt
gitextract_mnfxyeca/

├── .clang-format
├── .dockerignore
├── .flake8
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── config.yml
│   ├── copilot-instructions.md
│   ├── dependabot.yml
│   ├── matchers/
│   │   ├── copr-ci.json
│   │   ├── docker.json
│   │   ├── gcc-strip3.json
│   │   └── gcc.json
│   ├── semantic.yml
│   └── workflows/
│       ├── _codeql.yml
│       ├── _common-lint.yml
│       ├── _release-notifier.yml
│       ├── _update-changelog.yml
│       ├── _update-docs.yml
│       ├── _update-flathub-repo.yml
│       ├── _update-homebrew-repo.yml
│       ├── _update-pacman-repo.yml
│       ├── _update-winget-repo.yml
│       ├── ci-archlinux.yml
│       ├── ci-bundle.yml
│       ├── ci-copr.yml
│       ├── ci-flatpak.yml
│       ├── ci-freebsd.yml
│       ├── ci-homebrew.yml
│       ├── ci-linux.yml
│       ├── ci-macos.yml
│       ├── ci-windows.yml
│       ├── ci.yml
│       ├── localize.yml
│       ├── release-notifier-moonlight.yml
│       └── update-pages.yml
├── .gitignore
├── .gitmodules
├── .prettierrc.json
├── .readthedocs.yaml
├── .rstcheck.cfg
├── CMakeLists.txt
├── DOCKER_README.md
├── LICENSE
├── NOTICE
├── README.md
├── cmake/
│   ├── FindLIBCAP.cmake
│   ├── FindLIBDRM.cmake
│   ├── FindLibva.cmake
│   ├── FindSystemd.cmake
│   ├── FindUdev.cmake
│   ├── FindWayland.cmake
│   ├── compile_definitions/
│   │   ├── common.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── dependencies/
│   │   ├── Boost_Sunshine.cmake
│   │   ├── FindOpus.cmake
│   │   ├── common.cmake
│   │   ├── ffmpeg.cmake
│   │   ├── glad.cmake
│   │   ├── libevdev_Sunshine.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── nlohmann_json.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── macros/
│   │   ├── common.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   └── windows.cmake
│   ├── packaging/
│   │   ├── common.cmake
│   │   ├── freebsd_custom_cpack.cmake
│   │   ├── linux.cmake
│   │   ├── macos.cmake
│   │   ├── unix.cmake
│   │   ├── windows.cmake
│   │   ├── windows_nsis.cmake
│   │   ├── windows_wix.cmake
│   │   └── wix_resources/
│   │       ├── patch.xml
│   │       └── sunshine-installer.wxs
│   ├── prep/
│   │   ├── build_version.cmake
│   │   ├── constants.cmake
│   │   ├── init.cmake
│   │   ├── options.cmake
│   │   └── special_package_configuration.cmake
│   └── targets/
│       ├── common.cmake
│       ├── linux.cmake
│       ├── macos.cmake
│       ├── unix.cmake
│       └── windows.cmake
├── codecov.yml
├── crowdin.yml
├── docker/
│   ├── clion-toolchain.dockerfile
│   ├── debian-trixie.dockerfile
│   ├── ubuntu-22.04.dockerfile
│   └── ubuntu-24.04.dockerfile
├── docs/
│   ├── Doxyfile
│   ├── api.js
│   ├── api.md
│   ├── app_examples.md
│   ├── awesome_sunshine.md
│   ├── building.md
│   ├── changelog.md
│   ├── configuration.js
│   ├── configuration.md
│   ├── contributing.md
│   ├── doc-styles.css
│   ├── gamestream_migration.md
│   ├── getting_started.md
│   ├── guides.md
│   ├── legal.md
│   ├── maintainers/
│   │   ├── README.md
│   │   └── release.md
│   ├── performance_tuning.md
│   ├── third_party_packages.md
│   └── troubleshooting.md
├── gh-pages-template/
│   ├── .readthedocs.yaml
│   ├── _config.yml
│   ├── _data/
│   │   ├── clients.yml
│   │   └── features.yml
│   └── index.html
├── package.json
├── packaging/
│   ├── linux/
│   │   ├── AppImage/
│   │   │   ├── AppRun
│   │   │   └── dev.lizardbyte.app.Sunshine.desktop
│   │   ├── Arch/
│   │   │   ├── PKGBUILD
│   │   │   └── sunshine.install
│   │   ├── app-dev.lizardbyte.app.Sunshine.service.in
│   │   ├── copr/
│   │   │   └── Sunshine.spec
│   │   ├── dev.lizardbyte.app.Sunshine.desktop
│   │   ├── dev.lizardbyte.app.Sunshine.metainfo.xml
│   │   ├── dev.lizardbyte.app.Sunshine.terminal.desktop
│   │   ├── flatpak/
│   │   │   ├── README.md
│   │   │   ├── apps.json
│   │   │   ├── dev.lizardbyte.app.Sunshine.desktop
│   │   │   ├── dev.lizardbyte.app.Sunshine.yml
│   │   │   ├── exceptions.json
│   │   │   ├── flathub.json
│   │   │   ├── modules/
│   │   │   │   ├── avahi.json
│   │   │   │   ├── boost.json
│   │   │   │   ├── cuda.json
│   │   │   │   ├── ffmpeg.json
│   │   │   │   ├── libevdev.json
│   │   │   │   ├── miniupnpc.json
│   │   │   │   ├── nlohmann_json.json
│   │   │   │   ├── numactl.json
│   │   │   │   └── xvfb/
│   │   │   │       ├── xvfb-run
│   │   │   │       └── xvfb.json
│   │   │   └── scripts/
│   │   │       ├── additional-install.sh
│   │   │       ├── remove-additional-install.sh
│   │   │       └── sunshine.sh
│   │   └── patches/
│   │       ├── aarch64/
│   │       │   ├── cuda-12-math_functions.patch
│   │       │   └── cuda-13-math_functions.patch
│   │       └── x86_64/
│   │           ├── cuda-12-math_functions.patch
│   │           └── cuda-13-math_functions.patch
│   └── sunshine.rb
├── pyproject.toml
├── scripts/
│   ├── _locale.py
│   ├── icons/
│   │   └── convert_and_pack.sh
│   ├── linux_build.sh
│   ├── macos_build.sh
│   └── update_clang_format.py
├── src/
│   ├── audio.cpp
│   ├── audio.h
│   ├── cbs.cpp
│   ├── cbs.h
│   ├── config.cpp
│   ├── config.h
│   ├── confighttp.cpp
│   ├── confighttp.h
│   ├── crypto.cpp
│   ├── crypto.h
│   ├── display_device.cpp
│   ├── display_device.h
│   ├── entry_handler.cpp
│   ├── entry_handler.h
│   ├── file_handler.cpp
│   ├── file_handler.h
│   ├── globals.cpp
│   ├── globals.h
│   ├── httpcommon.cpp
│   ├── httpcommon.h
│   ├── input.cpp
│   ├── input.h
│   ├── logging.cpp
│   ├── logging.h
│   ├── main.cpp
│   ├── main.h
│   ├── move_by_copy.h
│   ├── network.cpp
│   ├── network.h
│   ├── nvenc/
│   │   ├── nvenc_base.cpp
│   │   ├── nvenc_base.h
│   │   ├── nvenc_colorspace.h
│   │   ├── nvenc_config.h
│   │   ├── nvenc_d3d11.cpp
│   │   ├── nvenc_d3d11.h
│   │   ├── nvenc_d3d11_native.cpp
│   │   ├── nvenc_d3d11_native.h
│   │   ├── nvenc_d3d11_on_cuda.cpp
│   │   ├── nvenc_d3d11_on_cuda.h
│   │   ├── nvenc_encoded_frame.h
│   │   ├── nvenc_utils.cpp
│   │   └── nvenc_utils.h
│   ├── nvhttp.cpp
│   ├── nvhttp.h
│   ├── platform/
│   │   ├── common.h
│   │   ├── linux/
│   │   │   ├── audio.cpp
│   │   │   ├── cuda.cpp
│   │   │   ├── cuda.cu
│   │   │   ├── cuda.h
│   │   │   ├── graphics.cpp
│   │   │   ├── graphics.h
│   │   │   ├── input/
│   │   │   │   ├── inputtino.cpp
│   │   │   │   ├── inputtino_common.h
│   │   │   │   ├── inputtino_gamepad.cpp
│   │   │   │   ├── inputtino_gamepad.h
│   │   │   │   ├── inputtino_keyboard.cpp
│   │   │   │   ├── inputtino_keyboard.h
│   │   │   │   ├── inputtino_mouse.cpp
│   │   │   │   ├── inputtino_mouse.h
│   │   │   │   ├── inputtino_pen.cpp
│   │   │   │   ├── inputtino_pen.h
│   │   │   │   ├── inputtino_touch.cpp
│   │   │   │   └── inputtino_touch.h
│   │   │   ├── kmsgrab.cpp
│   │   │   ├── misc.cpp
│   │   │   ├── misc.h
│   │   │   ├── portalgrab.cpp
│   │   │   ├── publish.cpp
│   │   │   ├── vaapi.cpp
│   │   │   ├── vaapi.h
│   │   │   ├── wayland.cpp
│   │   │   ├── wayland.h
│   │   │   ├── wlgrab.cpp
│   │   │   ├── x11grab.cpp
│   │   │   └── x11grab.h
│   │   ├── macos/
│   │   │   ├── av_audio.h
│   │   │   ├── av_audio.m
│   │   │   ├── av_img_t.h
│   │   │   ├── av_video.h
│   │   │   ├── av_video.m
│   │   │   ├── display.mm
│   │   │   ├── input.cpp
│   │   │   ├── microphone.mm
│   │   │   ├── misc.h
│   │   │   ├── misc.mm
│   │   │   ├── nv12_zero_device.cpp
│   │   │   ├── nv12_zero_device.h
│   │   │   └── publish.cpp
│   │   └── windows/
│   │       ├── PolicyConfig.h
│   │       ├── audio.cpp
│   │       ├── display.h
│   │       ├── display_base.cpp
│   │       ├── display_ram.cpp
│   │       ├── display_vram.cpp
│   │       ├── display_wgc.cpp
│   │       ├── input.cpp
│   │       ├── keylayout.h
│   │       ├── misc.cpp
│   │       ├── misc.h
│   │       ├── nvprefs/
│   │       │   ├── driver_settings.cpp
│   │       │   ├── driver_settings.h
│   │       │   ├── nvapi_opensource_wrapper.cpp
│   │       │   ├── nvprefs_common.cpp
│   │       │   ├── nvprefs_common.h
│   │       │   ├── nvprefs_interface.cpp
│   │       │   ├── nvprefs_interface.h
│   │       │   ├── undo_data.cpp
│   │       │   ├── undo_data.h
│   │       │   ├── undo_file.cpp
│   │       │   └── undo_file.h
│   │       ├── publish.cpp
│   │       ├── utf_utils.cpp
│   │       ├── utf_utils.h
│   │       └── windows.rc
│   ├── process.cpp
│   ├── process.h
│   ├── round_robin.h
│   ├── rswrapper.c
│   ├── rswrapper.h
│   ├── rtsp.cpp
│   ├── rtsp.h
│   ├── stat_trackers.cpp
│   ├── stat_trackers.h
│   ├── stream.cpp
│   ├── stream.h
│   ├── sync.h
│   ├── system_tray.cpp
│   ├── system_tray.h
│   ├── task_pool.h
│   ├── thread_pool.h
│   ├── thread_safe.h
│   ├── upnp.cpp
│   ├── upnp.h
│   ├── utility.h
│   ├── uuid.h
│   ├── video.cpp
│   ├── video.h
│   ├── video_colorspace.cpp
│   └── video_colorspace.h
├── src_assets/
│   ├── bsd/
│   │   └── misc/
│   │       ├── +POST_INSTALL
│   │       └── +PRE_DEINSTALL
│   ├── common/
│   │   └── assets/
│   │       └── web/
│   │           ├── Checkbox.vue
│   │           ├── Navbar.vue
│   │           ├── PlatformLayout.vue
│   │           ├── ResourceCard.vue
│   │           ├── SimpleIcon.vue
│   │           ├── ThemeToggle.vue
│   │           ├── apps.html
│   │           ├── config.html
│   │           ├── configs/
│   │           │   └── tabs/
│   │           │       ├── Advanced.vue
│   │           │       ├── AudioVideo.vue
│   │           │       ├── ContainerEncoders.vue
│   │           │       ├── Files.vue
│   │           │       ├── General.vue
│   │           │       ├── Inputs.vue
│   │           │       ├── Network.vue
│   │           │       ├── audiovideo/
│   │           │       │   ├── AdapterNameSelector.vue
│   │           │       │   ├── DisplayDeviceOptions.vue
│   │           │       │   ├── DisplayModesSettings.vue
│   │           │       │   └── DisplayOutputSelector.vue
│   │           │       └── encoders/
│   │           │           ├── AmdAmfEncoder.vue
│   │           │           ├── IntelQuickSyncEncoder.vue
│   │           │           ├── NvidiaNvencEncoder.vue
│   │           │           ├── SoftwareEncoder.vue
│   │           │           ├── VAAPIEncoder.vue
│   │           │           └── VideotoolboxEncoder.vue
│   │           ├── featured.html
│   │           ├── index.html
│   │           ├── init.js
│   │           ├── locale.js
│   │           ├── password.html
│   │           ├── pin.html
│   │           ├── platform-i18n.js
│   │           ├── public/
│   │           │   └── assets/
│   │           │       ├── css/
│   │           │       │   └── sunshine.css
│   │           │       └── locale/
│   │           │           ├── bg.json
│   │           │           ├── cs.json
│   │           │           ├── de.json
│   │           │           ├── en.json
│   │           │           ├── en_GB.json
│   │           │           ├── en_US.json
│   │           │           ├── es.json
│   │           │           ├── fr.json
│   │           │           ├── hu.json
│   │           │           ├── it.json
│   │           │           ├── ja.json
│   │           │           ├── ko.json
│   │           │           ├── pl.json
│   │           │           ├── pt.json
│   │           │           ├── pt_BR.json
│   │           │           ├── ru.json
│   │           │           ├── sv.json
│   │           │           ├── tr.json
│   │           │           ├── uk.json
│   │           │           ├── vi.json
│   │           │           ├── zh.json
│   │           │           └── zh_TW.json
│   │           ├── sunshine_version.js
│   │           ├── template_header.html
│   │           ├── theme.js
│   │           ├── troubleshooting.html
│   │           └── welcome.html
│   ├── linux/
│   │   ├── assets/
│   │   │   ├── apps.json
│   │   │   └── shaders/
│   │   │       └── opengl/
│   │   │           ├── ConvertUV.frag
│   │   │           ├── ConvertUV.vert
│   │   │           ├── ConvertY.frag
│   │   │           ├── Scene.frag
│   │   │           └── Scene.vert
│   │   └── misc/
│   │       ├── 60-sunshine.conf
│   │       ├── 60-sunshine.rules
│   │       └── postinst
│   ├── macos/
│   │   └── assets/
│   │       └── apps.json
│   └── windows/
│       ├── assets/
│       │   ├── apps.json
│       │   └── shaders/
│       │       └── directx/
│       │           ├── convert_yuv420_packed_uv_type0_ps.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_ps_linear.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_packed_uv_type0_vs.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps_linear.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_packed_uv_type0s_vs.hlsl
│       │           ├── convert_yuv420_planar_y_ps.hlsl
│       │           ├── convert_yuv420_planar_y_ps_linear.hlsl
│       │           ├── convert_yuv420_planar_y_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv420_planar_y_vs.hlsl
│       │           ├── convert_yuv444_packed_ayuv_ps.hlsl
│       │           ├── convert_yuv444_packed_ayuv_ps_linear.hlsl
│       │           ├── convert_yuv444_packed_vs.hlsl
│       │           ├── convert_yuv444_packed_y410_ps.hlsl
│       │           ├── convert_yuv444_packed_y410_ps_linear.hlsl
│       │           ├── convert_yuv444_packed_y410_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv444_planar_ps.hlsl
│       │           ├── convert_yuv444_planar_ps_linear.hlsl
│       │           ├── convert_yuv444_planar_ps_perceptual_quantizer.hlsl
│       │           ├── convert_yuv444_planar_vs.hlsl
│       │           ├── cursor_ps.hlsl
│       │           ├── cursor_ps_normalize_white.hlsl
│       │           ├── cursor_vs.hlsl
│       │           └── include/
│       │               ├── base_vs.hlsl
│       │               ├── base_vs_types.hlsl
│       │               ├── common.hlsl
│       │               ├── convert_base.hlsl
│       │               ├── convert_linear_base.hlsl
│       │               ├── convert_perceptual_quantizer_base.hlsl
│       │               ├── convert_yuv420_packed_uv_ps_base.hlsl
│       │               ├── convert_yuv420_planar_y_ps_base.hlsl
│       │               └── convert_yuv444_ps_base.hlsl
│       └── misc/
│           ├── autostart/
│           │   └── autostart-service.bat
│           ├── firewall/
│           │   ├── add-firewall-rule.bat
│           │   └── delete-firewall-rule.bat
│           ├── migration/
│           │   └── migrate-config.bat
│           ├── path/
│           │   └── update-path.bat
│           ├── service/
│           │   ├── install-service.bat
│           │   └── uninstall-service.bat
│           └── sunshine-setup.ps1
├── tests/
│   ├── CMakeLists.txt
│   ├── fixtures/
│   │   └── http/
│   │       ├── hello-redirect.txt
│   │       └── hello.txt
│   ├── integration/
│   │   ├── test_config_consistency.cpp
│   │   ├── test_external_commands.cpp
│   │   └── test_locale_consistency.cpp
│   ├── tests_common.h
│   ├── tests_environment.h
│   ├── tests_events.h
│   ├── tests_log_checker.h
│   ├── tests_main.cpp
│   └── unit/
│       ├── platform/
│       │   ├── test_common.cpp
│       │   └── windows/
│       │       └── test_utf_utils.cpp
│       ├── test_audio.cpp
│       ├── test_confighttp.cpp
│       ├── test_display_device.cpp
│       ├── test_entry_handler.cpp
│       ├── test_file_handler.cpp
│       ├── test_http_pairing.cpp
│       ├── test_httpcommon.cpp
│       ├── test_logging.cpp
│       ├── test_mouse.cpp
│       ├── test_network.cpp
│       ├── test_process.cpp
│       ├── test_rswrapper.cpp
│       ├── test_stream.cpp
│       └── test_video.cpp
├── third-party/
│   ├── .clang-format-ignore
│   └── nvfbc/
│       ├── NvFBC.h
│       └── helper_math.h
├── tools/
│   ├── CMakeLists.txt
│   ├── audio.cpp
│   ├── dxgi.cpp
│   └── sunshinesvc.cpp
└── vite.config.js
Download .txt
SYMBOL INDEX (2054 symbols across 166 files)

FILE: docs/api.js
  function generateExamples (line 1) | function generateExamples(endpoint, method, body = null) {
  function hashString (line 46) | function hashString(str) {
  function createTabs (line 56) | function createTabs(examples) {
  function copyContent (line 93) | function copyContent() {
  function openTab (line 116) | function openTab(evt, lang) {

FILE: packaging/sunshine.rb
  class Sunshine (line 3) | class Sunshine < Formula
    method setup_build_environment (line 139) | def setup_build_environment
    method setup_linux_gcc_environment (line 158) | def setup_linux_gcc_environment
    method base_cmake_args (line 165) | def base_cmake_args
    method add_test_args (line 184) | def add_test_args(args)
    method add_docs_args (line 194) | def add_docs_args(args)
    method add_boost_args (line 204) | def add_boost_args(args)
    method configure_static_boost (line 213) | def configure_static_boost(args)
    method add_cuda_args (line 230) | def add_cuda_args(args)
    method configure_cuda (line 241) | def configure_cuda(args)
    method build_cmake_args (line 252) | def build_cmake_args
    method build_and_install_project (line 261) | def build_and_install_project
    method install_platform_specific_files (line 270) | def install_platform_specific_files
    method install (line 279) | def install
    method post_install (line 289) | def post_install
    method caveats (line 307) | def caveats

FILE: scripts/_locale.py
  function x_extract (line 50) | def x_extract():
  function babel_init (line 112) | def babel_init(locale_code: str):
  function babel_update (line 130) | def babel_update():
  function babel_compile (line 145) | def babel_compile():

FILE: scripts/update_clang_format.py
  function clang_format (line 21) | def clang_format(file: str):
  function main (line 26) | def main():

FILE: src/audio.cpp
  type audio (line 20) | namespace audio {
    function encodeThread (line 86) | void encodeThread(sample_queue_t samples, config_t config, void *chann...
    function capture (line 131) | void capture(safe::mail_t mail, config_t config, void *channel_data) {
    function audio_ctx_ref_t (line 249) | audio_ctx_ref_t get_audio_ctx_ref() {
    function is_audio_ctx_sink_available (line 254) | bool is_audio_ctx_sink_available(const audio_ctx_t &ctx) {
    function map_stream (line 267) | int map_stream(int channels, bool quality) {
    function start_audio_control (line 280) | int start_audio_control(audio_ctx_t &ctx) {
    function stop_audio_control (line 307) | void stop_audio_control(audio_ctx_t &ctx) {
    function apply_surround_params (line 321) | void apply_surround_params(opus_stream_config_t &stream, const stream_...

FILE: src/audio.h
  function namespace (line 14) | namespace audio {

FILE: src/cbs.cpp
  type cbs (line 21) | namespace cbs {
    function close (line 22) | void close(CodedBitstreamContext *c) {
    class frag_t (line 28) | class frag_t: public CodedBitstreamFragment {
      method frag_t (line 30) | frag_t(frag_t &&o) {
      method frag_t (line 37) | frag_t() {
      method frag_t (line 41) | frag_t &operator=(frag_t &&o) {
    function write (line 57) | util::buffer_t<std::uint8_t> write(cbs::ctx_t &cbs_ctx, std::uint8_t n...
    function write (line 82) | util::buffer_t<std::uint8_t> write(std::uint8_t nal, void *uh, AVCodec...
    function h264_t (line 89) | h264_t make_sps_h264(const AVCodecContext *avctx, const AVPacket *pack...
    function hevc_t (line 145) | hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *pack...
    function validate_sps (line 222) | bool validate_sps(const AVPacket *packet, int codec_id) {

FILE: src/cbs.h
  type AVPacket (line 10) | struct AVPacket
  type AVCodecContext (line 11) | struct AVCodecContext
  function namespace (line 13) | namespace cbs {

FILE: src/config.cpp
  type config (line 49) | namespace config {
    type nv (line 51) | namespace nv {
      function twopass_from_view (line 53) | nvenc::nvenc_two_pass twopass_from_view(const std::string_view &pres...
    type amd (line 69) | namespace amd {
      type quality_av1_e (line 120) | enum class quality_av1_e : int {
      type quality_hevc_e (line 126) | enum class quality_hevc_e : int {
      type quality_h264_e (line 132) | enum class quality_h264_e : int {
      type rc_av1_e (line 138) | enum class rc_av1_e : int {
      type rc_hevc_e (line 145) | enum class rc_hevc_e : int {
      type rc_h264_e (line 152) | enum class rc_h264_e : int {
      type usage_av1_e (line 159) | enum class usage_av1_e : int {
      type usage_hevc_e (line 167) | enum class usage_hevc_e : int {
      type usage_h264_e (line 175) | enum class usage_h264_e : int {
      type coder_e (line 183) | enum coder_e : int {
      function quality_from_view (line 190) | ::std::optional<int> quality_from_view(const ::std::string_view &qua...
      function rc_from_view (line 202) | ::std::optional<int> rc_from_view(const ::std::string_view &rc, cons...
      function usage_from_view (line 215) | ::std::optional<int> usage_from_view(const ::std::string_view &usage...
      function coder_from_view (line 228) | int coder_from_view(const ::std::string_view &coder) {
    type qsv (line 243) | namespace qsv {
      type preset_e (line 244) | enum preset_e : int {
      type cavlc_e (line 254) | enum cavlc_e : int {
      function preset_from_view (line 260) | std::optional<int> preset_from_view(const std::string_view &preset) {
      function coder_from_view (line 275) | std::optional<int> coder_from_view(const std::string_view &coder) {
    type vt (line 290) | namespace vt {
      type coder_e (line 292) | enum coder_e : int {
      function coder_from_view (line 298) | int coder_from_view(const std::string_view &coder) {
      function allow_software_from_view (line 312) | int allow_software_from_view(const std::string_view &software) {
      function force_software_from_view (line 320) | int force_software_from_view(const std::string_view &software) {
      function rt_from_view (line 328) | int rt_from_view(const std::string_view &rt) {
    type sw (line 338) | namespace sw {
      function svtav1_preset_from_view (line 339) | int svtav1_preset_from_view(const std::string_view &preset) {
    type dd (line 357) | namespace dd {
      function config_option_from_view (line 358) | video_t::dd_t::config_option_e config_option_from_view(const std::st...
      function resolution_option_from_view (line 371) | video_t::dd_t::resolution_option_e resolution_option_from_view(const...
      function refresh_rate_option_from_view (line 384) | video_t::dd_t::refresh_rate_option_e refresh_rate_option_from_view(c...
      function hdr_option_from_view (line 397) | video_t::dd_t::hdr_option_e hdr_option_from_view(const std::string_v...
      function mode_remapping_from_view (line 409) | video_t::dd_t::mode_remapping_t mode_remapping_from_view(const std::...
    function endline (line 586) | bool endline(char ch) {
    function space_tab (line 590) | bool space_tab(char ch) {
    function whitespace (line 594) | bool whitespace(char ch) {
    function to_string (line 598) | std::string to_string(const char *begin, const char *end) {
    function It (line 614) | It skip_list(It skipper, It end) {
    function parse_config (line 671) | std::unordered_map<std::string, std::string> parse_config(const std::s...
    function string_f (line 696) | void string_f(std::unordered_map<std::string, std::string> &vars, cons...
    function generic_f (line 708) | void generic_f(std::unordered_map<std::string, std::string> &vars, con...
    function string_restricted_f (line 716) | void string_restricted_f(std::unordered_map<std::string, std::string> ...
    function string_list_f (line 728) | void string_list_f(std::unordered_map<std::string, std::string> &vars,...
    function path_f (line 749) | void path_f(std::unordered_map<std::string, std::string> &vars, const ...
    function path_f (line 773) | void path_f(std::unordered_map<std::string, std::string> &vars, const ...
    function int_f (line 781) | void int_f(std::unordered_map<std::string, std::string> &vars, const s...
    function int_f (line 805) | void int_f(std::unordered_map<std::string, std::string> &vars, const s...
    function int_f (line 830) | void int_f(std::unordered_map<std::string, std::string> &vars, const s...
    function int_f (line 839) | void int_f(std::unordered_map<std::string, std::string> &vars, const s...
    function int_between_f (line 847) | void int_between_f(std::unordered_map<std::string, std::string> &vars,...
    function to_bool (line 858) | bool to_bool(std::string &boolean) {
    function bool_f (line 871) | void bool_f(std::unordered_map<std::string, std::string> &vars, const ...
    function double_f (line 882) | void double_f(std::unordered_map<std::string, std::string> &vars, cons...
    function double_between_f (line 900) | void double_between_f(std::unordered_map<std::string, std::string> &va...
    function list_string_f (line 911) | void list_string_f(std::unordered_map<std::string, std::string> &vars,...
    function list_prep_cmd_f (line 950) | void list_prep_cmd_f(std::unordered_map<std::string, std::string> &var...
    function list_int_f (line 976) | void list_int_f(std::unordered_map<std::string, std::string> &vars, co...
    function map_int_int_f (line 1009) | void map_int_int_f(std::unordered_map<std::string, std::string> &vars,...
    function apply_flags (line 1028) | int apply_flags(const char *line) {
    function apply_config (line 1065) | void apply_config(std::unordered_map<std::string, std::string> &&vars) {
    function parse (line 1367) | int parse(int argc, char *argv[]) {

FILE: src/config.h
  function namespace (line 18) | namespace config {

FILE: src/confighttp.cpp
  type confighttp (line 49) | namespace confighttp {
    type op_e (line 59) | enum class op_e {
    type csrf_token_t (line 65) | struct csrf_token_t {
    function print_req (line 82) | void print_req(const req_https_t &request) {
    function send_response (line 104) | void send_response(const resp_https_t &response, const nlohmann::json ...
    function send_unauthorized (line 117) | void send_unauthorized(const resp_https_t &response, const req_https_t...
    function send_redirect (line 144) | void send_redirect(const resp_https_t &response, const req_https_t &re...
    function authenticate (line 161) | bool authenticate(const resp_https_t &response, const req_https_t &req...
    function not_found (line 210) | void not_found(const resp_https_t &response, [[maybe_unused]] const re...
    function bad_request (line 231) | void bad_request(const resp_https_t &response, [[maybe_unused]] const ...
    function check_content_type (line 253) | bool check_content_type(const resp_https_t &response, const req_https_...
    function get_client_id (line 284) | std::string get_client_id(const req_https_t &request) {
    function generate_csrf_token (line 304) | std::string generate_csrf_token(const std::string &client_id) {
    function validate_stored_csrf_token (line 333) | bool validate_stored_csrf_token(const resp_https_t &response, const re...
    function validate_csrf_token (line 356) | bool validate_csrf_token(const resp_https_t &response, const req_https...
    function check_app_index (line 417) | bool check_app_index(const resp_https_t &response, const req_https_t &...
    function getPage (line 441) | void getPage(const resp_https_t &response, const req_https_t &request,...
    function getFaviconImage (line 472) | void getFaviconImage(const resp_https_t &response, const req_https_t &...
    function getSunshineLogoImage (line 490) | void getSunshineLogoImage(const resp_https_t &response, const req_http...
    function isChildPath (line 507) | bool isChildPath(fs::path const &base, fs::path const &query) {
    function getAsset (line 517) | void getAsset(const resp_https_t &response, const req_https_t &request) {
    function getCSRFToken (line 562) | void getCSRFToken(const resp_https_t &response, const req_https_t &req...
    function getApps (line 584) | void getApps(const resp_https_t &response, const req_https_t &request) {
    function saveApp (line 669) | void saveApp(const resp_https_t &response, const req_https_t &request) {
    function closeApp (line 744) | void closeApp(const resp_https_t &response, const req_https_t &request) {
    function deleteApp (line 770) | void deleteApp(const resp_https_t &response, const req_https_t &reques...
    function getClients (line 821) | void getClients(const resp_https_t &response, const req_https_t &reque...
    function unpair (line 849) | void unpair(const resp_https_t &response, const req_https_t &request) {
    function unpairAll (line 887) | void unpairAll(const resp_https_t &response, const req_https_t &reques...
    function getConfig (line 914) | void getConfig(const resp_https_t &response, const req_https_t &reques...
    function getLocale (line 942) | void getLocale(const resp_https_t &response, const req_https_t &reques...
    function saveConfig (line 968) | void saveConfig(const resp_https_t &response, const req_https_t &reque...
    function getCover (line 1017) | void getCover(const resp_https_t &response, const req_https_t &request) {
    function uploadCover (line 1087) | void uploadCover(const resp_https_t &response, const req_https_t &requ...
    function getLogs (line 1143) | void getLogs(const resp_https_t &response, const req_https_t &request) {
    function savePassword (line 1175) | void savePassword(const resp_https_t &response, const req_https_t &req...
    function savePin (line 1253) | void savePin(const resp_https_t &response, const req_https_t &request) {
    function resetDisplayDevicePersistence (line 1297) | void resetDisplayDevicePersistence(const resp_https_t &response, const...
    function restart (line 1321) | void restart(const resp_https_t &response, const req_https_t &request) {
    function getViGEmBusStatus (line 1344) | void getViGEmBusStatus(const resp_https_t &response, const req_https_t...
    function installViGEmBus (line 1402) | void installViGEmBus(const resp_https_t &response, const req_https_t &...
    function is_browsable_executable (line 1471) | bool is_browsable_executable([[maybe_unused]] const fs::directory_entr...
    function get_windows_drives (line 1489) | nlohmann::json get_windows_drives() {
    function build_browse_entries (line 1513) | nlohmann::json build_browse_entries(const fs::path &dir_path, const st...
    function browseDirectory (line 1576) | void browseDirectory(const resp_https_t &response, const req_https_t &...
    function start (line 1652) | void start() {

FILE: src/confighttp.h
  function namespace (line 21) | namespace confighttp {

FILE: src/crypto.cpp
  type crypto (line 12) | namespace crypto {
    function openssl_verify_cb (line 31) | static int openssl_verify_cb(int ok, X509_STORE_CTX *ctx) {
    type cipher (line 90) | namespace cipher {
      function init_decrypt_gcm (line 92) | static int init_decrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv...
      function init_encrypt_gcm (line 115) | static int init_encrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv...
      function init_encrypt_cbc (line 135) | static int init_encrypt_cbc(cipher_ctx_t &ctx, aes_t *key, aes_t *iv...
    function aes_t (line 326) | aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::stri...
    function sha256_t (line 342) | sha256_t hash(const std::string_view &plaintext) {
    function x509_t (line 348) | x509_t x509(const std::string_view &x) {
    function pkey_t (line 359) | pkey_t pkey(const std::string_view &k) {
    function pem (line 370) | std::string pem(x509_t &x509) {
    function pem (line 380) | std::string pem(pkey_t &pkey) {
    function signature (line 390) | std::string_view signature(const x509_t &x) {
    function rand (line 399) | std::string rand(std::size_t bytes) {
    function sign (line 408) | std::vector<uint8_t> sign(const pkey_t &pkey, const std::string_view &...
    function creds_t (line 432) | creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
    function sign256 (line 475) | std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_vie...
    function verify (line 479) | bool verify(const x509_t &x509, const std::string_view &data, const st...
    function verify256 (line 499) | bool verify256(const x509_t &x509, const std::string_view &data, const...
    function md_ctx_destroy (line 503) | void md_ctx_destroy(EVP_MD_CTX *ctx) {
    function rand_alphabet (line 507) | std::string rand_alphabet(std::size_t bytes, const std::string_view &a...

FILE: src/crypto.h
  function namespace (line 19) | namespace crypto {

FILE: src/display_device.cpp
  type display_device (line 30) | namespace display_device {
    class sunshine_audio_context_t (line 50) | class sunshine_audio_context_t: public AudioContextInterface {
      method capture (line 52) | [[nodiscard]] bool capture() override {
      method isCaptured (line 63) | [[nodiscard]] bool isCaptured() const override {
      method release (line 75) | void release() override {
      type audio_context_t (line 97) | struct audio_context_t {
    function stou (line 124) | unsigned int stou(const std::string &value) {
    function parse_resolution_string (line 150) | bool parse_resolution_string(const std::string &input, std::optional<R...
    function parse_refresh_rate_string (line 198) | bool parse_refresh_rate_string(const std::string &input, std::optional...
    function parse_device_prep_option (line 271) | std::optional<SingleDisplayConfiguration::DevicePreparation> parse_dev...
    function parse_resolution_option (line 306) | bool parse_resolution_option(const config::video_t &video_config, cons...
    function parse_refresh_rate_option (line 364) | bool parse_refresh_rate_option(const config::video_t &video_config, co...
    function parse_hdr_option (line 411) | std::optional<HdrState> parse_hdr_option(const config::video_t &video_...
    type remapping_type_e (line 427) | enum class remapping_type_e {
    function determine_remapping_type (line 438) | std::optional<remapping_type_e> determine_remapping_type(const config:...
    type parsed_remapping_entry_t (line 461) | struct parsed_remapping_entry_t {
    function is_resolution_mapped (line 473) | bool is_resolution_mapped(const remapping_type_e type) {
    function is_fps_mapped (line 482) | bool is_fps_mapped(const remapping_type_e type) {
    function parse_remapping_entry (line 492) | std::optional<parsed_remapping_entry_t> parse_remapping_entry(const co...
    function remap_display_mode_if_needed (line 523) | bool remap_display_mode_if_needed(const config::video_t &video_config,...
    function make_settings_manager (line 615) | std::unique_ptr<SettingsManagerInterface> make_settings_manager([[mayb...
    type revert_option_e (line 635) | enum class revert_option_e {
    function revert_configuration_unlocked (line 645) | void revert_configuration_unlocked(const revert_option_e option) {
    function init (line 704) | std::unique_ptr<platf::deinit_t> init(const std::filesystem::path &per...
    function map_output_name (line 748) | std::string map_output_name(const std::string &output_name) {
    function configure_display (line 760) | void configure_display(const config::video_t &video_config, const rtsp...
    function configure_display (line 776) | void configure_display(const SingleDisplayConfiguration &config) {
    function revert_configuration (line 793) | void revert_configuration() {
    function reset_persistence (line 798) | bool reset_persistence() {
    function EnumeratedDeviceList (line 813) | EnumeratedDeviceList enumerate_devices() {
    function parse_configuration (line 825) | std::variant<failed_to_parse_tag_t, configuration_disabled_tag_t, Sing...

FILE: src/display_device.h
  function namespace (line 15) | namespace platf {
  function namespace (line 19) | namespace config {
  function namespace (line 23) | namespace rtsp_stream {
  function namespace (line 27) | namespace display_device {

FILE: src/entry_handler.cpp
  function launch_ui (line 29) | void launch_ui(const std::optional<std::string> &path) {
  type args (line 37) | namespace args {
    function creds (line 38) | int creds(const char *name, int argc, char *argv[]) {
    function help (line 48) | int help(const char *name) {
    function version (line 53) | int version() {
    function restore_nvprefs_undo (line 59) | int restore_nvprefs_undo() {
  type lifetime (line 69) | namespace lifetime {
    function exit_sunshine (line 73) | void exit_sunshine(int exit_code, bool async) {
    function debug_trap (line 88) | void debug_trap() {
  function log_publisher_data (line 101) | void log_publisher_data() {
  function is_gamestream_enabled (line 108) | bool is_gamestream_enabled() {
  type service_ctrl (line 123) | namespace service_ctrl {
    class service_controller (line 124) | class service_controller {
      method service_controller (line 130) | service_controller(DWORD service_desired_access) {
      method start_service (line 159) | bool start_service() {
      method query_service_status (line 179) | bool query_service_status(SERVICE_STATUS &status) {
    function is_service_running (line 198) | bool is_service_running() {
    function start_service (line 209) | bool start_service() {
    function wait_for_ui_ready (line 234) | bool wait_for_ui_ready() {

FILE: src/entry_handler.h
  function namespace (line 28) | namespace args {
  function namespace (line 74) | namespace lifetime {
  function namespace (line 111) | namespace service_ctrl {

FILE: src/file_handler.cpp
  type file_handler (line 14) | namespace file_handler {
    function get_parent_directory (line 15) | std::string get_parent_directory(const std::string &path) {
    function make_directory (line 26) | bool make_directory(const std::string &path) {
    function read_file (line 35) | std::string read_file(const char *path) {
    function write_file (line 45) | int write_file(const char *path, const std::string_view &contents) {

FILE: src/file_handler.h
  function namespace (line 13) | namespace file_handler {

FILE: src/globals.h
  function namespace (line 34) | namespace mail {

FILE: src/httpcommon.cpp
  type http (line 35) | namespace http {
    function init (line 46) | int init() {
    function save_user_creds (line 69) | int save_user_creds(const std::string &file, const std::string &userna...
    function user_creds_exist (line 96) | bool user_creds_exist(const std::string &file) {
    function reload_user_creds (line 114) | int reload_user_creds(const std::string &file) {
    function create_creds (line 128) | int create_creds(const std::string &pkey, const std::string &cert) {
    function download_file (line 179) | bool download_file(const std::string &url, const std::string &file, lo...
    function url_escape (line 215) | std::string url_escape(const std::string &url) {
    function url_get_host (line 222) | std::string url_get_host(const std::string &url) {

FILE: src/httpcommon.h
  function namespace (line 14) | namespace http {

FILE: src/input.cpp
  type input (line 38) | namespace input {
    type button_state_e (line 54) | enum class button_state_e {
    function alloc_id (line 61) | int alloc_id(std::bitset<N> &gamepad_mask) {
    function free_id (line 73) | void free_id(std::bitset<N> &gamepad_mask, int id) {
    function key_press_id_t (line 79) | key_press_id_t make_kpid(uint16_t vk, uint8_t flags) {
    function vk_from_kpid (line 83) | uint16_t vk_from_kpid(key_press_id_t kpid) {
    function flags_from_kpid (line 87) | uint8_t flags_from_kpid(key_press_id_t kpid) {
    function from_netfloat (line 96) | float from_netfloat(netfloat f) {
    function from_clamped_netfloat (line 107) | float from_clamped_netfloat(netfloat f, float min, float max) {
    function free_gamepad (line 118) | void free_gamepad(platf::input_t &platf_input, int id) {
    type gamepad_t (line 125) | struct gamepad_t {
      method gamepad_t (line 126) | gamepad_t():
    type input_t (line 155) | struct input_t {
      type shortkey_e (line 156) | enum shortkey_e {
      method input_t (line 163) | input_t(
    function apply_shortcut (line 203) | inline int apply_shortcut(short keyCode) {
    function print (line 223) | void print(PNV_REL_MOUSE_MOVE_PACKET packet) {
    function print (line 231) | void print(PNV_ABS_MOUSE_MOVE_PACKET packet) {
    function print (line 241) | void print(PNV_MOUSE_BUTTON_PACKET packet) {
    function print (line 249) | void print(PNV_SCROLL_PACKET packet) {
    function print (line 256) | void print(PSS_HSCROLL_PACKET packet) {
    function print (line 263) | void print(PNV_KEYBOARD_PACKET packet) {
    function print (line 273) | void print(PNV_UNICODE_PACKET packet) {
    function print (line 281) | void print(PNV_MULTI_CONTROLLER_PACKET packet) {
    function print (line 301) | void print(PSS_TOUCH_PACKET packet) {
    function print (line 319) | void print(PSS_PEN_PACKET packet) {
    function print (line 339) | void print(PSS_CONTROLLER_ARRIVAL_PACKET packet) {
    function print (line 353) | void print(PSS_CONTROLLER_TOUCH_PACKET packet) {
    function print (line 369) | void print(PSS_CONTROLLER_MOTION_PACKET packet) {
    function print (line 384) | void print(PSS_CONTROLLER_BATTERY_PACKET packet) {
    function print (line 393) | void print(void *payload) {
    function passthrough (line 444) | void passthrough(std::shared_ptr<input_t> &input, PNV_REL_MOUSE_MOVE_P...
    function client_to_touchport (line 460) | std::optional<std::pair<float, float>> client_to_touchport(std::shared...
    function multiply_polar_by_cartesian_scalar (line 515) | float multiply_polar_by_cartesian_scalar(float r, float angle, const s...
    function scale_client_contact_area (line 528) | std::pair<float, float> scale_client_contact_area(const std::pair<floa...
    function passthrough (line 541) | void passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_P...
    function passthrough (line 591) | void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PAC...
    function map_keycode (line 652) | short map_keycode(short keycode) {
    function update_shortcutFlags (line 664) | inline void update_shortcutFlags(int *flags, short keyCode, bool relea...
    function is_modifier (line 696) | bool is_modifier(uint16_t keyCode) {
    function send_key_and_modifiers (line 713) | void send_key_and_modifiers(uint16_t key_code, bool release, uint8_t f...
    function repeat_key (line 743) | void repeat_key(uint16_t key_code, uint8_t flags, uint8_t synthetic_mo...
    function passthrough (line 755) | void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET ...
    function passthrough (line 815) | void passthrough(std::shared_ptr<input_t> &input, PNV_SCROLL_PACKET pa...
    function passthrough (line 838) | void passthrough(std::shared_ptr<input_t> &input, PSS_HSCROLL_PACKET p...
    function passthrough (line 856) | void passthrough(PNV_UNICODE_PACKET packet) {
    function passthrough (line 870) | void passthrough(std::shared_ptr<input_t> &input, PSS_CONTROLLER_ARRIV...
    function monitor_touch_port (line 911) | std::optional<platf::touch_port_t> monitor_touch_port(const input::tou...
    function passthrough (line 935) | void passthrough(std::shared_ptr<input_t> &input, PSS_TOUCH_PACKET pac...
    function passthrough (line 986) | void passthrough(std::shared_ptr<input_t> &input, PSS_PEN_PACKET packe...
    function passthrough (line 1039) | void passthrough(std::shared_ptr<input_t> &input, PSS_CONTROLLER_TOUCH...
    function passthrough (line 1072) | void passthrough(std::shared_ptr<input_t> &input, PSS_CONTROLLER_MOTIO...
    function passthrough (line 1104) | void passthrough(std::shared_ptr<input_t> &input, PSS_CONTROLLER_BATTE...
    function passthrough (line 1129) | void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER...
    type batch_result_e (line 1244) | enum class batch_result_e {
    function batch_result_e (line 1256) | batch_result_e batch(PNV_REL_MOUSE_MOVE_PACKET dest, PNV_REL_MOUSE_MOV...
    function batch_result_e (line 1280) | batch_result_e batch(PNV_ABS_MOUSE_MOVE_PACKET dest, PNV_ABS_MOUSE_MOV...
    function batch_result_e (line 1297) | batch_result_e batch(PNV_SCROLL_PACKET dest, PNV_SCROLL_PACKET src) {
    function batch_result_e (line 1317) | batch_result_e batch(PSS_HSCROLL_PACKET dest, PSS_HSCROLL_PACKET src) {
    function batch_result_e (line 1336) | batch_result_e batch(PNV_MULTI_CONTROLLER_PACKET dest, PNV_MULTI_CONTR...
    function batch_result_e (line 1364) | batch_result_e batch(PSS_TOUCH_PACKET dest, PSS_TOUCH_PACKET src) {
    function batch_result_e (line 1398) | batch_result_e batch(PSS_PEN_PACKET dest, PSS_PEN_PACKET src) {
    function batch_result_e (line 1431) | batch_result_e batch(PSS_CONTROLLER_TOUCH_PACKET dest, PSS_CONTROLLER_...
    function batch_result_e (line 1471) | batch_result_e batch(PSS_CONTROLLER_MOTION_PACKET dest, PSS_CONTROLLER...
    function batch_result_e (line 1494) | batch_result_e batch(PNV_INPUT_HEADER dest, PNV_INPUT_HEADER src) {
    function passthrough_next_message (line 1530) | void passthrough_next_message(std::shared_ptr<input_t> input) {
    function passthrough (line 1628) | void passthrough(std::shared_ptr<input_t> &input, std::vector<std::uin...
    function reset (line 1636) | void reset(std::shared_ptr<input_t> &input) {
    class deinit_t (line 1660) | class deinit_t: public platf::deinit_t {
    function init (line 1667) | [[nodiscard]] std::unique_ptr<platf::deinit_t> init() {
    function probe_gamepads (line 1673) | bool probe_gamepads() {
    function alloc (line 1684) | std::shared_ptr<input_t> alloc(safe::mail_t mail) {

FILE: src/input.h
  function namespace (line 14) | namespace input {

FILE: src/logging.cpp
  function init (line 150) | [[nodiscard]] std::unique_ptr<deinit_t> init(int min_log_level, const st...
  function setup_av_logging (line 191) | void setup_av_logging(int min_log_level) {
  function setup_libdisplaydevice_logging (line 219) | void setup_libdisplaydevice_logging(int min_log_level) {
  function log_flush (line 250) | void log_flush() {
  function print_help (line 256) | void print_help(const char *name) {
  function bracket (line 276) | std::string bracket(const std::string &input) {
  function bracket (line 280) | std::wstring bracket(const std::wstring &input) {

FILE: src/logging.h
  function namespace (line 29) | namespace logging {

FILE: src/main.cpp
  function on_signal_forwarder (line 38) | void on_signal_forwarder(int sig) {
  function on_signal (line 43) | void on_signal(int sig, FN &&fn) {
  function LRESULT (line 67) | LRESULT CALLBACK SessionMonitorWindowProc(HWND hwnd, UINT uMsg, WPARAM w...
  function WINAPI (line 87) | WINAPI BOOL ConsoleCtrlHandler(DWORD type) {
  function mainThreadLoop (line 102) | void mainThreadLoop(const std::shared_ptr<safe::event_t<bool>> &shutdown...
  function main (line 123) | int main(int argc, char *argv[]) {

FILE: src/move_by_copy.h
  function namespace (line 13) | namespace move_by_copy_util {

FILE: src/network.cpp
  type net (line 19) | namespace net {
    function net_e (line 39) | net_e from_enum_string(const std::string_view &view) {
    function net_e (line 50) | net_e from_address(const std::string_view &view) {
    function to_enum_string (line 82) | std::string_view to_enum_string(net_e net) {
    function af_e (line 96) | af_e af_from_enum_string(const std::string_view &view) {
    function af_to_any_address_string (line 108) | std::string_view af_to_any_address_string(const af_e af) {
    function get_bind_address (line 120) | std::string get_bind_address(const af_e af) {
    function normalize_address (line 130) | boost::asio::ip::address normalize_address(boost::asio::ip::address ad...
    function addr_to_normalized_string (line 142) | std::string addr_to_normalized_string(boost::asio::ip::address address) {
    function addr_to_url_escaped_string (line 146) | std::string addr_to_url_escaped_string(boost::asio::ip::address addres...
    function encryption_mode_for_address (line 157) | int encryption_mode_for_address(boost::asio::ip::address address) {
    function host_t (line 166) | host_t host_create(af_e af, ENetAddress &addr, std::uint16_t port) {
    function free_host (line 185) | void free_host(ENetHost *host) {
    function map_port (line 197) | std::uint16_t map_port(int port) {
    function mdns_instance_name (line 214) | std::string mdns_instance_name(const std::string_view &hostname) {

FILE: src/network.h
  function namespace (line 18) | namespace net {

FILE: src/nvenc/nvenc_base.cpp
  function GUID (line 29) | GUID quality_preset_guid_from_number(unsigned number) {
  function equal_guids (line 59) | bool equal_guids(const GUID &guid1, const GUID &guid2) {
  function quality_preset_string_from_guid (line 63) | auto quality_preset_string_from_guid(const GUID &guid) {
  type nvenc (line 90) | namespace nvenc {
    function nvenc_encoded_frame (line 498) | nvenc_encoded_frame nvenc_base::encode_frame(uint64_t frame_index, boo...

FILE: src/nvenc/nvenc_base.h
  function namespace (line 20) | namespace nvenc {

FILE: src/nvenc/nvenc_colorspace.h
  function namespace (line 10) | namespace nvenc {

FILE: src/nvenc/nvenc_config.h
  function namespace (line 7) | namespace nvenc {

FILE: src/nvenc/nvenc_d3d11.cpp
  type nvenc (line 11) | namespace nvenc {

FILE: src/nvenc/nvenc_d3d11.h
  function namespace (line 15) | namespace nvenc {

FILE: src/nvenc/nvenc_d3d11_native.cpp
  type nvenc (line 12) | namespace nvenc {
    function ID3D11Texture2D (line 26) | ID3D11Texture2D *

FILE: src/nvenc/nvenc_d3d11_native.h
  function namespace (line 14) | namespace nvenc {

FILE: src/nvenc/nvenc_d3d11_on_cuda.cpp
  type nvenc (line 12) | namespace nvenc {
    function ID3D11Texture2D (line 55) | ID3D11Texture2D *nvenc_d3d11_on_cuda::get_input_texture() {

FILE: src/nvenc/nvenc_d3d11_on_cuda.h
  function namespace (line 13) | namespace nvenc {

FILE: src/nvenc/nvenc_encoded_frame.h
  function namespace (line 11) | namespace nvenc {

FILE: src/nvenc/nvenc_utils.cpp
  type nvenc (line 11) | namespace nvenc {
    function DXGI_FORMAT (line 14) | DXGI_FORMAT dxgi_format_from_nvenc_format(NV_ENC_BUFFER_FORMAT format) {
    function NV_ENC_BUFFER_FORMAT (line 34) | NV_ENC_BUFFER_FORMAT nvenc_format_from_sunshine_format(platf::pix_fmt_...
    function nvenc_colorspace_t (line 53) | nvenc_colorspace_t nvenc_colorspace_from_sunshine_colorspace(const vid...

FILE: src/nvenc/nvenc_utils.h
  function namespace (line 20) | namespace nvenc {

FILE: src/nvhttp.cpp
  type nvhttp (line 41) | namespace nvhttp {
    class SunshineHTTPSServer (line 50) | class SunshineHTTPSServer: public SimpleWeb::ServerBase<SunshineHTTPS> {
      method SunshineHTTPSServer (line 52) | SunshineHTTPSServer(const std::string &certification_file, const std...
      method after_bind (line 68) | void after_bind() override {
      method accept (line 79) | void accept() override {
    type conf_intern_t (line 126) | struct conf_intern_t {
    type named_cert_t (line 131) | struct named_cert_t {
    type client_t (line 137) | struct client_t {
    type op_e (line 152) | enum class op_e {
    function get_arg (line 157) | std::string get_arg(const args_t &args, const char *name, const char *...
    function save_state (line 169) | void save_state() {
    function load_state (line 205) | void load_state() {
    function add_authorized_client (line 269) | void add_authorized_client(const std::string &name, std::string &&cert) {
    function make_launch_session (line 282) | std::shared_ptr<rtsp_stream::launch_session_t> make_launch_session(boo...
    function remove_session (line 340) | void remove_session(const pair_session_t &sess) {
    function fail_pair (line 344) | void fail_pair(pair_session_t &sess, pt::ptree &tree, const std::strin...
    function getservercert (line 351) | void getservercert(pair_session_t &sess, pt::ptree &tree, const std::s...
    function clientchallenge (line 375) | void clientchallenge(pair_session_t &sess, pt::ptree &tree, const std:...
    function serverchallengeresp (line 418) | void serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const ...
    function clientpairingsecret (line 447) | void clientpairingsecret(pair_session_t &sess, std::shared_ptr<safe::q...
    type tunnel (line 498) | struct tunnel
    type tunnel<SunshineHTTPS> (line 501) | struct tunnel<SunshineHTTPS> {
    type tunnel<SimpleWeb::HTTP> (line 506) | struct tunnel<SimpleWeb::HTTP> {
    function print_req (line 511) | void print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Requ...
    function not_found (line 531) | void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Resp...
    function pair (line 550) | void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, st...
    function pin (line 631) | bool pin(std::string pin, std::string name) {
    function serverinfo (line 680) | void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Res...
    function get_all_clients (line 772) | nlohmann::json get_all_clients() {
    function applist (line 785) | void applist(resp_https_t response, req_https_t request) {
    function launch (line 813) | void launch(bool &host_audio, resp_https_t response, req_https_t reque...
    function resume (line 924) | void resume(bool &host_audio, resp_https_t response, req_https_t reque...
    function cancel (line 1015) | void cancel(resp_https_t response, req_https_t request) {
    function appasset (line 1040) | void appasset(resp_https_t response, req_https_t request) {
    function setup (line 1053) | void setup(const std::string &pkey, const std::string &cert) {
    function start (line 1058) | void start() {
    function erase_all_clients (line 1204) | void erase_all_clients() {
    function unpair_client (line 1211) | bool unpair_client(const std::string_view uuid) {

FILE: src/nvhttp.h
  function namespace (line 23) | namespace nvhttp {

FILE: src/platform/common.h
  type sockaddr (line 34) | struct sockaddr
  type AVFrame (line 35) | struct AVFrame
  type AVBufferRef (line 36) | struct AVBufferRef
  type AVHWFramesContext (line 37) | struct AVHWFramesContext
  type AVCodecContext (line 38) | struct AVCodecContext
  type AVDictionary (line 39) | struct AVDictionary
  function namespace (line 44) | namespace boost {
  function namespace (line 64) | namespace video {
  function namespace (line 68) | namespace nvenc {
  function namespace (line 72) | namespace platf {
  type speaker_e (line 193) | enum speaker_e {
  type class (line 229) | enum class
  type class (line 238) | enum class
  function std (line 249) | inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) {
  type touch_port_t (line 270) | struct touch_port_t {
  function namespace (line 280) | namespace platform_caps {
  type gamepad_state_t (line 287) | struct gamepad_state_t {
  type gamepad_id_t (line 297) | struct gamepad_id_t {
  type gamepad_arrival_t (line 308) | struct gamepad_arrival_t {
  type gamepad_touch_t (line 314) | struct gamepad_touch_t {
  type gamepad_motion_t (line 323) | struct gamepad_motion_t {
  type gamepad_battery_t (line 334) | struct gamepad_battery_t {
  type touch_input_t (line 340) | struct touch_input_t {
  type pen_input_t (line 351) | struct pen_input_t {
  function class (line 364) | class deinit_t {
  function img_t (line 369) | struct img_t: std::enable_shared_from_this<img_t> {
  type sink_t (line 389) | struct sink_t {
  type encode_device_t (line 404) | struct encode_device_t {
  function encode_device_t (line 412) | struct avcodec_encode_device_t: encode_device_t {
  function encode_device_t (line 453) | struct nvenc_encode_device_t: encode_device_t {
  function capture_e (line 459) | enum class capture_e : int {
  type send_info_t (line 717) | struct send_info_t {
  function qos_data_type_e (line 731) | enum class qos_data_type_e : int {

FILE: src/platform/linux/audio.cpp
  type platf (line 22) | namespace platf {
    function to_string (line 36) | std::string to_string(const char *name, const std::uint8_t *mapping, i...
    type mic_attr_t (line 53) | struct mic_attr_t: public mic_t {
      method capture_e (line 56) | capture_e sample(std::vector<float> &sample_buf) override {
    function microphone (line 71) | std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int cha...
    type pa (line 105) | namespace pa {
      type add_const_helper (line 107) | struct add_const_helper
      type add_const_helper<true, T> (line 110) | struct add_const_helper<true, T> {
      type add_const_helper<false, T> (line 115) | struct add_const_helper<false, T> {
      function pa_free (line 123) | void pa_free(T *p) {
      function cb (line 136) | void cb(ctx_t::pointer ctx, add_const_t<T> i, void *userdata) {
      function cb (line 148) | void cb(ctx_t::pointer ctx, add_const_t<T> i, int eol, void *userdat...
      function cb_i (line 159) | void cb_i(ctx_t::pointer ctx, std::uint32_t i, void *userdata) {
      function ctx_state_cb (line 165) | void ctx_state_cb(ctx_t::pointer ctx, void *userdata) {
      function success_cb (line 171) | void success_cb(ctx_t::pointer ctx, int status, void *userdata) {
      class server_t (line 178) | class server_t: public audio_control_t {
        type ctx_event_e (line 179) | enum ctx_event_e : int {
        method init (line 201) | int init() {
        method load_null (line 258) | int load_null(const char *name, const std::uint8_t *channel_mappin...
        method unload_null (line 275) | int unload_null(std::uint32_t i) {
        method sink_info (line 296) | std::optional<sink_t> sink_info() override {
        method get_default_sink_name (line 391) | std::string get_default_sink_name() {
        method get_monitor_name (line 413) | std::string get_monitor_name(const std::string &sink_name) {
        method microphone (line 444) | std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int...
        method is_sink_available (line 463) | bool is_sink_available(const std::string &sink) override {
        method set_sink (line 468) | int set_sink(const std::string &sink) override {
    function audio_control (line 517) | std::unique_ptr<audio_control_t> audio_control() {

FILE: src/platform/linux/cuda.cpp
  type cuda (line 43) | namespace cuda {
    function pass_error (line 47) | void pass_error(const std::string_view &sv, const char *name, const ch...
    function cff (line 51) | void cff(CudaFunctions *cf) {
    function check (line 59) | inline static int check(CUresult result, const std::string_view &sv) {
    function freeStream (line 74) | void freeStream(CUstream stream) {
    function unregisterResource (line 78) | void unregisterResource(CUgraphicsResource resource) {
    class img_t (line 84) | class img_t: public platf::img_t {
    function init (line 89) | int init() {
    class cuda_t (line 102) | class cuda_t: public platf::avcodec_encode_device_t {
      method init (line 104) | int init(int in_width, int in_height) {
      method set_frame (line 118) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
      method apply_colorspace (line 156) | void apply_colorspace() override {
      method cudaTextureObject_t (line 184) | cudaTextureObject_t tex_obj(const tex_t &tex) const {
    class cuda_ram_t (line 200) | class cuda_ram_t: public cuda_t {
      method convert (line 202) | int convert(platf::img_t &img) override {
      method set_frame (line 206) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
    class cuda_vram_t (line 224) | class cuda_vram_t: public cuda_t {
      method convert (line 226) | int convert(platf::img_t &img) override {
    function file_t (line 236) | file_t open_drm_fd_for_cuda_device(int index) {
    class gl_cuda_vram_t (line 277) | class gl_cuda_vram_t: public platf::avcodec_encode_device_t {
      method init (line 287) | int init(int in_width, int in_height, int offset_x, int offset_y) {
      method set_frame (line 334) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx_buf) overri...
      method convert (line 381) | int convert(platf::img_t &img) override {
      method apply_colorspace (line 434) | void apply_colorspace() override {
    function make_avcodec_encode_device (line 464) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_de...
    function make_avcodec_gl_encode_device (line 492) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_gl_encode...
    type nvfbc (line 506) | namespace nvfbc {
      function NVFBC_BOOL (line 510) | static constexpr inline NVFBC_BOOL nv_bool(bool b) {
      function init (line 516) | int init() {
      class ctx_t (line 554) | class ctx_t {
        method ctx_t (line 556) | ctx_t(NVFBC_SESSION_HANDLE handle) {
      class handle_t (line 576) | class handle_t {
        type flag_e (line 577) | enum flag_e {
        method handle_t (line 584) | handle_t() = default;
        method handle_t (line 586) | handle_t(handle_t &&other):
        method handle_t (line 592) | handle_t &operator=(handle_t &&other) {
        method make (line 599) | static std::optional<handle_t> make() {
        method status (line 625) | std::optional<NVFBC_GET_STATUS_PARAMS> status() {
        method capture (line 638) | int capture(NVFBC_CREATE_CAPTURE_SESSION_PARAMS &capture_params) {
        method stop (line 658) | int stop() {
        method reset (line 676) | int reset() {
      class display_t (line 704) | class display_t: public platf::display_t {
        method init (line 706) | int init(const std::string_view &display_name, const ::video::conf...
        method capture (line 767) | platf::capture_e capture(const push_captured_image_cb_t &push_capt...
        method reinit (line 827) | platf::capture_e reinit(bool cursor) {
        method snapshot (line 895) | platf::capture_e snapshot(const pull_free_image_cb_t &pull_free_im...
        method make_avcodec_encode_device (line 935) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encod...
        method alloc_img (line 939) | std::shared_ptr<platf::img_t> alloc_img() override {
        method dummy_img (line 958) | int dummy_img(platf::img_t *) override {
  type platf (line 972) | namespace platf {
    function nvfbc_display (line 973) | std::shared_ptr<display_t> nvfbc_display(mem_type_e hwdevice_type, con...
    function nvfbc_display_names (line 988) | std::vector<std::string> nvfbc_display_names() {

FILE: src/platform/linux/cuda.h
  function namespace (line 18) | namespace platf {
  function namespace (line 23) | namespace cuda {
  type cudaArray (line 44) | struct cudaArray
  type CUstream_st (line 47) | struct CUstream_st
  type cudaTextureObject_t (line 48) | typedef unsigned long long cudaTextureObject_t;
  type struct (line 50) | typedef __location__(device_builtin) struct
  function namespace (line 54) | namespace cuda {

FILE: src/platform/linux/graphics.cpp
  type gl (line 32) | namespace gl {
    function PFNGLEGLIMAGETARGETTEXTURE2DOESPROC (line 37) | PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture_2d() {
    function drain_errors (line 41) | void drain_errors(const std::string_view &prefix) {
    function tex_t (line 54) | tex_t tex_t::make(std::size_t count) {
    function frame_buf_t (line 79) | frame_buf_t frame_buf_t::make(std::size_t count) {
    function GLuint (line 128) | GLuint shader_t::handle() const {
    function buffer_t (line 132) | buffer_t buffer_t::make(util::buffer_t<GLint> &&offsets, const char *b...
    function GLuint (line 145) | GLuint buffer_t::handle() const {
    function GLuint (line 266) | GLuint program_t::handle() const {
  type gbm (line 272) | namespace gbm {
    function init (line 276) | int init() {
  type egl (line 305) | namespace egl {
    function fail (line 307) | bool fail() {
    function display_t (line 314) | display_t make_display(std::variant<gbm::gbm_t::pointer, wl_display *,...
    function make_ctx (line 389) | std::optional<ctx_t> make_ctx(display_t::pointer display) {
    type plane_attr_t (line 459) | struct plane_attr_t {
    function plane_attr_t (line 467) | inline plane_attr_t get_plane(std::uint32_t plane_indice) {
    function surface_descriptor_to_egl_attribs (line 512) | std::vector<EGLAttrib> surface_descriptor_to_egl_attribs(const surface...
    function import_source (line 549) | std::optional<rgb_t> import_source(display_t::pointer egl_display, con...
    function rgb_t (line 583) | rgb_t create_blank(platf::img_t &img) {
    function import_target (line 607) | std::optional<nv12_t> import_target(display_t::pointer egl_display, st...
    function create_target (line 666) | std::optional<nv12_t> create_target(int width, int height, AVPixelForm...
  function free_frame (line 1012) | void free_frame(AVFrame *frame) {

FILE: src/platform/linux/graphics.h
  type _XDisplay (line 30) | struct _XDisplay
  type AVFrame (line 32) | struct AVFrame
  function namespace (line 37) | namespace gl {
  function class (line 60) | class frame_buf_t: public util::buffer_t<GLuint> {
  function class (line 107) | class shader_t {
  function class (line 125) | class buffer_t {
  function namespace (line 175) | namespace gbm {
  function namespace (line 189) | namespace egl {

FILE: src/platform/linux/input/inputtino.cpp
  type platf (line 22) | namespace platf {
    function input_t (line 24) | input_t input() {
    function allocate_client_input_context (line 28) | std::unique_ptr<client_input_t> allocate_client_input_context(input_t ...
    function freeInput (line 32) | void freeInput(void *p) {
    function move_mouse (line 37) | void move_mouse(input_t &input, int deltaX, int deltaY) {
    function abs_mouse (line 42) | void abs_mouse(input_t &input, const touch_port_t &touch_port, float x...
    function button_mouse (line 47) | void button_mouse(input_t &input, int button, bool release) {
    function scroll (line 52) | void scroll(input_t &input, int high_res_distance) {
    function hscroll (line 57) | void hscroll(input_t &input, int high_res_distance) {
    function keyboard_update (line 62) | void keyboard_update(input_t &input, uint16_t modcode, bool release, u...
    function unicode (line 67) | void unicode(input_t &input, char *utf8, int size) {
    function touch_update (line 72) | void touch_update(client_input_t *input, const touch_port_t &touch_por...
    function pen_update (line 77) | void pen_update(client_input_t *input, const touch_port_t &touch_port,...
    function alloc_gamepad (line 82) | int alloc_gamepad(input_t &input, const gamepad_id_t &id, const gamepa...
    function free_gamepad (line 87) | void free_gamepad(input_t &input, int nr) {
    function gamepad_update (line 92) | void gamepad_update(input_t &input, int nr, const gamepad_state_t &gam...
    function gamepad_touch (line 97) | void gamepad_touch(input_t &input, const gamepad_touch_t &touch) {
    function gamepad_motion (line 102) | void gamepad_motion(input_t &input, const gamepad_motion_t &motion) {
    function gamepad_battery (line 107) | void gamepad_battery(input_t &input, const gamepad_battery_t &battery) {
    function get_capabilities (line 112) | platform_caps::caps_t get_capabilities() {
    function get_mouse_loc (line 125) | util::point_t get_mouse_loc(input_t &input) {

FILE: src/platform/linux/input/inputtino_common.h
  function namespace (line 20) | namespace platf {
  function client_input_t (line 66) | struct client_input_raw_t: public client_input_t {
  function deg2rad (line 99) | inline float deg2rad(float degree) {

FILE: src/platform/linux/input/inputtino_gamepad.cpp
  type platf::gamepad (line 20) | namespace platf::gamepad {
    type GamepadStatus (line 22) | enum GamepadStatus {
    function create_xbox_one (line 29) | auto create_xbox_one() {
    function create_switch (line 37) | auto create_switch() {
    function create_ds5 (line 45) | auto create_ds5(int globalIndex) {
    function alloc (line 56) | int alloc(input_raw_t *raw, const gamepad_id_t &id, const gamepad_arri...
    function free (line 182) | void free(input_raw_t *raw, int nr) {
    function update (line 188) | void update(input_raw_t *raw, int nr, const gamepad_state_t &gamepad_s...
    function touch (line 203) | void touch(input_raw_t *raw, const gamepad_touch_t &touch) {
    function motion (line 218) | void motion(input_raw_t *raw, const gamepad_motion_t &motion) {
    function battery (line 236) | void battery(input_raw_t *raw, const gamepad_battery_t &battery) {

FILE: src/platform/linux/input/inputtino_gamepad.h
  function namespace (line 18) | namespace platf::gamepad {

FILE: src/platform/linux/input/inputtino_keyboard.cpp
  type platf::keyboard (line 20) | namespace platf::keyboard {
    function to_hex (line 29) | std::string to_hex(const std::basic_string<char32_t> &str) {
    function update (line 163) | void update(input_raw_t *raw, uint16_t modcode, bool release, uint8_t ...
    function unicode (line 173) | void unicode(input_raw_t *raw, char *utf8, int size) {

FILE: src/platform/linux/input/inputtino_keyboard.h
  function namespace (line 17) | namespace platf::keyboard {

FILE: src/platform/linux/input/inputtino_mouse.cpp
  type platf::mouse (line 20) | namespace platf::mouse {
    function move (line 22) | void move(input_raw_t *raw, int deltaX, int deltaY) {
    function move_abs (line 28) | void move_abs(input_raw_t *raw, const touch_port_t &touch_port, float ...
    function button (line 34) | void button(input_raw_t *raw, int button, bool release) {
    function scroll (line 65) | void scroll(input_raw_t *raw, int high_res_distance) {
    function hscroll (line 71) | void hscroll(input_raw_t *raw, int high_res_distance) {
    function get_location (line 77) | util::point_t get_location(input_raw_t *raw) {

FILE: src/platform/linux/input/inputtino_mouse.h
  function namespace (line 17) | namespace platf::mouse {

FILE: src/platform/linux/input/inputtino_pen.cpp
  type platf::pen (line 20) | namespace platf::pen {
    function update (line 21) | void update(client_input_raw_t *raw, const touch_port_t &touch_port, c...

FILE: src/platform/linux/input/inputtino_pen.h
  function namespace (line 18) | namespace platf::pen {

FILE: src/platform/linux/input/inputtino_touch.cpp
  type platf::touch (line 20) | namespace platf::touch {
    function update (line 21) | void update(client_input_raw_t *raw, const touch_port_t &touch_port, c...

FILE: src/platform/linux/input/inputtino_touch.h
  function namespace (line 18) | namespace platf::touch {

FILE: src/platform/linux/kmsgrab.cpp
  type platf (line 35) | namespace platf {
    type kms (line 37) | namespace kms {
      class cap_sys_admin (line 39) | class cap_sys_admin {
        method cap_sys_admin (line 41) | cap_sys_admin() {
      class wrapper_fb (line 61) | class wrapper_fb {
        method wrapper_fb (line 63) | wrapper_fb(uint32_t card_fd, drmModeFB *fb):
        method wrapper_fb (line 78) | wrapper_fb(uint32_t card_fd, drmModeFB2 *fb2):
        type drm_gem_close (line 95) | struct drm_gem_close
      function plane_type (line 141) | std::string_view plane_type(std::uint64_t val) {
      type connector_t (line 154) | struct connector_t {
      type monitor_t (line 170) | struct monitor_t {
      type card_descriptor_t (line 181) | struct card_descriptor_t {
      function from_view (line 189) | static std::uint32_t from_view(const std::string_view &string) {
      class plane_it_t (line 246) | class plane_it_t: public round_robin_util::it_wrap_t<plane_t::elemen...
        method plane_it_t (line 248) | plane_it_t(int fd, std::uint32_t *plane_p, std::uint32_t *end):
        method plane_it_t (line 255) | plane_it_t(int fd, std::uint32_t *end):
        method load_next_valid_plane (line 261) | void load_next_valid_plane() {
        method inc (line 276) | void inc() {
        method eq (line 281) | bool eq(const plane_it_t &other) const {
        method get (line 285) | plane_t::pointer get() {
      type cursor_t (line 296) | struct cursor_t {
      class card_t (line 316) | class card_t {
        method init (line 320) | int init(const char *path) {
        method fb_t (line 375) | fb_t fb(plane_t::pointer plane) {
        method crtc_t (line 391) | crtc_t crtc(std::uint32_t id) {
        method encoder_t (line 395) | encoder_t encoder(std::uint32_t id) {
        method res_t (line 399) | res_t res() {
        method is_nvidia (line 403) | bool is_nvidia() {
        method is_cursor (line 408) | bool is_cursor(std::uint32_t plane_id) {
        method prop_value_by_name (line 423) | std::optional<std::uint64_t> prop_value_by_name(const std::vector<...
        method get_panel_orientation (line 432) | std::uint32_t get_panel_orientation(std::uint32_t plane_id) {
        method get_crtc_index_by_id (line 443) | int get_crtc_index_by_id(std::uint32_t crtc_id) {
        method connector_interal_t (line 453) | connector_interal_t connector(std::uint32_t id) {
        method monitors (line 457) | std::vector<connector_t> monitors(conn_type_count_t &conn_type_cou...
        method file_t (line 491) | file_t handleFD(std::uint32_t handle) {
        method props (line 502) | std::vector<std::pair<prop_t, std::uint64_t>> props(std::uint32_t ...
        method plane_props (line 518) | std::vector<std::pair<prop_t, std::uint64_t>> plane_props(std::uin...
        method crtc_props (line 522) | std::vector<std::pair<prop_t, std::uint64_t>> crtc_props(std::uint...
        method connector_props (line 526) | std::vector<std::pair<prop_t, std::uint64_t>> connector_props(std:...
        method plane_t (line 530) | plane_t operator[](std::uint32_t index) {
        method count (line 534) | std::uint32_t count() {
        method plane_it_t (line 538) | plane_it_t begin() const {
        method plane_it_t (line 542) | plane_it_t end() const {
      function map_crtc_to_monitor (line 551) | std::map<std::uint32_t, monitor_t> map_crtc_to_monitor(const std::ve...
      type kms_img_t (line 564) | struct kms_img_t: public img_t {
      function print (line 571) | void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer...
      class display_t (line 603) | class display_t: public platf::display_t {
        method display_t (line 605) | display_t(mem_type_e mem_type):
        method init (line 610) | int init(const std::string &display_name, const ::video::config_t ...
        method is_hdr (line 818) | bool is_hdr() {
        method get_hdr_metadata (line 864) | bool get_hdr_metadata(SS_HDR_METADATA &metadata) {
        method update_cursor (line 893) | void update_cursor() {
        method capture_e (line 1074) | inline capture_e refresh(file_t *file, egl::surface_descriptor_t *...
      class display_ram_t (line 1160) | class display_ram_t: public display_t {
        method display_ram_t (line 1162) | display_ram_t(mem_type_e mem_type):
        method init (line 1166) | int init(const std::string &display_name, const ::video::config_t ...
        method capture_e (line 1197) | capture_e capture(const push_captured_image_cb_t &push_captured_im...
        method make_avcodec_encode_device (line 1242) | std::unique_ptr<avcodec_encode_device_t> make_avcodec_encode_devic...
        method blend_cursor (line 1258) | void blend_cursor(img_t &img) {
        method capture_e (line 1306) | capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb,...
        method alloc_img (line 1349) | std::shared_ptr<img_t> alloc_img() override {
        method dummy_img (line 1360) | int dummy_img(platf::img_t *img) override {
      class display_vram_t (line 1369) | class display_vram_t: public display_t {
        method display_vram_t (line 1371) | display_vram_t(mem_type_e mem_type):
        method make_avcodec_encode_device (line 1375) | std::unique_ptr<avcodec_encode_device_t> make_avcodec_encode_devic...
        method alloc_img (line 1392) | std::shared_ptr<img_t> alloc_img() override {
        method dummy_img (line 1407) | int dummy_img(platf::img_t *img) override {
        method capture_e (line 1412) | capture_e capture(const push_captured_image_cb_t &push_captured_im...
        method capture_e (line 1457) | capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb,...
        method init (line 1499) | int init(const std::string &display_name, const ::video::config_t ...
    function kms_display (line 1526) | std::shared_ptr<display_t> kms_display(mem_type_e hwdevice_type, const...
    function correlate_to_wayland (line 1556) | void correlate_to_wayland(std::vector<kms::card_descriptor_t> &cds) {
    function kms_display_names (line 1612) | std::vector<std::string> kms_display_names(mem_type_e hwdevice_type) {

FILE: src/platform/linux/misc.cpp
  type dyn (line 68) | namespace dyn {
    function load (line 92) | int load(void *handle, const std::vector<std::tuple<apiproc *, const c...
  type platf (line 110) | namespace platf {
    function ifaddr_t (line 113) | ifaddr_t get_ifaddrs() {
    function appdata (line 126) | fs::path appdata() {
    function from_sockaddr (line 204) | std::string from_sockaddr(const sockaddr *const ip_addr) {
    function from_sockaddr_ex (line 217) | std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr ...
    function get_mac_address (line 233) | std::string get_mac_address(const std::string_view &address) {
    function run_command (line 285) | bp::child run_command(bool elevated, bool interactive, const std::stri...
    function open_url (line 310) | void open_url(const std::string &url) {
    function adjust_thread_priority (line 326) | void adjust_thread_priority(thread_priority_e priority) {
    function set_thread_name (line 330) | void set_thread_name(const std::string &name) {
    function enable_mouse_keys (line 334) | void enable_mouse_keys() {
    function streaming_will_start (line 338) | void streaming_will_start() {
    function streaming_will_stop (line 342) | void streaming_will_stop() {
    function restart_on_exit (line 346) | void restart_on_exit() {
    function restart (line 368) | void restart() {
    function set_env (line 374) | int set_env(const std::string &name, const std::string &value) {
    function unset_env (line 378) | int unset_env(const std::string &name) {
    function request_process_group_exit (line 382) | bool request_process_group_exit(std::uintptr_t native_handle) {
    function process_group_running (line 392) | bool process_group_running(std::uintptr_t native_handle) {
    function to_sockaddr (line 396) | struct sockaddr_in to_sockaddr(boost::asio::ip::address_v4 address, ui...
    function to_sockaddr (line 408) | struct sockaddr_in6 to_sockaddr(boost::asio::ip::address_v6 address, u...
    function send_batch (line 421) | bool send_batch(batched_send_info_t &send_info) {
    function send (line 646) | bool send(send_info_t &send_info) {
    class qos_t (line 769) | class qos_t: public deinit_t {
      method qos_t (line 771) | qos_t(int sockfd, std::vector<std::tuple<int, int, int>> options):
    function enable_socket_qos (line 801) | std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, b...
    function get_host_name (line 869) | std::string get_host_name() {
    type source (line 878) | namespace source {
      type source_e (line 879) | enum source_e : std::size_t {
    function verify_nvfbc (line 905) | bool verify_nvfbc() {
    function verify_wl (line 914) | bool verify_wl() {
    function verify_kms (line 923) | bool verify_kms() {
    function verify_x11 (line 932) | bool verify_x11() {
    function verify_portal (line 941) | bool verify_portal() {
    function display_names (line 946) | std::vector<std::string> display_names(mem_type_e hwdevice_type) {
    function needs_encoder_reenumeration (line 980) | bool needs_encoder_reenumeration() {
    function display (line 985) | std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std...
    function init (line 1020) | std::unique_ptr<deinit_t> init() {
    class linux_high_precision_timer (line 1085) | class linux_high_precision_timer: public high_precision_timer {
      method sleep_for (line 1087) | void sleep_for(const std::chrono::nanoseconds &duration) override {
    function create_high_precision_timer (line 1096) | std::unique_ptr<high_precision_timer> create_high_precision_timer() {

FILE: src/platform/linux/misc.h
  function window_system_e (line 20) | enum class window_system_e {

FILE: src/platform/linux/portalgrab.cpp
  type portal (line 67) | namespace portal {
    class session_cache_t (line 69) | class session_cache_t
      method get_or_create_session (line 660) | int get_or_create_session(int &pipewire_fd, int &pipewire_node, int ...
      method invalidate (line 705) | void invalidate() noexcept {
      method session_cache_t (line 727) | session_cache_t() = default;
      method session_cache_t (line 736) | session_cache_t(const session_cache_t &) = delete;
      method session_cache_t (line 737) | session_cache_t &operator=(const session_cache_t &) = delete;
    class restore_token_t (line 71) | class restore_token_t {
      method get (line 73) | static std::string get() {
      method set (line 77) | static void set(std::string_view value) {
      method empty (line 81) | static bool empty() {
      method load (line 85) | static void load() {
      method save (line 95) | static void save() {
      method get_file_path (line 111) | static std::string get_file_path() {
    type format_map_t (line 116) | struct format_map_t {
    type dbus_response_t (line 127) | struct dbus_response_t {
    type shared_state_t (line 133) | struct shared_state_t {
    type stream_data_t (line 139) | struct stream_data_t {
      type pw_stream (line 140) | struct pw_stream
      type spa_hook (line 141) | struct spa_hook
      type spa_video_info (line 142) | struct spa_video_info
      type pw_buffer (line 143) | struct pw_buffer
      method stream_data_t (line 158) | stream_data_t():
    type dmabuf_format_info_t (line 163) | struct dmabuf_format_info_t {
    class dbus_t (line 169) | class dbus_t {
      method init (line 213) | int init() {
      method finalize_portal_security (line 232) | void finalize_portal_security() {
      method connect_to_portal (line 260) | int connect_to_portal() {
      method try_remote_desktop_session (line 290) | bool try_remote_desktop_session(GMainLoop *loop, gchar **session_pat...
      method try_screencast_only_session (line 313) | int try_screencast_only_session(GMainLoop *loop, gchar **session_pat...
      method create_portal_session (line 336) | int create_portal_session(GMainLoop *loop, gchar **session_path_out,...
      method select_remote_desktop_devices (line 402) | int select_remote_desktop_devices(GMainLoop *loop, const gchar *sess...
      method select_screencast_sources (line 451) | int select_screencast_sources(GMainLoop *loop, const gchar *session_...
      method start_portal_session (line 501) | int start_portal_session(GMainLoop *loop, const gchar *session_path,...
      method open_pipewire_remote (line 570) | int open_pipewire_remote(const gchar *session_path, int &fd) {
      method on_response_received_cb (line 587) | static void on_response_received_cb([[maybe_unused]] GDBusConnection...
      method gchar (line 593) | static gchar *get_sender_string(GDBusConnection *conn) {
      method create_request_path (line 602) | static void create_request_path(GDBusConnection *conn, gchar **out_p...
      method create_session_path (line 616) | static void create_session_path(GDBusConnection *conn, gchar **out_p...
      method dbus_response_init (line 631) | static void dbus_response_init(struct dbus_response_t *response, GMa...
      method GVariant (line 636) | static GVariant *dbus_response_wait(struct dbus_response_t *response) {
    class session_cache_t (line 648) | class session_cache_t {
      method get_or_create_session (line 660) | int get_or_create_session(int &pipewire_fd, int &pipewire_node, int ...
      method invalidate (line 705) | void invalidate() noexcept {
      method session_cache_t (line 727) | session_cache_t() = default;
      method session_cache_t (line 736) | session_cache_t(const session_cache_t &) = delete;
      method session_cache_t (line 737) | session_cache_t &operator=(const session_cache_t &) = delete;
    function session_cache_t (line 748) | session_cache_t &session_cache_t::instance() {
      method get_or_create_session (line 660) | int get_or_create_session(int &pipewire_fd, int &pipewire_node, int ...
      method invalidate (line 705) | void invalidate() noexcept {
      method session_cache_t (line 727) | session_cache_t() = default;
      method session_cache_t (line 736) | session_cache_t(const session_cache_t &) = delete;
      method session_cache_t (line 737) | session_cache_t &operator=(const session_cache_t &) = delete;
    class pipewire_t (line 754) | class pipewire_t {
      method pipewire_t (line 756) | pipewire_t():
      method is_frame_ready (line 792) | bool is_frame_ready() const {
      method set_frame_ready (line 796) | void set_frame_ready(bool ready) {
      method init (line 800) | void init(int stream_fd, int stream_node, std::shared_ptr<shared_sta...
      method cleanup_stream (line 818) | void cleanup_stream() {
      method ensure_stream (line 839) | void ensure_stream(const platf::mem_type_e mem_type, const uint32_t ...
      method fill_img (line 882) | void fill_img(platf::img_t *img) {
      type pw_thread_loop (line 955) | struct pw_thread_loop
      type pw_context (line 956) | struct pw_context
      type pw_core (line 957) | struct pw_core
      type spa_hook (line 958) | struct spa_hook
      type stream_data_t (line 959) | struct stream_data_t
      type spa_pod (line 963) | struct spa_pod
      type spa_pod_builder (line 963) | struct spa_pod_builder
      type spa_pod_frame (line 964) | struct spa_pod_frame
      type spa_pod_frame (line 965) | struct spa_pod_frame
      type spa_rectangle (line 966) | struct spa_rectangle
      type spa_fraction (line 967) | struct spa_fraction
      type spa_pod (line 998) | struct spa_pod
      method on_core_info_cb (line 1001) | static void on_core_info_cb([[maybe_unused]] void *user_data, const ...
      method on_core_error_cb (line 1005) | static void on_core_error_cb([[maybe_unused]] void *user_data, const...
      type pw_core_events (line 1009) | struct pw_core_events
      method on_stream_state_changed (line 1015) | static void on_stream_state_changed(void *user_data, enum pw_stream_...
      method on_process (line 1040) | static void on_process(void *user_data) {
      method on_param_changed (line 1092) | static void on_param_changed(void *user_data, uint32_t id, const str...
      type pw_stream_events (line 1171) | struct pw_stream_events
    class portal_t (line 1179) | class portal_t: public platf::display_t {
      method init (line 1181) | int init(platf::mem_type_e hwdevice_type, const std::string &display...
      method snapshot (line 1260) | platf::capture_e snapshot(const pull_free_image_cb_t &pull_free_imag...
      method alloc_img (line 1291) | std::shared_ptr<platf::img_t> alloc_img() override {
      method capture (line 1307) | platf::capture_e capture(const push_captured_image_cb_t &push_captur...
      method make_avcodec_encode_device (line 1372) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_...
      method dummy_img (line 1395) | int dummy_img(platf::img_t *img) override {
      method is_event_driven (line 1406) | bool is_event_driven() override {
      method is_buffer_redundant (line 1411) | bool is_buffer_redundant(const egl::img_descriptor_t *img) {
      method update_metadata (line 1425) | void update_metadata(egl::img_descriptor_t *img, int retries) {
      method wait_for_frame (line 1435) | bool wait_for_frame(std::chrono::steady_clock::time_point deadline) {
      method lookup_pw_format (line 1449) | static uint32_t lookup_pw_format(uint64_t fourcc) {
      method query_dmabuf_formats (line 1461) | void query_dmabuf_formats(EGLDisplay egl_display) {
      method get_dmabuf_modifiers (line 1492) | int get_dmabuf_modifiers() {
      type dmabuf_format_info_t (line 1543) | struct dmabuf_format_info_t
  type platf (line 1559) | namespace platf {
    function portal_display (line 1560) | std::shared_ptr<display_t> portal_display(mem_type_e hwdevice_type, co...
    function portal_display_names (line 1575) | std::vector<std::string> portal_display_names() {

FILE: src/platform/linux/publish.cpp
  type avahi (line 19) | namespace avahi {
    type err_e (line 24) | enum err_e {
    type proto (line 90) | enum proto {
    type ServerState (line 96) | enum ServerState {
    type ClientState (line 104) | enum ClientState {
    type EntryGroupState (line 112) | enum EntryGroupState {
    type ClientFlags (line 120) | enum ClientFlags {
    type PublishFlags (line 128) | enum PublishFlags {
    type EntryGroup (line 143) | struct EntryGroup
    type Poll (line 144) | struct Poll
    type SimplePoll (line 145) | struct SimplePoll
    type Client (line 146) | struct Client
    function init_common (line 206) | int init_common() {
    function init_client (line 241) | int init_client() {
  type platf::publish (line 281) | namespace platf::publish {
    function free (line 284) | void free(T *p) {
    function entry_group_callback (line 302) | void entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState...
    function create_services (line 325) | void create_services(avahi::Client *c) {
    function client_callback (line 383) | void client_callback(avahi::Client *c, avahi::ClientState state, void ...
    class deinit_t (line 402) | class deinit_t: public ::platf::deinit_t {
      method deinit_t (line 406) | deinit_t(std::thread poll_thread):
    function start (line 421) | [[nodiscard]] std::unique_ptr<::platf::deinit_t> start() {

FILE: src/platform/linux/vaapi.cpp
  function VAStatus (line 18) | VAStatus
  function VAStatus (line 29) | VAStatus
  type AVBufferRef (line 52) | struct AVBufferRef
  type va (line 54) | namespace va {
    type DRMPRIMESurfaceDescriptor (line 64) | struct DRMPRIMESurfaceDescriptor {
    class va_t (line 110) | class va_t: public platf::avcodec_encode_device_t {
      method init (line 112) | int init(int in_width, int in_height, file_t &&render_device) {
      method VAEntrypoint (line 152) | VAEntrypoint select_va_entrypoint(VAProfile profile) {
      method is_va_profile_supported (line 182) | bool is_va_profile_supported(VAProfile profile) {
      method VAProfile (line 200) | VAProfile get_va_profile(AVCodecContext *ctx) {
      method init_codec_options (line 232) | void init_codec_options(AVCodecContext *ctx, AVDictionary **options)...
      method set_frame (line 306) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx_buf) overri...
      method apply_colorspace (line 383) | void apply_colorspace() override {
    class va_ram_t (line 405) | class va_ram_t: public va_t {
      method convert (line 407) | int convert(platf::img_t &img) override {
    class va_vram_t (line 415) | class va_vram_t: public va_t {
      method convert (line 417) | int convert(platf::img_t &img) override {
      method init (line 443) | int init(int in_width, int in_height, file_t &&render_device, int of...
    type VAAPIDevicePriv (line 469) | struct VAAPIDevicePriv {
    type AVVAAPIDeviceContext (line 483) | struct AVVAAPIDeviceContext {
    function __log (line 498) | static void __log(void *level, const char *msg) {
    function vaapi_hwdevice_ctx_free (line 502) | static void vaapi_hwdevice_ctx_free(AVHWDeviceContext *ctx) {
    function vaapi_init_avcodec_hardware_input_buffer (line 511) | int vaapi_init_avcodec_hardware_input_buffer(platf::avcodec_encode_dev...
    function query (line 567) | static bool query(display_t::pointer display, VAProfile profile) {
    function validate (line 588) | bool validate(int fd) {
    function make_avcodec_encode_device (line 624) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_de...
    function make_avcodec_encode_device (line 644) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_de...
    function make_avcodec_encode_device (line 658) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_de...

FILE: src/platform/linux/vaapi.h
  function namespace (line 11) | namespace egl {
  function namespace (line 15) | namespace va {

FILE: src/platform/linux/wayland.cpp
  type wl (line 35) | namespace wl {
    function classCall (line 39) | static auto classCall(void *data, Params... params) -> decltype(((*rei...
    type zwp_linux_buffer_params_v1_listener (line 46) | struct zwp_linux_buffer_params_v1_listener
    type pollfd (line 88) | struct pollfd
    function wl_registry (line 106) | wl_registry *display_t::registry() {
    type zwp_linux_buffer_params_v1 (line 445) | struct zwp_linux_buffer_params_v1
    type wl_buffer (line 446) | struct wl_buffer
    type zwp_linux_buffer_params_v1 (line 462) | struct zwp_linux_buffer_params_v1
    function monitors (line 541) | std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_n...
    function validate (line 567) | static bool validate() {
    function init (line 573) | int init() {

FILE: src/platform/linux/wayland.h
  function class (line 28) | class frame_t {
  function class (line 37) | class dmabuf_t {
  type gbm_device (line 95) | struct gbm_device
  type gbm_bo (line 96) | struct gbm_bo
  type wl_buffer (line 97) | struct wl_buffer
  function y_invert (line 98) | bool y_invert {false};
  function class (line 101) | class monitor_t {
  type bind_t (line 135) | struct bind_t {
  type interface_e (line 141) | enum interface_e {
  function const (line 157) | bool operator[](interface_e bit) const {
  function zwlr_screencopy_manager_v1 (line 162) | zwlr_screencopy_manager_v1 *screencopy_manager {nullptr};

FILE: src/platform/linux/wlgrab.cpp
  type wl (line 18) | namespace wl {
    type img_t (line 22) | struct img_t: public platf::img_t {
    class wlr_t (line 29) | class wlr_t: public platf::display_t {
      method init (line 31) | int init(platf::mem_type_e hwdevice_type, const std::string &display...
      method dummy_img (line 112) | int dummy_img(platf::img_t *img) override {
      method snapshot (line 116) | inline platf::capture_e snapshot(const pull_free_image_cb_t &pull_fr...
    class wlr_ram_t (line 152) | class wlr_ram_t: public wlr_t {
      method capture (line 154) | platf::capture_e capture(const push_captured_image_cb_t &push_captur...
      method snapshot (line 199) | platf::capture_e snapshot(const pull_free_image_cb_t &pull_free_imag...
      method init (line 234) | int init(platf::mem_type_e hwdevice_type, const std::string &display...
      method make_avcodec_encode_device (line 254) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_...
      method alloc_img (line 270) | std::shared_ptr<platf::img_t> alloc_img() override {
    class wlr_vram_t (line 285) | class wlr_vram_t: public wlr_t {
      method capture (line 287) | platf::capture_e capture(const push_captured_image_cb_t &push_captur...
      method snapshot (line 332) | platf::capture_e snapshot(const pull_free_image_cb_t &pull_free_imag...
      method alloc_img (line 358) | std::shared_ptr<platf::img_t> alloc_img() override {
      method make_avcodec_encode_device (line 373) | std::unique_ptr<platf::avcodec_encode_device_t> make_avcodec_encode_...
      method dummy_img (line 389) | int dummy_img(platf::img_t *img) override {
  type platf (line 399) | namespace platf {
    function wl_display (line 400) | std::shared_ptr<display_t> wl_display(mem_type_e hwdevice_type, const ...
    function wl_display_names (line 423) | std::vector<std::string> wl_display_names() {

FILE: src/platform/linux/x11grab.cpp
  type platf (line 35) | namespace platf {
    type x11 (line 39) | namespace x11 {
      type rr (line 53) | namespace rr {
        function init (line 61) | static int init() {
      type fix (line 95) | namespace fix {
        function init (line 98) | static int init() {
      function init (line 126) | static int init() {
      function xdisplay_t (line 871) | xdisplay_t make_display() {
      function freeDisplay (line 875) | void freeDisplay(_XDisplay *xdisplay) {
      function freeCursorCtx (line 879) | void freeCursorCtx(cursor_ctx_t::pointer ctx) {
    type xcb (line 159) | namespace xcb {
      function init_shm (line 177) | int init_shm() {
      function init (line 207) | int init() {
    class shm_id_t (line 256) | class shm_id_t {
      method shm_id_t (line 258) | shm_id_t():
      method shm_id_t (line 262) | shm_id_t(int id):
      method shm_id_t (line 266) | shm_id_t(shm_id_t &&other) noexcept:
    class shm_data_t (line 281) | class shm_data_t {
      method shm_data_t (line 283) | shm_data_t():
      method shm_data_t (line 287) | shm_data_t(void *data):
      method shm_data_t (line 291) | shm_data_t(shm_data_t &&other) noexcept:
    type x11_img_t (line 305) | struct x11_img_t: public img_t {
    type shm_img_t (line 309) | struct shm_img_t: public img_t {
    function blend_cursor (line 316) | static void blend_cursor(Display *display, img_t &img, int offsetX, in...
    type x11_attr_t (line 365) | struct x11_attr_t: public display_t {
      method x11_attr_t (line 380) | x11_attr_t(mem_type_e mem_type):
      method init (line 388) | int init(const std::string &display_name, const ::video::config_t &c...
      method refresh (line 455) | void refresh() {
      method capture_e (line 459) | capture_e capture(const push_captured_image_cb_t &push_captured_imag...
      method capture_e (line 504) | capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb, s...
      method alloc_img (line 535) | std::shared_ptr<img_t> alloc_img() override {
      method make_avcodec_encode_device (line 539) | std::unique_ptr<avcodec_encode_device_t> make_avcodec_encode_device(...
      method dummy_img (line 555) | int dummy_img(img_t *img) override {
    type shm_attr_t (line 570) | struct shm_attr_t: public x11_attr_t {
      method delayed_refresh (line 582) | void delayed_refresh() {
      method shm_attr_t (line 588) | shm_attr_t(mem_type_e mem_type):
      method capture_e (line 598) | capture_e capture(const push_captured_image_cb_t &push_captured_imag...
      method capture_e (line 643) | capture_e snapshot(const pull_free_image_cb_t &pull_free_image_cb, s...
      method alloc_img (line 673) | std::shared_ptr<img_t> alloc_img() override {
      method dummy_img (line 684) | int dummy_img(platf::img_t *img) override {
      method init (line 688) | int init(const std::string &display_name, const ::video::config_t &c...
      method frame_size (line 727) | std::uint32_t frame_size() {
    function x11_display (line 732) | std::shared_ptr<display_t> x11_display(platf::mem_type_e hwdevice_type...
    function x11_display_names (line 766) | std::vector<std::string> x11_display_names() {
    function freeImage (line 803) | void freeImage(XImage *p) {
    function freeX (line 807) | void freeX(XFixesCursorImage *p) {
    function load_xcb (line 811) | int load_xcb() {
    function load_x11 (line 818) | int load_x11() {
    type x11 (line 827) | namespace x11 {
      type rr (line 53) | namespace rr {
        function init (line 61) | static int init() {
      type fix (line 95) | namespace fix {
        function init (line 98) | static int init() {
      function init (line 126) | static int init() {
      function xdisplay_t (line 871) | xdisplay_t make_display() {
      function freeDisplay (line 875) | void freeDisplay(_XDisplay *xdisplay) {
      function freeCursorCtx (line 879) | void freeCursorCtx(cursor_ctx_t::pointer ctx) {

FILE: src/platform/linux/x11grab.h
  type _XDisplay (line 15) | struct _XDisplay
  function namespace (line 17) | namespace egl {
  function namespace (line 21) | namespace platf::x11 {

FILE: src/platform/macos/av_audio.h
  function interface (line 15) | interface AVAudio: NSObject <AVCaptureAudioDataOutputSampleBufferDelegat...

FILE: src/platform/macos/av_img_t.h
  function namespace (line 14) | namespace platf {
  function img_t (line 52) | struct av_img_t: img_t {
  type temp_retain_av_img_t (line 57) | struct temp_retain_av_img_t {

FILE: src/platform/macos/av_video.h
  type CaptureSession (line 11) | struct CaptureSession {

FILE: src/platform/macos/input.cpp
  type platf (line 29) | namespace platf {
    type macos_input_t (line 32) | struct macos_input_t {
    type KeyCodeMap (line 49) | struct KeyCodeMap {
    function keysym (line 231) | int keysym(int keycode) {
    function keyboard_update (line 249) | void keyboard_update(input_t &input, uint16_t modcode, bool release, u...
    function unicode (line 297) | void unicode(input_t &input, char *utf8, int size) {
    function alloc_gamepad (line 301) | int alloc_gamepad(input_t &input, const gamepad_id_t &id, const gamepa...
    function free_gamepad (line 306) | void free_gamepad(input_t &input, int nr) {
    function gamepad_update (line 310) | void gamepad_update(input_t &input, int nr, const gamepad_state_t &gam...
    function get_mouse_loc (line 315) | util::point_t get_mouse_loc(input_t &input) {
    function post_mouse (line 327) | void post_mouse(
    function CGEventType (line 367) | inline CGEventType event_type_mouse(input_t &input) {
    function move_mouse (line 382) | void move_mouse(
    function abs_mouse (line 393) | void abs_mouse(
    function button_mouse (line 412) | void button_mouse(input_t &input, const int button, const bool release) {
    function scroll (line 451) | void scroll(input_t &input, const int high_res_distance) {
    function hscroll (line 459) | void hscroll(input_t &input, int high_res_distance) {
    function allocate_client_input_context (line 472) | std::unique_ptr<client_input_t> allocate_client_input_context(input_t ...
    function touch_update (line 483) | void touch_update(client_input_t *input, const touch_port_t &touch_por...
    function pen_update (line 493) | void pen_update(client_input_t *input, const touch_port_t &touch_port,...
    function gamepad_touch (line 502) | void gamepad_touch(input_t &input, const gamepad_touch_t &touch) {
    function gamepad_motion (line 511) | void gamepad_motion(input_t &input, const gamepad_motion_t &motion) {
    function gamepad_battery (line 520) | void gamepad_battery(input_t &input, const gamepad_battery_t &battery) {
    function input_t (line 524) | input_t input() {
    function freeInput (line 571) | void freeInput(void *p) {
    function get_capabilities (line 593) | platform_caps::caps_t get_capabilities() {

FILE: src/platform/macos/misc.h
  function namespace (line 13) | namespace platf {
  function namespace (line 17) | namespace dyn {

FILE: src/platform/macos/nv12_zero_device.cpp
  type platf (line 17) | namespace platf {
    function free_frame (line 19) | void free_frame(AVFrame *frame) {
    function free_buffer (line 23) | void free_buffer(void *opaque, uint8_t *data) {

FILE: src/platform/macos/nv12_zero_device.h
  type AVFrame (line 10) | struct AVFrame
  function namespace (line 12) | namespace platf {

FILE: src/platform/macos/publish.cpp
  type platf::publish (line 19) | namespace platf::publish {
    type ServiceRefDeleter (line 22) | struct ServiceRefDeleter {
    class deinit_t (line 34) | class deinit_t: public ::platf::deinit_t, std::unique_ptr<DNSServiceRe...
      method deinit_t (line 43) | deinit_t(DNSServiceRef serviceRef):
      method deinit_t (line 73) | deinit_t(const deinit_t &) = delete;
      method deinit_t (line 74) | deinit_t &operator=(const deinit_t &) = delete;
    function registrationCallback (line 84) | void registrationCallback(DNSServiceRef /*serviceRef*/, DNSServiceFlag...
    function start (line 104) | [[nodiscard]] std::unique_ptr<::platf::deinit_t> start() {

FILE: src/platform/windows/PolicyConfig.h
  function interface (line 42) | interface IPolicyConfig: public IUnknown {

FILE: src/platform/windows/audio.cpp
  type sample_format_e (line 59) | enum class sample_format_e {
  function WAVEFORMATEXTENSIBLE (line 68) | constexpr WAVEFORMATEXTENSIBLE create_waveformat(sample_format_e sample_...
  function virtual_sink_waveformats_t (line 130) | virtual_sink_waveformats_t create_virtual_sink_waveformats() {
  function waveformat_to_pretty_string (line 169) | std::string waveformat_to_pretty_string(const WAVEFORMATEXTENSIBLE &wave...
  type platf::audio (line 205) | namespace platf::audio {
    function Release (line 207) | void Release(T *p) {
    function co_task_free (line 212) | void co_task_free(T *p) {
    class co_init_t (line 227) | class co_init_t: public deinit_t {
      method co_init_t (line 229) | co_init_t() {
    class prop_var_t (line 238) | class prop_var_t {
      method prop_var_t (line 240) | prop_var_t() {
    type format_t (line 251) | struct format_t {
    function audio_client_t (line 279) | audio_client_t make_audio_client(device_t &device, const format_t &for...
    function device_t (line 338) | device_t default_device(device_enum_t &device_enum) {
    class audio_notification_t (line 356) | class audio_notification_t: public ::IMMNotificationClient {
      method audio_notification_t (line 358) | audio_notification_t() {
      method AddRef (line 362) | AddRef() {
      method Release (line 366) | Release() {
      method QueryInterface (line 370) | QueryInterface(REFIID riid, VOID **ppvInterface) {
      method OnDefaultDeviceChanged (line 386) | OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDevi...
      method OnDeviceAdded (line 393) | OnDeviceAdded(LPCWSTR pwstrDeviceId) {
      method OnDeviceRemoved (line 397) | OnDeviceRemoved(LPCWSTR pwstrDeviceId) {
      method OnDeviceStateChanged (line 401) | OnDeviceStateChanged(
      method OnPropertyValueChanged (line 408) | OnPropertyValueChanged(
      method check_default_render_device_changed (line 419) | bool check_default_render_device_changed() {
    class mic_wasapi_t (line 427) | class mic_wasapi_t: public mic_t {
      method capture_e (line 429) | capture_e sample(std::vector<float> &sample_out) override {
      method init (line 454) | int init(std::uint32_t sample_rate, std::uint32_t frame_size, std::u...
      method capture_e (line 576) | capture_e _fill_buffer() {
    class audio_control_t (line 691) | class audio_control_t: public ::platf::audio_control_t {
      method sink_info (line 693) | std::optional<sink_t> sink_info() override {
      method is_sink_available (line 738) | bool is_sink_available(const std::string &sink) override {
      method extract_virtual_sink_info (line 750) | std::optional<std::pair<std::wstring, std::reference_wrapper<const f...
      method microphone (line 770) | std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int c...
      method set_format (line 797) | std::optional<std::wstring> set_format(const std::string &sink) {
      method set_sink (line 857) | int set_sink(const std::string &sink) override {
      type match_field_e (line 887) | enum class match_field_e {
      method match_steam_speakers (line 897) | audio_control_t::match_fields_list_t match_steam_speakers() {
      method match_all_fields (line 903) | audio_control_t::match_fields_list_t match_all_fields(const std::wst...
      method find_device_id (line 917) | std::optional<matched_field_t> find_device_id(const match_fields_lis...
      method reset_default_device (line 991) | void reset_default_device() {
      method install_steam_audio_drivers (line 1052) | bool install_steam_audio_drivers() {
      method init (line 1119) | int init() {
  type platf (line 1159) | namespace platf {
    type dxgi (line 1162) | namespace dxgi {
    function audio_control (line 1166) | std::unique_ptr<audio_control_t> audio_control() {
    function init (line 1183) | std::unique_ptr<deinit_t> init() {

FILE: src/platform/windows/display.h
  function namespace (line 22) | namespace platf::dxgi {
  function namespace (line 65) | namespace video {
  type cursor_t (line 76) | struct cursor_t {
  function class (line 85) | class gpu_cursor_t {
  function class (line 158) | class display_base_t: public display_t {
  function class (line 253) | class display_ram_t: public display_base_t {
  function class (line 288) | class duplication_t {
  function class (line 370) | class display_wgc_ram_t: public display_ram_t {
  function class (line 382) | class display_wgc_vram_t: public display_vram_t {

FILE: src/platform/windows/display_base.cpp
  type _D3DKMT_GPU_PREFERENCE_QUERY_STATE (line 25) | enum _D3DKMT_GPU_PREFERENCE_QUERY_STATE: DWORD {
  type platf (line 42) | namespace platf {
    function display (line 1007) | std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std...
    function display_names (line 1044) | std::vector<std::string> display_names(mem_type_e) {
    function needs_encoder_reenumeration (line 1115) | bool needs_encoder_reenumeration() {
  type platf::dxgi (line 46) | namespace platf::dxgi {
    function capture_e (line 138) | capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_inf...
    function capture_e (line 170) | capture_e duplication_t::reset(dup_t::pointer dup_p) {
    function capture_e (line 178) | capture_e duplication_t::release_frame() {
    function capture_e (line 206) | capture_e display_base_t::capture(const push_captured_image_cb_t &push...
    function test_dxgi_duplication (line 358) | bool test_dxgi_duplication(adapter_t &adapter, output_t &output, bool ...
    function NTSTATUS (line 428) | NTSTATUS __stdcall NtGdiDdDDIGetCachedHybridQueryValueHook(D3DKMT_GPU_...
  type platf (line 1002) | namespace platf {
    function display (line 1007) | std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std...
    function display_names (line 1044) | std::vector<std::string> display_names(mem_type_e) {
    function needs_encoder_reenumeration (line 1115) | bool needs_encoder_reenumeration() {

FILE: src/platform/windows/display_ram.cpp
  type platf (line 10) | namespace platf {
  type platf::dxgi (line 14) | namespace platf::dxgi {
    type img_t (line 15) | struct img_t: public ::platf::img_t {
    function blend_cursor_monochrome (line 22) | void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) {
    function apply_color_alpha (line 84) | void apply_color_alpha(int *img_pixel_p, int cursor_pixel) {
    function apply_color_masked (line 99) | void apply_color_masked(int *img_pixel_p, int cursor_pixel) {
    function blend_cursor_color (line 109) | void blend_cursor_color(const cursor_t &cursor, img_t &img, const bool...
    function blend_cursor (line 155) | void blend_cursor(const cursor_t &cursor, img_t &img) {
    function capture_e (line 171) | capture_e display_ddup_ram_t::snapshot(const pull_free_image_cb_t &pul...
    function capture_e (line 318) | capture_e display_ddup_ram_t::release_snapshot() {

FILE: src/platform/windows/display_vram.cpp
  type platf (line 36) | namespace platf {
  function free_frame (line 40) | static void free_frame(AVFrame *frame) {
  type platf::dxgi (line 46) | namespace platf::dxgi {
    function buf_t (line 49) | buf_t make_buffer(device_t::pointer device, const T &t) {
    function blend_t (line 72) | blend_t make_blend(device_t::pointer device, bool enable, bool invert) {
    type img_d3d_t (line 132) | struct img_d3d_t: public platf::img_t {
    type texture_lock_helper (line 161) | struct texture_lock_helper {
      method texture_lock_helper (line 165) | texture_lock_helper(const texture_lock_helper &) = delete;
      method texture_lock_helper (line 166) | texture_lock_helper &operator=(const texture_lock_helper &) = delete;
      method texture_lock_helper (line 168) | texture_lock_helper(texture_lock_helper &&other) {
      method texture_lock_helper (line 174) | texture_lock_helper &operator=(texture_lock_helper &&other) {
      method texture_lock_helper (line 184) | texture_lock_helper(IDXGIKeyedMutex *mutex):
      method lock (line 197) | bool lock() {
    function make_cursor_xor_image (line 211) | util::buffer_t<std::uint8_t> make_cursor_xor_image(const util::buffer_...
    function make_cursor_alpha_image (line 280) | util::buffer_t<std::uint8_t> make_cursor_alpha_image(const util::buffe...
    function blob_t (line 353) | blob_t compile_shader(LPCSTR file, LPCSTR entrypoint, LPCSTR shader_mo...
    function blob_t (line 379) | blob_t compile_pixel_shader(LPCSTR file) {
    function blob_t (line 383) | blob_t compile_vertex_shader(LPCSTR file) {
    class d3d_base_encode_device (line 387) | class d3d_base_encode_device final {
      method convert (line 389) | int convert(platf::img_t &img_base) {
      method apply_colorspace (line 460) | void apply_colorspace(const ::video::sunshine_colorspace_t &colorspa...
      method init_output (line 485) | int init_output(ID3D11Texture2D *frame_texture, int width, int heigh...
      method init (line 712) | int init(std::shared_ptr<platf::display_t> display, adapter_t::point...
      type encoder_img_ctx_t (line 826) | struct encoder_img_ctx_t {
        method reset (line 837) | void reset() {
      method initialize_image_context (line 846) | int initialize_image_context(const img_d3d_t &img, encoder_img_ctx_t...
      method shader_res_t (line 891) | shader_res_t create_black_texture_for_rtv_clear() {
    class d3d_avcodec_encode_device_t (line 966) | class d3d_avcodec_encode_device_t: public avcodec_encode_device_t {
      method init (line 968) | int init(std::shared_ptr<platf::display_t> display, adapter_t::point...
      method convert (line 974) | int convert(platf::img_t &img_base) override {
      method apply_colorspace (line 978) | void apply_colorspace() override {
      method init_hwframes (line 982) | void init_hwframes(AVHWFramesContext *frames) override {
      method prepare_to_derive_context (line 996) | int prepare_to_derive_context(int hw_device_type) override {
      method set_frame (line 1013) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
    class d3d_nvenc_encode_device_t (line 1056) | class d3d_nvenc_encode_device_t: public nvenc_encode_device_t {
      method init_device (line 1058) | bool init_device(std::shared_ptr<platf::display_t> display, adapter_...
      method init_encoder (line 1079) | bool init_encoder(const ::video::config_t &client_config, const ::vi...
      method convert (line 1093) | int convert(platf::img_t &img_base) override {
    function set_cursor_texture (line 1103) | bool set_cursor_texture(device_t::pointer device, gpu_cursor_t &cursor...
    function capture_e (line 1147) | capture_e display_ddup_vram_t::snapshot(const pull_free_image_cb_t &pu...
    function capture_e (line 1556) | capture_e display_ddup_vram_t::release_snapshot() {
    function capture_e (line 1646) | capture_e display_wgc_vram_t::snapshot(const pull_free_image_cb_t &pul...
    function capture_e (line 1699) | capture_e display_wgc_vram_t::release_snapshot() {
    function init (line 1941) | int init() {

FILE: src/platform/windows/display_wgc.cpp
  type platf (line 21) | namespace platf {
  type winrt (line 25) | namespace winrt {
    type WINRT_IMPL_HAS_DECLSPEC_UUID (line 40) | struct
  type platf::dxgi (line 63) | namespace platf::dxgi {
    function capture_e (line 190) | capture_e wgc_capture_t::next_frame(std::chrono::milliseconds timeout,...
    function capture_e (line 221) | capture_e wgc_capture_t::release_frame() {
    function capture_e (line 256) | capture_e display_wgc_ram_t::snapshot(const pull_free_image_cb_t &pull...
    function capture_e (line 341) | capture_e display_wgc_ram_t::release_snapshot() {

FILE: src/platform/windows/input.cpp
  type platf (line 26) | namespace platf {
    type gp_touch_context_t (line 59) | struct gp_touch_context_t {
    type gamepad_context_t (line 65) | struct gamepad_context_t {
    function ds4_update_motion (line 137) | static void ds4_update_motion(gamepad_context_t &gamepad, uint8_t moti...
    class vigem_t (line 194) | class vigem_t {
      method init (line 196) | int init() {
      method alloc_gamepad_internal (line 220) | int alloc_gamepad_internal(const gamepad_id_t &id, feedback_queue_t ...
      method free_target (line 287) | void free_target(int nr) {
      method rumble (line 325) | void rumble(target_t::pointer target, std::uint8_t largeMotor, std::...
      method set_rgb_led (line 358) | void set_rgb_led(target_t::pointer target, std::uint8_t r, std::uint...
    function x360_notify (line 400) | void CALLBACK x360_notify(
    function ds4_notify (line 415) | void CALLBACK ds4_notify(
    type input_raw_t (line 434) | struct input_raw_t {
    function input_t (line 446) | input_t input() {
    function send_input (line 468) | void send_input(INPUT &i) {
    function inject_synthetic_pointer_input (line 490) | bool inject_synthetic_pointer_input(input_raw_t *input, HSYNTHETICPOIN...
    function abs_mouse (line 503) | void abs_mouse(input_t &input, const touch_port_t &touch_port, float x...
    function move_mouse (line 525) | void move_mouse(input_t &input, int deltaX, int deltaY) {
    function get_mouse_loc (line 538) | util::point_t get_mouse_loc(input_t &input) {
    function button_mouse (line 552) | void button_mouse(input_t &input, int button, bool release) {
    function scroll (line 575) | void scroll(input_t &input, int distance) {
    function hscroll (line 587) | void hscroll(input_t &input, int distance) {
    function keyboard_update (line 599) | void keyboard_update(input_t &input, uint16_t modcode, bool release, u...
    type client_input_raw_t (line 654) | struct client_input_raw_t: public client_input_t {
      method client_input_raw_t (line 655) | client_input_raw_t(input_t &input) {
    function allocate_client_input_context (line 697) | std::unique_ptr<client_input_t> allocate_client_input_context(input_t ...
    function perform_touch_compaction (line 706) | void perform_touch_compaction(client_input_raw_t *raw) {
    function POINTER_TYPE_INFO (line 737) | POINTER_TYPE_INFO *pointer_by_id(client_input_raw_t *raw, uint32_t poi...
    function populate_common_pointer_info (line 777) | void populate_common_pointer_info(POINTER_INFO &pointerInfo, const tou...
    function repeat_touch (line 837) | void repeat_touch(client_input_raw_t *raw) {
    function repeat_pen (line 850) | void repeat_pen(client_input_raw_t *raw) {
    function cancel_all_active_touches (line 863) | void cancel_all_active_touches(client_input_raw_t *raw) {
    function touch_update (line 899) | void touch_update(client_input_t *input, const touch_port_t &touch_por...
    function pen_update (line 1025) | void pen_update(client_input_t *input, const touch_port_t &touch_port,...
    function unicode (line 1138) | void unicode(input_t &input, char *utf8, int size) {
    function alloc_gamepad (line 1166) | int alloc_gamepad(input_t &input, const gamepad_id_t &id, const gamepa...
    function free_gamepad (line 1220) | void free_gamepad(input_t &input, int nr) {
    function XUSB_BUTTON (line 1235) | static XUSB_BUTTON x360_buttons(const gamepad_state_t &gamepad_state) {
    function x360_update_state (line 1293) | static void x360_update_state(gamepad_context_t &gamepad, const gamepa...
    function DS4_DPAD_DIRECTIONS (line 1305) | static DS4_DPAD_DIRECTIONS ds4_dpad(const gamepad_state_t &gamepad_sta...
    function DS4_BUTTONS (line 1343) | static DS4_BUTTONS ds4_buttons(const gamepad_state_t &gamepad_state) {
    function DS4_SPECIAL_BUTTONS (line 1388) | static DS4_SPECIAL_BUTTONS ds4_special_buttons(const gamepad_state_t &...
    function to_ds4_triggerX (line 1408) | static std::uint8_t to_ds4_triggerX(std::int16_t v) {
    function to_ds4_triggerY (line 1412) | static std::uint8_t to_ds4_triggerY(std::int16_t v) {
    function ds4_update_state (line 1423) | static void ds4_update_state(gamepad_context_t &gamepad, const gamepad...
    function ds4_update_ts_and_send (line 1445) | void ds4_update_ts_and_send(vigem_t *vigem, int nr) {
    function gamepad_update (line 1480) | void gamepad_update(input_t &input, int nr, const gamepad_state_t &gam...
    function gamepad_touch (line 1512) | void gamepad_touch(input_t &input, const gamepad_touch_t &touch) {
    function gamepad_motion (line 1618) | void gamepad_motion(input_t &input, const gamepad_motion_t &motion) {
    function gamepad_battery (line 1645) | void gamepad_battery(input_t &input, const gamepad_battery_t &battery) {
    function freeInput (line 1713) | void freeInput(void *p) {
    function get_capabilities (line 1754) | platform_caps::caps_t get_capabilities() {

FILE: src/platform/windows/keylayout.h
  function namespace (line 11) | namespace platf {

FILE: src/platform/windows/misc.cpp
  function nt_set_timer_resolution_max (line 76) | bool nt_set_timer_resolution_max() {
  function nt_set_timer_resolution_min (line 86) | bool nt_set_timer_resolution_min() {
  type platf (line 102) | namespace platf {
    function appdata (line 122) | std::filesystem::path appdata() {
    function from_sockaddr (line 128) | std::string from_sockaddr(const sockaddr *const socket_address) {
    function from_sockaddr_ex (line 141) | std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr ...
    function adapteraddrs_t (line 157) | adapteraddrs_t get_adapteraddrs() {
    function get_mac_address (line 168) | std::string get_mac_address(const std::string_view &address) {
    function HDESK (line 189) | HDESK syncThreadDesktop() {
    function print_status (line 208) | void print_status(const std::string_view &prefix, HRESULT status) {
    function IsUserAdmin (line 216) | bool IsUserAdmin(HANDLE user_token) {
    function HANDLE (line 250) | HANDLE retrieve_users_token(bool elevated) {
    function merge_user_environment_block (line 311) | bool merge_user_environment_block(bp::environment &env, HANDLE shell_t...
    function is_running_as_system (line 351) | bool is_running_as_system() {
    function append_string_to_environment_block (line 381) | void append_string_to_environment_block(wchar_t *env_block, int &offse...
    function create_environment_block (line 386) | std::wstring create_environment_block(const bp::environment &env) {
    function LPPROC_THREAD_ATTRIBUTE_LIST (line 418) | LPPROC_THREAD_ATTRIBUTE_LIST allocate_proc_thread_attr_list(DWORD attr...
    function free_proc_thread_attr_list (line 435) | void free_proc_thread_attr_list(LPPROC_THREAD_ATTRIBUTE_LIST list) {
    function create_boost_child_from_results (line 448) | bp::child create_boost_child_from_results(bool process_launched, const...
    function impersonate_current_user (line 484) | std::error_code impersonate_current_user(HANDLE user_token, std::funct...
    function STARTUPINFOEXW (line 521) | STARTUPINFOEXW create_startup_info(FILE *file, HANDLE *job, std::error...
    function override_per_user_predefined_keys (line 568) | bool override_per_user_predefined_keys(HANDLE token) {
    function escape_argument (line 624) | std::wstring escape_argument(const std::wstring &argument) {
    function escape_argument_for_cmd (line 661) | std::wstring escape_argument_for_cmd(const std::wstring &argument) {
    function resolve_command_string (line 685) | std::wstring resolve_command_string(const std::string &raw_cmd, const ...
    function run_command (line 905) | bp::child run_command(bool elevated, bool interactive, const std::stri...
    function open_url (line 1017) | void open_url(const std::string &url) {
    function adjust_thread_priority (line 1031) | void adjust_thread_priority(thread_priority_e priority) {
    function set_thread_name (line 1058) | void set_thread_name(const std::string &name) {
    function streaming_will_start (line 1066) | void streaming_will_start() {
    function enable_mouse_keys (line 1154) | void enable_mouse_keys() {
    function streaming_will_stop (line 1183) | void streaming_will_stop() {
    function restart_on_exit (line 1216) | void restart_on_exit() {
    function restart (line 1238) | void restart() {
    function set_env (line 1250) | int set_env(const std::string &name, const std::string &value) {
    function unset_env (line 1254) | int unset_env(const std::string &name) {
    type enum_wnd_context_t (line 1258) | struct enum_wnd_context_t {
    function BOOL (line 1263) | static BOOL CALLBACK prgrp_enum_windows(HWND hwnd, LPARAM lParam) {
    function request_process_group_exit (line 1289) | bool request_process_group_exit(std::uintptr_t native_handle) {
    function process_group_running (line 1330) | bool process_group_running(std::uintptr_t native_handle) {
    function SOCKADDR_IN (line 1342) | SOCKADDR_IN to_sockaddr(boost::asio::ip::address_v4 address, uint16_t ...
    function SOCKADDR_IN6 (line 1354) | SOCKADDR_IN6 to_sockaddr(boost::asio::ip::address_v6 address, uint16_t...
    function send_batch (line 1369) | bool send_batch(batched_send_info_t &send_info) {
    function send (line 1472) | bool send(send_info_t &send_info) {
    class qos_t (line 1552) | class qos_t: public deinit_t {
      method qos_t (line 1554) | qos_t(QOS_FLOWID flow_id):
    function enable_socket_qos (line 1577) | std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, b...
    function qpc_counter (line 1686) | int64_t qpc_counter() {
    function qpc_time_difference (line 1694) | std::chrono::nanoseconds qpc_time_difference(int64_t performance_count...
    function get_host_name (line 1708) | std::string get_host_name() {
    class win32_high_precision_timer (line 1717) | class win32_high_precision_timer: public high_precision_timer {
      method win32_high_precision_timer (line 1719) | win32_high_precision_timer() {
      method sleep_for (line 1736) | void sleep_for(const std::chrono::nanoseconds &duration) override {
    function create_high_precision_timer (line 1764) | std::unique_ptr<high_precision_timer> create_high_precision_timer() {
    function getFileVersionInfo (line 1768) | bool getFileVersionInfo(const std::filesystem::path &file_path, std::s...

FILE: src/platform/windows/misc.h
  function namespace (line 17) | namespace platf {

FILE: src/platform/windows/nvprefs/driver_settings.cpp
  function nvapi_error_message (line 16) | void nvapi_error_message(NvAPI_Status status) {
  function fill_nvapi_string (line 22) | void fill_nvapi_string(NvAPI_UnicodeString &dest, const wchar_t *src) {
  type nvprefs (line 29) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/driver_settings.h
  function namespace (line 37) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/nvapi_opensource_wrapper.cpp
  function NvAPI_Status (line 21) | NvAPI_Status call_interface(const char *name, Args... args) {
  function NVAPI_INTERFACE (line 38) | NVAPI_INTERFACE
  function NVAPI_INTERFACE (line 63) | NVAPI_INTERFACE NvAPI_Unload() {
  function NVAPI_INTERFACE (line 72) | NVAPI_INTERFACE NvAPI_GetErrorMessage(NvAPI_Status nr, NvAPI_ShortString...
  function NVAPI_INTERFACE (line 78) | NVAPI_INTERFACE NvAPI_DRS_CreateSession(NvDRSSessionHandle *phSession) {
  function NVAPI_INTERFACE (line 82) | NVAPI_INTERFACE NvAPI_DRS_DestroySession(NvDRSSessionHandle hSession) {
  function NVAPI_INTERFACE (line 86) | NVAPI_INTERFACE NvAPI_DRS_LoadSettings(NvDRSSessionHandle hSession) {
  function NVAPI_INTERFACE (line 90) | NVAPI_INTERFACE NvAPI_DRS_SaveSettings(NvDRSSessionHandle hSession) {
  function NVAPI_INTERFACE (line 94) | NVAPI_INTERFACE NvAPI_DRS_CreateProfile(NvDRSSessionHandle hSession, NVD...
  function NVAPI_INTERFACE (line 98) | NVAPI_INTERFACE NvAPI_DRS_FindProfileByName(NvDRSSessionHandle hSession,...
  function NVAPI_INTERFACE (line 102) | NVAPI_INTERFACE NvAPI_DRS_CreateApplication(NvDRSSessionHandle hSession,...
  function NVAPI_INTERFACE (line 106) | NVAPI_INTERFACE NvAPI_DRS_GetApplicationInfo(NvDRSSessionHandle hSession...
  function NVAPI_INTERFACE (line 110) | NVAPI_INTERFACE NvAPI_DRS_SetSetting(NvDRSSessionHandle hSession, NvDRSP...
  function NVAPI_INTERFACE (line 114) | NVAPI_INTERFACE NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSP...
  function NVAPI_INTERFACE (line 118) | NVAPI_INTERFACE NvAPI_DRS_DeleteProfileSetting(NvDRSSessionHandle hSessi...
  function NVAPI_INTERFACE (line 122) | NVAPI_INTERFACE NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle hSession, Nv...

FILE: src/platform/windows/nvprefs/nvprefs_common.cpp
  type nvprefs (line 12) | namespace nvprefs {
    function info_message (line 14) | void info_message(const std::wstring &message) {
    function info_message (line 18) | void info_message(const std::string &message) {
    function error_message (line 22) | void error_message(const std::wstring &message) {
    function error_message (line 26) | void error_message(const std::string &message) {
    function nvprefs_options (line 30) | nvprefs_options get_nvprefs_options() {

FILE: src/platform/windows/nvprefs/nvprefs_common.h
  function namespace (line 17) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/nvprefs_interface.cpp
  type nvprefs (line 20) | namespace nvprefs {
    type nvprefs_interface::impl (line 22) | struct nvprefs_interface::impl {

FILE: src/platform/windows/nvprefs/nvprefs_interface.h
  function namespace (line 10) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/undo_data.cpp
  type nlohmann (line 16) | namespace nlohmann {
    type adl_serializer<std::optional<T>> (line 21) | struct adl_serializer<std::optional<T>> {
      method to_json (line 22) | static void to_json(json &j, const std::optional<T> &opt) {
      method from_json (line 30) | static void from_json(const json &j, std::optional<T> &opt) {
    type adl_serializer<data_t> (line 40) | struct adl_serializer<data_t> {
      method to_json (line 41) | static void to_json(json &j, const data_t &data) {
      method from_json (line 45) | static void from_json(const json &j, data_t &data) {
    type adl_serializer<opengl_swapchain_t> (line 51) | struct adl_serializer<opengl_swapchain_t> {
      method to_json (line 52) | static void to_json(json &j, const opengl_swapchain_t &opengl_swapch...
      method from_json (line 59) | static void from_json(const json &j, opengl_swapchain_t &opengl_swap...
  type nvprefs (line 66) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/undo_data.h
  function namespace (line 13) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/undo_file.cpp
  function DWORD (line 12) | DWORD relax_permissions(HANDLE file_handle) {
  type nvprefs (line 50) | namespace nvprefs {

FILE: src/platform/windows/nvprefs/undo_file.h
  function namespace (line 14) | namespace nvprefs {

FILE: src/platform/windows/publish.cpp
  type _DNS_SERVICE_INSTANCE (line 44) | struct _DNS_SERVICE_INSTANCE {
  type _DNS_SERVICE_CANCEL (line 75) | struct _DNS_SERVICE_CANCEL {
  type _DNS_SERVICE_REGISTER_REQUEST (line 79) | struct _DNS_SERVICE_REGISTER_REQUEST {
  type platf::publish (line 95) | namespace platf::publish {
    function VOID (line 96) | VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVIC...
    function service (line 106) | static int service(bool enable, PDNS_SERVICE_INSTANCE &existing_instan...
    class mdns_registration_t (line 172) | class mdns_registration_t: public ::platf::deinit_t {
      method mdns_registration_t (line 174) | mdns_registration_t():
    function load_funcs (line 199) | int load_funcs(HMODULE handle) {
    function start (line 217) | std::unique_ptr<::platf::deinit_t> start() {

FILE: src/platform/windows/utf_utils.cpp
  type utf_utils (line 14) | namespace utf_utils {
    function from_utf8 (line 15) | std::wstring from_utf8(const std::string &string) {
    function to_utf8 (line 41) | std::string to_utf8(const std::wstring &string) {

FILE: src/platform/windows/utf_utils.h
  function namespace (line 9) | namespace utf_utils {

FILE: src/process.cpp
  type proc (line 42) | namespace proc {
    class deinit_t (line 48) | class deinit_t: public platf::deinit_t {
    function init (line 55) | std::unique_ptr<platf::deinit_t> init() {
    function terminate_process_group (line 59) | void terminate_process_group(boost::process::v1::child &proc, boost::p...
    function find_working_directory (line 97) | boost::filesystem::path find_working_directory(const std::string &cmd,...
    function find_match (line 391) | std::string_view::iterator find_match(std::string_view::iterator begin...
    function parse_env_val (line 412) | std::string parse_env_val(boost::process::v1::native_environment &env,...
    function check_valid_png (line 472) | bool check_valid_png(const std::filesystem::path &path) {
    function validate_app_image_path (line 501) | std::string validate_app_image_path(std::string app_image_path) {
    function calculate_sha256 (line 548) | std::optional<std::string> calculate_sha256(const std::string &filenam...
    function calculate_crc32 (line 583) | uint32_t calculate_crc32(const std::string &input) {
    function calculate_app_id (line 589) | std::tuple<std::string, std::string> calculate_app_id(const std::strin...
    function parse (line 620) | std::optional<proc::proc_t> parse(const std::string &file_name) {
    function refresh (line 751) | void refresh(const std::string &file_name) {

FILE: src/process.h
  function namespace (line 26) | namespace proc {

FILE: src/round_robin.h
  function namespace (line 15) | namespace round_robin_util {
  function dec (line 164) | void dec() {
  function eq (line 172) | bool eq(const round_robin_t &other) const {

FILE: src/rswrapper.c
  function reed_solomon_init (line 124) | void reed_solomon_init(void) {

FILE: src/rswrapper.h
  type reed_solomon (line 13) | typedef struct _reed_solomon reed_solomon;
  type reed_solomon (line 15) | typedef reed_solomon *(*reed_solomon_new_t)(int data_shards, int parity_...

FILE: src/rtsp.cpp
  type rtsp_stream (line 42) | namespace rtsp_stream {
    function free_msg (line 43) | void free_msg(PRTSP_MESSAGE msg) {
    type encrypted_rtsp_header_t (line 51) | struct encrypted_rtsp_header_t {
      method payload_length (line 60) | std::uint32_t payload_length() {
      method is_encrypted (line 64) | bool is_encrypted() {
    class rtsp_server_t (line 80) | class rtsp_server_t
      method bind (line 407) | int bind(net::af_e af, std::uint16_t port, boost::system::error_code...
      method handle_msg (line 443) | void handle_msg(tcp::socket &sock, launch_session_t &session, msg_t ...
      method handle_accept (line 455) | void handle_accept(const boost::system::error_code &ec) {
      method map (line 489) | void map(const std::string_view &type, cmd_func_t cb) {
      method session_raise (line 499) | void session_raise(std::shared_ptr<launch_session_t> launch_session) {
      method session_clear (line 524) | void session_clear(uint32_t launch_session_id) {
      method session_count (line 542) | int session_count() {
      method clear (line 556) | void clear(bool all = true) {
      method remove (line 576) | void remove(const std::shared_ptr<stream::session_t> &session) {
      method insert (line 585) | void insert(const std::shared_ptr<stream::session_t> &session) {
      method iterate (line 594) | void iterate() {
      method stop (line 607) | void stop() {
    class socket_t (line 89) | class socket_t: public std::enable_shared_from_this<socket_t> {
      method socket_t (line 91) | socket_t(boost::asio::io_context &io_context, std::function<void(tcp...
      method read (line 99) | void read() {
      method handle_read_encrypted_header (line 133) | static void handle_read_encrypted_header(std::shared_ptr<socket_t> &...
      method handle_read_encrypted_message (line 182) | static void handle_read_encrypted_message(std::shared_ptr<socket_t> ...
      method read_plaintext_payload (line 244) | void read_plaintext_payload() {
      method handle_plaintext_payload (line 273) | static void handle_plaintext_payload(std::shared_ptr<socket_t> &sock...
      method handle_read_plaintext (line 343) | static void handle_read_plaintext(std::shared_ptr<socket_t> &socket,...
      method handle_data (line 385) | void handle_data(msg_t &&req) {
    class rtsp_server_t (line 401) | class rtsp_server_t {
      method bind (line 407) | int bind(net::af_e af, std::uint16_t port, boost::system::error_code...
      method handle_msg (line 443) | void handle_msg(tcp::socket &sock, launch_session_t &session, msg_t ...
      method handle_accept (line 455) | void handle_accept(const boost::system::error_code &ec) {
      method map (line 489) | void map(const std::string_view &type, cmd_func_t cb) {
      method session_raise (line 499) | void session_raise(std::shared_ptr<launch_session_t> launch_session) {
      method session_clear (line 524) | void session_clear(uint32_t launch_session_id) {
      method session_count (line 542) | int session_count() {
      method clear (line 556) | void clear(bool all = true) {
      method remove (line 576) | void remove(const std::shared_ptr<stream::session_t> &session) {
      method insert (line 585) | void insert(const std::shared_ptr<stream::session_t> &session) {
      method iterate (line 594) | void iterate() {
      method stop (line 607) | void stop() {
    function launch_session_raise (line 627) | void launch_session_raise(std::shared_ptr<launch_session_t> launch_ses...
    function launch_session_clear (line 631) | void launch_session_clear(uint32_t launch_session_id) {
    function session_count (line 635) | int session_count() {
    function terminate_sessions (line 642) | void terminate_sessions() {
    function send (line 646) | int send(tcp::socket &sock, const std::string_view &sv) {
    function respond (line 662) | void respond(tcp::socket &sock, launch_session_t &session, msg_t &resp) {
    function respond (line 730) | void respond(tcp::socket &sock, launch_session_t &session, POPTION_ITE...
    function cmd_not_found (line 737) | void cmd_not_found(tcp::socket &sock, launch_session_t &session, msg_t...
    function cmd_option (line 741) | void cmd_option(rtsp_server_t *server, tcp::socket &sock, launch_sessi...
    function cmd_describe (line 753) | void cmd_describe(rtsp_server_t *server, tcp::socket &sock, launch_ses...
    function cmd_setup (line 836) | void cmd_setup(rtsp_server_t *server, tcp::socket &sock, launch_sessio...
    function cmd_announce (line 895) | void cmd_announce(rtsp_server_t *server, tcp::socket &sock, launch_ses...
    function cmd_play (line 1111) | void cmd_play(rtsp_server_t *server, tcp::socket &sock, launch_session...
    function start (line 1123) | void start() {
    function print_msg (line 1167) | void print_msg(PRTSP_MESSAGE msg) {

FILE: src/rtsp.h
  function namespace (line 14) | namespace rtsp_stream {

FILE: src/stat_trackers.cpp
  type stat_trackers (line 8) | namespace stat_trackers {
    function one_digit_after_decimal (line 10) | boost::format one_digit_after_decimal() {
    function two_digits_after_decimal (line 14) | boost::format two_digits_after_decimal() {

FILE: src/stat_trackers.h
  function namespace (line 15) | namespace stat_trackers {

FILE: src/stream.cpp
  type stream (line 80) | namespace stream {
    type socket_e (line 82) | enum class socket_e : int {
    type video_short_frame_header_t (line 89) | struct video_short_frame_header_t {
    type video_packet_raw_t (line 120) | struct video_packet_raw_t {
    type video_packet_enc_prefix_t (line 131) | struct video_packet_enc_prefix_t {
    type audio_packet_t (line 137) | struct audio_packet_t {
    type control_header_v2 (line 141) | struct control_header_v2 {
    type control_terminate_t (line 150) | struct control_terminate_t {
    type control_rumble_t (line 156) | struct control_rumble_t {
    type control_rumble_triggers_t (line 166) | struct control_rumble_triggers_t {
    type control_set_motion_event_t (line 174) | struct control_set_motion_event_t {
    type control_set_rgb_led_t (line 182) | struct control_set_rgb_led_t {
    type control_adaptive_triggers_t (line 191) | struct control_adaptive_triggers_t {
    type control_hdr_mode_t (line 206) | struct control_hdr_mode_t {
    type control_encrypted_t (line 215) | struct control_encrypted_t {
    type audio_fec_packet_t (line 229) | struct audio_fec_packet_t {
    function round_to_pkcs7_padded (line 236) | constexpr std::size_t round_to_pkcs7_padded(std::size_t size) {
    function encode_audio (line 250) | static inline int encode_audio(bool encrypted, const audio::buffer_t &...
    function while_starting_do_nothing (line 260) | static inline void while_starting_do_nothing(std::atomic<session::stat...
    class control_server_t (line 266) | class control_server_t {
      method bind (line 268) | int bind(net::af_e address_family, std::uint16_t port) {
      method map (line 295) | void map(uint16_t type, std::function<void(session_t *, const std::s...
      method send (line 299) | int send(const std::string_view &payload, net::peer_t peer) {
      method flush (line 310) | void flush() {
    type broadcast_ctx_t (line 327) | struct broadcast_ctx_t {
    type session_t (line 343) | struct session_t {
    function encode_control (line 422) | static inline std::string_view encode_control(session_t *session, cons...
    function session_t (line 477) | session_t *control_server_t::get_session(const net::peer_t peer, uint3...
    type fec (line 610) | namespace fec {
      type fec_t (line 615) | struct fec_t {
        method size (line 636) | size_t size() const {
      function fec_t (line 641) | static fec_t encode(const std::string_view &payload, size_t blocksiz...
        method size (line 636) | size_t size() const {
    function concat_and_insert (line 727) | std::vector<uint8_t> concat_and_insert(uint64_t insert_size, uint64_t ...
    function replace (line 765) | std::vector<uint8_t> replace(const std::string_view &original, const s...
    function send_feedback_msg (line 788) | int send_feedback_msg(session_t *session, platf::gamepad_feedback_msg_...
    function send_hdr_mode (line 893) | int send_hdr_mode(session_t *session, video::hdr_info_t hdr_info) {
    function controlBroadcastThread (line 922) | void controlBroadcastThread(control_server_t *server) {
    function recvThread (line 1176) | void recvThread(broadcast_ctx_t &ctx) {
    function videoBroadcastThread (line 1271) | void videoBroadcastThread(udp::socket &sock) {
    function audioBroadcastThread (line 1595) | void audioBroadcastThread(udp::socket &sock) {
    function start_broadcast (line 1700) | int start_broadcast(broadcast_ctx_t &ctx) {
    function end_broadcast (line 1767) | void end_broadcast(broadcast_ctx_t &ctx) {
    function recv_ping (line 1801) | int recv_ping(session_t *session, decltype(broadcast)::ptr_t ref, sock...
    function videoThread (line 1854) | void videoThread(session_t *session) {
    function audioThread (line 1876) | void audioThread(session_t *session) {
    type session (line 1898) | namespace session {
      function state_e (line 1901) | state_e state(session_t &session) {
      function stop (line 1905) | void stop(session_t &session) {
      function join (line 1916) | void join(session_t &session) {
      function start (line 1963) | int start(session_t &session, const std::string &addr_string) {
      function alloc (line 2005) | std::shared_ptr<session_t> alloc(config_t &config, rtsp_stream::laun...

FILE: src/stream.h
  function namespace (line 18) | namespace stream {

FILE: src/system_tray.cpp
  type system_tray (line 55) | namespace system_tray {
    function tray_open_ui_cb (line 58) | void tray_open_ui_cb([[maybe_unused]] struct tray_menu *item) {
    function tray_donate_github_cb (line 63) | void tray_donate_github_cb([[maybe_unused]] struct tray_menu *item) {
    function tray_donate_patreon_cb (line 67) | void tray_donate_patreon_cb([[maybe_unused]] struct tray_menu *item) {
    function tray_donate_paypal_cb (line 71) | void tray_donate_paypal_cb([[maybe_unused]] struct tray_menu *item) {
    function tray_reset_display_device_config_cb (line 75) | void tray_reset_display_device_config_cb([[maybe_unused]] struct tray_...
    function tray_restart_cb (line 81) | void tray_restart_cb([[maybe_unused]] struct tray_menu *item) {
    function tray_quit_cb (line 87) | void tray_quit_cb([[maybe_unused]] struct tray_menu *item) {
    type tray (line 103) | struct tray
    type tray_menu (line 107) | struct tray_menu
    type tray_menu (line 113) | struct tray_menu
    function init_tray (line 184) | int init_tray() {
    function process_tray_events (line 267) | int process_tray_events() {
    function end_tray (line 277) | int end_tray() {
    function update_tray_playing (line 285) | void update_tray_playing(std::string app_name) {
    function update_tray_pausing (line 306) | void update_tray_pausing(std::string app_name) {
    function update_tray_stopped (line 327) | void update_tray_stopped(std::string app_name) {
    function update_tray_require_pin (line 348) | void update_tray_require_pin() {
    function tray_thread_worker (line 371) | static void tray_thread_worker() {
    function init_tray_threaded (line 387) | int init_tray_threaded() {

FILE: src/system_tray.h
  function namespace (line 10) | namespace system_tray {

FILE: src/task_pool.h
  function namespace (line 22) | namespace task_pool_util {

FILE: src/thread_pool.h
  function namespace (line 14) | namespace thread_pool_util {

FILE: src/thread_safe.h
  function peek (line 119) | bool peek() {
  function status_t (line 145) | status_t _status {util::false_v<status_t>};
  function ring (line 156) | void ring(const status_t &status) {
  function ring (line 164) | void ring(status_t &&status) {
  function reset (line 231) | void reset() {
  function _rang (line 241) | bool _rang {false};
  function peek (line 278) | bool peek() {
  function stop (line 327) | void stop() {
  function ptr_t (line 357) | struct ptr_t {
  function release (line 413) | void release() {
  function cleanup (line 538) | void cleanup() {
  function cleanup (line 557) | inline void cleanup(mail_raw_t *mail) {

FILE: src/upnp.cpp
  type upnp (line 26) | namespace upnp {
    type mapping_t (line 28) | struct mapping_t {
    function status_string (line 38) | static std::string_view status_string(int status) {
    function UPNP_GetValidIGDStatus (line 57) | int UPNP_GetValidIGDStatus(device_t &device, urls_t *urls, IGDdatas *d...
    class deinit_t (line 65) | class deinit_t: public platf::deinit_t {
      method deinit_t (line 67) | deinit_t() {
      method create_ipv6_pinholes (line 103) | bool create_ipv6_pinholes() {
      method map_upnp_port (line 173) | bool map_upnp_port(const IGDdatas &data, const urls_t &urls, const s...
      method unmap_all_upnp_ports (line 281) | void unmap_all_upnp_ports(const urls_t &urls, const IGDdatas &data) {
      method upnp_thread_proc (line 302) | void upnp_thread_proc() {
    function start (line 370) | std::unique_ptr<platf::deinit_t> start() {

FILE: src/upnp.h
  function namespace (line 16) | namespace upnp {

FILE: src/utility.h
  type U (line 31) | typedef U type;
  function namespace (line 125) | namespace util {
  function disable (line 186) | void disable() {
  function failure (line 190) | bool failure {true};
  function string (line 297) | string log_hex(const T &value) {
  function is_convertable (line 354) | auto is_convertable = [](char ch) -> bool {
  function convert (line 373) | auto convert = [](char ch) -> std::uint8_t {
  function is_convertable (line 408) | auto is_convertable = [](char ch) -> bool {
  function convert (line 427) | auto convert = [](char ch) -> std::uint8_t {
  function T (line 469) | enm(const T &val) -> const std::underlying_type_t<T> & {
  function from_chars (line 478) | inline std::int64_t from_chars(const char *begin, const char *end) {
  function from_view (line 494) | inline std::int64_t from_view(const std::string_view &number) {
  function has_left (line 503) | constexpr bool has_left() const {
  function X (line 519) | const X &left() const {
  function _p (line 541) | constexpr uniq_ptr(std::nullptr_t) noexcept:
  function reset (line 587) | void reset(pointer p = pointer()) {
  function pointer (line 595) | pointer release() {
  function pointer (line 601) | pointer get() {
  function reference (line 783) | reference operator*() {
  function const_pointer (line 787) | const_pointer operator->() const {
  function pointer (line 791) | pointer operator->() {
  function explicit (line 864) | explicit buffer_t(size_t elements, const T &t):
  function string_view (line 957) | string_view view(It begin, It end) {

FILE: src/uuid.h
  function namespace (line 13) | namespace uuid_util {
  function uuid_t (line 34) | static uuid_t generate() {

FILE: src/video.cpp
  type video (line 41) | namespace video {
    function allow_encoder_probing (line 48) | bool allow_encoder_probing() {
    function free_ctx (line 74) | void free_ctx(AVCodecContext *ctx) {
    function free_frame (line 78) | void free_frame(AVFrame *frame) {
    function free_buffer (line 82) | void free_buffer(AVBufferRef *ref) {
    type nv (line 86) | namespace nv {
      type profile_h264_e (line 88) | enum class profile_h264_e : int {
      type profile_hevc_e (line 93) | enum class profile_hevc_e : int {
    type qsv (line 101) | namespace qsv {
      type profile_h264_e (line 103) | enum class profile_h264_e : int {
      type profile_hevc_e (line 108) | enum class profile_hevc_e : int {
      type profile_av1_e (line 114) | enum class profile_av1_e : int {
    class avcodec_software_encode_device_t (line 126) | class avcodec_software_encode_device_t: public platf::avcodec_encode_d...
      method convert (line 128) | int convert(platf::img_t &img) override {
      method set_frame (line 174) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
      method apply_colorspace (line 191) | void apply_colorspace() override {
      method prefill (line 199) | void prefill() {
      method init (line 207) | int init(int in_width, int in_height, AVFrame *frame, AVPixelFormat ...
    type flag_e (line 290) | enum flag_e : uint32_t {
    class avcodec_encode_session_t (line 306) | class avcodec_encode_session_t: public encode_session_t {
      method avcodec_encode_session_t (line 308) | avcodec_encode_session_t() = default;
      method avcodec_encode_session_t (line 310) | avcodec_encode_session_t(avcodec_ctx_t &&avcodec_ctx, std::unique_pt...
      method avcodec_encode_session_t (line 316) | avcodec_encode_session_t(avcodec_encode_session_t &&other) noexcept ...
      method avcodec_encode_session_t (line 331) | avcodec_encode_session_t &operator=(avcodec_encode_session_t &&other) {
      method convert (line 343) | int convert(platf::img_t &img) override {
      method request_idr_frame (line 350) | void request_idr_frame() override {
      method request_normal_frame (line 358) | void request_normal_frame() override {
      method invalidate_ref_frames (line 366) | void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) ...
    class nvenc_encode_session_t (line 383) | class nvenc_encode_session_t: public encode_session_t {
      method nvenc_encode_session_t (line 385) | nvenc_encode_session_t(std::unique_ptr<platf::nvenc_encode_device_t>...
      method convert (line 389) | int convert(platf::img_t &img) override {
      method request_idr_frame (line 396) | void request_idr_frame() override {
      method request_normal_frame (line 400) | void request_normal_frame() override {
      method invalidate_ref_frames (line 404) | void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) ...
      method encode_frame (line 414) | nvenc::nvenc_encoded_frame encode_frame(uint64_t frame_index) {
    type sync_session_ctx_t (line 429) | struct sync_session_ctx_t {
    type sync_session_t (line 442) | struct sync_session_t {
    type capture_ctx_t (line 450) | struct capture_ctx_t {
    type capture_thread_async_ctx_t (line 455) | struct capture_thread_async_ctx_t {
    type capture_thread_sync_ctx_t (line 464) | struct capture_thread_sync_ctx_t {
    function encoder_t (line 517) | encoder_t nvenc {
    function dxgi_init_avcodec_hardware_input_buffer (line 2971) | util::Either<avcodec_buffer_t, int> dxgi_init_avcodec_hardware_input_b...
    function start_capture_async (line 2998) | int start_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
    function end_capture_async (line 3015) | void end_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
    function start_capture_sync (line 3021) | int start_capture_sync(capture_thread_sync_ctx_t &ctx) {
    function end_capture_sync (line 3026) | void end_capture_sync(capture_thread_sync_ctx_t &ctx) {
    function map_base_dev_type (line 3029) | platf::mem_type_e map_base_dev_type(AVHWDeviceType type) {
    function map_pix_fmt (line 3048) | platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt) {
  function vaapi_init_avcodec_hardware_input_buffer (line 2914) | util::Either<avcodec_buffer_t, int> vaapi_init_avcodec_hardware_input_bu...
  function cuda_init_avcodec_hardware_input_buffer (line 2938) | util::Either<avcodec_buffer_t, int> cuda_init_avcodec_hardware_input_buf...
  function vt_init_avcodec_hardware_input_buffer (line 2951) | util::Either<avcodec_buffer_t, int> vt_init_avcodec_hardware_input_buffe...
  function do_nothing (line 2967) | void do_nothing(void *) {
  type video (line 2970) | namespace video {
    function allow_encoder_probing (line 48) | bool allow_encoder_probing() {
    function free_ctx (line 74) | void free_ctx(AVCodecContext *ctx) {
    function free_frame (line 78) | void free_frame(AVFrame *frame) {
    function free_buffer (line 82) | void free_buffer(AVBufferRef *ref) {
    type nv (line 86) | namespace nv {
      type profile_h264_e (line 88) | enum class profile_h264_e : int {
      type profile_hevc_e (line 93) | enum class profile_hevc_e : int {
    type qsv (line 101) | namespace qsv {
      type profile_h264_e (line 103) | enum class profile_h264_e : int {
      type profile_hevc_e (line 108) | enum class profile_hevc_e : int {
      type profile_av1_e (line 114) | enum class profile_av1_e : int {
    class avcodec_software_encode_device_t (line 126) | class avcodec_software_encode_device_t: public platf::avcodec_encode_d...
      method convert (line 128) | int convert(platf::img_t &img) override {
      method set_frame (line 174) | int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
      method apply_colorspace (line 191) | void apply_colorspace() override {
      method prefill (line 199) | void prefill() {
      method init (line 207) | int init(int in_width, int in_height, AVFrame *frame, AVPixelFormat ...
    type flag_e (line 290) | enum flag_e : uint32_t {
    class avcodec_encode_session_t (line 306) | class avcodec_encode_session_t: public encode_session_t {
      method avcodec_encode_session_t (line 308) | avcodec_encode_session_t() = default;
      method avcodec_encode_session_t (line 310) | avcodec_encode_session_t(avcodec_ctx_t &&avcodec_ctx, std::unique_pt...
      method avcodec_encode_session_t (line 316) | avcodec_encode_session_t(avcodec_encode_session_t &&other) noexcept ...
      method avcodec_encode_session_t (line 331) | avcodec_encode_session_t &operator=(avcodec_encode_session_t &&other) {
      method convert (line 343) | int convert(platf::img_t &img) override {
      method request_idr_frame (line 350) | void request_idr_frame() override {
      method request_normal_frame (line 358) | void request_normal_frame() override {
      method invalidate_ref_frames (line 366) | void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) ...
    class nvenc_encode_session_t (line 383) | class nvenc_encode_session_t: public encode_session_t {
      method nvenc_encode_session_t (line 385) | nvenc_encode_session_t(std::unique_ptr<platf::nvenc_encode_device_t>...
      method convert (line 389) | int convert(platf::img_t &img) override {
      method request_idr_frame (line 396) | void request_idr_frame() override {
      method request_normal_frame (line 400) | void request_normal_frame() override {
      method invalidate_ref_frames (line 404) | void invalidate_ref_frames(int64_t first_frame, int64_t last_frame) ...
      method encode_frame (line 414) | nvenc::nvenc_encoded_frame encode_frame(uint64_t frame_index) {
    type sync_session_ctx_t (line 429) | struct sync_session_ctx_t {
    type sync_session_t (line 442) | struct sync_session_t {
    type capture_ctx_t (line 450) | struct capture_ctx_t {
    type capture_thread_async_ctx_t (line 455) | struct capture_thread_async_ctx_t {
    type capture_thread_sync_ctx_t (line 464) | struct capture_thread_sync_ctx_t {
    function encoder_t (line 517) | encoder_t nvenc {
    function dxgi_init_avcodec_hardware_input_buffer (line 2971) | util::Either<avcodec_buffer_t, int> dxgi_init_avcodec_hardware_input_b...
    function start_capture_async (line 2998) | int start_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
    function end_capture_async (line 3015) | void end_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
    function start_capture_sync (line 3021) | int start_capture_sync(capture_thread_sync_ctx_t &ctx) {
    function end_capture_sync (line 3026) | void end_capture_sync(capture_thread_sync_ctx_t &ctx) {
    function map_base_dev_type (line 3029) | platf::mem_type_e map_base_dev_type(AVHWDeviceType type) {
    function map_pix_fmt (line 3048) | platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt) {

FILE: src/video.h
  type AVPacket (line 18) | struct AVPacket
  function namespace (line 20) | namespace video {
  function encoder_platform_formats_t (line 109) | struct encoder_platform_formats_nvenc: encoder_platform_formats_t {
  type encoder_t (line 125) | struct encoder_t {
  type option_t (line 154) | struct option_t {
  function codec_t (line 193) | const codec_t &codec_from_config(const config_t &config) const {
  type encode_session_t (line 210) | struct encode_session_t {
  function packet_raw_avcodec (line 243) | struct packet_raw_t {
  function is_idr (line 281) | bool is_idr() override {
  function frame_index (line 285) | int64_t frame_index() override {
  function data_size (line 293) | size_t data_size() override {
  type packet_raw_generic (line 300) | struct packet_raw_generic
  function is_idr (line 307) | bool is_idr() override {
  function frame_index (line 311) | int64_t frame_index() override {
  function data_size (line 319) | size_t data_size() override {
  type hdr_info_raw_t (line 330) | struct hdr_info_raw_t {

FILE: src/video_colorspace.cpp
  type video (line 16) | namespace video {
    function colorspace_is_hdr (line 18) | bool colorspace_is_hdr(const sunshine_colorspace_t &colorspace) {
    function sunshine_colorspace_t (line 22) | sunshine_colorspace_t colorspace_from_client_config(const config_t &co...
    function avcodec_colorspace_t (line 79) | avcodec_colorspace_t avcodec_colorspace_from_sunshine_colorspace(const...
    function color_t (line 123) | const color_t *color_vectors_from_colorspace(const sunshine_colorspace...

FILE: src/video_colorspace.h
  function namespace (line 11) | namespace video {

FILE: src_assets/common/assets/web/init.js
  function initApp (line 8) | function initApp(app, config) {

FILE: src_assets/common/assets/web/platform-i18n.js
  class PlatformMessageI18n (line 3) | class PlatformMessageI18n {
    method constructor (line 7) | constructor(platform) {
    method getPlatformKey (line 16) | getPlatformKey(key, platform) {
    method getMessageUsingPlatform (line 25) | getMessageUsingPlatform(key, defaultMsg) {
  function usePlatformI18n (line 56) | function usePlatformI18n(platform) {
  function $tp (line 77) | function $tp(key, defaultMsg) {

FILE: src_assets/common/assets/web/sunshine_version.js
  class SunshineVersion (line 1) | class SunshineVersion {
    method constructor (line 2) | constructor(release = null, version = null) {
    method parseVersion (line 22) | parseVersion(version) {
    method isGreater (line 33) | isGreater(otherVersion) {

FILE: src_assets/common/assets/web/theme.js
  function setupThemeToggleListener (line 81) | function setupThemeToggleListener() {
  function loadAutoTheme (line 95) | function loadAutoTheme() {

FILE: tests/integration/test_config_consistency.cpp
  class ConfigConsistencyTest (line 23) | class ConfigConsistencyTest: public ::testing::Test {
    method SetUp (line 25) | void SetUp() override {
    method extractConfigCppOptions (line 44) | static std::set<std::string, std::less<>> extractConfigCppOptions() {
    method findClosingBrace (line 72) | static size_t findClosingBrace(const std::string &content, const size_...
    method extractTabId (line 89) | static std::string extractTabId(const std::string &tabObject) {
    method extractTabsContent (line 100) | static std::string extractTabsContent(const std::string &content) {
    method extractOptionsFromTabGeneric (line 126) | static void extractOptionsFromTabGeneric(const std::string &tabObject,...
    method processTabObjects (line 163) | static void processTabObjects(const std::string &tabsContent, Containe...
    method trimWhitespace (line 181) | static void trimWhitespace(std::string &str) {
    method extractOptionFromMarkdownLine (line 186) | static std::string extractOptionFromMarkdownLine(const std::string &li...
    method extractConfigHtmlOptions (line 197) | static std::map<std::string, std::string, std::less<>> extractConfigHt...
    method extractOptionsFromTab (line 211) | static void extractOptionsFromTab(const std::string &tabObject, std::m...
    method extractConfigHtmlOptionsWithOrder (line 216) | static std::map<std::string, std::vector<std::string>, std::less<>> ex...
    method processSectionHeader (line 230) | static bool processSectionHeader(const std::string &line, std::string ...
    method processOptionHeader (line 243) | static bool processOptionHeader(const std::string &line, const std::st...
    method extractConfigMdOptions (line 257) | static std::map<std::string, std::string, std::less<>> extractConfigMd...
    method processMarkdownOptionLine (line 277) | static void processMarkdownOptionLine(const std::string &line, const s...
    method extractConfigMdOptionsWithOrder (line 288) | static std::map<std::string, std::vector<std::string>, std::less<>> ex...
    method findConfigSectionEnd (line 308) | static size_t findConfigSectionEnd(const std::string &content, size_t ...
    method extractKeysFromConfigSection (line 326) | static void extractKeysFromConfigSection(const std::string_view config...
    method extractEnJsonConfigOptions (line 337) | static std::set<std::string, std::less<>> extractEnJsonConfigOptions() {
    method isOptionInHtml (line 362) | static bool isOptionInHtml(const std::string &option, const std::map<s...
    method isOptionInMd (line 367) | static bool isOptionInMd(const std::string &option, const std::map<std...
    method validateOptionExistence (line 372) | static void validateOptionExistence(const std::string &option, const s...
    method checkTabCorrespondence (line 387) | static void checkTabCorrespondence(const std::string &tab, const std::...
    method checkTestDummyDetection (line 408) | static void checkTestDummyDetection(const std::vector<std::string> &mi...
    method buildCommaSeparatedString (line 427) | static std::string buildCommaSeparatedString(const std::vector<std::st...
  function TEST_F (line 439) | TEST_F(ConfigConsistencyTest, AllConfigOptionsExistInAllFiles) {
  function TEST_F (line 470) | TEST_F(ConfigConsistencyTest, ConfigTabsMatchDocumentationSections) {
  function TEST_F (line 509) | TEST_F(ConfigConsistencyTest, ConfigOptionsInSameOrderWithinSections) {
  function TEST_F (line 569) | TEST_F(ConfigConsistencyTest, DummyConfigOptionsDoNotExist) {
  function TEST_F (line 616) | TEST_F(ConfigConsistencyTest, TestFrameworkDetectsMissingOptions) {

FILE: tests/integration/test_external_commands.cpp
  type ExternalCommandTestData (line 20) | struct ExternalCommandTestData {
    method ExternalCommandTestData (line 30) | ExternalCommandTestData(std::string cmd, std::string plat, const bool ...
  class ExternalCommandTest (line 40) | class ExternalCommandTest: public ::testing::TestWithParam<ExternalComma...
    method SetUp (line 42) | void SetUp() override {
    method shouldRunOnCurrentPlatform (line 52) | [[nodiscard]] bool shouldRunOnCurrentPlatform(const std::string_view &...
    method runCommand (line 57) | static std::pair<int, std::string> runCommand(const std::string &cmd, ...
  function TEST_P (line 117) | TEST_P(ExternalCommandTest, RunExternalCommand) {

FILE: tests/integration/test_locale_consistency.cpp
  class LocaleConsistencyTest (line 26) | class LocaleConsistencyTest: public ::testing::Test {
    method extractConfigCppLocales (line 29) | static std::set<std::string, std::less<>> extractConfigCppLocales() {
    method extractGeneralVueLocales (line 52) | static std::map<std::string, std::string, std::less<>> extractGeneralV...
    method getAvailableLocaleFiles (line 77) | static std::set<std::string, std::less<>> getAvailableLocaleFiles() {
    method isValidLocaleFile (line 96) | static bool isValidLocaleFile(const std::string &localeCode) {
  function TEST_F (line 117) | TEST_F(LocaleConsistencyTest, AllLocaleFilesHaveConfigCppEntries) {
  function TEST_F (line 139) | TEST_F(LocaleConsistencyTest, AllLocaleFilesHaveGeneralVueEntries) {
  function TEST_F (line 161) | TEST_F(LocaleConsistencyTest, AllConfigCppLocalesHaveFiles) {
  function TEST_F (line 183) | TEST_F(LocaleConsistencyTest, AllGeneralVueLocalesHaveFiles) {
  function TEST_F (line 205) | TEST_F(LocaleConsistencyTest, ConfigCppAndGeneralVueLocalesMatch) {
  function TEST_F (line 247) | TEST_F(LocaleConsistencyTest, AllLocaleFilesAreValid) {
  function TEST_F (line 267) | TEST_F(LocaleConsistencyTest, LocaleDisplayNamesAreConsistent) {
  function TEST_F (line 299) | TEST_F(LocaleConsistencyTest, NoOrphanedLocaleReferences) {
  function TEST_F (line 328) | TEST_F(LocaleConsistencyTest, TestFrameworkDetectsLocaleInconsistencies) {

FILE: tests/tests_common.h
  function namespace (line 26) | namespace test_utils {
  function Test (line 149) | struct PlatformTestSuite: testing::Test {

FILE: tests/tests_environment.h
  function Environment (line 8) | struct SunshineEnvironment: testing::Environment {

FILE: tests/tests_events.h
  function EmptyTestEventListener (line 8) | struct SunshineEventListener: testing::EmptyTestEventListener {

FILE: tests/tests_log_checker.h
  function namespace (line 13) | namespace log_checker {

FILE: tests/tests_main.cpp
  function main (line 9) | int main(int argc, char **argv) {

FILE: tests/unit/platform/test_common.cpp
  type SetEnvTest (line 10) | struct SetEnvTest: ::testing::TestWithParam<std::tuple<std::string, std:...
    method TearDown (line 12) | void TearDown() override {
  function TEST_P (line 19) | TEST_P(SetEnvTest, SetEnvironmentVariableTests) {
  function TEST_P (line 32) | TEST_P(SetEnvTest, UnsetEnvironmentVariableTests) {
  function TEST (line 52) | TEST(HostnameTests, TestAsioEquality) {

FILE: tests/unit/platform/windows/test_utf_utils.cpp
  class UtfUtilsTest (line 19) | class UtfUtilsTest: public testing::Test {}
  function TEST_F (line 21) | TEST_F(UtfUtilsTest, FromUtf8WithEmptyString) {
  function TEST_F (line 28) | TEST_F(UtfUtilsTest, ToUtf8WithEmptyWideString) {
  function TEST_F (line 35) | TEST_F(UtfUtilsTest, FromUtf8WithBasicString) {
  function TEST_F (line 42) | TEST_F(UtfUtilsTest, ToUtf8WithBasicWideString) {
  function TEST_F (line 49) | TEST_F(UtfUtilsTest, RoundTripConversionBasic) {
  function TEST_F (line 57) | TEST_F(UtfUtilsTest, FromUtf8WithQuotationMarks) {
  function TEST_F (line 117) | TEST_F(UtfUtilsTest, FromUtf8WithSpecialSymbols) {
  function TEST_F (line 135) | TEST_F(UtfUtilsTest, ToUtf8WithQuotationMarks) {
  function TEST_F (line 243) | TEST_F(UtfUtilsTest, LongStringsWithSpecialCharacters) {
  function TEST (line 259) | TEST(UtfUtilsTest, UtfUtilsNotAvailableOnNonWindows) {

FILE: tests/unit/test_audio.cpp
  type AudioTest (line 11) | struct AudioTest: PlatformTestSuite, testing::WithParamInterface<std::tu...
    method SetUp (line 12) | void SetUp() override {
  function config_flags (line 21) | constexpr std::bitset<config_t::MAX_FLAGS> config_flags(const int flag =...
  function TEST_P (line 43) | TEST_P(AudioTest, TestEncode) {

FILE: tests/unit/test_confighttp.cpp
  class ConfigHttpTest (line 92) | class ConfigHttpTest: public ::testing::Test {  // NOSONAR(cpp:S3656) - ...
    method SetUp (line 109) | void SetUp() override {
    method TearDown (line 335) | void TearDown() override {
    method create_auth_header (line 359) | static std::string create_auth_header(const std::string &username, con...
    method assert_security_headers (line 363) | static void assert_security_headers(const std::shared_ptr<SimpleWeb::C...
    method assert_json_error_response (line 373) | static void assert_json_error_response(const std::shared_ptr<SimpleWeb...
  function TEST_F (line 387) | TEST_F(ConfigHttpTest, AuthenticateRejectsNoAuth) {
  function TEST_F (line 397) | TEST_F(ConfigHttpTest, AuthenticateAcceptsValidCredentials) {
  function TEST_F (line 409) | TEST_F(ConfigHttpTest, AuthenticateRejectsInvalidPassword) {
  function TEST_F (line 418) | TEST_F(ConfigHttpTest, AuthenticateCaseInsensitiveUsername) {
  function TEST_F (line 427) | TEST_F(ConfigHttpTest, SendUnauthorizedResponse) {
  function TEST_F (line 446) | TEST_F(ConfigHttpTest, NotFoundResponse) {
  function TEST_F (line 453) | TEST_F(ConfigHttpTest, BadRequestResponse) {
  function TEST_F (line 460) | TEST_F(ConfigHttpTest, SendResponseJson) {
  function TEST_F (line 480) | TEST_F(ConfigHttpTest, SendRedirectResponse) {
  function TEST_F (line 494) | TEST_F(ConfigHttpTest, CheckContentTypeValid) {
  function TEST_F (line 506) | TEST_F(ConfigHttpTest, CheckContentTypeMissing) {
  function TEST_F (line 515) | TEST_F(ConfigHttpTest, CheckContentTypeWrong) {
  function TEST_F (line 527) | TEST_F(ConfigHttpTest, CheckContentTypeWithCharset) {
  function TEST_F (line 539) | TEST_F(ConfigHttpTest, CSRFTokenGeneration) {
  function TEST_F (line 557) | TEST_F(ConfigHttpTest, CSRFValidationWithValidTokenInHeader) {
  function TEST_F (line 582) | TEST_F(ConfigHttpTest, CSRFValidationWithMissingToken) {
  function TEST_F (line 606) | TEST_F(ConfigHttpTest, CSRFValidationWithInvalidToken) {
  function TEST_F (line 625) | TEST_F(ConfigHttpTest, CSRFSameOriginExemptionWithOrigin) {
  function TEST_F (line 639) | TEST_F(ConfigHttpTest, CSRFSameOriginExemptionWithReferer) {
  function TEST_F (line 653) | TEST_F(ConfigHttpTest, GetPageWithAuth) {
  function TEST_F (line 677) | TEST_F(ConfigHttpTest, GetPageRequiresAuth) {
  function TEST_F (line 687) | TEST_F(ConfigHttpTest, GetPageWithoutAuthRequired) {
  function TEST_F (line 697) | TEST_F(ConfigHttpTest, GetPageRedirectsWhenUsernameSet) {
  function TEST_F (line 709) | TEST_F(ConfigHttpTest, GetPageNoRedirectWhenUsernameEmpty) {
  function TEST_F (line 722) | TEST_F(ConfigHttpTest, GetLocaleReturnsJson) {
  class BrowseDirectoryTest (line 754) | class BrowseDirectoryTest: public ConfigHttpTest {  // NOSONAR(cpp:S3656...
    method SetUp (line 758) | void SetUp() override {
    method TearDown (line 786) | void TearDown() override {
    method url_encode_param (line 800) | static std::string url_encode_param(const std::string &str) {
    method browse_url (line 815) | std::string browse_url(const std::string &path = "", const std::string...
    method find_entry (line 831) | static nlohmann::json::const_iterator find_entry(const nlohmann::json ...
  function TEST_F (line 839) | TEST_F(BrowseDirectoryTest, BrowseRequiresAuthentication) {
  function TEST_F (line 845) | TEST_F(BrowseDirectoryTest, BrowseListsValidDirectory) {
  function TEST_F (line 866) | TEST_F(BrowseDirectoryTest, BrowseResponsePathMatchesRequest) {
  function TEST_F (line 880) | TEST_F(BrowseDirectoryTest, BrowseResponseParentIsCorrect) {
  function TEST_F (line 894) | TEST_F(BrowseDirectoryTest, BrowseResponseContainsExpectedEntries) {
  function TEST_F (line 922) | TEST_F(BrowseDirectoryTest, BrowseEntryFieldsArePresent) {
  function TEST_F (line 942) | TEST_F(BrowseDirectoryTest, BrowseEntriesSortedDirsFirst) {
  function TEST_F (line 962) | TEST_F(BrowseDirectoryTest, BrowseEntriesSortedAlphabeticallyWithinGroup...
  function TEST_F (line 991) | TEST_F(BrowseDirectoryTest, BrowseTypeDirFilterExcludesFiles) {
  function TEST_F (line 1012) | TEST_F(BrowseDirectoryTest, BrowseTypeFileReturnsBoth) {
  function TEST_F (line 1033) | TEST_F(BrowseDirectoryTest, BrowseTypeExecutableIncludesDirs) {
  function TEST_F (line 1050) | TEST_F(BrowseDirectoryTest, BrowseTypeExecutableExcludesNonExecutableFil...
  function TEST_F (line 1071) | TEST_F(BrowseDirectoryTest, BrowseTypeExecutableIncludesExecutableFile) {
  function TEST_F (line 1092) | TEST_F(BrowseDirectoryTest, BrowseFilepathNavigatesToParentDirectory) {
  function TEST_F (line 1107) | TEST_F(BrowseDirectoryTest, BrowseNonexistentChildPathFallsBackToParent) {
  function TEST_F (line 1122) | TEST_F(BrowseDirectoryTest, BrowseTrulyNonexistentPathReturnsBadRequest) {
  function TEST_F (line 1133) | TEST_F(BrowseDirectoryTest, BrowseEmptyPathReturnsValidResponse) {
  function TEST_F (line 1149) | TEST_F(BrowseDirectoryTest, BrowseWindowsEmptyPathReturnsDriveList) {
  function TEST_F (line 1173) | TEST_F(BrowseDirectoryTest, BrowseUnixRootParentEqualsSelf) {
  function TEST_F (line 1195) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_WindowsExeExtension_Re...
  function TEST_F (line 1201) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_WindowsBatExtension_Re...
  function TEST_F (line 1209) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_WindowsTxtExtension_Re...
  function TEST_F (line 1215) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_WindowsCaseInsensitive...
  function TEST_F (line 1224) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_LinuxExecBitSet_Return...
  function TEST_F (line 1230) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_LinuxNoExecBit_Returns...
  function TEST_F (line 1236) | TEST_F(BrowseDirectoryTest, IsBrowsableExecutable_LinuxGroupExecBit_Retu...
  function TEST_F (line 1251) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_TypeAny_ReturnsAllEntries) {
  function TEST_F (line 1259) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_TypeDirectory_OnlyReturns...
  function TEST_F (line 1269) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_TypeFile_ReturnsDirsAndFi...
  function TEST_F (line 1283) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_TypeExecutable_IncludesDi...
  function TEST_F (line 1305) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_SortsDirsBeforeFiles) {
  function TEST_F (line 1322) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_SortsAlphabeticallyWithin...
  function TEST_F (line 1347) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_EachEntryHasRequiredField...
  function TEST_F (line 1361) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_EmptyDirectory_ReturnsEmp...
  function TEST_F (line 1374) | TEST_F(BrowseDirectoryTest, BuildBrowseEntries_NonexistentDirectory_Retu...
  function TEST_F (line 1382) | TEST_F(BrowseDirectoryTest, GetWindowsDrives_ReturnsAtLeastOneDrive) {
  function TEST_F (line 1389) | TEST_F(BrowseDirectoryTest, GetWindowsDrives_EntriesHaveCorrectFormat) {

FILE: tests/unit/test_display_device.cpp
  type failed_to_parse_resolution_tag_t (line 25) | struct failed_to_parse_resolution_tag_t {}
  type failed_to_parse_refresh_rate_tag_t (line 27) | struct failed_to_parse_refresh_rate_tag_t {}
  type no_refresh_rate_tag_t (line 29) | struct no_refresh_rate_tag_t {}
  type no_resolution_tag_t (line 31) | struct no_resolution_tag_t {}
  type client_resolution_t (line 33) | struct client_resolution_t {
  type DisplayDeviceConfigTest (line 46) | struct DisplayDeviceConfigTest: testing::TestWithParam<T> {}
  function TEST_P (line 60) | TEST_P(ParseDeviceId, IntegrationTest) {
  function TEST_P (line 84) | TEST_P(ParseConfigOption, IntegrationTest) {
  function TEST_P (line 110) | TEST_P(ParseHdrOption, IntegrationTest) {
  function TEST_P (line 176) | TEST_P(ParseResolutionOption, IntegrationTest) {
  function TEST_P (line 260) | TEST_P(ParseRefreshRateOption, IntegrationTest) {
  type no_value_t (line 295) | struct no_value_t {}
  type auto_value_t (line 298) | struct auto_value_t {
  type manual_value_t (line 303) | struct manual_value_t {
  type failed_to_remap_t (line 310) | struct failed_to_remap_t {}
  type final_values_t (line 312) | struct final_values_t {
  function TEST_P (line 458) | TEST_P(DisplayModeRemapping, IntegrationTest) {

FILE: tests/unit/test_entry_handler.cpp
  function TEST (line 10) | TEST(EntryHandlerTests, LogPublisherDataTest) {

FILE: tests/unit/test_file_handler.cpp
  type FileHandlerParentDirectoryTest (line 10) | struct FileHandlerParentDirectoryTest: testing::TestWithParam<std::tuple...
  function TEST_P (line 12) | TEST_P(FileHandlerParentDirectoryTest, Run) {
  type FileHandlerMakeDirectoryTest (line 27) | struct FileHandlerMakeDirectoryTest: testing::TestWithParam<std::tuple<s...
  function TEST_P (line 29) | TEST_P(FileHandlerMakeDirectoryTest, Run) {
  type FileHandlerTests (line 55) | struct FileHandlerTests: testing::TestWithParam<std::tuple<int, std::str...
  function TEST_P (line 81) | TEST_P(FileHandlerTests, WriteFileTest) {
  function TEST_P (line 87) | TEST_P(FileHandlerTests, ReadFileTest) {
  function TEST (line 93) | TEST(FileHandlerTests, ReadMissingFileTest) {

FILE: tests/unit/test_http_pairing.cpp
  type pairing_input (line 12) | struct pairing_input {
  type pairing_output (line 25) | struct pairing_output {
  type PairingTest (line 79) | struct PairingTest: testing::TestWithParam<std::tuple<pairing_input, pai...
  function TEST_P (line 81) | TEST_P(PairingTest, Run) {
  function TEST (line 242) | TEST(PairingTest, OutOfOrderCalls) {

FILE: tests/unit/test_httpcommon.cpp
  type UrlEscapeTest (line 14) | struct UrlEscapeTest: testing::TestWithParam<std::tuple<std::string, std...
  function TEST_P (line 16) | TEST_P(UrlEscapeTest, Run) {
  type UrlGetHostTest (line 31) | struct UrlGetHostTest: testing::TestWithParam<std::tuple<std::string, st...
  function TEST_P (line 33) | TEST_P(UrlGetHostTest, Run) {
  type DownloadFileTest (line 48) | struct DownloadFileTest: testing::TestWithParam<std::tuple<std::string, ...
  function TEST_P (line 50) | TEST_P(DownloadFileTest, Run) {

FILE: tests/unit/test_logging.cpp
  type LogLevelsTest (line 25) | struct LogLevelsTest: testing::TestWithParam<decltype(log_levels)::value...
  function TEST_P (line 36) | TEST_P(LogLevelsTest, PutMessage) {

FILE: tests/unit/test_mouse.cpp
  type MouseHIDTest (line 9) | struct MouseHIDTest: PlatformTestSuite, testing::WithParamInterface<util...
    method SetUp (line 10) | void SetUp() override {
    method TearDown (line 22) | void TearDown() override {
  function TEST_P (line 38) | TEST_P(MouseHIDTest, MoveInputTest) {
  function TEST_P (line 73) | TEST_P(MouseHIDTest, AbsMoveInputTest) {

FILE: tests/unit/test_network.cpp
  type MdnsInstanceNameTest (line 9) | struct MdnsInstanceNameTest: testing::TestWithParam<std::tuple<std::stri...
  function TEST_P (line 11) | TEST_P(MdnsInstanceNameTest, Run) {
  class BindAddressTest (line 33) | class BindAddressTest: public ::testing::Test {
    method SetUp (line 37) | void SetUp() override {
    method TearDown (line 42) | void TearDown() override {
  function TEST_F (line 51) | TEST_F(BindAddressTest, DefaultBehaviorIPv4) {
  function TEST_F (line 62) | TEST_F(BindAddressTest, DefaultBehaviorIPv6) {
  function TEST_F (line 73) | TEST_F(BindAddressTest, ConfiguredIPv4Address) {
  function TEST_F (line 84) | TEST_F(BindAddressTest, ConfiguredIPv6Address) {
  function TEST_F (line 95) | TEST_F(BindAddressTest, ConfiguredAddressOverridesFamily) {
  function TEST_F (line 107) | TEST_F(BindAddressTest, LoopbackAddresses) {
  function TEST_F (line 122) | TEST_F(BindAddressTest, LinkLocalAddresses) {
  function TEST_F (line 137) | TEST_F(BindAddressTest, WildcardAddressFunction) {

FILE: tests/unit/test_process.cpp
  class ProcessPNGTest (line 17) | class ProcessPNGTest: public ::testing::Test {
    method SetUp (line 19) | void SetUp() override {
    method TearDown (line 25) | void TearDown() override {
    method createTestFile (line 33) | void createTestFile(const fs::path &path, const std::vector<unsigned c...
  function TEST_F (line 43) | TEST_F(ProcessPNGTest, CheckValidPNG_ValidSignature) {
  function TEST_F (line 71) | TEST_F(ProcessPNGTest, CheckValidPNG_WrongSignature) {
  function TEST_F (line 90) | TEST_F(ProcessPNGTest, CheckValidPNG_TooShort) {
  function TEST_F (line 105) | TEST_F(ProcessPNGTest, CheckValidPNG_EmptyFile) {
  function TEST_F (line 115) | TEST_F(ProcessPNGTest, CheckValidPNG_NonExistentFile) {
  function TEST_F (line 122) | TEST_F(ProcessPNGTest, CheckValidPNG_RealFile) {
  function TEST_F (line 133) | TEST_F(ProcessPNGTest, CheckValidPNG_JPEGFile) {
  function TEST_F (line 152) | TEST_F(ProcessPNGTest, CheckValidPNG_PartialSignature) {
  function TEST_F (line 172) | TEST_F(ProcessPNGTest, ValidateAppImagePath_EmptyPath) {
  function TEST_F (line 178) | TEST_F(ProcessPNGTest, ValidateAppImagePath_NonPNGExtension) {
  function TEST_F (line 184) | TEST_F(ProcessPNGTest, ValidateAppImagePath_CaseInsensitiveExtension) {
  function TEST_F (line 214) | TEST_F(ProcessPNGTest, ValidateAppImagePath_NonExistentFile) {
  function TEST_F (line 220) | TEST_F(ProcessPNGTest, ValidateAppImagePath_InvalidPNGSignature) {
  function TEST_F (line 240) | TEST_F(ProcessPNGTest, ValidateAppImagePath_ValidPNG) {
  function TEST_F (line 268) | TEST_F(ProcessPNGTest, ValidateAppImagePath_OldSteamDefault) {

FILE: tests/unit/test_rswrapper.cpp
  function TEST (line 11) | TEST(ReedSolomonWrapperTests, InitTest) {
  function TEST (line 21) | TEST(ReedSolomonWrapperTests, EncodeTest) {

FILE: tests/unit/test_stream.cpp
  type stream (line 11) | namespace stream {
  function TEST (line 17) | TEST(ConcatAndInsertTests, ConcatNoInsertionTest) {
  function TEST (line 25) | TEST(ConcatAndInsertTests, ConcatLargeStrideTest) {
  function TEST (line 33) | TEST(ConcatAndInsertTests, ConcatSmallStrideTest) {

FILE: tests/unit/test_video.cpp
  type EncoderTest (line 9) | struct EncoderTest: PlatformTestSuite, testing::WithParamInterface<video...
    method SetUp (line 10) | void SetUp() override {
  function TEST_P (line 48) | TEST_P(EncoderTest, ValidateEncoder) {
  type FramerateX100Test (line 52) | struct FramerateX100Test: testing::TestWithParam<std::tuple<std::int32_t...
  function TEST_P (line 54) | TEST_P(FramerateX100Test, Run) {

FILE: third-party/nvfbc/NvFBC.h
  type NVFBCSTATUS (line 281) | typedef enum _NVFBCSTATUS {
  type NVFBC_BOOL (line 386) | typedef enum _NVFBC_BOOL {
  type NVFBC_CAPTURE_TYPE (line 405) | typedef enum _NVFBC_CAPTURE_TYPE {
  type NVFBC_TRACKING_TYPE (line 439) | typedef enum {
  type NVFBC_BUFFER_FORMAT (line 470) | typedef enum _NVFBC_BUFFER_FORMAT {
  type NVFBC_SESSION_HANDLE (line 505) | typedef uint64_t NVFBC_SESSION_HANDLE;
  type NVFBC_BOX (line 517) | typedef struct _NVFBC_BOX {
  type NVFBC_SIZE (line 539) | typedef struct _NVFBC_SIZE {
  type NVFBC_FRAME_GRAB_INFO (line 553) | typedef struct _NVFBC_FRAME_GRAB_INFO {
  type NVFBC_CREATE_HANDLE_PARAMS (line 639) | typedef struct _NVFBC_CREATE_HANDLE_PARAMS {
  type NVFBC_DESTROY_HANDLE_PARAMS (line 699) | typedef struct _NVFBC_DESTROY_HANDLE_PARAMS {
  type NVFBC_RANDR_OUTPUT_INFO (line 729) | typedef struct _NVFBC_OUTPUT {
  type NVFBC_GET_STATUS_PARAMS (line 750) | typedef struct _NVFBC_GET_STATUS_PARAMS {
  type NVFBC_CREATE_CAPTURE_SESSION_PARAMS (line 821) | typedef struct _NVFBC_CREATE_CAPTURE_SESSION_PARAMS {
  type NVFBC_DESTROY_CAPTURE_SESSION_PARAMS (line 988) | typedef struct _NVFBC_DESTROY_CAPTURE_SESSION_PARAMS {
  type NVFBC_BIND_CONTEXT_PARAMS (line 1003) | typedef struct _NVFBC_BIND_CONTEXT_PARAMS {
  type NVFBC_RELEASE_CONTEXT_PARAMS (line 1018) | typedef struct _NVFBC_RELEASE_CONTEXT_PARAMS {
  type NVFBC_TOSYS_GRAB_FLAGS (line 1033) | typedef enum {
  type NVFBC_TOSYS_SETUP_PARAMS (line 1073) | typedef struct _NVFBC_TOSYS_SETUP_PARAMS {
  type NVFBC_TOSYS_GRAB_FRAME_PARAMS (line 1151) | typedef struct _NVFBC_TOSYS_GRAB_FRAME_PARAMS {
  type NVFBC_TOCUDA_FLAGS (line 1202) | typedef enum {
  type NVFBC_TOCUDA_SETUP_PARAMS (line 1242) | typedef struct _NVFBC_TOCUDA_SETUP_PARAMS {
  type NVFBC_TOCUDA_GRAB_FRAME_PARAMS (line 1261) | typedef struct _NVFBC_TOCUDA_GRAB_FRAME_PARAMS {
  type NVFBC_TOGL_FLAGS (line 1326) | typedef enum {
  type NVFBC_TOGL_SETUP_PARAMS (line 1371) | typedef struct _NVFBC_TOGL_SETUP_PARAMS {
  type NVFBC_TOGL_GRAB_FRAME_PARAMS (line 1437) | typedef struct _NVFBC_TOGL_GRAB_FRAME_PARAMS {
  type NVFBC_API_FUNCTION_LIST (line 1941) | typedef struct

FILE: third-party/nvfbc/helper_math.h
  type uint (line 44) | typedef unsigned int uint;
  type ushort (line 45) | typedef unsigned short ushort;
  function fminf (line 58) | inline float
  function fmaxf (line 63) | inline float
  function max (line 68) | inline int
  function min (line 73) | inline int
  function rsqrtf (line 78) | inline float
  function float2 (line 88) | float2
  function float2 (line 92) | float2
  function float2 (line 96) | float2
  function float2 (line 100) | float2
  function int2 (line 105) | int2
  function int2 (line 109) | int2
  function int2 (line 113) | int2
  function int2 (line 117) | int2
  function uint2 (line 122) | uint2
  function uint2 (line 126) | uint2
  function uint2 (line 130) | uint2
  function float3 (line 135) | float3
  function float3 (line 139) | float3
  function float3 (line 143) | float3
  function float3 (line 147) | float3
  function float3 (line 151) | float3
  function float3 (line 155) | float3
  function int3 (line 160) | int3
  function int3 (line 164) | int3
  function int3 (line 168) | int3
  function int3 (line 172) | int3
  function int3 (line 176) | int3
  function uint3 (line 181) | uint3
  function uint3 (line 185) | uint3
  function uint3 (line 189) | uint3
  function uint3 (line 193) | uint3
  function uint3 (line 197) | uint3
  function float4 (line 202) | float4
  function float4 (line 206) | float4
  function float4 (line 210) | float4
  function float4 (line 214) | float4
  function float4 (line 218) | float4
  function int4 (line 223) | int4
  function int4 (line 227) | int4
  function int4 (line 231) | int4
  function int4 (line 235) | int4
  function int4 (line 239) | int4
  function uint4 (line 244) | uint4
  function uint4 (line 248) | uint4
  function uint4 (line 252) | uint4
  function uint4 (line 256) | uint4
  function float2 (line 749) | float2
  function float2 (line 758) | float2
  function float2 (line 762) | float2
  function int2 (line 772) | int2
  function int2 (line 781) | int2
  function int2 (line 785) | int2
  function uint2 (line 795) | uint2
  function uint2 (line 804) | uint2
  function uint2 (line 808) | uint2
  function float3 (line 818) | float3
  function float3 (line 828) | float3
  function float3 (line 832) | float3
  function int3 (line 843) | int3
  function int3 (line 853) | int3
  function int3 (line 857) | int3
  function uint3 (line 868) | uint3
  function uint3 (line 878) | uint3
  function uint3 (line 882) | uint3
  function float4 (line 893) | float4
  function float4 (line 904) | float4
  function float4 (line 908) | float4
  function int4 (line 920) | int4
  function int4 (line 931) | int4
  function int4 (line 935) | int4
  function uint4 (line 947) | uint4
  function uint4 (line 958) | uint4
  function uint4 (line 962) | uint4
  function float2 (line 1057) | float2
  function float3 (line 1061) | float3
  function float4 (line 1065) | float4
  function int2 (line 1070) | int2
  function int3 (line 1074) | int3
  function int4 (line 1078) | int4
  function uint2 (line 1083) | uint2
  function uint3 (line 1087) | uint3
  function uint4 (line 1091) | uint4
  function float2 (line 1100) | float2
  function float3 (line 1104) | float3
  function float4 (line 1108) | float4
  function int2 (line 1113) | int2
  function int3 (line 1117) | int3
  function int4 (line 1121) | int4
  function uint2 (line 1126) | uint2
  function uint3 (line 1130) | uint3
  function uint4 (line 1134) | uint4
  function lerp (line 1144) | float
  function float2 (line 1148) | float2
  function float3 (line 1152) | float3
  function float4 (line 1156) | float4
  function clamp (line 1166) | float
  function clamp (line 1170) | int
  function uint (line 1174) | uint
  function float2 (line 1179) | float2
  function float2 (line 1183) | float2
  function float3 (line 1187) | float3
  function float3 (line 1191) | float3
  function float4 (line 1195) | float4
  function float4 (line 1199) | float4
  function int2 (line 1204) | int2
  function int2 (line 1208) | int2
  function int3 (line 1212) | int3
  function int3 (line 1216) | int3
  function int4 (line 1220) | int4
  function int4 (line 1224) | int4
  function uint2 (line 1229) | uint2
  function uint2 (line 1233) | uint2
  function uint3 (line 1237) | uint3
  function uint3 (line 1241) | uint3
  function uint4 (line 1245) | uint4
  function uint4 (line 1249) | uint4
  function dot (line 1258) | float
  function dot (line 1262) | float
  function dot (line 1266) | float
  function dot (line 1271) | int
  function dot (line 1275) | int
  function dot (line 1279) | int
  function uint (line 1284) | uint
  function uint (line 1288) | uint
  function uint (line 1292) | uint
  function length (line 1301) | float
  function length (line 1305) | float
  function length (line 1309) | float
  function float2 (line 1318) | float2
  function float3 (line 1323) | float3
  function float4 (line 1328) | float4
  function float2 (line 1338) | float2
  function float3 (line 1342) | float3
  function float4 (line 1346) | float4
  function fracf (line 1355) | float
  function float2 (line 1359) | float2
  function float3 (line 1363) | float3
  function float4 (line 1367) | float4
  function float2 (line 1376) | float2
  function float3 (line 1380) | float3
  function float4 (line 1384) | float4
  function float2 (line 1393) | float2
  function float3 (line 1397) | float3
  function float4 (line 1401) | float4
  function int2 (line 1406) | int2
  function int3 (line 1410) | int3
  function int4 (line 1414) | int4
  function float3 (line 1425) | float3
  function float3 (line 1434) | float3
  function smoothstep (line 1446) | float
  function float2 (line 1451) | float2
  function float3 (line 1456) | float3
  function float4 (line 1461) | float4

FILE: tools/audio.cpp
  type audio (line 26) | namespace audio {
    function Release (line 28) | void Release(T *p) {
    function co_task_free (line 33) | void co_task_free(T *p) {
    class prop_var_t (line 49) | class prop_var_t {
      method prop_var_t (line 51) | prop_var_t() {
    type format_t (line 62) | struct format_t {
    function set_wave_format (line 107) | void set_wave_format(audio::wave_format_t &wave_format, const format_t...
    function audio_client_t (line 121) | audio_client_t make_audio_client(device_t &device, const format_t &for...
    function print_device (line 163) | void print_device(device_t &device) {
  function print_help (line 232) | void print_help() {
  function main (line 239) | int main(int argc, char *argv[]) {

FILE: tools/dxgi.cpp
  type dxgi (line 16) | namespace dxgi {
    function Release (line 18) | void Release(T *dxgi) {
  function main (line 27) | int main(int argc, char *argv[]) {

FILE: tools/sunshinesvc.cpp
  function DWORD (line 23) | DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEven...
  function HANDLE (line 54) | HANDLE CreateJobObjectForChildProcess() {
  function LPPROC_THREAD_ATTRIBUTE_LIST (line 78) | LPPROC_THREAD_ATTRIBUTE_LIST AllocateProcThreadAttributeList(DWORD attri...
  function HANDLE (line 95) | HANDLE DuplicateTokenForSession(DWORD console_session_id) {
  function HANDLE (line 119) | HANDLE OpenLogFileHandle() {
  function RunTerminationHelper (line 133) | bool RunTerminationHelper(HANDLE console_token, DWORD pid) {
  function VOID (line 169) | VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
  function DoGracefulTermination (line 323) | int DoGracefulTermination(DWORD pid) {
  function main (line 340) | int main(int argc, char *argv[]) {
Condensed preview — 452 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,051K chars).
[
  {
    "path": ".clang-format",
    "chars": 3485,
    "preview": "---\n# This file is centrally managed in https://github.com/<organization>/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".dockerignore",
    "chars": 384,
    "preview": "# ignore hidden files\n.*\n\n# do not ignore .git, needed for versioning\n!/.git\n\n# do not ignore .rstcheck.cfg, needed to t"
  },
  {
    "path": ".flake8",
    "chars": 89,
    "preview": "[flake8]\nfilename =\n    *.py\nmax-line-length = 120\nextend-exclude =\n    .venv/\n    venv/\n"
  },
  {
    "path": ".gitattributes",
    "chars": 165,
    "preview": "# ensure Linux specific files are checked out with LF line endings\nDockerfile text eol=lf\n*.dockerfile text eol=lf\n*flat"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 5672,
    "preview": "---\nname: Bug Report\ndescription: Create a bug report to help us improve.\nbody:\n  - type: markdown\n    attributes:\n     "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 703,
    "preview": "---\n# This file is centrally managed in https://github.com/<organization>/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/copilot-instructions.md",
    "chars": 437,
    "preview": "On Windows we use msys2 and ucrt64 to compile.\nYou need to prefix commands with `C:\\msys64\\msys2_shell.cmd -defterm -her"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 2600,
    "preview": "---\n# This file is centrally managed in https://github.com/<organization>/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/matchers/copr-ci.json",
    "chars": 337,
    "preview": "{\n  \"problemMatcher\": [\n    {\n      \"owner\": \"copr-ci-gcc\",\n      \"pattern\": [\n        {\n          \"regexp\": \"^/?(?:[^/]"
  },
  {
    "path": ".github/matchers/docker.json",
    "chars": 365,
    "preview": "{\n  \"problemMatcher\": [\n    {\n      \"owner\": \"docker-gcc\",\n      \"pattern\": [\n        {\n          \"regexp\": \"^(?:#\\\\d+\\\\"
  },
  {
    "path": ".github/matchers/gcc-strip3.json",
    "chars": 336,
    "preview": "{\n  \"problemMatcher\": [\n    {\n      \"owner\": \"gcc-strip3\",\n      \"pattern\": [\n        {\n          \"regexp\": \"^/?(?:[^/]+"
  },
  {
    "path": ".github/matchers/gcc.json",
    "chars": 578,
    "preview": "{\n  \"problemMatcher\": [\n    {\n      \"owner\": \"gcc\",\n      \"pattern\": [\n        {\n          \"regexp\": \"^(.*):(\\\\d+):(\\\\d+"
  },
  {
    "path": ".github/semantic.yml",
    "chars": 591,
    "preview": "---\n# This file is centrally managed in https://github.com/<organization>/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_codeql.yml",
    "chars": 727,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_common-lint.yml",
    "chars": 608,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_release-notifier.yml",
    "chars": 836,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-changelog.yml",
    "chars": 849,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-docs.yml",
    "chars": 1062,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-flathub-repo.yml",
    "chars": 951,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-homebrew-repo.yml",
    "chars": 961,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-pacman-repo.yml",
    "chars": 950,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/_update-winget-repo.yml",
    "chars": 901,
    "preview": "---\n# This workflow is centrally managed in https://github.com/LizardByte/.github/\n# Don't make changes to this file in "
  },
  {
    "path": ".github/workflows/ci-archlinux.yml",
    "chars": 5386,
    "preview": "---\nname: CI-Archlinux\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      release_commit:\n        required: true\n  "
  },
  {
    "path": ".github/workflows/ci-bundle.yml",
    "chars": 757,
    "preview": "---\nname: CI-Bundle\npermissions: {}\n\non:\n  workflow_call:\n    secrets:\n      CODECOV_TOKEN:\n        required: false\n\njob"
  },
  {
    "path": ".github/workflows/ci-copr.yml",
    "chars": 2208,
    "preview": "---\nname: CI-Copr\npermissions: {}\n\non:\n  release:\n    types:\n      - prereleased\n      - released\n  workflow_call:\n    s"
  },
  {
    "path": ".github/workflows/ci-flatpak.yml",
    "chars": 7848,
    "preview": "---\nname: CI-Flatpak\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      release_commit:\n        required: true\n    "
  },
  {
    "path": ".github/workflows/ci-freebsd.yml",
    "chars": 8685,
    "preview": "---\nname: CI-FreeBSD\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      release_commit:\n        required: true\n    "
  },
  {
    "path": ".github/workflows/ci-homebrew.yml",
    "chars": 7361,
    "preview": "---\nname: CI-Homebrew\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      git_username:\n        required: true\n     "
  },
  {
    "path": ".github/workflows/ci-linux.yml",
    "chars": 6683,
    "preview": "---\nname: CI-Linux\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      release_commit:\n        required: true\n      "
  },
  {
    "path": ".github/workflows/ci-macos.yml",
    "chars": 10236,
    "preview": "---\nname: CI-macOS\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      publish_release:\n        required: true\n     "
  },
  {
    "path": ".github/workflows/ci-windows.yml",
    "chars": 12715,
    "preview": "---\nname: CI-Windows\npermissions: {}\n\non:\n  workflow_call:\n    inputs:\n      # Azure Artifact Signing account name\n     "
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 11812,
    "preview": "---\nname: CI\npermissions: {}\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n  workflow_dispatch:\n\nconcurrency"
  },
  {
    "path": ".github/workflows/localize.yml",
    "chars": 2895,
    "preview": "---\nname: localize\npermissions: {}\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - '.github/workflows/local"
  },
  {
    "path": ".github/workflows/release-notifier-moonlight.yml",
    "chars": 1399,
    "preview": "---\nname: Release Notifications (Moonlight)\npermissions: {}\n\non:\n  release:\n    types:\n      - released  # this triggers"
  },
  {
    "path": ".github/workflows/update-pages.yml",
    "chars": 1108,
    "preview": "---\nname: Build GH-Pages\npermissions: {}\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n  workflow_dispatch:\n"
  },
  {
    "path": ".gitignore",
    "chars": 490,
    "preview": "# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic"
  },
  {
    "path": ".gitmodules",
    "chars": 2684,
    "preview": "[submodule \"packaging/linux/flatpak/deps/flatpak-builder-tools\"]\n\tpath = packaging/linux/flatpak/deps/flatpak-builder-to"
  },
  {
    "path": ".prettierrc.json",
    "chars": 2,
    "preview": "{}"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 790,
    "preview": "---\n# .readthedocs.yaml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.ht"
  },
  {
    "path": ".rstcheck.cfg",
    "chars": 208,
    "preview": "# configuration file for rstcheck, an rst linting tool\n# https://rstcheck.readthedocs.io/en/latest/usage/config\n\n[rstche"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 2394,
    "preview": "cmake_minimum_required(VERSION 3.20)\n# `CMAKE_CUDA_ARCHITECTURES` requires 3.18\n# `set_source_files_properties` requires"
  },
  {
    "path": "DOCKER_README.md",
    "chars": 5811,
    "preview": "# Docker\n\n## Important note\nStarting with v0.18.0, tag names have changed. You may no longer use `latest`, `master`, `vX"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "NOTICE",
    "chars": 171,
    "preview": "©2018 Valve Corporation. Steam and the Steam logo are trademarks and/or\nregistered trademarks of Valve Corporation in th"
  },
  {
    "path": "README.md",
    "chars": 13309,
    "preview": "<div align=\"center\">\n  <img src=\"sunshine.png\"  alt=\"Sunshine icon\"/>\n  <h1 align=\"center\">Sunshine</h1>\n  <h4 align=\"ce"
  },
  {
    "path": "cmake/FindLIBCAP.cmake",
    "chars": 879,
    "preview": "# - Try to find Libcap\n# Once done this will define\n#\n#  LIBCAP_FOUND - system has Libcap\n#  LIBCAP_INCLUDE_DIRS - the L"
  },
  {
    "path": "cmake/FindLIBDRM.cmake",
    "chars": 889,
    "preview": "# - Try to find Libdrm\n# Once done this will define\n#\n#  LIBDRM_FOUND - system has Libdrm\n#  LIBDRM_INCLUDE_DIRS - the L"
  },
  {
    "path": "cmake/FindLibva.cmake",
    "chars": 2483,
    "preview": "# - Try to find Libva\n# This module defines the following variables:\n#\n# * LIBVA_FOUND - The component was found\n# * LIB"
  },
  {
    "path": "cmake/FindSystemd.cmake",
    "chars": 1301,
    "preview": "# - Try to find Systemd\n# Once done this will define\n#\n# SYSTEMD_FOUND - system has systemd\n# SYSTEMD_USER_UNIT_INSTALL_"
  },
  {
    "path": "cmake/FindUdev.cmake",
    "chars": 1828,
    "preview": "# - Try to find Udev\n# Once done this will define\n#\n# UDEV_FOUND - system has udev\n# UDEV_RULES_INSTALL_DIR - the udev r"
  },
  {
    "path": "cmake/FindWayland.cmake",
    "chars": 3860,
    "preview": "# Try to find Wayland on a Unix system\n#\n# This will define:\n#\n#   WAYLAND_FOUND        - True if Wayland is found\n#   W"
  },
  {
    "path": "cmake/compile_definitions/common.cmake",
    "chars": 6643,
    "preview": "# common compile definitions\n# this file will also load platform specific definitions\n\nlist(APPEND SUNSHINE_COMPILE_OPTI"
  },
  {
    "path": "cmake/compile_definitions/linux.cmake",
    "chars": 9554,
    "preview": "# linux specific compile definitions\n\nif(FREEBSD)\n    add_compile_definitions(SUNSHINE_PLATFORM=\"freebsd\")\nelse()\n    ad"
  },
  {
    "path": "cmake/compile_definitions/macos.cmake",
    "chars": 2402,
    "preview": "# macos specific compile definitions\n\nadd_compile_definitions(SUNSHINE_PLATFORM=\"macos\")\n\nif (SUNSHINE_BUILD_HOMEBREW)\n "
  },
  {
    "path": "cmake/compile_definitions/unix.cmake",
    "chars": 382,
    "preview": "# unix specific compile definitions\n# put anything here that applies to both linux and macos\n\nlist(APPEND SUNSHINE_EXTER"
  },
  {
    "path": "cmake/compile_definitions/windows.cmake",
    "chars": 4395,
    "preview": "# windows specific compile definitions\n\nadd_compile_definitions(SUNSHINE_PLATFORM=\"windows\")\n\nenable_language(RC)\nset(CM"
  },
  {
    "path": "cmake/dependencies/Boost_Sunshine.cmake",
    "chars": 3628,
    "preview": "#\n# Loads the boost library giving the priority to the system package first, with a fallback to FetchContent.\n#\ninclude_"
  },
  {
    "path": "cmake/dependencies/FindOpus.cmake",
    "chars": 3416,
    "preview": "# Copyright 2019-2022, Collabora, Ltd.\n#\n# SPDX-License-Identifier: BSL-1.0\n#\n# Distributed under the Boost Software Lic"
  },
  {
    "path": "cmake/dependencies/common.cmake",
    "chars": 1852,
    "preview": "# load common dependencies\n# this file will also load platform specific dependencies\n\n# Resolve OpenSSL before subprojec"
  },
  {
    "path": "cmake/dependencies/ffmpeg.cmake",
    "chars": 6736,
    "preview": "#\n# Loads FFmpeg pre-compiled binaries from GitHub releases or a user-specified path\n#\ninclude_guard(GLOBAL)\n\n# ffmpeg p"
  },
  {
    "path": "cmake/dependencies/glad.cmake",
    "chars": 9844,
    "preview": "#\n# Generates the glad OpenGL/EGL loader library using the glad2 generator.\n# Sources are generated at build time via th"
  },
  {
    "path": "cmake/dependencies/libevdev_Sunshine.cmake",
    "chars": 1713,
    "preview": "#\n# Loads the libevdev library giving the priority to the system package first, with a fallback to ExternalProject\n#\ninc"
  },
  {
    "path": "cmake/dependencies/linux.cmake",
    "chars": 87,
    "preview": "# linux specific dependencies\n\ninclude(\"${CMAKE_MODULE_PATH}/dependencies/glad.cmake\")\n"
  },
  {
    "path": "cmake/dependencies/macos.cmake",
    "chars": 424,
    "preview": "# macos specific dependencies\n\nFIND_LIBRARY(APP_KIT_LIBRARY AppKit)\nFIND_LIBRARY(APP_SERVICES_LIBRARY ApplicationService"
  },
  {
    "path": "cmake/dependencies/nlohmann_json.cmake",
    "chars": 933,
    "preview": "#\n# Loads the nlohmann_json library giving the priority to the system package first, with a fallback to FetchContent.\n#\n"
  },
  {
    "path": "cmake/dependencies/unix.cmake",
    "chars": 86,
    "preview": "# unix specific dependencies\n# put anything here that applies to both linux and macos\n"
  },
  {
    "path": "cmake/dependencies/windows.cmake",
    "chars": 1685,
    "preview": "# windows specific dependencies\n\n# MinHook setup - use installed minhook for AMD64, otherwise download minhook-detours f"
  },
  {
    "path": "cmake/macros/common.cmake",
    "chars": 881,
    "preview": "# common macros\n# this file will also load platform specific macros\n\n# platform specific macros\nif(WIN32)\n    include(${"
  },
  {
    "path": "cmake/macros/linux.cmake",
    "chars": 1160,
    "preview": "# linux specific macros\n\n# GEN_WAYLAND: args = `filename`\nmacro(GEN_WAYLAND wayland_directory subdirectory filename)\n   "
  },
  {
    "path": "cmake/macros/macos.cmake",
    "chars": 619,
    "preview": "# macos specific macros\n\n# ADD_FRAMEWORK: args = `fwname`, `appname`\nmacro(ADD_FRAMEWORK fwname appname)\n    find_librar"
  },
  {
    "path": "cmake/macros/unix.cmake",
    "chars": 80,
    "preview": "# unix specific macros\n# put anything here that applies to both linux and macos\n"
  },
  {
    "path": "cmake/macros/windows.cmake",
    "chars": 26,
    "preview": "# windows specific macros\n"
  },
  {
    "path": "cmake/packaging/common.cmake",
    "chars": 1971,
    "preview": "# common packaging\n\n# common cpack options\nset(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})\nset(CPACK_PACKAGE_VENDOR \"Lizar"
  },
  {
    "path": "cmake/packaging/freebsd_custom_cpack.cmake",
    "chars": 5278,
    "preview": "# FreeBSD post-build script to fix +POST_INSTALL and +PRE_DEINSTALL scripts\n# in the generated .pkg file.\n#\n# This scrip"
  },
  {
    "path": "cmake/packaging/linux.cmake",
    "chars": 7299,
    "preview": "# linux specific packaging\n\ninstall(DIRECTORY \"${SUNSHINE_SOURCE_ASSETS_DIR}/linux/assets/\"\n        DESTINATION \"${SUNSH"
  },
  {
    "path": "cmake/packaging/macos.cmake",
    "chars": 4347,
    "preview": "# macos specific packaging\n\nif (SUNSHINE_BUILD_HOMEBREW)\n    install(DIRECTORY \"${SUNSHINE_SOURCE_ASSETS_DIR}/macos/asse"
  },
  {
    "path": "cmake/packaging/unix.cmake",
    "chars": 408,
    "preview": "# unix specific packaging\n# put anything here that applies to both linux and macos\n\n# return here if building a macos .a"
  },
  {
    "path": "cmake/packaging/windows.cmake",
    "chars": 5120,
    "preview": "# windows specific packaging\ninstall(TARGETS sunshine RUNTIME DESTINATION \".\" COMPONENT application)\n\n# Hardening: inclu"
  },
  {
    "path": "cmake/packaging/windows_nsis.cmake",
    "chars": 2866,
    "preview": "# NSIS Packaging\n# see options at: https://cmake.org/cmake/help/latest/cpack_gen/nsis.html\n\nset(CPACK_NSIS_INSTALLED_ICO"
  },
  {
    "path": "cmake/packaging/windows_wix.cmake",
    "chars": 3481,
    "preview": "# WIX Packaging\n# see options at: https://cmake.org/cmake/help/latest/cpack_gen/wix.html\n\n# find dotnet\nfind_program(DOT"
  },
  {
    "path": "cmake/packaging/wix_resources/patch.xml",
    "chars": 140,
    "preview": "<CPackWiXPatch>\n  <CPackWiXFragment Id=\"CM_G_Core\">\n    <FeatureRef Id=\"RunSunshineInstallScripts\"/>\n  </CPackWiXFragmen"
  },
  {
    "path": "cmake/packaging/wix_resources/sunshine-installer.wxs",
    "chars": 6218,
    "preview": "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\"\n     xmlns:util=\"http://wixtoolset.org/schemas/v4/wxs/util\">\n  <Fragme"
  },
  {
    "path": "cmake/prep/build_version.cmake",
    "chars": 6697,
    "preview": "# Set build variables if env variables are defined\n# These are used in configured files such as manifests for different "
  },
  {
    "path": "cmake/prep/constants.cmake",
    "chars": 245,
    "preview": "# source assets will be installed from this directory\nset(SUNSHINE_SOURCE_ASSETS_DIR \"${CMAKE_SOURCE_DIR}/src_assets\")\n\n"
  },
  {
    "path": "cmake/prep/init.cmake",
    "chars": 739,
    "preview": "if (WIN32)\nelseif (APPLE)\n    if (NOT SUNSHINE_BUILD_HOMEBREW)\n        set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)\n        se"
  },
  {
    "path": "cmake/prep/options.cmake",
    "chars": 2943,
    "preview": "# Publisher Metadata\nset(SUNSHINE_PUBLISHER_NAME \"Third Party Publisher\"\n        CACHE STRING \"The name of the publisher"
  },
  {
    "path": "cmake/prep/special_package_configuration.cmake",
    "chars": 2067,
    "preview": "if(UNIX)\n    if(${SUNSHINE_CONFIGURE_HOMEBREW})\n        configure_file(packaging/sunshine.rb sunshine.rb @ONLY)\n    endi"
  },
  {
    "path": "cmake/targets/common.cmake",
    "chars": 4977,
    "preview": "# common target definitions\n# this file will also load platform specific macros\n\nif(APPLE AND NOT SUNSHINE_BUILD_HOMEBRE"
  },
  {
    "path": "cmake/targets/linux.cmake",
    "chars": 215,
    "preview": "# linux specific target definitions\n\n# Using newer c++ compilers / features on older distros causes runtime dyn link err"
  },
  {
    "path": "cmake/targets/macos.cmake",
    "chars": 1338,
    "preview": "# macos specific target definitions\n\nif (SUNSHINE_BUILD_HOMEBREW)\n    target_link_options(sunshine PRIVATE LINKER:-sectc"
  },
  {
    "path": "cmake/targets/unix.cmake",
    "chars": 92,
    "preview": "# unix specific target definitions\n# put anything here that applies to both linux and macos\n"
  },
  {
    "path": "cmake/targets/windows.cmake",
    "chars": 323,
    "preview": "# windows specific target definitions\nset_target_properties(sunshine PROPERTIES LINK_SEARCH_START_STATIC 1)\nset(CMAKE_FI"
  },
  {
    "path": "codecov.yml",
    "chars": 302,
    "preview": "---\ncodecov:\n  branch: master\n\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: 1"
  },
  {
    "path": "crowdin.yml",
    "chars": 1070,
    "preview": "---\n\"base_path\": \".\"\n\"base_url\": \"https://api.crowdin.com\"  # optional (for Crowdin Enterprise only)\n\"preserve_hierarchy"
  },
  {
    "path": "docker/clion-toolchain.dockerfile",
    "chars": 2420,
    "preview": "# syntax=docker/dockerfile:1\n# artifacts: false\n# platforms: linux/amd64\n# platforms_pr: linux/amd64\n# no-cache-filters:"
  },
  {
    "path": "docker/debian-trixie.dockerfile",
    "chars": 2851,
    "preview": "# syntax=docker/dockerfile:1\n# artifacts: true\n# platforms: linux/amd64,linux/arm64/v8\n# platforms_pr: linux/amd64\n# no-"
  },
  {
    "path": "docker/ubuntu-22.04.dockerfile",
    "chars": 2770,
    "preview": "# syntax=docker/dockerfile:1\n# artifacts: true\n# platforms: linux/amd64,linux/arm64/v8\n# platforms_pr: linux/amd64\n# no-"
  },
  {
    "path": "docker/ubuntu-24.04.dockerfile",
    "chars": 2747,
    "preview": "# syntax=docker/dockerfile:1\n# artifacts: true\n# platforms: linux/amd64,linux/arm64/v8\n# platforms_pr: linux/amd64\n# no-"
  },
  {
    "path": "docs/Doxyfile",
    "chars": 2232,
    "preview": "# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n#"
  },
  {
    "path": "docs/api.js",
    "chars": 5585,
    "preview": "function generateExamples(endpoint, method, body = null) {\n  let curlBodyString = '';\n  let curlHeaderString = '';\n  let"
  },
  {
    "path": "docs/api.md",
    "chars": 2963,
    "preview": "# API\n\nSunshine has a RESTful API which can be used to interact with the service.\n\nUnless otherwise specified, authentic"
  },
  {
    "path": "docs/app_examples.md",
    "chars": 21240,
    "preview": "# App Examples\nSince not all applications behave the same, we decided to create some examples to help you get started ad"
  },
  {
    "path": "docs/awesome_sunshine.md",
    "chars": 541,
    "preview": "# Awesome-Sunshine\n\n@htmlonly\n<script type=\"module\" src=\"https://md-block.verou.me/md-block.js\"></script>\n<md-block\n  hl"
  },
  {
    "path": "docs/building.md",
    "chars": 6589,
    "preview": "# Building\nSunshine binaries are built using [CMake](https://cmake.org) and requires `cmake` > 3.25.\n\n## Building Locall"
  },
  {
    "path": "docs/changelog.md",
    "chars": 568,
    "preview": "# Changelog\n\n@htmlonly\n<script type=\"module\" src=\"https://md-block.verou.me/md-block.js\"></script>\n<md-block\n  hmin=\"2\"\n"
  },
  {
    "path": "docs/configuration.js",
    "chars": 1299,
    "preview": "/**\n * @brief Add a button to open the configuration option for each table\n */\ndocument.addEventListener(\"DOMContentLoad"
  },
  {
    "path": "docs/configuration.md",
    "chars": 80333,
    "preview": "# Configuration\n\n@admonition{ Host authority | @htmlonly\nBy providing the host authority (URI + port), you can easily op"
  },
  {
    "path": "docs/contributing.md",
    "chars": 8481,
    "preview": "# Contributing\nRead our contribution guide in our organization level\n[docs](https://docs.lizardbyte.dev/latest/developer"
  },
  {
    "path": "docs/doc-styles.css",
    "chars": 155,
    "preview": "/* A fake button as doxygen doesn't allow button elements */\n.open-button {\n    background: var(--primary-color);\n    co"
  },
  {
    "path": "docs/gamestream_migration.md",
    "chars": 1703,
    "preview": "# GameStream Migration\nNvidia announced that their GameStream service for Nvidia Games clients will be discontinued in F"
  },
  {
    "path": "docs/getting_started.md",
    "chars": 23077,
    "preview": "# Getting Started\n\nThe recommended method for running Sunshine is to use the [binaries](#binaries) included in the\n[late"
  },
  {
    "path": "docs/guides.md",
    "chars": 671,
    "preview": "# Guides\n\n@admonition{Community | A collection of guides written by the community is available on our\n[blog](https://app"
  },
  {
    "path": "docs/legal.md",
    "chars": 1816,
    "preview": "# Legal\n\n> [!CAUTION]\n> This documentation is for informational purposes only and is not intended as legal advice. If yo"
  },
  {
    "path": "docs/maintainers/README.md",
    "chars": 639,
    "preview": "# Maintainer Documentation\n\nThis directory contains documentation intended for Sunshine maintainers only. These document"
  },
  {
    "path": "docs/maintainers/release.md",
    "chars": 2636,
    "preview": "# Create a stable Sunshine release\n\nPre-releases in Sunshine are created automatically on every push event to the `maste"
  },
  {
    "path": "docs/performance_tuning.md",
    "chars": 680,
    "preview": "# Performance Tuning\nIn addition to the options available in the [Configuration](configuration.md) section, there are a "
  },
  {
    "path": "docs/third_party_packages.md",
    "chars": 2778,
    "preview": "# Third-Party Packages\n\n> [!WARNING]\n> These packages are not maintained by LizardByte. Use at your own risk.\n\n## Chocol"
  },
  {
    "path": "docs/troubleshooting.md",
    "chars": 9927,
    "preview": "# Troubleshooting\n\n## General\n\n### Forgotten Credentials\nIf you forgot your credentials to the web UI, try this.\n\n@tabs{"
  },
  {
    "path": "gh-pages-template/.readthedocs.yaml",
    "chars": 623,
    "preview": "---\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\nvers"
  },
  {
    "path": "gh-pages-template/_config.yml",
    "chars": 159,
    "preview": "---\n# See https://github.com/LizardByte/beautiful-jekyll-next/blob/master/_config.yml for documented options\n\navatar: \"/"
  },
  {
    "path": "gh-pages-template/_data/clients.yml",
    "chars": 5920,
    "preview": "---\n- name: \"Android\"\n  type: \"official\"\n  github: \"https://github.com/moonlight-stream/moonlight-android\"\n  icons:\n    "
  },
  {
    "path": "gh-pages-template/_data/features.yml",
    "chars": 1379,
    "preview": "---\n- title: \"Self-hosted\"\n  icon_fa: \"fas fa-server\"\n  description: >\n    Run Sunshine on your own hardware. No need to"
  },
  {
    "path": "gh-pages-template/index.html",
    "chars": 13388,
    "preview": "---\ntitle: Sunshine\nsubtitle: A LizardByte project\nlayout: page\nfull-width: true\nafter-content:\n- donate.html\n- support."
  },
  {
    "path": "package.json",
    "chars": 664,
    "preview": "{\n  \"name\": \"sunshine\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"build\": \"vite build --debug\",\n    \"build-clean\": \"vite"
  },
  {
    "path": "packaging/linux/AppImage/AppRun",
    "chars": 2704,
    "preview": "#!/bin/bash\n\n# custom AppRun for Sunshine AppImage\n\n# path of the extracted AppRun\nHERE=\"$(dirname \"$(readlink -f \"${0}\""
  },
  {
    "path": "packaging/linux/AppImage/dev.lizardbyte.app.Sunshine.desktop",
    "chars": 305,
    "preview": "[Desktop Entry]\nCategories=RemoteAccess;Network;\nComment=@PROJECT_DESCRIPTION@\nExec=sunshine\nIcon=sunshine\nKeywords=game"
  },
  {
    "path": "packaging/linux/Arch/PKGBUILD",
    "chars": 6122,
    "preview": "# Edit on github: https://github.com/LizardByte/Sunshine/blob/master/packaging/linux/Arch/PKGBUILD\n# Reference: https://"
  },
  {
    "path": "packaging/linux/Arch/sunshine.install",
    "chars": 416,
    "preview": "do_setcap() {\n  setcap cap_sys_admin+p $(readlink -f usr/bin/sunshine)\n}\n\ndo_udev_reload() {\n  udevadm control --reload-"
  },
  {
    "path": "packaging/linux/app-dev.lizardbyte.app.Sunshine.service.in",
    "chars": 442,
    "preview": "[Unit]\nDescription=@PROJECT_DESCRIPTION@\nStartLimitIntervalSec=500\nStartLimitBurst=5\nAfter=graphical-session.target xdg-"
  },
  {
    "path": "packaging/linux/copr/Sunshine.spec",
    "chars": 10898,
    "preview": "%global build_timestamp %(date +\"%Y%m%d\")\n\n# use sed to replace these values\n%global build_version 0\n%global branch 0\n%g"
  },
  {
    "path": "packaging/linux/dev.lizardbyte.app.Sunshine.desktop",
    "chars": 494,
    "preview": "[Desktop Entry]\nActions=RunInTerminal;\nCategories=RemoteAccess;Network;\nComment=@PROJECT_DESCRIPTION@\nExec=/usr/bin/env "
  },
  {
    "path": "packaging/linux/dev.lizardbyte.app.Sunshine.metainfo.xml",
    "chars": 2244,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<component type=\"desktop\">\n  <id>@PROJECT_FQDN@</id>\n\n  <name>@PROJECT_NAME@</nam"
  },
  {
    "path": "packaging/linux/dev.lizardbyte.app.Sunshine.terminal.desktop",
    "chars": 96,
    "preview": "[Desktop Entry]\nName=@PROJECT_NAME@\nExec=sunshine\nTerminal=true\nType=Application\nNoDisplay=true\n"
  },
  {
    "path": "packaging/linux/flatpak/README.md",
    "chars": 1124,
    "preview": "<div align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/LizardByte/Sunshine/master/sunshine.png\" />\n  <h1 ali"
  },
  {
    "path": "packaging/linux/flatpak/apps.json",
    "chars": 148,
    "preview": "{\n  \"env\": {\n    \"PATH\": \"$(PATH):$(HOME)/.local/bin\"\n  },\n  \"apps\": [\n    {\n      \"name\": \"Desktop\",\n      \"image-path\""
  },
  {
    "path": "packaging/linux/flatpak/dev.lizardbyte.app.Sunshine.desktop",
    "chars": 224,
    "preview": "[Desktop Entry]\nCategories=RemoteAccess;Network;\nComment=@PROJECT_DESCRIPTION@\nExec=sunshine.sh\nIcon=@SUNSHINE_DESKTOP_I"
  },
  {
    "path": "packaging/linux/flatpak/dev.lizardbyte.app.Sunshine.yml",
    "chars": 3691,
    "preview": "---\napp-id: \"@PROJECT_FQDN@\"\nruntime: org.freedesktop.Platform\nruntime-version: \"24.08\"\nsdk: org.freedesktop.Sdk\nsdk-ext"
  },
  {
    "path": "packaging/linux/flatpak/exceptions.json",
    "chars": 253,
    "preview": "{\n  \"dev.lizardbyte.app.Sunshine\": [\n    \"appstream-external-screenshot-url\",\n    \"appstream-screenshots-not-mirrored-in"
  },
  {
    "path": "packaging/linux/flatpak/flathub.json",
    "chars": 44,
    "preview": "{\n  \"disable-external-data-checker\": true\n}\n"
  },
  {
    "path": "packaging/linux/flatpak/modules/avahi.json",
    "chars": 1042,
    "preview": "{\n  \"name\": \"avahi\",\n  \"cleanup\": [\n    \"/bin\",\n    \"/lib/avahi\",\n    \"/share\"\n  ],\n  \"config-opts\": [\n    \"--with-distr"
  },
  {
    "path": "packaging/linux/flatpak/modules/boost.json",
    "chars": 597,
    "preview": "{\n  \"name\": \"boost\",\n  \"buildsystem\": \"simple\",\n  \"build-commands\": [\n    \"cd tools/build && bison -y -d -o src/engine/j"
  },
  {
    "path": "packaging/linux/flatpak/modules/cuda.json",
    "chars": 1071,
    "preview": "{\n  \"name\": \"cuda\",\n  \"build-options\": {\n    \"no_debuginfo\": true\n  },\n  \"buildsystem\": \"simple\",\n  \"cleanup\": [\n    \"*\""
  },
  {
    "path": "packaging/linux/flatpak/modules/ffmpeg.json",
    "chars": 1427,
    "preview": "{\n  \"name\": \"ffmpeg-prebuilt\",\n  \"buildsystem\": \"simple\",\n  \"build-commands\": [\n    \"mkdir -p /app/ffmpeg\",\n    \"tar -xz"
  },
  {
    "path": "packaging/linux/flatpak/modules/libevdev.json",
    "chars": 594,
    "preview": "{\n  \"name\": \"libevdev\",\n  \"buildsystem\": \"meson\",\n  \"config-opts\": [\n    \"-Ddocumentation=disabled\",\n    \"-Dtests=disabl"
  },
  {
    "path": "packaging/linux/flatpak/modules/miniupnpc.json",
    "chars": 832,
    "preview": "{\n  \"name\": \"miniupnpc\",\n  \"buildsystem\": \"cmake-ninja\",\n  \"builddir\": true,\n  \"subdir\": \"miniupnpc\",\n  \"config-opts\": ["
  },
  {
    "path": "packaging/linux/flatpak/modules/nlohmann_json.json",
    "chars": 375,
    "preview": "{\n  \"name\": \"nlohmann_json\",\n  \"buildsystem\": \"cmake-ninja\",\n  \"config-opts\": [\n    \"-DJSON_MultipleHeaders=OFF\",\n    \"-"
  },
  {
    "path": "packaging/linux/flatpak/modules/numactl.json",
    "chars": 460,
    "preview": "{\n  \"name\": \"numactl\",\n  \"sources\": [\n    {\n      \"type\": \"git\",\n      \"url\": \"https://github.com/numactl/numactl.git\",\n"
  },
  {
    "path": "packaging/linux/flatpak/modules/xvfb/xvfb-run",
    "chars": 5696,
    "preview": "#!/bin/sh\n\n# This script starts an instance of Xvfb, the \"fake\" X server, runs a command\n# with that server available, a"
  },
  {
    "path": "packaging/linux/flatpak/modules/xvfb/xvfb.json",
    "chars": 4151,
    "preview": "{\n  \"name\": \"xvfb\",\n  \"buildsystem\": \"meson\",\n  \"config-opts\": [\n    \"-Dxorg=true\",\n    \"-Dxvfb=true\",\n    \"-Dhal=false\""
  },
  {
    "path": "packaging/linux/flatpak/scripts/additional-install.sh",
    "chars": 875,
    "preview": "#!/bin/sh\n\n# User Service\nmkdir -p ~/.config/systemd/user\ncp \"/app/share/sunshine/systemd/user/app-dev.lizardbyte.app.Su"
  },
  {
    "path": "packaging/linux/flatpak/scripts/remove-additional-install.sh",
    "chars": 458,
    "preview": "#!/bin/sh\n\n# User Service\nsystemctl --user stop app-dev.lizardbyte.app.Sunshine\nrm \"$HOME/.config/systemd/user/app-dev.l"
  },
  {
    "path": "packaging/linux/flatpak/scripts/sunshine.sh",
    "chars": 264,
    "preview": "#!/bin/sh\n\nPORT=47990\n\nif ! curl -k https://localhost:$PORT > /dev/null 2>&1; then\n  (sleep 3 && xdg-open https://localh"
  },
  {
    "path": "packaging/linux/patches/aarch64/cuda-12-math_functions.patch",
    "chars": 3203,
    "preview": "diff '--color=auto' -ur a/cuda/targets/sbsa-linux/include/crt/math_functions.h b/cuda/targets/sbsa-linux/include/crt/mat"
  },
  {
    "path": "packaging/linux/patches/aarch64/cuda-13-math_functions.patch",
    "chars": 1676,
    "preview": "diff --color=auto -ur a/cuda/targets/sbsa-linux/include/crt/math_functions.h b/cuda/targets/sbsa-linux/include/crt/math_"
  },
  {
    "path": "packaging/linux/patches/x86_64/cuda-12-math_functions.patch",
    "chars": 3211,
    "preview": "diff '--color=auto' -ur a/cuda/targets/x86_64-linux/include/crt/math_functions.h b/cuda/targets/x86_64-linux/include/crt"
  },
  {
    "path": "packaging/linux/patches/x86_64/cuda-13-math_functions.patch",
    "chars": 1684,
    "preview": "diff --color=auto -ur a/cuda/targets/x86_64-linux/include/crt/math_functions.h b/cuda/targets/x86_64-linux/include/crt/m"
  },
  {
    "path": "packaging/sunshine.rb",
    "chars": 11132,
    "preview": "require \"language/node\"\n\nclass Sunshine < Formula\n  include Language::Python::Virtualenv\n\n  CUDA_VERSION = \"13.1\".freeze"
  },
  {
    "path": "pyproject.toml",
    "chars": 1302,
    "preview": "[build-system]\nrequires = [\"setuptools\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"Sunshine\"\nd"
  },
  {
    "path": "scripts/_locale.py",
    "chars": 5269,
    "preview": "\"\"\"\n..\n   _locale.py\n\nFunctions related to building, initializing, updating, and compiling localization translations.\n\nB"
  },
  {
    "path": "scripts/icons/convert_and_pack.sh",
    "chars": 2007,
    "preview": "#!/bin/bash\n\nif ! [ -x \"$(command -v ./go-png2ico)\" ]; then\n    echo \"./go-png2ico not found\"\n    echo \"download the exe"
  },
  {
    "path": "scripts/linux_build.sh",
    "chars": 23860,
    "preview": "#!/bin/bash\nset -e\n\n# Version requirements - centralized for easy maintenance\ncmake_min=\"3.25.0\"\ntarget_cmake_version=\"3"
  },
  {
    "path": "scripts/macos_build.sh",
    "chars": 6447,
    "preview": "#!/usr/bin/env bash\n# Note: This script is not used by CI, and is only for manually building/signing the .app.\n# Changes"
  },
  {
    "path": "scripts/update_clang_format.py",
    "chars": 731,
    "preview": "# standard imports\nimport os\nimport subprocess\n\n# variables\ndirectories = [\n    'src',\n    'tests',\n    'tools',\n]\nfile_"
  },
  {
    "path": "src/audio.cpp",
    "chars": 9143,
    "preview": "/**\n * @file src/audio.cpp\n * @brief Definitions for audio capture and encoding.\n */\n// standard includes\n#include <thre"
  },
  {
    "path": "src/audio.h",
    "chars": 2797,
    "preview": "/**\n * @file src/audio.h\n * @brief Declarations for audio capture and encoding.\n */\n#pragma once\n\n// local includes\n#inc"
  },
  {
    "path": "src/cbs.cpp",
    "chars": 7988,
    "preview": "/**\n * @file src/cbs.cpp\n * @brief Definitions for FFmpeg Coded Bitstream API.\n */\nextern \"C\" {\n// lib includes\n#include"
  },
  {
    "path": "src/cbs.h",
    "chars": 934,
    "preview": "/**\n * @file src/cbs.h\n * @brief Declarations for FFmpeg Coded Bitstream API.\n */\n#pragma once\n\n// local includes\n#inclu"
  },
  {
    "path": "src/config.cpp",
    "chars": 52460,
    "preview": "/**\n * @file src/config.cpp\n * @brief Definitions for the configuration of Sunshine.\n */\n// standard includes\n#include <"
  },
  {
    "path": "src/config.h",
    "chars": 8505,
    "preview": "/**\n * @file src/config.h\n * @brief Declarations for the configuration of Sunshine.\n */\n#pragma once\n\n// standard includ"
  },
  {
    "path": "src/confighttp.cpp",
    "chars": 61443,
    "preview": "/**\n * @file src/confighttp.cpp\n * @brief Definitions for the Web UI Config HTTP server.\n *\n * @todo Authentication, bet"
  },
  {
    "path": "src/confighttp.h",
    "chars": 3900,
    "preview": "/**\n * @file src/confighttp.h\n * @brief Declarations for the Web UI Config HTTP server.\n */\n#pragma once\n\n// standard in"
  },
  {
    "path": "src/crypto.cpp",
    "chars": 16812,
    "preview": "/**\n * @file src/crypto.cpp\n * @brief Definitions for cryptography functions.\n */\n// lib includes\n#include <openssl/pem."
  },
  {
    "path": "src/crypto.h",
    "chars": 5475,
    "preview": "/**\n * @file src/crypto.h\n * @brief Declarations for cryptography functions.\n */\n#pragma once\n\n// standard includes\n#inc"
  },
  {
    "path": "src/display_device.cpp",
    "chars": 34720,
    "preview": "/**\n * @file src/display_device.cpp\n * @brief Definitions for display device handling.\n */\n// header include\n#include \"d"
  },
  {
    "path": "src/display_device.h",
    "chars": 5800,
    "preview": "/**\n * @file src/display_device.h\n * @brief Declarations for display device handling.\n */\n#pragma once\n\n// standard incl"
  },
  {
    "path": "src/entry_handler.cpp",
    "chars": 6887,
    "preview": "/**\n * @file entry_handler.cpp\n * @brief Definitions for entry handling functions.\n */\n// standard includes\n#include <cs"
  },
  {
    "path": "src/entry_handler.h",
    "chars": 3133,
    "preview": "/**\n * @file entry_handler.h\n * @brief Declarations for entry handling functions.\n */\n#pragma once\n\n// standard includes"
  },
  {
    "path": "src/file_handler.cpp",
    "chars": 1310,
    "preview": "/**\n * @file file_handler.cpp\n * @brief Definitions for file handling functions.\n */\n\n// standard includes\n#include <fil"
  },
  {
    "path": "src/file_handler.h",
    "chars": 1460,
    "preview": "/**\n * @file file_handler.h\n * @brief Declarations for file handling functions.\n */\n#pragma once\n\n// standard includes\n#"
  },
  {
    "path": "src/globals.cpp",
    "chars": 299,
    "preview": "/**\n * @file globals.cpp\n * @brief Definitions for globally accessible variables and functions.\n */\n// local includes\n#i"
  },
  {
    "path": "src/globals.h",
    "chars": 1213,
    "preview": "/**\n * @file globals.h\n * @brief Declarations for globally accessible variables and functions.\n */\n#pragma once\n\n// loca"
  },
  {
    "path": "src/httpcommon.cpp",
    "chars": 7560,
    "preview": "/**\n * @file src/httpcommon.cpp\n * @brief Definitions for common HTTP.\n */\n#define BOOST_BIND_GLOBAL_PLACEHOLDERS\n\n// st"
  },
  {
    "path": "src/httpcommon.h",
    "chars": 815,
    "preview": "/**\n * @file src/httpcommon.h\n * @brief Declarations for common HTTP.\n */\n#pragma once\n\n// lib includes\n#include <curl/c"
  },
  {
    "path": "src/input.cpp",
    "chars": 59825,
    "preview": "/**\n * @file src/input.cpp\n * @brief Definitions for gamepad, keyboard, and mouse input handling.\n */\n#include <cstdint>"
  },
  {
    "path": "src/input.h",
    "chars": 1462,
    "preview": "/**\n * @file src/input.h\n * @brief Declarations for gamepad, keyboard, and mouse input handling.\n */\n#pragma once\n\n// st"
  },
  {
    "path": "src/logging.cpp",
    "chars": 9322,
    "preview": "/**\n * @file src/logging.cpp\n * @brief Definitions for logging related functions.\n */\n// standard includes\n#include <fst"
  },
  {
    "path": "src/logging.h",
    "chars": 6528,
    "preview": "/**\n * @file src/logging.h\n * @brief Declarations for logging related functions.\n */\n#pragma once\n\n// lib includes\n#incl"
  },
  {
    "path": "src/main.cpp",
    "chars": 13759,
    "preview": "/**\n * @file src/main.cpp\n * @brief Definitions for the main entry point for Sunshine.\n */\n// standard includes\n#include"
  },
  {
    "path": "src/main.h",
    "chars": 342,
    "preview": "/**\n * @file src/main.h\n * @brief Declarations for the main entry point for Sunshine.\n */\n#pragma once\n\n/**\n * @brief Ma"
  },
  {
    "path": "src/move_by_copy.h",
    "chars": 1381,
    "preview": "/**\n * @file src/move_by_copy.h\n * @brief Declarations for the MoveByCopy utility class.\n */\n#pragma once\n\n// standard i"
  },
  {
    "path": "src/network.cpp",
    "chars": 6260,
    "preview": "/**\n * @file src/network.cpp\n * @brief Definitions for networking related functions.\n */\n// standard includes\n#include <"
  },
  {
    "path": "src/network.h",
    "chars": 3502,
    "preview": "/**\n * @file src/network.h\n * @brief Declarations for networking related functions.\n */\n#pragma once\n\n// standard includ"
  },
  {
    "path": "src/nvenc/nvenc_base.cpp",
    "chars": 26905,
    "preview": "/**\n * @file src/nvenc/nvenc_base.cpp\n * @brief Definitions for abstract platform-agnostic base of standalone NVENC enco"
  },
  {
    "path": "src/nvenc/nvenc_base.h",
    "chars": 6311,
    "preview": "/**\n * @file src/nvenc/nvenc_base.h\n * @brief Declarations for abstract platform-agnostic base of standalone NVENC encod"
  },
  {
    "path": "src/nvenc/nvenc_colorspace.h",
    "chars": 451,
    "preview": "/**\n * @file src/nvenc/nvenc_colorspace.h\n * @brief Declarations for NVENC YUV colorspace.\n */\n#pragma once\n\n// lib incl"
  },
  {
    "path": "src/nvenc/nvenc_config.h",
    "chars": 1816,
    "preview": "/**\n * @file src/nvenc/nvenc_config.h\n * @brief Declarations for NVENC encoder configuration.\n */\n#pragma once\n\nnamespac"
  },
  {
    "path": "src/nvenc/nvenc_d3d11.cpp",
    "chars": 1859,
    "preview": "/**\n * @file src/nvenc/nvenc_d3d11.cpp\n * @brief Definitions for abstract Direct3D11 NVENC encoder.\n */\n// local include"
  },
  {
    "path": "src/nvenc/nvenc_d3d11.h",
    "chars": 1099,
    "preview": "/**\n * @file src/nvenc/nvenc_d3d11.h\n * @brief Declarations for abstract Direct3D11 NVENC encoder.\n */\n#pragma once\n#ifd"
  },
  {
    "path": "src/nvenc/nvenc_d3d11_native.cpp",
    "chars": 2405,
    "preview": "/**\n * @file src/nvenc/nvenc_d3d11_native.cpp\n * @brief Definitions for native Direct3D11 NVENC encoder.\n */\n#ifdef _WIN"
  },
  {
    "path": "src/nvenc/nvenc_d3d11_native.h",
    "chars": 789,
    "preview": "/**\n * @file src/nvenc/nvenc_d3d11_native.h\n * @brief Declarations for native Direct3D11 NVENC encoder.\n */\n#pragma once"
  }
]

// ... and 252 more files (download for full content)

About this extraction

This page contains the full source code of the LizardByte/Sunshine GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 452 files (3.7 MB), approximately 984.4k tokens, and a symbol index with 2054 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!