diff --git a/android/app/src/cpp/android_host_interface.cpp b/android/app/src/cpp/android_host_interface.cpp index 05c768167..28d69fa20 100644 --- a/android/app/src/cpp/android_host_interface.cpp +++ b/android/app/src/cpp/android_host_interface.cpp @@ -128,9 +128,10 @@ std::unique_ptr ReadInputStreamToMemory(JNIEnv* env, j } // namespace AndroidHelpers AndroidHostInterface::AndroidHostInterface(jobject java_object, jobject context_object, std::string user_directory) - : m_java_object(java_object), m_settings_interface(context_object) + : m_java_object(java_object) { m_user_directory = std::move(user_directory); + m_settings_interface = std::make_unique(context_object); } AndroidHostInterface::~AndroidHostInterface() @@ -192,26 +193,6 @@ void AndroidHostInterface::ReportMessage(const char* message) } } -std::string AndroidHostInterface::GetStringSettingValue(const char* section, const char* key, const char* default_value) -{ - return m_settings_interface.GetStringValue(section, key, default_value); -} - -bool AndroidHostInterface::GetBoolSettingValue(const char* section, const char* key, bool default_value /* = false */) -{ - return m_settings_interface.GetBoolValue(section, key, default_value); -} - -int AndroidHostInterface::GetIntSettingValue(const char* section, const char* key, int default_value /* = 0 */) -{ - return m_settings_interface.GetIntValue(section, key, default_value); -} - -float AndroidHostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /* = 0.0f */) -{ - return m_settings_interface.GetFloatValue(section, key, default_value); -} - std::unique_ptr AndroidHostInterface::OpenPackageFile(const char* path, u32 flags) { Log_DevPrintf("OpenPackageFile(%s, %x)", path, flags); @@ -266,35 +247,33 @@ void AndroidHostInterface::SetUserDirectory() Assert(!m_user_directory.empty()); } -void AndroidHostInterface::LoadSettings() +void AndroidHostInterface::LoadSettings(SettingsInterface& si) { - LoadAndConvertSettings(); - CommonHostInterface::FixIncompatibleSettings(false); - CommonHostInterface::UpdateInputMap(m_settings_interface); -} + const GPURenderer old_renderer = g_settings.gpu_renderer; + CommonHostInterface::LoadSettings(si); -void AndroidHostInterface::LoadAndConvertSettings() -{ - CommonHostInterface::LoadSettings(m_settings_interface); - - const std::string msaa_str = m_settings_interface.GetStringValue("GPU", "MSAA", "1"); + const std::string msaa_str = si.GetStringValue("GPU", "MSAA", "1"); g_settings.gpu_multisamples = std::max(StringUtil::FromChars(msaa_str).value_or(1), 1); g_settings.gpu_per_sample_shading = StringUtil::EndsWith(msaa_str, "-ssaa"); // turn percentage into fraction for overclock const u32 overclock_percent = - static_cast(std::max(m_settings_interface.GetIntValue("CPU", "Overclock", 100), 1)); + static_cast(std::max(si.GetIntValue("CPU", "Overclock", 100), 1)); Settings::CPUOverclockPercentToFraction(overclock_percent, &g_settings.cpu_overclock_numerator, &g_settings.cpu_overclock_denominator); g_settings.cpu_overclock_enable = (overclock_percent != 100); g_settings.UpdateOverclockActive(); - m_vibration_enabled = m_settings_interface.GetBoolValue("Controller1", "Vibration", false); -} + m_vibration_enabled = si.GetBoolValue("Controller1", "Vibration", false); -void AndroidHostInterface::UpdateInputMap() -{ - CommonHostInterface::UpdateInputMap(m_settings_interface); + // Defer renderer changes, the app really doesn't like it. + if (System::IsValid() && g_settings.gpu_renderer != old_renderer) + { + AddFormattedOSDMessage(5.0f, + TranslateString("OSDMessage", "Change to %s GPU renderer will take effect on restart."), + Settings::GetRendererName(g_settings.gpu_renderer)); + g_settings.gpu_renderer = old_renderer; + } } bool AndroidHostInterface::IsEmulationThreadPaused() const @@ -755,30 +734,10 @@ void AndroidHostInterface::SetFastForwardEnabled(bool enabled) void AndroidHostInterface::RefreshGameList(bool invalidate_cache, bool invalidate_database, ProgressCallback* progress_callback) { - m_game_list->SetSearchDirectoriesFromSettings(m_settings_interface); + m_game_list->SetSearchDirectoriesFromSettings(*m_settings_interface); m_game_list->Refresh(invalidate_cache, invalidate_database, progress_callback); } -void AndroidHostInterface::ApplySettings(bool display_osd_messages) -{ - Settings old_settings = std::move(g_settings); - LoadAndConvertSettings(); - CommonHostInterface::ApplyGameSettings(display_osd_messages); - CommonHostInterface::FixIncompatibleSettings(display_osd_messages); - UpdateInputMap(); - - // Defer renderer changes, the app really doesn't like it. - if (System::IsValid() && g_settings.gpu_renderer != old_settings.gpu_renderer) - { - AddFormattedOSDMessage(5.0f, - TranslateString("OSDMessage", "Change to %s GPU renderer will take effect on restart."), - Settings::GetRendererName(g_settings.gpu_renderer)); - g_settings.gpu_renderer = old_settings.gpu_renderer; - } - - CheckForSettingsChanges(old_settings); -} - bool AndroidHostInterface::ImportPatchCodesFromString(const std::string& str) { CheatList* cl = new CheatList(); @@ -872,27 +831,6 @@ jobjectArray AndroidHostInterface::GetInputProfileNames(JNIEnv* env) const return name_array; } -bool AndroidHostInterface::ApplyInputProfile(const char* profile_name) -{ - const std::string path(GetInputProfilePath(profile_name)); - if (path.empty()) - return false; - - Assert(!IsEmulationThreadRunning() || IsEmulationThreadPaused()); - CommonHostInterface::ApplyInputProfile(path.c_str(), m_settings_interface); - ApplySettings(false); - return true; -} - -bool AndroidHostInterface::SaveInputProfile(const char* profile_name) -{ - const std::string path(GetSavePathForInputProfile(profile_name)); - if (path.empty()) - return false; - - return CommonHostInterface::SaveInputProfile(path.c_str(), m_settings_interface); -} - extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { Log::SetDebugOutputParams(true, nullptr, LOGLEVEL_DEV); diff --git a/android/app/src/cpp/android_host_interface.h b/android/app/src/cpp/android_host_interface.h index 9c32e0f36..501b17561 100644 --- a/android/app/src/cpp/android_host_interface.h +++ b/android/app/src/cpp/android_host_interface.h @@ -36,10 +36,6 @@ public: void ReportError(const char* message) override; void ReportMessage(const char* message) override; - std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") override; - bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false) override; - int GetIntSettingValue(const char* section, const char* key, int default_value = 0) override; - float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f) override; std::unique_ptr OpenPackageFile(const char* path, u32 flags) override; bool GetMainDisplayRefreshRate(float* refresh_rate) override; @@ -64,18 +60,13 @@ public: void SetFastForwardEnabled(bool enabled); void RefreshGameList(bool invalidate_cache, bool invalidate_database, ProgressCallback* progress_callback); - void ApplySettings(bool display_osd_messages) override; bool ImportPatchCodesFromString(const std::string& str); jobjectArray GetInputProfileNames(JNIEnv* env) const; - bool ApplyInputProfile(const char* profile_name); - bool SaveInputProfile(const char* profile_name); protected: void SetUserDirectory() override; - void LoadSettings() override; - void UpdateInputMap() override; void RegisterHotkeys() override; bool AcquireHostDisplay() override; @@ -94,15 +85,13 @@ private: void CreateImGuiContext(); void DestroyImGuiContext(); - void LoadAndConvertSettings(); + void LoadSettings(SettingsInterface& si) override; void SetVibration(bool enabled); void UpdateVibration(); jobject m_java_object = {}; jobject m_emulation_activity_object = {}; - AndroidSettingsInterface m_settings_interface; - ANativeWindow* m_surface = nullptr; std::mutex m_mutex; diff --git a/src/core/host_interface.h b/src/core/host_interface.h index 5bcf37da4..573a495bd 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -115,6 +115,9 @@ public: /// Returns a float setting from the configuration. virtual float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f); + /// Returns a string list from the configuration. + virtual std::vector GetSettingStringList(const char* section, const char* key) = 0; + /// Translates a string to the current language. virtual TinyString TranslateString(const char* context, const char* str) const; virtual std::string TranslateStdString(const char* context, const char* str) const; @@ -162,9 +165,6 @@ protected: /// Restores all settings to defaults. virtual void SetDefaultSettings(SettingsInterface& si); - /// Performs the initial load of settings. Should call CheckSettings() and LoadSettings(SettingsInterface&). - virtual void LoadSettings() = 0; - /// Loads settings to m_settings and any frontend-specific parameters. virtual void LoadSettings(SettingsInterface& si); diff --git a/src/duckstation-nogui/nogui_host_interface.cpp b/src/duckstation-nogui/nogui_host_interface.cpp index 944b4c22b..1727c2a7d 100644 --- a/src/duckstation-nogui/nogui_host_interface.cpp +++ b/src/duckstation-nogui/nogui_host_interface.cpp @@ -38,6 +38,9 @@ const char* NoGUIHostInterface::GetFrontendName() const bool NoGUIHostInterface::Initialize() { + SetUserDirectory(); + m_settings_interface = std::make_unique(GetSettingsFileName()); + // TODO: Make command line. m_fullscreen_ui_enabled = true; @@ -81,52 +84,6 @@ void NoGUIHostInterface::Shutdown() DestroyPlatformWindow(); } -std::string NoGUIHostInterface::GetStringSettingValue(const char* section, const char* key, - const char* default_value /*= ""*/) -{ - return m_settings_interface->GetStringValue(section, key, default_value); -} - -bool NoGUIHostInterface::GetBoolSettingValue(const char* section, const char* key, bool default_value /* = false */) -{ - return m_settings_interface->GetBoolValue(section, key, default_value); -} - -int NoGUIHostInterface::GetIntSettingValue(const char* section, const char* key, int default_value /* = 0 */) -{ - return m_settings_interface->GetIntValue(section, key, default_value); -} - -float NoGUIHostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /* = 0.0f */) -{ - return m_settings_interface->GetFloatValue(section, key, default_value); -} - -void NoGUIHostInterface::LoadSettings() -{ - m_settings_interface = std::make_unique(GetSettingsFileName()); - - if (!CommonHostInterface::CheckSettings(*m_settings_interface.get())) - AddOSDMessage("Settings version mismatch, settings have been reset to defaults.", 30.0f); - - CommonHostInterface::LoadSettings(*m_settings_interface.get()); - CommonHostInterface::FixIncompatibleSettings(false); -} - -void NoGUIHostInterface::UpdateInputMap() -{ - CommonHostInterface::UpdateInputMap(*m_settings_interface.get()); -} - -void NoGUIHostInterface::ApplySettings(bool display_osd_messages) -{ - Settings old_settings(std::move(g_settings)); - CommonHostInterface::LoadSettings(*m_settings_interface.get()); - CommonHostInterface::ApplyGameSettings(display_osd_messages); - CommonHostInterface::FixIncompatibleSettings(display_osd_messages); - CheckForSettingsChanges(old_settings); -} - void NoGUIHostInterface::CreateImGuiContext() { ImGui::CreateContext(); diff --git a/src/duckstation-nogui/nogui_host_interface.h b/src/duckstation-nogui/nogui_host_interface.h index 63185ac7b..3f6a2af68 100644 --- a/src/duckstation-nogui/nogui_host_interface.h +++ b/src/duckstation-nogui/nogui_host_interface.h @@ -29,13 +29,7 @@ public: void ReportError(const char* message) override; bool ConfirmMessage(const char* message) override; - std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") override; - bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false) override; - int GetIntSettingValue(const char* section, const char* key, int default_value = 0) override; - float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f) override; - void RunLater(std::function callback) override; - void ApplySettings(bool display_osd_messages) override; protected: enum : u32 @@ -44,13 +38,9 @@ protected: DEFAULT_WINDOW_HEIGHT = 720 }; - virtual void LoadSettings() override; - bool AcquireHostDisplay() override; void ReleaseHostDisplay() override; - void UpdateInputMap() override; - void OnSystemCreated() override; void OnSystemPaused(bool paused) override; void OnSystemDestroyed() override; @@ -70,7 +60,6 @@ protected: void CreateImGuiContext(); void RunCallbacks(); - std::unique_ptr m_settings_interface; std::deque> m_queued_callbacks; std::mutex m_queued_callbacks_lock; diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index e6363adc8..0f3487c20 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -91,6 +91,9 @@ void QtHostInterface::Shutdown() bool QtHostInterface::initializeOnThread() { + SetUserDirectory(); + m_settings_interface = std::make_unique(GetSettingsFileName()); + if (!CommonHostInterface::Initialize()) return false; @@ -183,37 +186,6 @@ bool QtHostInterface::ConfirmMessage(const char* message) return result; } -std::string QtHostInterface::GetStringSettingValue(const char* section, const char* key, - const char* default_value /*= ""*/) -{ - std::lock_guard guard(m_settings_mutex); - return m_settings_interface->GetStringValue(section, key, default_value); -} - -bool QtHostInterface::GetBoolSettingValue(const char* section, const char* key, bool default_value /* = false */) -{ - std::lock_guard guard(m_settings_mutex); - return m_settings_interface->GetBoolValue(section, key, default_value); -} - -int QtHostInterface::GetIntSettingValue(const char* section, const char* key, int default_value /* = 0 */) -{ - std::lock_guard guard(m_settings_mutex); - return m_settings_interface->GetIntValue(section, key, default_value); -} - -float QtHostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /* = 0.0f */) -{ - std::lock_guard guard(m_settings_mutex); - return m_settings_interface->GetFloatValue(section, key, default_value); -} - -std::vector QtHostInterface::GetSettingStringList(const char* section, const char* key) -{ - std::lock_guard guard(m_settings_mutex); - return m_settings_interface->GetStringList(section, key); -} - void QtHostInterface::SetBoolSettingValue(const char* section, const char* key, bool value) { std::lock_guard guard(m_settings_mutex); @@ -311,15 +283,7 @@ void QtHostInterface::applySettings(bool display_osd_messages /* = false */) void QtHostInterface::ApplySettings(bool display_osd_messages) { - Settings old_settings(std::move(g_settings)); - { - std::lock_guard guard(m_settings_mutex); - CommonHostInterface::LoadSettings(*m_settings_interface.get()); - CommonHostInterface::ApplyGameSettings(display_osd_messages); - CommonHostInterface::FixIncompatibleSettings(display_osd_messages); - } - - CheckForSettingsChanges(old_settings); + CommonHostInterface::ApplySettings(display_osd_messages); // detect when render-to-main flag changes if (!System::IsShutdown()) @@ -724,20 +688,6 @@ void QtHostInterface::OnSystemStateSaved(bool global, s32 slot) emit stateSaved(QString::fromStdString(System::GetRunningCode()), global, slot); } -void QtHostInterface::LoadSettings() -{ - m_settings_interface = std::make_unique(CommonHostInterface::GetSettingsFileName()); - - if (!CommonHostInterface::CheckSettings(*m_settings_interface.get())) - { - QTimer::singleShot(1000, - [this]() { ReportError("Settings version mismatch, settings have been reset to defaults."); }); - } - - CommonHostInterface::LoadSettings(*m_settings_interface.get()); - CommonHostInterface::FixIncompatibleSettings(false); -} - void QtHostInterface::SetDefaultSettings(SettingsInterface& si) { CommonHostInterface::SetDefaultSettings(si); @@ -751,11 +701,6 @@ void QtHostInterface::SetDefaultSettings(SettingsInterface& si) si.SetBoolValue("Main", "RenderToMainWindow", true); } -void QtHostInterface::UpdateInputMap() -{ - updateInputMap(); -} - void QtHostInterface::SetMouseMode(bool relative, bool hide_cursor) { emit mouseModeRequested(relative, hide_cursor); @@ -781,24 +726,14 @@ void QtHostInterface::applyInputProfile(const QString& profile_path) return; } - Settings old_settings(std::move(g_settings)); - { - std::lock_guard lock(m_settings_mutex); - CommonHostInterface::ApplyInputProfile(profile_path.toUtf8().data(), *m_settings_interface.get()); - CommonHostInterface::LoadSettings(*m_settings_interface.get()); - CommonHostInterface::ApplyGameSettings(false); - CommonHostInterface::FixIncompatibleSettings(false); - } - - CheckForSettingsChanges(old_settings); - + ApplyInputProfile(profile_path.toUtf8().data()); emit inputProfileLoaded(); } void QtHostInterface::saveInputProfile(const QString& profile_name) { std::lock_guard lock(m_settings_mutex); - SaveInputProfile(profile_name.toUtf8().data(), *m_settings_interface.get()); + SaveInputProfile(profile_name.toUtf8().data()); } QString QtHostInterface::getUserDirectoryRelativePath(const QString& arg) const diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index b3c5f7a81..0ef5022c1 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -57,11 +57,6 @@ public Q_SLOTS: public: /// Thread-safe settings access. - std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") override; - bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false) override; - int GetIntSettingValue(const char* section, const char* key, int default_value = 0) override; - float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f) override; - std::vector GetSettingStringList(const char* section, const char* key); void SetBoolSettingValue(const char* section, const char* key, bool value); void SetIntSettingValue(const char* section, const char* key, int value); void SetFloatSettingValue(const char* section, const char* key, float value); @@ -206,10 +201,8 @@ protected: const std::string& game_title) override; void OnSystemStateSaved(bool global, s32 slot) override; - void LoadSettings() override; - void ApplySettings(bool display_osd_messages) override; void SetDefaultSettings(SettingsInterface& si) override; - void UpdateInputMap() override; + void ApplySettings(bool display_osd_messages) override; void SetMouseMode(bool relative, bool hide_cursor) override; void RunLater(std::function func) override; @@ -264,9 +257,6 @@ private: void queueSettingsSave(); void wakeThread(); - std::unique_ptr m_settings_interface; - std::recursive_mutex m_settings_mutex; - std::unique_ptr m_translator; MainWindow* m_main_window = nullptr; diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index fb99133b7..45628a182 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -59,7 +59,6 @@ bool CommonHostInterface::Initialize() if (!HostInterface::Initialize()) return false; - SetUserDirectory(); InitializeUserDirectory(); // Change to the user directory so that all default/relative paths in the config are after this. @@ -2001,26 +2000,31 @@ std::string CommonHostInterface::GetInputProfilePath(const char* name) const return {}; } -void CommonHostInterface::ClearAllControllerBindings(SettingsInterface& si) +void CommonHostInterface::ClearAllControllerBindings() { for (u32 controller_index = 1; controller_index <= NUM_CONTROLLER_AND_CARD_PORTS; controller_index++) - si.ClearSection(TinyString::FromFormat("Controller%u", controller_index)); + m_settings_interface->ClearSection(TinyString::FromFormat("Controller%u", controller_index)); } -void CommonHostInterface::ApplyInputProfile(const char* profile_path, SettingsInterface& si) +bool CommonHostInterface::ApplyInputProfile(const char* profile_path) { - // clear bindings for all controllers - ClearAllControllerBindings(si); + if (!FileSystem::FileExists(profile_path)) + return false; INISettingsInterface profile(profile_path); + std::lock_guard guard(m_settings_mutex); + + // clear bindings for all controllers + ClearAllControllerBindings(); + for (u32 controller_index = 1; controller_index <= NUM_CONTROLLER_AND_CARD_PORTS; controller_index++) { const auto section_name = TinyString::FromFormat("Controller%u", controller_index); const std::string ctype_str = profile.GetStringValue(section_name, "Type"); if (ctype_str.empty()) { - si.SetStringValue(section_name, "Type", Settings::GetControllerTypeName(ControllerType::None)); + m_settings_interface->SetStringValue(section_name, "Type", Settings::GetControllerTypeName(ControllerType::None)); g_settings.controller_types[controller_index - 1] = ControllerType::None; continue; } @@ -2029,38 +2033,38 @@ void CommonHostInterface::ApplyInputProfile(const char* profile_path, SettingsIn if (!ctype) { Log_ErrorPrintf("Invalid controller type in profile: '%s'", ctype_str.c_str()); - return; + continue; } g_settings.controller_types[controller_index - 1] = *ctype; HostInterface::OnControllerTypeChanged(controller_index - 1); - si.SetStringValue(section_name, "Type", Settings::GetControllerTypeName(*ctype)); + m_settings_interface->SetStringValue(section_name, "Type", Settings::GetControllerTypeName(*ctype)); for (const auto& button : Controller::GetButtonNames(*ctype)) { const auto key_name = TinyString::FromFormat("Button%s", button.first.c_str()); - si.DeleteValue(section_name, key_name); + m_settings_interface->DeleteValue(section_name, key_name); const std::vector bindings = profile.GetStringList(section_name, key_name); for (const std::string& binding : bindings) - si.AddToStringList(section_name, key_name, binding.c_str()); + m_settings_interface->AddToStringList(section_name, key_name, binding.c_str()); } for (const auto& axis : Controller::GetAxisNames(*ctype)) { const auto key_name = TinyString::FromFormat("Axis%s", std::get(axis).c_str()); - si.DeleteValue(section_name, std::get(axis).c_str()); + m_settings_interface->DeleteValue(section_name, std::get(axis).c_str()); const std::vector bindings = profile.GetStringList(section_name, key_name); for (const std::string& binding : bindings) - si.AddToStringList(section_name, key_name, binding.c_str()); + m_settings_interface->AddToStringList(section_name, key_name, binding.c_str()); } - si.DeleteValue(section_name, "Rumble"); + m_settings_interface->DeleteValue(section_name, "Rumble"); if (Controller::GetVibrationMotorCount(*ctype) > 0) { const std::string rumble_value = profile.GetStringValue(section_name, "Rumble"); if (!rumble_value.empty()) - si.SetStringValue(section_name, "Rumble", rumble_value.c_str()); + m_settings_interface->SetStringValue(section_name, "Rumble", rumble_value.c_str()); } Controller::SettingList settings = Controller::GetSettings(*ctype); @@ -2068,14 +2072,16 @@ void CommonHostInterface::ApplyInputProfile(const char* profile_path, SettingsIn { const std::string value = profile.GetStringValue(section_name, ssi.key, ""); if (!value.empty()) - si.SetStringValue(section_name, ssi.key, value.c_str()); + m_settings_interface->SetStringValue(section_name, ssi.key, value.c_str()); } } ReportFormattedMessage(TranslateString("OSDMessage", "Loaded input profile from '%s'"), profile_path); + ApplySettings(false); + return true; } -bool CommonHostInterface::SaveInputProfile(const char* profile_path, SettingsInterface& si) +bool CommonHostInterface::SaveInputProfile(const char* profile_path) { if (FileSystem::FileExists(profile_path)) Log_WarningPrintf("Existing input profile at '%s' will be overwritten", profile_path); @@ -2098,7 +2104,7 @@ bool CommonHostInterface::SaveInputProfile(const char* profile_path, SettingsInt for (const auto& button : Controller::GetButtonNames(ctype)) { const auto key_name = TinyString::FromFormat("Button%s", button.first.c_str()); - const std::vector bindings = si.GetStringList(section_name, key_name); + const std::vector bindings = m_settings_interface->GetStringList(section_name, key_name); for (const std::string& binding : bindings) profile.AddToStringList(section_name, key_name, binding.c_str()); } @@ -2106,14 +2112,14 @@ bool CommonHostInterface::SaveInputProfile(const char* profile_path, SettingsInt for (const auto& axis : Controller::GetAxisNames(ctype)) { const auto key_name = TinyString::FromFormat("Axis%s", std::get(axis).c_str()); - const std::vector bindings = si.GetStringList(section_name, key_name); + const std::vector bindings = m_settings_interface->GetStringList(section_name, key_name); for (const std::string& binding : bindings) profile.AddToStringList(section_name, key_name, binding.c_str()); } if (Controller::GetVibrationMotorCount(ctype) > 0) { - const std::string rumble_value = si.GetStringValue(section_name, "Rumble"); + const std::string rumble_value = m_settings_interface->GetStringValue(section_name, "Rumble"); if (!rumble_value.empty()) profile.SetStringValue(section_name, "Rumble", rumble_value.c_str()); } @@ -2121,7 +2127,7 @@ bool CommonHostInterface::SaveInputProfile(const char* profile_path, SettingsInt Controller::SettingList settings = Controller::GetSettings(ctype); for (const SettingInfo& ssi : settings) { - const std::string value = si.GetStringValue(section_name, ssi.key, ""); + const std::string value = m_settings_interface->GetStringValue(section_name, ssi.key, ""); if (!value.empty()) profile.SetStringValue(section_name, ssi.key, value.c_str()); } @@ -2308,21 +2314,6 @@ std::string CommonHostInterface::GetMostRecentResumeSaveStatePath() const return std::move(most_recent->FileName); } -bool CommonHostInterface::CheckSettings(SettingsInterface& si) -{ - const int settings_version = si.GetIntValue("Main", "SettingsVersion", -1); - if (settings_version == SETTINGS_VERSION) - return true; - - Log_ErrorPrintf("Settings version %d does not match expected version %d, resetting", settings_version, - SETTINGS_VERSION); - - si.Clear(); - si.SetIntValue("Main", "SettingsVersion", SETTINGS_VERSION); - SetDefaultSettings(si); - return false; -} - void CommonHostInterface::SetDefaultSettings(SettingsInterface& si) { HostInterface::SetDefaultSettings(si); @@ -2361,6 +2352,30 @@ void CommonHostInterface::SetDefaultSettings(SettingsInterface& si) #endif } +void CommonHostInterface::LoadSettings() +{ + // no lock needed here since it's done on startup + Assert(m_settings_interface); + +#ifndef __ANDROID__ + // we don't check the settings version on android, because it's not using the ini yet.. + // we can re-enable this once we move it over.. eventually. + const int settings_version = m_settings_interface->GetIntValue("Main", "SettingsVersion", -1); + if (settings_version != SETTINGS_VERSION) + { + ReportFormattedError("Settings version %d does not match expected version %d, resetting", settings_version, + SETTINGS_VERSION); + + m_settings_interface->Clear(); + m_settings_interface->SetIntValue("Main", "SettingsVersion", SETTINGS_VERSION); + SetDefaultSettings(*m_settings_interface); + } +#endif + + LoadSettings(*m_settings_interface); + FixIncompatibleSettings(false); +} + void CommonHostInterface::LoadSettings(SettingsInterface& si) { HostInterface::LoadSettings(si); @@ -2375,6 +2390,25 @@ void CommonHostInterface::SaveSettings(SettingsInterface& si) HostInterface::SaveSettings(si); } +void CommonHostInterface::ApplySettings(bool display_osd_messages) +{ + Settings old_settings(std::move(g_settings)); + { + std::lock_guard guard(m_settings_mutex); + LoadSettings(*m_settings_interface.get()); + ApplyGameSettings(display_osd_messages); + FixIncompatibleSettings(display_osd_messages); + } + + CheckForSettingsChanges(old_settings); +} + +void CommonHostInterface::UpdateInputMap() +{ + std::lock_guard lock(m_settings_mutex); + UpdateInputMap(*m_settings_interface.get()); +} + void CommonHostInterface::CheckForSettingsChanges(const Settings& old_settings) { HostInterface::CheckForSettingsChanges(old_settings); @@ -2425,6 +2459,37 @@ void CommonHostInterface::CheckForSettingsChanges(const Settings& old_settings) UpdateInputMap(); } +std::string CommonHostInterface::GetStringSettingValue(const char* section, const char* key, + const char* default_value /*= ""*/) +{ + std::lock_guard guard(m_settings_mutex); + return m_settings_interface->GetStringValue(section, key, default_value); +} + +bool CommonHostInterface::GetBoolSettingValue(const char* section, const char* key, bool default_value /* = false */) +{ + std::lock_guard guard(m_settings_mutex); + return m_settings_interface->GetBoolValue(section, key, default_value); +} + +int CommonHostInterface::GetIntSettingValue(const char* section, const char* key, int default_value /* = 0 */) +{ + std::lock_guard guard(m_settings_mutex); + return m_settings_interface->GetIntValue(section, key, default_value); +} + +float CommonHostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /* = 0.0f */) +{ + std::lock_guard guard(m_settings_mutex); + return m_settings_interface->GetFloatValue(section, key, default_value); +} + +std::vector CommonHostInterface::GetSettingStringList(const char* section, const char* key) +{ + std::lock_guard guard(m_settings_mutex); + return m_settings_interface->GetStringList(section, key); +} + void CommonHostInterface::SetTimerResolutionIncreased(bool enabled) { if (m_timer_resolution_increased == enabled) diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 5dc9512aa..2d69aad05 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -105,8 +105,18 @@ public: /// Runs an event next frame as part of the event loop. virtual void RunLater(std::function func) = 0; + /// Thread-safe settings access. + std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") override; + bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false) override; + int GetIntSettingValue(const char* section, const char* key, int default_value = 0) override; + float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f) override; + std::vector GetSettingStringList(const char* section, const char* key) override; + /// Loads new settings and applies them. - virtual void ApplySettings(bool display_osd_messages) = 0; + virtual void ApplySettings(bool display_osd_messages); + + /// Reloads the input map from config. Callable from controller interface. + void UpdateInputMap(); virtual bool IsFullscreen() const; virtual bool SetFullscreen(bool enabled); @@ -118,6 +128,9 @@ public: virtual void PowerOffSystem() override; virtual void DestroySystem() override; + /// Returns the settings interface. + ALWAYS_INLINE SettingsInterface* GetSettingsInterface() const { return m_settings_interface.get(); } + /// Returns the game list. ALWAYS_INLINE GameList* GetGameList() const { return m_game_list.get(); } @@ -146,10 +159,10 @@ public: std::string GetInputProfilePath(const char* name) const; /// Applies the specified input profile. - void ApplyInputProfile(const char* profile_path, SettingsInterface& si); + bool ApplyInputProfile(const char* profile_path); /// Saves the current input configuration to the specified profile name. - bool SaveInputProfile(const char* profile_path, SettingsInterface& si); + bool SaveInputProfile(const char* profile_path); /// Loads the current emulation state from file. Specifying a slot of -1 loads the "resume" game state. bool LoadState(bool global, s32 slot); @@ -322,9 +335,6 @@ protected: InputAxisHandler handler); virtual bool AddRumbleToInputMap(const std::string& binding, u32 controller_index, u32 num_motors); - /// Reloads the input map from config. Callable from controller interface. - virtual void UpdateInputMap() = 0; - void RegisterHotkey(String category, String name, String display_name, InputButtonHandler handler); bool HandleHostKeyEvent(HostKeyCode code, bool pressed); bool HandleHostMouseEvent(HostMouseButton button, bool pressed); @@ -357,14 +367,10 @@ protected: /// Returns the path to the cheat file for the specified game title. std::string GetCheatFileName() const; - /// Ensures the settings is valid and the correct version. If not, resets to defaults. - bool CheckSettings(SettingsInterface& si); - /// Restores all settings to defaults. virtual void SetDefaultSettings(SettingsInterface& si) override; /// Loads settings to m_settings and any frontend-specific parameters. - using HostInterface::LoadSettings; virtual void LoadSettings(SettingsInterface& si) override; /// Saves current settings variables to ini. @@ -391,6 +397,8 @@ protected: void DoToggleCheats(); std::string m_settings_filename; + std::unique_ptr m_settings_interface; + std::recursive_mutex m_settings_mutex; std::unique_ptr m_game_list; @@ -425,6 +433,7 @@ protected: } m_command_line_flags = {}; private: + void LoadSettings(); void InitializeUserDirectory(); void RegisterGeneralHotkeys(); void RegisterGraphicsHotkeys(); @@ -434,7 +443,7 @@ private: void UpdateControllerInputMap(SettingsInterface& si); bool UpdateControllerInputMapFromGameSettings(); void UpdateHotkeyInputMap(SettingsInterface& si); - void ClearAllControllerBindings(SettingsInterface& si); + void ClearAllControllerBindings(); #ifdef WITH_DISCORD_PRESENCE void SetDiscordPresenceEnabled(bool enabled); diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 385e6df18..9a9e76693 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -1497,7 +1497,7 @@ void DrawSettingsWindow() return; // needs a reload... - s_host_interface->ApplyInputProfile(profiles[index].path.c_str(), *s_settings_interface); + s_host_interface->ApplyInputProfile(profiles[index].path.c_str()); s_settings_copy.Load(*s_settings_interface); s_host_interface->RunLater(SaveAndApplySettings); CloseChoiceDialog();