mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-09-13 06:53:22 -06:00
make input system thread-safe
This commit is contained in:
@ -155,6 +155,7 @@ public:
|
|||||||
void setJoystick(int id);
|
void setJoystick(int id);
|
||||||
int getJoystickID() { return joystickID; }
|
int getJoystickID() { return joystickID; }
|
||||||
SDL_Joystick* getJoystick() { return joystick; }
|
SDL_Joystick* getJoystick() { return joystick; }
|
||||||
|
std::shared_ptr<SDL_mutex> getJoyMutex() { return joyMutex; }
|
||||||
|
|
||||||
void touchScreen(int x, int y);
|
void touchScreen(int x, int y);
|
||||||
void releaseScreen();
|
void releaseScreen();
|
||||||
@ -359,6 +360,9 @@ private:
|
|||||||
bool hasRumble = false;
|
bool hasRumble = false;
|
||||||
bool isRumbling = false;
|
bool isRumbling = false;
|
||||||
|
|
||||||
|
static std::shared_ptr<SDL_mutex> joyMutexGlobal;
|
||||||
|
std::shared_ptr<SDL_mutex> joyMutex;
|
||||||
|
|
||||||
melonDS::u32 keyInputMask, joyInputMask;
|
melonDS::u32 keyInputMask, joyInputMask;
|
||||||
melonDS::u32 keyHotkeyMask, joyHotkeyMask;
|
melonDS::u32 keyHotkeyMask, joyHotkeyMask;
|
||||||
melonDS::u32 hotkeyMask, lastHotkeyMask;
|
melonDS::u32 hotkeyMask, lastHotkeyMask;
|
||||||
|
@ -69,9 +69,18 @@ const char* EmuInstance::hotkeyNames[HK_MAX] =
|
|||||||
"HK_GuitarGripBlue"
|
"HK_GuitarGripBlue"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<SDL_mutex> EmuInstance::joyMutexGlobal = nullptr;
|
||||||
|
|
||||||
|
|
||||||
void EmuInstance::inputInit()
|
void EmuInstance::inputInit()
|
||||||
{
|
{
|
||||||
|
if (!joyMutexGlobal)
|
||||||
|
{
|
||||||
|
SDL_mutex* mutex = SDL_CreateMutex();
|
||||||
|
joyMutexGlobal = std::shared_ptr<SDL_mutex>(mutex, SDL_DestroyMutex);
|
||||||
|
}
|
||||||
|
joyMutex = joyMutexGlobal;
|
||||||
|
|
||||||
keyInputMask = 0xFFF;
|
keyInputMask = 0xFFF;
|
||||||
joyInputMask = 0xFFF;
|
joyInputMask = 0xFFF;
|
||||||
inputMask = 0xFFF;
|
inputMask = 0xFFF;
|
||||||
@ -91,16 +100,21 @@ void EmuInstance::inputInit()
|
|||||||
hasAccelerometer = false;
|
hasAccelerometer = false;
|
||||||
hasGyroscope = false;
|
hasGyroscope = false;
|
||||||
isRumbling = false;
|
isRumbling = false;
|
||||||
|
|
||||||
inputLoadConfig();
|
inputLoadConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::inputDeInit()
|
void EmuInstance::inputDeInit()
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
closeJoystick();
|
closeJoystick();
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::inputLoadConfig()
|
void EmuInstance::inputLoadConfig()
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
|
|
||||||
Config::Table keycfg = localCfg.GetTable("Keyboard");
|
Config::Table keycfg = localCfg.GetTable("Keyboard");
|
||||||
Config::Table joycfg = localCfg.GetTable("Joystick");
|
Config::Table joycfg = localCfg.GetTable("Joystick");
|
||||||
|
|
||||||
@ -117,35 +131,47 @@ void EmuInstance::inputLoadConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
setJoystick(localCfg.GetInt("JoystickID"));
|
setJoystick(localCfg.GetInt("JoystickID"));
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::inputRumbleStart(melonDS::u32 len_ms)
|
void EmuInstance::inputRumbleStart(melonDS::u32 len_ms)
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
|
|
||||||
if (controller && hasRumble && !isRumbling)
|
if (controller && hasRumble && !isRumbling)
|
||||||
{
|
{
|
||||||
SDL_GameControllerRumble(controller, 0xFFFF, 0xFFFF, len_ms);
|
SDL_GameControllerRumble(controller, 0xFFFF, 0xFFFF, len_ms);
|
||||||
isRumbling = true;
|
isRumbling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::inputRumbleStop()
|
void EmuInstance::inputRumbleStop()
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
|
|
||||||
if (controller && hasRumble && isRumbling)
|
if (controller && hasRumble && isRumbling)
|
||||||
{
|
{
|
||||||
SDL_GameControllerRumble(controller, 0, 0, 0);
|
SDL_GameControllerRumble(controller, 0, 0, 0);
|
||||||
isRumbling = false;
|
isRumbling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
||||||
{
|
{
|
||||||
float values[3];
|
float values[3];
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
if (type <= melonDS::Platform::MotionAccelerationZ)
|
if (type <= melonDS::Platform::MotionAccelerationZ)
|
||||||
{
|
{
|
||||||
if (controller && hasAccelerometer)
|
if (controller && hasAccelerometer)
|
||||||
|
{
|
||||||
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_ACCEL, values, 3) == 0)
|
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_ACCEL, values, 3) == 0)
|
||||||
{
|
{
|
||||||
// Map values from DS console orientation to SDL controller orientation.
|
// Map values from DS console orientation to SDL controller orientation.
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case melonDS::Platform::MotionAccelerationX:
|
case melonDS::Platform::MotionAccelerationX:
|
||||||
@ -156,13 +182,16 @@ float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
|||||||
return values[1];
|
return values[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (type <= melonDS::Platform::MotionRotationZ)
|
else if (type <= melonDS::Platform::MotionRotationZ)
|
||||||
{
|
{
|
||||||
if (controller && hasGyroscope)
|
if (controller && hasGyroscope)
|
||||||
|
{
|
||||||
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_GYRO, values, 3) == 0)
|
if (SDL_GameControllerGetSensorData(controller, SDL_SENSOR_GYRO, values, 3) == 0)
|
||||||
{
|
{
|
||||||
// Map values from DS console orientation to SDL controller orientation.
|
// Map values from DS console orientation to SDL controller orientation.
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case melonDS::Platform::MotionRotationX:
|
case melonDS::Platform::MotionRotationX:
|
||||||
@ -173,7 +202,9 @@ float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
|||||||
return values[1];
|
return values[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
if (type == melonDS::Platform::MotionAccelerationZ)
|
if (type == melonDS::Platform::MotionAccelerationZ)
|
||||||
return SDL_STANDARD_GRAVITY;
|
return SDL_STANDARD_GRAVITY;
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
@ -182,8 +213,10 @@ float EmuInstance::inputMotionQuery(melonDS::Platform::MotionQueryType type)
|
|||||||
|
|
||||||
void EmuInstance::setJoystick(int id)
|
void EmuInstance::setJoystick(int id)
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
joystickID = id;
|
joystickID = id;
|
||||||
openJoystick();
|
openJoystick();
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::openJoystick()
|
void EmuInstance::openJoystick()
|
||||||
@ -195,11 +228,11 @@ void EmuInstance::openJoystick()
|
|||||||
int num = SDL_NumJoysticks();
|
int num = SDL_NumJoysticks();
|
||||||
if (num < 1)
|
if (num < 1)
|
||||||
{
|
{
|
||||||
controller = nullptr;
|
controller = nullptr;
|
||||||
joystick = nullptr;
|
joystick = nullptr;
|
||||||
hasRumble = false;
|
hasRumble = false;
|
||||||
hasAccelerometer = false;
|
hasAccelerometer = false;
|
||||||
hasGyroscope = false;
|
hasGyroscope = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,23 +243,23 @@ void EmuInstance::openJoystick()
|
|||||||
|
|
||||||
if (SDL_IsGameController(joystickID))
|
if (SDL_IsGameController(joystickID))
|
||||||
{
|
{
|
||||||
controller = SDL_GameControllerOpen(joystickID);
|
controller = SDL_GameControllerOpen(joystickID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller)
|
if (controller)
|
||||||
{
|
{
|
||||||
if (SDL_GameControllerHasRumble(controller))
|
if (SDL_GameControllerHasRumble(controller))
|
||||||
{
|
{
|
||||||
hasRumble = true;
|
hasRumble = true;
|
||||||
}
|
}
|
||||||
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL))
|
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL))
|
||||||
{
|
{
|
||||||
hasAccelerometer = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE) == 0;
|
hasAccelerometer = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE) == 0;
|
||||||
}
|
}
|
||||||
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO))
|
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO))
|
||||||
{
|
{
|
||||||
hasGyroscope = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE) == 0;
|
hasGyroscope = SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE) == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,11 +267,11 @@ void EmuInstance::closeJoystick()
|
|||||||
{
|
{
|
||||||
if (controller)
|
if (controller)
|
||||||
{
|
{
|
||||||
SDL_GameControllerClose(controller);
|
SDL_GameControllerClose(controller);
|
||||||
controller = nullptr;
|
controller = nullptr;
|
||||||
hasRumble = false;
|
hasRumble = false;
|
||||||
hasAccelerometer = false;
|
hasAccelerometer = false;
|
||||||
hasGyroscope = false;
|
hasGyroscope = false;
|
||||||
}
|
}
|
||||||
if (joystick)
|
if (joystick)
|
||||||
{
|
{
|
||||||
@ -381,6 +414,7 @@ bool EmuInstance::joystickButtonDown(int val)
|
|||||||
|
|
||||||
void EmuInstance::inputProcess()
|
void EmuInstance::inputProcess()
|
||||||
{
|
{
|
||||||
|
SDL_LockMutex(joyMutex.get());
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
|
|
||||||
if (joystick)
|
if (joystick)
|
||||||
@ -418,6 +452,7 @@ void EmuInstance::inputProcess()
|
|||||||
hotkeyPress = hotkeyMask & ~lastHotkeyMask;
|
hotkeyPress = hotkeyMask & ~lastHotkeyMask;
|
||||||
hotkeyRelease = lastHotkeyMask & ~hotkeyMask;
|
hotkeyRelease = lastHotkeyMask & ~hotkeyMask;
|
||||||
lastHotkeyMask = hotkeyMask;
|
lastHotkeyMask = hotkeyMask;
|
||||||
|
SDL_UnlockMutex(joyMutex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuInstance::touchScreen(int x, int y)
|
void EmuInstance::touchScreen(int x, int y)
|
||||||
|
@ -153,7 +153,9 @@ void EmuThread::run()
|
|||||||
|
|
||||||
while (emuStatus != emuStatus_Exit)
|
while (emuStatus != emuStatus_Exit)
|
||||||
{
|
{
|
||||||
MPInterface::Get().Process();
|
if (emuInstance->instanceID == 0)
|
||||||
|
MPInterface::Get().Process();
|
||||||
|
|
||||||
emuInstance->inputProcess();
|
emuInstance->inputProcess();
|
||||||
|
|
||||||
if (emuInstance->hotkeyPressed(HK_FrameLimitToggle)) emit windowLimitFPSChange();
|
if (emuInstance->hotkeyPressed(HK_FrameLimitToggle)) emit windowLimitFPSChange();
|
||||||
|
@ -252,3 +252,8 @@ SDL_Joystick* InputConfigDialog::getJoystick()
|
|||||||
{
|
{
|
||||||
return emuInstance->getJoystick();
|
return emuInstance->getJoystick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SDL_mutex> InputConfigDialog::getJoyMutex()
|
||||||
|
{
|
||||||
|
return emuInstance->getJoyMutex();
|
||||||
|
}
|
||||||
|
@ -105,6 +105,7 @@ public:
|
|||||||
~InputConfigDialog();
|
~InputConfigDialog();
|
||||||
|
|
||||||
SDL_Joystick* getJoystick();
|
SDL_Joystick* getJoystick();
|
||||||
|
std::shared_ptr<SDL_mutex> getJoyMutex();
|
||||||
|
|
||||||
static InputConfigDialog* currentDlg;
|
static InputConfigDialog* currentDlg;
|
||||||
static InputConfigDialog* openDlg(QWidget* parent)
|
static InputConfigDialog* openDlg(QWidget* parent)
|
||||||
|
@ -220,7 +220,7 @@ protected:
|
|||||||
QPushButton::focusOutEvent(event);
|
QPushButton::focusOutEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timerEvent(QTimerEvent* event) override
|
void checkJoystick()
|
||||||
{
|
{
|
||||||
SDL_Joystick* joy = parentDialog->getJoystick();
|
SDL_Joystick* joy = parentDialog->getJoystick();
|
||||||
if (!joy) { click(); return; }
|
if (!joy) { click(); return; }
|
||||||
@ -287,6 +287,14 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void timerEvent(QTimerEvent* event) override
|
||||||
|
{
|
||||||
|
auto mutex = parentDialog->getJoyMutex();
|
||||||
|
SDL_LockMutex(mutex.get());
|
||||||
|
checkJoystick();
|
||||||
|
SDL_UnlockMutex(mutex.get());
|
||||||
|
}
|
||||||
|
|
||||||
bool focusNextPrevChild(bool next) override { return false; }
|
bool focusNextPrevChild(bool next) override { return false; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -299,6 +307,8 @@ private slots:
|
|||||||
|
|
||||||
memset(axesRest, 0, sizeof(axesRest));
|
memset(axesRest, 0, sizeof(axesRest));
|
||||||
|
|
||||||
|
auto mutex = parentDialog->getJoyMutex();
|
||||||
|
SDL_LockMutex(mutex.get());
|
||||||
SDL_Joystick* joy = parentDialog->getJoystick();
|
SDL_Joystick* joy = parentDialog->getJoystick();
|
||||||
if (joy && SDL_JoystickGetAttached(joy))
|
if (joy && SDL_JoystickGetAttached(joy))
|
||||||
{
|
{
|
||||||
@ -309,6 +319,7 @@ private slots:
|
|||||||
axesRest[a] = SDL_JoystickGetAxis(joy, a);
|
axesRest[a] = SDL_JoystickGetAxis(joy, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SDL_UnlockMutex(mutex.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user