System: Rewrite input profile hotkey priority logic

This commit is contained in:
Stenzek 2024-05-16 16:48:50 +10:00
parent 284b10f8eb
commit c53717bbe4
No known key found for this signature in database
7 changed files with 93 additions and 63 deletions

View file

@ -40,12 +40,6 @@ SettingsInterface* Host::GetSettingsInterface()
return &s_layered_settings_interface; return &s_layered_settings_interface;
} }
SettingsInterface* Host::GetSettingsInterfaceForBindings()
{
SettingsInterface* input_layer = s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_INPUT);
return input_layer ? input_layer : &s_layered_settings_interface;
}
std::string Host::GetBaseStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) std::string Host::GetBaseStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/)
{ {
std::unique_lock lock(s_settings_mutex); std::unique_lock lock(s_settings_mutex);
@ -241,15 +235,13 @@ void Host::Internal::SetBaseSettingsLayer(SettingsInterface* sif)
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif); s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_BASE, sif);
} }
void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif) void Host::Internal::SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& lock)
{ {
std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif); s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_GAME, sif);
} }
void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif) void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& lock)
{ {
std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif); s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif);
} }

View file

@ -70,10 +70,6 @@ std::vector<std::string> GetStringListSetting(const char* section, const char* k
std::unique_lock<std::mutex> GetSettingsLock(); std::unique_lock<std::mutex> GetSettingsLock();
SettingsInterface* GetSettingsInterface(); SettingsInterface* GetSettingsInterface();
/// Returns the settings interface that controller bindings should be loaded from.
/// If an input profile is being used, this will be the input layer, otherwise the layered interface.
SettingsInterface* GetSettingsInterfaceForBindings();
/// Debugger feedback. /// Debugger feedback.
void ReportDebuggerMessage(std::string_view message); void ReportDebuggerMessage(std::string_view message);
void ReportFormattedDebuggerMessage(const char* format, ...); void ReportFormattedDebuggerMessage(const char* format, ...);
@ -120,9 +116,9 @@ SettingsInterface* GetInputSettingsLayer();
void SetBaseSettingsLayer(SettingsInterface* sif); void SetBaseSettingsLayer(SettingsInterface* sif);
/// Sets the game settings layer. Called by VMManager when the game changes. /// Sets the game settings layer. Called by VMManager when the game changes.
void SetGameSettingsLayer(SettingsInterface* sif); void SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& lock);
/// Sets the input profile settings layer. Called by VMManager when the game changes. /// Sets the input profile settings layer. Called by VMManager when the game changes.
void SetInputSettingsLayer(SettingsInterface* sif); void SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& lock);
} // namespace Internal } // namespace Internal
} // namespace Host } // namespace Host

View file

