libcamera/
control.rs

1use std::{ffi::CStr, 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 ControlInfo(libcamera_control_info_t);
48
49impl ControlInfo {
50    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_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    pub(crate) fn ptr(&self) -> *const libcamera_control_info_t {
56        // Safety: we can cast it because of `#[repr(transparent)]`
57        &self.0 as *const libcamera_control_info_t
58    }
59
60    pub fn min(&self) -> ControlValue {
61        unsafe {
62            ControlValue::read(NonNull::new(libcamera_control_info_min(self.ptr().cast_mut()).cast_mut()).unwrap())
63                .unwrap()
64        }
65    }
66
67    pub fn max(&self) -> ControlValue {
68        unsafe {
69            ControlValue::read(NonNull::new(libcamera_control_info_max(self.ptr().cast_mut()).cast_mut()).unwrap())
70                .unwrap()
71        }
72    }
73
74    pub fn def(&self) -> ControlValue {
75        unsafe {
76            ControlValue::read(NonNull::new(libcamera_control_info_def(self.ptr().cast_mut()).cast_mut()).unwrap())
77                .unwrap()
78        }
79    }
80
81    pub fn values(&self) -> Vec<ControlValue> {
82        unsafe {
83            let mut size: usize = 0;
84            let values_ptr = libcamera_control_info_values(self.ptr(), &mut size as *mut usize);
85
86            if values_ptr.is_null() || size == 0 {
87                return Vec::new();
88            }
89
90            // Determine the size of libcamera_control_value_t
91            let control_value_size = libcamera_control_value_size();
92
93            // Cast the pointer to *const u8 for byte-wise pointer arithmetic
94            let base_ptr = values_ptr as *const u8;
95
96            let mut control_values = Vec::with_capacity(size);
97            for i in 0..size {
98                // Calculate the pointer to the i-th ControlValue
99                let offset = i * control_value_size;
100                let val_ptr = base_ptr.add(offset) as *const libcamera_control_value_t;
101
102                if val_ptr.is_null() {
103                    eprintln!("ControlValue at index {i} is null");
104                    continue;
105                }
106
107                // Read and convert the ControlValue
108                match ControlValue::read(NonNull::new(val_ptr.cast_mut()).unwrap()) {
109                    Ok(control_val) => control_values.push(control_val),
110                    Err(e) => {
111                        eprintln!("Failed to read ControlValue at index {i}: {e:?}");
112                    }
113                }
114            }
115
116            control_values
117        }
118    }
119}
120
121impl core::fmt::Debug for ControlInfo {
122    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123        f.debug_struct("ControlInfo")
124            .field("min", &self.min())
125            .field("max", &self.max())
126            .field("def", &self.def())
127            .field("values", &self.values())
128            .finish()
129    }
130}
131
132#[repr(transparent)]
133pub struct ControlInfoMap(libcamera_control_info_map_t);
134
135impl ControlInfoMap {
136    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_map_t>) -> &'a mut Self {
137        // Safety: we can cast it because of `#[repr(transparent)]`
138        &mut *(ptr.as_ptr() as *mut Self)
139    }
140
141    pub(crate) fn ptr(&self) -> *const libcamera_control_info_map_t {
142        // Safety: we can cast it because of `#[repr(transparent)]`
143        &self.0 as *const libcamera_control_info_map_t
144    }
145
146    pub fn at(&self, key: u32) -> Result<&ControlInfo, ControlError> {
147        unsafe {
148            let ptr = NonNull::new(libcamera_control_info_map_at(self.ptr().cast_mut(), key).cast_mut());
149            match ptr {
150                Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
151                None => Err(ControlError::NotFound(key)),
152            }
153        }
154    }
155
156    pub fn count(&self, key: u32) -> usize {
157        unsafe { libcamera_control_info_map_count(self.ptr().cast_mut(), key) }
158    }
159
160    pub fn find(&self, key: u32) -> Result<&ControlInfo, ControlError> {
161        unsafe {
162            let ptr = NonNull::new(libcamera_control_info_map_find(self.ptr().cast_mut(), key).cast_mut());
163
164            match ptr {
165                Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
166                None => Err(ControlError::NotFound(key)),
167            }
168        }
169    }
170
171    pub fn size(&self) -> usize {
172        unsafe { libcamera_control_info_map_size(self.ptr().cast_mut()) }
173    }
174}
175
176impl<'a> IntoIterator for &'a ControlInfoMap {
177    type Item = (u32, &'a ControlInfo);
178    type IntoIter = ControlInfoMapIter<'a>;
179
180    fn into_iter(self) -> Self::IntoIter {
181        ControlInfoMapIter::new(self).expect("Failed to create ControlInfoMap iterator")
182    }
183}
184
185impl core::fmt::Debug for ControlInfoMap {
186    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187        let mut dm = f.debug_map();
188        for (key, value) in self.into_iter() {
189            match ControlId::try_from(key) {
190                Ok(id) => dm.entry(&id, value),
191                Err(_) => dm.entry(&key, value),
192            };
193        }
194        dm.finish()
195    }
196}
197
198#[repr(transparent)]
199pub struct ControlList(libcamera_control_list_t);
200
201impl UniquePtrTarget for ControlList {
202    unsafe fn ptr_new() -> *mut Self {
203        libcamera_control_list_create() as *mut Self
204    }
205
206    unsafe fn ptr_drop(ptr: *mut Self) {
207        libcamera_control_list_destroy(ptr as *mut libcamera_control_list_t)
208    }
209}
210
211impl ControlList {
212    pub fn new() -> UniquePtr<Self> {
213        UniquePtr::new()
214    }
215
216    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
217        // Safety: we can cast it because of `#[repr(transparent)]`
218        &mut *(ptr.as_ptr() as *mut Self)
219    }
220
221    pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
222        // Safety: we can cast it because of `#[repr(transparent)]`
223        &self.0 as *const libcamera_control_list_t
224    }
225
226    pub fn get<C: Control>(&self) -> Result<C, ControlError> {
227        let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
228            .ok_or(ControlError::NotFound(C::ID))?;
229
230        let val = unsafe { ControlValue::read(val_ptr) }?;
231        Ok(C::try_from(val)?)
232    }
233
234    /// Sets control value.
235    ///
236    /// This can fail if control is not supported by the camera, but due to libcamera API limitations an error will not
237    /// be returned. Use [ControlList::get] if you need to ensure that value was set.
238    pub fn set<C: Control>(&mut self, val: C) -> Result<(), ControlError> {
239        let ctrl_val: ControlValue = val.into();
240
241        unsafe {
242            let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
243            ctrl_val.write(val_ptr);
244            libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
245            libcamera_control_value_destroy(val_ptr.as_ptr());
246        }
247
248        Ok(())
249    }
250
251    /// Sets control value.
252    ///
253    /// This can fail if control is not supported by the camera, but due to libcamera API limitations an error will not
254    /// be returned. Use [ControlList::get] if you need to ensure that value was set.
255    pub fn set_raw(&mut self, id: u32, val: ControlValue) -> Result<(), ControlError> {
256        unsafe {
257            let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
258            val.write(val_ptr);
259            libcamera_control_list_set(self.ptr().cast_mut(), id as _, val_ptr.as_ptr());
260            libcamera_control_value_destroy(val_ptr.as_ptr());
261        }
262
263        Ok(())
264    }
265
266    pub fn get_raw(&mut self, id: u32) -> Result<ControlValue, ControlError> {
267        let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), id as _).cast_mut() })
268            .ok_or(ControlError::NotFound(id))?;
269
270        let val = unsafe { ControlValue::read(val_ptr) }?;
271        Ok(val)
272    }
273}
274
275impl<'d> IntoIterator for &'d ControlList {
276    type Item = (u32, ControlValue);
277
278    type IntoIter = ControlListRefIterator<'d>;
279
280    fn into_iter(self) -> Self::IntoIter {
281        ControlListRefIterator {
282            it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
283            _phantom: Default::default(),
284        }
285    }
286}
287
288impl core::fmt::Debug for ControlList {
289    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290        let mut map = f.debug_map();
291        for (id, val) in self.into_iter() {
292            match ControlId::try_from(id) {
293                // Try to parse dynamic control, if not successful, just display the raw ControlValue
294                Ok(id) => match controls::make_dyn(id, val.clone()) {
295                    Ok(val) => map.entry(&id, &val),
296                    Err(_) => map.entry(&id, &val),
297                },
298                // If ControlId is unknown just use u32 as key
299                Err(_) => map.entry(&id, &val),
300            };
301        }
302        map.finish()
303    }
304}
305
306#[repr(transparent)]
307pub struct PropertyList(libcamera_control_list_t);
308
309impl PropertyList {
310    pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
311        // Safety: we can cast it because of `#[repr(transparent)]`
312        &mut *(ptr.as_ptr() as *mut Self)
313    }
314
315    pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
316        // Safety: we can cast it because of `#[repr(transparent)]`
317        &self.0 as *const libcamera_control_list_t
318    }
319
320    pub fn get<C: Property>(&self) -> Result<C, ControlError> {
321        let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
322            .ok_or(ControlError::NotFound(C::ID))?;
323
324        let val = unsafe { ControlValue::read(val_ptr) }?;
325
326        Ok(C::try_from(val)?)
327    }
328
329    /// Sets property value.
330    ///
331    /// This can fail if property is not supported by the camera, but due to libcamera API limitations an error will not
332    /// be returned. Use [PropertyList::get] if you need to ensure that value was set.
333    pub fn set<C: Property>(&mut self, val: C) -> Result<(), ControlError> {
334        let ctrl_val: ControlValue = val.into();
335
336        unsafe {
337            let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
338            ctrl_val.write(val_ptr);
339            libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
340            libcamera_control_value_destroy(val_ptr.as_ptr());
341        }
342
343        Ok(())
344    }
345}
346
347impl<'d> IntoIterator for &'d PropertyList {
348    type Item = (u32, ControlValue);
349
350    type IntoIter = ControlListRefIterator<'d>;
351
352    fn into_iter(self) -> Self::IntoIter {
353        ControlListRefIterator {
354            it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
355            _phantom: Default::default(),
356        }
357    }
358}
359
360impl core::fmt::Debug for PropertyList {
361    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362        let mut map = f.debug_map();
363        for (id, val) in self.into_iter() {
364            match PropertyId::try_from(id) {
365                // Try to parse dynamic property, if not successful, just display the raw ControlValue
366                Ok(id) => match properties::make_dyn(id, val.clone()) {
367                    Ok(val) => map.entry(&id, &val),
368                    Err(_) => map.entry(&id, &val),
369                },
370                // If PropertyId is unknown just use u32 as key
371                Err(_) => map.entry(&id, &val),
372            };
373        }
374        map.finish()
375    }
376}
377
378pub struct ControlListRefIterator<'d> {
379    it: NonNull<libcamera_control_list_iter_t>,
380    _phantom: PhantomData<&'d ()>,
381}
382
383impl Iterator for ControlListRefIterator<'_> {
384    type Item = (u32, ControlValue);
385
386    fn next(&mut self) -> Option<Self::Item> {
387        if unsafe { libcamera_control_list_iter_end(self.it.as_ptr()) } {
388            None
389        } else {
390            let id = unsafe { libcamera_control_list_iter_id(self.it.as_ptr()) };
391            let val_ptr =
392                NonNull::new(unsafe { libcamera_control_list_iter_value(self.it.as_ptr()).cast_mut() }).unwrap();
393            let val = unsafe { ControlValue::read(val_ptr) }.unwrap();
394
395            unsafe { libcamera_control_list_iter_next(self.it.as_ptr()) };
396
397            Some((id, val))
398        }
399    }
400}
401
402impl Drop for ControlListRefIterator<'_> {
403    fn drop(&mut self) {
404        unsafe { libcamera_control_list_iter_destroy(self.it.as_ptr()) }
405    }
406}
407
408pub struct ControlInfoMapIter<'a> {
409    iter: *mut libcamera_control_info_map_iter_t,
410    marker: PhantomData<&'a libcamera_control_info_map_t>,
411}
412
413impl<'a> ControlInfoMapIter<'a> {
414    pub fn new(map: &'a ControlInfoMap) -> Option<Self> {
415        unsafe {
416            let iter = libcamera_control_info_map_iter_create(map.ptr());
417            if iter.is_null() {
418                None
419            } else {
420                Some(ControlInfoMapIter {
421                    iter,
422                    marker: PhantomData,
423                })
424            }
425        }
426    }
427}
428
429impl<'a> Iterator for ControlInfoMapIter<'a> {
430    type Item = (u32, &'a ControlInfo);
431
432    fn next(&mut self) -> Option<Self::Item> {
433        unsafe {
434            if libcamera_control_info_map_iter_has_next(self.iter) {
435                let key = libcamera_control_info_map_iter_key(self.iter);
436                let value_ptr = libcamera_control_info_map_iter_value(self.iter);
437                if value_ptr.is_null() {
438                    None
439                } else {
440                    let control_info = &*(value_ptr as *const ControlInfo);
441                    libcamera_control_info_map_iter_next(self.iter);
442                    Some((key, control_info))
443                }
444            } else {
445                None
446            }
447        }
448    }
449}
450
451impl<'a> Drop for ControlInfoMapIter<'a> {
452    fn drop(&mut self) {
453        unsafe {
454            libcamera_control_info_map_iter_destroy(self.iter);
455        }
456    }
457}
458
459impl ControlId {
460    pub fn name(&self) -> String {
461        unsafe { CStr::from_ptr(libcamera_control_name_from_id(self.id())) }
462            .to_str()
463            .unwrap()
464            .into()
465    }
466}
467
468impl PropertyId {
469    pub fn name(&self) -> String {
470        unsafe { CStr::from_ptr(libcamera_property_name_from_id(self.id())) }
471            .to_str()
472            .unwrap()
473            .into()
474    }
475}