main.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // SPDX-FileCopyrightText: 2017 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <memory>
  4. #include "common/input.h"
  5. #include "common/param_package.h"
  6. #include "input_common/drivers/camera.h"
  7. #include "input_common/drivers/keyboard.h"
  8. #include "input_common/drivers/mouse.h"
  9. #include "input_common/drivers/tas_input.h"
  10. #include "input_common/drivers/touch_screen.h"
  11. #include "input_common/drivers/udp_client.h"
  12. #include "input_common/drivers/virtual_amiibo.h"
  13. #include "input_common/drivers/virtual_gamepad.h"
  14. #include "input_common/helpers/stick_from_buttons.h"
  15. #include "input_common/helpers/touch_from_buttons.h"
  16. #include "input_common/input_engine.h"
  17. #include "input_common/input_mapping.h"
  18. #include "input_common/input_poller.h"
  19. #include "input_common/main.h"
  20. #ifdef HAVE_LIBUSB
  21. #include "input_common/drivers/gc_adapter.h"
  22. #endif
  23. #ifdef HAVE_SDL2
  24. #include "input_common/drivers/joycon.h"
  25. #include "input_common/drivers/sdl_driver.h"
  26. #endif
  27. namespace InputCommon {
  28. /// Dummy engine to get periodic updates
  29. class UpdateEngine final : public InputEngine {
  30. public:
  31. explicit UpdateEngine(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
  32. PreSetController(identifier);
  33. }
  34. void PumpEvents() {
  35. SetButton(identifier, 0, last_state);
  36. last_state = !last_state;
  37. }
  38. private:
  39. static constexpr PadIdentifier identifier = {
  40. .guid = Common::UUID{},
  41. .port = 0,
  42. .pad = 0,
  43. };
  44. bool last_state{};
  45. };
  46. struct InputSubsystem::Impl {
  47. template <typename Engine>
  48. void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) {
  49. MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
  50. engine = std::make_shared<Engine>(name);
  51. engine->SetMappingCallback(mapping_callback);
  52. std::shared_ptr<InputFactory> input_factory = std::make_shared<InputFactory>(engine);
  53. std::shared_ptr<OutputFactory> output_factory = std::make_shared<OutputFactory>(engine);
  54. Common::Input::RegisterInputFactory(engine->GetEngineName(), std::move(input_factory));
  55. Common::Input::RegisterOutputFactory(engine->GetEngineName(), std::move(output_factory));
  56. }
  57. void Initialize() {
  58. mapping_factory = std::make_shared<MappingFactory>();
  59. RegisterEngine("updater", update_engine);
  60. RegisterEngine("keyboard", keyboard);
  61. RegisterEngine("mouse", mouse);
  62. RegisterEngine("touch", touch_screen);
  63. #ifdef HAVE_LIBUSB
  64. RegisterEngine("gcpad", gcadapter);
  65. #endif
  66. RegisterEngine("cemuhookudp", udp_client);
  67. RegisterEngine("tas", tas_input);
  68. RegisterEngine("camera", camera);
  69. RegisterEngine("virtual_amiibo", virtual_amiibo);
  70. RegisterEngine("virtual_gamepad", virtual_gamepad);
  71. #ifdef HAVE_SDL2
  72. RegisterEngine("sdl", sdl);
  73. RegisterEngine("joycon", joycon);
  74. #endif
  75. Common::Input::RegisterInputFactory("touch_from_button",
  76. std::make_shared<TouchFromButton>());
  77. Common::Input::RegisterInputFactory("analog_from_button",
  78. std::make_shared<StickFromButton>());
  79. }
  80. template <typename Engine>
  81. void UnregisterEngine(std::shared_ptr<Engine>& engine) {
  82. Common::Input::UnregisterInputFactory(engine->GetEngineName());
  83. Common::Input::UnregisterOutputFactory(engine->GetEngineName());
  84. engine.reset();
  85. }
  86. void Shutdown() {
  87. UnregisterEngine(update_engine);
  88. UnregisterEngine(keyboard);
  89. UnregisterEngine(mouse);
  90. UnregisterEngine(touch_screen);
  91. #ifdef HAVE_LIBUSB
  92. UnregisterEngine(gcadapter);
  93. #endif
  94. UnregisterEngine(udp_client);
  95. UnregisterEngine(tas_input);
  96. UnregisterEngine(camera);
  97. UnregisterEngine(virtual_amiibo);
  98. UnregisterEngine(virtual_gamepad);
  99. #ifdef HAVE_SDL2
  100. UnregisterEngine(sdl);
  101. UnregisterEngine(joycon);
  102. #endif
  103. Common::Input::UnregisterInputFactory("touch_from_button");
  104. Common::Input::UnregisterInputFactory("analog_from_button");
  105. }
  106. [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
  107. std::vector<Common::ParamPackage> devices = {
  108. Common::ParamPackage{{"display", "Any"}, {"engine", "any"}},
  109. };
  110. auto keyboard_devices = keyboard->GetInputDevices();
  111. devices.insert(devices.end(), keyboard_devices.begin(), keyboard_devices.end());
  112. auto mouse_devices = mouse->GetInputDevices();
  113. devices.insert(devices.end(), mouse_devices.begin(), mouse_devices.end());
  114. #ifdef HAVE_LIBUSB
  115. auto gcadapter_devices = gcadapter->GetInputDevices();
  116. devices.insert(devices.end(), gcadapter_devices.begin(), gcadapter_devices.end());
  117. #endif
  118. auto udp_devices = udp_client->GetInputDevices();
  119. devices.insert(devices.end(), udp_devices.begin(), udp_devices.end());
  120. #ifdef HAVE_SDL2
  121. auto joycon_devices = joycon->GetInputDevices();
  122. devices.insert(devices.end(), joycon_devices.begin(), joycon_devices.end());
  123. auto sdl_devices = sdl->GetInputDevices();
  124. devices.insert(devices.end(), sdl_devices.begin(), sdl_devices.end());
  125. #endif
  126. return devices;
  127. }
  128. [[nodiscard]] std::shared_ptr<InputEngine> GetInputEngine(
  129. const Common::ParamPackage& params) const {
  130. if (!params.Has("engine") || params.Get("engine", "") == "any") {
  131. return nullptr;
  132. }
  133. const std::string engine = params.Get("engine", "");
  134. if (engine == keyboard->GetEngineName()) {
  135. return keyboard;
  136. }
  137. if (engine == mouse->GetEngineName()) {
  138. return mouse;
  139. }
  140. #ifdef HAVE_LIBUSB
  141. if (engine == gcadapter->GetEngineName()) {
  142. return gcadapter;
  143. }
  144. #endif
  145. if (engine == udp_client->GetEngineName()) {
  146. return udp_client;
  147. }
  148. #ifdef HAVE_SDL2
  149. if (engine == sdl->GetEngineName()) {
  150. return sdl;
  151. }
  152. if (engine == joycon->GetEngineName()) {
  153. return joycon;
  154. }
  155. #endif
  156. return nullptr;
  157. }
  158. [[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
  159. const Common::ParamPackage& params) const {
  160. const auto input_engine = GetInputEngine(params);
  161. if (input_engine == nullptr) {
  162. return {};
  163. }
  164. return input_engine->GetAnalogMappingForDevice(params);
  165. }
  166. [[nodiscard]] ButtonMapping GetButtonMappingForDevice(
  167. const Common::ParamPackage& params) const {
  168. const auto input_engine = GetInputEngine(params);
  169. if (input_engine == nullptr) {
  170. return {};
  171. }
  172. return input_engine->GetButtonMappingForDevice(params);
  173. }
  174. [[nodiscard]] MotionMapping GetMotionMappingForDevice(
  175. const Common::ParamPackage& params) const {
  176. const auto input_engine = GetInputEngine(params);
  177. if (input_engine == nullptr) {
  178. return {};
  179. }
  180. return input_engine->GetMotionMappingForDevice(params);
  181. }
  182. Common::Input::ButtonNames GetButtonName(const Common::ParamPackage& params) const {
  183. if (!params.Has("engine") || params.Get("engine", "") == "any") {
  184. return Common::Input::ButtonNames::Undefined;
  185. }
  186. const auto input_engine = GetInputEngine(params);
  187. if (input_engine == nullptr) {
  188. return Common::Input::ButtonNames::Invalid;
  189. }
  190. return input_engine->GetUIName(params);
  191. }
  192. bool IsStickInverted(const Common::ParamPackage& params) {
  193. const auto input_engine = GetInputEngine(params);
  194. if (input_engine == nullptr) {
  195. return false;
  196. }
  197. return input_engine->IsStickInverted(params);
  198. }
  199. bool IsController(const Common::ParamPackage& params) {
  200. const std::string engine = params.Get("engine", "");
  201. if (engine == mouse->GetEngineName()) {
  202. return true;
  203. }
  204. #ifdef HAVE_LIBUSB
  205. if (engine == gcadapter->GetEngineName()) {
  206. return true;
  207. }
  208. #endif
  209. if (engine == udp_client->GetEngineName()) {
  210. return true;
  211. }
  212. if (engine == tas_input->GetEngineName()) {
  213. return true;
  214. }
  215. if (engine == virtual_gamepad->GetEngineName()) {
  216. return true;
  217. }
  218. #ifdef HAVE_SDL2
  219. if (engine == sdl->GetEngineName()) {
  220. return true;
  221. }
  222. if (engine == joycon->GetEngineName()) {
  223. return true;
  224. }
  225. #endif
  226. return false;
  227. }
  228. void BeginConfiguration() {
  229. keyboard->BeginConfiguration();
  230. mouse->BeginConfiguration();
  231. #ifdef HAVE_LIBUSB
  232. gcadapter->BeginConfiguration();
  233. #endif
  234. udp_client->BeginConfiguration();
  235. #ifdef HAVE_SDL2
  236. sdl->BeginConfiguration();
  237. joycon->BeginConfiguration();
  238. #endif
  239. }
  240. void EndConfiguration() {
  241. keyboard->EndConfiguration();
  242. mouse->EndConfiguration();
  243. #ifdef HAVE_LIBUSB
  244. gcadapter->EndConfiguration();
  245. #endif
  246. udp_client->EndConfiguration();
  247. #ifdef HAVE_SDL2
  248. sdl->EndConfiguration();
  249. joycon->EndConfiguration();
  250. #endif
  251. }
  252. void PumpEvents() const {
  253. update_engine->PumpEvents();
  254. #ifdef HAVE_SDL2
  255. sdl->PumpEvents();
  256. #endif
  257. }
  258. void RegisterInput(const MappingData& data) {
  259. mapping_factory->RegisterInput(data);
  260. }
  261. std::shared_ptr<MappingFactory> mapping_factory;
  262. std::shared_ptr<UpdateEngine> update_engine;
  263. std::shared_ptr<Keyboard> keyboard;
  264. std::shared_ptr<Mouse> mouse;
  265. std::shared_ptr<TouchScreen> touch_screen;
  266. std::shared_ptr<TasInput::Tas> tas_input;
  267. std::shared_ptr<CemuhookUDP::UDPClient> udp_client;
  268. std::shared_ptr<Camera> camera;
  269. std::shared_ptr<VirtualAmiibo> virtual_amiibo;
  270. std::shared_ptr<VirtualGamepad> virtual_gamepad;
  271. #ifdef HAVE_LIBUSB
  272. std::shared_ptr<GCAdapter> gcadapter;
  273. #endif
  274. #ifdef HAVE_SDL2
  275. std::shared_ptr<SDLDriver> sdl;
  276. std::shared_ptr<Joycons> joycon;
  277. #endif
  278. };
  279. InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
  280. InputSubsystem::~InputSubsystem() = default;
  281. void InputSubsystem::Initialize() {
  282. impl->Initialize();
  283. }
  284. void InputSubsystem::Shutdown() {
  285. impl->Shutdown();
  286. }
  287. Keyboard* InputSubsystem::GetKeyboard() {
  288. return impl->keyboard.get();
  289. }
  290. const Keyboard* InputSubsystem::GetKeyboard() const {
  291. return impl->keyboard.get();
  292. }
  293. Mouse* InputSubsystem::GetMouse() {
  294. return impl->mouse.get();
  295. }
  296. const Mouse* InputSubsystem::GetMouse() const {
  297. return impl->mouse.get();
  298. }
  299. TouchScreen* InputSubsystem::GetTouchScreen() {
  300. return impl->touch_screen.get();
  301. }
  302. const TouchScreen* InputSubsystem::GetTouchScreen() const {
  303. return impl->touch_screen.get();
  304. }
  305. TasInput::Tas* InputSubsystem::GetTas() {
  306. return impl->tas_input.get();
  307. }
  308. const TasInput::Tas* InputSubsystem::GetTas() const {
  309. return impl->tas_input.get();
  310. }
  311. Camera* InputSubsystem::GetCamera() {
  312. return impl->camera.get();
  313. }
  314. const Camera* InputSubsystem::GetCamera() const {
  315. return impl->camera.get();
  316. }
  317. VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() {
  318. return impl->virtual_amiibo.get();
  319. }
  320. const VirtualAmiibo* InputSubsystem::GetVirtualAmiibo() const {
  321. return impl->virtual_amiibo.get();
  322. }
  323. VirtualGamepad* InputSubsystem::GetVirtualGamepad() {
  324. return impl->virtual_gamepad.get();
  325. }
  326. const VirtualGamepad* InputSubsystem::GetVirtualGamepad() const {
  327. return impl->virtual_gamepad.get();
  328. }
  329. std::vector<Common::ParamPackage> InputSubsystem::GetInputDevices() const {
  330. return impl->GetInputDevices();
  331. }
  332. AnalogMapping InputSubsystem::GetAnalogMappingForDevice(const Common::ParamPackage& device) const {
  333. return impl->GetAnalogMappingForDevice(device);
  334. }
  335. ButtonMapping InputSubsystem::GetButtonMappingForDevice(const Common::ParamPackage& device) const {
  336. return impl->GetButtonMappingForDevice(device);
  337. }
  338. MotionMapping InputSubsystem::GetMotionMappingForDevice(const Common::ParamPackage& device) const {
  339. return impl->GetMotionMappingForDevice(device);
  340. }
  341. Common::Input::ButtonNames InputSubsystem::GetButtonName(const Common::ParamPackage& params) const {
  342. return impl->GetButtonName(params);
  343. }
  344. bool InputSubsystem::IsController(const Common::ParamPackage& params) const {
  345. return impl->IsController(params);
  346. }
  347. bool InputSubsystem::IsStickInverted(const Common::ParamPackage& params) const {
  348. if (params.Has("axis_x") && params.Has("axis_y")) {
  349. return impl->IsStickInverted(params);
  350. }
  351. return false;
  352. }
  353. void InputSubsystem::ReloadInputDevices() {
  354. impl->udp_client.get()->ReloadSockets();
  355. }
  356. void InputSubsystem::BeginMapping(Polling::InputType type) {
  357. impl->BeginConfiguration();
  358. impl->mapping_factory->BeginMapping(type);
  359. }
  360. Common::ParamPackage InputSubsystem::GetNextInput() const {
  361. return impl->mapping_factory->GetNextInput();
  362. }
  363. void InputSubsystem::StopMapping() const {
  364. impl->EndConfiguration();
  365. impl->mapping_factory->StopMapping();
  366. }
  367. void InputSubsystem::PumpEvents() const {
  368. impl->PumpEvents();
  369. }
  370. std::string GenerateKeyboardParam(int key_code) {
  371. Common::ParamPackage param;
  372. param.Set("engine", "keyboard");
  373. param.Set("code", key_code);
  374. param.Set("toggle", false);
  375. return param.Serialize();
  376. }
  377. std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right,
  378. int key_modifier, float modifier_scale) {
  379. Common::ParamPackage circle_pad_param{
  380. {"engine", "analog_from_button"},
  381. {"up", GenerateKeyboardParam(key_up)},
  382. {"down", GenerateKeyboardParam(key_down)},
  383. {"left", GenerateKeyboardParam(key_left)},
  384. {"right", GenerateKeyboardParam(key_right)},
  385. {"modifier", GenerateKeyboardParam(key_modifier)},
  386. {"modifier_scale", std::to_string(modifier_scale)},
  387. };
  388. return circle_pad_param.Serialize();
  389. }
  390. } // namespace InputCommon