Browse Source

joystick: Expose sensor data at the SDL_Joystick level.

Previously this was only available through the gamepad API, but this state has
always actually lived on the lower-level joystick objects, so there's no sense
in not offering a public API for that level, as well.

Closes #16202.
Ryan C. Gordon 3 weeks ago
parent
commit
4f3d7017b0

+ 87 - 0
include/SDL3/SDL_joystick.h

@@ -1250,6 +1250,93 @@ extern SDL_DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, int
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int button);
 extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int button);
 
 
+/**
+ * Return whether a joystick has a particular sensor.
+ *
+ * Sensors are disabled by default and SDL_SetJoystickSensorEnabled() is used
+ * to enable them.
+ *
+ * \param joystick the joystick to query.
+ * \param type the type of sensor to query.
+ * \returns true if the sensor exists, false otherwise.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.2.0.
+ *
+ * \sa SDL_GetJoystickSensorData
+ * \sa SDL_GetJoystickSensorDataRate
+ * \sa SDL_SetJoystickSensorEnabled
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_JoystickHasSensor(SDL_Joystick *joystick, SDL_SensorType type);
+
+/**
+ * Set whether data reporting for a joystick sensor is enabled.
+ *
+ * Sensors are disabled by default and this function is used to enable them.
+ *
+ * \param joystick the joystick to update.
+ * \param type the type of sensor to enable/disable.
+ * \param enabled whether data reporting should be enabled.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.2.0.
+ *
+ * \sa SDL_JoystickHasSensor
+ * \sa SDL_JoystickSensorEnabled
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickSensorEnabled(SDL_Joystick *joystick, SDL_SensorType type, bool enabled);
+
+/**
+ * Query whether sensor data reporting is enabled for a joystick.
+ *
+ * \param joystick the joystick to query.
+ * \param type the type of sensor to query.
+ * \returns true if the sensor is enabled, false otherwise.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.2.0.
+ *
+ * \sa SDL_SetJoystickSensorEnabled
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_JoystickSensorEnabled(SDL_Joystick *joystick, SDL_SensorType type);
+
+/**
+ * Get the data rate (number of events per second) of a joystick sensor.
+ *
+ * \param joystick the joystick to query.
+ * \param type the type of sensor to query.
+ * \returns the data rate, or 0.0f if the data rate is not available.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.2.0.
+ */
+extern SDL_DECLSPEC float SDLCALL SDL_GetJoystickSensorDataRate(SDL_Joystick *joystick, SDL_SensorType type);
+
+/**
+ * Get the current state of a joystick sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ * See the remarks in SDL_SensorType for details for each type of sensor.
+ *
+ * \param joystick the joystick to query.
+ * \param type the type of sensor to query.
+ * \param data a pointer filled with the current sensor state.
+ * \param num_values the number of values to write to data.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.2.0.
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickSensorData(SDL_Joystick *joystick, SDL_SensorType type, float *data, int num_values);
+
 /**
 /**
  * Start a rumble effect.
  * Start a rumble effect.
  *
  *

+ 5 - 0
src/dynapi/SDL_dynapi.exports

@@ -1302,3 +1302,8 @@ _SDL_GetDeviceFormFactor
 _SDL_GetDeviceFormFactorName
 _SDL_GetDeviceFormFactorName
 _SDL_IsUbuntuTouch
 _SDL_IsUbuntuTouch
 _SDL_GetNumProperties
 _SDL_GetNumProperties
+_SDL_JoystickHasSensor
+_SDL_SetJoystickSensorEnabled
+_SDL_JoystickSensorEnabled
+_SDL_GetJoystickSensorDataRate
+_SDL_GetJoystickSensorData

+ 5 - 0
src/dynapi/SDL_dynapi.sym

@@ -1303,6 +1303,11 @@ SDL3_0.0.0 {
     SDL_GetDeviceFormFactorName;
     SDL_GetDeviceFormFactorName;
     SDL_IsUbuntuTouch;
     SDL_IsUbuntuTouch;
     SDL_GetNumProperties;
     SDL_GetNumProperties;
+    SDL_JoystickHasSensor;
+    SDL_SetJoystickSensorEnabled;
+    SDL_JoystickSensorEnabled;
+    SDL_GetJoystickSensorDataRate;
+    SDL_GetJoystickSensorData;
     # extra symbols go here (don't modify this line)
     # extra symbols go here (don't modify this line)
   local: *;
   local: *;
 };
 };

+ 5 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1329,3 +1329,8 @@
 #define SDL_GetDeviceFormFactorName SDL_GetDeviceFormFactorName_REAL
 #define SDL_GetDeviceFormFactorName SDL_GetDeviceFormFactorName_REAL
 #define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_REAL
 #define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_REAL
 #define SDL_GetNumProperties SDL_GetNumProperties_REAL
 #define SDL_GetNumProperties SDL_GetNumProperties_REAL
+#define SDL_JoystickHasSensor SDL_JoystickHasSensor_REAL
+#define SDL_SetJoystickSensorEnabled SDL_SetJoystickSensorEnabled_REAL
+#define SDL_JoystickSensorEnabled SDL_JoystickSensorEnabled_REAL
+#define SDL_GetJoystickSensorDataRate SDL_GetJoystickSensorDataRate_REAL
+#define SDL_GetJoystickSensorData SDL_GetJoystickSensorData_REAL

+ 5 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1337,3 +1337,8 @@ SDL_DYNAPI_PROC(SDL_FormFactor,SDL_GetDeviceFormFactor,(void),(),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetDeviceFormFactorName,(SDL_FormFactor a),(a),return)
 SDL_DYNAPI_PROC(const char*,SDL_GetDeviceFormFactorName,(SDL_FormFactor a),(a),return)
 SDL_DYNAPI_PROC(bool,SDL_IsUbuntuTouch,(void),(),return)
 SDL_DYNAPI_PROC(bool,SDL_IsUbuntuTouch,(void),(),return)
 SDL_DYNAPI_PROC(int,SDL_GetNumProperties,(SDL_PropertiesID a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_GetNumProperties,(SDL_PropertiesID a),(a),return)
+SDL_DYNAPI_PROC(bool,SDL_JoystickHasSensor,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
+SDL_DYNAPI_PROC(bool,SDL_SetJoystickSensorEnabled,(SDL_Joystick *a,SDL_SensorType b,bool c),(a,b,c),return)
+SDL_DYNAPI_PROC(bool,SDL_JoystickSensorEnabled,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
+SDL_DYNAPI_PROC(float,SDL_GetJoystickSensorDataRate,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
+SDL_DYNAPI_PROC(bool,SDL_GetJoystickSensorData,(SDL_Joystick *a,SDL_SensorType b,float *c,int d),(a,b,c,d),return)

+ 5 - 161
src/joystick/SDL_gamepad.c

@@ -3780,185 +3780,29 @@ bool SDL_GetGamepadTouchpadFinger(SDL_Gamepad *gamepad, int touchpad, int finger
     return result;
     return result;
 }
 }
 
 
-/**
- *  Return whether a gamepad has a particular sensor.
- */
 bool SDL_GamepadHasSensor(SDL_Gamepad *gamepad, SDL_SensorType type)
 bool SDL_GamepadHasSensor(SDL_Gamepad *gamepad, SDL_SensorType type)
 {
 {
-    bool result = false;
-
-    SDL_LockJoysticks();
-    {
-        SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);
-        if (joystick) {
-            int i;
-            for (i = 0; i < joystick->nsensors; ++i) {
-                if (joystick->sensors[i].type == type) {
-                    result = true;
-                    break;
-                }
-            }
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return result;
+    return SDL_JoystickHasSensor(SDL_GetGamepadJoystick(gamepad), type);
 }
 }
 
 
-/*
- *  Set whether data reporting for a gamepad sensor is enabled
- */
 bool SDL_SetGamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type, bool enabled)
 bool SDL_SetGamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type, bool enabled)
 {
 {
-    SDL_LockJoysticks();
-    {
-        SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);
-        if (joystick) {
-            int i;
-            for (i = 0; i < joystick->nsensors; ++i) {
-                SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
-
-                if (sensor->type == type) {
-                    if (sensor->enabled == (enabled != false)) {
-                        SDL_UnlockJoysticks();
-                        return true;
-                    }
-
-                    if (type == SDL_SENSOR_ACCEL && joystick->accel_sensor) {
-                        if (enabled) {
-                            joystick->accel = SDL_OpenSensor(joystick->accel_sensor);
-                            if (!joystick->accel) {
-                                SDL_UnlockJoysticks();
-                                return false;
-                            }
-                        } else {
-                            if (joystick->accel) {
-                                SDL_CloseSensor(joystick->accel);
-                                joystick->accel = NULL;
-                            }
-                        }
-                    } else if (type == SDL_SENSOR_GYRO && joystick->gyro_sensor) {
-                        if (enabled) {
-                            joystick->gyro = SDL_OpenSensor(joystick->gyro_sensor);
-                            if (!joystick->gyro) {
-                                SDL_UnlockJoysticks();
-                                return false;
-                            }
-                        } else {
-                            if (joystick->gyro) {
-                                SDL_CloseSensor(joystick->gyro);
-                                joystick->gyro = NULL;
-                            }
-                        }
-                    } else {
-                        if (enabled) {
-                            if (joystick->nsensors_enabled == 0) {
-                                if (!joystick->driver->SetSensorsEnabled(joystick, true)) {
-                                    SDL_UnlockJoysticks();
-                                    return false;
-                                }
-                            }
-                            ++joystick->nsensors_enabled;
-                        } else {
-                            if (joystick->nsensors_enabled == 1) {
-                                if (!joystick->driver->SetSensorsEnabled(joystick, false)) {
-                                    SDL_UnlockJoysticks();
-                                    return false;
-                                }
-                            }
-                            --joystick->nsensors_enabled;
-                        }
-                    }
-
-                    sensor->enabled = enabled;
-                    SDL_UnlockJoysticks();
-                    return true;
-                }
-            }
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return SDL_Unsupported();
+    return SDL_SetJoystickSensorEnabled(SDL_GetGamepadJoystick(gamepad), type, enabled);
 }
 }
 
 
-/*
- *  Query whether sensor data reporting is enabled for a gamepad
- */
 bool SDL_GamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type)
 bool SDL_GamepadSensorEnabled(SDL_Gamepad *gamepad, SDL_SensorType type)
 {
 {
-    bool result = false;
-
-    SDL_LockJoysticks();
-    {
-        SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);
-        if (joystick) {
-            int i;
-            for (i = 0; i < joystick->nsensors; ++i) {
-                if (joystick->sensors[i].type == type) {
-                    result = joystick->sensors[i].enabled;
-                    break;
-                }
-            }
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return result;
+    return SDL_JoystickSensorEnabled(SDL_GetGamepadJoystick(gamepad), type);
 }
 }
 
 
-/*
- *  Get the data rate of a gamepad sensor.
- */
 float SDL_GetGamepadSensorDataRate(SDL_Gamepad *gamepad, SDL_SensorType type)
 float SDL_GetGamepadSensorDataRate(SDL_Gamepad *gamepad, SDL_SensorType type)
 {
 {
-    float result = 0.0f;
-
-    SDL_LockJoysticks();
-    {
-        SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);
-        if (joystick) {
-            int i;
-            for (i = 0; i < joystick->nsensors; ++i) {
-                SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
-
-                if (sensor->type == type) {
-                    result = sensor->rate;
-                    break;
-                }
-            }
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return result;
+    return SDL_GetJoystickSensorDataRate(SDL_GetGamepadJoystick(gamepad), type);
 }
 }
 
 
-/*
- *  Get the current state of a gamepad sensor.
- */
 bool SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, SDL_SensorType type, float *data, int num_values)
 bool SDL_GetGamepadSensorData(SDL_Gamepad *gamepad, SDL_SensorType type, float *data, int num_values)
 {
 {
-    SDL_LockJoysticks();
-    {
-        SDL_Joystick *joystick = SDL_GetGamepadJoystick(gamepad);
-        if (joystick) {
-            int i;
-            for (i = 0; i < joystick->nsensors; ++i) {
-                SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
-
-                if (sensor->type == type) {
-                    num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
-                    SDL_memcpy(data, sensor->data, num_values * sizeof(*data));
-                    SDL_UnlockJoysticks();
-                    return true;
-                }
-            }
-        }
-    }
-    SDL_UnlockJoysticks();
-
-    return SDL_Unsupported();
+    return SDL_GetJoystickSensorData(SDL_GetGamepadJoystick(gamepad), type, data, num_values);
 }
 }
 
 
 bool SDL_GamepadHasCapSense(SDL_Gamepad *gamepad, SDL_GamepadCapSenseType type)
 bool SDL_GamepadHasCapSense(SDL_Gamepad *gamepad, SDL_GamepadCapSenseType type)

+ 171 - 0
src/joystick/SDL_joystick.c

@@ -1889,6 +1889,177 @@ bool SDL_GetJoystickButton(SDL_Joystick *joystick, int button)
     return down;
     return down;
 }
 }
 
 
