summaryrefslogtreecommitdiff
path: root/src/input_common/sdl/sdl_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/sdl/sdl_impl.cpp')
-rw-r--r--src/input_common/sdl/sdl_impl.cpp89
1 files changed, 45 insertions, 44 deletions
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index bd480570a..9c3035920 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -56,9 +56,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
56class SDLJoystick { 56class SDLJoystick {
57public: 57public:
58 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, 58 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
59 SDL_GameController* gamecontroller) 59 SDL_GameController* game_controller)
60 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, 60 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
61 sdl_controller{gamecontroller, &SDL_GameControllerClose} {} 61 sdl_controller{game_controller, &SDL_GameControllerClose} {}
62 62
63 void SetButton(int button, bool value) { 63 void SetButton(int button, bool value) {
64 std::lock_guard lock{mutex}; 64 std::lock_guard lock{mutex};
@@ -77,10 +77,10 @@ public:
77 77
78 float GetAxis(int axis, float range) const { 78 float GetAxis(int axis, float range) const {
79 std::lock_guard lock{mutex}; 79 std::lock_guard lock{mutex};
80 return state.axes.at(axis) / (32767.0f * range); 80 return static_cast<float>(state.axes.at(axis)) / (32767.0f * range);
81 } 81 }
82 82
83 bool RumblePlay(f32 amp_low, f32 amp_high, int time) { 83 bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) {
84 const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); 84 const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
85 const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); 85 const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
86 // Lower drastically the number of state changes 86 // Lower drastically the number of state changes
@@ -124,7 +124,7 @@ public:
124 return std::make_tuple(x, y); 124 return std::make_tuple(x, y);
125 } 125 }
126 126
127 const InputCommon::MotionInput& GetMotion() const { 127 const MotionInput& GetMotion() const {
128 return motion; 128 return motion;
129 } 129 }
130 130
@@ -172,15 +172,15 @@ private:
172 } state; 172 } state;
173 std::string guid; 173 std::string guid;
174 int port; 174 int port;
175 u16 last_state_rumble_high; 175 u16 last_state_rumble_high = 0;
176 u16 last_state_rumble_low; 176 u16 last_state_rumble_low = 0;
177 std::chrono::time_point<std::chrono::system_clock> last_vibration; 177 std::chrono::time_point<std::chrono::system_clock> last_vibration;
178 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 178 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
179 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 179 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
180 mutable std::mutex mutex; 180 mutable std::mutex mutex;
181 181
182 // motion is initalized without PID values as motion input is not aviable for SDL2 182 // Motion is initialized without PID values as motion input is not aviable for SDL2
183 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f}; 183 MotionInput motion{0.0f, 0.0f, 0.0f};
184}; 184};
185 185
186std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { 186std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
@@ -192,7 +192,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& g
192 nullptr, nullptr); 192 nullptr, nullptr);
193 it->second.emplace_back(std::move(joystick)); 193 it->second.emplace_back(std::move(joystick));
194 } 194 }
195 return it->second[port]; 195 return it->second[static_cast<std::size_t>(port)];
196 } 196 }
197 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); 197 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
198 return joystick_map[guid].emplace_back(std::move(joystick)); 198 return joystick_map[guid].emplace_back(std::move(joystick));
@@ -212,7 +212,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
212 return sdl_joystick == joystick->GetSDLJoystick(); 212 return sdl_joystick == joystick->GetSDLJoystick();
213 }); 213 });
214 if (vec_it != map_it->second.end()) { 214 if (vec_it != map_it->second.end()) {
215 // This is the common case: There is already an existing SDL_Joystick maped to a 215 // This is the common case: There is already an existing SDL_Joystick mapped to a
216 // SDLJoystick. return the SDLJoystick 216 // SDLJoystick. return the SDLJoystick
217 return *vec_it; 217 return *vec_it;
218 } 218 }
@@ -220,7 +220,7 @@ std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_
220 // Search for a SDLJoystick without a mapped SDL_Joystick... 220 // Search for a SDLJoystick without a mapped SDL_Joystick...
221 const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), 221 const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(),
222 [](const std::shared_ptr<SDLJoystick>& joystick) { 222 [](const std::shared_ptr<SDLJoystick>& joystick) {
223 return !joystick->GetSDLJoystick(); 223 return joystick->GetSDLJoystick() == nullptr;
224 }); 224 });
225 if (nullptr_it != map_it->second.end()) { 225 if (nullptr_it != map_it->second.end()) {
226 // ... and map it 226 // ... and map it
@@ -273,22 +273,19 @@ void SDLState::InitJoystick(int joystick_index) {
273void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { 273void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
274 const std::string guid = GetGUID(sdl_joystick); 274 const std::string guid = GetGUID(sdl_joystick);
275 275
276 std::shared_ptr<SDLJoystick> joystick; 276 std::lock_guard lock{joystick_map_mutex};
277 { 277 auto& joystick_guid_list = joystick_map[guid];
278 std::lock_guard lock{joystick_map_mutex}; 278 auto joystick_it = std::find_if(
279 // This call to guid is safe since the joystick is guaranteed to be in the map 279 joystick_guid_list.begin(), joystick_guid_list.end(),
280 const auto& joystick_guid_list = joystick_map[guid]; 280 [&sdl_joystick](auto& joystick) { return joystick->GetSDLJoystick() == sdl_joystick; });
281 const auto joystick_it =
282 std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
283 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
284 return joystick->GetSDLJoystick() == sdl_joystick;
285 });
286 joystick = *joystick_it;
287 }
288 281
289 // Destruct SDL_Joystick outside the lock guard because SDL can internally call the 282 if (joystick_it != joystick_guid_list.end()) {
290 // event callback which locks the mutex again. 283 (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
291 joystick->SetSDLJoystick(nullptr, nullptr); 284 joystick_guid_list.erase(joystick_it);
285 if (joystick_guid_list.empty()) {
286 joystick_map.erase(guid);
287 }
288 }
292} 289}
293 290
294void SDLState::HandleGameControllerEvent(const SDL_Event& event) { 291void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
@@ -392,8 +389,8 @@ private:
392 389
393class SDLAnalog final : public Input::AnalogDevice { 390class SDLAnalog final : public Input::AnalogDevice {
394public: 391public:
395 SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_, float deadzone_, 392 explicit SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_,
396 float range_) 393 float deadzone_, float range_)
397 : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_), 394 : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_), deadzone(deadzone_),
398 range(range_) {} 395 range(range_) {}
399 396
@@ -672,13 +669,13 @@ SDLState::SDLState() {
672 RegisterFactory<ButtonDevice>("sdl", button_factory); 669 RegisterFactory<ButtonDevice>("sdl", button_factory);
673 RegisterFactory<MotionDevice>("sdl", motion_factory); 670 RegisterFactory<MotionDevice>("sdl", motion_factory);
674 671
675 // If the frontend is going to manage the event loop, then we dont start one here 672 // If the frontend is going to manage the event loop, then we don't start one here
676 start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); 673 start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0;
677 if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { 674 if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) {
678 LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); 675 LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
679 return; 676 return;
680 } 677 }
681 has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); 678 has_gamecontroller = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) != 0;
682 if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { 679 if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) {
683 LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); 680 LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());
684 } 681 }
@@ -723,8 +720,8 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
723 std::vector<Common::ParamPackage> devices; 720 std::vector<Common::ParamPackage> devices;
724 for (const auto& [key, value] : joystick_map) { 721 for (const auto& [key, value] : joystick_map) {
725 for (const auto& joystick : value) { 722 for (const auto& joystick : value) {
726 auto joy = joystick->GetSDLJoystick(); 723 auto* joy = joystick->GetSDLJoystick();
727 if (auto controller = joystick->GetSDLGameController()) { 724 if (auto* controller = joystick->GetSDLGameController()) {
728 std::string name = 725 std::string name =
729 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); 726 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
730 devices.emplace_back(Common::ParamPackage{ 727 devices.emplace_back(Common::ParamPackage{
@@ -748,7 +745,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
748} 745}
749 746
750namespace { 747namespace {
751Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, u8 axis, 748Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
752 float value = 0.1f) { 749 float value = 0.1f) {
753 Common::ParamPackage params({{"engine", "sdl"}}); 750 Common::ParamPackage params({{"engine", "sdl"}});
754 params.Set("port", port); 751 params.Set("port", port);
@@ -764,7 +761,7 @@ Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid
764 return params; 761 return params;
765} 762}
766 763
767Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, u8 button) { 764Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, s32 button) {
768 Common::ParamPackage params({{"engine", "sdl"}}); 765 Common::ParamPackage params({{"engine", "sdl"}});
769 params.Set("port", port); 766 params.Set("port", port);
770 params.Set("guid", std::move(guid)); 767 params.Set("guid", std::move(guid));
@@ -772,7 +769,7 @@ Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid
772 return params; 769 return params;
773} 770}
774 771
775Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, u8 hat, u8 value) { 772Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, s32 value) {
776 Common::ParamPackage params({{"engine", "sdl"}}); 773 Common::ParamPackage params({{"engine", "sdl"}});
777 774
778 params.Set("port", port); 775 params.Set("port", port);
@@ -802,17 +799,19 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
802 case SDL_JOYAXISMOTION: { 799 case SDL_JOYAXISMOTION: {
803 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 800 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
804 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 801 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
805 event.jaxis.axis, event.jaxis.value); 802 static_cast<s32>(event.jaxis.axis),
803 event.jaxis.value);
806 } 804 }
807 case SDL_JOYBUTTONUP: { 805 case SDL_JOYBUTTONUP: {
808 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); 806 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
809 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 807 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
810 event.jbutton.button); 808 static_cast<s32>(event.jbutton.button));
811 } 809 }
812 case SDL_JOYHATMOTION: { 810 case SDL_JOYHATMOTION: {
813 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); 811 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
814 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 812 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
815 event.jhat.hat, event.jhat.value); 813 static_cast<s32>(event.jhat.hat),
814 static_cast<s32>(event.jhat.value));
816 } 815 }
817 } 816 }
818 return {}; 817 return {};
@@ -823,17 +822,19 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
823 case SDL_JOYAXISMOTION: { 822 case SDL_JOYAXISMOTION: {
824 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 823 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
825 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 824 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
826 event.jaxis.axis, event.jaxis.value); 825 static_cast<s32>(event.jaxis.axis),
826 event.jaxis.value);
827 } 827 }
828 case SDL_JOYBUTTONUP: { 828 case SDL_JOYBUTTONUP: {
829 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); 829 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
830 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 830 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
831 event.jbutton.button); 831 static_cast<s32>(event.jbutton.button));
832 } 832 }
833 case SDL_JOYHATMOTION: { 833 case SDL_JOYHATMOTION: {
834 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); 834 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
835 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 835 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
836 event.jhat.hat, event.jhat.value); 836 static_cast<s32>(event.jhat.hat),
837 static_cast<s32>(event.jhat.value));
837 } 838 }
838 } 839 }
839 return {}; 840 return {};
@@ -1062,7 +1063,7 @@ public:
1062 if (event.type == SDL_JOYAXISMOTION) { 1063 if (event.type == SDL_JOYAXISMOTION) {
1063 const auto axis = event.jaxis.axis; 1064 const auto axis = event.jaxis.axis;
1064 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 1065 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
1065 const auto controller = joystick->GetSDLGameController(); 1066 auto* const controller = joystick->GetSDLGameController();
1066 if (controller) { 1067 if (controller) {
1067 const auto axis_left_x = 1068 const auto axis_left_x =
1068 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) 1069 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)