@ -96,6 +96,8 @@ SystemBootParameters::~SystemBootParameters() = default;
namespace System { namespace System {
static std::optional<ExtendedSaveStateInfo> InternalGetExtendedSaveStateInfo(ByteStream* stream); static std::optional<ExtendedSaveStateInfo> InternalGetExtendedSaveStateInfo(ByteStream* stream);
static void LoadInputBindings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
static bool LoadEXE(const char* filename); static bool LoadEXE(const char* filename);
static std::string GetExecutableNameForImage(IsoReader& iso, bool strip_subdirectories); static std::string GetExecutableNameForImage(IsoReader& iso, bool strip_subdirectories);
@ -970,7 +972,7 @@ void System::LoadSettings(bool display_osd_messages)
Host::LoadSettings(si, lock); Host::LoadSettings(si, lock);
InputManager::ReloadSources(si, lock); InputManager::ReloadSources(si, lock);
InputManager::ReloadBindings(si, *Host::GetSettingsInterfaceForBindings()); LoadInputBindings(si, lock);
// apply compatibility settings // apply compatibility settings
if (g_settings.apply_compatibility_settings) if (g_settings.apply_compatibility_settings)
@ -993,6 +995,57 @@ void System::LoadSettings(bool display_osd_messages)
g_settings.FixIncompatibleSettings(display_osd_messages); g_settings.FixIncompatibleSettings(display_osd_messages);
} }
void System::ReloadInputSources()
{
std::unique_lock<std::mutex> lock = Host::GetSettingsLock();
SettingsInterface* si = Host::GetSettingsInterface();
InputManager::ReloadSources(*si, lock);
// skip loading bindings if we're not running, since it'll get done on startup anyway
if (IsValid())
LoadInputBindings(*si, lock);
}
void System::ReloadInputBindings()
{
// skip loading bindings if we're not running, since it'll get done on startup anyway
if (!IsValid())
return;
std::unique_lock<std::mutex> lock = Host::GetSettingsLock();
SettingsInterface* si = Host::GetSettingsInterface();
LoadInputBindings(*si, lock);
}
void System::LoadInputBindings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
// Hotkeys use the base configuration, except if the custom hotkeys option is enabled.
if (SettingsInterface* isi = Host::Internal::GetInputSettingsLayer())
{
const bool use_profile_hotkeys = isi->GetBoolValue("ControllerPorts", "UseProfileHotkeyBindings", false);
if (use_profile_hotkeys)
{
InputManager::ReloadBindings(si, *isi, *isi);
}
else
{
// Temporarily disable the input profile layer, so it doesn't take precedence.
Host::Internal::SetInputSettingsLayer(nullptr, lock);
InputManager::ReloadBindings(si, *isi, si);
Host::Internal::SetInputSettingsLayer(s_input_settings_interface.get(), lock);
}
}
else if (SettingsInterface* gsi = Host::Internal::GetGameSettingsLayer();
gsi && gsi->GetBoolValue("ControllerPorts", "UseGameSettingsForController", false))
{
InputManager::ReloadBindings(si, *gsi, si);
}
else
{
InputManager::ReloadBindings(si, si, si);
}
}
void System::SetDefaultSettings(SettingsInterface& si) void System::SetDefaultSettings(SettingsInterface& si)
{ {
Settings temp; Settings temp;
@ -1072,53 +1125,42 @@ bool System::UpdateGameSettingsLayer()
} }
std::string input_profile_name; std::string input_profile_name;
bool use_game_settings_for_controller = false;
if (new_interface) if (new_interface)
{ {
new_interface->GetBoolValue("ControllerPorts", "UseGameSettingsForController", &use_game_settings_for_controller); if (!new_interface->GetBoolValue("ControllerPorts", "UseGameSettingsForController", false))
if (!use_game_settings_for_controller)
new_interface->GetStringValue("ControllerPorts", "InputProfileName", &input_profile_name); new_interface->GetStringValue("ControllerPorts", "InputProfileName", &input_profile_name);
} }
if (!s_game_settings_interface && !new_interface && s_input_profile_name == input_profile_name) if (!s_game_settings_interface && !new_interface && s_input_profile_name == input_profile_name)
return false; return false;
Host::Internal::SetGameSettingsLayer(new_interface.get()); auto lock = Host::GetSettingsLock();
Host::Internal::SetGameSettingsLayer(new_interface.get(), lock);
s_game_settings_interface = std::move(new_interface); s_game_settings_interface = std::move(new_interface);
std::unique_ptr<INISettingsInterface> input_interface; std::unique_ptr<INISettingsInterface> input_interface;
if (!use_game_settings_for_controller) if (!input_profile_name.empty())
{ {
if (!input_profile_name.empty()) const std::string filename(GetInputProfilePath(input_profile_name));
if (FileSystem::FileExists(filename.c_str()))
{ {
const std::string filename(GetInputProfilePath(input_profile_name)); Log_InfoFmt("Loading input profile from '{}'...", Path::GetFileName(filename));
if (FileSystem::FileExists(filename.c_str())) input_interface = std::make_unique<INISettingsInterface>(std::move(filename));
if (!input_interface->Load())
{ {
Log_InfoPrintf("Loading input profile from '%s'...", filename.c_str()); Log_ErrorFmt("Failed to parse input profile ini '{}'", Path::GetFileName(input_interface->GetFileName()));
input_interface = std::make_unique<INISettingsInterface>(std::move(filename)); input_interface.reset();
if (!input_interface->Load())
{
Log_ErrorPrintf("Failed to parse input profile ini '%s'", input_interface->GetFileName().c_str());
input_interface.reset();
input_profile_name = {};
}
}
else
{
Log_InfoPrintf("No input profile found (tried '%s')", filename.c_str());
input_profile_name = {}; input_profile_name = {};
} }
} }
else
Host::Internal::SetInputSettingsLayer(input_interface ? input_interface.get() : {
Host::Internal::GetBaseSettingsLayer()); Log_WarningFmt("No input profile found (tried '{}')", Path::GetFileName(filename));
} input_profile_name = {};
else }
{
// using game settings for bindings too
Host::Internal::SetInputSettingsLayer(s_game_settings_interface.get());
} }
Host::Internal::SetInputSettingsLayer(input_interface.get(), lock);
s_input_settings_interface = std::move(input_interface); s_input_settings_interface = std::move(input_interface);
s_input_profile_name = std::move(input_profile_name); s_input_profile_name = std::move(input_profile_name);
return true; return true;
@ -3084,7 +3126,7 @@ void System::UpdateControllers()
std::unique_ptr<Controller> controller = Controller::Create(type, i); std::unique_ptr<Controller> controller = Controller::Create(type, i);
if (controller) if (controller)
{ {
controller->LoadSettings(*Host::GetSettingsInterfaceForBindings(), Controller::GetSettingsSection(i).c_str()); controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str());
Pad::SetController(i, std::move(controller)); Pad::SetController(i, std::move(controller));
} }
} }
@ -3099,7 +3141,7 @@ void System::UpdateControllerSettings()
{ {
Controller* controller = Pad::GetController(i); Controller* controller = Pad::GetController(i);
if (controller) if (controller)
controller->LoadSettings(*Host::GetSettingsInterfaceForBindings(), Controller::GetSettingsSection(i).c_str()); controller->LoadSettings(*Host::GetSettingsInterface(), Controller::GetSettingsSection(i).c_str());
} }
} }

