Files
Sunshine/src/config.h
2026-07-15 10:41:22 -04:00

402 lines
17 KiB
C++

/**
* @file src/config.h
* @brief Declarations for the configuration of Sunshine.
*/
#pragma once
// standard includes
#include <bitset>
#include <chrono>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
// local includes
#include "nvenc/nvenc_config.h"
namespace config {
// Valid range for the packetsize limit
constexpr int PACKETSIZE_MIN = 200; ///< Lowest accepted configured packet size in bytes.
constexpr int PACKETSIZE_MAX = 65535; ///< Highest accepted configured packet size in bytes.
constexpr int PACKETSIZE_SMALL = 500; ///< Conservative packet size used for low-MTU links.
constexpr int PACKETSIZE_LARGE = 1456; ///< Default large packet size that avoids common MTU fragmentation.
// track modified config options
inline std::unordered_map<std::string, std::string> modified_config_settings; ///< Configuration keys changed during the current parse or UI update.
// sensitive values that should be redacted from logging
/**
* @brief Configuration keys whose values must be hidden in logs.
*/
inline constexpr std::array redacted_config = {
"csrf_allowed_origins"
};
/**
* @brief Log configuration entries and optionally mark them for persistence.
*
* @param vars Parsed configuration entries to log.
* @param save Whether modified configuration values should be written back to disk.
*/
void log_config_settings(const std::unordered_map<std::string, std::string> &vars, bool save);
/**
* @brief Video encoder, capture, and color settings loaded from configuration.
*/
struct video_t {
// ffmpeg params
/**
* @brief Quantization parameter used by encoders where higher values trade quality for compression.
*/
int qp; // higher == more compression and less quality
int hevc_mode; ///< HEVC support mode advertised to clients.
int av1_mode; ///< AV1 support mode advertised to clients.
int min_threads; ///< Minimum number of threads or slices for CPU encoding.
struct {
std::string sw_preset;
std::string sw_tune;
std::optional<int> svtav1_preset;
} sw; ///< Software encoder options.
nvenc::nvenc_config nv; ///< NVIDIA NVENC encoder settings.
bool nv_realtime_hags; ///< Enable the NVIDIA realtime HAGS workaround.
bool nv_opengl_vulkan_on_dxgi; ///< Prefer NVIDIA OpenGL/Vulkan-on-DXGI interop.
bool nv_sunshine_high_power_mode; ///< Request NVIDIA high-power mode for Sunshine.
struct {
int preset;
int multipass;
int h264_coder;
int aq;
int vbv_percentage_increase;
} nv_legacy; ///< Legacy NVIDIA encoder options kept for config compatibility.
struct {
std::optional<int> qsv_preset;
std::optional<int> qsv_cavlc;
bool qsv_slow_hevc;
} qsv; ///< Intel Quick Sync encoder options.
struct {
std::optional<int> amd_usage_h264;
std::optional<int> amd_usage_hevc;
std::optional<int> amd_usage_av1;
std::optional<int> amd_rc_h264;
std::optional<int> amd_rc_hevc;
std::optional<int> amd_rc_av1;
std::optional<int> amd_enforce_hrd;
std::optional<int> amd_quality_h264;
std::optional<int> amd_quality_hevc;
std::optional<int> amd_quality_av1;
std::optional<int> amd_preanalysis;
std::optional<int> amd_vbaq;
int amd_coder;
} amd; ///< AMD AMF encoder options.
struct {
int vt_allow_sw;
int vt_require_sw;
int vt_realtime;
int vt_coder;
} vt; ///< VideoToolbox encoder options.
struct {
std::optional<int> blbrc;
std::optional<int> vaapi_quality;
std::optional<int> vaapi_rc;
std::string vaapi_rc_str;
bool strict_rc_buffer;
} vaapi; ///< VA-API encoder options.
struct {
int tune; // 0=default, 1=hq, 2=ll, 3=ull, 4=lossless
int rc_mode; // 0=driver, 1=cqp, 2=cbr, 4=vbr
} vk; ///< Vulkan encoder options.
std::string capture; ///< Capture backend name selected by configuration.
std::string encoder; ///< Encoder backend name selected by configuration.
std::string adapter_name; ///< Display adapter name selected in configuration.
std::string output_name; ///< Display output name selected in configuration.
/**
* @brief Display-device integration settings.
*/
struct dd_t {
/**
* @brief Compatibility workarounds for display-device control.
*/
struct workarounds_t {
std::chrono::milliseconds hdr_toggle_delay; ///< Specify whether to apply HDR high-contrast color workaround and what delay to use.
};
/**
* @brief Selects how Sunshine prepares the active display before streaming.
*/
enum class config_option_e {
disabled, ///< Disable the configuration for the device.
verify_only, ///< @seealso{display_device::SingleDisplayConfiguration::DevicePreparation}
ensure_active, ///< @seealso{display_device::SingleDisplayConfiguration::DevicePreparation}
ensure_primary, ///< @seealso{display_device::SingleDisplayConfiguration::DevicePreparation}
ensure_only_display ///< @seealso{display_device::SingleDisplayConfiguration::DevicePreparation}
};
/**
* @brief Selects how Sunshine chooses the stream display resolution.
*/
enum class resolution_option_e {
disabled, ///< Do not change resolution.
automatic, ///< Change resolution and use the one received from Moonlight.
manual ///< Change resolution and use the manually provided one.
};
/**
* @brief Selects how Sunshine chooses the stream display refresh rate.
*/
enum class refresh_rate_option_e {
disabled, ///< Do not change refresh rate.
automatic, ///< Change refresh rate and use the one received from Moonlight.
manual ///< Change refresh rate and use the manually provided one.
};
/**
* @brief Selects how Sunshine handles HDR state for the stream display.
*/
enum class hdr_option_e {
disabled, ///< Do not change HDR settings.
automatic ///< Change HDR settings and use the state requested by Moonlight.
};
/**
* @brief Single display mode remapping rule from configuration.
*/
struct mode_remapping_entry_t {
std::string requested_resolution; ///< Resolution string requested by the client.
std::string requested_fps; ///< Refresh-rate string requested by the client.
std::string final_resolution; ///< Resolution string to apply after remapping.
std::string final_refresh_rate; ///< Refresh-rate string to apply after remapping.
};
/**
* @brief Collection of display mode remapping rules.
*/
struct mode_remapping_t {
std::vector<mode_remapping_entry_t> mixed; ///< To be used when `resolution_option` and `refresh_rate_option` is set to `automatic`.
std::vector<mode_remapping_entry_t> resolution_only; ///< To be use when only `resolution_option` is set to `automatic`.
std::vector<mode_remapping_entry_t> refresh_rate_only; ///< To be use when only `refresh_rate_option` is set to `automatic`.
};
config_option_e configuration_option; ///< Display-preparation mode selected by configuration.
resolution_option_e resolution_option; ///< Resolution-selection mode selected by configuration.
std::string manual_resolution; ///< Manual resolution in case `resolution_option == resolution_option_e::manual`.
refresh_rate_option_e refresh_rate_option; ///< Refresh-rate selection mode selected by configuration.
std::string manual_refresh_rate; ///< Manual refresh rate in case `refresh_rate_option == refresh_rate_option_e::manual`.
hdr_option_e hdr_option; ///< HDR-selection mode selected by configuration.
std::chrono::milliseconds config_revert_delay; ///< Time to wait until settings are reverted (after stream ends/app exists).
bool config_revert_on_disconnect; ///< Specify whether to revert display configuration on client disconnect.
mode_remapping_t mode_remapping; ///< Display mode remapping rules grouped by automatic selection mode.
workarounds_t wa; ///< Display-device compatibility workarounds.
} dd; ///< Display-device integration settings.
int max_bitrate; ///< Maximum bitrate ceiling in kbps for bitrate requested from the client.
double minimum_fps_target; ///< Lowest framerate that will be used when streaming. Range 0-1000, 0 = half of client's requested framerate.
};
/**
* @brief Audio capture and encoder settings loaded from configuration.
*/
struct audio_t {
std::string sink; ///< Audio output device/sink to use for audio capture
std::string virtual_sink; ///< Virtual audio sink for audio routing
bool stream; ///< Enable audio streaming to clients
bool install_steam_drivers; ///< Install Steam audio drivers for enhanced compatibility
};
/**
* @brief Encryption policy that always sends unencrypted video.
*/
constexpr int ENCRYPTION_MODE_NEVER = 0; // Never use video encryption, even if the client supports it
/**
* @brief Encryption policy that uses encrypted video only when the client supports it.
*/
constexpr int ENCRYPTION_MODE_OPPORTUNISTIC = 1; // Use video encryption if available, but stream without it if not supported
/**
* @brief Encryption policy that rejects clients without video encryption support.
*/
constexpr int ENCRYPTION_MODE_MANDATORY = 2; // Always use video encryption and refuse clients that can't encrypt
/**
* @brief Network stream settings shared by audio, video, and control channels.
*/
struct stream_t {
std::chrono::milliseconds ping_timeout; ///< Timeout used when waiting for client ping responses.
std::string file_apps; ///< Path to the configured applications file.
int fec_percentage; ///< Percentage of forward-error-correction packets to add to the stream.
// Video encryption settings for LAN and WAN streams
int lan_encryption_mode; ///< Video encryption policy for LAN clients.
int wan_encryption_mode; ///< Video encryption policy for WAN clients.
// Limit the packetsize to avoid fragmentation on a low MTU link
int packetsize; ///< Maximum payload size for network packets.
};
/**
* @brief HTTP and HTTPS settings used by the GameStream pairing server.
*/
struct nvhttp_t {
// Could be any of the following values:
// pc|lan|wan
std::string origin_web_ui_allowed; ///< Origin policy used for Web UI access checks.
std::string pkey; ///< Private key PEM string or path.
std::string cert; ///< Certificate PEM string or path.
std::string sunshine_name; ///< Host name advertised to Moonlight clients.
std::string file_state; ///< Path to the persisted Sunshine state file.
std::string external_ip; ///< External address advertised to clients when configured.
};
/**
* @brief Input emulation settings loaded from configuration.
*/
struct input_t {
std::unordered_map<int, int> keybindings; ///< Client keycode to platform keycode bindings.
std::chrono::milliseconds back_button_timeout; ///< Hold duration that turns a controller Back button into a special action.
std::chrono::milliseconds key_repeat_delay; ///< Delay before repeating a held keyboard key.
std::chrono::duration<double> key_repeat_period; ///< Interval between repeated keyboard key events.
std::string gamepad; ///< Virtual controller backend selected by configuration.
bool ds4_back_as_touchpad_click; ///< Map the DS4 Back button to a touchpad click.
bool motion_as_ds4; ///< Expose motion controls through the DS4 protocol.
bool touchpad_as_ds4; ///< Expose touchpad input through the DS4 protocol.
bool ds5_inputtino_randomize_mac; ///< Randomize the inputtino DualSense MAC address.
bool keyboard; ///< Enable keyboard input from clients.
bool key_rightalt_to_key_win; ///< Map the client Right Alt key to the Windows key.
bool mouse; ///< Enable mouse input from clients.
bool controller; ///< Enable controller input from clients.
bool always_send_scancodes; ///< Always send keyboard scancodes when available.
bool high_resolution_scrolling; ///< Enable high-resolution mouse-wheel events.
bool native_pen_touch; ///< Enable native pen and touch injection.
};
namespace flag {
/**
* @brief Enumerates supported flag options.
*/
enum flag_e : std::size_t {
PIN_STDIN = 0, ///< Read PIN from stdin instead of http
FRESH_STATE, ///< Do not load or save state
FORCE_VIDEO_HEADER_REPLACE, ///< force replacing headers inside video data
UPNP, ///< Try Universal Plug 'n Play
CONST_PIN, ///< Use "universal" pin
FLAG_SIZE ///< Number of flags
};
} // namespace flag
/**
* @brief External preparation command plus its privilege requirement.
*/
struct prep_cmd_t {
/**
* @brief Build a preparation command entry from parsed configuration data.
*
* @param do_cmd Command to run before the application starts.
* @param undo_cmd Command to run after the application exits.
* @param elevated Whether the command should run with elevated privileges.
*/
prep_cmd_t(std::string &&do_cmd, std::string &&undo_cmd, bool &&elevated):
do_cmd(std::move(do_cmd)),
undo_cmd(std::move(undo_cmd)),
elevated(std::move(elevated)) {
}
/**
* @brief Build a preparation command entry from parsed configuration data.
*
* @param do_cmd Command to run before the application starts.
* @param elevated Whether the command should run with elevated privileges.
*/
explicit prep_cmd_t(std::string &&do_cmd, bool &&elevated):
do_cmd(std::move(do_cmd)),
elevated(std::move(elevated)) {
}
std::string do_cmd; ///< Command to run before the application starts.
std::string undo_cmd; ///< Command to run after the application exits.
bool elevated; ///< Whether the process should be launched elevated.
};
/**
* @brief Top-level Sunshine configuration and credential state.
*/
struct sunshine_t {
std::string locale; ///< Locale selected for Sunshine UI and log messages.
int min_log_level; ///< Minimum severity level written to the configured log sink.
std::bitset<flag::FLAG_SIZE> flags; ///< Runtime flags parsed from command-line options.
std::string credentials_file; ///< Path to the stored pairing credentials file.
std::string username; ///< Username for the local Web UI account.
std::string password; ///< Password hash or secret for the local Web UI account.
std::string salt; ///< Salt used when hashing the Web UI password.
std::string config_file; ///< Path to the active Sunshine configuration file.
/**
* @brief Command-line options parsed before configuration loading.
*/
struct cmd_t {
std::string name; ///< Executable name from the command line.
int argc; ///< Number of command-line arguments.
char **argv; ///< Command-line argument vector.
} cmd; ///< Command line used to launch the application.
std::uint16_t port; ///< TCP port used by Sunshine services.
std::string address_family; ///< Address family requested for listening sockets.
std::string bind_address; ///< Local address Sunshine should bind to.
std::string log_file; ///< Path to the configured log file.
bool notify_pre_releases; ///< Notify users about pre-release updates.
bool system_tray; ///< Enable the system tray integration.
std::vector<prep_cmd_t> prep_cmds; ///< Preparation commands executed around application launch.
// List of allowed origins for CSRF protection (e.g., "https://example.com,https://app.example.com")
// Comma-separated list of additional origins. Default includes localhost variants and web UI port.
std::vector<std::string> csrf_allowed_origins; ///< Additional origins allowed by CSRF validation.
};
extern video_t video;
extern audio_t audio;
extern stream_t stream;
extern nvhttp_t nvhttp;
extern input_t input;
extern sunshine_t sunshine;
/**
* @brief Parse serialized text into the corresponding runtime representation.
*
* @param argc Number of command-line arguments.
* @param argv Command-line argument vector.
* @return 0 on success; nonzero when command-line or configuration parsing fails.
*/
int parse(int argc, char *argv[]);
/**
* @brief Parse Sunshine configuration text into key-value entries.
*
* @param file_content Raw configuration file contents to parse.
* @return Parsed configuration key-value entries.
*/
std::unordered_map<std::string, std::string> parse_config(const std::string_view &file_content);
} // namespace config