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.
This commit is contained in:
Michael Maltese 2016-10-16 13:39:05 -07:00
parent cebb4d84f2
commit 3e69d066f5
21 changed files with 79 additions and 25 deletions

View File

@ -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();

View File

@ -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<Touchscreen>(i));

View File

@ -11,7 +11,7 @@ namespace ciface
{
namespace Android
{
void Init();
void PopulateDevices();
class Touchscreen : public Core::Device
{
private:

View File

@ -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<std::mutex> lk(m_devices_mutex);
m_devices.clear();
}
#ifdef CIFACE_USE_DINPUT
ciface::DInput::PopulateDevices(reinterpret_cast<HWND>(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
}
//

View File

@ -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<ciface::Core::Device> device);
void RemoveDevice(std::function<bool(const ciface::Core::Device*)> callback);

View File

@ -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,

View File

@ -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);
}
}

View File

@ -9,6 +9,7 @@ namespace ciface
namespace OSX
{
void Init(void* window);
void PopulateDevices(void* window);
void DeInit();
void DeviceElementDebugPrint(const void*, void*);

View File

@ -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

View File

@ -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.

View File

@ -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
{

View File

@ -8,7 +8,7 @@ namespace ciface
{
namespace Quartz
{
void Init(void* window);
void PopulateDevices(void* window);
void DeInit();
}
}

View File

@ -10,7 +10,7 @@ namespace ciface
{
namespace Quartz
{
void Init(void* window)
void PopulateDevices(void* window)
{
g_controller_interface.AddDevice(std::make_shared<KeyboardAndMouse>(window));
}

View File

@ -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)

View File

@ -21,6 +21,7 @@ namespace ciface
namespace SDL
{
void Init();
void PopulateDevices();
class Joystick : public Core::Device
{

View File

@ -85,6 +85,12 @@ void Init()
return;
}
}
}
void PopulateDevices()
{
if (!hXInput)
return;
XINPUT_CAPABILITIES caps;
for (int i = 0; i != 4; ++i)

View File

@ -23,6 +23,7 @@ namespace ciface
namespace XInput
{
void Init();
void PopulateDevices();
void DeInit();
class Device : public Core::Device

View File

@ -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);

View File

@ -18,7 +18,7 @@ namespace ciface
{
namespace XInput2
{
void Init(void* const hwnd);
void PopulateDevices(void* const hwnd);
class KeyboardMouse : public Core::Device
{

View File

@ -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()

View File

@ -15,6 +15,7 @@ namespace ciface
namespace evdev
{
void Init();
void PopulateDevices();
void Shutdown();
class evdevDevice : public Core::Device