[common] No need to specify min/max for settings; fix crash when OOB value is given for some settings (#2609)

This fixes issues when migrating settings that refer to invalid filters/scales. For example if we had 5 filters, but we set filter=6, the program would crash.
This also makes so specifying min/max manually isn't needed (but can still be set for cases like NCE).

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2609
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2025-09-29 18:40:29 +02:00
committed by crueter
parent d19a7c3782
commit bf302d7917
4 changed files with 84 additions and 150 deletions

View File

@@ -178,7 +178,7 @@ struct Values {
SwitchableSetting<std::string> audio_input_device_id{ SwitchableSetting<std::string> audio_input_device_id{
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
SwitchableSetting<AudioMode, true> sound_index{ SwitchableSetting<AudioMode, true> sound_index{
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, linkage, AudioMode::Stereo,
"sound_index", Category::SystemAudio, Specialization::Default, true, "sound_index", Category::SystemAudio, Specialization::Default, true,
true}; true};
SwitchableSetting<u8, true> volume{linkage, SwitchableSetting<u8, true> volume{linkage,
@@ -199,8 +199,6 @@ struct Values {
SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core}; SwitchableSetting<bool> use_multi_core{linkage, true, "use_multi_core", Category::Core};
SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage, SwitchableSetting<MemoryLayout, true> memory_layout_mode{linkage,
MemoryLayout::Memory_4Gb, MemoryLayout::Memory_4Gb,
MemoryLayout::Memory_4Gb,
MemoryLayout::Memory_12Gb,
"memory_layout_mode", "memory_layout_mode",
Category::Core, Category::Core,
Specialization::Default, Specialization::Default,
@@ -240,9 +238,8 @@ struct Values {
#endif #endif
"cpu_backend", "cpu_backend",
Category::Cpu}; Category::Cpu};
SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto, SwitchableSetting<CpuAccuracy, true> cpu_accuracy{linkage, CpuAccuracy::Auto,
CpuAccuracy::Auto, CpuAccuracy::Paranoid, "cpu_accuracy", Category::Cpu};
"cpu_accuracy", Category::Cpu};
SwitchableSetting<bool> use_fast_cpu_time{linkage, SwitchableSetting<bool> use_fast_cpu_time{linkage,
false, false,
@@ -324,10 +321,10 @@ struct Values {
// Renderer // Renderer
SwitchableSetting<RendererBackend, true> renderer_backend{ SwitchableSetting<RendererBackend, true> renderer_backend{
linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, linkage, RendererBackend::Vulkan,
"backend", Category::Renderer}; "backend", Category::Renderer};
SwitchableSetting<ShaderBackend, true> shader_backend{ SwitchableSetting<ShaderBackend, true> shader_backend{
linkage, ShaderBackend::SpirV, ShaderBackend::Glsl, ShaderBackend::SpirV, linkage, ShaderBackend::SpirV,
"shader_backend", Category::Renderer, Specialization::RuntimeList}; "shader_backend", Category::Renderer, Specialization::RuntimeList};
SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, SwitchableSetting<int> vulkan_device{linkage, 0, "vulkan_device", Category::Renderer,
Specialization::RuntimeList}; Specialization::RuntimeList};
@@ -342,8 +339,6 @@ struct Values {
Category::Renderer}; Category::Renderer};
SwitchableSetting<SpirvOptimizeMode, true> optimize_spirv_output{linkage, SwitchableSetting<SpirvOptimizeMode, true> optimize_spirv_output{linkage,
SpirvOptimizeMode::Never, SpirvOptimizeMode::Never,
SpirvOptimizeMode::Never,
SpirvOptimizeMode::Always,
"optimize_spirv_output", "optimize_spirv_output",
Category::Renderer}; Category::Renderer};
SwitchableSetting<bool> use_asynchronous_gpu_emulation{ SwitchableSetting<bool> use_asynchronous_gpu_emulation{
@@ -354,12 +349,10 @@ struct Values {
#else #else
AstcDecodeMode::Gpu, AstcDecodeMode::Gpu,
#endif #endif
AstcDecodeMode::Cpu,
AstcDecodeMode::CpuAsynchronous,
"accelerate_astc", "accelerate_astc",
Category::Renderer}; Category::Renderer};
SwitchableSetting<VSyncMode, true> vsync_mode{ SwitchableSetting<VSyncMode, true> vsync_mode{
linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed, linkage, VSyncMode::Fifo,
"use_vsync", Category::Renderer, Specialization::RuntimeList, true, "use_vsync", Category::Renderer, Specialization::RuntimeList, true,
true}; true};
SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu, SwitchableSetting<NvdecEmulation> nvdec_emulation{linkage, NvdecEmulation::Gpu,
@@ -372,8 +365,6 @@ struct Values {
#else #else
FullscreenMode::Exclusive, FullscreenMode::Exclusive,
#endif #endif
FullscreenMode::Borderless,
FullscreenMode::Exclusive,
"fullscreen_mode", "fullscreen_mode",
Category::Renderer, Category::Renderer,
Specialization::Default, Specialization::Default,
@@ -381,8 +372,6 @@ struct Values {
true}; true};
SwitchableSetting<AspectRatio, true> aspect_ratio{linkage, SwitchableSetting<AspectRatio, true> aspect_ratio{linkage,
AspectRatio::R16_9, AspectRatio::R16_9,
AspectRatio::R16_9,
AspectRatio::Stretch,
"aspect_ratio", "aspect_ratio",
Category::Renderer, Category::Renderer,
Specialization::Default, Specialization::Default,
@@ -430,8 +419,6 @@ struct Values {
#else #else
GpuAccuracy::High, GpuAccuracy::High,
#endif #endif
GpuAccuracy::Normal,
GpuAccuracy::Extreme,
"gpu_accuracy", "gpu_accuracy",
Category::RendererAdvanced, Category::RendererAdvanced,
Specialization::Default, Specialization::Default,
@@ -442,8 +429,6 @@ struct Values {
SwitchableSetting<DmaAccuracy, true> dma_accuracy{linkage, SwitchableSetting<DmaAccuracy, true> dma_accuracy{linkage,
DmaAccuracy::Default, DmaAccuracy::Default,
DmaAccuracy::Default,
DmaAccuracy::Safe,
"dma_accuracy", "dma_accuracy",
Category::RendererAdvanced, Category::RendererAdvanced,
Specialization::Default, Specialization::Default,
@@ -456,20 +441,14 @@ struct Values {
#else #else
AnisotropyMode::Automatic, AnisotropyMode::Automatic,
#endif #endif
AnisotropyMode::Automatic,
AnisotropyMode::X16,
"max_anisotropy", "max_anisotropy",
Category::RendererAdvanced}; Category::RendererAdvanced};
SwitchableSetting<AstcRecompression, true> astc_recompression{linkage, SwitchableSetting<AstcRecompression, true> astc_recompression{linkage,
AstcRecompression::Uncompressed, AstcRecompression::Uncompressed,
AstcRecompression::Uncompressed,
AstcRecompression::Bc3,
"astc_recompression", "astc_recompression",
Category::RendererAdvanced}; Category::RendererAdvanced};
SwitchableSetting<VramUsageMode, true> vram_usage_mode{linkage, SwitchableSetting<VramUsageMode, true> vram_usage_mode{linkage,
VramUsageMode::Conservative, VramUsageMode::Conservative,
VramUsageMode::Conservative,
VramUsageMode::Aggressive,
"vram_usage_mode", "vram_usage_mode",
Category::RendererAdvanced}; Category::RendererAdvanced};
SwitchableSetting<bool> skip_cpu_inner_invalidation{linkage, SwitchableSetting<bool> skip_cpu_inner_invalidation{linkage,
@@ -595,14 +574,10 @@ struct Values {
// System // System
SwitchableSetting<Language, true> language_index{linkage, SwitchableSetting<Language, true> language_index{linkage,
Language::EnglishAmerican, Language::EnglishAmerican,
Language::Japanese,
Language::Serbian,
"language_index", "language_index",
Category::System}; Category::System};
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, Region::Japan, SwitchableSetting<Region, true> region_index{linkage, Region::Usa, "region_index", Category::System};
Region::Taiwan, "region_index", Category::System}; SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
TimeZone::Auto, TimeZone::Zulu,
"time_zone_index", Category::System}; "time_zone_index", Category::System};
// Measured in seconds since epoch // Measured in seconds since epoch
SwitchableSetting<bool> custom_rtc_enabled{ SwitchableSetting<bool> custom_rtc_enabled{

View File

@@ -10,6 +10,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <string_view>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@@ -18,8 +19,10 @@ namespace Settings {
template <typename T> template <typename T>
struct EnumMetadata { struct EnumMetadata {
static std::vector<std::pair<std::string, T>> Canonicalizations(); static std::vector<std::pair<std::string_view, T>> Canonicalizations();
static u32 Index(); static u32 Index();
static constexpr T GetFirst();
static constexpr T GetLast();
}; };
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
@@ -69,138 +72,101 @@ struct EnumMetadata {
#define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__)) #define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__))
#define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__)) #define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__))
#define ENUM(NAME, ...) \ #define PP_HEAD(A, ...) A
enum class NAME : u32 { __VA_ARGS__ }; \
template <> \ #define ENUM(NAME, ...) \
inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ enum class NAME : u32 { __VA_ARGS__ }; \
return {PAIR(NAME, __VA_ARGS__)}; \ template<> inline std::vector<std::pair<std::string_view, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
} \ return {PAIR(NAME, __VA_ARGS__)}; \
template <> \ } \
inline u32 EnumMetadata<NAME>::Index() { \ template<> inline u32 EnumMetadata<NAME>::Index() { \
return __COUNTER__; \ return __COUNTER__; \
} \
template<> inline constexpr NAME EnumMetadata<NAME>::GetFirst() { \
return NAME::PP_HEAD(__VA_ARGS__); \
} \
template<> inline constexpr NAME EnumMetadata<NAME>::GetLast() { \
return (std::vector<std::pair<std::string_view, NAME>>{PAIR(NAME, __VA_ARGS__)}).back().second; \
} }
// AudioEngine must be specified discretely due to having existing but slightly different // AudioEngine must be specified discretely due to having existing but slightly different
// canonicalizations // canonicalizations
// TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id
enum class AudioEngine : u32 { enum class AudioEngine : u32 { Auto, Cubeb, Sdl2, Null, Oboe, };
Auto, template<>
Cubeb, inline std::vector<std::pair<std::string_view, AudioEngine>> EnumMetadata<AudioEngine>::Canonicalizations() {
Sdl2,
Null,
Oboe,
};
template <>
inline std::vector<std::pair<std::string, AudioEngine>>
EnumMetadata<AudioEngine>::Canonicalizations() {
return { return {
{"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2}, {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2},
{"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe},
}; };
} }
/// @brief This is just a sufficiently large number that is more than the number of other enums declared here
template <> template<>
inline u32 EnumMetadata<AudioEngine>::Index() { inline u32 EnumMetadata<AudioEngine>::Index() {
// This is just a sufficiently large number that is more than the number of other enums declared
// here
return 100; return 100;
} }
template<>
inline constexpr AudioEngine EnumMetadata<AudioEngine>::GetFirst() {
return AudioEngine::Auto;
}
template<>
inline constexpr AudioEngine EnumMetadata<AudioEngine>::GetLast() {
return AudioEngine::Oboe;
}
ENUM(AudioMode, Mono, Stereo, Surround); ENUM(AudioMode, Mono, Stereo, Surround);
static_assert(EnumMetadata<AudioMode>::GetFirst() == AudioMode::Mono);
static_assert(EnumMetadata<AudioMode>::GetLast() == AudioMode::Surround);
ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch, ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch,
Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin, Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin,
ChineseSimplified, ChineseTraditional, PortugueseBrazilian, Serbian); ChineseSimplified, ChineseTraditional, PortugueseBrazilian, Serbian);
ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan); ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan);
ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt, ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt,
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16); ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16);
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous); ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3); ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed); ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
ENUM(VramUsageMode, Conservative, Aggressive); ENUM(VramUsageMode, Conservative, Aggressive);
ENUM(RendererBackend, OpenGL, Vulkan, Null); ENUM(RendererBackend, OpenGL, Vulkan, Null);
ENUM(ShaderBackend, Glsl, Glasm, SpirV); ENUM(ShaderBackend, Glsl, Glasm, SpirV);
ENUM(GpuAccuracy, Normal, High, Extreme); ENUM(GpuAccuracy, Normal, High, Extreme);
ENUM(DmaAccuracy, Default, Unsafe, Safe); ENUM(DmaAccuracy, Default, Unsafe, Safe);
ENUM(CpuBackend, Dynarmic, Nce); ENUM(CpuBackend, Dynarmic, Nce);
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid);
ENUM(CpuClock, Boost, Fast) ENUM(CpuClock, Boost, Fast)
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb); ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb);
ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);
ENUM(FullscreenMode, Borderless, Exclusive); ENUM(FullscreenMode, Borderless, Exclusive);
ENUM(NvdecEmulation, Off, Cpu, Gpu); ENUM(NvdecEmulation, Off, Cpu, Gpu);
ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X);
ENUM(ResolutionSetup,
Res1_4X,
Res1_2X,
Res3_4X,
Res1X,
Res3_2X,
Res2X,
Res3X,
Res4X,
Res5X,
Res6X,
Res7X,
Res8X);
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Spline1, Gaussian, Lanczos, ScaleForce, Fsr, Area, MaxEnum); ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Spline1, Gaussian, Lanczos, ScaleForce, Fsr, Area, MaxEnum);
ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum);
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
ENUM(ConsoleMode, Handheld, Docked); ENUM(ConsoleMode, Handheld, Docked);
ENUM(AppletMode, HLE, LLE); ENUM(AppletMode, HLE, LLE);
ENUM(SpirvOptimizeMode, Never, OnLoad, Always); ENUM(SpirvOptimizeMode, Never, OnLoad, Always);
ENUM(GpuOverclock, Low, Medium, High) ENUM(GpuOverclock, Low, Medium, High)
ENUM(TemperatureUnits, Celsius, Fahrenheit) ENUM(TemperatureUnits, Celsius, Fahrenheit)
template <typename Type> template <typename Type>
inline std::string CanonicalizeEnum(Type id) { inline std::string_view CanonicalizeEnum(Type id) {
const auto group = EnumMetadata<Type>::Canonicalizations(); const auto group = EnumMetadata<Type>::Canonicalizations();
for (auto& [name, value] : group) { for (auto& [name, value] : group)
if (value == id) { if (value == id)
return name; return name;
}
}
return "unknown"; return "unknown";
} }
template <typename Type> template <typename Type>
inline Type ToEnum(const std::string& canonicalization) { inline Type ToEnum(const std::string& canonicalization) {
const auto group = EnumMetadata<Type>::Canonicalizations(); const auto group = EnumMetadata<Type>::Canonicalizations();
for (auto& [name, value] : group) { for (auto& [name, value] : group)
if (name == canonicalization) { if (name == canonicalization)
return value; return value;
}
}
return {}; return {};
} }
} // namespace Settings } // namespace Settings

