summaryrefslogtreecommitdiff
path: root/src/input_common/sdl/sdl.cpp
diff options
context:
space:
mode:
authorGravatar James Rowe2018-09-20 00:28:05 -0600
committerGravatar fearlessTobi2019-03-02 19:09:34 +0100
commit09ac66388c01187ed6a402efcad76984c8af9a2e (patch)
treebeed8a86e7b7e02e0c5526723bbf812920341d12 /src/input_common/sdl/sdl.cpp
parentInput: Copy current SDL.h/cpp files to impl (diff)
downloadyuzu-09ac66388c01187ed6a402efcad76984c8af9a2e.tar.gz
yuzu-09ac66388c01187ed6a402efcad76984c8af9a2e.tar.xz
yuzu-09ac66388c01187ed6a402efcad76984c8af9a2e.zip
Input: Remove global variables from SDL Input
Changes the interface as well to remove any unique methods that frontends needed to call such as StartJoystickEventHandler by conditionally starting the polling thread only if the frontend hasn't started it already. Additionally, moves all global state into a single SDLState class in order to guarantee that the destructors are called in the proper order
Diffstat (limited to '')
-rw-r--r--src/input_common/sdl/sdl.cpp636
1 files changed, 12 insertions, 624 deletions
diff --git a/src/input_common/sdl/sdl.cpp b/src/input_common/sdl/sdl.cpp
index faf3c1fa3..644db3448 100644
--- a/src/input_common/sdl/sdl.cpp
+++ b/src/input_common/sdl/sdl.cpp
@@ -1,631 +1,19 @@
1// Copyright 2017 Citra Emulator Project 1// Copyright 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <atomic>
7#include <cmath>
8#include <functional>
9#include <iterator>
10#include <mutex>
11#include <string>
12#include <thread>
13#include <tuple>
14#include <unordered_map>
15#include <utility>
16#include <vector>
17#include <SDL.h>
18#include "common/assert.h"
19#include "common/logging/log.h"
20#include "common/math_util.h"
21#include "common/param_package.h"
22#include "common/threadsafe_queue.h"
23#include "input_common/main.h"
24#include "input_common/sdl/sdl.h" 5#include "input_common/sdl/sdl.h"
6#ifdef HAVE_SDL2
7#include "input_common/sdl/sdl_impl.h"
8#endif
25 9
26namespace InputCommon { 10namespace InputCommon::SDL {
27 11
28namespace SDL { 12std::unique_ptr<State> Init() {
29 13#ifdef HAVE_SDL2
30class SDLJoystick; 14 return std::make_unique<SDLState>();
31class SDLButtonFactory; 15#else
32class SDLAnalogFactory; 16 return std::make_unique<NullState>();
33 17#endif
34/// Map of GUID of a list of corresponding virtual Joysticks
35static std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
36static std::mutex joystick_map_mutex;
37
38static std::shared_ptr<SDLButtonFactory> button_factory;
39static std::shared_ptr<SDLAnalogFactory> analog_factory;
40
41/// Used by the Pollers during config
42static std::atomic<bool> polling;
43static Common::SPSCQueue<SDL_Event> event_queue;
44
45static std::atomic<bool> initialized = false;
46
47static std::string GetGUID(SDL_Joystick* joystick) {
48 SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
49 char guid_str[33];
50 SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
51 return guid_str;
52}
53
54class SDLJoystick {
55public:
56 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
57 decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose)
58 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, deleter} {}
59
60 void SetButton(int button, bool value) {
61 std::lock_guard<std::mutex> lock(mutex);
62 state.buttons[button] = value;
63 }
64
65 bool GetButton(int button) const {
66 std::lock_guard<std::mutex> lock(mutex);
67 return state.buttons.at(button);
68 }
69
70 void SetAxis(int axis, Sint16 value) {
71 std::lock_guard<std::mutex> lock(mutex);
72 state.axes[axis] = value;
73 }
74
75 float GetAxis(int axis) const {
76 std::lock_guard<std::mutex> lock(mutex);
77 return state.axes.at(axis) / 32767.0f;
78 }
79
80 std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const {
81 float x = GetAxis(axis_x);
82 float y = GetAxis(axis_y);
83 y = -y; // 3DS uses an y-axis inverse from SDL
84
85 // Make sure the coordinates are in the unit circle,
86 // otherwise normalize it.
87 float r = x * x + y * y;
88 if (r > 1.0f) {
89 r = std::sqrt(r);
90 x /= r;
91 y /= r;
92 }
93
94 return std::make_tuple(x, y);
95 }
96
97 void SetHat(int hat, Uint8 direction) {
98 std::lock_guard<std::mutex> lock(mutex);
99 state.hats[hat] = direction;
100 }
101
102 bool GetHatDirection(int hat, Uint8 direction) const {
103 std::lock_guard<std::mutex> lock(mutex);
104 return (state.hats.at(hat) & direction) != 0;
105 }
106 /**
107 * The guid of the joystick
108 */
109 const std::string& GetGUID() const {
110 return guid;
111 }
112
113 /**
114 * The number of joystick from the same type that were connected before this joystick
115 */
116 int GetPort() const {
117 return port;
118 }
119
120 SDL_Joystick* GetSDLJoystick() const {
121 return sdl_joystick.get();
122 }
123
124 void SetSDLJoystick(SDL_Joystick* joystick,
125 decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) {
126 sdl_joystick =
127 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)>(joystick, deleter);
128 }
129
130private:
131 struct State {
132 std::unordered_map<int, bool> buttons;
133 std::unordered_map<int, Sint16> axes;
134 std::unordered_map<int, Uint8> hats;
135 } state;
136 std::string guid;
137 int port;
138 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
139 mutable std::mutex mutex;
140};
141
142/**
143 * Get the nth joystick with the corresponding GUID
144 */
145static std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port) {
146 std::lock_guard<std::mutex> lock(joystick_map_mutex);
147 const auto it = joystick_map.find(guid);
148 if (it != joystick_map.end()) {
149 while (it->second.size() <= port) {
150 auto joystick = std::make_shared<SDLJoystick>(guid, it->second.size(), nullptr,
151 [](SDL_Joystick*) {});
152 it->second.emplace_back(std::move(joystick));
153 }
154 return it->second[port];
155 }
156 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, [](SDL_Joystick*) {});
157 return joystick_map[guid].emplace_back(std::move(joystick));
158}
159
160/**
161 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so tie
162 * it to a SDLJoystick with the same guid and that port
163 */
164static std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
165 std::lock_guard<std::mutex> lock(joystick_map_mutex);
166 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
167 const std::string guid = GetGUID(sdl_joystick);
168 auto map_it = joystick_map.find(guid);
169 if (map_it != joystick_map.end()) {
170 auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
171 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
172 return sdl_joystick == joystick->GetSDLJoystick();
173 });
174 if (vec_it != map_it->second.end()) {
175 // This is the common case: There is already an existing SDL_Joystick maped to a
176 // SDLJoystick. return the SDLJoystick
177 return *vec_it;
178 }
179 // Search for a SDLJoystick without a mapped SDL_Joystick...
180 auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(),
181 [](const std::shared_ptr<SDLJoystick>& joystick) {
182 return !joystick->GetSDLJoystick();
183 });
184 if (nullptr_it != map_it->second.end()) {
185 // ... and map it
186 (*nullptr_it)->SetSDLJoystick(sdl_joystick);
187 return *nullptr_it;
188 }
189 // There is no SDLJoystick without a mapped SDL_Joystick
190 // Create a new SDLJoystick
191 auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick);
192 return map_it->second.emplace_back(std::move(joystick));
193 }
194 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
195 return joystick_map[guid].emplace_back(std::move(joystick));
196}
197
198void InitJoystick(int joystick_index) {
199 std::lock_guard<std::mutex> lock(joystick_map_mutex);
200 SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
201 if (!sdl_joystick) {
202 LOG_ERROR(Input, "failed to open joystick {}", joystick_index);
203 return;
204 }
205 std::string guid = GetGUID(sdl_joystick);
206 if (joystick_map.find(guid) == joystick_map.end()) {
207 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
208 joystick_map[guid].emplace_back(std::move(joystick));
209 return;
210 }
211 auto& joystick_guid_list = joystick_map[guid];
212 const auto it = std::find_if(
213 joystick_guid_list.begin(), joystick_guid_list.end(),
214 [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); });
215 if (it != joystick_guid_list.end()) {
216 (*it)->SetSDLJoystick(sdl_joystick);
217 return;
218 }
219 auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick);
220 joystick_guid_list.emplace_back(std::move(joystick));
221}
222
223void CloseJoystick(SDL_Joystick* sdl_joystick) {
224 std::lock_guard<std::mutex> lock(joystick_map_mutex);
225 std::string guid = GetGUID(sdl_joystick);
226 // This call to guid is save since the joystick is guranteed to be in that map
227 auto& joystick_guid_list = joystick_map[guid];
228 const auto joystick_it =
229 std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
230 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
231 return joystick->GetSDLJoystick() == sdl_joystick;
232 });
233 (*joystick_it)->SetSDLJoystick(nullptr, [](SDL_Joystick*) {});
234}
235
236void HandleGameControllerEvent(const SDL_Event& event) {
237 switch (event.type) {
238 case SDL_JOYBUTTONUP: {
239 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
240 if (joystick) {
241 joystick->SetButton(event.jbutton.button, false);
242 }
243 break;
244 }
245 case SDL_JOYBUTTONDOWN: {
246 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
247 if (joystick) {
248 joystick->SetButton(event.jbutton.button, true);
249 }
250 break;
251 }
252 case SDL_JOYHATMOTION: {
253 auto joystick = GetSDLJoystickBySDLID(event.jhat.which);
254 if (joystick) {
255 joystick->SetHat(event.jhat.hat, event.jhat.value);
256 }
257 break;
258 }
259 case SDL_JOYAXISMOTION: {
260 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
261 if (joystick) {
262 joystick->SetAxis(event.jaxis.axis, event.jaxis.value);
263 }
264 break;
265 }
266 case SDL_JOYDEVICEREMOVED:
267 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
268 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
269 break;
270 case SDL_JOYDEVICEADDED:
271 LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which);
272 InitJoystick(event.jdevice.which);
273 break;
274 }
275}
276
277void CloseSDLJoysticks() {
278 std::lock_guard<std::mutex> lock(joystick_map_mutex);
279 joystick_map.clear();
280}
281
282void PollLoop() {
283 if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
284 LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
285 return;
286 }
287
288 SDL_Event event;
289 while (initialized) {
290 // Wait for 10 ms or until an event happens
291 if (SDL_WaitEventTimeout(&event, 10)) {
292 // Don't handle the event if we are configuring
293 if (polling) {
294 event_queue.Push(event);
295 } else {
296 HandleGameControllerEvent(event);
297 }
298 }
299 }
300 CloseSDLJoysticks();
301 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
302}
303
304class SDLButton final : public Input::ButtonDevice {
305public:
306 explicit SDLButton(std::shared_ptr<SDLJoystick> joystick_, int button_)
307 : joystick(std::move(joystick_)), button(button_) {}
308
309 bool GetStatus() const override {
310 return joystick->GetButton(button);
311 }
312
313private:
314 std::shared_ptr<SDLJoystick> joystick;
315 int button;
316};
317
318class SDLDirectionButton final : public Input::ButtonDevice {
319public:
320 explicit SDLDirectionButton(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
321 : joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
322
323 bool GetStatus() const override {
324 return joystick->GetHatDirection(hat, direction);
325 }
326
327private:
328 std::shared_ptr<SDLJoystick> joystick;
329 int hat;
330 Uint8 direction;
331};
332
333class SDLAxisButton final : public Input::ButtonDevice {
334public:
335 explicit SDLAxisButton(std::shared_ptr<SDLJoystick> joystick_, int axis_, float threshold_,
336 bool trigger_if_greater_)
337 : joystick(std::move(joystick_)), axis(axis_), threshold(threshold_),
338 trigger_if_greater(trigger_if_greater_) {}
339
340 bool GetStatus() const override {
341 float axis_value = joystick->GetAxis(axis);
342 if (trigger_if_greater)
343 return axis_value > threshold;
344 return axis_value < threshold;
345 }
346
347private:
348 std::shared_ptr<SDLJoystick> joystick;
349 int axis;
350 float threshold;
351 bool trigger_if_greater;
352};
353
354class SDLAnalog final : public Input::AnalogDevice {
355public:
356 SDLAnalog(std::shared_ptr<SDLJoystick> joystick_, int axis_x_, int axis_y_)
357 : joystick(std::move(joystick_)), axis_x(axis_x_), axis_y(axis_y_) {}
358
359 std::tuple<float, float> GetStatus() const override {
360 return joystick->GetAnalog(axis_x, axis_y);
361 }
362
363private:
364 std::shared_ptr<SDLJoystick> joystick;
365 int axis_x;
366 int axis_y;
367};
368
369/// A button device factory that creates button devices from SDL joystick
370class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> {
371public:
372 /**
373 * Creates a button device from a joystick button
374 * @param params contains parameters for creating the device:
375 * - "guid": the guid of the joystick to bind
376 * - "port": the nth joystick of the same type to bind
377 * - "button"(optional): the index of the button to bind
378 * - "hat"(optional): the index of the hat to bind as direction buttons
379 * - "axis"(optional): the index of the axis to bind
380 * - "direction"(only used for hat): the direction name of the hat to bind. Can be "up",
381 * "down", "left" or "right"
382 * - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
383 * triggered if the axis value crosses
384 * - "direction"(only used for axis): "+" means the button is triggered when the axis
385 * value is greater than the threshold; "-" means the button is triggered when the axis
386 * value is smaller than the threshold
387 */
388 std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override {
389 const std::string guid = params.Get("guid", "0");
390 const int port = params.Get("port", 0);
391
392 auto joystick = GetSDLJoystickByGUID(guid, port);
393
394 if (params.Has("hat")) {
395 const int hat = params.Get("hat", 0);
396 const std::string direction_name = params.Get("direction", "");
397 Uint8 direction;
398 if (direction_name == "up") {
399 direction = SDL_HAT_UP;
400 } else if (direction_name == "down") {
401 direction = SDL_HAT_DOWN;
402 } else if (direction_name == "left") {
403 direction = SDL_HAT_LEFT;
404 } else if (direction_name == "right") {
405 direction = SDL_HAT_RIGHT;
406 } else {
407 direction = 0;
408 }
409 // This is necessary so accessing GetHat with hat won't crash
410 joystick->SetHat(hat, SDL_HAT_CENTERED);
411 return std::make_unique<SDLDirectionButton>(joystick, hat, direction);
412 }
413
414 if (params.Has("axis")) {
415 const int axis = params.Get("axis", 0);
416 const float threshold = params.Get("threshold", 0.5f);
417 const std::string direction_name = params.Get("direction", "");
418 bool trigger_if_greater;
419 if (direction_name == "+") {
420 trigger_if_greater = true;
421 } else if (direction_name == "-") {
422 trigger_if_greater = false;
423 } else {
424 trigger_if_greater = true;
425 LOG_ERROR(Input, "Unknown direction '{}'", direction_name);
426 }
427 // This is necessary so accessing GetAxis with axis won't crash
428 joystick->SetAxis(axis, 0);
429 return std::make_unique<SDLAxisButton>(joystick, axis, threshold, trigger_if_greater);
430 }
431
432 const int button = params.Get("button", 0);
433 // This is necessary so accessing GetButton with button won't crash
434 joystick->SetButton(button, false);
435 return std::make_unique<SDLButton>(joystick, button);
436 }
437};
438
439/// An analog device factory that creates analog devices from SDL joystick
440class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
441public:
442 /**
443 * Creates analog device from joystick axes
444 * @param params contains parameters for creating the device:
445 * - "guid": the guid of the joystick to bind
446 * - "port": the nth joystick of the same type
447 * - "axis_x": the index of the axis to be bind as x-axis
448 * - "axis_y": the index of the axis to be bind as y-axis
449 */
450 std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override {
451 const std::string guid = params.Get("guid", "0");
452 const int port = params.Get("port", 0);
453 const int axis_x = params.Get("axis_x", 0);
454 const int axis_y = params.Get("axis_y", 1);
455
456 auto joystick = GetSDLJoystickByGUID(guid, port);
457
458 // This is necessary so accessing GetAxis with axis_x and axis_y won't crash
459 joystick->SetAxis(axis_x, 0);
460 joystick->SetAxis(axis_y, 0);
461 return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y);
462 }
463};
464
465void Init() {
466 using namespace Input;
467 RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>());
468 RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>());
469 polling = false;
470 initialized = true;
471}
472
473void Shutdown() {
474 if (initialized) {
475 using namespace Input;
476 UnregisterFactory<ButtonDevice>("sdl");
477 UnregisterFactory<AnalogDevice>("sdl");
478 initialized = false;
479 }
480}
481
482Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) {
483 Common::ParamPackage params({{"engine", "sdl"}});
484 switch (event.type) {
485 case SDL_JOYAXISMOTION: {
486 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
487 params.Set("port", joystick->GetPort());
488 params.Set("guid", joystick->GetGUID());
489 params.Set("axis", event.jaxis.axis);
490 if (event.jaxis.value > 0) {
491 params.Set("direction", "+");
492 params.Set("threshold", "0.5");
493 } else {
494 params.Set("direction", "-");
495 params.Set("threshold", "-0.5");
496 }
497 break;
498 }
499 case SDL_JOYBUTTONUP: {
500 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
501 params.Set("port", joystick->GetPort());
502 params.Set("guid", joystick->GetGUID());
503 params.Set("button", event.jbutton.button);
504 break;
505 }
506 case SDL_JOYHATMOTION: {
507 auto joystick = GetSDLJoystickBySDLID(event.jhat.which);
508 params.Set("port", joystick->GetPort());
509 params.Set("guid", joystick->GetGUID());
510 params.Set("hat", event.jhat.hat);
511 switch (event.jhat.value) {
512 case SDL_HAT_UP:
513 params.Set("direction", "up");
514 break;
515 case SDL_HAT_DOWN:
516 params.Set("direction", "down");
517 break;
518 case SDL_HAT_LEFT:
519 params.Set("direction", "left");
520 break;
521 case SDL_HAT_RIGHT:
522 params.Set("direction", "right");
523 break;
524 default:
525 return {};
526 }
527 break;
528 }
529 }
530 return params;
531}
532
533namespace Polling {
534
535class SDLPoller : public InputCommon::Polling::DevicePoller {
536public:
537 void Start() override {
538 event_queue.Clear();
539 polling = true;
540 }
541
542 void Stop() override {
543 polling = false;
544 }
545};
546
547class SDLButtonPoller final : public SDLPoller {
548public:
549 Common::ParamPackage GetNextInput() override {
550 SDL_Event event;
551 while (event_queue.Pop(event)) {
552 switch (event.type) {
553 case SDL_JOYAXISMOTION:
554 if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
555 break;
556 }
557 case SDL_JOYBUTTONUP:
558 case SDL_JOYHATMOTION:
559 return SDLEventToButtonParamPackage(event);
560 }
561 }
562 return {};
563 }
564};
565
566class SDLAnalogPoller final : public SDLPoller {
567public:
568 void Start() override {
569 SDLPoller::Start();
570
571 // Reset stored axes
572 analog_xaxis = -1;
573 analog_yaxis = -1;
574 analog_axes_joystick = -1;
575 }
576
577 Common::ParamPackage GetNextInput() override {
578 SDL_Event event;
579 while (event_queue.Pop(event)) {
580 if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) {
581 continue;
582 }
583 // An analog device needs two axes, so we need to store the axis for later and wait for
584 // a second SDL event. The axes also must be from the same joystick.
585 int axis = event.jaxis.axis;
586 if (analog_xaxis == -1) {
587 analog_xaxis = axis;
588 analog_axes_joystick = event.jaxis.which;
589 } else if (analog_yaxis == -1 && analog_xaxis != axis &&
590 analog_axes_joystick == event.jaxis.which) {
591 analog_yaxis = axis;
592 }
593 }
594 Common::ParamPackage params;
595 if (analog_xaxis != -1 && analog_yaxis != -1) {
596 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
597 params.Set("engine", "sdl");
598 params.Set("port", joystick->GetPort());
599 params.Set("guid", joystick->GetGUID());
600 params.Set("axis_x", analog_xaxis);
601 params.Set("axis_y", analog_yaxis);
602 analog_xaxis = -1;
603 analog_yaxis = -1;
604 analog_axes_joystick = -1;
605 return params;
606 }
607 return params;
608 }
609
610private:
611 int analog_xaxis = -1;
612 int analog_yaxis = -1;
613 SDL_JoystickID analog_axes_joystick = -1;
614};
615
616std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> GetPollers(
617 InputCommon::Polling::DeviceType type) {
618 std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> pollers;
619 switch (type) {
620 case InputCommon::Polling::DeviceType::Analog:
621 pollers.push_back(std::make_unique<SDLAnalogPoller>());
622 break;
623 case InputCommon::Polling::DeviceType::Button:
624 pollers.push_back(std::make_unique<SDLButtonPoller>());
625 break;
626 }
627 return pollers;
628} 18}
629} // namespace Polling 19} // namespace InputCommon::SDL
630} // namespace SDL
631} // namespace InputCommon