summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface/Android
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface/Android')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Android/Android.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
index 058a9e3171..811343bf73 100644
--- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
@@ -62,6 +62,9 @@ jmethodID s_motion_event_get_source;
jclass s_controller_interface_class;
jmethodID s_controller_interface_register_input_device_listener;
jmethodID s_controller_interface_unregister_input_device_listener;
+jmethodID s_controller_interface_get_vibrator_manager;
+jmethodID s_controller_interface_get_system_vibrator_manager;
+jmethodID s_controller_interface_vibrate;
jclass s_sensor_event_listener_class;
jmethodID s_sensor_event_listener_constructor;
@@ -71,6 +74,10 @@ jmethodID s_sensor_event_listener_request_unsuspend_sensor;
jmethodID s_sensor_event_listener_get_axis_names;
jmethodID s_sensor_event_listener_get_negative_axes;
+jclass s_dolphin_vibrator_manager_class;
+jmethodID s_dolphin_vibrator_manager_get_vibrator;
+jmethodID s_dolphin_vibrator_manager_get_vibrator_ids;
+
jintArray s_keycodes_array;
using Clock = std::chrono::steady_clock;
@@ -534,6 +541,35 @@ private:
std::atomic<bool> m_is_suspended = true;
};
+class AndroidMotor : public Core::Device::Output
+{
+public:
+ AndroidMotor(JNIEnv* env, jobject vibrator, jint id)
+ : m_vibrator(env->NewGlobalRef(vibrator)), m_id(id)
+ {
+ }
+
+ ~AndroidMotor() { IDCache::GetEnvForThread()->DeleteGlobalRef(m_vibrator); }
+
+ std::string GetName() const override { return "Motor " + std::to_string(m_id); }
+
+ void SetState(ControlState state) override
+ {
+ ControlState old_state = m_state.exchange(state, std::memory_order_relaxed);
+
+ if (old_state < 0.5 && state >= 0.5)
+ {
+ IDCache::GetEnvForThread()->CallStaticVoidMethod(s_controller_interface_class,
+ s_controller_interface_vibrate, m_vibrator);
+ }
+ }
+
+private:
+ const jobject m_vibrator;
+ const jint m_id;
+ std::atomic<ControlState> m_state = 0;
+};
+
class AndroidDevice final : public Core::Device
{
public:
@@ -551,6 +587,7 @@ public:
AddKeys(env, input_device);
AddAxes(env, input_device);
+ AddMotors(env, input_device);
}
// Constructor for the device added by Dolphin to contain sensor inputs
@@ -558,6 +595,7 @@ public:
: m_sensor_event_listener(AddSensors(env, nullptr)), m_source(AINPUT_SOURCE_SENSOR),
m_controller_number(0), m_name(std::move(name))
{
+ AddSystemMotors(env);
}
~AndroidDevice()
@@ -687,6 +725,41 @@ private:
return sensor_event_listener;
}
+ void AddMotors(JNIEnv* env, jobject input_device)
+ {
+ jobject vibrator_manager = env->CallStaticObjectMethod(
+ s_controller_interface_class, s_controller_interface_get_vibrator_manager, input_device);
+ AddMotorsFromManager(env, vibrator_manager);
+ env->DeleteLocalRef(vibrator_manager);
+ }
+
+ void AddSystemMotors(JNIEnv* env)
+ {
+ jobject vibrator_manager = env->CallStaticObjectMethod(
+ s_controller_interface_class, s_controller_interface_get_system_vibrator_manager);
+ AddMotorsFromManager(env, vibrator_manager);
+ env->DeleteLocalRef(vibrator_manager);
+ }
+
+ void AddMotorsFromManager(JNIEnv* env, jobject vibrator_manager)
+ {
+ jintArray j_vibrator_ids = reinterpret_cast<jintArray>(
+ env->CallObjectMethod(vibrator_manager, s_dolphin_vibrator_manager_get_vibrator_ids));
+ jint* vibrator_ids = env->GetIntArrayElements(j_vibrator_ids, nullptr);
+
+ jint size = env->GetArrayLength(j_vibrator_ids);
+ for (jint i = 0; i < size; ++i)
+ {
+ jobject vibrator =
+ env->CallObjectMethod(vibrator_manager, s_dolphin_vibrator_manager_get_vibrator, i);
+ AddOutput(new AndroidMotor(env, vibrator, i));
+ env->DeleteLocalRef(vibrator);
+ }
+
+ env->ReleaseIntArrayElements(j_vibrator_ids, vibrator_ids, 0);
+ env->DeleteLocalRef(j_vibrator_ids);
+ }
+
const jobject m_sensor_event_listener;
const int m_source;
const int m_controller_number;
@@ -764,6 +837,15 @@ void Init()
env->GetStaticMethodID(s_controller_interface_class, "registerInputDeviceListener", "()V");
s_controller_interface_unregister_input_device_listener =
env->GetStaticMethodID(s_controller_interface_class, "unregisterInputDeviceListener", "()V");
+ s_controller_interface_get_vibrator_manager =
+ env->GetStaticMethodID(s_controller_interface_class, "getVibratorManager",
+ "(Landroid/view/InputDevice;)Lorg/dolphinemu/dolphinemu/features/"
+ "input/model/DolphinVibratorManager;");
+ s_controller_interface_get_system_vibrator_manager = env->GetStaticMethodID(
+ s_controller_interface_class, "getSystemVibratorManager",
+ "()Lorg/dolphinemu/dolphinemu/features/input/model/DolphinVibratorManager;");
+ s_controller_interface_vibrate =
+ env->GetStaticMethodID(s_controller_interface_class, "vibrate", "(Landroid/os/Vibrator;)V");
const jclass sensor_event_listener_class =
env->FindClass("org/dolphinemu/dolphinemu/features/input/model/DolphinSensorEventListener");
@@ -782,6 +864,15 @@ void Init()
s_sensor_event_listener_get_negative_axes =
env->GetMethodID(s_sensor_event_listener_class, "getNegativeAxes", "()[Z");
+ const jclass dolphin_vibrator_manager_class =
+ env->FindClass("org/dolphinemu/dolphinemu/features/input/model/DolphinVibratorManager");
+ s_dolphin_vibrator_manager_class =
+ reinterpret_cast<jclass>(env->NewGlobalRef(dolphin_vibrator_manager_class));
+ s_dolphin_vibrator_manager_get_vibrator =
+ env->GetMethodID(s_dolphin_vibrator_manager_class, "getVibrator", "(I)Landroid/os/Vibrator;");
+ s_dolphin_vibrator_manager_get_vibrator_ids =
+ env->GetMethodID(s_dolphin_vibrator_manager_class, "getVibratorIds", "()[I");
+
jintArray keycodes_array = CreateKeyCodesArray(env);
s_keycodes_array = reinterpret_cast<jintArray>(env->NewGlobalRef(keycodes_array));
env->DeleteLocalRef(keycodes_array);
@@ -804,6 +895,7 @@ void Shutdown()
env->DeleteGlobalRef(s_motion_event_class);
env->DeleteGlobalRef(s_controller_interface_class);
env->DeleteGlobalRef(s_sensor_event_listener_class);
+ env->DeleteGlobalRef(s_dolphin_vibrator_manager_class);
env->DeleteGlobalRef(s_keycodes_array);
}