summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/input/input_winhybrid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/input/input_winhybrid.cpp')
-rw-r--r--src/osd/modules/input/input_winhybrid.cpp351
1 files changed, 159 insertions, 192 deletions
diff --git a/src/osd/modules/input/input_winhybrid.cpp b/src/osd/modules/input/input_winhybrid.cpp
index 1436ae009d6..2f1023e24fb 100644
--- a/src/osd/modules/input/input_winhybrid.cpp
+++ b/src/osd/modules/input/input_winhybrid.cpp
@@ -6,48 +6,31 @@
//
//============================================================
-#include "input_module.h"
#include "modules/osdmodule.h"
-#if defined(OSD_WINDOWS)
+#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
+
+#include "input_dinput.h"
+#include "input_xinput.h"
-#include <list>
#include <vector>
-// standard windows headers
-#include <windows.h>
-#include <wrl/client.h>
+#include <oleauto.h>
#include <wbemcli.h>
-// XInput/DirectInput
-#include <xinput.h>
-#include <dinput.h>
-
-#undef interface
-// MAME headers
-#include "emu.h"
-
-// MAMEOS headers
-#include "strconv.h"
-#include "winmain.h"
-
-#include "input_common.h"
-#include "input_windows.h"
-#include "input_xinput.h"
-#include "input_dinput.h"
+namespace osd {
-using namespace Microsoft::WRL;
+namespace {
-template<class TCom>
+template <class TCom>
class ComArray
{
private:
- std::vector<TCom*> m_entries;
+ std::vector<TCom *> m_entries;
public:
- ComArray(size_t capacity)
- : m_entries(capacity, nullptr)
+ ComArray(size_t capacity) : m_entries(capacity, nullptr)
{
}
@@ -56,7 +39,7 @@ public:
Release();
}
- TCom** ReleaseAndGetAddressOf()
+ TCom **ReleaseAndGetAddressOf()
{
Release();
@@ -64,7 +47,7 @@ public:
return &m_entries[0];
}
- TCom* operator [] (int i)
+ TCom *operator[](int i)
{
return m_entries[i];
}
@@ -76,12 +59,12 @@ public:
void Release()
{
- for (int i = 0; i < m_entries.size(); i++)
+ for (auto &entry : m_entries)
{
- if (m_entries[i] != nullptr)
+ if (entry)
{
- m_entries[i]->Release();
- m_entries[i] = nullptr;
+ entry->Release();
+ entry = nullptr;
}
}
}
@@ -91,7 +74,7 @@ struct bstr_deleter
{
void operator () (BSTR bstr) const
{
- if (bstr != nullptr)
+ if (bstr)
SysFreeString(bstr);
}
};
@@ -104,8 +87,8 @@ private:
public:
variant_wrapper()
- : m_variant({0})
{
+ VariantInit(&m_variant);
}
~variant_wrapper()
@@ -133,28 +116,24 @@ public:
typedef std::unique_ptr<OLECHAR, bstr_deleter> bstr_ptr;
+
//============================================================
// winhybrid_joystick_module
//============================================================
-class winhybrid_joystick_module : public wininput_module, public device_enum_interface
+class winhybrid_joystick_module : public input_module_impl<device_info, osd_common_t>
{
private:
- std::shared_ptr<xinput_api_helper> m_xinput_helper;
+ std::unique_ptr<xinput_api_helper> m_xinput_helper;
std::unique_ptr<dinput_api_helper> m_dinput_helper;
- std::list<DWORD> m_xinput_deviceids;
- bool m_xinput_detect_failed;
public:
- winhybrid_joystick_module()
- : wininput_module(OSD_JOYSTICKINPUT_PROVIDER, "winhybrid"),
- m_xinput_helper(nullptr),
- m_dinput_helper(nullptr),
- m_xinput_detect_failed(false)
+ winhybrid_joystick_module() :
+ input_module_impl<device_info, osd_common_t>(OSD_JOYSTICKINPUT_PROVIDER, "winhybrid")
{
}
- bool probe() override
+ virtual bool probe() override
{
int status = init_helpers();
if (status != 0)
@@ -166,10 +145,12 @@ public:
return true;
}
- int init(const osd_options &options) override
+ virtual int init(osd_interface &osd, const osd_options &options) override
{
+ int status;
+
// Call the base
- int status = wininput_module::init(options);
+ status = input_module_impl<device_info, osd_common_t>::init(osd, options);
if (status != 0)
return status;
@@ -184,129 +165,116 @@ public:
return 0;
}
- BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref) override
+ virtual void input_init(running_machine &machine) override
{
- dinput_cooperative_level cooperative_level = dinput_cooperative_level::FOREGROUND;
- running_machine &machine = *static_cast<running_machine *>(ref);
- dinput_joystick_device *devinfo;
- int result = 0;
-
- // First check if this device is XInput Compatible. If so, don't add it here
- // as it'll be picked up by Xinput
- if (!m_xinput_detect_failed && is_xinput_device(&instance->guidProduct))
- {
- osd_printf_verbose("Skipping DirectInput for XInput compatible joystick %S.\n", instance->tszInstanceName);
- goto exit;
- }
+ input_module_impl<device_info, osd_common_t>::input_init(machine);
- if (!osd_common_t::s_window_list.empty() && osd_common_t::s_window_list.front()->win_has_menu())
- cooperative_level = dinput_cooperative_level::BACKGROUND;
-
- // allocate and link in a new device
- devinfo = m_dinput_helper->create_device<dinput_joystick_device>(machine, *this, instance, &c_dfDIJoystick, nullptr, cooperative_level);
- if (devinfo == nullptr)
- goto exit;
-
- result = devinfo->configure();
+ bool xinput_detect_failed = false;
+ std::vector<DWORD> xinput_deviceids;
+ HRESULT result = get_xinput_devices(xinput_deviceids);
if (result != 0)
{
- osd_printf_error("Failed to configure DI Joystick device. Error 0x%x\n", static_cast<unsigned int>(result));
+ xinput_detect_failed = true;
+ xinput_deviceids.clear();
+ osd_printf_warning("XInput device detection failed. XInput won't be used. Error: 0x%X\n", uint32_t(result));
}
- exit:
- return DIENUM_CONTINUE;
- }
-
- void exit() override
- {
- m_xinput_helper.reset();
- m_dinput_helper.reset();
-
- wininput_module::exit();
- }
-
-protected:
- virtual void input_init(running_machine &machine) override
- {
- HRESULT result = get_xinput_devices(m_xinput_deviceids);
- if (result != 0)
- {
- m_xinput_detect_failed = true;
- osd_printf_warning("XInput device detection failed. XInput won't be used. Error: 0x%X\n", static_cast<unsigned int>(result));
- }
+ // Enumerate all the DirectInput joysticks and add them if they aren't XInput compatible
+ result = m_dinput_helper->enum_attached_devices(
+ DI8DEVCLASS_GAMECTRL,
+ [this, &xinput_deviceids] (LPCDIDEVICEINSTANCE instance)
+ {
+ // First check if this device is XInput compatible.
+ // If so, don't add it here as it'll be picked up by Xinput.
+ auto const found = std::find(
+ xinput_deviceids.begin(),
+ xinput_deviceids.end(),
+ instance->guidProduct.Data1);
+ if (xinput_deviceids.end() != found)
+ {
+ osd_printf_verbose("Skipping DirectInput for XInput compatible joystick %S.\n", instance->tszInstanceName);
+ return DIENUM_CONTINUE;
+ }
- // Enumerate all the directinput joysticks and add them if they aren't xinput compatible
- result = m_dinput_helper->enum_attached_devices(DI8DEVCLASS_GAMECTRL, this, &machine);
+ // allocate and link in a new device
+ auto devinfo = m_dinput_helper->create_device<dinput_joystick_device>(
+ *this,
+ instance,
+ &c_dfDIJoystick,
+ nullptr,
+ background_input() ? dinput_cooperative_level::BACKGROUND : dinput_cooperative_level::FOREGROUND,
+ [] (auto const &device, auto const &format) -> bool
+ {
+ // set absolute mode
+ HRESULT const result = dinput_api_helper::set_dword_property(
+ device,
+ DIPROP_AXISMODE,
+ 0,
+ DIPH_DEVICE,
+ DIPROPAXISMODE_ABS);
+ if ((result != DI_OK) && (result != DI_PROPNOEFFECT))
+ {
+ osd_printf_error("DirectInput: Unable to set absolute mode for joystick.\n");
+ return false;
+ }
+ return true;
+ });
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
+
+ return DIENUM_CONTINUE;
+ });
if (result != DI_OK)
- fatalerror("DirectInput: Unable to enumerate keyboards (result=%08X)\n", static_cast<uint32_t>(result));
-
- xinput_joystick_device *devinfo;
+ fatalerror("DirectInput: Unable to enumerate game controllers (result=%08X).\n", uint32_t(result));
// now add all xinput devices
- if (!m_xinput_detect_failed)
+ if (!xinput_detect_failed)
{
// Loop through each gamepad to determine if they are connected
for (UINT i = 0; i < XUSER_MAX_COUNT; i++)
{
- XINPUT_STATE state = { 0 };
-
- if (m_xinput_helper->xinput_get_state(i, &state) == ERROR_SUCCESS)
- {
- // allocate and link in a new device
- devinfo = m_xinput_helper->create_xinput_device(machine, i, *this);
- if (devinfo == nullptr)
- continue;
-
- // Configure each gamepad to add buttons and Axes, etc.
- devinfo->configure();
- }
+ // allocate and link in a new device
+ auto devinfo = m_xinput_helper->create_xinput_device(i, *this);
+ if (devinfo)
+ add_device(DEVICE_CLASS_JOYSTICK, std::move(devinfo));
}
}
}
+ virtual void exit() override
+ {
+ input_module_impl<device_info, osd_common_t>::exit();
+
+ m_xinput_helper.reset();
+ m_dinput_helper.reset();
+ }
+
private:
int init_helpers()
{
- int status = 0;
-
- if (m_xinput_helper == nullptr)
+ if (!m_xinput_helper)
{
- m_xinput_helper = std::make_shared<xinput_api_helper>();
- status = m_xinput_helper->initialize();
+ m_xinput_helper = std::make_unique<xinput_api_helper>();
+ int const status = m_xinput_helper->initialize();
if (status != 0)
{
- osd_printf_verbose("xinput_api_helper failed to initialize! Error: %u\n", static_cast<unsigned int>(status));
+ osd_printf_verbose("Failed to initialize XInput API! Error: %u\n", static_cast<unsigned int>(status));
return -1;
}
}
- if (m_dinput_helper == nullptr)
+ if (!m_dinput_helper)
{
- m_dinput_helper = std::make_unique<dinput_api_helper>(DIRECTINPUT_VERSION);
- status = m_dinput_helper->initialize();
+ m_dinput_helper = std::make_unique<dinput_api_helper>();
+ int const status = m_dinput_helper->initialize();
if (status != DI_OK)
{
- osd_printf_verbose("dinput_api_helper failed to initialize! Error: %u\n", static_cast<unsigned int>(status));
+ osd_printf_verbose("Failed to initialize DirectInput API! Error: %u\n", static_cast<unsigned int>(status));
return -1;
}
}
- return status;
- }
-
- //-----------------------------------------------------------------------------
- // Returns true if the DirectInput device is also an XInput device.
- //-----------------------------------------------------------------------------
- bool is_xinput_device(const GUID* pGuidProductFromDirectInput)
- {
- // Check each xinput device to see if this device's vid/pid matches
- for (auto devid = m_xinput_deviceids.begin(); devid != m_xinput_deviceids.end(); ++devid)
- {
- if (*devid == pGuidProductFromDirectInput->Data1)
- return true;
- }
-
- return false;
+ return 0;
}
//-----------------------------------------------------------------------------
@@ -316,54 +284,43 @@ private:
// Checking against a VID/PID of 0x028E/0x045E won't find 3rd party or future
// XInput devices.
//-----------------------------------------------------------------------------
- HRESULT get_xinput_devices(std::list<DWORD> &xinput_id_list) const
+ HRESULT get_xinput_devices(std::vector<DWORD> &xinput_deviceids)
{
- ComPtr<IWbemServices> pIWbemServices;
- ComPtr<IEnumWbemClassObject> pEnumDevices;
- ComPtr<IWbemLocator> pIWbemLocator;
- ComArray<IWbemClassObject> pDevices(20);
- bstr_ptr bstrDeviceID;
- bstr_ptr bstrClassName;
- bstr_ptr bstrNamespace;
- DWORD uReturned = 0;
- UINT iDevice;
- variant_wrapper var;
- HRESULT hr;
+ xinput_deviceids.clear();
- // CoInit if needed
- CoInitialize(nullptr);
+ HRESULT hr;
// Create WMI
+ Microsoft::WRL::ComPtr<IWbemLocator> pIWbemLocator;
hr = CoCreateInstance(
- __uuidof(WbemLocator),
- nullptr,
- CLSCTX_INPROC_SERVER,
- __uuidof(IWbemLocator),
- reinterpret_cast<void**>(pIWbemLocator.GetAddressOf()));
-
- if (FAILED(hr) || pIWbemLocator == nullptr)
+ __uuidof(WbemLocator),
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ __uuidof(IWbemLocator),
+ reinterpret_cast<void **>(pIWbemLocator.GetAddressOf()));
+ if (FAILED(hr) || !pIWbemLocator)
{
osd_printf_error("Creating WbemLocator failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
// Create BSTRs for WMI
- bstrNamespace = bstr_ptr(SysAllocString(L"\\\\.\\root\\cimv2"));
- bstrDeviceID = bstr_ptr(SysAllocString(L"DeviceID"));
- bstrClassName = bstr_ptr(SysAllocString(L"Win32_PNPEntity"));
+ bstr_ptr bstrNamespace = bstr_ptr(SysAllocString(L"\\\\.\\root\\cimv2"));
+ bstr_ptr bstrDeviceID = bstr_ptr(SysAllocString(L"DeviceID"));
+ bstr_ptr bstrClassName = bstr_ptr(SysAllocString(L"Win32_PNPEntity"));
// Connect to WMI
+ Microsoft::WRL::ComPtr<IWbemServices> pIWbemServices;
hr = pIWbemLocator->ConnectServer(
- bstrNamespace.get(),
- nullptr,
- nullptr,
- nullptr,
- 0L,
- nullptr,
- nullptr,
- pIWbemServices.GetAddressOf());
-
- if (FAILED(hr) || pIWbemServices == nullptr)
+ bstrNamespace.get(),
+ nullptr,
+ nullptr,
+ nullptr,
+ 0L,
+ nullptr,
+ nullptr,
+ pIWbemServices.GetAddressOf());
+ if (FAILED(hr) || !pIWbemServices)
{
osd_printf_error("Connecting to WMI Server failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
@@ -371,38 +328,41 @@ private:
// Switch security level to IMPERSONATE
(void)CoSetProxyBlanket(
- pIWbemServices.Get(),
- RPC_C_AUTHN_WINNT,
- RPC_C_AUTHZ_NONE,
- nullptr,
- RPC_C_AUTHN_LEVEL_CALL,
- RPC_C_IMP_LEVEL_IMPERSONATE,
- nullptr,
- 0);
+ pIWbemServices.Get(),
+ RPC_C_AUTHN_WINNT,
+ RPC_C_AUTHZ_NONE,
+ nullptr,
+ RPC_C_AUTHN_LEVEL_CALL,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ nullptr,
+ 0);
// Get list of Win32_PNPEntity devices
+ Microsoft::WRL::ComPtr<IEnumWbemClassObject> pEnumDevices;
hr = pIWbemServices->CreateInstanceEnum(bstrClassName.get(), 0, nullptr, pEnumDevices.GetAddressOf());
- if (FAILED(hr) || pEnumDevices == nullptr)
+ if (FAILED(hr) || !pEnumDevices)
{
osd_printf_error("Getting list of Win32_PNPEntity devices failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
// Loop over all devices
- for (; ; )
+ ComArray<IWbemClassObject> pDevices(20);
+ variant_wrapper var;
+ for ( ; ; )
{
// Get a few at a time
+ DWORD uReturned = 0;
hr = pEnumDevices->Next(10000, pDevices.Size(), pDevices.ReleaseAndGetAddressOf(), &uReturned);
if (FAILED(hr))
{
osd_printf_error("Enumerating WMI classes failed. Error: 0x%X\n", static_cast<unsigned int>(hr));
return hr;
}
-
if (uReturned == 0)
break;
- for (iDevice = 0; iDevice < uReturned; iDevice++)
+ for (UINT iDevice = 0; iDevice < uReturned; iDevice++)
{
if (!pDevices[iDevice])
continue;
@@ -416,19 +376,18 @@ private:
if (wcsstr(var.Get().bstrVal, L"IG_"))
{
// If it does, then get the VID/PID from var.bstrVal
- DWORD dwPid = 0, dwVid = 0;
- WCHAR* strVid = wcsstr(var.Get().bstrVal, L"VID_");
+ DWORD dwVid = 0;
+ WCHAR const *const strVid = wcsstr(var.Get().bstrVal, L"VID_");
if (strVid && swscanf(strVid, L"VID_%4X", &dwVid) != 1)
dwVid = 0;
- WCHAR* strPid = wcsstr(var.Get().bstrVal, L"PID_");
+ DWORD dwPid = 0;
+ WCHAR const *const strPid = wcsstr(var.Get().bstrVal, L"PID_");
if (strPid && swscanf(strPid, L"PID_%4X", &dwPid) != 1)
dwPid = 0;
- DWORD dwVidPid = MAKELONG(dwVid, dwPid);
-
- // Add the VID/PID to a linked list
- xinput_id_list.push_back(dwVidPid);
+ // Add the VID/PID to a list
+ xinput_deviceids.push_back(MAKELONG(dwVid, dwPid));
}
}
}
@@ -441,8 +400,16 @@ private:
}
};
-#else
-MODULE_NOT_SUPPORTED(winhybrid_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "winhybrid")
-#endif
+} // anonymous namespace
+
+} // namespace osd
+
+#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
+
+#include "input_module.h"
+
+namespace osd { namespace { MODULE_NOT_SUPPORTED(winhybrid_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "winhybrid") } }
+
+#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
-MODULE_DEFINITION(JOYSTICKINPUT_WINHYBRID, winhybrid_joystick_module)
+MODULE_DEFINITION(JOYSTICKINPUT_WINHYBRID, osd::winhybrid_joystick_module)