Skip to content

Commit 24a3dcb

Browse files
committed
InputManager: Sync effect state on connection
Fixes mic/RGB LED not synchronizing on new device connection. Apparently I forgot that it doesn't reload bindings, only when the InputSource list changes.
1 parent e373be9 commit 24a3dcb

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

src/util/input_manager.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <memory>
3030
#include <mutex>
3131
#include <sstream>
32+
#include <tuple>
3233
#include <unordered_map>
3334
#include <variant>
3435
#include <vector>
@@ -73,6 +74,16 @@ struct PadVibrationBinding
7374
Timer::Value last_update_time; ///< Last time this motor was updated.
7475
InputSource* source; ///< Input source for this motor.
7576
float last_intensity; ///< Last intensity we sent to the motor.
77+
78+
ALWAYS_INLINE static u64 PackPadAndBindIndex(u32 pad_index, u32 bind_index)
79+
{
80+
return (static_cast<u64>(pad_index) << 32) | static_cast<u64>(bind_index);
81+
}
82+
83+
ALWAYS_INLINE static std::tuple<u32, u32> UnpackPadAndBindIndex(u64 packed)
84+
{
85+
return {static_cast<u32>(packed >> 32), static_cast<u32>(packed)};
86+
}
7687
};
7788

7889
struct PadLEDBinding
@@ -132,6 +143,7 @@ static float ApplySingleBindingScale(float sensitivity, float deadzone, float va
132143
static void AddHotkeyBindings(const SettingsInterface& si);
133144
static void AddPadBindings(const SettingsInterface& si, const std::string& section, u32 pad,
134145
const Controller::ControllerInfo& cinfo);
146+
static void SynchronizePadEffectBindings(InputBindingKey key);
135147
static void UpdateContinuedVibration();
136148
static void GenerateRelativeMouseEvents();
137149

@@ -149,11 +161,6 @@ static void UpdateInputSourceState(const SettingsInterface& si, std::unique_lock
149161

150162
static const KeyCodeData* FindKeyCodeData(u32 usb_code);
151163

152-
ALWAYS_INLINE static u64 PackPadAndBindIndex(u32 pad_index, u32 bind_index)
153-
{
154-
return (static_cast<u64>(pad_index) << 32) | static_cast<u64>(bind_index);
155-
}
156-
157164
// ------------------------------------------------------------------------
158165
// Tracking host mouse movement and turning into relative events
159166
// 4 axes: pointer left/right, wheel vertical/horizontal. Last/Next/Normalized.
@@ -617,7 +624,7 @@ void InputManager::AddVibrationBinding(u32 pad_index, u32 bind_index, const Inpu
617624
InputSource* source)
618625
{
619626
s_state.pad_vibration_array.push_back(
620-
PadVibrationBinding{.pad_and_bind_index = PackPadAndBindIndex(pad_index, bind_index),
627+
PadVibrationBinding{.pad_and_bind_index = PadVibrationBinding::PackPadAndBindIndex(pad_index, bind_index),
621628
.binding = binding,
622629
.last_update_time = 0,
623630
.source = source,
@@ -1016,7 +1023,7 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string
10161023
PadVibrationBinding vib_binding;
10171024
if (ParseBindingAndGetSource(binding, &vib_binding.binding, &vib_binding.source))
10181025
{
1019-
vib_binding.pad_and_bind_index = PackPadAndBindIndex(pad_index, bi.bind_index);
1026+
vib_binding.pad_and_bind_index = PadVibrationBinding::PackPadAndBindIndex(pad_index, bi.bind_index);
10201027
vib_binding.last_update_time = 0;
10211028

10221029
// If we're reloading bindings due to e.g. device connection, sync the vibration state.
@@ -1070,6 +1077,37 @@ void InputManager::AddPadBindings(const SettingsInterface& si, const std::string
10701077
}
10711078
}
10721079

1080+
void InputManager::SynchronizePadEffectBindings(InputBindingKey key)
1081+
{
1082+
for (PadVibrationBinding& vib_binding : s_state.pad_vibration_array)
1083+
{
1084+
// only matching devices
1085+
if (vib_binding.binding.source_type != key.source_type && vib_binding.binding.source_index != key.source_index)
1086+
continue;
1087+
1088+
// need to find the max intensity for this binding, might be more than one if combined motors
1089+
float max_intensity = 0.0f;
1090+
for (PadVibrationBinding& other_vib_binding : s_state.pad_vibration_array)
1091+
{
1092+
if (vib_binding.binding == other_vib_binding.binding)
1093+
max_intensity = std::max(max_intensity, other_vib_binding.last_intensity);
1094+
}
1095+
1096+
if (max_intensity > 0.0f)
1097+
vib_binding.source->UpdateMotorState(vib_binding.binding, max_intensity);
1098+
}
1099+
1100+
for (PadLEDBinding& led_binding : s_state.pad_led_array)
1101+
{
1102+
// only matching devices
1103+
if (led_binding.binding.source_type != key.source_type && led_binding.binding.source_index != key.source_index)
1104+
continue;
1105+
1106+
// Need to pass it through unconditionally, otherwise if the LED was on it'll stay on.
1107+
led_binding.source->UpdateLEDState(led_binding.binding, led_binding.last_intensity);
1108+
}
1109+
}
1110+
10731111
// ------------------------------------------------------------------------
10741112
// Event Handling
10751113
// ------------------------------------------------------------------------
@@ -1791,6 +1829,7 @@ void InputManager::OnInputDeviceConnected(InputBindingKey key, std::string_view
17911829
std::string_view device_name)
17921830
{
17931831
INFO_LOG("Device '{}' connected: '{}'", identifier, device_name);
1832+
SynchronizePadEffectBindings(key);
17941833
Host::OnInputDeviceConnected(key, identifier, device_name);
17951834
}
17961835

@@ -1819,7 +1858,7 @@ std::unique_ptr<ForceFeedbackDevice> InputManager::CreateForceFeedbackDevice(con
18191858

18201859
void InputManager::SetPadVibrationIntensity(u32 pad_index, u32 bind_index, float intensity)
18211860
{
1822-
const u64 pad_and_bind_index = PackPadAndBindIndex(pad_index, bind_index);
1861+
const u64 pad_and_bind_index = PadVibrationBinding::PackPadAndBindIndex(pad_index, bind_index);
18231862
for (PadVibrationBinding& vib : s_state.pad_vibration_array)
18241863
{
18251864
if (vib.pad_and_bind_index == pad_and_bind_index && vib.last_intensity != intensity)

0 commit comments

Comments
 (0)