Skip to content

Commit

Permalink
Merge pull request #4343 from ligfx/fixsdlcrash
Browse files Browse the repository at this point in the history
ControllerInterface: Fix crashes when using SDL controllers
  • Loading branch information
Helios747 committed Dec 1, 2016
2 parents e2018f2 + 3e69d06 commit a95e3c8
Show file tree
Hide file tree
Showing 21 changed files with 92 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Source/Core/DolphinWX/Input/InputConfigDiag.cpp
Expand Up @@ -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();
Expand Down
Expand Up @@ -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));
Expand Down
Expand Up @@ -11,7 +11,7 @@ namespace ciface
{
namespace Android
{
void Init();
void PopulateDevices();
class Touchscreen : public Core::Device
{
private:
Expand Down
69 changes: 50 additions & 19 deletions Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
Expand Up @@ -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
}

//
Expand All @@ -102,6 +131,19 @@ void ControllerInterface::Shutdown()
if (!m_is_init)
return;

{
std::lock_guard<std::mutex> lk(m_devices_mutex);

for (const auto& d : m_devices)
{
// Set outputs to ZERO before destroying device
for (ciface::Core::Device::Output* o : d->Outputs())
o->SetState(0);
}

m_devices.clear();
}

#ifdef CIFACE_USE_XINPUT
ciface::XInput::DeInit();
#endif
Expand All @@ -126,17 +168,6 @@ void ControllerInterface::Shutdown()
ciface::evdev::Shutdown();
#endif

std::lock_guard<std::mutex> lk(m_devices_mutex);

for (const auto& d : m_devices)
{
// Set outputs to ZERO before destroying device
for (ciface::Core::Device::Output* o : d->Outputs())
o->SetState(0);
}

m_devices.clear();

m_is_init = false;
}

Expand Down
Expand Up @@ -116,7 +116,7 @@ class ControllerInterface : public ciface::Core::DeviceContainer

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);
Expand Down
Expand Up @@ -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,
Expand Down
Expand Up @@ -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);
}
}
1 change: 1 addition & 0 deletions Source/Core/InputCommon/ControllerInterface/OSX/OSX.h
Expand Up @@ -9,6 +9,7 @@ namespace ciface
namespace OSX
{
void Init(void* window);
void PopulateDevices(void* window);
void DeInit();

void DeviceElementDebugPrint(const void*, void*);
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm
Expand Up @@ -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
Expand Down
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h
Expand Up @@ -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
{
Expand Down
Expand Up @@ -8,7 +8,7 @@ namespace ciface
{
namespace Quartz
{
void Init(void* window);
void PopulateDevices(void* window);
void DeInit();
}
}
Expand Up @@ -10,7 +10,7 @@
{
namespace Quartz
{
void Init(void* window)
void PopulateDevices(void* window)
{
g_controller_interface.AddDevice(std::make_shared<KeyboardAndMouse>(window));
}
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions Source/Core/InputCommon/ControllerInterface/SDL/SDL.h
Expand Up @@ -21,6 +21,7 @@ namespace ciface
namespace SDL
{
void Init();
void PopulateDevices();

class Joystick : public Core::Device
{
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp
Expand Up @@ -85,6 +85,12 @@ void Init()
return;
}
}
}

void PopulateDevices()
{
if (!hXInput)
return;

XINPUT_CAPABILITIES caps;
for (int i = 0; i != 4; ++i)
Expand Down
Expand Up @@ -23,6 +23,7 @@ namespace ciface
namespace XInput
{
void Init();
void PopulateDevices();
void DeInit();

class Device : public Core::Device
Expand Down
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h
Expand Up @@ -18,7 +18,7 @@ namespace ciface
{
namespace XInput2
{
void Init(void* const hwnd);
void PopulateDevices(void* const hwnd);

class KeyboardMouse : public Core::Device
{
Expand Down
13 changes: 8 additions & 5 deletions Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
Expand Up @@ -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.");
Expand Down Expand Up @@ -182,8 +187,6 @@ void Init()
}
udev_enumerate_unref(enumerate);
udev_unref(udev);

StartHotplugThread();
}

void Shutdown()
Expand Down
1 change: 1 addition & 0 deletions Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
Expand Up @@ -15,6 +15,7 @@ namespace ciface
namespace evdev
{
void Init();
void PopulateDevices();
void Shutdown();

class evdevDevice : public Core::Device
Expand Down

2 comments on commit a95e3c8

@P3rf3ctXZer0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This release fails to save or load wii saves. Please fix in next release!

@JosJuice
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@P3rf3ctXZer0 If you want to report a bug, please find the exact version where it stopped working, then make an issue report at https://bugs.dolphin-emu.org/projects/emulator

Please sign in to comment.