android: do all rumble/haptic on background thread
Haptic effects for the virtual gamepad must be done on a background thread. Not sure about gamepad rumble but it shouldn't hurt. Reuse haptic duration for haptic power (0-100). Fix crash when power is zero (createOneShot needs power >= 1)
This commit is contained in:
parent
aafa9f0bf0
commit
f1fd8b12e2
|
@ -1441,7 +1441,7 @@ static void gamepadSettingsPopup(const std::shared_ptr<GamepadDevice>& gamepad)
|
|||
if (gamepad->is_virtual_gamepad())
|
||||
{
|
||||
header("Haptic");
|
||||
OptionSlider("Power", config::VirtualGamepadVibration, 0, 60, "Haptic feedback power");
|
||||
OptionSlider("Power", config::VirtualGamepadVibration, 0, 100, "Haptic feedback power", "%d%%");
|
||||
}
|
||||
else if (gamepad->is_rumble_enabled())
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@ public class Emulator extends Application {
|
|||
public static final int MDT_Microphone = 2;
|
||||
public static final int MDT_None = 8;
|
||||
|
||||
public static int vibrationDuration = 20;
|
||||
public static int vibrationPower = 80;
|
||||
|
||||
public static int[] maple_devices = {
|
||||
MDT_None,
|
||||
|
@ -42,7 +42,7 @@ public class Emulator extends Application {
|
|||
*
|
||||
*/
|
||||
public void getConfigurationPrefs() {
|
||||
Emulator.vibrationDuration = JNIdc.getVirtualGamepadVibration();
|
||||
Emulator.vibrationPower = JNIdc.getVirtualGamepadVibration();
|
||||
JNIdc.getControllers(maple_devices, maple_expansion_devices);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class Emulator extends Application {
|
|||
{
|
||||
Log.i("flycast", "SaveAndroidSettings: saving preferences");
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
Emulator.vibrationDuration = JNIdc.getVirtualGamepadVibration();
|
||||
Emulator.vibrationPower = JNIdc.getVirtualGamepadVibration();
|
||||
JNIdc.getControllers(maple_devices, maple_expansion_devices);
|
||||
|
||||
prefs.edit()
|
||||
|
|
|
@ -105,12 +105,31 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene
|
|||
}
|
||||
}
|
||||
|
||||
private void vibrate(Vibrator vibrator, long duration_ms, float power)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
int ipow = Math.min((int)(power * 255), 255);
|
||||
if (ipow >= 1)
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(duration_ms, ipow));
|
||||
else
|
||||
vibrator.cancel();
|
||||
}
|
||||
else
|
||||
vibrator.vibrate(duration_ms);
|
||||
}
|
||||
|
||||
// Called from native code
|
||||
// returns false if the device has no vibrator
|
||||
private boolean rumble(int i, float power, float inclination, int duration_ms)
|
||||
{
|
||||
Vibrator vibrator = getVibrator(i);
|
||||
if (vibrator == null)
|
||||
return false;
|
||||
if (i == VIRTUAL_GAMEPAD_ID) {
|
||||
if (Emulator.vibrationPower == 0)
|
||||
return true;
|
||||
power *= Emulator.vibrationPower / 100.f;
|
||||
}
|
||||
|
||||
VibrationParams params;
|
||||
synchronized (this) {
|
||||
|
@ -120,25 +139,15 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene
|
|||
vibParams.put(i, params);
|
||||
}
|
||||
}
|
||||
if (power == 0) {
|
||||
if (params.power != 0)
|
||||
vibrator.cancel();
|
||||
} else {
|
||||
if (inclination > 0) {
|
||||
params.inclination = inclination * power;
|
||||
params.stopTime = System.currentTimeMillis() + duration_ms;
|
||||
}
|
||||
else {
|
||||
params.inclination = 0;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(duration_ms, (int)(power * 255)));
|
||||
else
|
||||
vibrator.vibrate(duration_ms);
|
||||
if (power != 0) {
|
||||
params.stopTime = System.currentTimeMillis() + duration_ms;
|
||||
if (inclination > 0)
|
||||
VibratorThread.getInstance().setVibrating();
|
||||
params.inclination = inclination * power;
|
||||
else
|
||||
params.inclination = 0;
|
||||
}
|
||||
params.power = power;
|
||||
VibratorThread.getInstance().setVibrating();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -164,19 +173,19 @@ public final class InputDeviceManager implements InputManager.InputDeviceListene
|
|||
synchronized (this) {
|
||||
params = vibParams.get(i);
|
||||
}
|
||||
if (vibrator == null || params == null || params.power == 0 || params.inclination == 0)
|
||||
if (vibrator == null || params == null)
|
||||
return false;
|
||||
long remTime = params.stopTime - System.currentTimeMillis();
|
||||
if (remTime <= 0) {
|
||||
if (remTime <= 0 || params.power == 0) {
|
||||
params.power = 0;
|
||||
params.inclination = 0;
|
||||
vibrator.cancel();
|
||||
return false;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(remTime, (int)(params.inclination * remTime * 255)));
|
||||
if (params.inclination > 0)
|
||||
vibrate(vibrator, remTime, params.inclination * remTime);
|
||||
else
|
||||
vibrator.vibrate(remTime);
|
||||
vibrate(vibrator, remTime, params.power);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public class VibratorThread extends Thread {
|
|||
private VibrationEffect clickEffect = null;
|
||||
int clickDuration = 0;
|
||||
private static VibratorThread INSTANCE = null;
|
||||
private static final int LEGACY_VIBRATION_DURATION = 20; // ms
|
||||
|
||||
public static VibratorThread getInstance() {
|
||||
synchronized (VibratorThread.class) {
|
||||
|
@ -52,7 +53,11 @@ public class VibratorThread extends Thread {
|
|||
private Vibrator getVibrator(int i)
|
||||
{
|
||||
if (i == InputDeviceManager.VIRTUAL_GAMEPAD_ID) {
|
||||
return (Vibrator) Emulator.getAppContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
if (Emulator.vibrationPower > 0)
|
||||
return (Vibrator) Emulator.getAppContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
else
|
||||
// vibration disabled
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
InputDevice device = InputDevice.getDevice(i);
|
||||
|
@ -111,7 +116,7 @@ public class VibratorThread extends Thread {
|
|||
}
|
||||
|
||||
public void click() {
|
||||
if (Emulator.vibrationDuration > 0) {
|
||||
if (Emulator.vibrationPower > 0) {
|
||||
synchronized (this) {
|
||||
click = true;
|
||||
notify();
|
||||
|
@ -126,17 +131,16 @@ public class VibratorThread extends Thread {
|
|||
return;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
{
|
||||
if (clickEffect == null || clickDuration != Emulator.vibrationDuration)
|
||||
if (clickEffect == null)
|
||||
{
|
||||
clickDuration = Emulator.vibrationDuration;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
clickEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
|
||||
else
|
||||
clickEffect = VibrationEffect.createOneShot(clickDuration, VibrationEffect.DEFAULT_AMPLITUDE);
|
||||
clickEffect = VibrationEffect.createOneShot(LEGACY_VIBRATION_DURATION, VibrationEffect.DEFAULT_AMPLITUDE);
|
||||
}
|
||||
vibrator.vibrate(clickEffect);
|
||||
} else {
|
||||
vibrator.vibrate(Emulator.vibrationDuration);
|
||||
vibrator.vibrate(LEGACY_VIBRATION_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,8 +148,7 @@ public class VibratorThread extends Thread {
|
|||
{
|
||||
// FIXME possible race condition
|
||||
synchronized (this) {
|
||||
if (nextRumbleUpdate == 0)
|
||||
nextRumbleUpdate = System.currentTimeMillis() + 16667;
|
||||
nextRumbleUpdate = 1;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue