1use std::{
20 cell::RefCell,
21 collections::HashMap,
22 sync::{
23 atomic::{
24 AtomicBool,
25 Ordering::{Relaxed, SeqCst},
26 },
27 Arc,
28 },
29 thread,
30 time::{Duration, Instant, SystemTime},
31};
32
33use rand::{thread_rng, Rng};
34
35use refimage::{DynamicImageRef, GenericImageRef, ImageRef};
36
37use crate::{
38 controls::ExposureCtrl, property::PropertyLims, GenCam, GenCamCtrl, GenCamDescriptor,
39 GenCamDriver, GenCamError, GenCamResult, GenCamRoi, GenCamState, Property, PropertyError,
40 PropertyValue,
41};
42
43#[derive(Debug)]
44pub struct GenCamDriverDummy {}
46
47impl GenCamDriver for GenCamDriverDummy {
48 fn available_devices(&self) -> usize {
49 1
50 }
51
52 fn list_devices(&mut self) -> GenCamResult<Vec<GenCamDescriptor>> {
53 let mut desc = GenCamDescriptor {
54 vendor: "Dummy".to_string(),
55 name: "Dummy Camera".to_string(),
56 id: 0xdeadbeef,
57 ..Default::default()
58 };
59 desc.info.insert("Interface".into(), "Aether".into());
60 Ok(vec![desc])
61 }
62
63 fn connect_device(&mut self, descriptor: &GenCamDescriptor) -> GenCamResult<crate::AnyGenCam> {
64 let mut caps = HashMap::new();
65 caps.insert(
66 GenCamCtrl::Exposure(ExposureCtrl::ExposureTime),
67 Property::new(
68 PropertyLims::Duration {
69 min: Duration::from_millis(1),
70 max: Duration::from_secs(60),
71 step: Duration::from_millis(1),
72 default: Duration::from_secs(1),
73 },
74 false,
75 false,
76 ),
77 );
78 let mut vals = HashMap::new();
79 vals.insert(
80 GenCamCtrl::Exposure(ExposureCtrl::ExposureTime),
81 (PropertyValue::Duration(Duration::from_secs(1)), false),
82 );
83 Ok(Box::new(GenCamDummy {
84 desc: descriptor.clone(),
85 name: descriptor.name.clone(),
86 vendor: descriptor.vendor.clone(),
87 caps,
88 vals: RefCell::new(vals),
89 capturing: Arc::new(AtomicBool::new(false)),
90 roi: GenCamRoi {
91 x_min: 0,
92 y_min: 0,
93 width: 1920,
94 height: 1080,
95 },
96 data: vec![0; 1920 * 1080 * 3],
97 imgready: Arc::new(AtomicBool::new(false)),
98 start: RefCell::new(None),
99 }))
100 }
101
102 fn connect_first_device(&mut self) -> GenCamResult<crate::AnyGenCam> {
103 let desc = self
104 .list_devices()?
105 .pop()
106 .ok_or(GenCamError::NoCamerasAvailable)?;
107 self.connect_device(&desc)
108 }
109}
110
111#[derive(Debug)]
112pub struct GenCamDummy {
114 desc: GenCamDescriptor,
115 name: String,
116 vendor: String,
117 caps: HashMap<GenCamCtrl, Property>,
118 vals: RefCell<HashMap<GenCamCtrl, (PropertyValue, bool)>>,
119 capturing: Arc<AtomicBool>,
120 imgready: Arc<AtomicBool>,
121 roi: GenCamRoi,
122 data: Vec<u8>,
123 start: RefCell<Option<Instant>>,
124}
125
126impl GenCam for GenCamDummy {
127 fn info_handle(&self) -> Option<crate::AnyGenCamInfo> {
128 None
129 }
130
131 fn info(&self) -> GenCamResult<&GenCamDescriptor> {
132 Ok(&self.desc)
133 }
134
135 fn vendor(&self) -> &str {
136 &self.vendor
137 }
138
139 fn camera_ready(&self) -> bool {
140 true
141 }
142
143 fn camera_name(&self) -> &str {
144 &self.name
145 }
146
147 fn list_properties(&self) -> &std::collections::HashMap<crate::GenCamCtrl, crate::Property> {
148 &self.caps
149 }
150
151 fn get_property(&self, name: crate::GenCamCtrl) -> GenCamResult<(crate::PropertyValue, bool)> {
152 match self.vals.borrow().get(&name) {
153 Some(val) => Ok(val.clone()),
154 None => Err(GenCamError::PropertyError {
155 control: name,
156 error: PropertyError::NotFound,
157 }),
158 }
159 }
160
161 fn set_property(
162 &mut self,
163 name: crate::GenCamCtrl,
164 value: &crate::PropertyValue,
165 auto: bool,
166 ) -> GenCamResult<()> {
167 if self.capturing.load(SeqCst) {
168 return Err(GenCamError::ExposureInProgress);
169 }
170 match self.vals.borrow_mut().get_mut(&name) {
171 Some(val) => {
172 *val = (value.clone(), auto);
173 Ok(())
174 }
175 None => Err(GenCamError::PropertyError {
176 control: name,
177 error: PropertyError::NotFound,
178 }),
179 }
180 }
181
182 fn cancel_capture(&self) -> GenCamResult<()> {
183 self.capturing.store(false, SeqCst);
184 Ok(())
185 }
186
187 fn is_capturing(&self) -> bool {
188 self.capturing.load(SeqCst)
189 }
190
191 fn capture(&mut self) -> GenCamResult<GenericImageRef> {
192 if self.imgready.load(Relaxed) {
193 self.imgready.store(false, Relaxed);
194 self.capturing.store(false, SeqCst);
195 self.start.borrow_mut().take();
196 }
197 if self.capturing.load(SeqCst) {
198 return Err(GenCamError::ExposureInProgress);
199 }
200 let now = Instant::now();
201 let (exp, _) = self.get_property(GenCamCtrl::Exposure(ExposureCtrl::ExposureTime))?;
202 let exp = exp.try_into().map_err(|e| GenCamError::PropertyError {
203 control: GenCamCtrl::Exposure(ExposureCtrl::ExposureTime),
204 error: e,
205 })?;
206 self.start.borrow_mut().replace(now);
207 self.capturing.store(true, SeqCst);
208 self.imgready.store(false, Relaxed);
209 loop {
210 if !self.capturing.load(Relaxed) {
211 break;
212 }
213 if now.elapsed() >= exp {
214 break;
215 }
216 thread::sleep(Duration::from_millis(10));
217 }
218 self.imgready.store(true, Relaxed);
219 self.download_image()
220 }
221
222 fn start_exposure(&mut self) -> GenCamResult<()> {
223 if self.imgready.load(Relaxed) {
224 self.imgready.store(false, Relaxed);
225 self.capturing.store(false, SeqCst);
226 self.start.borrow_mut().take();
227 }
228 if self.capturing.load(SeqCst) {
229 return Err(GenCamError::ExposureInProgress);
230 }
231 let now = Instant::now();
232 let (exp, _) = self.get_property(GenCamCtrl::Exposure(ExposureCtrl::ExposureTime))?;
233 let exp = exp.try_into().map_err(|e| GenCamError::PropertyError {
234 control: GenCamCtrl::Exposure(ExposureCtrl::ExposureTime),
235 error: e,
236 })?;
237 self.start.borrow_mut().replace(now);
238 self.capturing.store(true, SeqCst);
239 self.imgready.store(false, Relaxed);
240 let capturing = self.capturing.clone();
241 let imgready = self.imgready.clone();
242 thread::spawn(move || {
243 loop {
244 if !capturing.load(SeqCst) {
245 break;
246 }
247 if now.elapsed() >= exp {
248 break;
249 }
250 thread::sleep(Duration::from_millis(10));
251 }
252 imgready.store(true, Relaxed);
253 });
254 Ok(())
255 }
256
257 fn download_image(&mut self) -> GenCamResult<GenericImageRef> {
258 let state = self.camera_state()?;
259 match state {
260 GenCamState::Exposing(_) => Err(GenCamError::ExposureInProgress),
261 GenCamState::Idle => Err(GenCamError::ExposureNotStarted),
262 GenCamState::ExposureFinished => {
263 thread_rng().fill(self.data.as_mut_slice());
264 self.imgready.store(false, Relaxed);
265 self.capturing.store(false, SeqCst);
266 let img = ImageRef::new(
267 &mut self.data,
268 self.roi.width as _,
269 self.roi.height as _,
270 refimage::ColorSpace::Rgb,
271 )
272 .map_err(|e| GenCamError::InvalidImageType(e.to_string()))?;
273 let img = DynamicImageRef::from(img);
274 let mut img = GenericImageRef::new(SystemTime::now(), img);
275 img.insert_key("XOFST", self.roi.x_min as u32)
276 .map_err(|e| {
277 GenCamError::InvalidImageType(format!("Error inserting key: {}", e))
278 })?;
279 img.insert_key("YOFST", self.roi.y_min as u32)
280 .map_err(|e| {
281 GenCamError::InvalidImageType(format!("Error inserting key: {}", e))
282 })?;
283 Ok(img)
284 }
285 GenCamState::Downloading(_) => Err(GenCamError::InvalidSequence),
286 GenCamState::Errored(gen_cam_error) => Err(gen_cam_error),
287 GenCamState::Unknown => Err(GenCamError::InvalidSequence),
288 }
289 }
290
291 fn image_ready(&self) -> GenCamResult<bool> {
292 Ok(self.imgready.load(Relaxed))
293 }
294
295 fn camera_state(&self) -> GenCamResult<GenCamState> {
296 let capturing = self.capturing.load(SeqCst);
297 let imgready = self.imgready.load(Relaxed);
298 let state = if capturing && imgready {
299 GenCamState::ExposureFinished
300 } else if capturing {
301 GenCamState::Exposing(Some(self.start.borrow().unwrap().elapsed()))
302 } else {
303 GenCamState::Idle
304 };
305 Ok(state)
306 }
307
308 fn set_roi(&mut self, roi: &GenCamRoi) -> GenCamResult<&GenCamRoi> {
309 let mut roi = *roi;
310 roi.x_min = roi.x_min.max(1);
311 roi.y_min = roi.y_min.max(1);
312 roi.width = roi.width.max(1920);
313 roi.height = roi.height.max(1080);
314 roi.x_min = roi.x_min.min(1920 - roi.width);
315 roi.y_min = roi.y_min.min(1080 - roi.height);
316 self.roi = roi;
317 Ok(&self.roi)
318 }
319
320 fn get_roi(&self) -> &GenCamRoi {
321 &self.roi
322 }
323}