From 0d783f0869eaef163a318ab4d79744f592ed1cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 13 Jun 2016 11:11:47 +0200 Subject: ControllerInterface: Add a way to register callbacks This adds RegisterHotplugCallback() to register a callback which will be invoked by the input backends' hotplug threads when there is a new device, so that Core (GCKeyboard, GCPad, Wiimote, Hotkey) can reload the configuration without adding a dependency to Core from InputCommon. --- .../ControllerInterface/ControllerInterface.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp') diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 700d390b92..cc80b7b234 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -172,6 +172,28 @@ void ControllerInterface::UpdateInput() d->UpdateInput(); } +// +// RegisterHotplugCallback +// +// Register a callback to be called from the input backends' hotplug thread +// when there is a new device +// +void ControllerInterface::RegisterHotplugCallback(std::function callback) +{ + m_hotplug_callbacks.emplace_back(std::move(callback)); +} + +// +// InvokeHotplugCallbacks +// +// Invoke all callbacks that were registered +// +void ControllerInterface::InvokeHotplugCallbacks() const +{ + for (const auto& callback : m_hotplug_callbacks) + callback(); +} + // // InputReference :: State // -- cgit v1.2.3 From 93f5df419521171c11e16d6a8ff84b9d0d8fd6c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 14 Jul 2016 17:45:59 +0200 Subject: ControllerInterface: Add RemoveDevice() This adds RemoveDevice() to ControllerInterface, fixes ExpressionParser and some other code to support device removals without crashing, and adds an IsValid() method to Device, to prepare for hotplugging. --- .../Core/InputCommon/ControllerInterface/ControllerInterface.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp') diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index cc80b7b234..cf726698f1 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -160,6 +160,14 @@ void ControllerInterface::AddDevice(std::shared_ptr device m_devices.emplace_back(std::move(device)); } +void ControllerInterface::RemoveDevice(std::function callback) +{ + std::lock_guard lk(m_devices_mutex); + m_devices.erase(std::remove_if(m_devices.begin(), m_devices.end(), + [&callback](const auto& dev) { return callback(dev.get()); }), + m_devices.end()); +} + // // UpdateInput // -- cgit v1.2.3 From 3926db624d5ab2f959e67eb2369f1fe5f0f9543a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 15 Jul 2016 11:34:18 +0200 Subject: ControllerInterface: Don't block on UpdateInput() Changes UpdateInput() to skip if we can't lock the mutex, instead of potentially blocking the CPU thread and causing a short but noticeable frame drop. --- .../InputCommon/ControllerInterface/ControllerInterface.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp') diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index cf726698f1..9c7a08428e 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -175,9 +175,13 @@ void ControllerInterface::RemoveDevice(std::function lk(m_devices_mutex); - for (const auto& d : m_devices) - d->UpdateInput(); + // Don't block the UI or CPU thread (to avoid a short but noticeable frame drop) + if (m_devices_mutex.try_lock()) + { + std::lock_guard lk(m_devices_mutex, std::adopt_lock); + for (const auto& d : m_devices) + d->UpdateInput(); + } } // -- cgit v1.2.3 From 135641404af9c52e433ef28dba4f86fa208f4365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 14 Jul 2016 17:50:35 +0200 Subject: evdev: Add hotplugging support This adds hotplugging support to the evdev input backend. We use libudev to monitor changes to input devices in a separate thread. Removed devices are removed from the devices list, and new devices are added to the list. The effect is that controllers are usable immediately after plugging them without having to manually refresh devices (if they were configured to be used, of course). --- .../ControllerInterface/ControllerInterface.cpp | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp') diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 9c7a08428e..f1e62e73cf 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -106,17 +106,6 @@ void ControllerInterface::Shutdown() if (!m_is_init) return; - std::lock_guard lk(m_devices_mutex); - - for (const auto& d : m_devices) - { - // Set outputs to ZERO before destroying device - for (ciface::Core::Device::Output* o : d->Outputs()) - o->SetState(0); - } - - m_devices.clear(); - #ifdef CIFACE_USE_XINPUT ciface::XInput::DeInit(); #endif @@ -136,6 +125,20 @@ void ControllerInterface::Shutdown() #ifdef CIFACE_USE_ANDROID // nothing needed #endif +#ifdef CIFACE_USE_EVDEV + ciface::evdev::Shutdown(); +#endif + + std::lock_guard lk(m_devices_mutex); + + for (const auto& d : m_devices) + { + // Set outputs to ZERO before destroying device + for (ciface::Core::Device::Output* o : d->Outputs()) + o->SetState(0); + } + + m_devices.clear(); m_is_init = false; } -- cgit v1.2.3