mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
osd/modules/input: Modernised interface for enumerating DirectInput devices.
Gets rid of some state in the winhybrid joystick module that's only used during initialisation.
This commit is contained in:
parent
b13a5d971f
commit
deceecfbfb
@ -125,12 +125,6 @@ namespace osd {
|
||||
|
||||
namespace {
|
||||
|
||||
BOOL CALLBACK device_enum_interface_callback(LPCDIDEVICEINSTANCE instance, LPVOID ref)
|
||||
{
|
||||
return static_cast<device_enum_interface *>(ref)->device_enum_callback(instance);
|
||||
}
|
||||
|
||||
|
||||
std::string guid_to_string(GUID const &guid)
|
||||
{
|
||||
// size of a GUID string with dashes plus NUL terminator
|
||||
@ -307,11 +301,8 @@ void dinput_mouse_device::configure(input_device &device)
|
||||
// dinput_module - base DirectInput module
|
||||
//============================================================
|
||||
|
||||
class dinput_module : public input_module_impl<dinput_device, osd_common_t>, public device_enum_interface
|
||||
class dinput_module : public input_module_impl<dinput_device, osd_common_t>
|
||||
{
|
||||
protected:
|
||||
std::unique_ptr<dinput_api_helper> m_dinput_helper;
|
||||
|
||||
public:
|
||||
dinput_module(const char* type, const char* name) :
|
||||
input_module_impl<dinput_device, osd_common_t>(type, name),
|
||||
@ -343,13 +334,18 @@ public:
|
||||
{
|
||||
input_module_impl<dinput_device, osd_common_t>::input_init(machine);
|
||||
|
||||
HRESULT result = m_dinput_helper->enum_attached_devices(dinput_devclass(), *this);
|
||||
HRESULT const result = m_dinput_helper->enum_attached_devices(
|
||||
dinput_devclass(),
|
||||
[this] (LPCDIDEVICEINSTANCE instance) { return device_enum_callback(instance); });
|
||||
if (result != DI_OK)
|
||||
fatalerror("DirectInput: Unable to enumerate devices (result=%08X)\n", uint32_t(result));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int dinput_devclass() = 0;
|
||||
virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) = 0;
|
||||
|
||||
std::unique_ptr<dinput_api_helper> m_dinput_helper;
|
||||
};
|
||||
|
||||
|
||||
@ -361,6 +357,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int dinput_devclass() override
|
||||
{
|
||||
return DI8DEVCLASS_KEYBOARD;
|
||||
@ -392,6 +389,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int dinput_devclass() override
|
||||
{
|
||||
return DI8DEVCLASS_POINTER;
|
||||
@ -438,6 +436,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int dinput_devclass() override
|
||||
{
|
||||
return DI8DEVCLASS_GAMECTRL;
|
||||
@ -1212,12 +1211,6 @@ int dinput_api_helper::initialize()
|
||||
}
|
||||
|
||||
|
||||
HRESULT dinput_api_helper::enum_attached_devices(int devclass, device_enum_interface &enumerate_interface) const
|
||||
{
|
||||
return m_dinput->EnumDevices(devclass, device_enum_interface_callback, &enumerate_interface, DIEDFL_ATTACHEDONLY);
|
||||
}
|
||||
|
||||
|
||||
std::pair<Microsoft::WRL::ComPtr<IDirectInputDevice8>, LPCDIDATAFORMAT> dinput_api_helper::open_device(
|
||||
LPCDIDEVICEINSTANCE instance,
|
||||
LPCDIDATAFORMAT format1,
|
||||
|
@ -37,14 +37,6 @@ namespace osd {
|
||||
// dinput_device - base directinput device
|
||||
//============================================================
|
||||
|
||||
class device_enum_interface
|
||||
{
|
||||
public:
|
||||
virtual ~device_enum_interface() = default;
|
||||
|
||||
virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) = 0;
|
||||
};
|
||||
|
||||
enum class dinput_cooperative_level
|
||||
{
|
||||
FOREGROUND,
|
||||
@ -92,7 +84,18 @@ public:
|
||||
format);
|
||||
}
|
||||
|
||||
HRESULT enum_attached_devices(int devclass, device_enum_interface &enumerate_interface) const;
|
||||
template <typename T>
|
||||
HRESULT enum_attached_devices(int devclass, T &&callback) const
|
||||
{
|
||||
return m_dinput->EnumDevices(
|
||||
devclass,
|
||||
[] (LPCDIDEVICEINSTANCE instance, LPVOID ref) -> BOOL
|
||||
{
|
||||
return (*reinterpret_cast<T *>(ref))(instance);
|
||||
},
|
||||
reinterpret_cast<LPVOID>(&callback),
|
||||
DIEDFL_ATTACHEDONLY);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static HRESULT set_dword_property(
|
||||
|
@ -121,12 +121,11 @@ typedef std::unique_ptr<OLECHAR, bstr_deleter> bstr_ptr;
|
||||
// winhybrid_joystick_module
|
||||
//============================================================
|
||||
|
||||
class winhybrid_joystick_module : public input_module_impl<device_info, osd_common_t>, public device_enum_interface
|
||||
class winhybrid_joystick_module : public input_module_impl<device_info, osd_common_t>
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<xinput_api_helper> m_xinput_helper;
|
||||
std::unique_ptr<dinput_api_helper> m_dinput_helper;
|
||||
std::vector<DWORD> m_xinput_deviceids;
|
||||
|
||||
public:
|
||||
winhybrid_joystick_module() :
|
||||
@ -166,60 +165,65 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual BOOL device_enum_callback(LPCDIDEVICEINSTANCE instance) override
|
||||
{
|
||||
// First check if this device is XInput compatible.
|
||||
// If so, don't add it here as it'll be picked up by Xinput.
|
||||
if (is_xinput_device(instance->guidProduct))
|
||||
{
|
||||
osd_printf_verbose("Skipping DirectInput for XInput compatible joystick %S.\n", instance->tszInstanceName);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
virtual void input_init(running_machine &machine) override
|
||||
{
|
||||
input_module_impl<device_info, osd_common_t>::input_init(machine);
|
||||
|
||||
bool xinput_detect_failed = false;
|
||||
HRESULT result = get_xinput_devices();
|
||||
std::vector<DWORD> xinput_deviceids;
|
||||
HRESULT result = get_xinput_devices(xinput_deviceids);
|
||||
if (result != 0)
|
||||
{
|
||||
xinput_detect_failed = true;
|
||||
m_xinput_deviceids.clear();
|
||||
xinput_deviceids.clear();
|
||||
osd_printf_warning("XInput device detection failed. XInput won't be used. Error: 0x%X\n", uint32_t(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);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 game controllers (result=%08X).\n", uint32_t(result));
|
||||
|
||||
@ -273,19 +277,6 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns true if the DirectInput device is also an XInput device.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool is_xinput_device(GUID const &pGuidProductFromDirectInput) const
|
||||
{
|
||||
// Check each xinput device to see if this device's vid/pid matches
|
||||
auto const found = std::find(
|
||||
m_xinput_deviceids.begin(),
|
||||
m_xinput_deviceids.end(),
|
||||
pGuidProductFromDirectInput.Data1);
|
||||
return m_xinput_deviceids.end() != found;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Enum each PNP device using WMI and check each device ID to see if it contains
|
||||
// "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it's an XInput device
|
||||
@ -293,9 +284,9 @@ private:
|
||||
// Checking against a VID/PID of 0x028E/0x045E won't find 3rd party or future
|
||||
// XInput devices.
|
||||
//-----------------------------------------------------------------------------
|
||||
HRESULT get_xinput_devices()
|
||||
HRESULT get_xinput_devices(std::vector<DWORD> &xinput_deviceids)
|
||||
{
|
||||
m_xinput_deviceids.clear();
|
||||
xinput_deviceids.clear();
|
||||
|
||||
// CoInit if needed
|
||||
class com_helper
|
||||
@ -419,7 +410,7 @@ private:
|
||||
dwPid = 0;
|
||||
|
||||
// Add the VID/PID to a list
|
||||
m_xinput_deviceids.push_back(MAKELONG(dwVid, dwPid));
|
||||
xinput_deviceids.push_back(MAKELONG(dwVid, dwPid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,12 +435,13 @@ HRESULT sound_direct_sound::dsound_init()
|
||||
{
|
||||
// make a format description for what we want
|
||||
WAVEFORMATEX stream_format;
|
||||
stream_format.wBitsPerSample = 16;
|
||||
stream_format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
stream_format.nChannels = 2;
|
||||
stream_format.nSamplesPerSec = m_sample_rate;
|
||||
stream_format.wBitsPerSample = 16;
|
||||
stream_format.nBlockAlign = stream_format.wBitsPerSample * stream_format.nChannels / 8;
|
||||
stream_format.nAvgBytesPerSec = stream_format.nSamplesPerSec * stream_format.nBlockAlign;
|
||||
stream_format.cbSize = 0;
|
||||
|
||||
// compute the buffer size based on the output sample rate
|
||||
int audio_latency = std::max(m_audio_latency, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user