input_common: cache vibration tests

master
german77 2022-10-21 00:23:12 +07:00
parent 6b71530fa8
commit 7f66050f0c
10 changed files with 93 additions and 57 deletions

@ -100,7 +100,6 @@ enum class CameraError {
enum class VibrationAmplificationType { enum class VibrationAmplificationType {
Linear, Linear,
Exponential, Exponential,
Test,
}; };
// Analog properties for calibration // Analog properties for calibration
@ -325,6 +324,10 @@ public:
return VibrationError::NotSupported; return VibrationError::NotSupported;
} }
virtual bool IsVibrationEnabled() {
return false;
}
virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) { virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
return PollingError::NotSupported; return PollingError::NotSupported;
} }

@ -970,14 +970,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
Common::Input::VibrationError::None; Common::Input::VibrationError::None;
} }
bool EmulatedController::TestVibration(std::size_t device_index) { bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
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_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index]; const auto& player = Settings::values.players.GetValue()[player_index];
@ -985,31 +978,15 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
return false; return false;
} }
const Common::Input::VibrationStatus test_vibration = { if (device_index >= output_devices.size()) {
.low_amplitude = 0.001f, return false;
.low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency, }
.high_amplitude = 0.001f,
.high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
.type = Common::Input::VibrationAmplificationType::Test,
};
const Common::Input::VibrationStatus zero_vibration = { if (!output_devices[device_index]) {
.low_amplitude = DEFAULT_VIBRATION_VALUE.low_amplitude, return false;
.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 return output_devices[device_index]->IsVibrationEnabled();
output_devices[device_index]->SetVibration(test_vibration);
// Wait for about 15ms to ensure the controller is ready for the stop command
std::this_thread::sleep_for(std::chrono::milliseconds(15));
// Stop any vibration and return the result
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) {
@ -1234,12 +1211,6 @@ bool EmulatedController::IsConnected(bool get_temporary_value) const {
return is_connected; return is_connected;
} }
bool EmulatedController::IsVibrationEnabled() const {
const auto player_index = NpadIdTypeToIndex(npad_id_type);
const auto& player = Settings::values.players.GetValue()[player_index];
return player.vibration_enabled;
}
NpadIdType EmulatedController::GetNpadIdType() const { NpadIdType EmulatedController::GetNpadIdType() const {
std::scoped_lock lock{mutex}; std::scoped_lock lock{mutex};
return npad_id_type; return npad_id_type;

@ -206,9 +206,6 @@ public:
*/ */
bool IsConnected(bool get_temporary_value = false) const; bool IsConnected(bool get_temporary_value = false) const;
/// Returns true if vibration is enabled
bool IsVibrationEnabled() const;
/// Removes all callbacks created from input devices /// Removes all callbacks created from input devices
void UnloadInput(); void UnloadInput();
@ -339,7 +336,7 @@ public:
* Sends a small vibration to the output device * Sends a small vibration to the output device
* @return true if SetVibration was successfull * @return true if SetVibration was successfull
*/ */
bool TestVibration(std::size_t device_index); bool IsVibrationEnabled(std::size_t device_index);
/** /**
* Sets the desired data to be polled from a controller * Sets the desired data to be polled from a controller

@ -867,7 +867,7 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
return false; return false;
} }
if (!controller.device->IsVibrationEnabled()) { if (!controller.device->IsVibrationEnabled(device_index)) {
if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
// Send an empty vibration to stop any vibrations. // Send an empty vibration to stop any vibrations.
@ -1000,7 +1000,7 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
} }
controller.vibration[device_index].device_mounted = controller.vibration[device_index].device_mounted =
controller.device->TestVibration(device_index); controller.device->IsVibrationEnabled(device_index);
} }
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {

@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
return true; return true;
} }
Common::Input::VibrationError GCAdapter::SetRumble( Common::Input::VibrationError GCAdapter::SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
const auto processed_amplitude = const auto processed_amplitude =
@ -338,6 +338,10 @@ Common::Input::VibrationError GCAdapter::SetRumble(
return Common::Input::VibrationError::None; return Common::Input::VibrationError::None;
} }
bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
return rumble_enabled;
}
void GCAdapter::UpdateVibrations() { void GCAdapter::UpdateVibrations() {
// Use 8 states to keep the switching between on/off fast enough for // Use 8 states to keep the switching between on/off fast enough for
// a human to feel different vibration strenght // a human to feel different vibration strenght

@ -25,9 +25,11 @@ public:
explicit GCAdapter(std::string input_engine_); explicit GCAdapter(std::string input_engine_);
~GCAdapter() override; ~GCAdapter() override;
Common::Input::VibrationError SetRumble( Common::Input::VibrationError SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
bool IsVibrationEnabled(const PadIdentifier& identifier) override;
/// Used for automapping features /// Used for automapping features
std::vector<Common::ParamPackage> GetInputDevices() const override; std::vector<Common::ParamPackage> GetInputDevices() const override;
ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;

@ -114,6 +114,20 @@ public:
} }
return false; return false;
} }
void EnableVibration(bool is_enabled) {
has_vibration = is_enabled;
is_vibration_tested = true;
}
bool HasVibration() const {
return has_vibration;
}
bool IsVibrationTested() const {
return is_vibration_tested;
}
/** /**
* The Pad identifier of the joystick * The Pad identifier of the joystick
*/ */
@ -236,6 +250,8 @@ private:
u64 last_motion_update{}; u64 last_motion_update{};
bool has_gyro{false}; bool has_gyro{false};
bool has_accel{false}; bool has_accel{false};
bool has_vibration{false};
bool is_vibration_tested{false};
BasicMotion motion; BasicMotion motion;
}; };
@ -517,7 +533,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
return devices; return devices;
} }
Common::Input::VibrationError SDLDriver::SetRumble( Common::Input::VibrationError SDLDriver::SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto joystick = const auto joystick =
GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
@ -546,13 +562,6 @@ Common::Input::VibrationError SDLDriver::SetRumble(
.type = Common::Input::VibrationAmplificationType::Exponential, .type = Common::Input::VibrationAmplificationType::Exponential,
}; };
if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
if (!joystick->RumblePlay(new_vibration)) {
return Common::Input::VibrationError::Unknown;
}
return Common::Input::VibrationError::None;
}
vibration_queue.Push(VibrationRequest{ vibration_queue.Push(VibrationRequest{
.identifier = identifier, .identifier = identifier,
.vibration = new_vibration, .vibration = new_vibration,
@ -561,6 +570,45 @@ Common::Input::VibrationError SDLDriver::SetRumble(
return Common::Input::VibrationError::None; return Common::Input::VibrationError::None;
} }
bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
const auto joystick =
GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
constexpr Common::Input::VibrationStatus test_vibration{
.low_amplitude = 1,
.low_frequency = 160.0f,
.high_amplitude = 1,
.high_frequency = 320.0f,
.type = Common::Input::VibrationAmplificationType::Exponential,
};
constexpr Common::Input::VibrationStatus zero_vibration{
.low_amplitude = 0,
.low_frequency = 160.0f,
.high_amplitude = 0,
.high_frequency = 320.0f,
.type = Common::Input::VibrationAmplificationType::Exponential,
};
if (joystick->IsVibrationTested()) {
return joystick->HasVibration();
}
// First vibration might fail
joystick->RumblePlay(test_vibration);
// Wait for about 15ms to ensure the controller is ready for the stop command
std::this_thread::sleep_for(std::chrono::milliseconds(15));
if (!joystick->RumblePlay(zero_vibration)) {
joystick->EnableVibration(false);
return false;
}
joystick->EnableVibration(true);
return true;
}
void SDLDriver::SendVibrations() { void SDLDriver::SendVibrations() {
while (!vibration_queue.Empty()) { while (!vibration_queue.Empty()) {
VibrationRequest request; VibrationRequest request;

@ -61,9 +61,11 @@ public:
bool IsStickInverted(const Common::ParamPackage& params) override; bool IsStickInverted(const Common::ParamPackage& params) override;
Common::Input::VibrationError SetRumble( Common::Input::VibrationError SetVibration(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
bool IsVibrationEnabled(const PadIdentifier& identifier) override;
private: private:
struct VibrationRequest { struct VibrationRequest {
PadIdentifier identifier; PadIdentifier identifier;

@ -108,12 +108,17 @@ public:
[[maybe_unused]] const Common::Input::LedStatus& led_status) {} [[maybe_unused]] const Common::Input::LedStatus& led_status) {}
// Sets rumble to a controller // Sets rumble to a controller
virtual Common::Input::VibrationError SetRumble( virtual Common::Input::VibrationError SetVibration(
[[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::VibrationStatus& vibration) { [[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
return Common::Input::VibrationError::NotSupported; return Common::Input::VibrationError::NotSupported;
} }
// Returns true if device supports vibrations
virtual bool IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
return false;
}
// Sets polling mode to a controller // Sets polling mode to a controller
virtual Common::Input::PollingError SetPollingMode( virtual Common::Input::PollingError SetPollingMode(
[[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const PadIdentifier& identifier,

@ -763,7 +763,11 @@ public:
Common::Input::VibrationError SetVibration( Common::Input::VibrationError SetVibration(
const Common::Input::VibrationStatus& vibration_status) override { const Common::Input::VibrationStatus& vibration_status) override {
return input_engine->SetRumble(identifier, vibration_status); return input_engine->SetVibration(identifier, vibration_status);
}
bool IsVibrationEnabled() override {
return input_engine->IsVibrationEnabled(identifier);
} }
Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override { Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override {