mirror of
https://github.com/Rosalie241/RMG.git
synced 2026-07-11 01:24:01 +02:00
RMG-Input: migrate to SDL3
This commit is contained in:
@@ -10,8 +10,7 @@ set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
|
||||
find_package(Qt6 COMPONENTS Gui Widgets Core Svg REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SDL2 REQUIRED sdl2)
|
||||
find_package(SDL3 REQUIRED)
|
||||
|
||||
set(RMG_INPUT_SOURCES
|
||||
UserInterface/Widget/ControllerWidget.ui
|
||||
@@ -29,8 +28,7 @@ set(RMG_INPUT_SOURCES
|
||||
UserInterface/MainDialog.ui
|
||||
UserInterface/MainDialog.cpp
|
||||
UserInterface/UIResources.qrc
|
||||
Utilities/QtKeyToSdl2Key.cpp
|
||||
Utilities/InputDevice.cpp
|
||||
Utilities/QtKeyToSdl3Key.cpp
|
||||
Thread/SDLThread.cpp
|
||||
Thread/HotkeysThread.cpp
|
||||
main.cpp
|
||||
@@ -46,13 +44,12 @@ endif(VRU)
|
||||
|
||||
add_library(RMG-Input SHARED ${RMG_INPUT_SOURCES})
|
||||
|
||||
target_link_libraries(RMG-Input RMG-Core ${SDL2_LIBRARIES})
|
||||
target_link_libraries(RMG-Input RMG-Core SDL3::SDL3)
|
||||
|
||||
target_include_directories(RMG-Input PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(RMG-Input Qt6::Gui Qt6::Widgets Qt6::Svg)
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "SDLThread.hpp"
|
||||
#include "main.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <RMG-Core/m64p/api/m64p_types.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
using namespace Thread;
|
||||
|
||||
@@ -61,49 +63,77 @@ void SDLThread::run(void)
|
||||
case SDLThreadAction::GetInputDevices:
|
||||
{
|
||||
// force re-fresh joystick list
|
||||
SDL_JoystickUpdate();
|
||||
SDL_UpdateJoysticks();
|
||||
|
||||
QString name;
|
||||
QString path;
|
||||
QString serial;
|
||||
QString errorMessage;
|
||||
|
||||
SDL_GameController* controller;
|
||||
SDL_Gamepad* controller;
|
||||
SDL_Joystick* joystick;
|
||||
|
||||
for (int i = 0; i < SDL_NumJoysticks(); i++)
|
||||
int joysticksCount = 0;
|
||||
SDL_JoystickID* joysticks = SDL_GetJoysticks(&joysticksCount);
|
||||
if (joysticks == nullptr)
|
||||
{
|
||||
if (SDL_IsGameController(i))
|
||||
errorMessage = "SDLThread::run() SDL_GetJoysticks Failed: ";
|
||||
errorMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, errorMessage.toStdString());
|
||||
|
||||
// ensure count is reset
|
||||
joysticksCount = 0;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < joysticksCount; i++)
|
||||
{
|
||||
SDL_JoystickID joystickId = joysticks[i];
|
||||
|
||||
if (SDL_IsGamepad(joystickId))
|
||||
{
|
||||
controller = SDL_GameControllerOpen(i);
|
||||
controller = SDL_OpenGamepad(joystickId);
|
||||
if (controller == nullptr)
|
||||
{ // skip invalid controllers
|
||||
errorMessage = "SDLThread::run(): SDL_OpenGamepad Failed: ";
|
||||
errorMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, errorMessage.toStdString());
|
||||
continue;
|
||||
}
|
||||
name = SDL_GameControllerName(controller);
|
||||
path = SDL_GameControllerPath(controller);
|
||||
serial = SDL_GameControllerGetSerial(controller);
|
||||
SDL_GameControllerClose(controller);
|
||||
name = SDL_GetGamepadName(controller);
|
||||
path = SDL_GetGamepadPath(controller);
|
||||
serial = SDL_GetGamepadSerial(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
joystick = SDL_JoystickOpen(i);
|
||||
joystick = SDL_OpenJoystick(joystickId);
|
||||
if (joystick == nullptr)
|
||||
{ // skip invalid joysticks
|
||||
errorMessage = "SDLThread::run(): SDL_OpenJoystick Failed: ";
|
||||
errorMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, errorMessage.toStdString());
|
||||
continue;
|
||||
}
|
||||
name = SDL_JoystickName(joystick);
|
||||
path = SDL_JoystickPath(joystick);
|
||||
serial = SDL_JoystickGetSerial(joystick);
|
||||
SDL_JoystickClose(joystick);
|
||||
name = SDL_GetJoystickName(joystick);
|
||||
path = SDL_GetJoystickPath(joystick);
|
||||
serial = SDL_GetJoystickSerial(joystick);
|
||||
SDL_CloseJoystick(joystick);
|
||||
}
|
||||
|
||||
if (name != nullptr)
|
||||
{
|
||||
emit this->OnInputDeviceFound(name, path, serial, i);
|
||||
emit this->OnInputDeviceFound(name, path, serial, joystickId);
|
||||
}
|
||||
}
|
||||
|
||||
this->currentAction = SDLThreadAction::None;
|
||||
emit this->OnDeviceSearchFinished();
|
||||
|
||||
if (joysticks != nullptr)
|
||||
{
|
||||
SDL_free(joysticks);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#ifndef SDLTHREAD_HPP
|
||||
#define SDLTHREAD_HPP
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <QThread>
|
||||
|
||||
enum class SDLThreadAction
|
||||
@@ -40,7 +41,7 @@ private:
|
||||
SDLThreadAction currentAction = SDLThreadAction::None;
|
||||
|
||||
signals:
|
||||
void OnInputDeviceFound(QString name, QString path, QString serial, int number);
|
||||
void OnInputDeviceFound(QString name, QString path, QString serial, SDL_JoystickID joystickId);
|
||||
void OnDeviceSearchFinished(void);
|
||||
};
|
||||
} // namespace Thread
|
||||
|
||||
@@ -105,15 +105,15 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
default:
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||
{
|
||||
SDL_JoystickID joystickId = -1;
|
||||
InputType inputType = InputType::Invalid;
|
||||
int sdlButton = 0;
|
||||
QString sdlButtonName;
|
||||
|
||||
if (event->type == SDL_CONTROLLERBUTTONDOWN)
|
||||
if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN)
|
||||
{ // gamepad button
|
||||
if (!this->isCurrentJoystickGameController &&
|
||||
this->filterEventsForButtons)
|
||||
@@ -121,10 +121,10 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->cbutton.which;
|
||||
joystickId = event->gbutton.which;
|
||||
inputType = InputType::GamepadButton;
|
||||
sdlButton = event->cbutton.button;
|
||||
sdlButtonName = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)sdlButton);
|
||||
sdlButton = event->gbutton.button;
|
||||
sdlButtonName = SDL_GetGamepadStringForButton((SDL_GamepadButton)sdlButton);
|
||||
}
|
||||
else
|
||||
{ // joystick button
|
||||
@@ -157,12 +157,12 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||
{
|
||||
SDL_JoystickID joystickId = -1;
|
||||
|
||||
if (event->type == SDL_CONTROLLERBUTTONUP)
|
||||
if (event->type == SDL_EVENT_GAMEPAD_BUTTON_UP)
|
||||
{ // gamepad button
|
||||
if (!this->isCurrentJoystickGameController &&
|
||||
this->filterEventsForButtons)
|
||||
@@ -170,7 +170,7 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->cbutton.which;
|
||||
joystickId = event->gbutton.which;
|
||||
}
|
||||
else
|
||||
{ // joystick button
|
||||
@@ -198,8 +198,8 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_JOYAXISMOTION:
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||
{ // gamepad & joystick axis
|
||||
SDL_JoystickID joystickId = -1;
|
||||
InputType inputType = InputType::Invalid;
|
||||
@@ -207,7 +207,7 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
int sdlAxisValue = 0;
|
||||
QString sdlAxisName;
|
||||
|
||||
if (event->type == SDL_CONTROLLERAXISMOTION)
|
||||
if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION)
|
||||
{ // gamepad axis
|
||||
if (!this->isCurrentJoystickGameController &&
|
||||
this->filterEventsForButtons)
|
||||
@@ -215,11 +215,11 @@ void HotkeysDialog::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->caxis.which;
|
||||
joystickId = event->gaxis.which;
|
||||
inputType = InputType::GamepadAxis;
|
||||
sdlAxis = event->caxis.axis;
|
||||
sdlAxisValue = event->caxis.value;
|
||||
sdlAxisName = SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)sdlAxis);
|
||||
sdlAxis = event->gaxis.axis;
|
||||
sdlAxisValue = event->gaxis.value;
|
||||
sdlAxisName = SDL_GetGamepadStringForAxis((SDL_GamepadAxis)sdlAxis);
|
||||
sdlAxisName += sdlAxisValue > 0 ? "+" : "-";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <QDialog>
|
||||
#include <string>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <RMG-Core/Settings.hpp>
|
||||
|
||||
|
||||
@@ -9,20 +9,20 @@
|
||||
*/
|
||||
#include "MainDialog.hpp"
|
||||
#include "Widget/ControllerWidget.hpp"
|
||||
#include "Utilities/QtKeyToSdl2Key.hpp"
|
||||
#include "Utilities/QtKeyToSdl3Key.hpp"
|
||||
|
||||
#include <RMG-Core/Core.hpp>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <QTimer>
|
||||
|
||||
Q_DECLARE_METATYPE(SDLDevice);
|
||||
Q_DECLARE_METATYPE(InputDevice);
|
||||
|
||||
using namespace UserInterface;
|
||||
|
||||
MainDialog::MainDialog(QWidget* parent, Thread::SDLThread* sdlThread, bool romConfig, CoreRomHeader romHeader, CoreRomSettings romSettings) : QDialog(parent)
|
||||
{
|
||||
qRegisterMetaType<SDLDevice>();
|
||||
qRegisterMetaType<InputDevice>();
|
||||
|
||||
this->setupUi(this);
|
||||
|
||||
@@ -68,12 +68,14 @@ 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", "", "", static_cast<int>(InputDeviceType::EmulateVRU)});
|
||||
controllerWidget->AddInputDevice({ InputDeviceType::EmulateVRU, "Voice Recognition Unit" });
|
||||
}
|
||||
#endif // VRU
|
||||
controllerWidget->AddInputDevice({"None", "", "", static_cast<int>(InputDeviceType::None)});
|
||||
controllerWidget->AddInputDevice({"Automatic", "", "", static_cast<int>(InputDeviceType::Automatic)});
|
||||
controllerWidget->AddInputDevice({"Keyboard", "", "", static_cast<int>(InputDeviceType::Keyboard)});
|
||||
controllerWidget->SetAllowKeyboardForAutomatic(controllerWidget == this->controllerWidgets.first());
|
||||
|
||||
controllerWidget->AddInputDevice({ InputDeviceType::None, "None" });
|
||||
controllerWidget->AddInputDevice({ InputDeviceType::Automatic, "Automatic" });
|
||||
controllerWidget->AddInputDevice({ InputDeviceType::Keyboard, "Keyboard" });
|
||||
controllerWidget->SetInitialized(true);
|
||||
}
|
||||
|
||||
@@ -90,7 +92,7 @@ MainDialog::~MainDialog()
|
||||
this->closeInputDevice();
|
||||
}
|
||||
|
||||
void MainDialog::addInputDevice(SDLDevice device)
|
||||
void MainDialog::addInputDevice(const InputDevice& device)
|
||||
{
|
||||
for (auto& controllerWidget : this->controllerWidgets)
|
||||
{
|
||||
@@ -98,7 +100,7 @@ void MainDialog::addInputDevice(SDLDevice device)
|
||||
}
|
||||
}
|
||||
|
||||
void MainDialog::removeInputDevice(SDLDevice device)
|
||||
void MainDialog::removeInputDevice(const InputDevice& device)
|
||||
{
|
||||
for (auto& controllerWidget : this->controllerWidgets)
|
||||
{
|
||||
@@ -106,56 +108,53 @@ void MainDialog::removeInputDevice(SDLDevice device)
|
||||
}
|
||||
}
|
||||
|
||||
void MainDialog::openInputDevice(SDLDevice device)
|
||||
void MainDialog::openInputDevice(InputDevice 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 (device.number == static_cast<int>(InputDeviceType::None) ||
|
||||
device.number == static_cast<int>(InputDeviceType::Keyboard) ||
|
||||
device.number == static_cast<int>(InputDeviceType::EmulateVRU))
|
||||
// we don't need to open a non-joystick device
|
||||
if (device.type != InputDeviceType::Automatic &&
|
||||
device.type != InputDeviceType::Joystick)
|
||||
{
|
||||
this->currentDevice = { "", "", "", device.number };
|
||||
controllerWidget->SetCurrentJoystickID(this->currentDevice.number);
|
||||
this->currentDevice = { };
|
||||
controllerWidget->SetCurrentJoystickID(this->currentDevice.id);
|
||||
controllerWidget->SetCurrentJoystick(nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// handle automatic mode
|
||||
if (device.number == static_cast<int>(InputDeviceType::Automatic))
|
||||
if (device.type == InputDeviceType::Automatic)
|
||||
{
|
||||
int currentIndex = this->tabWidget->currentIndex();
|
||||
if (currentIndex < this->inputDeviceList.size())
|
||||
{ // use device when there's one
|
||||
device.number = this->inputDeviceList.at(currentIndex).number;
|
||||
device.id = this->inputDeviceList.at(currentIndex).id;
|
||||
}
|
||||
else
|
||||
{ // no device found, fallback to keyboard
|
||||
this->currentDevice = { "", "", "", static_cast<int>(InputDeviceType::Keyboard) };
|
||||
controllerWidget->SetCurrentJoystickID(this->currentDevice.number);
|
||||
this->currentDevice = { InputDeviceType::Keyboard, "Keyboard" };
|
||||
controllerWidget->SetCurrentJoystickID(this->currentDevice.id);
|
||||
controllerWidget->SetCurrentJoystick(nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int controllerMode = CoreSettingsGetIntValue(SettingsID::Input_ControllerMode);
|
||||
if ((controllerMode == 0 && SDL_IsGameController(device.number) == SDL_TRUE) ||
|
||||
if ((controllerMode == 0 && SDL_IsGamepad(device.id)) ||
|
||||
(controllerMode == 2))
|
||||
{
|
||||
this->currentJoystick = nullptr;
|
||||
this->currentController = SDL_GameControllerOpen(device.number);
|
||||
this->currentController = SDL_OpenGamepad(device.id);
|
||||
}
|
||||
else if (controllerMode == 0 || controllerMode == 1)
|
||||
{
|
||||
this->currentJoystick = SDL_JoystickOpen(device.number);
|
||||
this->currentJoystick = SDL_OpenJoystick(device.id);
|
||||
this->currentController = nullptr;
|
||||
}
|
||||
|
||||
this->currentDevice = device;
|
||||
joystickId = SDL_JoystickGetDeviceInstanceID(device.number);
|
||||
controllerWidget->SetCurrentJoystickID(joystickId);
|
||||
controllerWidget->SetCurrentJoystickID(device.id);
|
||||
controllerWidget->SetIsCurrentJoystickGameController(currentController != nullptr);
|
||||
controllerWidget->SetCurrentJoystick(this->currentJoystick, this->currentController);
|
||||
}
|
||||
@@ -164,13 +163,13 @@ void MainDialog::closeInputDevice()
|
||||
{
|
||||
if (this->currentJoystick != nullptr)
|
||||
{
|
||||
SDL_JoystickClose(this->currentJoystick);
|
||||
SDL_CloseJoystick(this->currentJoystick);
|
||||
this->currentJoystick = nullptr;
|
||||
}
|
||||
|
||||
if (this->currentController != nullptr)
|
||||
{
|
||||
SDL_GameControllerClose(this->currentController);
|
||||
SDL_CloseGamepad(this->currentController);
|
||||
this->currentController = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -205,8 +204,8 @@ void MainDialog::on_InputPollTimer_triggered()
|
||||
|
||||
// check if controller has been disconnected,
|
||||
// if so, keep trying to re-open it
|
||||
if ((this->currentJoystick != nullptr && !SDL_JoystickGetAttached(this->currentJoystick)) ||
|
||||
(this->currentController != nullptr && !SDL_GameControllerGetAttached(this->currentController)))
|
||||
if ((this->currentJoystick != nullptr && !SDL_JoystickConnected(this->currentJoystick)) ||
|
||||
(this->currentController != nullptr && !SDL_GamepadConnected(this->currentController)))
|
||||
{
|
||||
this->closeInputDevice();
|
||||
this->openInputDevice(this->currentDevice);
|
||||
@@ -214,7 +213,7 @@ void MainDialog::on_InputPollTimer_triggered()
|
||||
|
||||
// process SDL events
|
||||
SDL_Event event;
|
||||
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, 0, SDL_LASTEVENT) == 1)
|
||||
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) == 1)
|
||||
{
|
||||
controllerWidget->on_MainDialog_SdlEvent(&event);
|
||||
}
|
||||
@@ -222,7 +221,7 @@ void MainDialog::on_InputPollTimer_triggered()
|
||||
controllerWidget->on_MainDialog_SdlEventPollFinished();
|
||||
}
|
||||
|
||||
void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget* widget, SDLDevice device)
|
||||
void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget* widget, InputDevice device)
|
||||
{
|
||||
Widget::ControllerWidget* currentWidget;
|
||||
currentWidget = controllerWidgets.at(this->tabWidget->currentIndex());
|
||||
@@ -237,9 +236,8 @@ void MainDialog::on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*
|
||||
this->closeInputDevice();
|
||||
|
||||
// only open device when needed
|
||||
if (device.number != static_cast<int>(InputDeviceType::None) &&
|
||||
device.number != static_cast<int>(InputDeviceType::Keyboard) &&
|
||||
device.number != static_cast<int>(InputDeviceType::EmulateVRU))
|
||||
if (device.type == InputDeviceType::Automatic ||
|
||||
device.type == InputDeviceType::Joystick)
|
||||
{
|
||||
this->openInputDevice(device);
|
||||
}
|
||||
@@ -275,7 +273,7 @@ void MainDialog::on_ControllerWidget_UserProfileRemoved(QString name, QString se
|
||||
|
||||
void MainDialog::on_tabWidget_currentChanged(int index)
|
||||
{
|
||||
SDLDevice device;
|
||||
InputDevice device;
|
||||
Widget::ControllerWidget* controllerWidget;
|
||||
|
||||
// save previous tab's user profile
|
||||
@@ -302,17 +300,17 @@ void MainDialog::on_tabWidget_currentChanged(int index)
|
||||
controllerWidget->GetCurrentInputDevice(device);
|
||||
|
||||
// only open device when needed
|
||||
if (device.number != static_cast<int>(InputDeviceType::None) &&
|
||||
device.number != static_cast<int>(InputDeviceType::Keyboard) &&
|
||||
device.number != static_cast<int>(InputDeviceType::EmulateVRU))
|
||||
if (device.type == InputDeviceType::Automatic ||
|
||||
device.type == InputDeviceType::Joystick)
|
||||
{
|
||||
this->openInputDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
void MainDialog::on_SDLThread_DeviceFound(QString name, QString path, QString serial, int number)
|
||||
void MainDialog::on_SDLThread_DeviceFound(QString name, QString path, QString serial, SDL_JoystickID joystickId)
|
||||
{
|
||||
SDLDevice inputDevice = {name.toStdString(), path.toStdString(), serial.toStdString(), number};
|
||||
const InputDevice inputDevice = { InputDeviceType::Joystick, name.toStdString(),
|
||||
path.toStdString(), serial.toStdString(), joystickId };
|
||||
this->inputDeviceList.append(inputDevice);
|
||||
}
|
||||
|
||||
@@ -351,38 +349,38 @@ void MainDialog::on_SDLThread_DeviceSearchFinished(void)
|
||||
|
||||
void MainDialog::on_EventFilter_KeyPressed(QKeyEvent *event)
|
||||
{
|
||||
int key = Utilities::QtKeyToSdl2Key(event->key());
|
||||
int mod = Utilities::QtModKeyToSdl2ModKey(event->modifiers());
|
||||
int key = Utilities::QtKeyToSdl3Key(event->key());
|
||||
int mod = Utilities::QtModKeyToSdl3ModKey(event->modifiers());
|
||||
|
||||
SDL_KeyboardEvent keyboardEvent;
|
||||
keyboardEvent.state = SDL_PRESSED;
|
||||
keyboardEvent.type = SDL_KEYDOWN;
|
||||
keyboardEvent.keysym.scancode = (SDL_Scancode)key;
|
||||
keyboardEvent.keysym.sym = (SDL_Keycode)key;
|
||||
keyboardEvent.keysym.mod = mod;
|
||||
keyboardEvent.down = true;
|
||||
keyboardEvent.type = SDL_EVENT_KEY_DOWN;
|
||||
keyboardEvent.scancode = (SDL_Scancode)key;
|
||||
keyboardEvent.key = (SDL_Keycode)key;
|
||||
keyboardEvent.mod = mod;
|
||||
|
||||
SDL_Event sdlEvent;
|
||||
sdlEvent.key = keyboardEvent;
|
||||
sdlEvent.type = SDL_KEYDOWN;
|
||||
sdlEvent.type = SDL_EVENT_KEY_DOWN;
|
||||
|
||||
SDL_PeepEvents(&sdlEvent, 1, SDL_ADDEVENT, 0, 0);
|
||||
}
|
||||
|
||||
void MainDialog::on_EventFilter_KeyReleased(QKeyEvent *event)
|
||||
{
|
||||
int key = Utilities::QtKeyToSdl2Key(event->key());
|
||||
int mod = Utilities::QtModKeyToSdl2ModKey(event->modifiers());
|
||||
int key = Utilities::QtKeyToSdl3Key(event->key());
|
||||
int mod = Utilities::QtModKeyToSdl3ModKey(event->modifiers());
|
||||
|
||||
SDL_KeyboardEvent keyboardEvent;
|
||||
keyboardEvent.state = SDL_RELEASED;
|
||||
keyboardEvent.type = SDL_KEYUP;
|
||||
keyboardEvent.keysym.scancode = (SDL_Scancode)key;
|
||||
keyboardEvent.keysym.sym = (SDL_Keycode)key;
|
||||
keyboardEvent.keysym.mod = mod;
|
||||
keyboardEvent.down = false;
|
||||
keyboardEvent.type = SDL_EVENT_KEY_UP;
|
||||
keyboardEvent.scancode = (SDL_Scancode)key;
|
||||
keyboardEvent.key = (SDL_Keycode)key;
|
||||
keyboardEvent.mod = mod;
|
||||
|
||||
SDL_Event sdlEvent;
|
||||
sdlEvent.key = keyboardEvent;
|
||||
sdlEvent.type = SDL_KEYUP;
|
||||
sdlEvent.type = SDL_EVENT_KEY_UP;
|
||||
|
||||
SDL_PeepEvents(&sdlEvent, 1, SDL_ADDEVENT, 0, 0);
|
||||
}
|
||||
|
||||
@@ -31,23 +31,23 @@ private:
|
||||
QTimer* inputPollTimer;
|
||||
Thread::SDLThread* sdlThread;
|
||||
|
||||
QList<SDLDevice> oldInputDeviceList;
|
||||
QList<SDLDevice> inputDeviceList;
|
||||
QList<InputDevice> oldInputDeviceList;
|
||||
QList<InputDevice> inputDeviceList;
|
||||
bool updatingDeviceList = false;
|
||||
|
||||
QList<Widget::ControllerWidget*> controllerWidgets;
|
||||
SDL_Joystick* currentJoystick = nullptr;
|
||||
SDL_GameController* currentController = nullptr;
|
||||
SDLDevice currentDevice;
|
||||
SDL_Gamepad* currentController = nullptr;
|
||||
InputDevice currentDevice;
|
||||
|
||||
int previousTabWidgetIndex = 0;
|
||||
|
||||
EventFilter* eventFilter;
|
||||
|
||||
void addInputDevice(SDLDevice device);
|
||||
void removeInputDevice(SDLDevice device);
|
||||
void addInputDevice(const InputDevice& device);
|
||||
void removeInputDevice(const InputDevice& device);
|
||||
|
||||
void openInputDevice(SDLDevice device);
|
||||
void openInputDevice(InputDevice device);
|
||||
void closeInputDevice();
|
||||
|
||||
public:
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
public slots:
|
||||
void on_InputPollTimer_triggered();
|
||||
|
||||
void on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*, SDLDevice);
|
||||
void on_ControllerWidget_CurrentInputDeviceChanged(ControllerWidget*, InputDevice);
|
||||
void on_ControllerWidget_RefreshInputDevicesButtonClicked();
|
||||
|
||||
void on_ControllerWidget_UserProfileAdded(QString, QString);
|
||||
@@ -65,7 +65,7 @@ public slots:
|
||||
|
||||
void on_tabWidget_currentChanged(int);
|
||||
|
||||
void on_SDLThread_DeviceFound(QString, QString, QString, int);
|
||||
void on_SDLThread_DeviceFound(QString, QString, QString, SDL_JoystickID);
|
||||
void on_SDLThread_DeviceSearchFinished(void);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <RMG-Core/Emulation.hpp>
|
||||
#include <RMG-Core/Settings.hpp>
|
||||
@@ -21,7 +21,7 @@
|
||||
using namespace UserInterface;
|
||||
|
||||
OptionsDialog::OptionsDialog(QWidget* parent, OptionsDialogSettings settings,
|
||||
SDL_Joystick* joystick, SDL_GameController* controller) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
|
||||
SDL_Joystick* joystick, SDL_Gamepad* controller) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
|
||||
{
|
||||
this->setupUi(this);
|
||||
|
||||
@@ -123,9 +123,9 @@ void OptionsDialog::on_changeGameboySaveButton_clicked()
|
||||
|
||||
void OptionsDialog::on_testRumbleButton_clicked()
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2,0,18)
|
||||
if ((this->currentJoystick != nullptr && SDL_JoystickHasRumble(this->currentJoystick) != SDL_TRUE) ||
|
||||
(this->currentController != nullptr && SDL_GameControllerHasRumble(this->currentController) != SDL_TRUE))
|
||||
#if SDL_VERSION_ATLEAST(2,0,18) && !SDL_VERSION_ATLEAST(3,0,0) // TODO: port this to SDL3
|
||||
if ((this->currentJoystick != nullptr && SDL_JoystickHasRumble(this->currentJoystick) != true) ||
|
||||
(this->currentController != nullptr && SDL_GameControllerHasRumble(this->currentController) != true))
|
||||
{
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
@@ -139,10 +139,10 @@ void OptionsDialog::on_testRumbleButton_clicked()
|
||||
|
||||
if (this->currentJoystick != nullptr)
|
||||
{
|
||||
SDL_JoystickRumble(this->currentJoystick, 0xFFFF, 0xFFFF, 1500);
|
||||
SDL_RumbleJoystick(this->currentJoystick, 0xFFFF, 0xFFFF, 1500);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_GameControllerRumble(this->currentController, 0xFFFF, 0xFFFF, 1500);
|
||||
SDL_RumbleGamepad(this->currentController, 0xFFFF, 0xFFFF, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <QDialog>
|
||||
#include <string>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "ui_OptionsDialog.h"
|
||||
|
||||
@@ -38,7 +38,7 @@ Q_OBJECT
|
||||
|
||||
public:
|
||||
OptionsDialog(QWidget *parent, OptionsDialogSettings settings,
|
||||
SDL_Joystick* joystick, SDL_GameController* controller);
|
||||
SDL_Joystick* joystick, SDL_Gamepad* controller);
|
||||
|
||||
OptionsDialogSettings GetSettings();
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
OptionsDialogSettings settings;
|
||||
|
||||
SDL_Joystick* currentJoystick = nullptr;
|
||||
SDL_GameController* currentController = nullptr;
|
||||
SDL_Gamepad* currentController = nullptr;
|
||||
|
||||
void setIconsForEmulationInfoText(void);
|
||||
void hideEmulationInfoText(void);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
using namespace UserInterface::Widget;
|
||||
|
||||
@@ -245,10 +245,10 @@ void ControllerWidget::initializeMiscButtons()
|
||||
|
||||
bool ControllerWidget::isCurrentDeviceKeyboard()
|
||||
{
|
||||
SDLDevice device = this->inputDeviceComboBox->currentData().value<SDLDevice>();
|
||||
const InputDevice device = this->inputDeviceComboBox->currentData().value<InputDevice>();
|
||||
|
||||
return device.number == static_cast<int>(InputDeviceType::Automatic) ||
|
||||
device.number == static_cast<int>(InputDeviceType::Keyboard);
|
||||
return device.type == InputDeviceType::Keyboard ||
|
||||
(this->allowKeyboardForAutomatic && device.type == InputDeviceType::Automatic);
|
||||
}
|
||||
|
||||
bool ControllerWidget::isCurrentDeviceNotFound()
|
||||
@@ -410,15 +410,10 @@ bool ControllerWidget::hasAnySettingChanged(QString sectionQString)
|
||||
// retrieve data from settings
|
||||
bool settingsIsPluggedIn = CoreSettingsGetBoolValue(SettingsID::Input_PluggedIn, section);
|
||||
int settingsDeadZone = CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section);
|
||||
int settingsAnalogSensitivity = 100;
|
||||
int settingsAnalogSensitivity = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
|
||||
int settingsPak = CoreSettingsGetIntValue(SettingsID::Input_Pak, section);
|
||||
std::string settingsGameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section);
|
||||
std::string settingsGameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section);
|
||||
// account for profiles before v0.3.9
|
||||
if (CoreSettingsKeyExists(section, "Sensitivity"))
|
||||
{
|
||||
settingsAnalogSensitivity = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
|
||||
}
|
||||
|
||||
// retrieve current data
|
||||
bool currentIsPluggedIn = this->inputDeviceComboBox->currentText() != "None";
|
||||
@@ -504,27 +499,27 @@ void ControllerWidget::showErrorMessage(QString text, QString details)
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
void ControllerWidget::AddInputDevice(SDLDevice device)
|
||||
void ControllerWidget::AddInputDevice(const InputDevice& device)
|
||||
{
|
||||
QString deviceName = QString::fromStdString(device.name);
|
||||
QString name = deviceName;
|
||||
|
||||
if (device.number >= 0)
|
||||
if (device.type == InputDeviceType::Joystick)
|
||||
{
|
||||
name += " (";
|
||||
name += QString::number(device.number);
|
||||
name += QString::number(device.id);
|
||||
name += ")";
|
||||
}
|
||||
|
||||
this->inputDeviceNameList.append(deviceName);
|
||||
this->inputDeviceComboBox->addItem(name, QVariant::fromValue<SDLDevice>(device));
|
||||
this->inputDeviceComboBox->addItem(name, QVariant::fromValue<InputDevice>(device));
|
||||
}
|
||||
|
||||
void ControllerWidget::RemoveInputDevice(SDLDevice device)
|
||||
void ControllerWidget::RemoveInputDevice(const InputDevice& device)
|
||||
{
|
||||
inputDeviceNameList.removeOne(QString::fromStdString(device.name));
|
||||
|
||||
int index = this->inputDeviceComboBox->findData(QVariant::fromValue<SDLDevice>(device));
|
||||
int index = this->inputDeviceComboBox->findData(QVariant::fromValue<InputDevice>(device));
|
||||
if (index >= 0)
|
||||
{
|
||||
this->inputDeviceComboBox->removeItem(index);
|
||||
@@ -561,8 +556,37 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString)
|
||||
std::string deviceName = CoreSettingsGetStringValue(SettingsID::Input_DeviceName, section);
|
||||
std::string devicePath = CoreSettingsGetStringValue(SettingsID::Input_DevicePath, section);
|
||||
std::string deviceSerial = CoreSettingsGetStringValue(SettingsID::Input_DeviceSerial, section);
|
||||
int deviceNum = CoreSettingsGetIntValue(SettingsID::Input_DeviceNum, section);
|
||||
SDLDevice device = { deviceName, devicePath, deviceSerial, deviceNum };
|
||||
InputDeviceType deviceType;
|
||||
|
||||
// keep compatibility with <v0.8.1
|
||||
if (CoreSettingsKeyExists(section, "DeviceType"))
|
||||
{
|
||||
deviceType = static_cast<InputDeviceType>(CoreSettingsGetIntValue(SettingsID::Input_DeviceType, section));
|
||||
}
|
||||
else
|
||||
{
|
||||
int deviceNum = CoreSettingsGetIntValue(SettingsID::Input_DeviceNum, section);
|
||||
switch (deviceNum)
|
||||
{
|
||||
case -4:
|
||||
deviceType = InputDeviceType::EmulateVRU;
|
||||
break;
|
||||
case -3:
|
||||
deviceType = InputDeviceType::None;
|
||||
break;
|
||||
case -2:
|
||||
deviceType = InputDeviceType::Automatic;
|
||||
break;
|
||||
case -1:
|
||||
deviceType = InputDeviceType::Keyboard;
|
||||
break;
|
||||
default:
|
||||
deviceType = InputDeviceType::Joystick;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InputDevice device = { deviceType, deviceName, devicePath, deviceSerial };
|
||||
|
||||
// do nothing when input device combobox
|
||||
// is empty
|
||||
@@ -571,12 +595,6 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString)
|
||||
return;
|
||||
}
|
||||
|
||||
// account for old setting
|
||||
if (!isPluggedIn && deviceNum != static_cast<int>(InputDeviceType::None))
|
||||
{
|
||||
device = { "None", "", "", static_cast<int>(InputDeviceType::None) };
|
||||
}
|
||||
|
||||
// clear (not found) devices first
|
||||
int notFoundIndex = this->inputDeviceComboBox->findText("(not found)", Qt::MatchFlag::MatchEndsWith);
|
||||
if (notFoundIndex != -1)
|
||||
@@ -585,26 +603,14 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString)
|
||||
this->inputDeviceComboBox->removeItem(notFoundIndex);
|
||||
}
|
||||
|
||||
int deviceNameIndex = this->inputDeviceComboBox->findText(QString::fromStdString(deviceName), Qt::MatchFlag::MatchStartsWith);
|
||||
int deviceIndex = -1;
|
||||
int deviceSerialIndex = -1;
|
||||
bool needCompatibility = deviceNum >= 0 && devicePath.empty() && deviceSerial.empty();
|
||||
|
||||
int count = this->inputDeviceComboBox->count();
|
||||
for (int i = 0; i < count; i++)
|
||||
for (int i = 0; i < this->inputDeviceComboBox->count(); i++)
|
||||
{
|
||||
SDLDevice otherDevice = this->inputDeviceComboBox->itemData(i).value<SDLDevice>();
|
||||
if (needCompatibility)
|
||||
{ // backwards compatibility with <v0.7.2
|
||||
if (device.name == otherDevice.name &&
|
||||
device.number == otherDevice.number)
|
||||
{
|
||||
deviceIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (device.name == otherDevice.name &&
|
||||
device.serial == otherDevice.serial)
|
||||
InputDevice otherDevice = this->inputDeviceComboBox->itemData(i).value<InputDevice>();
|
||||
if (device.name == otherDevice.name &&
|
||||
device.serial == otherDevice.serial)
|
||||
{
|
||||
if (!device.serial.empty())
|
||||
{
|
||||
@@ -624,7 +630,7 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString)
|
||||
this->inputDeviceComboBox->setCurrentIndex(deviceIndex);
|
||||
|
||||
// force-refresh automatic input device
|
||||
if (deviceNum == static_cast<int>(InputDeviceType::Automatic))
|
||||
if (deviceType == InputDeviceType::Automatic)
|
||||
{
|
||||
this->on_inputDeviceComboBox_currentIndexChanged(deviceIndex);
|
||||
}
|
||||
@@ -633,16 +639,12 @@ void ControllerWidget::CheckInputDeviceSettings(QString sectionQString)
|
||||
{ // name and serial match
|
||||
this->inputDeviceComboBox->setCurrentIndex(deviceSerialIndex);
|
||||
}
|
||||
else if (deviceNameIndex != -1)
|
||||
{ // name only match
|
||||
this->inputDeviceComboBox->setCurrentIndex(deviceNameIndex);
|
||||
}
|
||||
else
|
||||
{ // no match
|
||||
QString title = QString::fromStdString(deviceName);
|
||||
title += " (not found)";
|
||||
this->inputDeviceNameList.append(QString::fromStdString(deviceName));
|
||||
this->inputDeviceComboBox->addItem(title, QVariant::fromValue<SDLDevice>(device));
|
||||
this->inputDeviceComboBox->addItem(title, QVariant::fromValue<InputDevice>(device));
|
||||
this->inputDeviceComboBox->setCurrentIndex(this->inputDeviceNameList.count() - 1);
|
||||
}
|
||||
}
|
||||
@@ -657,17 +659,17 @@ void ControllerWidget::ClearControllerImage()
|
||||
this->controllerImageWidget->ClearControllerState();
|
||||
}
|
||||
|
||||
void ControllerWidget::GetCurrentInputDevice(SDLDevice& device, bool ignoreDeviceNotFound)
|
||||
void ControllerWidget::GetCurrentInputDevice(InputDevice& device, bool ignoreDeviceNotFound)
|
||||
{
|
||||
int currentIndex = this->inputDeviceComboBox->currentIndex();
|
||||
|
||||
if (this->isCurrentDeviceNotFound() && !ignoreDeviceNotFound)
|
||||
{
|
||||
device = { "", "", "", -1 };
|
||||
device = { };
|
||||
}
|
||||
else
|
||||
{
|
||||
device = this->inputDeviceComboBox->itemData(currentIndex).value<SDLDevice>();
|
||||
device = this->inputDeviceComboBox->itemData(currentIndex).value<InputDevice>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,18 +724,18 @@ void ControllerWidget::on_inputDeviceComboBox_currentIndexChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
SDLDevice device = this->inputDeviceComboBox->itemData(value).value<SDLDevice>();
|
||||
InputDevice device = this->inputDeviceComboBox->itemData(value).value<InputDevice>();
|
||||
|
||||
this->ClearControllerImage();
|
||||
|
||||
if (this->isCurrentDeviceNotFound())
|
||||
{
|
||||
device = { "", "", "", -1 };
|
||||
device = { };
|
||||
}
|
||||
|
||||
// set plugged in state
|
||||
this->setPluggedIn(device.number != static_cast<int>(InputDeviceType::None) &&
|
||||
device.number != static_cast<int>(InputDeviceType::EmulateVRU));
|
||||
this->setPluggedIn(device.type != InputDeviceType::None &&
|
||||
device.type != InputDeviceType::EmulateVRU);
|
||||
|
||||
emit this->CurrentInputDeviceChanged(this, device);
|
||||
}
|
||||
@@ -869,12 +871,13 @@ void ControllerWidget::on_removeProfileButton_clicked()
|
||||
|
||||
void ControllerWidget::on_resetButton_clicked()
|
||||
{
|
||||
QString section = this->getCurrentSettingsSection();
|
||||
const QString section = this->getCurrentSettingsSection();
|
||||
const std::string sectionStr = section.toStdString();
|
||||
|
||||
// revert settings in current section when it exists
|
||||
if (CoreSettingsSectionExists(section.toStdString()))
|
||||
if (CoreSettingsSectionExists(sectionStr))
|
||||
{
|
||||
CoreSettingsRevertSection(section.toStdString());
|
||||
CoreSettingsRevertSection(sectionStr);
|
||||
}
|
||||
|
||||
this->LoadSettings(section);
|
||||
@@ -882,8 +885,8 @@ void ControllerWidget::on_resetButton_clicked()
|
||||
|
||||
void ControllerWidget::on_optionsButton_clicked()
|
||||
{
|
||||
SDLDevice device = this->inputDeviceComboBox->currentData().value<SDLDevice>();
|
||||
bool isKeyboard = device.number == static_cast<int>(InputDeviceType::Keyboard);
|
||||
InputDevice device = this->inputDeviceComboBox->currentData().value<InputDevice>();
|
||||
const bool isKeyboard = device.type == InputDeviceType::Keyboard;
|
||||
|
||||
OptionsDialog dialog(this, this->optionsDialogSettings,
|
||||
isKeyboard ? nullptr : this->currentJoystick,
|
||||
@@ -1022,10 +1025,10 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||
{ // gamepad & joystick button
|
||||
SDL_JoystickID joystickId = -1;
|
||||
InputType inputType = InputType::Invalid;
|
||||
@@ -1033,8 +1036,8 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
bool sdlButtonPressed = false;
|
||||
QString sdlButtonName;
|
||||
|
||||
if ((event->type == SDL_CONTROLLERBUTTONDOWN) ||
|
||||
(event->type == SDL_CONTROLLERBUTTONUP))
|
||||
if ((event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_BUTTON_UP))
|
||||
{ // gamepad button
|
||||
if (!this->isCurrentJoystickGameController &&
|
||||
this->optionsDialogSettings.FilterEventsForButtons)
|
||||
@@ -1042,14 +1045,14 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->cbutton.which;
|
||||
joystickId = event->gbutton.which;
|
||||
inputType = InputType::GamepadButton;
|
||||
sdlButton = event->cbutton.button;
|
||||
sdlButtonPressed = (event->type == SDL_CONTROLLERBUTTONDOWN);
|
||||
sdlButtonName = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)sdlButton);
|
||||
sdlButton = event->gbutton.button;
|
||||
sdlButtonPressed = (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
|
||||
sdlButtonName = SDL_GetGamepadStringForButton((SDL_GamepadButton)sdlButton);
|
||||
}
|
||||
else if ((event->type == SDL_JOYBUTTONDOWN) ||
|
||||
(event->type == SDL_JOYBUTTONUP))
|
||||
else if ((event->type == SDL_EVENT_JOYSTICK_BUTTON_DOWN) ||
|
||||
(event->type == SDL_EVENT_JOYSTICK_BUTTON_UP))
|
||||
{ // joystick button
|
||||
if (this->isCurrentJoystickGameController &&
|
||||
this->optionsDialogSettings.FilterEventsForButtons)
|
||||
@@ -1060,7 +1063,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
joystickId = event->jbutton.which;
|
||||
inputType = InputType::JoystickButton;
|
||||
sdlButton = event->jbutton.button;
|
||||
sdlButtonPressed = (event->type == SDL_JOYBUTTONDOWN);
|
||||
sdlButtonPressed = (event->type == SDL_EVENT_JOYSTICK_BUTTON_DOWN);
|
||||
sdlButtonName = "button " + QString::number(sdlButton);
|
||||
}
|
||||
|
||||
@@ -1142,7 +1145,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||
{ // joystick hat
|
||||
SDL_JoystickID joystickId = event->jhat.which;
|
||||
InputType inputType = InputType::JoystickHat;
|
||||
@@ -1279,8 +1282,8 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_JOYAXISMOTION:
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||
{ // gamepad & joystick axis
|
||||
SDL_JoystickID joystickId = -1;
|
||||
InputType inputType = InputType::Invalid;
|
||||
@@ -1288,7 +1291,7 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
int sdlAxisValue = 0;
|
||||
QString sdlAxisName;
|
||||
|
||||
if (event->type == SDL_CONTROLLERAXISMOTION)
|
||||
if (event->type == SDL_EVENT_GAMEPAD_AXIS_MOTION)
|
||||
{ // gamepad axis
|
||||
if (!this->isCurrentJoystickGameController &&
|
||||
this->optionsDialogSettings.FilterEventsForAxis)
|
||||
@@ -1296,11 +1299,11 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
return;
|
||||
}
|
||||
|
||||
joystickId = event->caxis.which;
|
||||
joystickId = event->gaxis.which;
|
||||
inputType = InputType::GamepadAxis;
|
||||
sdlAxis = event->caxis.axis;
|
||||
sdlAxisValue = event->caxis.value;
|
||||
sdlAxisName = SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)sdlAxis);
|
||||
sdlAxis = event->gaxis.axis;
|
||||
sdlAxisValue = event->gaxis.value;
|
||||
sdlAxisName = SDL_GetGamepadStringForAxis((SDL_GamepadAxis)sdlAxis);
|
||||
sdlAxisName += sdlAxisValue > 0 ? "+" : "-";
|
||||
}
|
||||
else
|
||||
@@ -1395,8 +1398,8 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
}
|
||||
} break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
{ // keyboard button
|
||||
|
||||
// make sure a keyboard is selected
|
||||
@@ -1405,8 +1408,8 @@ void ControllerWidget::on_MainDialog_SdlEvent(SDL_Event* event)
|
||||
break;
|
||||
}
|
||||
|
||||
const SDL_Scancode sdlButton = (SDL_Scancode)event->key.keysym.scancode;
|
||||
const bool sdlButtonPressed = (event->type == SDL_KEYDOWN);
|
||||
const SDL_Scancode sdlButton = (SDL_Scancode)event->key.scancode;
|
||||
const bool sdlButtonPressed = (event->type == SDL_EVENT_KEY_DOWN);
|
||||
|
||||
// handle button widget
|
||||
if (this->currentButton != nullptr)
|
||||
@@ -1494,7 +1497,8 @@ void ControllerWidget::on_MainDialog_SdlEventPollFinished()
|
||||
|
||||
bool ControllerWidget::IsPluggedIn()
|
||||
{
|
||||
return this->inputDeviceComboBox->currentData().toInt() != static_cast<int>(InputDeviceType::None);
|
||||
const InputDevice device = this->inputDeviceComboBox->currentData().value<InputDevice>();
|
||||
return device.type != InputDeviceType::None;
|
||||
}
|
||||
|
||||
void ControllerWidget::SetOnlyLoadGameProfile(bool value, CoreRomHeader romHeader, CoreRomSettings romSettings)
|
||||
@@ -1507,6 +1511,11 @@ void ControllerWidget::SetOnlyLoadGameProfile(bool value, CoreRomHeader romHeade
|
||||
this->addProfileButton->setDisabled(value);
|
||||
}
|
||||
|
||||
void ControllerWidget::SetAllowKeyboardForAutomatic(bool value)
|
||||
{
|
||||
this->allowKeyboardForAutomatic = value;
|
||||
}
|
||||
|
||||
void ControllerWidget::SetSettingsSection(QString profile, QString section)
|
||||
{
|
||||
this->settingsSection = section;
|
||||
@@ -1662,34 +1671,14 @@ void ControllerWidget::LoadSettings(QString sectionQString, bool loadUserProfile
|
||||
}
|
||||
}
|
||||
|
||||
// keep backwards compatibility with versions before v0.3.9
|
||||
if (CoreSettingsKeyExists(section, "Sensitivity"))
|
||||
{
|
||||
this->analogStickSensitivitySlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->analogStickSensitivitySlider->setValue(100);
|
||||
}
|
||||
|
||||
this->analogStickSensitivitySlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section));
|
||||
this->deadZoneSlider->setValue(CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section));
|
||||
this->optionsDialogSettings.RemoveDuplicateMappings = CoreSettingsGetBoolValue(SettingsID::Input_RemoveDuplicateMappings, section);
|
||||
this->optionsDialogSettings.ControllerPak = CoreSettingsGetIntValue(SettingsID::Input_Pak, section);
|
||||
this->optionsDialogSettings.GameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section);
|
||||
this->optionsDialogSettings.GameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section);
|
||||
|
||||
// keep backwards compatibility with old profiles
|
||||
if (CoreSettingsKeyExists(section, "FilterEventsForButtons") &&
|
||||
CoreSettingsKeyExists(section, "FilterEventsForAxis"))
|
||||
{
|
||||
this->optionsDialogSettings.FilterEventsForButtons = CoreSettingsGetBoolValue(SettingsID::Input_FilterEventsForButtons, section);
|
||||
this->optionsDialogSettings.FilterEventsForAxis = CoreSettingsGetBoolValue(SettingsID::Input_FilterEventsForAxis, section);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->optionsDialogSettings.FilterEventsForButtons = true;
|
||||
this->optionsDialogSettings.FilterEventsForAxis = true;
|
||||
}
|
||||
this->optionsDialogSettings.FilterEventsForButtons = CoreSettingsGetBoolValue(SettingsID::Input_FilterEventsForButtons, section);
|
||||
this->optionsDialogSettings.FilterEventsForAxis = CoreSettingsGetBoolValue(SettingsID::Input_FilterEventsForAxis, section);
|
||||
|
||||
for (auto& buttonSetting : this->buttonSettingMappings)
|
||||
{
|
||||
@@ -1755,7 +1744,7 @@ void ControllerWidget::SaveDefaultSettings()
|
||||
|
||||
CoreSettingsSetValue(SettingsID::Input_PluggedIn, section, false);
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceName, section, std::string("None"));
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceNum, section, static_cast<int>(InputDeviceType::None));
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceType, section, static_cast<int>(InputDeviceType::None));
|
||||
CoreSettingsSetValue(SettingsID::Input_DevicePath, section, std::string(""));
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceSerial, section, std::string(""));
|
||||
CoreSettingsSetValue(SettingsID::Input_Deadzone, section, 9);
|
||||
@@ -1799,7 +1788,7 @@ void ControllerWidget::SaveSettings()
|
||||
|
||||
// when we're only loading the game profile,
|
||||
// we should only save when anything has changed
|
||||
if (this->onlyLoadGameProfile &&
|
||||
if (this->onlyLoadGameProfile &&
|
||||
!this->hasAnySettingChanged(this->gameSection))
|
||||
{
|
||||
return;
|
||||
@@ -1838,7 +1827,7 @@ void ControllerWidget::SaveUserProfileSettings()
|
||||
|
||||
void ControllerWidget::SaveSettings(QString section)
|
||||
{
|
||||
SDLDevice device;
|
||||
InputDevice device;
|
||||
|
||||
std::string mainSettingsSection = this->settingsSection.toStdString();
|
||||
std::string sectionStr = section.toStdString();
|
||||
@@ -1871,7 +1860,7 @@ void ControllerWidget::SaveSettings(QString section)
|
||||
|
||||
CoreSettingsSetValue(SettingsID::Input_PluggedIn, sectionStr, this->IsPluggedIn());
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceName, sectionStr, device.name);
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceNum, sectionStr, device.number);
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceType, sectionStr, static_cast<int>(device.type));
|
||||
CoreSettingsSetValue(SettingsID::Input_DevicePath, sectionStr, device.path);
|
||||
CoreSettingsSetValue(SettingsID::Input_DeviceSerial, sectionStr, device.serial);
|
||||
CoreSettingsSetValue(SettingsID::Input_Deadzone, sectionStr, this->deadZoneSlider->value());
|
||||
@@ -1949,7 +1938,7 @@ void ControllerWidget::SetIsCurrentJoystickGameController(bool isGameController)
|
||||
this->isCurrentJoystickGameController = isGameController;
|
||||
}
|
||||
|
||||
void ControllerWidget::SetCurrentJoystick(SDL_Joystick* joystick, SDL_GameController* controller)
|
||||
void ControllerWidget::SetCurrentJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller)
|
||||
{
|
||||
this->currentJoystick = joystick;
|
||||
this->currentController = controller;
|
||||
|
||||
@@ -22,7 +22,7 @@ using namespace UserInterface::Widget;
|
||||
#include "ui_ControllerWidget.h"
|
||||
#include "common.hpp"
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <RMG-Core/RomSettings.hpp>
|
||||
#include <RMG-Core/RomHeader.hpp>
|
||||
@@ -107,7 +107,7 @@ private:
|
||||
bool isCurrentJoystickGameController = false;
|
||||
|
||||
SDL_Joystick* currentJoystick = nullptr;
|
||||
SDL_GameController* currentController = nullptr;
|
||||
SDL_Gamepad* currentController = nullptr;
|
||||
|
||||
int previousProfileComboBoxIndex = -1;
|
||||
|
||||
@@ -115,24 +115,27 @@ private:
|
||||
CoreRomHeader gameRomHeader;
|
||||
CoreRomSettings gameRomSettings;
|
||||
|
||||
bool allowKeyboardForAutomatic = false;
|
||||
|
||||
HotkeysDialog* currentHotkeysDialog = nullptr;
|
||||
|
||||
public:
|
||||
ControllerWidget(QWidget* parent, EventFilter* eventFilter);
|
||||
~ControllerWidget();
|
||||
|
||||
void AddInputDevice(SDLDevice device);
|
||||
void RemoveInputDevice(SDLDevice device);
|
||||
void AddInputDevice(const InputDevice& device);
|
||||
void RemoveInputDevice(const InputDevice& device);
|
||||
void CheckInputDeviceSettings();
|
||||
void CheckInputDeviceSettings(QString section);
|
||||
|
||||
void DrawControllerImage();
|
||||
void ClearControllerImage();
|
||||
|
||||
void GetCurrentInputDevice(SDLDevice& device, bool ignoreDeviceNotFound = false);
|
||||
void GetCurrentInputDevice(InputDevice& device, bool ignoreDeviceNotFound = false);
|
||||
bool IsPluggedIn();
|
||||
|
||||
void SetOnlyLoadGameProfile(bool value, CoreRomHeader romHeader, CoreRomSettings romSettings);
|
||||
void SetAllowKeyboardForAutomatic(bool value);
|
||||
|
||||
void SetSettingsSection(QString profile, QString section);
|
||||
void SetInitialized(bool value);
|
||||
@@ -150,7 +153,7 @@ public:
|
||||
|
||||
void SetCurrentJoystickID(SDL_JoystickID joystickId);
|
||||
void SetIsCurrentJoystickGameController(bool isGameController);
|
||||
void SetCurrentJoystick(SDL_Joystick* joystick, SDL_GameController* controller);
|
||||
void SetCurrentJoystick(SDL_Joystick* joystick, SDL_Gamepad* controller);
|
||||
|
||||
void AddUserProfile(QString name, QString section);
|
||||
void RemoveUserProfile(QString name, QString section);
|
||||
@@ -184,7 +187,7 @@ public slots:
|
||||
void on_MainDialog_SdlEventPollFinished();
|
||||
|
||||
signals:
|
||||
void CurrentInputDeviceChanged(ControllerWidget* widget, SDLDevice device);
|
||||
void CurrentInputDeviceChanged(ControllerWidget* widget, InputDevice device);
|
||||
void RefreshInputDevicesButtonClicked();
|
||||
|
||||
void UserProfileAdded(QString name, QString section);
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020-2025 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "InputDevice.hpp"
|
||||
|
||||
using namespace Utilities;
|
||||
|
||||
InputDevice::InputDevice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
InputDevice::~InputDevice()
|
||||
{
|
||||
this->CloseDevice();
|
||||
}
|
||||
|
||||
void InputDevice::SetSDLThread(Thread::SDLThread* sdlThread)
|
||||
{
|
||||
this->sdlThread = sdlThread;
|
||||
connect(this->sdlThread, &Thread::SDLThread::OnInputDeviceFound, this,
|
||||
&InputDevice::on_SDLThread_DeviceFound);
|
||||
connect(this->sdlThread, &Thread::SDLThread::OnDeviceSearchFinished, this,
|
||||
&InputDevice::on_SDLThread_DeviceSearchFinished);
|
||||
}
|
||||
|
||||
SDL_Joystick* InputDevice::GetJoystickHandle()
|
||||
{
|
||||
return this->joystick;
|
||||
}
|
||||
|
||||
SDL_GameController* InputDevice::GetGameControllerHandle()
|
||||
{
|
||||
return this->gameController;
|
||||
}
|
||||
|
||||
bool InputDevice::StartRumble(void)
|
||||
{
|
||||
if (this->gameController != nullptr)
|
||||
{
|
||||
return SDL_GameControllerRumble(this->gameController, 0xFFFF, 0xFFFF, SDL_HAPTIC_INFINITY) == 0;
|
||||
}
|
||||
else if (this->joystick != nullptr)
|
||||
{
|
||||
return SDL_JoystickRumble(this->joystick, 0xFFFF, 0xFFFF, SDL_HAPTIC_INFINITY) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDevice::StopRumble(void)
|
||||
{
|
||||
if (this->gameController != nullptr)
|
||||
{
|
||||
return SDL_GameControllerRumble(this->gameController, 0, 0, 0) == 0;
|
||||
}
|
||||
else if (this->joystick != nullptr)
|
||||
{
|
||||
return SDL_JoystickRumble(this->joystick, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputDevice::IsAttached(void)
|
||||
{
|
||||
return SDL_JoystickGetAttached(this->joystick) == SDL_TRUE;
|
||||
}
|
||||
|
||||
bool InputDevice::HasOpenDevice()
|
||||
{
|
||||
return this->hasOpenDevice;
|
||||
}
|
||||
|
||||
void InputDevice::OpenDevice(std::string name, std::string path, std::string serial, int num)
|
||||
{
|
||||
// wait until SDLThread is done first
|
||||
while (this->sdlThread->GetCurrentAction() != SDLThreadAction::None)
|
||||
{
|
||||
QThread::msleep(5);
|
||||
}
|
||||
|
||||
this->foundDevicesWithNameMatch.clear();
|
||||
this->desiredDevice = {name, path, serial, num};
|
||||
this->isOpeningDevice = true;
|
||||
|
||||
// tell SDLThread to query input devices
|
||||
this->sdlThread->SetAction(SDLThreadAction::GetInputDevices);
|
||||
}
|
||||
|
||||
bool InputDevice::IsOpeningDevice(void)
|
||||
{
|
||||
return this->isOpeningDevice;
|
||||
}
|
||||
|
||||
bool InputDevice::CloseDevice()
|
||||
{
|
||||
if (this->joystick != nullptr)
|
||||
{
|
||||
SDL_JoystickClose(this->joystick);
|
||||
this->joystick = nullptr;
|
||||
}
|
||||
|
||||
if (this->gameController != nullptr)
|
||||
{
|
||||
SDL_GameControllerClose(this->gameController);
|
||||
this->gameController = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputDevice::on_SDLThread_DeviceFound(QString name, QString path, QString serial, int number)
|
||||
{
|
||||
if ((!this->isOpeningDevice) ||
|
||||
(this->desiredDevice.name != name.toStdString()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDLDevice device;
|
||||
device.name = name.toStdString();
|
||||
device.path = path.toStdString();
|
||||
device.serial = serial.toStdString();
|
||||
device.number = number;
|
||||
|
||||
this->foundDevicesWithNameMatch.push_back(device);
|
||||
}
|
||||
|
||||
void InputDevice::on_SDLThread_DeviceSearchFinished(void)
|
||||
{
|
||||
if (!this->isOpeningDevice)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->CloseDevice();
|
||||
|
||||
if (this->foundDevicesWithNameMatch.empty())
|
||||
{
|
||||
this->isOpeningDevice = false;
|
||||
this->hasOpenDevice = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// try to find exact match
|
||||
SDLDevice device;
|
||||
bool hasDevice = false;
|
||||
|
||||
auto iter = std::find(this->foundDevicesWithNameMatch.begin(), this->foundDevicesWithNameMatch.end(), this->desiredDevice);
|
||||
if (iter != this->foundDevicesWithNameMatch.end())
|
||||
{ // use exact match
|
||||
device.name = iter->name;
|
||||
device.path = iter->path;
|
||||
device.serial = iter->serial;
|
||||
device.number = iter->number;
|
||||
}
|
||||
else
|
||||
{ // no exact match, try to find name + serial match first
|
||||
if (!this->desiredDevice.serial.empty())
|
||||
{ // only try serial match when it's not empty
|
||||
for (const auto& deviceNameMatch : this->foundDevicesWithNameMatch)
|
||||
{
|
||||
if (deviceNameMatch.serial == this->desiredDevice.serial)
|
||||
{
|
||||
device = deviceNameMatch;
|
||||
hasDevice = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasDevice)
|
||||
{ // fallback to name only match
|
||||
device = this->foundDevicesWithNameMatch.at(0);
|
||||
}
|
||||
}
|
||||
|
||||
this->joystick = SDL_JoystickOpen(device.number);
|
||||
if (SDL_IsGameController(device.number))
|
||||
{
|
||||
this->gameController = SDL_GameControllerOpen(device.number);
|
||||
}
|
||||
|
||||
this->isOpeningDevice = false;
|
||||
this->hasOpenDevice = this->joystick != nullptr || this->gameController != nullptr;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
|
||||
* Copyright (C) 2020-2025 Rosalie Wanders <rosalie@mailbox.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 3.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INPUTDEVICE_HPP
|
||||
#define INPUTDEVICE_HPP
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <string>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "Thread/SDLThread.hpp"
|
||||
|
||||
namespace Utilities
|
||||
{
|
||||
class InputDevice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InputDevice();
|
||||
~InputDevice();
|
||||
|
||||
void SetSDLThread(Thread::SDLThread* sdlThread);
|
||||
|
||||
SDL_Joystick* GetJoystickHandle(void);
|
||||
SDL_GameController* GetGameControllerHandle(void);
|
||||
|
||||
bool StartRumble(void);
|
||||
bool StopRumble(void);
|
||||
|
||||
// returns whether the device is attached
|
||||
bool IsAttached(void);
|
||||
|
||||
// returns whether a device has been opened
|
||||
bool HasOpenDevice(void);
|
||||
|
||||
// tries to open device with given name, path, serial & num
|
||||
void OpenDevice(std::string name, std::string path, std::string serial, int num);
|
||||
|
||||
// returns whether we're still trying to open the device
|
||||
bool IsOpeningDevice(void);
|
||||
|
||||
// tries to close opened device
|
||||
bool CloseDevice(void);
|
||||
|
||||
private:
|
||||
SDL_Joystick* joystick = nullptr;
|
||||
SDL_GameController* gameController = nullptr;
|
||||
|
||||
bool hasOpenDevice = false;
|
||||
bool isOpeningDevice = false;
|
||||
|
||||
Thread::SDLThread* sdlThread = nullptr;
|
||||
|
||||
SDLDevice desiredDevice;
|
||||
std::vector<SDLDevice> foundDevicesWithNameMatch;
|
||||
|
||||
private slots:
|
||||
void on_SDLThread_DeviceFound(QString name, QString path, QString serial, int number);
|
||||
void on_SDLThread_DeviceSearchFinished(void);
|
||||
};
|
||||
} // namespace Utilities
|
||||
|
||||
#endif // INPUTDEVICE_HPP
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef QTKEYTOSDL2KEY_HPP
|
||||
#define QTKEYTOSDL2KEY_HPP
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Utilities
|
||||
{
|
||||
int QtKeyToSdl2Key(int);
|
||||
int QtModKeyToSdl2ModKey(Qt::KeyboardModifiers);
|
||||
} // namespace Utilities
|
||||
|
||||
#endif // QTKEYTOSDL2KEY_HPP
|
||||
+8
-8
@@ -7,13 +7,13 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "QtKeyToSdl2Key.hpp"
|
||||
#include "QtKeyToSdl3Key.hpp"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
using namespace Utilities;
|
||||
|
||||
int Utilities::QtKeyToSdl2Key(int key)
|
||||
int Utilities::QtKeyToSdl3Key(int key)
|
||||
{
|
||||
SDL_Scancode returnValue;
|
||||
switch (key)
|
||||
@@ -323,16 +323,16 @@ int Utilities::QtKeyToSdl2Key(int key)
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
int Utilities::QtModKeyToSdl2ModKey(Qt::KeyboardModifiers modifiers)
|
||||
int Utilities::QtModKeyToSdl3ModKey(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
int value = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
value |= KMOD_SHIFT;
|
||||
value |= SDL_KMOD_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
value |= KMOD_CTRL;
|
||||
value |= SDL_KMOD_CTRL;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
value |= KMOD_ALT;
|
||||
value |= SDL_KMOD_ALT;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
value |= KMOD_GUI;
|
||||
value |= SDL_KMOD_GUI;
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef QTKEYTOSDL3KEY_HPP
|
||||
#define QTKEYTOSDL3KEY_HPP
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Utilities
|
||||
{
|
||||
int QtKeyToSdl3Key(int);
|
||||
int QtModKeyToSdl3ModKey(Qt::KeyboardModifiers);
|
||||
} // namespace Utilities
|
||||
|
||||
#endif // QTKEYTOSDL3KEY_HPP
|
||||
+38
-18
@@ -27,7 +27,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "VRUwords.hpp"
|
||||
#include "VRU.hpp"
|
||||
@@ -85,8 +85,8 @@ static int l_WordListCount = 0;
|
||||
static QStringList l_RegisteredWords;
|
||||
static QList<int> l_RegisteredWordsIndex;
|
||||
|
||||
static SDL_AudioDeviceID l_AudioDevice = 0;
|
||||
static SDL_AudioSpec l_AudioDeviceSpec;
|
||||
static SDL_AudioStream* l_AudioStream = nullptr;
|
||||
static bool l_HasInitSDL = false;
|
||||
|
||||
//
|
||||
// Local Functions
|
||||
@@ -260,14 +260,24 @@ static bool init_mic(void)
|
||||
SDL_AudioSpec desiredAudioSpec;
|
||||
|
||||
desiredAudioSpec.freq = 44100;
|
||||
desiredAudioSpec.format = AUDIO_S16SYS;
|
||||
desiredAudioSpec.format = SDL_AUDIO_S16;
|
||||
desiredAudioSpec.channels = 1;
|
||||
desiredAudioSpec.samples = 1024;
|
||||
desiredAudioSpec.callback = nullptr;
|
||||
desiredAudioSpec.userdata = nullptr;
|
||||
|
||||
l_AudioDevice = SDL_OpenAudioDevice(nullptr, 1, &desiredAudioSpec, &l_AudioDeviceSpec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (l_AudioDevice == 0)
|
||||
if (!SDL_WasInit(SDL_INIT_AUDIO))
|
||||
{
|
||||
if (!SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
{
|
||||
debugMessage = "VRU: SDL_InitSubSystem Failed: ";
|
||||
debugMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, debugMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
l_HasInitSDL = true;
|
||||
}
|
||||
|
||||
l_AudioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_RECORDING, &desiredAudioSpec, NULL, NULL);
|
||||
if (l_AudioStream == nullptr)
|
||||
{
|
||||
debugMessage = "VRU: SDL_OpenAudioDevice Failed: ";
|
||||
debugMessage += SDL_GetError();
|
||||
@@ -280,9 +290,10 @@ static bool init_mic(void)
|
||||
|
||||
static void quit_mic(void)
|
||||
{
|
||||
if (l_AudioDevice != 0)
|
||||
if (l_AudioStream != nullptr)
|
||||
{
|
||||
SDL_CloseAudioDevice(l_AudioDevice);
|
||||
SDL_DestroyAudioStream(l_AudioStream);
|
||||
l_AudioStream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,6 +390,11 @@ bool QuitVRU(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HasVRUInitSDL(void)
|
||||
{
|
||||
return l_HasInitSDL;
|
||||
}
|
||||
|
||||
int GetVRUMicState(void)
|
||||
{
|
||||
return l_MicState;
|
||||
@@ -442,7 +458,7 @@ EXPORT void CALL SendVRUWord(uint16_t length, uint16_t* word, uint8_t lang)
|
||||
}
|
||||
|
||||
// try to create a new recognizer
|
||||
l_VoskRecognizer = l_vosk_recognizer_new_grm(l_VoskModel, static_cast<float>(l_AudioDeviceSpec.freq), json_document.toJson().constData());
|
||||
l_VoskRecognizer = l_vosk_recognizer_new_grm(l_VoskModel, 44100.0f, json_document.toJson().constData());
|
||||
if (l_VoskRecognizer != nullptr)
|
||||
{
|
||||
l_vosk_recognizer_set_max_alternatives(l_VoskRecognizer, 3);
|
||||
@@ -459,12 +475,11 @@ EXPORT void CALL SetMicState(int state)
|
||||
|
||||
if (state)
|
||||
{
|
||||
SDL_ClearQueuedAudio(l_AudioDevice);
|
||||
SDL_PauseAudioDevice(l_AudioDevice, 0);
|
||||
SDL_ResumeAudioStreamDevice(l_AudioStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_PauseAudioDevice(l_AudioDevice, 1);
|
||||
SDL_PauseAudioStreamDevice(l_AudioStream);
|
||||
}
|
||||
|
||||
l_MicState = state;
|
||||
@@ -489,13 +504,18 @@ EXPORT void CALL ReadVRUResults(uint16_t* error_flags, uint16_t* num_results, ui
|
||||
}
|
||||
|
||||
// retrieve audio data from device
|
||||
SDL_PauseAudioDevice(l_AudioDevice, 1);
|
||||
SDL_PauseAudioStreamDevice(l_AudioStream);
|
||||
|
||||
int audio_size = SDL_GetAudioStreamAvailable(l_AudioStream);
|
||||
if (audio_size == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t audio_size = SDL_GetQueuedAudioSize(l_AudioDevice);
|
||||
std::vector<char> audio_buf(audio_size);
|
||||
|
||||
// read audio
|
||||
audio_size = SDL_DequeueAudio(l_AudioDevice, audio_buf.data(), audio_buf.size());
|
||||
audio_size = SDL_GetAudioStreamData(l_AudioStream, audio_buf.data(), audio_buf.size());
|
||||
|
||||
// hand audio data to vosk and retrieve results
|
||||
int ret = l_vosk_recognizer_accept_waveform(l_VoskRecognizer, audio_buf.data(), audio_size);
|
||||
|
||||
@@ -19,6 +19,9 @@ bool IsVRUInit(void);
|
||||
// attempts to de-initialize VRY capabilities
|
||||
bool QuitVRU(void);
|
||||
|
||||
// returns whether VRU has initialized SDL audio
|
||||
bool HasVRUInitSDL(void);
|
||||
|
||||
int GetVRUMicState(void);
|
||||
|
||||
#endif // VRU_HPP
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#define SDL_AXIS_PEAK 32767
|
||||
|
||||
enum class N64ControllerButton
|
||||
@@ -35,10 +37,12 @@ enum class N64ControllerButton
|
||||
|
||||
enum class InputDeviceType
|
||||
{
|
||||
EmulateVRU = -4,
|
||||
None = -3,
|
||||
Automatic = -2,
|
||||
Keyboard = -1,
|
||||
None = 0,
|
||||
EmulateVRU,
|
||||
Automatic,
|
||||
Keyboard,
|
||||
Joystick,
|
||||
Invalid
|
||||
};
|
||||
|
||||
enum class InputType
|
||||
@@ -68,19 +72,22 @@ enum class N64ControllerPak
|
||||
None,
|
||||
};
|
||||
|
||||
struct SDLDevice
|
||||
struct InputDevice
|
||||
{
|
||||
InputDeviceType type = InputDeviceType::Invalid;
|
||||
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::string serial;
|
||||
int number;
|
||||
SDL_JoystickID id = 0;
|
||||
|
||||
bool operator== (const SDLDevice& other) const
|
||||
bool operator== (const InputDevice& other) const
|
||||
{
|
||||
return other.name == name &&
|
||||
return other.type == type &&
|
||||
other.name == name &&
|
||||
other.path == path &&
|
||||
other.serial == serial &&
|
||||
other.number == number;
|
||||
other.id == id;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+223
-114
@@ -12,7 +12,6 @@
|
||||
#define INPUT_PLUGIN_API_VERSION 0x020100
|
||||
|
||||
#include "UserInterface/MainDialog.hpp"
|
||||
#include "Utilities/InputDevice.hpp"
|
||||
#include "Thread/HotkeysThread.hpp"
|
||||
#include "Thread/SDLThread.hpp"
|
||||
#include "common.hpp"
|
||||
@@ -40,7 +39,7 @@
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QApplication>
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -89,7 +88,7 @@ struct InputProfile
|
||||
std::string DeviceName;
|
||||
std::string DevicePath;
|
||||
std::string DeviceSerial;
|
||||
int DeviceNum = -1;
|
||||
InputDeviceType DeviceType = InputDeviceType::Invalid;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> LastDeviceCheckTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Gameboy information
|
||||
@@ -97,7 +96,8 @@ struct InputProfile
|
||||
std::string GameboySave;
|
||||
|
||||
// input device
|
||||
Utilities::InputDevice InputDevice;
|
||||
SDL_Joystick* SDLJoystick = nullptr;
|
||||
SDL_Gamepad* SDLGamepad = nullptr;
|
||||
|
||||
// buttons
|
||||
InputMapping Button_A;
|
||||
@@ -204,7 +204,7 @@ static void (*l_DebugCallback)(void *, int, const char *) = nullptr;
|
||||
static void *l_DebugCallContext = nullptr;
|
||||
|
||||
// keyboard state
|
||||
static bool l_KeyboardState[SDL_NUM_SCANCODES];
|
||||
static bool l_KeyboardState[SDL_SCANCODE_COUNT];
|
||||
|
||||
// config GUI state
|
||||
static bool l_IsConfigGuiOpen = false;
|
||||
@@ -309,23 +309,14 @@ static void load_settings(void)
|
||||
|
||||
profile->PluggedIn = CoreSettingsGetBoolValue(SettingsID::Input_PluggedIn, section);
|
||||
profile->DeadzoneValue = CoreSettingsGetIntValue(SettingsID::Input_Deadzone, section);
|
||||
profile->ControllerPak = (N64ControllerPak)CoreSettingsGetIntValue(SettingsID::Input_Pak, section);
|
||||
profile->ControllerPak = static_cast<N64ControllerPak>(CoreSettingsGetIntValue(SettingsID::Input_Pak, section));
|
||||
profile->DeviceName = CoreSettingsGetStringValue(SettingsID::Input_DeviceName, section);
|
||||
profile->DevicePath = CoreSettingsGetStringValue(SettingsID::Input_DevicePath, section);
|
||||
profile->DeviceSerial = CoreSettingsGetStringValue(SettingsID::Input_DeviceSerial, section);
|
||||
profile->DeviceNum = CoreSettingsGetIntValue(SettingsID::Input_DeviceNum, section);
|
||||
profile->DeviceType = static_cast<InputDeviceType>(CoreSettingsGetIntValue(SettingsID::Input_DeviceType, section));
|
||||
profile->GameboyRom = CoreSettingsGetStringValue(SettingsID::Input_GameboyRom, section);
|
||||
profile->GameboySave = CoreSettingsGetStringValue(SettingsID::Input_GameboySave, section);
|
||||
|
||||
// keep compatibility with profiles before version v0.3.9
|
||||
if (CoreSettingsKeyExists(section, "Sensitivity"))
|
||||
{
|
||||
profile->SensitivityValue = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile->SensitivityValue = 100;
|
||||
}
|
||||
profile->SensitivityValue = CoreSettingsGetIntValue(SettingsID::Input_Sensitivity, section);
|
||||
|
||||
#define LOAD_INPUT_MAPPING(mapping, setting) \
|
||||
load_inputmapping_settings(&profile->mapping, section, SettingsID::setting##_Name, SettingsID::setting##_InputType, SettingsID::setting##_Data, SettingsID::setting##_ExtraData)
|
||||
@@ -407,7 +398,7 @@ static void apply_controller_profiles(void)
|
||||
{
|
||||
InputProfile* profile = &l_InputProfiles[i];
|
||||
int plugin = PLUGIN_NONE;
|
||||
bool emulateVRU = (profile->DeviceNum == static_cast<int>(InputDeviceType::EmulateVRU));
|
||||
bool emulateVRU = (profile->DeviceType == InputDeviceType::EmulateVRU);
|
||||
|
||||
switch (profile->ControllerPak)
|
||||
{
|
||||
@@ -448,6 +439,8 @@ static void apply_controller_profiles(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_rumble_stop(InputProfile* profile); // forward declaration
|
||||
|
||||
static void switch_controller_pak(InputProfile* profile, const int Control, const int pak)
|
||||
{
|
||||
const int currentPak = l_ControlInfo.Controls[Control].Plugin;
|
||||
@@ -465,7 +458,7 @@ static void switch_controller_pak(InputProfile* profile, const int Control, cons
|
||||
// ensure that we stop the controller's rumble
|
||||
if (currentPak == PLUGIN_RAW)
|
||||
{
|
||||
profile->InputDevice.StopRumble();
|
||||
controller_rumble_stop(profile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,93 +491,232 @@ static void apply_gameboy_settings(void)
|
||||
CoreSettingsSave();
|
||||
}
|
||||
|
||||
static void setup_device_automatic(int num, InputProfile* profile)
|
||||
static std::string string_from_const_char(const char* str)
|
||||
{
|
||||
static int previousSdlDeviceNum = -1;
|
||||
|
||||
// reset variable when needed
|
||||
if (num == 0)
|
||||
std::string string;
|
||||
if (str != nullptr)
|
||||
{
|
||||
previousSdlDeviceNum = -1;
|
||||
string = str;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
bool foundSdlDevice = false;
|
||||
SDL_GameController* sdlGameController = nullptr;
|
||||
SDL_Joystick* sdlJoystick = nullptr;
|
||||
std::string sdlDeviceName;
|
||||
static void open_controller_automatic(int index, InputProfile* profile, SDL_JoystickID* joysticks, int joysticksCount)
|
||||
{
|
||||
bool foundJoystick = false;
|
||||
SDL_JoystickID joystickId;
|
||||
std::string debugMessage;
|
||||
|
||||
for (int i = (previousSdlDeviceNum + 1); i < SDL_NumJoysticks(); i++)
|
||||
std::string debugMessageBase;
|
||||
debugMessageBase = "setup_device_automatic(";
|
||||
debugMessageBase += std::to_string(index);
|
||||
debugMessageBase += "): ";
|
||||
|
||||
for (int i = index; i < joysticksCount; i++)
|
||||
{
|
||||
if (SDL_IsGameController(i))
|
||||
joystickId = joysticks[i];
|
||||
|
||||
if (SDL_IsGamepad(joystickId))
|
||||
{
|
||||
sdlGameController = SDL_GameControllerOpen(i);
|
||||
if (sdlGameController != nullptr)
|
||||
profile->SDLJoystick = SDL_OpenJoystick(joystickId);
|
||||
profile->SDLGamepad = SDL_OpenGamepad(joystickId);
|
||||
if (profile->SDLGamepad == nullptr)
|
||||
{
|
||||
sdlDeviceName = SDL_GameControllerName(sdlGameController);
|
||||
SDL_GameControllerClose(sdlGameController);
|
||||
profile->DeviceNum = i;
|
||||
profile->DeviceName = sdlDeviceName;
|
||||
previousSdlDeviceNum = i;
|
||||
foundSdlDevice = true;
|
||||
break;
|
||||
debugMessage = debugMessageBase + "SDL_OpenGamepad Failed: ";
|
||||
debugMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, debugMessage);
|
||||
continue;
|
||||
}
|
||||
|
||||
debugMessage = debugMessageBase + "found gamepad: ";
|
||||
debugMessage += string_from_const_char(SDL_GetGamepadName(profile->SDLGamepad));
|
||||
PluginDebugMessage(M64MSG_VERBOSE, debugMessage);
|
||||
|
||||
foundJoystick = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sdlJoystick = SDL_JoystickOpen(i);
|
||||
if (sdlJoystick != nullptr)
|
||||
profile->SDLJoystick = SDL_OpenJoystick(joystickId);
|
||||
profile->SDLGamepad = nullptr;
|
||||
if (profile->SDLJoystick == nullptr)
|
||||
{
|
||||
sdlDeviceName = SDL_JoystickName(sdlJoystick);
|
||||
SDL_JoystickClose(sdlJoystick);
|
||||
profile->DeviceNum = i;
|
||||
profile->DeviceName = sdlDeviceName;
|
||||
previousSdlDeviceNum = i;
|
||||
foundSdlDevice = true;
|
||||
break;
|
||||
debugMessage = debugMessageBase + "SDL_OpenJoystick Failed: ";
|
||||
debugMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, debugMessage);
|
||||
continue;
|
||||
}
|
||||
|
||||
debugMessage = debugMessageBase + "found joystick: ";
|
||||
debugMessage += string_from_const_char(SDL_GetJoystickName(profile->SDLJoystick));
|
||||
PluginDebugMessage(M64MSG_VERBOSE, debugMessage);
|
||||
|
||||
foundJoystick = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundSdlDevice)
|
||||
if (!foundJoystick)
|
||||
{ // fallback to keyboard
|
||||
if (num == 0)
|
||||
if (index == 0)
|
||||
{
|
||||
profile->DeviceNum = static_cast<int>(InputDeviceType::Keyboard);
|
||||
debugMessage = debugMessageBase + "falling back to keyboard";
|
||||
PluginDebugMessage(M64MSG_VERBOSE, debugMessage);
|
||||
|
||||
profile->DeviceType = InputDeviceType::Keyboard;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugMessage = debugMessageBase + "no device found";
|
||||
PluginDebugMessage(M64MSG_VERBOSE, debugMessage);
|
||||
|
||||
profile->PluggedIn = false;
|
||||
|
||||
// only override present in core
|
||||
// when we have the control info
|
||||
if (l_HasControlInfo)
|
||||
{
|
||||
l_ControlInfo.Controls[num].Present = 0;
|
||||
l_ControlInfo.Controls[index].Present = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void open_controller(InputProfile* profile, SDL_JoystickID* joysticks, int joysticksCount)
|
||||
{
|
||||
SDL_JoystickID joystickId;
|
||||
SDL_Joystick* joystick = nullptr;
|
||||
SDL_Gamepad* gamepad = nullptr;
|
||||
std::string errorMessage;
|
||||
|
||||
std::string deviceName;
|
||||
std::string devicePath;
|
||||
std::string deviceSerial;
|
||||
|
||||
for (int i = 0; i < joysticksCount; i++)
|
||||
{
|
||||
joystickId = joysticks[i];
|
||||
|
||||
if (SDL_IsGamepad(joystickId))
|
||||
{
|
||||
joystick = SDL_OpenJoystick(joystickId);
|
||||
gamepad = SDL_OpenGamepad(joystickId);
|
||||
if (gamepad == nullptr)
|
||||
{
|
||||
errorMessage = "open_controller(): SDL_OpenGamepad Failed: ";
|
||||
errorMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, errorMessage);
|
||||
continue;
|
||||
}
|
||||
|
||||
deviceName = string_from_const_char(SDL_GetGamepadName(gamepad));
|
||||
devicePath = string_from_const_char(SDL_GetGamepadPath(gamepad));
|
||||
deviceSerial = string_from_const_char(SDL_GetGamepadSerial(gamepad));
|
||||
}
|
||||
else
|
||||
{
|
||||
gamepad = nullptr;
|
||||
joystick = SDL_OpenJoystick(joystickId);
|
||||
if (joystick == nullptr)
|
||||
{
|
||||
errorMessage = "open_controller(): SDL_OpenJoystick Failed: ";
|
||||
errorMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_ERROR, errorMessage);
|
||||
continue;
|
||||
}
|
||||
|
||||
deviceName = string_from_const_char(SDL_GetJoystickName(joystick));
|
||||
devicePath = string_from_const_char(SDL_GetJoystickPath(joystick));
|
||||
deviceSerial = string_from_const_char(SDL_GetJoystickSerial(joystick));
|
||||
}
|
||||
|
||||
if (deviceName == profile->DeviceName &&
|
||||
devicePath == profile->DevicePath &&
|
||||
deviceSerial == profile->DeviceSerial)
|
||||
{
|
||||
profile->SDLJoystick = joystick;
|
||||
profile->SDLGamepad = gamepad;
|
||||
return;
|
||||
}
|
||||
|
||||
if (joystick != nullptr)
|
||||
{
|
||||
SDL_CloseJoystick(joystick);
|
||||
joystick = nullptr;
|
||||
}
|
||||
if (gamepad != nullptr)
|
||||
{
|
||||
SDL_CloseGamepad(gamepad);
|
||||
gamepad = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void close_controller(InputProfile* profile)
|
||||
{
|
||||
if (profile->SDLJoystick != nullptr)
|
||||
{
|
||||
SDL_CloseJoystick(profile->SDLJoystick);
|
||||
profile->SDLJoystick = nullptr;
|
||||
}
|
||||
if (profile->SDLGamepad != nullptr)
|
||||
{
|
||||
SDL_CloseGamepad(profile->SDLGamepad);
|
||||
profile->SDLGamepad = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_rumble_start(InputProfile* profile)
|
||||
{
|
||||
if (profile->SDLGamepad != nullptr)
|
||||
{
|
||||
SDL_RumbleGamepad(profile->SDLGamepad, 0xFFFF, 0xFFFF, SDL_HAPTIC_INFINITY);
|
||||
}
|
||||
else if (profile->SDLJoystick != nullptr)
|
||||
{
|
||||
SDL_RumbleJoystick(profile->SDLJoystick, 0xFFFF, 0xFFFF, SDL_HAPTIC_INFINITY);
|
||||
}
|
||||
}
|
||||
|
||||
static void controller_rumble_stop(InputProfile* profile)
|
||||
{
|
||||
if (profile->SDLGamepad != nullptr)
|
||||
{
|
||||
SDL_RumbleGamepad(profile->SDLGamepad, 0, 0, 0);
|
||||
}
|
||||
else if (profile->SDLJoystick != nullptr)
|
||||
{
|
||||
SDL_RumbleJoystick(profile->SDLJoystick, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void open_controllers(void)
|
||||
{
|
||||
// force re-fresh joystick list
|
||||
SDL_JoystickUpdate();
|
||||
SDL_UpdateJoysticks();
|
||||
|
||||
int joysticksCount = 0;
|
||||
SDL_JoystickID* joysticks = SDL_GetJoysticks(&joysticksCount);
|
||||
|
||||
for (int i = 0; i < NUM_CONTROLLERS; i++)
|
||||
{
|
||||
InputProfile* profile = &l_InputProfiles[i];
|
||||
|
||||
profile->InputDevice.CloseDevice();
|
||||
close_controller(profile);
|
||||
|
||||
if (profile->DeviceNum == static_cast<int>(InputDeviceType::Automatic))
|
||||
if (profile->DeviceType == InputDeviceType::Automatic)
|
||||
{
|
||||
setup_device_automatic(i, profile);
|
||||
open_controller_automatic(i, profile, joysticks, joysticksCount);
|
||||
}
|
||||
else if (profile->DeviceType == InputDeviceType::Joystick)
|
||||
{
|
||||
open_controller(profile, joysticks, joysticksCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (profile->DeviceNum != static_cast<int>(InputDeviceType::Keyboard))
|
||||
{
|
||||
profile->InputDevice.OpenDevice(profile->DeviceName, profile->DevicePath, profile->DeviceSerial, profile->DeviceNum);
|
||||
}
|
||||
if (joysticks != nullptr)
|
||||
{
|
||||
SDL_free(joysticks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,7 +726,7 @@ static void close_controllers(void)
|
||||
{
|
||||
InputProfile* profile = &l_InputProfiles[i];
|
||||
|
||||
profile->InputDevice.CloseDevice();
|
||||
close_controller(profile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,16 +745,16 @@ static int get_button_state(InputProfile* profile, const InputMapping* inputMapp
|
||||
{
|
||||
if (allPressed && i > 0)
|
||||
{
|
||||
state &= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
state &= SDL_GetGamepadButton(profile->SDLGamepad, (SDL_GamepadButton)data);
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
state |= SDL_GetGamepadButton(profile->SDLGamepad, (SDL_GamepadButton)data);
|
||||
}
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
int axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)data);
|
||||
int axis_value = SDL_GetGamepadAxis(profile->SDLGamepad, (SDL_GamepadAxis)data);
|
||||
if (allPressed && i > 0)
|
||||
{
|
||||
state &= (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (extraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
@@ -636,27 +768,27 @@ static int get_button_state(InputProfile* profile, const InputMapping* inputMapp
|
||||
{
|
||||
if (allPressed && i > 0)
|
||||
{
|
||||
state &= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
state &= SDL_GetJoystickButton(profile->SDLJoystick, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
state |= SDL_GetJoystickButton(profile->SDLJoystick, data);
|
||||
}
|
||||
} break;
|
||||
case InputType::JoystickHat:
|
||||
{
|
||||
if (allPressed && i > 0)
|
||||
{
|
||||
state &= (SDL_JoystickGetHat(profile->InputDevice.GetJoystickHandle(), data) & extraData) ? 1 : 0;
|
||||
state &= (SDL_GetJoystickHat(profile->SDLJoystick, data) & extraData) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state |= (SDL_JoystickGetHat(profile->InputDevice.GetJoystickHandle(), data) & extraData) ? 1 : 0;
|
||||
state |= (SDL_GetJoystickHat(profile->SDLJoystick, data) & extraData) ? 1 : 0;
|
||||
}
|
||||
} break;
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
int axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), data);
|
||||
int axis_value = SDL_GetJoystickAxis(profile->SDLJoystick, data);
|
||||
if (allPressed && i > 0)
|
||||
{
|
||||
state &= (abs(axis_value) >= (SDL_AXIS_PEAK / 2) && (extraData ? axis_value > 0 : axis_value < 0)) ? 1 : 0;
|
||||
@@ -706,11 +838,11 @@ static double get_axis_state(InputProfile* profile, const InputMapping* inputMap
|
||||
{
|
||||
case InputType::GamepadButton:
|
||||
{
|
||||
button_state |= SDL_GameControllerGetButton(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerButton)data);
|
||||
button_state |= SDL_GetGamepadButton(profile->SDLGamepad, (SDL_GamepadButton)data);
|
||||
} break;
|
||||
case InputType::GamepadAxis:
|
||||
{
|
||||
double axis_value = SDL_GameControllerGetAxis(profile->InputDevice.GetGameControllerHandle(), (SDL_GameControllerAxis)data);
|
||||
double axis_value = SDL_GetGamepadAxis(profile->SDLGamepad, (SDL_GamepadAxis)data);
|
||||
if (axis_value < -32767.0) axis_value = -32767.0;
|
||||
if (extraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
@@ -721,15 +853,15 @@ static double get_axis_state(InputProfile* profile, const InputMapping* inputMap
|
||||
} break;
|
||||
case InputType::JoystickButton:
|
||||
{
|
||||
button_state |= SDL_JoystickGetButton(profile->InputDevice.GetJoystickHandle(), data);
|
||||
button_state |= SDL_GetJoystickButton(profile->SDLJoystick, data);
|
||||
} break;
|
||||
case InputType::JoystickHat:
|
||||
{
|
||||
button_state |= (SDL_JoystickGetHat(profile->InputDevice.GetJoystickHandle(), data) & extraData) ? 1 : 0;
|
||||
button_state |= (SDL_GetJoystickHat(profile->SDLJoystick, data) & extraData) ? 1 : 0;
|
||||
} break;
|
||||
case InputType::JoystickAxis:
|
||||
{
|
||||
double axis_value = SDL_JoystickGetAxis(profile->InputDevice.GetJoystickHandle(), data);
|
||||
double axis_value = SDL_GetJoystickAxis(profile->SDLJoystick, data);
|
||||
if (axis_value < -32767.0) axis_value = -32767.0;
|
||||
if (extraData ? axis_value > 0 : axis_value < 0)
|
||||
{
|
||||
@@ -866,7 +998,7 @@ static bool check_hotkeys(int Control)
|
||||
|
||||
// we only have to check for hotkeys
|
||||
// when there's a controller opened
|
||||
if (!profile->InputDevice.HasOpenDevice())
|
||||
if (profile->SDLJoystick == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -936,7 +1068,7 @@ static void sdl_init()
|
||||
std::string debugMessage;
|
||||
int ret = -1;
|
||||
|
||||
for (const int subsystem : {SDL_INIT_GAMECONTROLLER, SDL_INIT_AUDIO, SDL_INIT_VIDEO, SDL_INIT_HAPTIC})
|
||||
for (const int subsystem : {SDL_INIT_GAMEPAD, SDL_INIT_HAPTIC})
|
||||
{
|
||||
if (!SDL_WasInit(subsystem))
|
||||
{
|
||||
@@ -950,10 +1082,10 @@ static void sdl_init()
|
||||
// try to load SDL_GameControllerDB when the file exists
|
||||
if (std::filesystem::is_regular_file(gameControllerDbPath))
|
||||
{
|
||||
ret = SDL_GameControllerAddMappingsFromFile(gameControllerDbPath.string().c_str());
|
||||
ret = SDL_AddGamepadMappingsFromFile(gameControllerDbPath.string().c_str());
|
||||
if (ret == -1)
|
||||
{
|
||||
debugMessage = "sdl_init(): SDL_GameControllerAddMappingsFromFile Failed: ";
|
||||
debugMessage = "sdl_init(): SDL_AddGamepadMappingsFromFile Failed: ";
|
||||
debugMessage += SDL_GetError();
|
||||
PluginDebugMessage(M64MSG_WARNING, debugMessage);
|
||||
}
|
||||
@@ -969,13 +1101,20 @@ static void sdl_init()
|
||||
|
||||
static void sdl_quit()
|
||||
{
|
||||
for (const int subsystem : {SDL_INIT_GAMECONTROLLER, SDL_INIT_HAPTIC})
|
||||
for (const int subsystem : {SDL_INIT_GAMEPAD, SDL_INIT_HAPTIC})
|
||||
{
|
||||
if (SDL_WasInit(subsystem))
|
||||
{
|
||||
SDL_QuitSubSystem(subsystem);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VRU
|
||||
if (HasVRUInitSDL() && SDL_WasInit(SDL_INIT_AUDIO))
|
||||
{
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@@ -998,11 +1137,6 @@ EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Con
|
||||
l_SDLThread = new Thread::SDLThread(nullptr);
|
||||
l_SDLThread->start();
|
||||
|
||||
for (int i = 0; i < NUM_CONTROLLERS; i++)
|
||||
{
|
||||
l_InputProfiles[i].InputDevice.SetSDLThread(l_SDLThread);
|
||||
}
|
||||
|
||||
l_HotkeysThread = new Thread::HotkeysThread(check_hotkeys, nullptr);
|
||||
l_HotkeysThread->start();
|
||||
|
||||
@@ -1184,11 +1318,11 @@ EXPORT void CALL ControllerCommand(int Control, unsigned char* Command)
|
||||
{
|
||||
if (*data)
|
||||
{
|
||||
profile->InputDevice.StartRumble();
|
||||
controller_rumble_start(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile->InputDevice.StopRumble();
|
||||
controller_rumble_stop(profile);
|
||||
}
|
||||
}
|
||||
data[32] = data_crc( data, 32 );
|
||||
@@ -1213,7 +1347,7 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
#ifdef VRU
|
||||
// when we're emulating the VRU,
|
||||
// we need to check the mic state
|
||||
if (profile->DeviceNum == static_cast<int>(InputDeviceType::EmulateVRU))
|
||||
if (profile->DeviceType == InputDeviceType::EmulateVRU)
|
||||
{
|
||||
if (GetVRUMicState())
|
||||
{
|
||||
@@ -1227,31 +1361,6 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
}
|
||||
#endif // VRU
|
||||
|
||||
#if 0 // TODO: fix hotplug support
|
||||
// check if device has been disconnected,
|
||||
// if it has, try to open it again,
|
||||
// only do this every 2 seconds to prevent lag
|
||||
const auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
const int secondsPassed = std::chrono::duration_cast<std::chrono::seconds>(currentTime - profile->LastDeviceCheckTime).count();
|
||||
if (secondsPassed >= 2)
|
||||
{
|
||||
profile->LastDeviceCheckTime = currentTime;
|
||||
|
||||
if (profile->DeviceNum != static_cast<int>(InputDeviceType::Keyboard))
|
||||
{
|
||||
if (profile->InputDevice.IsOpeningDevice())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!profile->InputDevice.HasOpenDevice() || !profile->InputDevice.IsAttached())
|
||||
{
|
||||
profile->InputDevice.OpenDevice(profile->DeviceName, profile->DevicePath, profile->DeviceSerial, profile->DeviceNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// when we've matched a hotkey,
|
||||
// we don't need to check anything
|
||||
// else
|
||||
@@ -1309,7 +1418,7 @@ EXPORT void CALL GetKeys(int Control, BUTTONS* Keys)
|
||||
|
||||
EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo)
|
||||
{
|
||||
for (int i = 0; i < SDL_NUM_SCANCODES; i++)
|
||||
for (int i = 0; i < SDL_SCANCODE_COUNT; i++)
|
||||
{
|
||||
l_KeyboardState[i] = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user