From 3e69d066f5e9ad0a1097d806c656035398bbb7bc Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Sun, 16 Oct 2016 13:39:05 -0700 Subject: [PATCH] ControllerInterface: replace Reinitialize with RefreshDevices The SDL backend crashes when you close a joystick after SDL_Quit has been called. Some backends don't need to be shutdown and re-initialized everytime, we can just ask to enumerate devices again. --- .../Core/DolphinWX/Input/InputConfigDiag.cpp | 2 +- .../ControllerInterface/Android/Android.cpp | 2 +- .../ControllerInterface/Android/Android.h | 2 +- .../ControllerInterface.cpp | 45 +++++++++++++++---- .../ControllerInterface/ControllerInterface.h | 2 +- .../ControllerInterface/DInput/DInput.cpp | 2 +- .../ControllerInterface/DInput/DInput.h | 2 +- .../InputCommon/ControllerInterface/OSX/OSX.h | 1 + .../ControllerInterface/OSX/OSX.mm | 6 +++ .../ControllerInterface/Pipes/Pipes.cpp | 2 +- .../ControllerInterface/Pipes/Pipes.h | 2 +- .../ControllerInterface/Quartz/Quartz.h | 2 +- .../ControllerInterface/Quartz/Quartz.mm | 2 +- .../ControllerInterface/SDL/SDL.cpp | 6 +++ .../InputCommon/ControllerInterface/SDL/SDL.h | 1 + .../ControllerInterface/XInput/XInput.cpp | 6 +++ .../ControllerInterface/XInput/XInput.h | 1 + .../ControllerInterface/Xlib/XInput2.cpp | 2 +- .../ControllerInterface/Xlib/XInput2.h | 2 +- .../ControllerInterface/evdev/evdev.cpp | 13 +++--- .../ControllerInterface/evdev/evdev.h | 1 + 21 files changed, 79 insertions(+), 25 deletions(-) diff --git a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp index 7434371e1b..3ebbc1253c 100644 --- a/Source/Core/DolphinWX/Input/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Input/InputConfigDiag.cpp @@ -894,7 +894,7 @@ void InputConfigDialog::RefreshDevices(wxCommandEvent&) bool was_unpaused = Core::PauseAndLock(true); // refresh devices - g_controller_interface.Reinitialize(); + g_controller_interface.RefreshDevices(); // update all control references UpdateControlReferences(); diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index a5e995f6cc..983108f356 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -10,7 +10,7 @@ namespace ciface { namespace Android { -void Init() +void PopulateDevices() { for (int i = 0; i < 8; ++i) g_controller_interface.AddDevice(std::make_shared(i)); diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index 987aaed863..bf588719c2 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -11,7 +11,7 @@ namespace ciface { namespace Android { -void Init(); +void PopulateDevices(); class Touchscreen : public Core::Device { private: diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 13873ac2dd..635284d2c5 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -55,41 +55,70 @@ void ControllerInterface::Initialize(void* const hwnd) m_hwnd = hwnd; #ifdef CIFACE_USE_DINPUT - ciface::DInput::Init((HWND)hwnd); +// nothing needed #endif #ifdef CIFACE_USE_XINPUT ciface::XInput::Init(); #endif #ifdef CIFACE_USE_XLIB - ciface::XInput2::Init(hwnd); +// nothing needed #endif #ifdef CIFACE_USE_OSX ciface::OSX::Init(hwnd); - ciface::Quartz::Init(hwnd); +// nothing needed for Quartz #endif #ifdef CIFACE_USE_SDL ciface::SDL::Init(); #endif #ifdef CIFACE_USE_ANDROID - ciface::Android::Init(); +// nothing needed #endif #ifdef CIFACE_USE_EVDEV ciface::evdev::Init(); #endif #ifdef CIFACE_USE_PIPES - ciface::Pipes::Init(); +// nothing needed #endif m_is_init = true; + RefreshDevices(); } -void ControllerInterface::Reinitialize() +void ControllerInterface::RefreshDevices() { if (!m_is_init) return; - Shutdown(); - Initialize(m_hwnd); + { + std::lock_guard lk(m_devices_mutex); + m_devices.clear(); + } + +#ifdef CIFACE_USE_DINPUT + ciface::DInput::PopulateDevices(reinterpret_cast(m_hwnd)); +#endif +#ifdef CIFACE_USE_XINPUT + ciface::XInput::PopulateDevices(); +#endif +#ifdef CIFACE_USE_XLIB + ciface::XInput2::PopulateDevices(m_hwnd); +#endif +#ifdef CIFACE_USE_OSX + ciface::OSX::PopulateDevices(m_hwnd); + ciface::Quartz::PopulateDevices(m_hwnd); +#endif +#ifdef CIFACE_USE_SDL + ciface::SDL::PopulateDevices(); +#endif +#ifdef CIFACE_USE_ANDROID + ciface::Android::PopulateDevices(); +#endif +#ifdef CIFACE_USE_EVDEV + ciface::evdev::PopulateDevices(); +#endif +#ifdef CIFACE_USE_PIPES + ciface::Pipes::PopulateDevices(); +#endif } // diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h index c89edd29b5..845c6cbbf6 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h @@ -116,7 +116,7 @@ public: ControllerInterface() : m_is_init(false), m_hwnd(nullptr) {} void Initialize(void* const hwnd); - void Reinitialize(); + void RefreshDevices(); void Shutdown(); void AddDevice(std::shared_ptr device); void RemoveDevice(std::function callback); diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInput.cpp b/Source/Core/InputCommon/ControllerInterface/DInput/DInput.cpp index 83394852af..aacbcd55f8 100644 --- a/Source/Core/InputCommon/ControllerInterface/DInput/DInput.cpp +++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInput.cpp @@ -44,7 +44,7 @@ std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device) return result; } -void Init(HWND hwnd) +void PopulateDevices(HWND hwnd) { IDirectInput8* idi8; if (FAILED(DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInput.h b/Source/Core/InputCommon/ControllerInterface/DInput/DInput.h index 94e4cb4fe3..951eabebb9 100644 --- a/Source/Core/InputCommon/ControllerInterface/DInput/DInput.h +++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInput.h @@ -20,6 +20,6 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device); -void Init(HWND hwnd); +void PopulateDevices(HWND hwnd); } } diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h index c2104774b7..ac1db3e89a 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h @@ -9,6 +9,7 @@ namespace ciface namespace OSX { void Init(void* window); +void PopulateDevices(void* window); void DeInit(); void DeviceElementDebugPrint(const void*, void*); diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm index e575260a89..9aeeec59fb 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm @@ -182,6 +182,12 @@ void Init(void* window) IOHIDManagerUnscheduleFromRunLoop(HIDManager, CFRunLoopGetCurrent(), OurRunLoop); } +void PopulateDevices(void* window) +{ + DeInit(); + Init(window); +} + void DeInit() { // This closes all devices as well diff --git a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp index 6e93a581d1..6f09214f5b 100644 --- a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp @@ -41,7 +41,7 @@ static double StringToDouble(const std::string& text) return result; } -void Init() +void PopulateDevices() { // Search the Pipes directory for files that we can open in read-only, // non-blocking mode. The device name is the virtual name of the file. diff --git a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h index a2e26db994..3cb79fee39 100644 --- a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h +++ b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h @@ -22,7 +22,7 @@ namespace Pipes // SET {L, R} [0, 1] // SET {MAIN, C} [0, 1] [0, 1] -void Init(); +void PopulateDevices(); class PipeDevice : public Core::Device { diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h index 3e08410f6b..03f6ca9993 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h @@ -8,7 +8,7 @@ namespace ciface { namespace Quartz { -void Init(void* window); +void PopulateDevices(void* window); void DeInit(); } } diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm index 6fdac0e798..a090b421a5 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm @@ -10,7 +10,7 @@ namespace ciface { namespace Quartz { -void Init(void* window) +void PopulateDevices(void* window) { g_controller_interface.AddDevice(std::make_shared(window)); } diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp index 8f8265e8d0..7da8e66fc6 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp @@ -47,6 +47,12 @@ void Init() // Failed to initialize return; } +} + +void PopulateDevices() +{ + if (!(SDL_WasInit(SDL_INIT_EVERYTHING) & SDL_INIT_JOYSTICK)) + return; // joysticks for (int i = 0; i < SDL_NumJoysticks(); ++i) diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h index e104af7715..c41bb57614 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h @@ -21,6 +21,7 @@ namespace ciface namespace SDL { void Init(); +void PopulateDevices(); class Joystick : public Core::Device { diff --git a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp index d39b0b8e1e..3d8650820e 100644 --- a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp +++ b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp @@ -85,6 +85,12 @@ void Init() return; } } +} + +void PopulateDevices() +{ + if (!hXInput) + return; XINPUT_CAPABILITIES caps; for (int i = 0; i != 4; ++i) diff --git a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h index 0dda9a93da..52530e9a00 100644 --- a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h +++ b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h @@ -23,6 +23,7 @@ namespace ciface namespace XInput { void Init(); +void PopulateDevices(); void DeInit(); class Device : public Core::Device diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp index de3490f2e0..29ac62f32c 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp @@ -46,7 +46,7 @@ namespace ciface namespace XInput2 { // This function will add zero or more KeyboardMouse objects to devices. -void Init(void* const hwnd) +void PopulateDevices(void* const hwnd) { Display* dpy = XOpenDisplay(nullptr); diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h index 80df03db70..5c5124cb3b 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h @@ -18,7 +18,7 @@ namespace ciface { namespace XInput2 { -void Init(void* const hwnd); +void PopulateDevices(void* const hwnd); class KeyboardMouse : public Core::Device { diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index d3f8f5fd36..bee0c44a02 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -141,10 +141,15 @@ static void StopHotplugThread() void Init() { s_devnode_name_map.clear(); + PopulateDevices(); + StartHotplugThread(); +} - // During initialization we use udev to iterate over all /dev/input/event* devices. - // Note: the Linux kernel is currently limited to just 32 event devices. If this ever - // changes, hopefully udev will take care of this. +void PopulateDevices() +{ + // We use udev to iterate over all /dev/input/event* devices. + // Note: the Linux kernel is currently limited to just 32 event devices. If + // this ever changes, hopefully udev will take care of this. udev* udev = udev_new(); _assert_msg_(PAD, udev != nullptr, "Couldn't initialize libudev."); @@ -182,8 +187,6 @@ void Init() } udev_enumerate_unref(enumerate); udev_unref(udev); - - StartHotplugThread(); } void Shutdown() diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h index dc8e917e23..513c5a67f2 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h @@ -15,6 +15,7 @@ namespace ciface namespace evdev { void Init(); +void PopulateDevices(); void Shutdown(); class evdevDevice : public Core::Device