Skip to content

Commit

Permalink
RMG-Input: detect devices using serial and path instead of device index
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosalie241 committed Jan 24, 2025
1 parent 8312b2a commit 0b3d705
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 149 deletions.
6 changes: 6 additions & 0 deletions Source/RMG-Core/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,12 @@ static l_Setting get_setting(SettingsID settingId)
case SettingsID::Input_DeviceNum:
setting = {"", "DeviceNum"};
break;
case SettingsID::Input_DevicePath:
setting = {"", "DevicePath"};
break;
case SettingsID::Input_DeviceSerial:
setting = {"", "DeviceSerial"};
break;
case SettingsID::Input_Deadzone:
setting = {"", "Deadzone"};
break;
Expand Down
2 changes: 2 additions & 0 deletions Source/RMG-Core/Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ enum class SettingsID
Input_DeviceType,
Input_DeviceName,
Input_DeviceNum,
Input_DevicePath,
Input_DeviceSerial,
Input_Deadzone,
Input_Sensitivity,
Input_Pak,
Expand Down
31 changes: 26 additions & 5 deletions Source/RMG-Input/Thread/SDLThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,43 @@ void SDLThread::run(void)
// force re-fresh joystick list
SDL_JoystickUpdate();

QString name;
QString path;
QString serial;

SDL_GameController* controller;
SDL_Joystick* joystick;

for (int i = 0; i < SDL_NumJoysticks(); i++)
{
const char* name;

if (SDL_IsGameController(i))
{
name = SDL_GameControllerNameForIndex(i);
controller = SDL_GameControllerOpen(i);
if (controller == nullptr)
{ // skip invalid controllers
continue;
}
name = SDL_GameControllerName(controller);
path = SDL_GameControllerPath(controller);
serial = SDL_GameControllerGetSerial(controller);
SDL_GameControllerClose(controller);
}
else
{
name = SDL_JoystickNameForIndex(i);
joystick = SDL_JoystickOpen(i);
if (joystick == nullptr)
{ // skip invalid joysticks
continue;
}
name = SDL_JoystickName(joystick);
path = SDL_JoystickPath(joystick);
serial = SDL_JoystickGetSerial(joystick);
SDL_JoystickClose(joystick);
}

if (name != nullptr)
{
emit this->OnInputDeviceFound(QString(name), i);
emit this->OnInputDeviceFound(name, path, serial, i);
}
}
this->currentAction = SDLThreadAction::None;
Expand Down
2 changes: 1 addition & 1 deletion Source/RMG-Input/Thread/SDLThread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SDLThread : public QThread
SDLThreadAction currentAction = SDLThreadAction::None;

signals:
void OnInputDeviceFound(QString, int);
void OnInputDeviceFound(QString name, QString path, QString serial, int number);
void OnDeviceSearchFinished(void);
};
} // namespace Thread
Expand Down
85 changes: 43 additions & 42 deletions Source/RMG-Input/UserInterface/MainDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
#include <SDL.h>
#include <QTimer>

Q_DECLARE_METATYPE(SDLDevice);

using namespace UserInterface;

MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romConfig) : QDialog(parent)
{
qRegisterMetaType<SDLDevice>();

this->setupUi(this);
this->setWindowIcon(QIcon(":Resource/RMG.png"));

Expand Down Expand Up @@ -65,12 +69,12 @@ MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romCo
// so we only have to expose it there
if (controllerWidget == this->controllerWidgets.last())
{
controllerWidget->AddInputDevice("Voice Recognition Unit", (int)InputDeviceType::EmulateVRU);
controllerWidget->AddInputDevice({"Voice Recognition Unit", "", "", (int)InputDeviceType::EmulateVRU});
}
#endif // VRU
controllerWidget->AddInputDevice("None", (int)InputDeviceType::None);
controllerWidget->AddInputDevice("Automatic", (int)InputDeviceType::Automatic);
controllerWidget->AddInputDevice("Keyboard", (int)InputDeviceType::Keyboard);
controllerWidget->AddInputDevice({"None", "", "", (int)InputDeviceType::None});
controllerWidget->AddInputDevice({"Automatic", "", "", (int)InputDeviceType::Automatic});
controllerWidget->AddInputDevice({"Keyboard", "", "", (int)InputDeviceType::Keyboard});
controllerWidget->SetInitialized(true);
}

Expand All @@ -87,73 +91,71 @@ MainDialog::~MainDialog()
this->closeInputDevice();
}

void MainDialog::addInputDevice(QString deviceName, int deviceNum)
void MainDialog::addInputDevice(SDLDevice device)
{
for (auto& controllerWidget : this->controllerWidgets)
{
controllerWidget->AddInputDevice(deviceName, deviceNum);
controllerWidget->AddInputDevice(device);
}
}

