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