android: Add RGB LED support for joysticks.
This commit is contained in:
@@ -6,6 +6,11 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.hardware.lights.Light;
|
||||||
|
import android.hardware.lights.LightsRequest;
|
||||||
|
import android.hardware.lights.LightsManager;
|
||||||
|
import android.hardware.lights.LightState;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
@@ -25,7 +30,7 @@ public class SDLControllerManager
|
|||||||
static native void nativeAddJoystick(int device_id, String name, String desc,
|
static native void nativeAddJoystick(int device_id, String name, String desc,
|
||||||
int vendor_id, int product_id,
|
int vendor_id, int product_id,
|
||||||
int button_mask,
|
int button_mask,
|
||||||
int naxes, int axis_mask, int nhats, boolean can_rumble);
|
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
|
||||||
static native void nativeRemoveJoystick(int device_id);
|
static native void nativeRemoveJoystick(int device_id);
|
||||||
static native void nativeAddHaptic(int device_id, String name);
|
static native void nativeAddHaptic(int device_id, String name);
|
||||||
static native void nativeRemoveHaptic(int device_id);
|
static native void nativeRemoveHaptic(int device_id);
|
||||||
@@ -69,6 +74,13 @@ public class SDLControllerManager
|
|||||||
mJoystickHandler.pollInputDevices();
|
mJoystickHandler.pollInputDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called by SDL using JNI.
|
||||||
|
*/
|
||||||
|
static void joystickSetLED(int device_id, int red, int green, int blue) {
|
||||||
|
mJoystickHandler.setLED(device_id, red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called by SDL using JNI.
|
* This method is called by SDL using JNI.
|
||||||
*/
|
*/
|
||||||
@@ -139,6 +151,8 @@ class SDLJoystickHandler {
|
|||||||
String desc;
|
String desc;
|
||||||
ArrayList<InputDevice.MotionRange> axes;
|
ArrayList<InputDevice.MotionRange> axes;
|
||||||
ArrayList<InputDevice.MotionRange> hats;
|
ArrayList<InputDevice.MotionRange> hats;
|
||||||
|
ArrayList<Light> lights;
|
||||||
|
LightsManager.LightsSession lightsSession;
|
||||||
}
|
}
|
||||||
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||||
@Override
|
@Override
|
||||||
@@ -211,6 +225,7 @@ class SDLJoystickHandler {
|
|||||||
joystick.desc = getJoystickDescriptor(joystickDevice);
|
joystick.desc = getJoystickDescriptor(joystickDevice);
|
||||||
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
||||||
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
||||||
|
joystick.lights = new ArrayList<Light>();
|
||||||
|
|
||||||
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
||||||
Collections.sort(ranges, new RangeComparator());
|
Collections.sort(ranges, new RangeComparator());
|
||||||
@@ -225,18 +240,30 @@ class SDLJoystickHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean can_rumble = false;
|
boolean can_rumble = false;
|
||||||
|
boolean has_rgb_led = false;
|
||||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||||
VibratorManager manager = joystickDevice.getVibratorManager();
|
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
|
||||||
int[] vibrators = manager.getVibratorIds();
|
int[] vibrators = vibratorManager.getVibratorIds();
|
||||||
if (vibrators.length > 0) {
|
if (vibrators.length > 0) {
|
||||||
can_rumble = true;
|
can_rumble = true;
|
||||||
}
|
}
|
||||||
|
LightsManager lightsManager = joystickDevice.getLightsManager();
|
||||||
|
List<Light> lights = lightsManager.getLights();
|
||||||
|
for (Light light : lights) {
|
||||||
|
if (light.hasRgbControl()) {
|
||||||
|
joystick.lights.add(light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!joystick.lights.isEmpty()) {
|
||||||
|
joystick.lightsSession = lightsManager.openSession();
|
||||||
|
has_rgb_led = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mJoysticks.add(joystick);
|
mJoysticks.add(joystick);
|
||||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||||
getVendorId(joystickDevice), getProductId(joystickDevice),
|
getVendorId(joystickDevice), getProductId(joystickDevice),
|
||||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble);
|
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,6 +289,16 @@ class SDLJoystickHandler {
|
|||||||
SDLControllerManager.nativeRemoveJoystick(device_id);
|
SDLControllerManager.nativeRemoveJoystick(device_id);
|
||||||
for (int i = 0; i < mJoysticks.size(); i++) {
|
for (int i = 0; i < mJoysticks.size(); i++) {
|
||||||
if (mJoysticks.get(i).device_id == device_id) {
|
if (mJoysticks.get(i).device_id == device_id) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||||
|
if (mJoysticks.get(i).lightsSession != null) {
|
||||||
|
try {
|
||||||
|
mJoysticks.get(i).lightsSession.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Session may already be unregistered when device disconnects
|
||||||
|
}
|
||||||
|
mJoysticks.get(i).lightsSession = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
mJoysticks.remove(i);
|
mJoysticks.remove(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -453,6 +490,24 @@ class SDLJoystickHandler {
|
|||||||
}
|
}
|
||||||
return button_mask;
|
return button_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setLED(int device_id, int red, int green, int blue) {
|
||||||
|
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDLJoystick joystick = getJoystick(device_id);
|
||||||
|
if (joystick == null || joystick.lights.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LightsRequest.Builder lightsRequest = new LightsRequest.Builder();
|
||||||
|
LightState lightState = new LightState.Builder().setColor(Color.rgb(red, green, blue)).build();
|
||||||
|
for (Light light : joystick.lights) {
|
||||||
|
if (light.hasRgbControl()) {
|
||||||
|
lightsRequest.addLight(light, lightState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
joystick.lightsSession.requestLights(lightsRequest.build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
|||||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id,
|
jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id,
|
||||||
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble);
|
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble, jboolean has_rgb_led);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
@@ -334,7 +334,7 @@ static JNINativeMethod SDLControllerManager_tab[] = {
|
|||||||
{ "onNativePadUp", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
{ "onNativePadUp", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||||
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
||||||
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
||||||
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZ)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZZ)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
||||||
{ "nativeRemoveJoystick", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) },
|
{ "nativeRemoveJoystick", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) },
|
||||||
{ "nativeAddHaptic", "(ILjava/lang/String;)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) },
|
{ "nativeAddHaptic", "(ILjava/lang/String;)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) },
|
||||||
{ "nativeRemoveHaptic", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) }
|
{ "nativeRemoveHaptic", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) }
|
||||||
@@ -406,6 +406,7 @@ static jclass mControllerManagerClass;
|
|||||||
|
|
||||||
// method signatures
|
// method signatures
|
||||||
static jmethodID midPollInputDevices;
|
static jmethodID midPollInputDevices;
|
||||||
|
static jmethodID midJoystickSetLED;
|
||||||
static jmethodID midPollHapticDevices;
|
static jmethodID midPollHapticDevices;
|
||||||
static jmethodID midHapticRun;
|
static jmethodID midHapticRun;
|
||||||
static jmethodID midHapticRumble;
|
static jmethodID midHapticRumble;
|
||||||
@@ -752,6 +753,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
|||||||
|
|
||||||
midPollInputDevices = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midPollInputDevices = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
"pollInputDevices", "()V");
|
"pollInputDevices", "()V");
|
||||||
|
midJoystickSetLED = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
|
"joystickSetLED", "(IIII)V");
|
||||||
midPollHapticDevices = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midPollHapticDevices = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
"pollHapticDevices", "()V");
|
"pollHapticDevices", "()V");
|
||||||
midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
@@ -761,7 +764,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
|||||||
midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||||
"hapticStop", "(I)V");
|
"hapticStop", "(I)V");
|
||||||
|
|
||||||
if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) {
|
if (!midPollInputDevices || !midJoystickSetLED || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) {
|
||||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,13 +1194,13 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
|||||||
JNIEnv *env, jclass jcls,
|
JNIEnv *env, jclass jcls,
|
||||||
jint device_id, jstring device_name, jstring device_desc,
|
jint device_id, jstring device_name, jstring device_desc,
|
||||||
jint vendor_id, jint product_id,
|
jint vendor_id, jint product_id,
|
||||||
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble)
|
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble, jboolean has_rgb_led)
|
||||||
{
|
{
|
||||||
#ifdef SDL_JOYSTICK_ANDROID
|
#ifdef SDL_JOYSTICK_ANDROID
|
||||||
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
||||||
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
||||||
|
|
||||||
Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats, can_rumble);
|
Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats, can_rumble, has_rgb_led);
|
||||||
|
|
||||||
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
||||||
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
||||||
@@ -2186,6 +2189,12 @@ void Android_JNI_PollInputDevices(void)
|
|||||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
|
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollInputDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Android_JNI_JoystickSetLED(int device_id, int red, int green, int blue)
|
||||||
|
{
|
||||||
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midJoystickSetLED, device_id, red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
void Android_JNI_PollHapticDevices(void)
|
void Android_JNI_PollHapticDevices(void)
|
||||||
{
|
{
|
||||||
JNIEnv *env = Android_JNI_GetEnv();
|
JNIEnv *env = Android_JNI_GetEnv();
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco
|
|||||||
|
|
||||||
// Joystick support
|
// Joystick support
|
||||||
void Android_JNI_PollInputDevices(void);
|
void Android_JNI_PollInputDevices(void);
|
||||||
|
void Android_JNI_JoystickSetLED(int device_id, int red, int green, int blue);
|
||||||
|
|
||||||
// Haptic support
|
// Haptic support
|
||||||
void Android_JNI_PollHapticDevices(void);
|
void Android_JNI_PollHapticDevices(void);
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ bool Android_OnHat(int device_id, int hat_id, int x, int y)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble)
|
void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble, bool has_rgb_led)
|
||||||
{
|
{
|
||||||
SDL_joylist_item *item;
|
SDL_joylist_item *item;
|
||||||
SDL_GUID guid;
|
SDL_GUID guid;
|
||||||
@@ -380,6 +380,7 @@ void Android_AddJoystick(int device_id, const char *name, const char *desc, int
|
|||||||
item->naxes = naxes;
|
item->naxes = naxes;
|
||||||
item->nhats = nhats;
|
item->nhats = nhats;
|
||||||
item->can_rumble = can_rumble;
|
item->can_rumble = can_rumble;
|
||||||
|
item->has_rgb_led = has_rgb_led;
|
||||||
item->device_instance = SDL_GetNextObjectID();
|
item->device_instance = SDL_GetNextObjectID();
|
||||||
if (!SDL_joylist_tail) {
|
if (!SDL_joylist_tail) {
|
||||||
SDL_joylist = SDL_joylist_tail = item;
|
SDL_joylist = SDL_joylist_tail = item;
|
||||||
@@ -581,6 +582,10 @@ static bool ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||||||
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true);
|
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item->has_rgb_led) {
|
||||||
|
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +612,15 @@ static bool ANDROID_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_r
|
|||||||
|
|
||||||
static bool ANDROID_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
static bool ANDROID_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
||||||
{
|
{
|
||||||
return SDL_Unsupported();
|
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||||
|
if (!item) {
|
||||||
|
return SDL_SetError("SetLED failed, device disconnected");
|
||||||
|
}
|
||||||
|
if (!item->has_rgb_led) {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
Android_JNI_JoystickSetLED(item->device_id, red, green, blue);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ANDROID_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
|
static bool ANDROID_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ extern bool Android_OnPadDown(int device_id, int keycode);
|
|||||||
extern bool Android_OnPadUp(int device_id, int keycode);
|
extern bool Android_OnPadUp(int device_id, int keycode);
|
||||||
extern bool Android_OnJoy(int device_id, int axisnum, float value);
|
extern bool Android_OnJoy(int device_id, int axisnum, float value);
|
||||||
extern bool Android_OnHat(int device_id, int hat_id, int x, int y);
|
extern bool Android_OnHat(int device_id, int hat_id, int x, int y);
|
||||||
extern void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble);
|
extern void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble, bool has_rgb_led);
|
||||||
extern void Android_RemoveJoystick(int device_id);
|
extern void Android_RemoveJoystick(int device_id);
|
||||||
|
|
||||||
// A linked list of available joysticks
|
// A linked list of available joysticks
|
||||||
@@ -46,6 +46,7 @@ typedef struct SDL_joylist_item
|
|||||||
int nbuttons, naxes, nhats;
|
int nbuttons, naxes, nhats;
|
||||||
int dpad_state;
|
int dpad_state;
|
||||||
bool can_rumble;
|
bool can_rumble;
|
||||||
|
bool has_rgb_led;
|
||||||
|
|
||||||
struct SDL_joylist_item *next;
|
struct SDL_joylist_item *next;
|
||||||
} SDL_joylist_item;
|
} SDL_joylist_item;
|
||||||
|
|||||||
Reference in New Issue
Block a user