1 // Copyright 2018 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <atomic>
8 #include <memory>
9 #include <thread>
10 #include "common/threadsafe_queue.h"
11 #include "core/settings.h"
12 #include "input_common/sdl/sdl.h"
13 
14 union SDL_Event;
15 using SDL_Joystick = struct _SDL_Joystick;
16 using SDL_JoystickID = s32;
17 using SDL_GameController = struct _SDL_GameController;
18 
19 namespace InputCommon::SDL {
20 
21 class SDLJoystick;
22 class SDLGameController;
23 class SDLButtonFactory;
24 class SDLAnalogFactory;
25 class SDLMotionFactory;
26 
27 class SDLState : public State {
28 public:
29     /// Initializes and registers SDL device factories
30     SDLState();
31 
32     /// Unregisters SDL device factories and shut them down.
33     ~SDLState() override;
34 
35     /// Handle SDL_Events for joysticks from SDL_PollEvent
36     void HandleGameControllerEvent(const SDL_Event& event);
37 
38     std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id);
39     std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port);
40 
41     std::shared_ptr<SDLGameController> GetSDLGameControllerByGUID(const std::string& guid,
42                                                                   int port);
43 
44     Common::ParamPackage GetSDLControllerButtonBindByGUID(const std::string& guid, int port,
45                                                           Settings::NativeButton::Values button);
46     Common::ParamPackage GetSDLControllerAnalogBindByGUID(const std::string& guid, int port,
47                                                           Settings::NativeAnalog::Values analog);
48 
49     /// Get all DevicePoller that use the SDL backend for a specific device type
50     Pollers GetPollers(Polling::DeviceType type) override;
51 
52     /// Used by the Pollers during config
53     std::atomic<bool> polling = false;
54     Common::SPSCQueue<SDL_Event> event_queue;
55 
56 private:
57     void InitJoystick(int joystick_index);
58     void CloseJoystick(SDL_Joystick* sdl_joystick);
59 
60     void InitGameController(int joystick_index);
61     void CloseGameController(SDL_GameController* sdl_controller);
62 
63     /// Needs to be called before SDL_QuitSubSystem.
64     void CloseJoysticks();
65     void CloseGameControllers();
66 
67     /// Map of GUID of a list of corresponding virtual Joysticks
68     std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
69     std::mutex joystick_map_mutex;
70 
71     /// Map of GUID of a list of corresponding virtual Controllers
72     std::unordered_map<std::string, std::vector<std::shared_ptr<SDLGameController>>> controller_map;
73     std::mutex controller_map_mutex;
74 
75     std::shared_ptr<SDLButtonFactory> button_factory;
76     std::shared_ptr<SDLAnalogFactory> analog_factory;
77     std::shared_ptr<SDLMotionFactory> motion_factory;
78 
79     bool start_thread = false;
80     std::atomic<bool> initialized = false;
81 
82     std::thread poll_thread;
83 };
84 } // namespace InputCommon::SDL
85