forked from eden-emu/eden
		
	Merge pull request #13142 from t895/vibration-queue
android: Play vibrations asynchronously
This commit is contained in:
		
						commit
						d1e0039bc8
					
				
					 4 changed files with 44 additions and 17 deletions
				
			
		|  | @ -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,18 +69,12 @@ 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); | ||||
|     vibration_queue.Push(VibrationRequest{ | ||||
|         .identifier = identifier, | ||||
|         .vibration = vibration, | ||||
|     }); | ||||
|     return Common::Input::DriverResult::Success; | ||||
| } | ||||
|     return Common::Input::DriverResult::NotSupported; | ||||
| } | ||||
| 
 | ||||
| bool Android::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { | ||||
|     auto device = input_devices.find(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 <> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 liamwhite
						liamwhite