[desktop] fix audio output engine not saving (#3083)
This issue has like 15 different causes, and I'm surprised it took this long to pop up. 1. LoadString had a hack *specific* to the AudioEngine enum. Why? Solving this was easy, just use the explicit type ctor. -_- 2. The LoadString hack was abused in configure_audio.cpp to get around the canonicalization infrastructure that was explicitly put in to make this exact operation easier. Why? 3. ToString was also broken because of LoadString's garbage output. Technically it might work now, but it's better to just use the canonicalization infrastructure that was made specifically for this purpose. Also did a few tiny optimizations in config/settings cuz wynaut. Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3083 Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: Lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
f40025fd9b
commit
027085e5ba
|
|
@ -129,7 +129,7 @@ protected:
|
||||||
} 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>) {
|
||||||
return std::to_string(static_cast<u32>(value_));
|
return std::to_string(u32(value_));
|
||||||
} else {
|
} else {
|
||||||
return std::to_string(value_);
|
return std::to_string(value_);
|
||||||
}
|
}
|
||||||
|
|
@ -192,15 +192,13 @@ public:
|
||||||
if constexpr (std::is_same_v<Type, std::string>) {
|
if constexpr (std::is_same_v<Type, std::string>) {
|
||||||
this->SetValue(input);
|
this->SetValue(input);
|
||||||
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
} else if constexpr (std::is_same_v<Type, std::optional<u32>>) {
|
||||||
this->SetValue(static_cast<u32>(std::stoul(input)));
|
this->SetValue(u32(std::stoul(input)));
|
||||||
} else if constexpr (std::is_same_v<Type, bool>) {
|
} else if constexpr (std::is_same_v<Type, bool>) {
|
||||||
this->SetValue(input == "true");
|
this->SetValue(input == "true");
|
||||||
} else if constexpr (std::is_same_v<Type, float>) {
|
} else if constexpr (std::is_same_v<Type, float>) {
|
||||||
this->SetValue(std::stof(input));
|
this->SetValue(std::stof(input));
|
||||||
} else if constexpr (std::is_same_v<Type, AudioEngine>) {
|
|
||||||
this->SetValue(ToEnum<AudioEngine>(input));
|
|
||||||
} else {
|
} else {
|
||||||
this->SetValue(static_cast<Type>(std::stoll(input)));
|
this->SetValue(Type(std::stoll(input)));
|
||||||
}
|
}
|
||||||
} catch (std::invalid_argument&) {
|
} catch (std::invalid_argument&) {
|
||||||
this->SetValue(this->GetDefault());
|
this->SetValue(this->GetDefault());
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
@ -10,14 +13,14 @@
|
||||||
#include "common/settings_common.h"
|
#include "common/settings_common.h"
|
||||||
#include "common/settings_enums.h"
|
#include "common/settings_enums.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#ifdef _WIN32
|
||||||
#include "hid_core/resources/npad/npad.h"
|
#include "common/string_util.h"
|
||||||
#include "network/network.h"
|
#endif
|
||||||
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
|
||||||
#include "common/string_util.h"
|
#include "common/assert.h"
|
||||||
|
|
||||||
namespace FS = Common::FS;
|
namespace FS = Common::FS;
|
||||||
|
|
||||||
|
|
@ -145,9 +148,9 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player_prefix.empty() && Settings::IsConfiguringGlobal()) {
|
if (player_prefix.empty() && Settings::IsConfiguringGlobal()) {
|
||||||
const auto controller = static_cast<Settings::ControllerType>(
|
const auto controller = Settings::ControllerType(
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
||||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
u8(Settings::ControllerType::ProController)));
|
||||||
|
|
||||||
if (controller == Settings::ControllerType::LeftJoycon ||
|
if (controller == Settings::ControllerType::LeftJoycon ||
|
||||||
controller == Settings::ControllerType::RightJoycon) {
|
controller == Settings::ControllerType::RightJoycon) {
|
||||||
|
|
@ -162,26 +165,26 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
|
||||||
player.connected = ReadBooleanSetting(connected_key.append("connected"),
|
player.connected = ReadBooleanSetting(connected_key.append("connected"),
|
||||||
std::make_optional(player_index == 0));
|
std::make_optional(player_index == 0));
|
||||||
|
|
||||||
player.controller_type = static_cast<Settings::ControllerType>(
|
player.controller_type = Settings::ControllerType(
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
ReadIntegerSetting(std::string(player_prefix).append("type"),
|
||||||
static_cast<u8>(Settings::ControllerType::ProController)));
|
u8(Settings::ControllerType::ProController)));
|
||||||
|
|
||||||
player.vibration_enabled = ReadBooleanSetting(
|
player.vibration_enabled = ReadBooleanSetting(
|
||||||
std::string(player_prefix).append("vibration_enabled"), std::make_optional(true));
|
std::string(player_prefix).append("vibration_enabled"), std::make_optional(true));
|
||||||
|
|
||||||
player.vibration_strength = static_cast<int>(
|
player.vibration_strength =
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100));
|
int(ReadIntegerSetting(std::string(player_prefix).append("vibration_strength"), 100));
|
||||||
|
|
||||||
player.body_color_left = static_cast<u32>(ReadIntegerSetting(
|
player.body_color_left = u32(ReadIntegerSetting(
|
||||||
std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE));
|
std::string(player_prefix).append("body_color_left"), Settings::JOYCON_BODY_NEON_BLUE));
|
||||||
player.body_color_right = static_cast<u32>(ReadIntegerSetting(
|
player.body_color_right = u32(ReadIntegerSetting(
|
||||||
std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED));
|
std::string(player_prefix).append("body_color_right"), Settings::JOYCON_BODY_NEON_RED));
|
||||||
player.button_color_left = static_cast<u32>(
|
player.button_color_left =
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_left"),
|
u32(ReadIntegerSetting(std::string(player_prefix).append("button_color_left"),
|
||||||
Settings::JOYCON_BUTTONS_NEON_BLUE));
|
Settings::JOYCON_BUTTONS_NEON_BLUE));
|
||||||
player.button_color_right = static_cast<u32>(
|
player.button_color_right =
|
||||||
ReadIntegerSetting(std::string(player_prefix).append("button_color_right"),
|
u32(ReadIntegerSetting(std::string(player_prefix).append("button_color_right"),
|
||||||
Settings::JOYCON_BUTTONS_NEON_RED));
|
Settings::JOYCON_BUTTONS_NEON_RED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,11 +192,11 @@ void Config::ReadTouchscreenValues() {
|
||||||
Settings::values.touchscreen.enabled =
|
Settings::values.touchscreen.enabled =
|
||||||
ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true));
|
ReadBooleanSetting(std::string("touchscreen_enabled"), std::make_optional(true));
|
||||||
Settings::values.touchscreen.rotation_angle =
|
Settings::values.touchscreen.rotation_angle =
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_angle"), 0));
|
u32(ReadIntegerSetting(std::string("touchscreen_angle"), 0));
|
||||||
Settings::values.touchscreen.diameter_x =
|
Settings::values.touchscreen.diameter_x =
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 90));
|
u32(ReadIntegerSetting(std::string("touchscreen_diameter_x"), 90));
|
||||||
Settings::values.touchscreen.diameter_y =
|
Settings::values.touchscreen.diameter_y =
|
||||||
static_cast<u32>(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 90));
|
u32(ReadIntegerSetting(std::string("touchscreen_diameter_y"), 90));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::ReadAudioValues() {
|
void Config::ReadAudioValues() {
|
||||||
|
|
@ -275,11 +278,17 @@ void Config::ReadCoreValues() {
|
||||||
void Config::ReadDataStorageValues() {
|
void Config::ReadDataStorageValues() {
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||||
|
|
||||||
FS::SetEdenPath(FS::EdenPath::NANDDir, ReadStringSetting(std::string("nand_directory")));
|
using namespace Common::FS;
|
||||||
FS::SetEdenPath(FS::EdenPath::SDMCDir, ReadStringSetting(std::string("sdmc_directory")));
|
|
||||||
FS::SetEdenPath(FS::EdenPath::LoadDir, ReadStringSetting(std::string("load_directory")));
|
const auto setPath = [this](const EdenPath& path, const char* setting) {
|
||||||
FS::SetEdenPath(FS::EdenPath::DumpDir, ReadStringSetting(std::string("dump_directory")));
|
SetEdenPath(path, ReadStringSetting(std::string(setting)));
|
||||||
FS::SetEdenPath(FS::EdenPath::TASDir, ReadStringSetting(std::string("tas_directory")));
|
};
|
||||||
|
|
||||||
|
setPath(EdenPath::NANDDir, "nand_directory");
|
||||||
|
setPath(EdenPath::SDMCDir, "sdmc_directory");
|
||||||
|
setPath(EdenPath::LoadDir, "load_directory");
|
||||||
|
setPath(EdenPath::DumpDir, "dump_directory");
|
||||||
|
setPath(EdenPath::TASDir, "tas_directory");
|
||||||
|
|
||||||
ReadCategory(Settings::Category::DataStorage);
|
ReadCategory(Settings::Category::DataStorage);
|
||||||
|
|
||||||
|
|
@ -449,9 +458,8 @@ void Config::SavePlayerValues(const std::size_t player_index) {
|
||||||
std::make_optional(std::string("")));
|
std::make_optional(std::string("")));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteIntegerSetting(
|
WriteIntegerSetting(std::string(player_prefix).append("type"), u8(player.controller_type),
|
||||||
std::string(player_prefix).append("type"), static_cast<u8>(player.controller_type),
|
std::make_optional(u8(Settings::ControllerType::ProController)));
|
||||||
std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
|
|
||||||
|
|
||||||
if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
|
if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
|
||||||
if (global) {
|
if (global) {
|
||||||
|
|
@ -487,24 +495,24 @@ void Config::SaveTouchscreenValues() {
|
||||||
std::make_optional(true));
|
std::make_optional(true));
|
||||||
|
|
||||||
WriteIntegerSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle,
|
WriteIntegerSetting(std::string("touchscreen_angle"), touchscreen.rotation_angle,
|
||||||
std::make_optional(static_cast<u32>(0)));
|
std::make_optional(u32(0)));
|
||||||
WriteIntegerSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x,
|
WriteIntegerSetting(std::string("touchscreen_diameter_x"), touchscreen.diameter_x,
|
||||||
std::make_optional(static_cast<u32>(90)));
|
std::make_optional(u32(90)));
|
||||||
WriteIntegerSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y,
|
WriteIntegerSetting(std::string("touchscreen_diameter_y"), touchscreen.diameter_y,
|
||||||
std::make_optional(static_cast<u32>(90)));
|
std::make_optional(u32(90)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::SaveMotionTouchValues() {
|
void Config::SaveMotionTouchValues() {
|
||||||
BeginArray(std::string("touch_from_button_maps"));
|
BeginArray(std::string("touch_from_button_maps"));
|
||||||
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
|
||||||
SetArrayIndex(static_cast<int>(p));
|
SetArrayIndex(int(p));
|
||||||
WriteStringSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name,
|
WriteStringSetting(std::string("name"), Settings::values.touch_from_button_maps[p].name,
|
||||||
std::make_optional(std::string("default")));
|
std::make_optional(std::string("default")));
|
||||||
|
|
||||||
BeginArray(std::string("entries"));
|
BeginArray(std::string("entries"));
|
||||||
for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
|
for (std::size_t q = 0; q < Settings::values.touch_from_button_maps[p].buttons.size();
|
||||||
++q) {
|
++q) {
|
||||||
SetArrayIndex(static_cast<int>(q));
|
SetArrayIndex(int(q));
|
||||||
WriteStringSetting(std::string("bind"),
|
WriteStringSetting(std::string("bind"),
|
||||||
Settings::values.touch_from_button_maps[p].buttons[q]);
|
Settings::values.touch_from_button_maps[p].buttons[q]);
|
||||||
}
|
}
|
||||||
|
|
@ -578,16 +586,18 @@ void Config::SaveCoreValues() {
|
||||||
void Config::SaveDataStorageValues() {
|
void Config::SaveDataStorageValues() {
|
||||||
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
|
||||||
|
|
||||||
WriteStringSetting(std::string("nand_directory"), FS::GetEdenPathString(FS::EdenPath::NANDDir),
|
using namespace Common::FS;
|
||||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::NANDDir)));
|
|
||||||
WriteStringSetting(std::string("sdmc_directory"), FS::GetEdenPathString(FS::EdenPath::SDMCDir),
|
const auto writePath = [this](const char* setting, const EdenPath& path) {
|
||||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::SDMCDir)));
|
WriteStringSetting(std::string(setting), FS::GetEdenPathString(path),
|
||||||
WriteStringSetting(std::string("load_directory"), FS::GetEdenPathString(FS::EdenPath::LoadDir),
|
std::make_optional(FS::GetEdenPathString(path)));
|
||||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::LoadDir)));
|
};
|
||||||
WriteStringSetting(std::string("dump_directory"), FS::GetEdenPathString(FS::EdenPath::DumpDir),
|
|
||||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::DumpDir)));
|
writePath("nand_directory", EdenPath::NANDDir);
|
||||||
WriteStringSetting(std::string("tas_directory"), FS::GetEdenPathString(FS::EdenPath::TASDir),
|
writePath("sdmc_directory", EdenPath::SDMCDir);
|
||||||
std::make_optional(FS::GetEdenPathString(FS::EdenPath::TASDir)));
|
writePath("load_directory", EdenPath::LoadDir);
|
||||||
|
writePath("dump_directory", EdenPath::DumpDir);
|
||||||
|
writePath("tas_directory", EdenPath::TASDir);
|
||||||
|
|
||||||
WriteCategory(Settings::Category::DataStorage);
|
WriteCategory(Settings::Category::DataStorage);
|
||||||
|
|
||||||
|
|
@ -632,11 +642,10 @@ void Config::SaveDisabledAddOnValues() {
|
||||||
BeginArray(std::string(""));
|
BeginArray(std::string(""));
|
||||||
for (const auto& elem : Settings::values.disabled_addons) {
|
for (const auto& elem : Settings::values.disabled_addons) {
|
||||||
SetArrayIndex(i);
|
SetArrayIndex(i);
|
||||||
WriteIntegerSetting(std::string("title_id"), elem.first,
|
WriteIntegerSetting(std::string("title_id"), elem.first, std::make_optional(u64(0)));
|
||||||
std::make_optional(static_cast<u64>(0)));
|
|
||||||
BeginArray(std::string("disabled"));
|
BeginArray(std::string("disabled"));
|
||||||
for (std::size_t j = 0; j < elem.second.size(); ++j) {
|
for (std::size_t j = 0; j < elem.second.size(); ++j) {
|
||||||
SetArrayIndex(static_cast<int>(j));
|
SetArrayIndex(int(j));
|
||||||
WriteStringSetting(std::string("d"), elem.second[j],
|
WriteStringSetting(std::string("d"), elem.second[j],
|
||||||
std::make_optional(std::string("")));
|
std::make_optional(std::string("")));
|
||||||
}
|
}
|
||||||
|
|
@ -720,10 +729,10 @@ bool Config::ReadBooleanSetting(const std::string& key, const std::optional<bool
|
||||||
|
|
||||||
if (config->GetBoolValue(GetSection().c_str(),
|
if (config->GetBoolValue(GetSection().c_str(),
|
||||||
std::string(full_key).append("\\default").c_str(), false)) {
|
std::string(full_key).append("\\default").c_str(), false)) {
|
||||||
return static_cast<bool>(default_value.value());
|
return bool(default_value.value());
|
||||||
} else {
|
} else {
|
||||||
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(),
|
return config->GetBoolValue(GetSection().c_str(), full_key.c_str(),
|
||||||
static_cast<bool>(default_value.value()));
|
bool(default_value.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -926,8 +935,7 @@ void Config::ReadSettingGeneric(Settings::BasicSetting* const setting) {
|
||||||
const bool is_default =
|
const bool is_default =
|
||||||
ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true));
|
ReadBooleanSetting(std::string(key).append("\\default"), std::make_optional(true));
|
||||||
if (!is_default) {
|
if (!is_default) {
|
||||||
const std::string setting_string = ReadStringSetting(key, default_value);
|
setting->LoadString(ReadStringSetting(key, default_value));
|
||||||
setting->LoadString(setting_string);
|
|
||||||
} else {
|
} else {
|
||||||
// Empty string resets the Setting to default
|
// Empty string resets the Setting to default
|
||||||
setting->LoadString("");
|
setting->LoadString("");
|
||||||
|
|
|
||||||
|
|
@ -186,16 +186,23 @@ void ConfigureAudio::SetConfiguration() {
|
||||||
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
||||||
[[maybe_unused]] const QSignalBlocker blocker(sink_combo_box);
|
[[maybe_unused]] const QSignalBlocker blocker(sink_combo_box);
|
||||||
|
|
||||||
int new_sink_index = 0;
|
const std::string new_sink_id = []() -> const std::string {
|
||||||
const QString sink_id = QString::fromStdString(Settings::values.sink_id.ToString());
|
const Settings::AudioEngine sink_id = Settings::values.sink_id.GetValue();
|
||||||
for (int index = 0; index < sink_combo_box->count(); index++) {
|
const auto canonicalizations
|
||||||
if (sink_combo_box->itemText(index) == sink_id) {
|
= Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
|
||||||
new_sink_index = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sink_combo_box->setCurrentIndex(new_sink_index);
|
for (u32 i = 0; i < canonicalizations.size(); ++i) {
|
||||||
|
const Settings::AudioEngine value = canonicalizations[i].second;
|
||||||
|
const std::string_view key = canonicalizations[i].first;
|
||||||
|
|
||||||
|
if (sink_id == value)
|
||||||
|
return std::string(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string("null");
|
||||||
|
}();
|
||||||
|
|
||||||
|
sink_combo_box->setCurrentText(QString::fromStdString(new_sink_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetOutputDevicesFromDeviceID() {
|
void ConfigureAudio::SetOutputDevicesFromDeviceID() {
|
||||||
|
|
@ -233,8 +240,20 @@ void ConfigureAudio::ApplyConfiguration() {
|
||||||
apply_func(is_powered_on);
|
apply_func(is_powered_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::values.sink_id.LoadString(
|
const u32 new_sink_id = [this]() {
|
||||||
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
const std::string sink_id = sink_combo_box->currentText().toStdString();
|
||||||
|
const auto canonicalizations
|
||||||
|
= Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
|
||||||
|
|
||||||
|
for (u32 i = 0; i < canonicalizations.size(); ++i) {
|
||||||
|
if (sink_id == canonicalizations[i].first)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return u32(0);
|
||||||
|
}();
|
||||||
|
|
||||||
|
Settings::values.sink_id.SetValue(Settings::AudioEngine(new_sink_id));
|
||||||
Settings::values.audio_output_device_id.SetValue(
|
Settings::values.audio_output_device_id.SetValue(
|
||||||
output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString());
|
output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString());
|
||||||
Settings::values.audio_input_device_id.SetValue(
|
Settings::values.audio_input_device_id.SetValue(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue