rich_sdl2_rust/event/
sensor.rs

1//! Setup and reading data from other sensors.
2
3use std::{ffi::CStr, os::raw::c_int, ptr::NonNull};
4
5use crate::bind;
6
7/// A kind of the other sensors.
8#[derive(Debug, Clone)]
9#[non_exhaustive]
10pub enum SensorKind {
11    /// The others unrecognized by SDL2.
12    Others(i32),
13    /// The accelerometer.
14    Accel,
15    /// The gyroscope.
16    Gyro,
17}
18
19/// A sensor loaded by SDL2.
20pub struct Sensor {
21    ptr: NonNull<bind::SDL_Sensor>,
22}
23
24impl std::fmt::Debug for Sensor {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        f.debug_struct("Sensor")
27            .field("name", &self.name())
28            .finish_non_exhaustive()
29    }
30}
31
32impl Sensor {
33    /// Reads some `f32` data by count
34    #[must_use]
35    pub fn data(&self, read_count: usize) -> Vec<f32> {
36        let mut data = vec![0.0; read_count];
37        unsafe {
38            bind::SDL_SensorGetData(self.ptr.as_ptr(), data.as_mut_ptr(), read_count as c_int);
39        }
40        data
41    }
42
43    /// Returns the name of the sensor
44    #[must_use]
45    pub fn name(&self) -> &str {
46        let cstr = unsafe { CStr::from_ptr(bind::SDL_SensorGetName(self.ptr.as_ptr())) };
47        cstr.to_str().unwrap()
48    }
49
50    /// Returns the kind of the sensor
51    #[must_use]
52    pub fn kind(&self) -> SensorKind {
53        let ty = unsafe { bind::SDL_SensorGetType(self.ptr.as_ptr()) };
54        match ty {
55            bind::SDL_SENSOR_ACCEL => SensorKind::Accel,
56            bind::SDL_SENSOR_GYRO => SensorKind::Gyro,
57            bind::SDL_SENSOR_UNKNOWN => {
58                let ty = unsafe { bind::SDL_SensorGetNonPortableType(self.ptr.as_ptr()) };
59                SensorKind::Others(ty)
60            }
61            _ => unreachable!(),
62        }
63    }
64}
65
66/// A set of `Sensor`, containing other sensors.
67#[derive(Debug)]
68pub struct SensorSet(Vec<Sensor>);
69
70impl SensorSet {
71    /// Setup the system and recognizes the sensors.
72    #[must_use]
73    pub fn new() -> Self {
74        let sensor_count = unsafe {
75            bind::SDL_InitSubSystem(bind::SDL_INIT_SENSOR);
76            bind::SDL_NumSensors()
77        };
78        Self(
79            (0..sensor_count)
80                .map(|index| {
81                    let sensor = unsafe { bind::SDL_SensorOpen(index) };
82                    Sensor {
83                        ptr: NonNull::new(sensor).expect("opening sensor failed"),
84                    }
85                })
86                .collect(),
87        )
88    }
89
90    /// Returns the sensors slice.
91    #[must_use]
92    pub fn sensors(&self) -> &[Sensor] {
93        &self.0
94    }
95}
96
97impl Default for SensorSet {
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103impl Drop for SensorSet {
104    fn drop(&mut self) {
105        for sensor in &self.0 {
106            unsafe { bind::SDL_SensorClose(sensor.ptr.as_ptr()) }
107        }
108    }
109}