input_common: Make vibration request async

This commit is contained in:
Narr the Reg 2022-05-23 11:33:34 -05:00
parent 4eb7f6c044
commit bf948b5790
4 changed files with 63 additions and 7 deletions

View File

@ -72,6 +72,7 @@ enum class PollingError {
enum class VibrationAmplificationType { enum class VibrationAmplificationType {
Linear, Linear,
Exponential, Exponential,
Test,
}; };
// Analog properties for calibration // Analog properties for calibration

View File

@ -884,18 +884,42 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
} }
bool EmulatedController::TestVibration(std::size_t device_index) { bool EmulatedController::TestVibration(std::size_t device_index) {
static constexpr VibrationValue test_vibration = { if (device_index >= output_devices.size()) {
return false;
}
if (!output_devices[device_index]) {
return false;
}
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
if (!player.vibration_enabled) {
return false;
}
const Common::Input::VibrationStatus test_vibration = {
.low_amplitude = 0.001f, .low_amplitude = 0.001f,
.low_frequency = 160.0f, .low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency,
.high_amplitude = 0.001f, .high_amplitude = 0.001f,
.high_frequency = 320.0f, .high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
.type = Common::Input::VibrationAmplificationType::Test,
};
const Common::Input::VibrationStatus zero_vibration = {
.low_amplitude = DEFAULT_VIBRATION_VALUE.low_amplitude,
.low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency,
.high_amplitude = DEFAULT_VIBRATION_VALUE.high_amplitude,
.high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
.type = Common::Input::VibrationAmplificationType::Test,
}; };
// Send a slight vibration to test for rumble support // Send a slight vibration to test for rumble support
SetVibration(device_index, test_vibration); output_devices[device_index]->SetVibration(test_vibration);
// Stop any vibration and return the result // Stop any vibration and return the result
return SetVibration(device_index, DEFAULT_VIBRATION_VALUE); return output_devices[device_index]->SetVibration(zero_vibration) ==
Common::Input::VibrationError::None;
} }
bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) { bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {

View File

@ -434,6 +434,7 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
using namespace std::chrono_literals; using namespace std::chrono_literals;
while (initialized) { while (initialized) {
SDL_PumpEvents(); SDL_PumpEvents();
SendVibrations();
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
} }
}); });
@ -531,13 +532,31 @@ Common::Input::VibrationError SDLDriver::SetRumble(
.type = Common::Input::VibrationAmplificationType::Exponential, .type = Common::Input::VibrationAmplificationType::Exponential,
}; };
if (!joystick->RumblePlay(new_vibration)) { if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
return Common::Input::VibrationError::Unknown; if (!joystick->RumblePlay(new_vibration)) {
return Common::Input::VibrationError::Unknown;
}
return Common::Input::VibrationError::None;
} }
vibration_queue.Push(VibrationRequest{
.identifier = identifier,
.vibration = new_vibration,
});
return Common::Input::VibrationError::None; return Common::Input::VibrationError::None;
} }
void SDLDriver::SendVibrations() {
while (!vibration_queue.Empty()) {
VibrationRequest request;
vibration_queue.Pop(request);
const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
static_cast<int>(request.identifier.port));
joystick->RumblePlay(request.vibration);
}
}
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
s32 axis, float value) const { s32 axis, float value) const {
Common::ParamPackage params{}; Common::ParamPackage params{};

View File

@ -12,6 +12,7 @@
#include <SDL.h> #include <SDL.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/threadsafe_queue.h"
#include "input_common/input_engine.h" #include "input_common/input_engine.h"
union SDL_Event; union SDL_Event;
@ -64,12 +65,20 @@ public:
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
private: private:
struct VibrationRequest {
PadIdentifier identifier;
Common::Input::VibrationStatus vibration;
};
void InitJoystick(int joystick_index); void InitJoystick(int joystick_index);
void CloseJoystick(SDL_Joystick* sdl_joystick); void CloseJoystick(SDL_Joystick* sdl_joystick);
/// Needs to be called before SDL_QuitSubSystem. /// Needs to be called before SDL_QuitSubSystem.
void CloseJoysticks(); void CloseJoysticks();
/// Takes all vibrations from the queue and sends the command to the controller
void SendVibrations();
Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
float value = 0.1f) const; float value = 0.1f) const;
Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid,
@ -107,6 +116,9 @@ private:
/// Returns true if the button is on the left joycon /// Returns true if the button is on the left joycon
bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const;
/// Queue of vibration request to controllers
Common::SPSCQueue<VibrationRequest> vibration_queue;
/// Map of GUID of a list of corresponding virtual Joysticks /// Map of GUID of a list of corresponding virtual Joysticks
std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
std::mutex joystick_map_mutex; std::mutex joystick_map_mutex;