xiapi/
camera.rs

1/*
2 * Copyright (c) 2022. XIMEA GmbH - All Rights Reserved
3 */
4use std::ffi::CStr;
5use std::marker::PhantomData;
6use std::mem::size_of;
7use std::mem::MaybeUninit;
8use std::ops::Deref;
9use std::os::raw::c_char;
10use std::str::from_utf8;
11
12use paste::paste;
13use xiapi_sys::*;
14
15use crate::Image;
16use crate::Roi;
17
18/// This macro is used to generate getters and setters for xiAPI parameters.
19/// The parameters are specified using the following syntax: \[mut\] <ParamName>: <Type>
20/// Documentation on the parameter will be added to the getter.
21/// Generic documentation is always added to the setter.
22///
23/// ## Examples:
24///
25/// ```ignore
26/// param!(
27///     mut exposure: f32;
28/// )
29/// ```
30macro_rules! param {
31    // This rule follows the Incremental TT muncher pattern.
32    () => {};
33    // For mutable parameters:
34    (
35        $(#[doc = $doc:expr])*
36        mut $prm:ident : $type:ty;
37        $($tail:tt)*
38    ) => {
39        paste! {
40            // Generate a getter with custom documentation
41            $(#[doc = $doc])*
42            pub fn $prm(&self) -> Result<$type, XI_RETURN>{
43                unsafe {self.param([<XI_PRM_ $prm:upper>]) }
44             }
45
46            // Generate a getter for the increment
47            #[doc = "Get the increment for the `" $prm "` parameter. See also [Self::" $prm "()]"]
48            pub fn [<$prm _increment>](& self) -> Result<$type, XI_RETURN>{
49                unsafe {self.param_increment([<XI_PRM_ $prm:upper>])}
50            }
51
52            // Generate getter for the minimum
53            #[doc = "Get the minimum for the `" $prm "` parameter. See also [Self::" $prm "()]"]
54            pub fn [<$prm _minimum>](& self) -> Result<$type, XI_RETURN>{
55                unsafe {self.param_min([<XI_PRM_ $prm:upper>])}
56            }
57
58            // Generate getter for the maximum
59            #[doc = "Get the maximum for the `" $prm "` parameter. See also [Self::" $prm "()]"]
60            pub fn [<$prm _maximum>](& self) -> Result<$type, XI_RETURN>{
61                unsafe {self.param_max([<XI_PRM_ $prm:upper>])}
62            }
63
64            // Generate a setter
65            // TODO: Customizable documentation for setters
66            #[doc = "Set the `" $prm "` parameter. See also [Self::" $prm "()]"]
67            pub fn [<set_ $prm>](& mut self, value: $type ) -> Result<(), XI_RETURN>{
68                unsafe {self.set_param([<XI_PRM_ $prm:upper>], value)}
69            }
70            param!($($tail)*);
71        }
72    };
73    // For immutable parameters
74    (
75        $(#[doc = $doc:expr])*
76        $prm:ident : $type:ty;
77        $($tail:tt)*
78    ) => {
79        paste! {
80            // Generate a getter with custom documentation
81            $(#[doc = $doc])*
82            pub fn $prm( &self) -> Result < $type, XI_RETURN >{
83                unsafe {self.param(paste ! ([ < XI_PRM_ $prm: upper > ]))}
84            }
85            param!($($tail)*);
86        }
87    };
88}
89/// Connected and initialized XIMEA camera.
90///
91/// Must be mutable to allow changing any parameters. A non-mutable Camera can be used from
92/// multiple threads or processes safely.
93pub struct Camera {
94    device_handle: HANDLE,
95}
96
97/// Buffer that is used by the camera to transfer images to the host system.
98///
99/// The AcquisitionBuffer is the primary way to communicate with the camera while it is actively
100/// acquiring images.
101/// It is generated when the image acquisition is started and destroyed when the image acquisition
102/// is stopped.
103///
104/// **Important difference to the C/C++ xiAPI:**
105/// The AcquisitionBuffer temporarily consumes the Camera during acquisition, to prevent any
106/// interactions that may change parameters that are fixed while the image acquisition is running.
107/// Trying to change an parameter that is not changeable during acquisition is therefore an error at
108/// compile time (as opposed to runtime in C/C++).
109pub struct AcquisitionBuffer {
110    camera: Camera,
111}
112
113/// Initializes a camera and returns it.
114///
115/// If successful, this function returns a Camera object that represents the camera which was
116/// initialized.
117/// If an error occurs, the Result contains the error code.
118///
119/// It is possible but not recommended to open the same camera from different processes at the same
120/// time.
121/// The device is automatically closed when the Camera object is dropped.
122///
123/// The automatic bandwidth calculation is enabled by default when using this method.
124///
125/// # Arguments
126///
127/// * `dev_id`: The device ID for the device to be initialized. Usually device IDs are sequential
128/// and start at 0 for the first device in the system. Default value: 0
129///
130/// # Examples
131///
132/// ```
133/// # #[serial_test::file_serial]
134/// # fn main() -> Result<(), xiapi_sys::XI_RETURN>{
135///     let mut cam = xiapi::open_device(None)?;
136///     cam.set_exposure(10000 as f32);
137///     // Do more stuff with the camera ...
138/// #   Ok(())
139/// # }
140/// ```
141pub fn open_device(dev_id: Option<u32>) -> Result<Camera, XI_RETURN> {
142    let mut device_handle: HANDLE = std::ptr::null_mut();
143    let dev_id = dev_id.unwrap_or(0);
144    let err = unsafe { xiapi_sys::xiOpenDevice(dev_id, &mut device_handle) };
145    match err as XI_RET::Type {
146        XI_RET::XI_OK => Ok(Camera { device_handle }),
147        _ => Err(err),
148    }
149}
150
151/// Initialize the camera with the given bandwidth and return it.
152///
153/// If successful, this function returns a Camera object that represents the camera which was
154/// initialized.
155/// If an error occurs, the Result contains the error code.
156///
157/// The automatic bandwidth measurement is disabled when using this method. This can lead to faster device initialization.
158///
159/// # Arguments
160///
161/// *`dev_id`: The device ID for the device to be initialized. Usually device IDs are sequential
162/// and start at 0 for the first device in the system. Default value: 0
163/// *`bandwidth`: Transport layer bandwidth for this camera in MBit/s
164///
165/// # Examples
166///
167/// ```
168/// # #[serial_test::file_serial]
169/// # fn main() -> Result<(), xiapi_sys::XI_RETURN>{
170///     let mut cam = xiapi::open_device_manual_bandwidth(None, 1000)?;
171///     cam.set_exposure(10000 as f32);
172///     // Do more stuff with the camera ...
173/// #   Ok(())
174/// # }
175/// ```
176pub fn open_device_manual_bandwidth(
177    dev_id: Option<u32>,
178    bandwidth: i32,
179) -> Result<Camera, XI_RETURN> {
180    let cam = unsafe {
181        let bandwidth_param_c = match CStr::from_bytes_with_nul(XI_PRM_AUTO_BANDWIDTH_CALCULATION) {
182            Ok(c) => c,
183            Err(_) => return Err(XI_RET::XI_INVALID_ARG as XI_RETURN),
184        };
185        match i32::set_param(
186            std::ptr::null_mut(),
187            bandwidth_param_c.as_ptr(),
188            XI_SWITCH::XI_OFF as i32,
189        ) as XI_RET::Type
190        {
191            XI_RET::XI_OK => {}
192            err => return Err(err as i32),
193        };
194
195        let cam = open_device(dev_id);
196        match i32::set_param(
197            std::ptr::null_mut(),
198            bandwidth_param_c.as_ptr(),
199            XI_SWITCH::XI_ON as i32,
200        ) as XI_RET::Type
201        {
202            XI_RET::XI_OK => {}
203            _ => panic!("Could not enable auto bandwidth calculation!"),
204        }
205        cam
206    };
207    match cam {
208        Ok(mut cam) => {
209            cam.set_limit_bandwidth(bandwidth)?;
210            Ok(cam)
211        }
212        Err(err) => Err(err),
213    }
214}
215
216/// Returns the number of available cameras.
217///
218/// # Examples
219///
220/// ```
221/// # #[serial_test::file_serial]
222/// # fn main() -> Result<(), xiapi::XI_RETURN>{
223///     let number_devices = xiapi::number_devices()?;
224///     let mut cameras = Vec::with_capacity(number_devices as usize);
225///     for i in 0..number_devices {
226///         cameras.push(xiapi::open_device(Some(i))?);
227///     }
228/// # Ok(())
229/// # }
230pub fn number_devices() -> Result<u32, XI_RETURN> {
231    unsafe {
232        let mut value = 0u32;
233        let res = xiapi_sys::xiGetNumberDevices(&mut value);
234        match res as XI_RET::Type {
235            XI_RET::XI_OK => Ok(value),
236            _ => Err(res),
237        }
238    }
239}
240
241impl Drop for Camera {
242    fn drop(&mut self) {
243        unsafe {
244            xiapi_sys::xiCloseDevice(self.device_handle);
245        }
246    }
247}
248
249trait ParamType: Default {
250    unsafe fn get_param(
251        handle: xiapi_sys::HANDLE,
252        prm: *const std::os::raw::c_char,
253        value: &mut Self,
254    ) -> XI_RETURN;
255    unsafe fn set_param(
256        handle: xiapi_sys::HANDLE,
257        prm: *const std::os::raw::c_char,
258        value: Self,
259    ) -> XI_RETURN;
260}
261
262impl ParamType for f32 {
263    unsafe fn get_param(handle: HANDLE, prm: *const c_char, value: &mut Self) -> XI_RETURN {
264        xiapi_sys::xiGetParamFloat(handle, prm, value)
265    }
266
267    unsafe fn set_param(handle: HANDLE, prm: *const c_char, value: Self) -> XI_RETURN {
268        xiapi_sys::xiSetParamFloat(handle, prm, value)
269    }
270}
271
272impl ParamType for i32 {
273    unsafe fn get_param(handle: HANDLE, prm: *const c_char, value: &mut Self) -> XI_RETURN {
274        xiapi_sys::xiGetParamInt(handle, prm, value)
275    }
276
277    unsafe fn set_param(handle: HANDLE, prm: *const c_char, value: Self) -> XI_RETURN {
278        xiapi_sys::xiSetParamInt(handle, prm, value)
279    }
280}
281
282impl ParamType for u32 {
283    // Selectors in xiAPI are defined as unsigned int, but treated as if they were signed
284    unsafe fn get_param(handle: HANDLE, prm: *const c_char, value: &mut Self) -> XI_RETURN {
285        xiapi_sys::xiGetParamInt(handle, prm, value as *mut u32 as *mut i32)
286    }
287
288    unsafe fn set_param(handle: HANDLE, prm: *const c_char, value: Self) -> XI_RETURN {
289        xiapi_sys::xiSetParamInt(handle, prm, value as i32)
290    }
291}
292
293impl Camera {
294    /// Starts the image acquisition on this camera
295    ///
296    /// This function creates the AcquisitionBuffer and tells the camera to start streaming data
297    /// to this buffer.
298    /// The camera is temporarily consumed by the AcquisitionBuffer, so you can only interact with
299    /// it through the AcquisitionBuffer.
300    ///
301    /// # Examples
302    /// ```
303    /// # #[serial_test::file_serial]
304    /// # fn main() -> Result<(), xiapi_sys::XI_RETURN> {
305    ///     let cam = xiapi::open_device(None)?;
306    ///     let buffer = cam.start_acquisition()?;
307    ///     let image = buffer.next_image::<u8>(None)?;
308    ///     // Do something with the image;
309    ///     let cam = buffer.stop_acquisition()?;
310    /// #   Ok(())
311    /// # }
312    pub fn start_acquisition(self) -> Result<AcquisitionBuffer, XI_RETURN> {
313        let err = unsafe { xiapi_sys::xiStartAcquisition(self.device_handle) };
314        match err as XI_RET::Type {
315            XI_RET::XI_OK => Ok(AcquisitionBuffer { camera: self }),
316            _ => Err(err),
317        }
318    }
319
320    unsafe fn set_param<T: ParamType>(&mut self, param: &[u8], value: T) -> Result<(), XI_RETURN> {
321        let param_c = match CStr::from_bytes_with_nul(param) {
322            Ok(c) => c,
323            Err(_) => return Err(XI_RET::XI_INVALID_ARG as XI_RETURN),
324        };
325        let err = T::set_param(self.device_handle, param_c.as_ptr(), value);
326        match err as XI_RET::Type {
327            XI_RET::XI_OK => Ok(()),
328            _ => Err(err),
329        }
330    }
331
332    unsafe fn param<T: ParamType>(&self, param: &[u8]) -> Result<T, XI_RETURN> {
333        let mut value = T::default();
334        let param_c = match CStr::from_bytes_with_nul(param) {
335            Ok(c) => c,
336            Err(_) => return Err(XI_RET::XI_INVALID_ARG as XI_RETURN),
337        };
338        let err = T::get_param(self.device_handle, param_c.as_ptr(), &mut value);
339        match err as XI_RET::Type {
340            XI_RET::XI_OK => Ok(value),
341            _ => Err(err),
342        }
343    }
344
345    unsafe fn param_increment<T: ParamType>(&self, param: &'static [u8]) -> Result<T, XI_RETURN> {
346        self.param_info(param, XI_PRM_INFO_INCREMENT)
347    }
348
349    unsafe fn param_min<T: ParamType>(&self, param: &'static [u8]) -> Result<T, XI_RETURN> {
350        self.param_info(param, XI_PRM_INFO_MIN)
351    }
352
353    unsafe fn param_max<T: ParamType>(&self, param: &'static [u8]) -> Result<T, XI_RETURN> {
354        self.param_info(param, XI_PRM_INFO_MAX)
355    }
356
357    unsafe fn param_info<T: ParamType>(
358        &self,
359        param: &'static [u8],
360        info_modifier: &'static [u8],
361    ) -> Result<T, XI_RETURN> {
362        // Strings need to be sanitized and then concatenated
363        let param_utf8 = from_utf8(param).or(Err(XI_RET::XI_INVALID_ARG as i32))?;
364        let modifier_utf8 =
365            from_utf8(info_modifier).expect("UTF8 error on API constant -> Unreachable");
366        // We have to specifically trim the null character from the first string
367        let modified_param = format!(
368            "{}{}",
369            param_utf8.trim_matches(char::from(0)),
370            modifier_utf8
371        );
372        self.param(modified_param.as_bytes())
373    }
374
375    /// Set the region of interest on this camera.
376    ///
377    /// Return the region of interest that was actually set to the camera.
378    ///
379    /// # Examples
380    ///
381    /// ```
382    /// # #[serial_test::file_serial]
383    /// # fn main() -> Result<(), xiapi_sys::XI_RETURN> {
384    ///     let mut cam = xiapi::open_device(None)?;
385    ///     let roi = xiapi::Roi{
386    ///         offset_x: 100,
387    ///         offset_y: 100,
388    ///         width: 100,
389    ///         height: 100
390    ///     };
391    ///     let actual_roi = cam.set_roi(&roi)?;
392    /// # Ok(())
393    /// # }
394    ///
395    pub fn set_roi(&mut self, roi: &Roi) -> Result<Roi, XI_RETURN> {
396        self.set_offset_x(0)?;
397        self.set_offset_y(0)?;
398
399        let width_inc = self.width_increment()?;
400        let width = roi.width - (roi.width % width_inc);
401        self.set_width(width)?;
402
403        let height_inc = self.height_increment()?;
404        let height = roi.height - (roi.height % height_inc);
405        self.set_height(height)?;
406
407        let offset_x_inc = self.offset_x_increment()?;
408        let offset_x = roi.offset_x - (roi.offset_x % offset_x_inc);
409        self.set_offset_x(offset_x)?;
410
411        let offset_y_inc = self.offset_y_increment()?;
412        let offset_y = roi.offset_y - (roi.offset_y % offset_y_inc);
413        self.set_offset_y(offset_y)?;
414
415        let actual_roi = Roi {
416            offset_x,
417            offset_y,
418            width,
419            height,
420        };
421        Ok(actual_roi)
422    }
423
424    /// Returns the current roi from this camera
425    pub fn roi(&self) -> Result<Roi, XI_RETURN> {
426        let width = self.width()?;
427        let height = self.height()?;
428        let offset_x = self.offset_x()?;
429        let offset_y = self.offset_y()?;
430        let result = Roi {
431            offset_x,
432            offset_y,
433            width,
434            height,
435        };
436        Ok(result)
437    }
438
439    /// Convenience method to read counters from the camera with a single call
440    /// See also [Self.counter_selector] and [Self.counter_value]
441    pub fn counter(
442        &mut self,
443        counter_selector: XI_COUNTER_SELECTOR::Type,
444    ) -> Result<i32, XI_RETURN> {
445        let prev_selector = self.counter_selector()?;
446        self.set_counter_selector(counter_selector)?;
447        let result = self.counter_value()?;
448        self.set_counter_selector(prev_selector)?;
449        Ok(result)
450    }
451
452    param! {
453        /// Current exposure time in microseconds.
454        mut exposure: f32;
455
456        /// Sets the number of times of exposure in one frame.
457        mut exposure_burst_count: i32;
458
459        /// Set the gain in dB.
460        /// If the camera has more than one type of gain, you can use [Self::set_gain_selector()] to
461        /// select a gain.
462        mut gain: f32;
463
464        /// The currently selected type of gain for [Self::gain()] and [Self::set_gain()]
465        mut gain_selector: XI_GAIN_SELECTOR_TYPE::Type;
466
467        /// Changes image resolution by binning or skipping
468        mut downsampling: XI_DOWNSAMPLING_VALUE::Type;
469
470        /// Changes the downsampling type between binning and skipping
471        mut downsampling_type: XI_DOWNSAMPLING_TYPE::Type;
472
473        /// Format of the image data
474        mut image_data_format: XI_IMG_FORMAT::Type;
475
476        /// Selects the Test Pattern Generator Engine
477        mut test_pattern_generator_selector: XI_TEST_PATTERN_GENERATOR::Type;
478
479        /// Selects the Test Pattern to be generated by selected Generator Engine
480        mut test_pattern: XI_TEST_PATTERN::Type;
481
482        /// Immage ROI height (number of lines)
483        mut height: u32;
484
485        /// Image ROI width (number of columns)
486        mut width: u32;
487
488        /// Image ROI offset in the horizontal direction
489        mut offset_x: u32;
490
491        /// Image ROI offset in the vertical direction
492        mut offset_y: u32;
493
494        /// Camera acquisition data-rate limit on transport layer in Megabits per second.
495        mut limit_bandwidth: i32;
496
497        /// Available interface bandwidth measured by automatic bandwidth measurement.
498        available_bandwidth: i32;
499
500        /// Defines the source of trigger
501        mut trg_source: XI_TRG_SOURCE::Type;
502
503        /// Selects the type of trigger
504        mut trg_selector: XI_TRG_SELECTOR::Type;
505
506        /// Selects the type of trigger overlap
507        mut trg_overlap: XI_TRG_OVERLAP::Type;
508
509        /// Sets the number of frames to be triggered for each trigger signal.
510        /// This setting is only valid if the trigger selector is set to XI_TRG_SEL_FRAME_BURST_START
511        mut acq_frame_burst_count: u32;
512
513        /// Selects a GPI
514        mut gpi_selector: XI_GPI_SELECTOR::Type;
515
516        /// Defines functionality for the selected GPI
517        mut gpi_mode: XI_GPI_MODE::Type;
518
519        /// Selects a GPO
520        mut gpo_selector: XI_GPO_SELECTOR::Type;
521
522        /// Defines functionality for the selected GPO
523        mut gpo_mode: XI_GPO_MODE::Type;
524
525        /// Selects a LED
526        mut led_selector: XI_LED_SELECTOR::Type;
527
528        /// Defines functionality for the selected LED
529        mut led_mode: XI_LED_MODE::Type;
530
531        /// Enable or disable signal debounce for selected GPI
532        mut debounce_en: XI_SWITCH::Type;
533
534        /// Set user data to be stored in the image header
535        mut image_user_data: u32;
536
537        /// Set the bit depth for the ADCs on the sensor
538        /// # Examples
539        /// ```
540        /// # #[serial_test::file_serial()]
541        /// # fn main() -> Result<(), xiapi::XI_RETURN>{
542        /// # use xiapi_sys::XI_IMG_FORMAT::XI_RAW16;
543        /// # use xiapi::XI_BIT_DEPTH::XI_BPP_12;
544        /// let mut cam = xiapi::open_device(None)?;
545        /// cam.set_image_data_format(XI_RAW16)?;
546        /// cam.set_sensor_data_bit_depth(XI_BPP_12)?;
547        /// cam.set_output_data_bit_depth(XI_BPP_12)?;
548        /// cam.set_image_data_bit_depth(XI_BPP_12)?;
549        /// # assert_eq!(cam.sensor_data_bit_depth()?, XI_BPP_12);
550        /// # assert_eq!(cam.output_data_bit_depth()?, XI_BPP_12);
551        /// # assert_eq!(cam.image_data_bit_depth()?, XI_BPP_12);
552        /// # Ok(())
553        /// }
554        mut sensor_data_bit_depth: XI_BIT_DEPTH::Type;
555
556        /// Set the bit depth send from the camera to the PC
557        mut output_data_bit_depth: XI_BIT_DEPTH::Type;
558
559        /// Bit depth of the image returned by [Self::next_image()]
560        mut image_data_bit_depth: XI_BIT_DEPTH::Type;
561
562        /// Enable column fpn correction in camera
563        mut column_fpn_correction: XI_SWITCH::Type;
564
565        /// Enable row fpn correction in camera
566        mut row_fpn_correction: XI_SWITCH::Type;
567
568        /// Enable column black offset correction
569        mut column_black_offset_correction: XI_SWITCH::Type;
570
571        /// Enable row black offset correction
572        mut row_black_offset_correction: XI_SWITCH::Type;
573
574        /// Select the frame counter to read
575        mut counter_selector: XI_COUNTER_SELECTOR::Type;
576
577        /// Read the value of a frame counter selected with [Self::set_counter_selector]
578        counter_value: i32;
579
580        /// Select a sensor specific feature
581        mut sensor_feature_selector: XI_SENSOR_FEATURE_SELECTOR::Type;
582
583        /// Set a value for the feature selected with [Self::set_sensor_feature_selector]
584        mut sensor_feature_value: i32;
585
586        /// Read the sensor clock frequency in Hz
587        sensor_clock_freq_hz: f32;
588
589        /// Data move policy
590        mut buffer_policy: i32;
591
592        /// Auto white balance mode.
593        mut auto_wb: XI_SWITCH::Type;
594
595        /// White balance Red coefficient.
596        mut wb_kr: f32;
597
598        /// White balance Green coefficient.
599        mut wb_kg: f32;
600
601        /// White balance Blue coefficient.
602        mut wb_kb: f32;
603
604        /// Recent Frame mode.
605        mut recent_frame: XI_SWITCH::Type;
606    }
607}
608
609impl Deref for Camera {
610    type Target = HANDLE;
611
612    /// Returns a reference to the wrapped device handle.
613    ///
614    /// While getting the handle itself is safe, everything that can practically be done with it
615    /// should be considered unsafe. Especially operations that change the state of the camera
616    /// (e.g. setting parameters) are undefined behavior.
617    fn deref(&self) -> &Self::Target {
618        &self.device_handle
619    }
620}
621
622unsafe impl Send for Camera {
623}
624
625impl AcquisitionBuffer {
626    /// Stop the image acquisition.
627    ///
628    /// This function consumes the acquisition buffer and returns the contained camera.
629    /// All resources acquired when creating this AcquisitionBuffer using
630    /// [Camera::start_acquisition()] will be freed again.
631    ///
632    /// When this is called, the camera will stop acquiring images and images previously acquired
633    /// but not retrieved from the acquisition buffer can no longer be accessed.
634    pub fn stop_acquisition(self) -> Result<Camera, XI_RETURN> {
635        let err = unsafe { xiapi_sys::xiStopAcquisition(self.camera.device_handle) };
636        match err as XI_RET::Type {
637            XI_RET::XI_OK => Ok(self.camera),
638            _ => Err(err),
639        }
640    }
641
642    /// Get the next image.
643    ///
644    /// Returns an [Image] which refers to memory in this [AcquisitionBuffer].
645    /// The image will have a reference with the same lifetime as the AcquisitionBuffer making sure
646    /// that it is always "safe" to use (However, it may still be overwritten in unsafe buffer mode).
647    pub fn next_image<'a, T>(&'a self, timeout: Option<u32>) -> Result<Image<'a, T>, XI_RETURN> {
648        let timeout = timeout.unwrap_or(u32::MAX);
649        let xi_img = unsafe {
650            let mut img = MaybeUninit::<XI_IMG>::zeroed().assume_init();
651            img.size = size_of::<XI_IMG>() as u32;
652            img
653        };
654        let mut image = Image::<'a, T> {
655            xi_img,
656            pix_type: PhantomData::default(),
657        };
658        let ret = unsafe {
659            xiapi_sys::xiGetImage(self.camera.device_handle, timeout, &mut image.xi_img)
660        };
661
662        match ret as XI_RET::Type{
663            XI_RET::XI_OK => {
664                Ok(image)
665            }
666            x => {
667               Err(x as XI_RETURN)
668            }
669        }
670
671    }
672
673    /// Send a software trigger signal to the camera.
674    ///
675    /// Trigger source has to be set to XI_TRG_SOFTWARE for this to take effect
676    ///
677    /// # Examples
678    /// ```
679    /// # #[serial_test::file_serial]
680    /// # fn main() -> Result<(), xiapi_sys::XI_RETURN> {
681    ///     let mut cam = xiapi::open_device(None)?;
682    ///     cam.set_trg_source(xiapi_sys::XI_TRG_SOURCE::XI_TRG_SOFTWARE)?;
683    ///     let mut acq_buffer = cam.start_acquisition()?;
684    ///     acq_buffer.software_trigger()?;
685    ///     let img = acq_buffer.next_image::<u8>(None)?;
686    /// # Ok(())
687    /// # }
688    /// ```
689    pub fn software_trigger(&mut self) -> Result<(), XI_RETURN> {
690        unsafe { self.camera.set_param(XI_PRM_TRG_SOFTWARE, XI_SWITCH::XI_ON) }
691    }
692}
693
694unsafe impl Send for AcquisitionBuffer{
695
696}