use crate::{
check_rs2_error,
kind::{Rs2CameraInfo, Rs2Exception},
sensor::Sensor,
};
use anyhow::Result;
use realsense_sys as sys;
use std::{
convert::{From, TryInto},
ffi::CStr,
ptr::NonNull,
};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DeviceConstructionError {
#[error("Could not create device from sensor. Type: {0}; Reason: {1}")]
CouldNotCreateDeviceFromSensor(Rs2Exception, String),
#[error("Could not get device from device list. Type: {0}; Reason: {1}")]
CouldNotGetDeviceFromDeviceList(Rs2Exception, String),
}
#[derive(Debug)]
pub struct Device {
device_ptr: NonNull<sys::rs2_device>,
}
impl Drop for Device {
fn drop(&mut self) {
unsafe {
sys::rs2_delete_device(self.device_ptr.as_ptr());
}
}
}
unsafe impl Send for Device {}
impl From<NonNull<sys::rs2_device>> for Device {
fn from(device_ptr: NonNull<sys::rs2_device>) -> Self {
Device { device_ptr }
}
}
impl Device {
pub(crate) fn try_create(
device_list: &NonNull<sys::rs2_device_list>,
index: i32,
) -> Result<Self, DeviceConstructionError> {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let device_ptr = sys::rs2_create_device(device_list.as_ptr(), index, &mut err);
check_rs2_error!(
err,
DeviceConstructionError::CouldNotGetDeviceFromDeviceList
)?;
let nonnull_device_ptr = NonNull::new(device_ptr).unwrap();
Ok(Device::from(nonnull_device_ptr))
}
}
pub fn sensors(&self) -> Vec<Sensor> {
unsafe {
let mut sensors = Vec::new();
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let sensor_list_ptr = sys::rs2_query_sensors(self.device_ptr.as_ptr(), &mut err);
if err.as_ref().is_some() {
sys::rs2_free_error(err);
return sensors;
}
let nonnull_sensor_list = NonNull::new(sensor_list_ptr).unwrap();
let len = sys::rs2_get_sensors_count(nonnull_sensor_list.as_ptr(), &mut err);
if err.as_ref().is_some() {
sys::rs2_free_error(err);
sys::rs2_delete_sensor_list(nonnull_sensor_list.as_ptr());
return sensors;
}
sensors.reserve(len as usize);
for i in 0..len {
match Sensor::try_create(&nonnull_sensor_list, i) {
Ok(s) => {
sensors.push(s);
}
Err(_) => {
continue;
}
}
}
sys::rs2_delete_sensor_list(nonnull_sensor_list.as_ptr());
sensors
}
}
pub fn hardware_reset(self) {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
sys::rs2_hardware_reset(self.device_ptr.as_ptr(), &mut err);
}
}
pub fn info(&self, camera_info: Rs2CameraInfo) -> Option<&CStr> {
if !self.supports_info(camera_info) {
return None;
}
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let val = sys::rs2_get_device_info(
self.device_ptr.as_ptr(),
#[allow(clippy::useless_conversion)]
(camera_info as i32).try_into().unwrap(),
&mut err,
);
if err.as_ref().is_none() {
Some(CStr::from_ptr(val))
} else {
sys::rs2_free_error(err);
None
}
}
}
pub fn supports_info(&self, camera_info: Rs2CameraInfo) -> bool {
unsafe {
let mut err = std::ptr::null_mut::<sys::rs2_error>();
let supports_info = sys::rs2_supports_device_info(
self.device_ptr.as_ptr(),
#[allow(clippy::useless_conversion)]
(camera_info as i32).try_into().unwrap(),
&mut err,
);
if err.as_ref().is_none() {
supports_info != 0
} else {
sys::rs2_free_error(err);
false
}
}
}
pub(crate) unsafe fn get_raw(&self) -> NonNull<sys::rs2_device> {
self.device_ptr
}
}