void MainDialog::removeInputDevice(QString deviceName, int deviceNum)
void MainDialog::removeInputDevice(SDLDevice device)
{
for (auto& controllerWidget : this->controllerWidgets)
{
controllerWidget->RemoveInputDevice(deviceName, deviceNum);
controllerWidget->RemoveInputDevice(device);
}
}

void MainDialog::openInputDevice(QString deviceName, int deviceNum)
void MainDialog::openInputDevice(SDLDevice device)
{
SDL_JoystickID joystickId;
Widget::ControllerWidget* controllerWidget;
controllerWidget = this->controllerWidgets.at(this->tabWidget->currentIndex());

// we don't need to open a keyboard or VRU
if (deviceNum == (int)InputDeviceType::None ||
deviceNum == (int)InputDeviceType::Keyboard ||
deviceNum == (int)InputDeviceType::EmulateVRU)
if (device.number == (int)InputDeviceType::None ||
device.number == (int)InputDeviceType::Keyboard ||
device.number == (int)InputDeviceType::EmulateVRU)
{
this->currentDeviceName = "";
this->currentDeviceNum = deviceNum;
controllerWidget->SetCurrentJoystickID(this->currentDeviceNum);
this->currentDevice = { "", "", "", device.number };
controllerWidget->SetCurrentJoystickID(this->currentDevice.number);
controllerWidget->SetCurrentJoystick(nullptr, nullptr);
return;
}

// handle automatic mode
if (deviceNum == (int)InputDeviceType::Automatic)
if (device.number == (int)InputDeviceType::Automatic)
{
int currentIndex = this->tabWidget->currentIndex();
if (currentIndex < this->inputDeviceList.size())
{ // use device when there's one
deviceNum = this->inputDeviceList.at(currentIndex).deviceNum;
device.number = this->inputDeviceList.at(currentIndex).number;
}
else
{ // no device found, fallback to keyboard
this->currentDeviceName = "";
this->currentDeviceNum = (int)InputDeviceType::Keyboard;
controllerWidget->SetCurrentJoystickID(this->currentDeviceNum);
this->currentDevice = { "", "", "", (int)InputDeviceType::Keyboard };
controllerWidget->SetCurrentJoystickID(this->currentDevice.number);
controllerWidget->SetCurrentJoystick(nullptr, nullptr);
return;
}
}

int controllerMode = CoreSettingsGetIntValue(SettingsID::Input_ControllerMode);
if ((controllerMode == 0 && SDL_IsGameController(deviceNum) == SDL_TRUE) ||
if ((controllerMode == 0 && SDL_IsGameController(device.number) == SDL_TRUE) ||
(controllerMode == 2))
{
this->currentJoystick = nullptr;
this->currentController = SDL_GameControllerOpen(deviceNum);
this->currentController = SDL_GameControllerOpen(device.number);
}
else if (controllerMode == 0 || controllerMode == 1)
{
this->currentJoystick = SDL_JoystickOpen(deviceNum);
this->currentJoystick = SDL_JoystickOpen(device.number);
this->currentController = nullptr;
}

this->currentDeviceNum = deviceNum;
joystickId = SDL_JoystickGetDeviceInstanceID(deviceNum);
this->currentDevice = device;
joystickId = SDL_JoystickGetDeviceInstanceID(device.number);
controllerWidget->SetCurrentJoystickID(joystickId);
controllerWidget->SetIsCurrentJoystickGameController(currentController != nullptr);
controllerWidget->SetCurrentJoystick(this->currentJoystick, this->currentController);
Expand Down Expand Up @@ -208,7 +210,7 @@ void MainDialog::on_InputPollTimer_triggered()
(this->currentController != nullptr && !SDL_GameControllerGetAttached(this->currentController)))
{
this->closeInputDevice();
this->openInputDevice(this->currentDeviceName, this->currentDeviceNum);
this->openInputDevice(this->currentDevice);
}

// process SDL events
Expand All @@ -221,7 +223,7 @@ void MainDialog::on_InputPollTimer_triggered()
controllerWidget->on_MainDialog_SdlEventPollFinished();
}

void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget* widget, QString deviceName, int deviceNum)
void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget* widget, SDLDevice device)
{
Widget::ControllerWidget* currentWidget;
currentWidget = controllerWidgets.at(this->tabWidget->currentIndex());
Expand All @@ -236,11 +238,11 @@ void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*
this->closeInputDevice();

// only open device when needed
if (deviceNum != (int)InputDeviceType::None &&
deviceNum != (int)InputDeviceType::Keyboard &&
deviceNum != (int)InputDeviceType::EmulateVRU)
if (device.number != (int)InputDeviceType::None &&
device.number != (int)InputDeviceType::Keyboard &&
device.number != (int)InputDeviceType::EmulateVRU)
{
this->openInputDevice(deviceName, deviceNum);
this->openInputDevice(device);
}
}

