From f2b35fb5b480030cd6c56a9e2ccad17e71795dbb Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 20:40:20 +0930 Subject: [PATCH] Project64-input: Detect devices changed --- Source/Project64-input/CProject64Input.cpp | 12 +++++++ Source/Project64-input/CProject64Input.h | 1 + Source/Project64-input/DeviceNotification.cpp | 34 +++++++++++++++++++ Source/Project64-input/DeviceNotification.h | 23 +++++++++++++ Source/Project64-input/DirectInput.cpp | 27 ++++++++++++--- Source/Project64-input/DirectInput.h | 5 ++- 6 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 Source/Project64-input/DeviceNotification.cpp create mode 100644 Source/Project64-input/DeviceNotification.h diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index 76aa661ee..aa863958e 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -16,6 +16,15 @@ CProject64Input::~CProject64Input() { } +void CProject64Input::DevicesChanged(void) +{ + CGuard guard(m_CS); + if (m_DirectInput.get() != nullptr) + { + m_DirectInput->DevicesChanged(); + } +} + void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) { CGuard guard(m_CS); @@ -101,10 +110,13 @@ std::wstring CProject64Input::ButtonAssignment(BUTTON & Button) bool CProject64Input::SaveController(uint32_t ControlIndex) { + CGuard guard(m_CS); + if (ControlIndex >= sizeof(m_Controllers) / sizeof(m_Controllers[0])) { return false; } g_Settings->SaveController(ControlIndex, m_ControlInfo.Controls[ControlIndex], m_Controllers[ControlIndex]); + m_DirectInput->MapControllerDevice(m_Controllers[ControlIndex]); return true; } diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index 35749e8c0..ef705c907 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -11,6 +11,7 @@ public: CProject64Input(HINSTANCE hinst); ~CProject64Input(); + void DevicesChanged(void); void InitiateControllers(CONTROL_INFO * ControlInfo); void GetKeys(int32_t Control, BUTTONS * Keys); void StartScanDevices(int32_t DisplayCtrlId); diff --git a/Source/Project64-input/DeviceNotification.cpp b/Source/Project64-input/DeviceNotification.cpp new file mode 100644 index 000000000..6f67e74b4 --- /dev/null +++ b/Source/Project64-input/DeviceNotification.cpp @@ -0,0 +1,34 @@ +#include "DeviceNotification.h" +#include "CProject64Input.h" +#include + +DeviceNotification::DeviceNotification() +{ + Create(NULL); +} + +DeviceNotification::~DeviceNotification() +{ + DestroyWindow(); +} + +int DeviceNotification::OnCreate(LPCREATESTRUCT /*lpCreateStruct*/) +{ + DEV_BROADCAST_DEVICEINTERFACE notificationFilter = { 0 }; + notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + notificationFilter.dbcc_size = sizeof(notificationFilter); + + HDEVNOTIFY hDevNotify; + hDevNotify = RegisterDeviceNotification(m_hWnd, ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); + + return TRUE; +} + +BOOL DeviceNotification::OnDeviceChange(UINT nEventType, DWORD /*dwData*/) +{ + if (g_InputPlugin != nullptr && (nEventType == DBT_DEVICEARRIVAL || nEventType == DBT_DEVICEREMOVECOMPLETE)) + { + g_InputPlugin->DevicesChanged(); + } + return TRUE; +} diff --git a/Source/Project64-input/DeviceNotification.h b/Source/Project64-input/DeviceNotification.h new file mode 100644 index 000000000..592ba095a --- /dev/null +++ b/Source/Project64-input/DeviceNotification.h @@ -0,0 +1,23 @@ +#pragma once +#include "wtl.h" + +typedef CWinTraits DeviceNotificationTraits; + +class DeviceNotification : + public CWindowImpl +{ +public: + DECLARE_WND_CLASS(_T("My Window Class")) + + BEGIN_MSG_MAP(DeviceNotification) + MSG_WM_CREATE(OnCreate) + MSG_WM_DEVICECHANGE(OnDeviceChange) + END_MSG_MAP() + + DeviceNotification(); + ~DeviceNotification(); + +private: + int OnCreate(LPCREATESTRUCT lpCreateStruct); + BOOL OnDeviceChange(UINT nEventType, DWORD dwData); +}; \ No newline at end of file diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 851b74fd0..21c8a3795 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -1,5 +1,6 @@ #include "DirectInput.h" #include +#include CDirectInput::CDirectInput(HINSTANCE hinst) : m_hDirectInputDLL(nullptr), @@ -25,10 +26,7 @@ CDirectInput::CDirectInput(HINSTANCE hinst) : } } - if (m_pDIHandle != nullptr) - { - m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY); - } + RefreshDeviceList(); } } @@ -101,6 +99,12 @@ BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi) return DIENUM_CONTINUE; } + DEVICE_MAP::iterator itr = m_Devices.find(lpddi->guidInstance); + if (itr != m_Devices.end()) + { + return DIENUM_CONTINUE; + } + DEVICE Device = { 0 }; Device.didHandle = nullptr; Device.dwDevType = lpddi->dwDevType; @@ -207,7 +211,7 @@ std::wstring CDirectInput::ButtonAssignment(BUTTON & Button) return L"Keyboard: ???"; } } - else if (Button.BtnType == BTNTYPE_UNASSIGNED) + if (Button.BtnType == BTNTYPE_UNASSIGNED) { return L""; } @@ -287,6 +291,19 @@ void CDirectInput::UpdateDeviceData(void) } } +void CDirectInput::DevicesChanged(void) +{ + RefreshDeviceList(); +} + +void CDirectInput::RefreshDeviceList(void) +{ + if (m_pDIHandle != nullptr) + { + m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY); + } +} + CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton) { if (didHandle == nullptr) diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index 2e759d44a..1a91beaae 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -1,6 +1,7 @@ #pragma once #include "ControllerSpec1.1.h" #include "Button.h" +#include "DeviceNotification.h" #include "N64Controller.h" #define DIRECTINPUT_VERSION 0x0800 #include @@ -28,6 +29,7 @@ public: bool IsButtonPressed(BUTTON & Button); int8_t AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range); void UpdateDeviceData(void); + void DevicesChanged(void); private: CDirectInput(); @@ -38,7 +40,7 @@ private: BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton); bool AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice); - void LoadConfig(void); + void RefreshDeviceList(void); typedef struct { @@ -63,6 +65,7 @@ private: }; typedef std::map DEVICE_MAP; + DeviceNotification m_DeviceNotification; DEVICE_MAP m_Devices; HMODULE m_hDirectInputDLL; LPDIRECTINPUT8 m_pDIHandle;