diff --git a/include/SDL3/SDL_joystick.h b/include/SDL3/SDL_joystick.h index e3bf5988c2..be9a881734 100644 --- a/include/SDL3/SDL_joystick.h +++ b/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); +/** + * 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. * diff --git a/src/dynapi/SDL_dynapi.exports b/src/dynapi/SDL_dynapi.exports index f0c685c4be..a06f0f21d6 100644 --- a/src/dynapi/SDL_dynapi.exports +++ b/src/dynapi/SDL_dynapi.exports @@ -1302,3 +1302,8 @@ _SDL_GetDeviceFormFactor _SDL_GetDeviceFormFactorName _SDL_IsUbuntuTouch _SDL_GetNumProperties +_SDL_JoystickHasSensor +_SDL_SetJoystickSensorEnabled +_SDL_JoystickSensorEnabled +_SDL_GetJoystickSensorDataRate +_SDL_GetJoystickSensorData diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index f30ea16eb5..6e03541481 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1303,6 +1303,11 @@ SDL3_0.0.0 { SDL_GetDeviceFormFactorName; SDL_IsUbuntuTouch; SDL_GetNumProperties; + SDL_JoystickHasSensor; + SDL_SetJoystickSensorEnabled; + SDL_JoystickSensorEnabled; + SDL_GetJoystickSensorDataRate; + SDL_GetJoystickSensorData; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c7ce948a96..1f8ba18a01 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1329,3 +1329,8 @@ #define SDL_GetDeviceFormFactorName SDL_GetDeviceFormFactorName_REAL #define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_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 diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 299f77f2e8..6bf988441a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/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(bool,SDL_IsUbuntuTouch,(void),(),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) diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index afcf6c5d18..5065e27726 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -3780,185 +3780,29 @@ bool SDL_GetGamepadTouchpadFinger(SDL_Gamepad *gamepad, int touchpad, int finger return result; } -/** - * Return whether a gamepad has a particular sensor. - */ 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) { - 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 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 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) { - 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) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index af4211dcd5..4fbe70b0ab 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1889,6 +1889,177 @@ bool SDL_GetJoystickButton(SDL_Joystick *joystick, int button) 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 false if not plugged in, true if still present.