mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-24 03:40:26 +00:00
Merge pull request #6166 from ligfx/invokedeviceschangedcallbacks
ControllerInterface: cleanup callbacks API and logic
This commit is contained in:
commit
4733bbd8f3
@ -37,7 +37,7 @@ void Initialize()
|
|||||||
s_config.CreateController<GCKeyboard>(i);
|
s_config.CreateController<GCKeyboard>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_controller_interface.RegisterHotplugCallback(LoadConfig);
|
g_controller_interface.RegisterDevicesChangedCallback(LoadConfig);
|
||||||
|
|
||||||
// Load the saved controller config
|
// Load the saved controller config
|
||||||
s_config.LoadConfig(true);
|
s_config.LoadConfig(true);
|
||||||
|
@ -34,7 +34,7 @@ void Initialize()
|
|||||||
s_config.CreateController<GCPad>(i);
|
s_config.CreateController<GCPad>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_controller_interface.RegisterHotplugCallback(LoadConfig);
|
g_controller_interface.RegisterDevicesChangedCallback(LoadConfig);
|
||||||
|
|
||||||
// Load the saved controller config
|
// Load the saved controller config
|
||||||
s_config.LoadConfig(true);
|
s_config.LoadConfig(true);
|
||||||
|
@ -80,7 +80,7 @@ void Initialize(InitializeMode init_mode)
|
|||||||
s_config.CreateController<WiimoteEmu::Wiimote>(i);
|
s_config.CreateController<WiimoteEmu::Wiimote>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_controller_interface.RegisterHotplugCallback(LoadConfig);
|
g_controller_interface.RegisterDevicesChangedCallback(LoadConfig);
|
||||||
|
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ void Initialize()
|
|||||||
if (s_config.ControllersNeedToBeCreated())
|
if (s_config.ControllersNeedToBeCreated())
|
||||||
s_config.CreateController<HotkeyManager>();
|
s_config.CreateController<HotkeyManager>();
|
||||||
|
|
||||||
g_controller_interface.RegisterHotplugCallback(LoadConfig);
|
g_controller_interface.RegisterDevicesChangedCallback(LoadConfig);
|
||||||
|
|
||||||
// load the saved controller config
|
// load the saved controller config
|
||||||
s_config.LoadConfig(true);
|
s_config.LoadConfig(true);
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#ifdef CIFACE_USE_XINPUT
|
#ifdef CIFACE_USE_XINPUT
|
||||||
#include "InputCommon/ControllerInterface/XInput/XInput.h"
|
#include "InputCommon/ControllerInterface/XInput/XInput.h"
|
||||||
#endif
|
#endif
|
||||||
@ -45,6 +47,7 @@ void ControllerInterface::Initialize(void* const hwnd)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_hwnd = hwnd;
|
m_hwnd = hwnd;
|
||||||
|
m_is_populating_devices = true;
|
||||||
|
|
||||||
#ifdef CIFACE_USE_DINPUT
|
#ifdef CIFACE_USE_DINPUT
|
||||||
// nothing needed
|
// nothing needed
|
||||||
@ -86,6 +89,8 @@ void ControllerInterface::RefreshDevices()
|
|||||||
m_devices.clear();
|
m_devices.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_is_populating_devices = true;
|
||||||
|
|
||||||
#ifdef CIFACE_USE_DINPUT
|
#ifdef CIFACE_USE_DINPUT
|
||||||
ciface::DInput::PopulateDevices(reinterpret_cast<HWND>(m_hwnd));
|
ciface::DInput::PopulateDevices(reinterpret_cast<HWND>(m_hwnd));
|
||||||
#endif
|
#endif
|
||||||
@ -111,6 +116,9 @@ void ControllerInterface::RefreshDevices()
|
|||||||
#ifdef CIFACE_USE_PIPES
|
#ifdef CIFACE_USE_PIPES
|
||||||
ciface::Pipes::PopulateDevices();
|
ciface::Pipes::PopulateDevices();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_is_populating_devices = false;
|
||||||
|
InvokeDevicesChangedCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -165,30 +173,49 @@ void ControllerInterface::Shutdown()
|
|||||||
|
|
||||||
void ControllerInterface::AddDevice(std::shared_ptr<ciface::Core::Device> device)
|
void ControllerInterface::AddDevice(std::shared_ptr<ciface::Core::Device> device)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_devices_mutex);
|
|
||||||
// Try to find an ID for this device
|
|
||||||
int id = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
const auto it = std::find_if(m_devices.begin(), m_devices.end(), [&device, &id](const auto& d) {
|
std::lock_guard<std::mutex> lk(m_devices_mutex);
|
||||||
return d->GetSource() == device->GetSource() && d->GetName() == device->GetName() &&
|
// Try to find an ID for this device
|
||||||
d->GetId() == id;
|
int id = 0;
|
||||||
});
|
while (true)
|
||||||
if (it == m_devices.end()) // no device with the same name with this ID, so we can use it
|
{
|
||||||
break;
|
const auto it =
|
||||||
else
|
std::find_if(m_devices.begin(), m_devices.end(), [&device, &id](const auto& d) {
|
||||||
id++;
|
return d->GetSource() == device->GetSource() && d->GetName() == device->GetName() &&
|
||||||
|
d->GetId() == id;
|
||||||
|
});
|
||||||
|
if (it == m_devices.end()) // no device with the same name with this ID, so we can use it
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
device->SetId(id);
|
||||||
|
|
||||||
|
NOTICE_LOG(SERIALINTERFACE, "Added device: %s", device->GetQualifiedName().c_str());
|
||||||
|
m_devices.emplace_back(std::move(device));
|
||||||
}
|
}
|
||||||
device->SetId(id);
|
|
||||||
m_devices.emplace_back(std::move(device));
|
if (!m_is_populating_devices)
|
||||||
|
InvokeDevicesChangedCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerInterface::RemoveDevice(std::function<bool(const ciface::Core::Device*)> callback)
|
void ControllerInterface::RemoveDevice(std::function<bool(const ciface::Core::Device*)> callback)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_devices_mutex);
|
{
|
||||||
m_devices.erase(std::remove_if(m_devices.begin(), m_devices.end(),
|
std::lock_guard<std::mutex> lk(m_devices_mutex);
|
||||||
[&callback](const auto& dev) { return callback(dev.get()); }),
|
auto it = std::remove_if(m_devices.begin(), m_devices.end(), [&callback](const auto& dev) {
|
||||||
m_devices.end());
|
if (callback(dev.get()))
|
||||||
|
{
|
||||||
|
NOTICE_LOG(SERIALINTERFACE, "Removed device: %s", dev->GetQualifiedName().c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
m_devices.erase(it, m_devices.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_is_populating_devices)
|
||||||
|
InvokeDevicesChangedCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -208,23 +235,25 @@ void ControllerInterface::UpdateInput()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// RegisterHotplugCallback
|
// RegisterDevicesChangedCallback
|
||||||
//
|
//
|
||||||
// Register a callback to be called from the input backends' hotplug thread
|
// Register a callback to be called when a device is added or removed (as from the input backends'
|
||||||
// when there is a new device
|
// hotplug thread), or when devices are refreshed
|
||||||
//
|
//
|
||||||
void ControllerInterface::RegisterHotplugCallback(std::function<void()> callback)
|
void ControllerInterface::RegisterDevicesChangedCallback(std::function<void()> callback)
|
||||||
{
|
{
|
||||||
m_hotplug_callbacks.emplace_back(std::move(callback));
|
std::lock_guard<std::mutex> lk(m_callbacks_mutex);
|
||||||
|
m_devices_changed_callbacks.emplace_back(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// InvokeHotplugCallbacks
|
// InvokeDevicesChangedCallbacks
|
||||||
//
|
//
|
||||||
// Invoke all callbacks that were registered
|
// Invoke all callbacks that were registered
|
||||||
//
|
//
|
||||||
void ControllerInterface::InvokeHotplugCallbacks() const
|
void ControllerInterface::InvokeDevicesChangedCallbacks() const
|
||||||
{
|
{
|
||||||
for (const auto& callback : m_hotplug_callbacks)
|
std::lock_guard<std::mutex> lk(m_callbacks_mutex);
|
||||||
|
for (const auto& callback : m_devices_changed_callbacks)
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <mutex>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
|
||||||
#include "InputCommon/ControllerInterface/Device.h"
|
#include "InputCommon/ControllerInterface/Device.h"
|
||||||
|
|
||||||
// enable disable sources
|
// enable disable sources
|
||||||
@ -53,12 +51,14 @@ public:
|
|||||||
bool IsInit() const { return m_is_init; }
|
bool IsInit() const { return m_is_init; }
|
||||||
void UpdateInput();
|
void UpdateInput();
|
||||||
|
|
||||||
void RegisterHotplugCallback(std::function<void(void)> callback);
|
void RegisterDevicesChangedCallback(std::function<void(void)> callback);
|
||||||
void InvokeHotplugCallbacks() const;
|
void InvokeDevicesChangedCallbacks() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::function<void()>> m_hotplug_callbacks;
|
std::vector<std::function<void()>> m_devices_changed_callbacks;
|
||||||
|
mutable std::mutex m_callbacks_mutex;
|
||||||
bool m_is_init;
|
bool m_is_init;
|
||||||
|
std::atomic<bool> m_is_populating_devices{false};
|
||||||
void* m_hwnd;
|
void* m_hwnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "InputCommon/ControllerInterface/Device.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/Device.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
namespace ciface
|
namespace ciface
|
||||||
{
|
{
|
||||||
@ -39,6 +41,11 @@ void Device::AddOutput(Device::Output* const o)
|
|||||||
m_outputs.push_back(o);
|
m_outputs.push_back(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Device::GetQualifiedName() const
|
||||||
|
{
|
||||||
|
return StringFromFormat("%s/%i/%s", this->GetSource().c_str(), GetId(), this->GetName().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
Device::Input* Device::FindInput(const std::string& name) const
|
Device::Input* Device::FindInput(const std::string& name) const
|
||||||
{
|
{
|
||||||
for (Input* input : m_inputs)
|
for (Input* input : m_inputs)
|
||||||
|
@ -76,6 +76,7 @@ public:
|
|||||||
void SetId(int id) { m_id = id; }
|
void SetId(int id) { m_id = id; }
|
||||||
virtual std::string GetName() const = 0;
|
virtual std::string GetName() const = 0;
|
||||||
virtual std::string GetSource() const = 0;
|
virtual std::string GetSource() const = 0;
|
||||||
|
std::string GetQualifiedName() const;
|
||||||
virtual void UpdateInput() {}
|
virtual void UpdateInput() {}
|
||||||
virtual bool IsValid() const { return true; }
|
virtual bool IsValid() const { return true; }
|
||||||
const std::vector<Input*>& Inputs() const { return m_inputs; }
|
const std::vector<Input*>& Inputs() const { return m_inputs; }
|
||||||
|
@ -156,8 +156,6 @@ static void DeviceRemovalCallback(void* inContext, IOReturn inResult, void* inSe
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
g_controller_interface.InvokeHotplugCallbacks();
|
|
||||||
NOTICE_LOG(SERIALINTERFACE, "Removed device: %s", GetDeviceRefName(inIOHIDDeviceRef).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DeviceMatchingCallback(void* inContext, IOReturn inResult, void* inSender,
|
static void DeviceMatchingCallback(void* inContext, IOReturn inResult, void* inSender,
|
||||||
@ -174,9 +172,6 @@ static void DeviceMatchingCallback(void* inContext, IOReturn inResult, void* inS
|
|||||||
{
|
{
|
||||||
g_controller_interface.AddDevice(std::make_shared<Joystick>(inIOHIDDeviceRef, name));
|
g_controller_interface.AddDevice(std::make_shared<Joystick>(inIOHIDDeviceRef, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTICE_LOG(SERIALINTERFACE, "Added device: %s", name.c_str());
|
|
||||||
g_controller_interface.InvokeHotplugCallbacks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(void* window)
|
void Init(void* window)
|
||||||
|
@ -92,9 +92,7 @@ static void HotplugThreadFunc()
|
|||||||
g_controller_interface.RemoveDevice([&name](const auto& device) {
|
g_controller_interface.RemoveDevice([&name](const auto& device) {
|
||||||
return device->GetSource() == "evdev" && device->GetName() == name && !device->IsValid();
|
return device->GetSource() == "evdev" && device->GetName() == name && !device->IsValid();
|
||||||
});
|
});
|
||||||
NOTICE_LOG(SERIALINTERFACE, "Removed device: %s", name.c_str());
|
|
||||||
s_devnode_name_map.erase(devnode);
|
s_devnode_name_map.erase(devnode);
|
||||||
g_controller_interface.InvokeHotplugCallbacks();
|
|
||||||
}
|
}
|
||||||
// Only react to "device added" events for evdev devices that we can access.
|
// Only react to "device added" events for evdev devices that we can access.
|
||||||
else if (strcmp(action, "add") == 0 && access(devnode, W_OK) == 0)
|
else if (strcmp(action, "add") == 0 && access(devnode, W_OK) == 0)
|
||||||
@ -107,8 +105,6 @@ static void HotplugThreadFunc()
|
|||||||
{
|
{
|
||||||
g_controller_interface.AddDevice(std::move(device));
|
g_controller_interface.AddDevice(std::move(device));
|
||||||
s_devnode_name_map.insert(std::pair<std::string, std::string>(devnode, name));
|
s_devnode_name_map.insert(std::pair<std::string, std::string>(devnode, name));
|
||||||
NOTICE_LOG(SERIALINTERFACE, "Added new device: %s", name.c_str());
|
|
||||||
g_controller_interface.InvokeHotplugCallbacks();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
udev_device_unref(dev);
|
udev_device_unref(dev);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user