summaryrefslogtreecommitdiff
path: root/src/input_common/sdl
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/sdl')
-rw-r--r--src/input_common/sdl/sdl_impl.cpp169
1 files changed, 84 insertions, 85 deletions
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 9c3035920..10883e2d9 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -155,15 +155,15 @@ public:
155 return sdl_joystick.get(); 155 return sdl_joystick.get();
156 } 156 }
157 157
158 void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
159 sdl_controller.reset(controller);
160 sdl_joystick.reset(joystick);
161 }
162
163 SDL_GameController* GetSDLGameController() const { 158 SDL_GameController* GetSDLGameController() const {
164 return sdl_controller.get(); 159 return sdl_controller.get();
165 } 160 }
166 161
162 void SetSDLJoystick(SDL_Joystick* joystick, SDL_GameController* controller) {
163 sdl_joystick.reset(joystick);
164 sdl_controller.reset(controller);
165 }
166
167private: 167private:
168 struct State { 168 struct State {
169 std::unordered_map<int, bool> buttons; 169 std::unordered_map<int, bool> buttons;
@@ -186,69 +186,58 @@ private:
186std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { 186std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
187 std::lock_guard lock{joystick_map_mutex}; 187 std::lock_guard lock{joystick_map_mutex};
188 const auto it = joystick_map.find(guid); 188 const auto it = joystick_map.find(guid);
189
189 if (it != joystick_map.end()) { 190 if (it != joystick_map.end()) {
190 while (it->second.size() <= static_cast<std::size_t>(port)) { 191 while (it->second.size() <= static_cast<std::size_t>(port)) {
191 auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), 192 auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()),
192 nullptr, nullptr); 193 nullptr, nullptr);
193 it->second.emplace_back(std::move(joystick)); 194 it->second.emplace_back(std::move(joystick));
194 } 195 }
196
195 return it->second[static_cast<std::size_t>(port)]; 197 return it->second[static_cast<std::size_t>(port)];
196 } 198 }
199
197 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr); 200 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, nullptr);
201
198 return joystick_map[guid].emplace_back(std::move(joystick)); 202 return joystick_map[guid].emplace_back(std::move(joystick));
199} 203}
200 204
201std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { 205std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
202 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); 206 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
203 auto sdl_controller = SDL_GameControllerFromInstanceID(sdl_id);
204 const std::string guid = GetGUID(sdl_joystick); 207 const std::string guid = GetGUID(sdl_joystick);
205 208
206 std::lock_guard lock{joystick_map_mutex}; 209 std::lock_guard lock{joystick_map_mutex};
207 const auto map_it = joystick_map.find(guid); 210 const auto map_it = joystick_map.find(guid);
208 if (map_it != joystick_map.end()) {
209 const auto vec_it =
210 std::find_if(map_it->second.begin(), map_it->second.end(),
211 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
212 return sdl_joystick == joystick->GetSDLJoystick();
213 });
214 if (vec_it != map_it->second.end()) {
215 // This is the common case: There is already an existing SDL_Joystick mapped to a
216 // SDLJoystick. return the SDLJoystick
217 return *vec_it;
218 }
219 211
220 // Search for a SDLJoystick without a mapped SDL_Joystick... 212 if (map_it == joystick_map.end()) {
221 const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), 213 return nullptr;
222 [](const std::shared_ptr<SDLJoystick>& joystick) { 214 }
223 return joystick->GetSDLJoystick() == nullptr;
224 });
225 if (nullptr_it != map_it->second.end()) {
226 // ... and map it
227 (*nullptr_it)->SetSDLJoystick(sdl_joystick, sdl_controller);
228 return *nullptr_it;
229 }
230 215
231 // There is no SDLJoystick without a mapped SDL_Joystick 216 const auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
232 // Create a new SDLJoystick 217 [&sdl_joystick](const auto& joystick) {
233 const int port = static_cast<int>(map_it->second.size()); 218 return joystick->GetSDLJoystick() == sdl_joystick;
234 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_controller); 219 });
235 return map_it->second.emplace_back(std::move(joystick)); 220
221 if (vec_it == map_it->second.end()) {
222 return nullptr;
236 } 223 }
237 224
238 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick, sdl_controller); 225 return *vec_it;
239 return joystick_map[guid].emplace_back(std::move(joystick));
240} 226}
241 227
242void SDLState::InitJoystick(int joystick_index) { 228void SDLState::InitJoystick(int joystick_index) {
243 SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index); 229 SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
244 SDL_GameController* sdl_gamecontroller = nullptr; 230 SDL_GameController* sdl_gamecontroller = nullptr;
231
245 if (SDL_IsGameController(joystick_index)) { 232 if (SDL_IsGameController(joystick_index)) {
246 sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); 233 sdl_gamecontroller = SDL_GameControllerOpen(joystick_index);
247 } 234 }
235
248 if (!sdl_joystick) { 236 if (!sdl_joystick) {
249 LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); 237 LOG_ERROR(Input, "Failed to open joystick {}", joystick_index);
250 return; 238 return;
251 } 239 }
240
252 const std::string guid = GetGUID(sdl_joystick); 241 const std::string guid = GetGUID(sdl_joystick);
253 242
254 std::lock_guard lock{joystick_map_mutex}; 243 std::lock_guard lock{joystick_map_mutex};
@@ -257,14 +246,17 @@ void SDLState::InitJoystick(int joystick_index) {
257 joystick_map[guid].emplace_back(std::move(joystick)); 246 joystick_map[guid].emplace_back(std::move(joystick));
258 return; 247 return;
259 } 248 }
249
260 auto& joystick_guid_list = joystick_map[guid]; 250 auto& joystick_guid_list = joystick_map[guid];
261 const auto it = std::find_if( 251 const auto joystick_it =
262 joystick_guid_list.begin(), joystick_guid_list.end(), 252 std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
263 [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); }); 253 [](const auto& joystick) { return !joystick->GetSDLJoystick(); });
264 if (it != joystick_guid_list.end()) { 254
265 (*it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller); 255 if (joystick_it != joystick_guid_list.end()) {
256 (*joystick_it)->SetSDLJoystick(sdl_joystick, sdl_gamecontroller);
266 return; 257 return;
267 } 258 }
259
268 const int port = static_cast<int>(joystick_guid_list.size()); 260 const int port = static_cast<int>(joystick_guid_list.size());
269 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller); 261 auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick, sdl_gamecontroller);
270 joystick_guid_list.emplace_back(std::move(joystick)); 262 joystick_guid_list.emplace_back(std::move(joystick));
@@ -274,18 +266,14 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {
274 const std::string guid = GetGUID(sdl_joystick); 266 const std::string guid = GetGUID(sdl_joystick);
275 267
276 std::lock_guard lock{joystick_map_mutex}; 268 std::lock_guard lock{joystick_map_mutex};
277 auto& joystick_guid_list = joystick_map[guid]; 269 // This call to guid is safe since the joystick is guaranteed to be in the map
278 auto joystick_it = std::find_if( 270 const auto& joystick_guid_list = joystick_map[guid];
279 joystick_guid_list.begin(), joystick_guid_list.end(), 271 const auto joystick_it = std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
280 [&sdl_joystick](auto& joystick) { return joystick->GetSDLJoystick() == sdl_joystick; }); 272 [&sdl_joystick](const auto& joystick) {
281 273 return joystick->GetSDLJoystick() == sdl_joystick;
282 if (joystick_it != joystick_guid_list.end()) { 274 });
283 (*joystick_it)->SetSDLJoystick(nullptr, nullptr); 275
284 joystick_guid_list.erase(joystick_it); 276 (*joystick_it)->SetSDLJoystick(nullptr, nullptr);
285 if (joystick_guid_list.empty()) {
286 joystick_map.erase(guid);
287 }
288 }
289} 277}
290 278
291void SDLState::HandleGameControllerEvent(const SDL_Event& event) { 279void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
@@ -720,8 +708,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
720 std::vector<Common::ParamPackage> devices; 708 std::vector<Common::ParamPackage> devices;
721 for (const auto& [key, value] : joystick_map) { 709 for (const auto& [key, value] : joystick_map) {
722 for (const auto& joystick : value) { 710 for (const auto& joystick : value) {
723 auto* joy = joystick->GetSDLJoystick(); 711 if (auto* const controller = joystick->GetSDLGameController()) {
724 if (auto* controller = joystick->GetSDLGameController()) {
725 std::string name = 712 std::string name =
726 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort()); 713 fmt::format("{} {}", SDL_GameControllerName(controller), joystick->GetPort());
727 devices.emplace_back(Common::ParamPackage{ 714 devices.emplace_back(Common::ParamPackage{
@@ -730,7 +717,7 @@ std::vector<Common::ParamPackage> SDLState::GetInputDevices() {
730 {"guid", joystick->GetGUID()}, 717 {"guid", joystick->GetGUID()},
731 {"port", std::to_string(joystick->GetPort())}, 718 {"port", std::to_string(joystick->GetPort())},
732 }); 719 });
733 } else if (joy) { 720 } else if (auto* const joy = joystick->GetSDLJoystick()) {
734 std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort()); 721 std::string name = fmt::format("{} {}", SDL_JoystickName(joy), joystick->GetPort());
735 devices.emplace_back(Common::ParamPackage{ 722 devices.emplace_back(Common::ParamPackage{
736 {"class", "sdl"}, 723 {"class", "sdl"},
@@ -797,21 +784,27 @@ Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s
797Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { 784Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
798 switch (event.type) { 785 switch (event.type) {
799 case SDL_JOYAXISMOTION: { 786 case SDL_JOYAXISMOTION: {
800 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 787 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
801 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 788 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
802 static_cast<s32>(event.jaxis.axis), 789 static_cast<s32>(event.jaxis.axis),
803 event.jaxis.value); 790 event.jaxis.value);
791 }
792 break;
804 } 793 }
805 case SDL_JOYBUTTONUP: { 794 case SDL_JOYBUTTONUP: {
806 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); 795 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which)) {
807 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 796 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
808 static_cast<s32>(event.jbutton.button)); 797 static_cast<s32>(event.jbutton.button));
798 }
799 break;
809 } 800 }
810 case SDL_JOYHATMOTION: { 801 case SDL_JOYHATMOTION: {
811 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); 802 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which)) {
812 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 803 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
813 static_cast<s32>(event.jhat.hat), 804 static_cast<s32>(event.jhat.hat),
814 static_cast<s32>(event.jhat.value)); 805 static_cast<s32>(event.jhat.value));
806 }
807 break;
815 } 808 }
816 } 809 }
817 return {}; 810 return {};
@@ -820,21 +813,27 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
820Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Event& event) { 813Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Event& event) {
821 switch (event.type) { 814 switch (event.type) {
822 case SDL_JOYAXISMOTION: { 815 case SDL_JOYAXISMOTION: {
823 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 816 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
824 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 817 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
825 static_cast<s32>(event.jaxis.axis), 818 static_cast<s32>(event.jaxis.axis),
826 event.jaxis.value); 819 event.jaxis.value);
820 }
821 break;
827 } 822 }
828 case SDL_JOYBUTTONUP: { 823 case SDL_JOYBUTTONUP: {
829 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); 824 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which)) {
830 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 825 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
831 static_cast<s32>(event.jbutton.button)); 826 static_cast<s32>(event.jbutton.button));
827 }
828 break;
832 } 829 }
833 case SDL_JOYHATMOTION: { 830 case SDL_JOYHATMOTION: {
834 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); 831 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which)) {
835 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(), 832 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
836 static_cast<s32>(event.jhat.hat), 833 static_cast<s32>(event.jhat.hat),
837 static_cast<s32>(event.jhat.value)); 834 static_cast<s32>(event.jhat.value));
835 }
836 break;
838 } 837 }
839 } 838 }
840 return {}; 839 return {};
@@ -1062,9 +1061,8 @@ public:
1062 // Simplify controller config by testing if game controller support is enabled. 1061 // Simplify controller config by testing if game controller support is enabled.
1063 if (event.type == SDL_JOYAXISMOTION) { 1062 if (event.type == SDL_JOYAXISMOTION) {
1064 const auto axis = event.jaxis.axis; 1063 const auto axis = event.jaxis.axis;
1065 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 1064 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
1066 auto* const controller = joystick->GetSDLGameController(); 1065 auto* const controller = joystick->GetSDLGameController()) {
1067 if (controller) {
1068 const auto axis_left_x = 1066 const auto axis_left_x =
1069 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) 1067 SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
1070 .value.axis; 1068 .value.axis;
@@ -1098,12 +1096,13 @@ public:
1098 } 1096 }
1099 1097
1100 if (analog_x_axis != -1 && analog_y_axis != -1) { 1098 if (analog_x_axis != -1 && analog_y_axis != -1) {
1101 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); 1099 if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which)) {
1102 auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(), 1100 auto params = BuildParamPackageForAnalog(joystick->GetPort(), joystick->GetGUID(),
1103 analog_x_axis, analog_y_axis); 1101 analog_x_axis, analog_y_axis);
1104 analog_x_axis = -1; 1102 analog_x_axis = -1;
1105 analog_y_axis = -1; 1103 analog_y_axis = -1;
1106 return params; 1104 return params;
1105 }
1107 } 1106 }
1108 return {}; 1107 return {};
1109 } 1108 }