View file

@ -245,6 +245,12 @@ void ApplySettings(bool display_osd_messages);
/// Reloads game specific settings, and applys any changes present. /// Reloads game specific settings, and applys any changes present.
bool ReloadGameSettings(bool display_osd_messages); bool ReloadGameSettings(bool display_osd_messages);
/// Reloads input sources.
void ReloadInputSources();
/// Reloads input bindings.
void ReloadInputBindings();
bool BootSystem(SystemBootParameters parameters, Error* error); bool BootSystem(SystemBootParameters parameters, Error* error);
void PauseSystem(bool paused); void PauseSystem(bool paused);
void ResetSystem(); void ResetSystem();

View file

@ -1030,11 +1030,7 @@ void EmuThread::reloadInputSources()
return; return;
} }
std::unique_lock<std::mutex> lock = Host::GetSettingsLock(); System::ReloadInputSources();
SettingsInterface* si = Host::GetSettingsInterface();
SettingsInterface* bindings_si = Host::GetSettingsInterfaceForBindings();
InputManager::ReloadSources(*si, lock);
InputManager::ReloadBindings(*si, *bindings_si);
} }
void EmuThread::reloadInputBindings() void EmuThread::reloadInputBindings()
@ -1045,10 +1041,7 @@ void EmuThread::reloadInputBindings()
return; return;
} }
auto lock = Host::GetSettingsLock(); System::ReloadInputBindings();
SettingsInterface* si = Host::GetSettingsInterface();
SettingsInterface* bindings_si = Host::GetSettingsInterfaceForBindings();
InputManager::ReloadBindings(*si, *bindings_si);
} }
void EmuThread::reloadInputDevices() void EmuThread::reloadInputDevices()

View file

@ -1320,9 +1320,10 @@ void InputManager::CopyConfiguration(SettingsInterface* dest_si, const SettingsI
for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++)
{ {
dest_si->CopyStringListValue(src_si, section.c_str(), fmt::format("Macro{}", i + 1).c_str()); dest_si->CopyStringListValue(src_si, section.c_str(), TinyString::from_format("Macro{}", i + 1));
dest_si->CopyStringValue(src_si, section.c_str(), fmt::format("Macro{}Binds", i + 1).c_str()); dest_si->CopyStringValue(src_si, section.c_str(), TinyString::from_format("Macro{}Binds", i + 1));
dest_si->CopyUIntValue(src_si, section.c_str(), fmt::format("Macro{}Frequency", i + 1).c_str()); dest_si->CopyUIntValue(src_si, section.c_str(), TinyString::from_format("Macro{}Frequency", i + 1));
dest_si->CopyBoolValue(src_si, section.c_str(), TinyString::from_format("Macro{}Toggle", i + 1));
} }
} }
@ -1717,7 +1718,8 @@ bool InputManager::DoEventHook(InputBindingKey key, float value)
// Binding Updater // Binding Updater
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si) void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si,
SettingsInterface& hotkey_binding_si)
{ {
PauseVibration(); PauseVibration();
@ -1730,8 +1732,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
Host::AddFixedInputBindings(binding_si); Host::AddFixedInputBindings(binding_si);
// Hotkeys use the base configuration, except if the custom hotkeys option is enabled. // Hotkeys use the base configuration, except if the custom hotkeys option is enabled.
const bool use_profile_hotkeys = si.GetBoolValue("ControllerPorts", "UseProfileHotkeyBindings", false); AddHotkeyBindings(hotkey_binding_si);
AddHotkeyBindings(use_profile_hotkeys ? binding_si : si);
// If there's an input profile, we load pad bindings from it alone, rather than // If there's an input profile, we load pad bindings from it alone, rather than
// falling back to the base configuration. // falling back to the base configuration.

View file

@ -253,7 +253,7 @@ GenericInputBindingMapping GetGenericBindingMapping(std::string_view device);
bool IsInputSourceEnabled(SettingsInterface& si, InputSourceType type); bool IsInputSourceEnabled(SettingsInterface& si, InputSourceType type);
/// Re-parses the config and registers all hotkey and pad bindings. /// Re-parses the config and registers all hotkey and pad bindings.
void ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si); void ReloadBindings(SettingsInterface& si, SettingsInterface& binding_si, SettingsInterface& hotkey_binding_si);
/// Re-parses the sources part of the config and initializes any backends. /// Re-parses the sources part of the config and initializes any backends.
void ReloadSources(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock); void ReloadSources(SettingsInterface& si, std::unique_lock<std::mutex>& settings_lock);