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
30pub 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 &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 &mut *(ptr.as_ptr() as *mut Self)
77 }
78
79 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
80 &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 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 Ok(id) => match controls::make_dyn(id, val.clone()) {
130 Ok(val) => map.entry(&id, &val),
131 Err(_) => map.entry(&id, &val),
132 },
133 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 &mut *(ptr.as_ptr() as *mut Self)
148 }
149
150 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
151 &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 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 Ok(id) => match properties::make_dyn(id, val.clone()) {
201 Ok(val) => map.entry(&id, &val),
202 Err(_) => map.entry(&id, &val),
203 },
204 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}