Merge pull request #2541 from lioncash/input
input_common/sdl/sdl_impl: Minor cleanup
This commit is contained in:
		| @@ -6,15 +6,8 @@ | ||||
|  | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include "core/frontend/input.h" | ||||
| #include "input_common/main.h" | ||||
|  | ||||
| union SDL_Event; | ||||
|  | ||||
| namespace Common { | ||||
| class ParamPackage; | ||||
| } // namespace Common | ||||
|  | ||||
| namespace InputCommon::Polling { | ||||
| class DevicePoller; | ||||
| enum class DeviceType; | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| #include <atomic> | ||||
| #include <cmath> | ||||
| #include <functional> | ||||
| #include <iterator> | ||||
| #include <mutex> | ||||
| #include <string> | ||||
| #include <thread> | ||||
| @@ -15,7 +14,6 @@ | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| #include <SDL.h> | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/param_package.h" | ||||
| @@ -23,12 +21,10 @@ | ||||
| #include "core/frontend/input.h" | ||||
| #include "input_common/sdl/sdl_impl.h" | ||||
|  | ||||
| namespace InputCommon { | ||||
|  | ||||
| namespace SDL { | ||||
| namespace InputCommon::SDL { | ||||
|  | ||||
| static std::string GetGUID(SDL_Joystick* joystick) { | ||||
|     SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); | ||||
|     const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); | ||||
|     char guid_str[33]; | ||||
|     SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); | ||||
|     return guid_str; | ||||
| @@ -37,26 +33,27 @@ static std::string GetGUID(SDL_Joystick* joystick) { | ||||
| /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice | ||||
| static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); | ||||
|  | ||||
| static int SDLEventWatcher(void* userdata, SDL_Event* event) { | ||||
|     SDLState* sdl_state = reinterpret_cast<SDLState*>(userdata); | ||||
| static int SDLEventWatcher(void* user_data, SDL_Event* event) { | ||||
|     auto* const sdl_state = static_cast<SDLState*>(user_data); | ||||
|  | ||||
|     // Don't handle the event if we are configuring | ||||
|     if (sdl_state->polling) { | ||||
|         sdl_state->event_queue.Push(*event); | ||||
|     } else { | ||||
|         sdl_state->HandleGameControllerEvent(*event); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| class SDLJoystick { | ||||
| public: | ||||
|     SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | ||||
|                 decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) | ||||
|         : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, deleter} {} | ||||
|     SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick) | ||||
|         : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {} | ||||
|  | ||||
|     void SetButton(int button, bool value) { | ||||
|         std::lock_guard lock{mutex}; | ||||
|         state.buttons[button] = value; | ||||
|         state.buttons.insert_or_assign(button, value); | ||||
|     } | ||||
|  | ||||
|     bool GetButton(int button) const { | ||||
| @@ -66,7 +63,7 @@ public: | ||||
|  | ||||
|     void SetAxis(int axis, Sint16 value) { | ||||
|         std::lock_guard lock{mutex}; | ||||
|         state.axes[axis] = value; | ||||
|         state.axes.insert_or_assign(axis, value); | ||||
|     } | ||||
|  | ||||
|     float GetAxis(int axis) const { | ||||
| @@ -93,7 +90,7 @@ public: | ||||
|  | ||||
|     void SetHat(int hat, Uint8 direction) { | ||||
|         std::lock_guard lock{mutex}; | ||||
|         state.hats[hat] = direction; | ||||
|         state.hats.insert_or_assign(hat, direction); | ||||
|     } | ||||
|  | ||||
|     bool GetHatDirection(int hat, Uint8 direction) const { | ||||
| @@ -118,10 +115,8 @@ public: | ||||
|         return sdl_joystick.get(); | ||||
|     } | ||||
|  | ||||
|     void SetSDLJoystick(SDL_Joystick* joystick, | ||||
|                         decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) { | ||||
|         sdl_joystick = | ||||
|             std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)>(joystick, deleter); | ||||
|     void SetSDLJoystick(SDL_Joystick* joystick) { | ||||
|         sdl_joystick.reset(joystick); | ||||
|     } | ||||
|  | ||||
| private: | ||||
| @@ -136,59 +131,57 @@ private: | ||||
|     mutable std::mutex mutex; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Get the nth joystick with the corresponding GUID | ||||
|  */ | ||||
| std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | ||||
|     std::lock_guard lock{joystick_map_mutex}; | ||||
|     const auto it = joystick_map.find(guid); | ||||
|     if (it != joystick_map.end()) { | ||||
|         while (it->second.size() <= static_cast<std::size_t>(port)) { | ||||
|             auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), | ||||
|                                                           nullptr, [](SDL_Joystick*) {}); | ||||
|             auto joystick = | ||||
|                 std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr); | ||||
|             it->second.emplace_back(std::move(joystick)); | ||||
|         } | ||||
|         return it->second[port]; | ||||
|     } | ||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, [](SDL_Joystick*) {}); | ||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr); | ||||
|     return joystick_map[guid].emplace_back(std::move(joystick)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so tie | ||||
|  * it to a SDLJoystick with the same guid and that port | ||||
|  */ | ||||
| std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { | ||||
|     auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); | ||||
|     const std::string guid = GetGUID(sdl_joystick); | ||||
|  | ||||
|     std::lock_guard lock{joystick_map_mutex}; | ||||
|     auto map_it = joystick_map.find(guid); | ||||
|     const auto map_it = joystick_map.find(guid); | ||||
|     if (map_it != joystick_map.end()) { | ||||
|         auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(), | ||||
|                                    [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { | ||||
|                                        return sdl_joystick == joystick->GetSDLJoystick(); | ||||
|                                    }); | ||||
|         const auto vec_it = | ||||
|             std::find_if(map_it->second.begin(), map_it->second.end(), | ||||
|                          [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { | ||||
|                              return sdl_joystick == joystick->GetSDLJoystick(); | ||||
|                          }); | ||||
|         if (vec_it != map_it->second.end()) { | ||||
|             // This is the common case: There is already an existing SDL_Joystick maped to a | ||||
|             // SDLJoystick. return the SDLJoystick | ||||
|             return *vec_it; | ||||
|         } | ||||
|  | ||||
|         // Search for a SDLJoystick without a mapped SDL_Joystick... | ||||
|         auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), | ||||
|                                        [](const std::shared_ptr<SDLJoystick>& joystick) { | ||||
|                                            return !joystick->GetSDLJoystick(); | ||||
|                                        }); | ||||
|         const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), | ||||
|                                              [](const std::shared_ptr<SDLJoystick>& joystick) { | ||||
|                                                  return !joystick->GetSDLJoystick(); | ||||
|                                              }); | ||||
|         if (nullptr_it != map_it->second.end()) { | ||||
|             // ... and map it | ||||
|             (*nullptr_it)->SetSDLJoystick(sdl_joystick); | ||||
|             return *nullptr_it; | ||||
|         } | ||||
|  | ||||
|         // There is no SDLJoystick without a mapped SDL_Joystick | ||||
|         // Create a new SDLJoystick | ||||
|         auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick); | ||||
|         const int port = static_cast<int>(map_it->second.size()); | ||||
|         auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | ||||
|         return map_it->second.emplace_back(std::move(joystick)); | ||||
|     } | ||||
|  | ||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick); | ||||
|     return joystick_map[guid].emplace_back(std::move(joystick)); | ||||
| } | ||||
| @@ -215,17 +208,19 @@ void SDLState::InitJoystick(int joystick_index) { | ||||
|         (*it)->SetSDLJoystick(sdl_joystick); | ||||
|         return; | ||||
|     } | ||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick); | ||||
|     const int port = static_cast<int>(joystick_guid_list.size()); | ||||
|     auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick); | ||||
|     joystick_guid_list.emplace_back(std::move(joystick)); | ||||
| } | ||||
|  | ||||
| void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | ||||
|     std::string guid = GetGUID(sdl_joystick); | ||||
|     const std::string guid = GetGUID(sdl_joystick); | ||||
|  | ||||
|     std::shared_ptr<SDLJoystick> joystick; | ||||
|     { | ||||
|         std::lock_guard lock{joystick_map_mutex}; | ||||
|         // This call to guid is safe since the joystick is guaranteed to be in the map | ||||
|         auto& joystick_guid_list = joystick_map[guid]; | ||||
|         const auto& joystick_guid_list = joystick_map[guid]; | ||||
|         const auto joystick_it = | ||||
|             std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(), | ||||
|                          [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { | ||||
| @@ -233,9 +228,10 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { | ||||
|                          }); | ||||
|         joystick = *joystick_it; | ||||
|     } | ||||
|     // Destruct SDL_Joystick outside the lock guard because SDL can internally call event calback | ||||
|     // which locks the mutex again | ||||
|     joystick->SetSDLJoystick(nullptr, [](SDL_Joystick*) {}); | ||||
|  | ||||
|     // Destruct SDL_Joystick outside the lock guard because SDL can internally call the | ||||
|     // event callback which locks the mutex again. | ||||
|     joystick->SetSDLJoystick(nullptr); | ||||
| } | ||||
|  | ||||
| void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | ||||
| @@ -317,9 +313,10 @@ public: | ||||
|           trigger_if_greater(trigger_if_greater_) {} | ||||
|  | ||||
|     bool GetStatus() const override { | ||||
|         float axis_value = joystick->GetAxis(axis); | ||||
|         if (trigger_if_greater) | ||||
|         const float axis_value = joystick->GetAxis(axis); | ||||
|         if (trigger_if_greater) { | ||||
|             return axis_value > threshold; | ||||
|         } | ||||
|         return axis_value < threshold; | ||||
|     } | ||||
|  | ||||
| @@ -444,7 +441,7 @@ public: | ||||
|         const int port = params.Get("port", 0); | ||||
|         const int axis_x = params.Get("axis_x", 0); | ||||
|         const int axis_y = params.Get("axis_y", 1); | ||||
|         float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | ||||
|         const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); | ||||
|  | ||||
|         auto joystick = state.GetSDLJoystickByGUID(guid, port); | ||||
|  | ||||
| @@ -470,7 +467,7 @@ SDLState::SDLState() { | ||||
|         return; | ||||
|     } | ||||
|     if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { | ||||
|         LOG_ERROR(Input, "Failed to set Hint for background events", SDL_GetError()); | ||||
|         LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); | ||||
|     } | ||||
|  | ||||
|     SDL_AddEventWatch(&SDLEventWatcher, this); | ||||
| @@ -507,12 +504,12 @@ SDLState::~SDLState() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | ||||
| static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | ||||
|     Common::ParamPackage params({{"engine", "sdl"}}); | ||||
|  | ||||
|     switch (event.type) { | ||||
|     case SDL_JOYAXISMOTION: { | ||||
|         auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||
|         params.Set("port", joystick->GetPort()); | ||||
|         params.Set("guid", joystick->GetGUID()); | ||||
|         params.Set("axis", event.jaxis.axis); | ||||
| @@ -526,14 +523,14 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve | ||||
|         break; | ||||
|     } | ||||
|     case SDL_JOYBUTTONUP: { | ||||
|         auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | ||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); | ||||
|         params.Set("port", joystick->GetPort()); | ||||
|         params.Set("guid", joystick->GetGUID()); | ||||
|         params.Set("button", event.jbutton.button); | ||||
|         break; | ||||
|     } | ||||
|     case SDL_JOYHATMOTION: { | ||||
|         auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | ||||
|         const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); | ||||
|         params.Set("port", joystick->GetPort()); | ||||
|         params.Set("guid", joystick->GetGUID()); | ||||
|         params.Set("hat", event.jhat.hat); | ||||
| @@ -607,8 +604,8 @@ public: | ||||
|         SDLPoller::Start(); | ||||
|  | ||||
|         // Reset stored axes | ||||
|         analog_xaxis = -1; | ||||
|         analog_yaxis = -1; | ||||
|         analog_x_axis = -1; | ||||
|         analog_y_axis = -1; | ||||
|         analog_axes_joystick = -1; | ||||
|     } | ||||
|  | ||||
| @@ -620,25 +617,25 @@ public: | ||||
|             } | ||||
|             // An analog device needs two axes, so we need to store the axis for later and wait for | ||||
|             // a second SDL event. The axes also must be from the same joystick. | ||||
|             int axis = event.jaxis.axis; | ||||
|             if (analog_xaxis == -1) { | ||||
|                 analog_xaxis = axis; | ||||
|             const int axis = event.jaxis.axis; | ||||
|             if (analog_x_axis == -1) { | ||||
|                 analog_x_axis = axis; | ||||
|                 analog_axes_joystick = event.jaxis.which; | ||||
|             } else if (analog_yaxis == -1 && analog_xaxis != axis && | ||||
|             } else if (analog_y_axis == -1 && analog_x_axis != axis && | ||||
|                        analog_axes_joystick == event.jaxis.which) { | ||||
|                 analog_yaxis = axis; | ||||
|                 analog_y_axis = axis; | ||||
|             } | ||||
|         } | ||||
|         Common::ParamPackage params; | ||||
|         if (analog_xaxis != -1 && analog_yaxis != -1) { | ||||
|             auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||
|         if (analog_x_axis != -1 && analog_y_axis != -1) { | ||||
|             const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | ||||
|             params.Set("engine", "sdl"); | ||||
|             params.Set("port", joystick->GetPort()); | ||||
|             params.Set("guid", joystick->GetGUID()); | ||||
|             params.Set("axis_x", analog_xaxis); | ||||
|             params.Set("axis_y", analog_yaxis); | ||||
|             analog_xaxis = -1; | ||||
|             analog_yaxis = -1; | ||||
|             params.Set("axis_x", analog_x_axis); | ||||
|             params.Set("axis_y", analog_y_axis); | ||||
|             analog_x_axis = -1; | ||||
|             analog_y_axis = -1; | ||||
|             analog_axes_joystick = -1; | ||||
|             return params; | ||||
|         } | ||||
| @@ -646,8 +643,8 @@ public: | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     int analog_xaxis = -1; | ||||
|     int analog_yaxis = -1; | ||||
|     int analog_x_axis = -1; | ||||
|     int analog_y_axis = -1; | ||||
|     SDL_JoystickID analog_axes_joystick = -1; | ||||
| }; | ||||
| } // namespace Polling | ||||
| @@ -667,5 +664,4 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) { | ||||
|     return pollers; | ||||
| } | ||||
|  | ||||
| } // namespace SDL | ||||
| } // namespace InputCommon | ||||
| } // namespace InputCommon::SDL | ||||
|   | ||||
| @@ -6,7 +6,10 @@ | ||||
|  | ||||
| #include <atomic> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <thread> | ||||
| #include <unordered_map> | ||||
| #include "common/common_types.h" | ||||
| #include "common/threadsafe_queue.h" | ||||
| #include "input_common/sdl/sdl.h" | ||||
|  | ||||
| @@ -16,9 +19,9 @@ using SDL_JoystickID = s32; | ||||
|  | ||||
| namespace InputCommon::SDL { | ||||
|  | ||||
| class SDLJoystick; | ||||
| class SDLButtonFactory; | ||||
| class SDLAnalogFactory; | ||||
| class SDLButtonFactory; | ||||
| class SDLJoystick; | ||||
|  | ||||
| class SDLState : public State { | ||||
| public: | ||||
| @@ -31,7 +34,13 @@ public: | ||||
|     /// Handle SDL_Events for joysticks from SDL_PollEvent | ||||
|     void HandleGameControllerEvent(const SDL_Event& event); | ||||
|  | ||||
|     /// Get the nth joystick with the corresponding GUID | ||||
|     std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); | ||||
|  | ||||
|     /** | ||||
|      * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so | ||||
|      * tie it to a SDLJoystick with the same guid and that port | ||||
|      */ | ||||
|     std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); | ||||
|  | ||||
|     /// Get all DevicePoller that use the SDL backend for a specific device type | ||||
|   | ||||
		Reference in New Issue
	
	Block a user