libcamera/
control.rs

1use std::{marker::PhantomData, ptr::NonNull};
2
3use libcamera_sys::*;
4use thiserror::Error;
5
6use crate::{
7    control_value::{ControlValue, ControlValueError},
8    controls::{self, ControlId},
9    properties::{self, PropertyId},
10    utils::{UniquePtr, UniquePtrTarget},
11};
12
13#[derive(Debug, Error)]
14pub enum ControlError {
15    #[error("Control id {0} not found")]
16    NotFound(u32),
17    #[error("Control value error: {0}")]
18    ValueError(#[from] ControlValueError),
19}
20
21pub trait ControlEntry:
22    Clone + Into<ControlValue> + TryFrom<ControlValue, Error = ControlValueError> + core::fmt::Debug
23{
24    const ID: u32;
25}
26
27pub trait Control: ControlEntry {}
28pub trait Property: ControlEntry {}
29
30/// Dynamic Control, which does not have strong typing.
31pub trait DynControlEntry: core::fmt::Debug {
32    fn id(&self) -> u32;
33    fn value(&self) -> ControlValue;
34}
35
36impl<T: ControlEntry> DynControlEntry for T {
37    fn id(&self) -> u32 {
38        Self::ID
39    }
40
41    fn value(&self) -> ControlValue {
42        self.clone().into()
43    }
44}
45
46#[repr(transparent)]
47pub struct ControlInfoMap(libcamera_control_info_map_t);
48
49impl ControlInfoMap {
50    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_map_t>) -> &'a mut Self {
51        // Safety: we can cast it because of `#[repr(transparent)]`
52        &mut *(ptr.as_ptr() as *mut Self)
53    }
54}
55
56#[repr(transparent)]
57pub struct ControlList(libcamera_control_list_t);
58
59impl UniquePtrTarget for ControlList {
60    unsafe fn ptr_new() -> *mut Self {
61        libcamera_control_list_create() as *mut Self
62    }
63
64    unsafe fn ptr_drop(ptr: *mut Self) {
65        libcamera_control_list_destroy(ptr as *mut libcamera_control_list_t)
66    }
67}
68
69impl ControlList {
70    pub fn new() -> UniquePtr<Self> {
71        UniquePtr::new()
72    }
73
74    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
75        // Safety: we can cast it because of `#[repr(transparent)]`
76        &mut *(ptr.as_ptr() as *mut Self)
77    }
78
79    pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
80        // Safety: we can cast it because of `#[repr(transparent)]`
81        &self.0 as *const libcamera_control_list_t
82    }
83
84    pub fn get<C: Control>(&self) -> Result<C, ControlError> {
85        let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
86            .ok_or(ControlError::NotFound(C::ID))?;
87
88        let val = unsafe { ControlValue::read(val_ptr) }?;
89        Ok(C::try_from(val)?)
90    }
91
92    /// Sets control value.
93    ///
94    /// This can fail if control is not supported by the camera, but due to libcamera API limitations an error will not
95    /// be returned. Use [ControlList::get] if you need to ensure that value was set.
96    pub fn set<C: Control>(&mut self, val: C) -> Result<(), ControlError> {
97        let ctrl_val: ControlValue = val.into();
98
99        unsafe {
100            let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
101            ctrl_val.write(val_ptr);
102            libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
103            libcamera_control_value_destroy(val_ptr.as_ptr());
104        }
105
106        Ok(())
107    }
108}
109
110impl<'d> IntoIterator for &'d ControlList {
111    type Item = (u32, ControlValue);
112
113    type IntoIter = ControlListRefIterator<'d>;
114
115    fn into_iter(self) -> Self::IntoIter {
116        ControlListRefIterator {
117            it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
118            _phantom: Default::default(),
119        }
120    }
121}
122
123impl core::fmt::Debug for ControlList {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        let mut map = f.debug_map();
126        for (id, val) in self.into_iter() {
127            match ControlId::try_from(id) {
128                // Try to parse dynamic control, if not successful, just display the raw ControlValue
129                Ok(id) => match controls::make_dyn(id, val.clone()) {
130                    Ok(val) => map.entry(&id, &val),
131                    Err(_) => map.entry(&id, &val),
132                },
133                // If ControlId is unknown just use u32 as key
134                Err(_) => map.entry(&id, &val),
135            };
136        }
137        map.finish()
138    }
139}
140
141#[repr(transparent)]
142pub struct PropertyList(libcamera_control_list_t);
143
144impl PropertyList {
145    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
146        // Safety: we can cast it because of `#[repr(transparent)]`
147        &mut *(ptr.as_ptr() as *mut Self)
148    }
149
150    pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
151        // Safety: we can cast it because of `#[repr(transparent)]`
152        &self.0 as *const libcamera_control_list_t
153    }
154
155    pub fn get<C: Property>(&self) -> Result<C, ControlError> {
156        let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
157            .ok_or(ControlError::NotFound(C::ID))?;
158
159        let val = unsafe { ControlValue::read(val_ptr) }?;
160        Ok(C::try_from(val)?)
161    }
162
163    /// Sets property value.
164    ///
165    /// This can fail if property is not supported by the camera, but due to libcamera API limitations an error will not
166    /// be returned. Use [PropertyList::get] if you need to ensure that value was set.
167    pub fn set<C: Property>(&mut self, val: C) -> Result<(), ControlError> {
168        let ctrl_val: ControlValue = val.into();
169
170        unsafe {
171            let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
172            ctrl_val.write(val_ptr);
173            libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
174            libcamera_control_value_destroy(val_ptr.as_ptr());
175        }
176
177        Ok(())
178    }
179}
180
181impl<'d> IntoIterator for &'d PropertyList {
182    type Item = (u32, ControlValue);
183
184    type IntoIter = ControlListRefIterator<'d>;
185
186    fn into_iter(self) -> Self::IntoIter {
187        ControlListRefIterator {
188            it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
189            _phantom: Default::default(),
190        }
191    }
192}
193
194impl core::fmt::Debug for PropertyList {
195    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196        let mut map = f.debug_map();
197        for (id, val) in self.into_iter() {
198            match PropertyId::try_from(id) {
199                // Try to parse dynamic property, if not successful, just display the raw ControlValue
200                Ok(id) => match properties::make_dyn(id, val.clone()) {
201                    Ok(val) => map.entry(&id, &val),
202                    Err(_) => map.entry(&id, &val),
203                },
204                // If PropertyId is unknown just use u32 as key
205                Err(_) => map.entry(&id, &val),
206            };
207        }
208        map.finish()
209    }
210}
211
212pub struct ControlListRefIterator<'d> {
213    it: NonNull<libcamera_control_list_iter_t>,
214    _phantom: PhantomData<&'d ()>,
215}
216
217impl Iterator for ControlListRefIterator<'_> {
218    type Item = (u32, ControlValue);
219
220    fn next(&mut self) -> Option<Self::Item> {
221        if unsafe { libcamera_control_list_iter_end(self.it.as_ptr()) } {
222            None
223        } else {
224            let id = unsafe { libcamera_control_list_iter_id(self.it.as_ptr()) };
225            let val_ptr =
226                NonNull::new(unsafe { libcamera_control_list_iter_value(self.it.as_ptr()).cast_mut() }).unwrap();
227            let val = unsafe { ControlValue::read(val_ptr) }.unwrap();
228
229            unsafe { libcamera_control_list_iter_next(self.it.as_ptr()) };
230
231            Some((id, val))
232        }
233    }
234}
235
236impl Drop for ControlListRefIterator<'_> {
237    fn drop(&mut self) {
238        unsafe { libcamera_control_list_iter_destroy(self.it.as_ptr()) }
239    }
240}