+static bool ErrorNoSuchSensor(void)
+{
+    return SDL_SetError("No such sensor on this device");
+}
+
+/**
+ *  Return whether a joystick has a particular sensor.
+ */
+bool SDL_JoystickHasSensor(SDL_Joystick *joystick, SDL_SensorType type)
+{
+    bool result = false;
+
+    SDL_LockJoysticks();
+    {
+        CHECK_JOYSTICK_MAGIC(joystick, false);
+        for (int i = 0; i < joystick->nsensors; ++i) {
+            if (joystick->sensors[i].type == type) {
+                result = true;
+                break;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return result;
+}
+
+/*
+ *  Set whether data reporting for a joystick sensor is enabled
+ */
+bool SDL_SetJoystickSensorEnabled(SDL_Joystick *joystick, SDL_SensorType type, bool enabled)
+{
+    SDL_LockJoysticks();
+    {
+        CHECK_JOYSTICK_MAGIC(joystick, false);
+        for (int i = 0; i < joystick->nsensors; ++i) {
+            SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
+
+            if (sensor->type == type) {
+                if (sensor->enabled == (enabled != false)) {
+                    SDL_UnlockJoysticks();
+                    return true;
+                }
+
+                if (type == SDL_SENSOR_ACCEL && joystick->accel_sensor) {
+                    if (enabled) {
+                        joystick->accel = SDL_OpenSensor(joystick->accel_sensor);
+                        if (!joystick->accel) {
+                            SDL_UnlockJoysticks();
+                            return false;
+                        }
+                    } else {
+                        if (joystick->accel) {
+                            SDL_CloseSensor(joystick->accel);
+                            joystick->accel = NULL;
+                        }
+                    }
+                } else if (type == SDL_SENSOR_GYRO && joystick->gyro_sensor) {
+                    if (enabled) {
+                        joystick->gyro = SDL_OpenSensor(joystick->gyro_sensor);
+                        if (!joystick->gyro) {
+                            SDL_UnlockJoysticks();
+                            return false;
+                        }
+                    } else {
+                        if (joystick->gyro) {
+                            SDL_CloseSensor(joystick->gyro);
+                            joystick->gyro = NULL;
+                        }
+                    }
+                } else {
+                    if (enabled) {
+                        if (joystick->nsensors_enabled == 0) {
+                            if (!joystick->driver->SetSensorsEnabled(joystick, true)) {
+                                SDL_UnlockJoysticks();
+                                return false;
+                            }
+                        }
+                        ++joystick->nsensors_enabled;
+                    } else {
+                        if (joystick->nsensors_enabled == 1) {
+                            if (!joystick->driver->SetSensorsEnabled(joystick, false)) {
+                                SDL_UnlockJoysticks();
+                                return false;
+                            }
+                        }
+                        --joystick->nsensors_enabled;
+                    }
+                }
+
+                sensor->enabled = enabled;
+                SDL_UnlockJoysticks();
+                return true;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return ErrorNoSuchSensor();
+}
+
+/*
+ *  Query whether sensor data reporting is enabled for a joystick
+ */
+bool SDL_JoystickSensorEnabled(SDL_Joystick *joystick, SDL_SensorType type)
+{
+    bool result = false;
+
+    SDL_LockJoysticks();
+    {
+        CHECK_JOYSTICK_MAGIC(joystick, false);
+        for (int i = 0; i < joystick->nsensors; ++i) {
+            if (joystick->sensors[i].type == type) {
+                result = joystick->sensors[i].enabled;
+                break;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return result;
+}
+
+/*
+ *  Get the data rate of a joystick sensor.
+ */
+float SDL_GetJoystickSensorDataRate(SDL_Joystick *joystick, SDL_SensorType type)
+{
+    float result = 0.0f;
+
+    SDL_LockJoysticks();
+    {
+        CHECK_JOYSTICK_MAGIC(joystick, 0.0f);
+        for (int i = 0; i < joystick->nsensors; ++i) {
+            SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
+
+            if (sensor->type == type) {
+                result = sensor->rate;
+                break;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return result;
+}
+
+/*
+ *  Get the current state of a joystick sensor.
+ */
+bool SDL_GetJoystickSensorData(SDL_Joystick *joystick, SDL_SensorType type, float *data, int num_values)
+{
+    SDL_LockJoysticks();
+    {
+        CHECK_JOYSTICK_MAGIC(joystick, false);
+        for (int i = 0; i < joystick->nsensors; ++i) {
+            SDL_JoystickSensorInfo *sensor = &joystick->sensors[i];
+
+            if (sensor->type == type) {
+                num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
+                SDL_memcpy(data, sensor->data, num_values * sizeof(*data));
+                SDL_UnlockJoysticks();
+                return true;
+            }
+        }
+    }
+    SDL_UnlockJoysticks();
+
+    return ErrorNoSuchSensor();
+}
+
 /*
 /*
  * Return if the joystick in question is currently attached to the system,
  * Return if the joystick in question is currently attached to the system,
  *  \return false if not plugged in, true if still present.
  *  \return false if not plugged in, true if still present.