mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 09:05:47 -04:00
Introduce ControllerInterface class, port SDL interface over
This breaks controller support in the SDL frontend until it's ported over to the common interface.
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
#include "inputbindingwidgets.h"
|
||||
#include "core/settings.h"
|
||||
#include "frontend-common/sdl_controller_interface.h"
|
||||
#include "frontend-common/controller_interface.h"
|
||||
#include "qthostinterface.h"
|
||||
#include "qtutils.h"
|
||||
#include <QtCore/QTimer>
|
||||
@ -130,33 +130,41 @@ bool InputButtonBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
||||
|
||||
void InputButtonBindingWidget::hookControllerInput()
|
||||
{
|
||||
ControllerInterface* controller_interface = m_host_interface->getControllerInterface();
|
||||
if (!controller_interface)
|
||||
return;
|
||||
|
||||
m_host_interface->enableBackgroundControllerPolling();
|
||||
g_sdl_controller_interface.SetHook([this](const SDLControllerInterface::Hook& ei) {
|
||||
if (ei.type == SDLControllerInterface::Hook::Type::Axis)
|
||||
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) {
|
||||
if (ei.type == ControllerInterface::Hook::Type::Axis)
|
||||
{
|
||||
// wait until it's at least half pushed so we don't get confused between axises with small movement
|
||||
if (std::abs(ei.value) < 0.5f)
|
||||
return SDLControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
|
||||
// TODO: this probably should consider the "last value"
|
||||
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
|
||||
Q_ARG(int, ei.button_or_axis_number), Q_ARG(bool, ei.value > 0));
|
||||
return SDLControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
}
|
||||
else if (ei.type == SDLControllerInterface::Hook::Type::Button && ei.value > 0.0f)
|
||||
else if (ei.type == ControllerInterface::Hook::Type::Button && ei.value > 0.0f)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "bindToControllerButton", Q_ARG(int, ei.controller_index),
|
||||
Q_ARG(int, ei.button_or_axis_number));
|
||||
return SDLControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
}
|
||||
|
||||
return SDLControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
});
|
||||
}
|
||||
|
||||
void InputButtonBindingWidget::unhookControllerInput()
|
||||
{
|
||||
g_sdl_controller_interface.ClearHook();
|
||||
ControllerInterface* controller_interface = m_host_interface->getControllerInterface();
|
||||
if (!controller_interface)
|
||||
return;
|
||||
|
||||
controller_interface->ClearHook();
|
||||
m_host_interface->disableBackgroundControllerPolling();
|
||||
}
|
||||
|
||||
@ -200,26 +208,34 @@ InputAxisBindingWidget::~InputAxisBindingWidget()
|
||||
|
||||
void InputAxisBindingWidget::hookControllerInput()
|
||||
{
|
||||
ControllerInterface* controller_interface = m_host_interface->getControllerInterface();
|
||||
if (!controller_interface)
|
||||
return;
|
||||
|
||||
m_host_interface->enableBackgroundControllerPolling();
|
||||
g_sdl_controller_interface.SetHook([this](const SDLControllerInterface::Hook& ei) {
|
||||
if (ei.type == SDLControllerInterface::Hook::Type::Axis)
|
||||
controller_interface->SetHook([this](const ControllerInterface::Hook& ei) {
|
||||
if (ei.type == ControllerInterface::Hook::Type::Axis)
|
||||
{
|
||||
// wait until it's at least half pushed so we don't get confused between axises with small movement
|
||||
if (std::abs(ei.value) < 0.5f)
|
||||
return SDLControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
|
||||
QMetaObject::invokeMethod(this, "bindToControllerAxis", Q_ARG(int, ei.controller_index),
|
||||
Q_ARG(int, ei.button_or_axis_number));
|
||||
return SDLControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::StopMonitoring;
|
||||
}
|
||||
|
||||
return SDLControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
return ControllerInterface::Hook::CallbackResult::ContinueMonitoring;
|
||||
});
|
||||
}
|
||||
|
||||
void InputAxisBindingWidget::unhookControllerInput()
|
||||
{
|
||||
g_sdl_controller_interface.ClearHook();
|
||||
ControllerInterface* controller_interface = m_host_interface->getControllerInterface();
|
||||
if (!controller_interface)
|
||||
return;
|
||||
|
||||
controller_interface->ClearHook();
|
||||
m_host_interface->disableBackgroundControllerPolling();
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ QtHostInterface::QtHostInterface(QObject* parent)
|
||||
{
|
||||
qRegisterMetaType<SystemBootParameters>();
|
||||
|
||||
// TODO: This probably should wait until the thread finishes initializing.
|
||||
loadSettings();
|
||||
createThread();
|
||||
}
|
||||
@ -45,6 +46,23 @@ QtHostInterface::~QtHostInterface()
|
||||
stopThread();
|
||||
}
|
||||
|
||||
bool QtHostInterface::Initialize()
|
||||
{
|
||||
if (!CommonHostInterface::Initialize())
|
||||
return false;
|
||||
|
||||
if (m_controller_interface)
|
||||
m_controller_interface->PollEvents();
|
||||
|
||||
updateInputMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtHostInterface::Shutdown()
|
||||
{
|
||||
CommonHostInterface::Shutdown();
|
||||
}
|
||||
|
||||
void QtHostInterface::ReportError(const char* message)
|
||||
{
|
||||
HostInterface::ReportError(message);
|
||||
@ -77,19 +95,19 @@ bool QtHostInterface::ConfirmMessage(const char* message)
|
||||
|
||||
QVariant QtHostInterface::getSettingValue(const QString& name, const QVariant& default_value)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||
return m_qsettings.value(name, default_value);
|
||||
}
|
||||
|
||||
void QtHostInterface::putSettingValue(const QString& name, const QVariant& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||
m_qsettings.setValue(name, value);
|
||||
}
|
||||
|
||||
void QtHostInterface::removeSettingValue(const QString& name)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||
m_qsettings.remove(name);
|
||||
}
|
||||
|
||||
@ -101,10 +119,10 @@ void QtHostInterface::setDefaultSettings()
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||
QtSettingsInterface si(m_qsettings);
|
||||
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
||||
UpdateInputMap(si);
|
||||
CommonHostInterface::UpdateInputMap(si);
|
||||
}
|
||||
|
||||
void QtHostInterface::applySettings()
|
||||
@ -115,10 +133,10 @@ void QtHostInterface::applySettings()
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||
QtSettingsInterface si(m_qsettings);
|
||||
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
||||
UpdateInputMap(si);
|
||||
CommonHostInterface::UpdateInputMap(si);
|
||||
}
|
||||
|
||||
void QtHostInterface::loadSettings()
|
||||
@ -143,7 +161,7 @@ void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool
|
||||
{
|
||||
Assert(!isOnWorkerThread());
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
||||
QtSettingsInterface si(m_qsettings);
|
||||
m_game_list->SetSearchDirectoriesFromSettings(si);
|
||||
|
||||
@ -348,13 +366,9 @@ void QtHostInterface::OnSystemStateSaved(bool global, s32 slot)
|
||||
emit stateSaved(QString::fromStdString(m_system->GetRunningCode()), global, slot);
|
||||
}
|
||||
|
||||
void QtHostInterface::OnControllerTypeChanged(u32 slot)
|
||||
void QtHostInterface::UpdateInputMap()
|
||||
{
|
||||
HostInterface::OnControllerTypeChanged(slot);
|
||||
|
||||
// this assumes the settings mutex is already locked - as it comes from updateSettings().
|
||||
QtSettingsInterface si(m_qsettings);
|
||||
UpdateInputMap(si);
|
||||
updateInputMap();
|
||||
}
|
||||
|
||||
void QtHostInterface::updateInputMap()
|
||||
@ -365,9 +379,9 @@ void QtHostInterface::updateInputMap()
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_qsettings_mutex);
|
||||
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
||||
QtSettingsInterface si(m_qsettings);
|
||||
UpdateInputMap(si);
|
||||
CommonHostInterface::UpdateInputMap(si);
|
||||
}
|
||||
|
||||
void QtHostInterface::powerOffSystem()
|
||||
@ -613,7 +627,7 @@ void QtHostInterface::enableBackgroundControllerPolling()
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_background_controller_polling_enable_count++ > 0)
|
||||
if (!m_controller_interface || m_background_controller_polling_enable_count++ > 0)
|
||||
return;
|
||||
|
||||
if (!m_system || m_paused)
|
||||
@ -621,7 +635,7 @@ void QtHostInterface::enableBackgroundControllerPolling()
|
||||
createBackgroundControllerPollTimer();
|
||||
|
||||
// drain the event queue so we don't get events late
|
||||
g_sdl_controller_interface.PumpSDLEvents();
|
||||
m_controller_interface->PollEvents();
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,7 +648,7 @@ void QtHostInterface::disableBackgroundControllerPolling()
|
||||
}
|
||||
|
||||
Assert(m_background_controller_polling_enable_count > 0);
|
||||
if (--m_background_controller_polling_enable_count > 0)
|
||||
if (!m_controller_interface || --m_background_controller_polling_enable_count > 0)
|
||||
return;
|
||||
|
||||
if (!m_system || m_paused)
|
||||
@ -643,7 +657,7 @@ void QtHostInterface::disableBackgroundControllerPolling()
|
||||
|
||||
void QtHostInterface::doBackgroundControllerPoll()
|
||||
{
|
||||
g_sdl_controller_interface.PumpSDLEvents();
|
||||
m_controller_interface->PollEvents();
|
||||
}
|
||||
|
||||
void QtHostInterface::createBackgroundControllerPollTimer()
|
||||
@ -689,9 +703,8 @@ void QtHostInterface::threadEntryPoint()
|
||||
m_worker_thread_event_loop = new QEventLoop();
|
||||
|
||||
// set up controller interface and immediate poll to pick up the controller attached events
|
||||
g_sdl_controller_interface.Initialize(this);
|
||||
g_sdl_controller_interface.PumpSDLEvents();
|
||||
updateInputMap();
|
||||
if (!Initialize())
|
||||
Panic("Failed to initialize host interface");
|
||||
|
||||
// TODO: Event which flags the thread as ready
|
||||
while (!m_shutdown_flag.load())
|
||||
@ -711,14 +724,12 @@ void QtHostInterface::threadEntryPoint()
|
||||
m_system->Throttle();
|
||||
|
||||
m_worker_thread_event_loop->processEvents(QEventLoop::AllEvents);
|
||||
g_sdl_controller_interface.PumpSDLEvents();
|
||||
if (m_controller_interface)
|
||||
m_controller_interface->PollEvents();
|
||||
}
|
||||
|
||||
m_system.reset();
|
||||
m_audio_stream.reset();
|
||||
|
||||
g_sdl_controller_interface.Shutdown();
|
||||
|
||||
Shutdown();
|
||||
|
||||
delete m_worker_thread_event_loop;
|
||||
m_worker_thread_event_loop = nullptr;
|
||||
|
||||
|
@ -28,7 +28,7 @@ class QtDisplayWidget;
|
||||
|
||||
Q_DECLARE_METATYPE(SystemBootParameters);
|
||||
|
||||
class QtHostInterface : public QObject, private CommonHostInterface
|
||||
class QtHostInterface final : public QObject, private CommonHostInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -36,6 +36,9 @@ public:
|
||||
explicit QtHostInterface(QObject* parent = nullptr);
|
||||
~QtHostInterface();
|
||||
|
||||
bool Initialize() override;
|
||||
void Shutdown() override;
|
||||
|
||||
void ReportError(const char* message) override;
|
||||
void ReportMessage(const char* message) override;
|
||||
bool ConfirmMessage(const char* message) override;
|
||||
@ -50,6 +53,7 @@ public:
|
||||
void refreshGameList(bool invalidate_cache = false, bool invalidate_database = false);
|
||||
|
||||
ALWAYS_INLINE const HotkeyInfoList& getHotkeyInfoList() const { return GetHotkeyInfoList(); }
|
||||
ALWAYS_INLINE ControllerInterface* getControllerInterface() const { return GetControllerInterface(); }
|
||||
|
||||
ALWAYS_INLINE bool isOnWorkerThread() const { return QThread::currentThread() == m_worker_thread; }
|
||||
|
||||
@ -125,7 +129,8 @@ protected:
|
||||
void OnSystemPerformanceCountersUpdated() override;
|
||||
void OnRunningGameChanged() override;
|
||||
void OnSystemStateSaved(bool global, s32 slot) override;
|
||||
void OnControllerTypeChanged(u32 slot) override;
|
||||
|
||||
void UpdateInputMap() override;
|
||||
|
||||
private:
|
||||
enum : u32
|
||||
@ -161,7 +166,7 @@ private:
|
||||
void wakeThread();
|
||||
|
||||
QSettings m_qsettings;
|
||||
std::mutex m_qsettings_mutex;
|
||||
std::recursive_mutex m_qsettings_mutex;
|
||||
|
||||
MainWindow* m_main_window = nullptr;
|
||||
QtDisplayWidget* m_display_widget = nullptr;
|
||||
|
Reference in New Issue
Block a user