View File

@@ -72,10 +72,17 @@ public:
u32 specialization_ = Specialization::Default, bool save_ = true, u32 specialization_ = Specialization::Default, bool save_ = true,
bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr)
requires(ranged) requires(ranged)
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_),
other_setting_),
value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {} value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {}
explicit Setting(Linkage& linkage, const Type& default_val,
const std::string& name, Category category_,
u32 specialization_ = Specialization::Default, bool save_ = true,
bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr)
requires(ranged && std::is_enum_v<Type>)
: BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_),
value{default_val}, default_value{default_val}, maximum{EnumMetadata<Type>::GetLast()}, minimum{EnumMetadata<Type>::GetFirst()} {}
/** /**
* Returns a reference to the setting's value. * Returns a reference to the setting's value.
* *
@@ -119,9 +126,6 @@ protected:
return value_.has_value() ? std::to_string(*value_) : "none"; return value_.has_value() ? std::to_string(*value_) : "none";
} else if constexpr (std::is_same_v<Type, bool>) { } else if constexpr (std::is_same_v<Type, bool>) {
return value_ ? "true" : "false"; return value_ ? "true" : "false";
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
// Compatibility with old AudioEngine setting being a string
return CanonicalizeEnum(value_);
} else if constexpr (std::is_floating_point_v<Type>) { } else if constexpr (std::is_floating_point_v<Type>) {
return fmt::format("{:f}", value_); return fmt::format("{:f}", value_);
} else if constexpr (std::is_enum_v<Type>) { } else if constexpr (std::is_enum_v<Type>) {
@@ -207,7 +211,7 @@ public:
[[nodiscard]] std::string Canonicalize() const override final { [[nodiscard]] std::string Canonicalize() const override final {
if constexpr (std::is_enum_v<Type>) { if constexpr (std::is_enum_v<Type>) {
return CanonicalizeEnum(this->GetValue()); return std::string{CanonicalizeEnum(this->GetValue())};
} else { } else {
return ToString(this->GetValue()); return ToString(this->GetValue());
} }
@@ -288,41 +292,32 @@ public:
* @param other_setting_ A second Setting to associate to this one in metadata * @param other_setting_ A second Setting to associate to this one in metadata
*/ */
template <typename T = BasicSetting> template <typename T = BasicSetting>
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(!ranged)
Category category_, u32 specialization_ = Specialization::Default, : Setting<Type, false>{ linkage, default_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} {
bool save_ = true, bool runtime_modifiable_ = false,
typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr)
: Setting<Type, false>{
linkage, default_val, name, category_, specialization_,
save_, runtime_modifiable_, other_setting_} {
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
} }
virtual ~SwitchableSetting() = default; virtual ~SwitchableSetting() = default;
/** /// @brief Sets a default value, minimum value, maximum value, and label.
* Sets a default value, minimum value, maximum value, and label. /// @param linkage Setting registry
* /// @param default_val Initial value of the setting, and default value of the setting
* @param linkage Setting registry /// @param min_val Sets the minimum allowed value of the setting
* @param default_val Initial value of the setting, and default value of the setting /// @param max_val Sets the maximum allowed value of the setting
* @param min_val Sets the minimum allowed value of the setting /// @param name Label for the setting
* @param max_val Sets the maximum allowed value of the setting /// @param category_ Category of the setting AKA INI group
* @param name Label for the setting /// @param specialization_ Suggestion for how frontend implementations represent this in a config
* @param category_ Category of the setting AKA INI group /// @param save_ Suggests that this should or should not be saved to a frontend config file
* @param specialization_ Suggestion for how frontend implementations represent this in a config /// @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
* @param save_ Suggests that this should or should not be saved to a frontend config file /// @param other_setting_ A second Setting to associate to this one in metadata
* @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded
* @param other_setting_ A second Setting to associate to this one in metadata
*/
template <typename T = BasicSetting> template <typename T = BasicSetting>
explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, const Type& max_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged)
const Type& max_val, const std::string& name, Category category_, : Setting<Type, true>{linkage, default_val, min_val, max_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} {
u32 specialization_ = Specialization::Default, bool save_ = true, linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
bool runtime_modifiable_ = false, }
typename std::enable_if<ranged, T*>::type other_setting_ = nullptr)
: Setting<Type, true>{linkage, default_val, min_val, template <typename T = BasicSetting>
max_val, name, category_, explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged)
specialization_, save_, runtime_modifiable_, : Setting<Type, true>{linkage, default_val, EnumMetadata<Type>::GetFirst(), EnumMetadata<Type>::GetLast(), name, category_, specialization_, save_, runtime_modifiable_, other_setting_} {
other_setting_} {
linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
} }

View File

@@ -270,10 +270,8 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) {
void ConfigureAudio::InitializeAudioSinkComboBox() { void ConfigureAudio::InitializeAudioSinkComboBox() {
sink_combo_box->clear(); sink_combo_box->clear();
sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
for (const auto& id : AudioCore::Sink::GetSinkIDs())
for (const auto& id : AudioCore::Sink::GetSinkIDs()) { sink_combo_box->addItem(QString::fromStdString(std::string{Settings::CanonicalizeEnum(id)}));
sink_combo_box->addItem(QString::fromStdString(Settings::CanonicalizeEnum(id)));
}
} }
void ConfigureAudio::RetranslateUI() { void ConfigureAudio::RetranslateUI() {