ControllerInterface: DInput Joystick fix non thread safe static variable

also fix devices being added to its own custom list of devices even when rejected by the CI
This commit is contained in:
Filoppi 2021-05-15 12:21:22 +03:00
parent a0ecca1a84
commit 038b57fecc
3 changed files with 23 additions and 15 deletions

View file

@ -54,7 +54,6 @@ enum LOG_TYPE
OSHLE, OSHLE,
OSREPORT, OSREPORT,
OSREPORT_HLE, OSREPORT_HLE,
PAD,
PIXELENGINE, PIXELENGINE,
PROCESSORINTERFACE, PROCESSORINTERFACE,
POWERPC, POWERPC,

View file

@ -157,7 +157,6 @@ LogManager::LogManager()
m_log[OSHLE] = {"HLE", "OSHLE"}; m_log[OSHLE] = {"HLE", "OSHLE"};
m_log[OSREPORT] = {"OSREPORT", "OSReport EXI"}; m_log[OSREPORT] = {"OSREPORT", "OSReport EXI"};
m_log[OSREPORT_HLE] = {"OSREPORT_HLE", "OSReport HLE"}; m_log[OSREPORT_HLE] = {"OSREPORT_HLE", "OSReport HLE"};
m_log[PAD] = {"PAD", "Pad"};
m_log[PIXELENGINE] = {"PE", "Pixel Engine"}; m_log[PIXELENGINE] = {"PE", "Pixel Engine"};
m_log[PROCESSORINTERFACE] = {"PI", "Processor Interface"}; m_log[PROCESSORINTERFACE] = {"PI", "Processor Interface"};
m_log[POWERPC] = {"PowerPC", "PowerPC IBM CPU"}; m_log[POWERPC] = {"PowerPC", "PowerPC IBM CPU"};

View file

@ -4,6 +4,7 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <mutex>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
@ -29,6 +30,7 @@ struct GUIDComparator
}; };
static std::set<GUID, GUIDComparator> s_guids_in_use; static std::set<GUID, GUIDComparator> s_guids_in_use;
static std::mutex s_guids_mutex;
void InitJoystick(IDirectInput8* const idi8, HWND hwnd) void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
{ {
@ -46,12 +48,16 @@ void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
} }
// Skip devices we are already using. // Skip devices we are already using.
{
std::lock_guard lk(s_guids_mutex);
if (s_guids_in_use.count(joystick.guidInstance)) if (s_guids_in_use.count(joystick.guidInstance))
{ {
continue; continue;
} }
}
LPDIRECTINPUTDEVICE8 js_device; LPDIRECTINPUTDEVICE8 js_device;
// Don't print any warnings on failure
if (SUCCEEDED(idi8->CreateDevice(joystick.guidInstance, &js_device, nullptr))) if (SUCCEEDED(idi8->CreateDevice(joystick.guidInstance, &js_device, nullptr)))
{ {
if (SUCCEEDED(js_device->SetDataFormat(&c_dfDIJoystick))) if (SUCCEEDED(js_device->SetDataFormat(&c_dfDIJoystick)))
@ -60,37 +66,40 @@ void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
DISCL_BACKGROUND | DISCL_EXCLUSIVE))) DISCL_BACKGROUND | DISCL_EXCLUSIVE)))
{ {
WARN_LOG_FMT( WARN_LOG_FMT(
PAD, CONTROLLERINTERFACE,
"DInput: Failed to acquire device exclusively. Force feedback will be unavailable."); "DInput: Failed to acquire device exclusively. Force feedback will be unavailable.");
// Fall back to non-exclusive mode, with no rumble // Fall back to non-exclusive mode, with no rumble
if (FAILED( if (FAILED(
js_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) js_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
{ {
// PanicAlert("SetCooperativeLevel failed!");
js_device->Release(); js_device->Release();
continue; continue;
} }
} }
s_guids_in_use.insert(joystick.guidInstance);
auto js = std::make_shared<Joystick>(js_device); auto js = std::make_shared<Joystick>(js_device);
// only add if it has some inputs/outputs.
// only add if it has some inputs/outputs // Don't even add it to our static list in case we first created it without a window handle,
// failing to get exclusive mode, and then later managed to obtain it, which mean it
// could now have some outputs if it didn't before.
if (js->Inputs().size() || js->Outputs().size()) if (js->Inputs().size() || js->Outputs().size())
g_controller_interface.AddDevice(std::move(js)); {
if (g_controller_interface.AddDevice(std::move(js)))
{
std::lock_guard lk(s_guids_mutex);
s_guids_in_use.insert(joystick.guidInstance);
}
}
} }
else else
{ {
// PanicAlert("SetDataFormat failed!");
js_device->Release(); js_device->Release();
} }
} }
} }
} }
Joystick::Joystick(/*const LPCDIDEVICEINSTANCE lpddi, */ const LPDIRECTINPUTDEVICE8 device) Joystick::Joystick(const LPDIRECTINPUTDEVICE8 device) : m_device(device)
: m_device(device)
//, m_name(TStringToString(lpddi->tszInstanceName))
{ {
// seems this needs to be done before GetCapabilities // seems this needs to be done before GetCapabilities
// polled or buffered data // polled or buffered data
@ -183,11 +192,12 @@ Joystick::~Joystick()
info.dwSize = sizeof(info); info.dwSize = sizeof(info);
if (SUCCEEDED(m_device->GetDeviceInfo(&info))) if (SUCCEEDED(m_device->GetDeviceInfo(&info)))
{ {
std::lock_guard lk(s_guids_mutex);
s_guids_in_use.erase(info.guidInstance); s_guids_in_use.erase(info.guidInstance);
} }
else else
{ {
ERROR_LOG_FMT(PAD, "DInputJoystick: GetDeviceInfo failed."); ERROR_LOG_FMT(CONTROLLERINTERFACE, "DInputJoystick: GetDeviceInfo failed.");
} }
DeInitForceFeedback(); DeInitForceFeedback();