android: Play vibrations asynchronously
This commit is contained in:
parent
975d6f1ec4
commit
0369c65870
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <set>
|
||||
#include <common/settings_input.h>
|
||||
#include <common/thread.h>
|
||||
#include <jni.h>
|
||||
#include "common/android/android_common.h"
|
||||
#include "common/android/id_cache.h"
|
||||
|
@ -10,7 +11,18 @@
|
|||
|
||||
namespace InputCommon {
|
||||
|
||||
Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {}
|
||||
Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
|
||||
vibration_thread = std::jthread([this](std::stop_token token) {
|
||||
Common::SetCurrentThreadName("Android_Vibration");
|
||||
auto env = Common::Android::GetEnvForThread();
|
||||
using namespace std::chrono_literals;
|
||||
while (!token.stop_requested()) {
|
||||
SendVibrations(env, token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Android::~Android() = default;
|
||||
|
||||
void Android::RegisterController(jobject j_input_device) {
|
||||
auto env = Common::Android::GetEnvForThread();
|
||||
|
@ -57,17 +69,11 @@ void Android::SetMotionState(std::string guid, size_t port, u64 delta_timestamp,
|
|||
Common::Input::DriverResult Android::SetVibration(
|
||||
[[maybe_unused]] const PadIdentifier& identifier,
|
||||
[[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
|
||||
auto device = input_devices.find(identifier);
|
||||
if (device != input_devices.end()) {
|
||||
Common::Android::RunJNIOnFiber<void>([&](JNIEnv* env) {
|
||||
float average_intensity =
|
||||
static_cast<float>((vibration.high_amplitude + vibration.low_amplitude) / 2.0);
|
||||
env->CallVoidMethod(device->second, Common::Android::GetYuzuDeviceVibrate(),
|
||||
average_intensity);
|
||||
});
|
||||
return Common::Input::DriverResult::Success;
|
||||
}
|
||||
return Common::Input::DriverResult::NotSupported;
|
||||
vibration_queue.Push(VibrationRequest{
|
||||
.identifier = identifier,
|
||||
.vibration = vibration,
|
||||
});
|
||||
return Common::Input::DriverResult::Success;
|
||||
}
|
||||
|
||||
bool Android::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
|
||||
|
@ -347,4 +353,15 @@ PadIdentifier Android::GetIdentifier(const std::string& guid, size_t port) const
|
|||
};
|
||||
}
|
||||
|
||||
void Android::SendVibrations(JNIEnv* env, std::stop_token token) {
|
||||
VibrationRequest request = vibration_queue.PopWait(token);
|
||||
auto device = input_devices.find(request.identifier);
|
||||
if (device != input_devices.end()) {
|
||||
float average_intensity = static_cast<float>(
|
||||
(request.vibration.high_amplitude + request.vibration.low_amplitude) / 2.0);
|
||||
env->CallVoidMethod(device->second, Common::Android::GetYuzuDeviceVibrate(),
|
||||
average_intensity);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace InputCommon
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <common/threadsafe_queue.h>
|
||||
#include <jni.h>
|
||||
#include "input_common/input_engine.h"
|
||||
|
||||
|
@ -16,6 +17,8 @@ class Android final : public InputEngine {
|
|||
public:
|
||||
explicit Android(std::string input_engine_);
|
||||
|
||||
~Android() override;
|
||||
|
||||
/**
|
||||
* Registers controller number to accept new inputs.
|
||||
* @param j_input_device YuzuInputDevice object from the Android frontend to register.
|
||||
|
@ -89,6 +92,9 @@ private:
|
|||
/// Returns the correct identifier corresponding to the player index
|
||||
PadIdentifier GetIdentifier(const std::string& guid, size_t port) const;
|
||||
|
||||
/// Takes all vibrations from the queue and sends the command to the controller
|
||||
void SendVibrations(JNIEnv* env, std::stop_token token);
|
||||
|
||||
static constexpr s32 AXIS_X = 0;
|
||||
static constexpr s32 AXIS_Y = 1;
|
||||
static constexpr s32 AXIS_Z = 11;
|
||||
|
@ -133,6 +139,10 @@ private:
|
|||
redmagic_vid, backbone_labs_vid, xbox_vid};
|
||||
const std::vector<std::string> flipped_xy_vids{sony_vid, razer_vid, redmagic_vid,
|
||||
backbone_labs_vid, xbox_vid};
|
||||
|
||||
/// Queue of vibration request to controllers
|
||||
Common::SPSCQueue<VibrationRequest> vibration_queue;
|
||||
std::jthread vibration_thread;
|
||||
};
|
||||
|
||||
} // namespace InputCommon
|
||||
|
|
|
@ -69,11 +69,6 @@ public:
|
|||
bool IsVibrationEnabled(const PadIdentifier& identifier) override;
|
||||
|
||||
private:
|
||||
struct VibrationRequest {
|
||||
PadIdentifier identifier;
|
||||
Common::Input::VibrationStatus vibration;
|
||||
};
|
||||
|
||||
void InitJoystick(int joystick_index);
|
||||
void CloseJoystick(SDL_Joystick* sdl_joystick);
|
||||
|
||||
|
|
|
@ -46,6 +46,11 @@ enum class EngineInputType {
|
|||
Nfc,
|
||||
};
|
||||
|
||||
struct VibrationRequest {
|
||||
PadIdentifier identifier;
|
||||
Common::Input::VibrationStatus vibration;
|
||||
};
|
||||
|
||||
namespace std {
|
||||
// Hash used to create lists from PadIdentifier data
|
||||
template <>
|
||||
|
|
Reference in New Issue