Expand Down Expand Up @@ -274,8 +276,7 @@ void MainDialog::on_ControllerWidget_UserProfileRemoved(QString name, QString se

void MainDialog::on_tabWidget_currentChanged(int index)
{
QString deviceName;
int deviceNum;
SDLDevice device;
Widget::ControllerWidget* controllerWidget;

// save previous tab's user profile
Expand All @@ -299,20 +300,20 @@ void MainDialog::on_tabWidget_currentChanged(int index)
controllerWidget->LoadUserProfileSettings();

// retrieve current input device
controllerWidget->GetCurrentInputDevice(deviceName, deviceNum);
controllerWidget->GetCurrentInputDevice(device);

// only open device when needed
if (deviceNum != (int)InputDeviceType::None &&
deviceNum != (int)InputDeviceType::Keyboard &&
deviceNum != (int)InputDeviceType::EmulateVRU)
if (device.number != (int)InputDeviceType::None &&
device.number != (int)InputDeviceType::Keyboard &&
device.number != (int)InputDeviceType::EmulateVRU)
{
this->openInputDevice(deviceName, deviceNum);
this->openInputDevice(device);
}
}

void MainDialog::on_SDLThread_DeviceFound(QString deviceName, int deviceNum)
void MainDialog::on_SDLThread_DeviceFound(QString name, QString path, QString serial, int number)
{
inputDevice_t inputDevice = {deviceName, deviceNum};
SDLDevice inputDevice = {name.toStdString(), path.toStdString(), serial.toStdString(), number};
this->inputDeviceList.append(inputDevice);
}

Expand All @@ -324,14 +325,14 @@ void MainDialog::on_SDLThread_DeviceSearchFinished(void)
{
if (!this->oldInputDeviceList.contains(inputDevice))
{
this->addInputDevice(inputDevice.deviceName, inputDevice.deviceNum);
this->addInputDevice(inputDevice);
}
}
for (auto& inputDevice : this->oldInputDeviceList)
{
if (!this->inputDeviceList.contains(inputDevice))
{
this->removeInputDevice(inputDevice.deviceName, inputDevice.deviceNum);
this->removeInputDevice(inputDevice);
}
}

Expand Down
30 changes: 9 additions & 21 deletions Source/RMG-Input/UserInterface/MainDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define MAINDIALOG_HPP

#include <QDialog>
#include "common.hpp"

#include "ui_MainDialog.h"
#include "Widget/ControllerWidget.hpp"
Expand All @@ -23,39 +24,26 @@ class MainDialog : public QDialog, private Ui::MainDialog
{
Q_OBJECT
private:
struct inputDevice_t
{
QString deviceName;
int deviceNum;

bool operator== (inputDevice_t other) const
{
return other.deviceNum == deviceNum &&
other.deviceName == deviceName;
}
};

QTimer* inputPollTimer;
Thread::SDLThread* sdlThread;

QList<inputDevice_t> oldInputDeviceList;
QList<inputDevice_t> inputDeviceList;
QList<SDLDevice> oldInputDeviceList;
QList<SDLDevice> inputDeviceList;
bool updatingDeviceList = false;

QList<Widget::ControllerWidget*> controllerWidgets;
SDL_Joystick* currentJoystick = nullptr;
SDL_GameController* currentController = nullptr;
QString currentDeviceName;
int currentDeviceNum = 0;
SDLDevice currentDevice;

int previousTabWidgetIndex = 0;

EventFilter* eventFilter;

void addInputDevice(QString, int);
void removeInputDevice(QString, int);
void addInputDevice(SDLDevice device);
void removeInputDevice(SDLDevice device);

void openInputDevice(QString, int);
void openInputDevice(SDLDevice device);
void closeInputDevice();

public:
Expand All @@ -65,15 +53,15 @@ Q_OBJECT
public slots:
void on_InputPollTimer_triggered();

void on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*, QString, int);
void on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*, SDLDevice);
void on_ControllerWidget_RefreshInputDevicesButtonClicked();

void on_ControllerWidget_UserProfileAdded(QString, QString);
void on_ControllerWidget_UserProfileRemoved(QString, QString);

void on_tabWidget_currentChanged(int);

void on_SDLThread_DeviceFound(QString, int);
void on_SDLThread_DeviceFound(QString, QString, QString, int);
void on_SDLThread_DeviceSearchFinished(void);

private slots:
Expand Down
Loading

0 comments on commit 0b3d705

Please sign in to comment.