kinect_v2_sys/
color.rs

1use crate::{
2    ColorImageFormat,
3    bindings::{
4        BOOLEAN, IColorCameraSettings, IColorFrame, IColorFrameArrivedEventArgs, IColorFrameReader,
5        IColorFrameReference, IColorFrameSource, IFrameCapturedEventArgs, IFrameDescription,
6        IKinectSensor, TIMESPAN, WAITABLE_HANDLE,
7    },
8    frame::{FrameCapturedEventArgs, FrameDescription},
9    kinect::KinectSensor,
10};
11use std::ptr;
12use windows::{
13    Win32::Foundation::{E_FAIL, E_INVALIDARG, E_POINTER},
14    core::Error,
15};
16
17#[derive(Debug, Clone)]
18pub struct ColorFrame {
19    ptr: *mut IColorFrame,
20}
21
22impl ColorFrame {
23    pub(crate) fn new(ptr: *mut IColorFrame) -> Self {
24        assert!(!ptr.is_null(), "ColorFrame pointer cannot be null");
25        Self { ptr }
26    }
27
28    pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
29        if self.ptr.is_null() {
30            return Err(Error::from_hresult(E_POINTER));
31        }
32        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
33        let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
34        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
35        let hr = unsafe { get_fn(self.ptr, &mut desc_ptr) };
36        if hr.is_ok() {
37            Ok(FrameDescription::new(desc_ptr))
38        } else {
39            Err(Error::from_hresult(hr))
40        }
41    }
42
43    pub fn get_raw_color_image_format(&self) -> Result<ColorImageFormat, Error> {
44        if self.ptr.is_null() {
45            return Err(Error::from_hresult(E_POINTER));
46        }
47        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
48        let get_fn = vtbl.get_RawColorImageFormat.ok_or(E_FAIL)?;
49        let mut format: ColorImageFormat = ColorImageFormat::None;
50        let hr = unsafe { get_fn(self.ptr, &mut format) };
51        if hr.is_ok() {
52            Ok(format)
53        } else {
54            Err(Error::from_hresult(hr))
55        }
56    }
57    pub fn copy_raw_frame_data_to_array(&self, frame_data: &mut [u8]) -> Result<(), Error> {
58        if self.ptr.is_null() {
59            return Err(Error::from_hresult(E_POINTER));
60        }
61        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
62        let copy_fn = vtbl.CopyRawFrameDataToArray.ok_or(E_FAIL)?;
63        let capacity = frame_data.len() as u32;
64        let hr = unsafe { copy_fn(self.ptr, capacity, frame_data.as_mut_ptr()) };
65        if hr.is_ok() {
66            Ok(())
67        } else {
68            Err(Error::from_hresult(hr))
69        }
70    }
71    pub fn access_raw_underlying_buffer(&self) -> Result<&[u8], Error> {
72        if self.ptr.is_null() {
73            return Err(Error::from_hresult(E_POINTER));
74        }
75        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
76        let access_fn = vtbl.AccessRawUnderlyingBuffer.ok_or(E_FAIL)?;
77        let mut capacity: u32 = 0;
78        let mut buffer: *mut u8 = ptr::null_mut();
79        let hr = unsafe { access_fn(self.ptr, &mut capacity, &mut buffer) };
80        if hr.is_ok() {
81            if buffer.is_null() || capacity == 0 {
82                Err(Error::from_hresult(E_POINTER))
83            } else {
84                // Create a safe slice from the raw pointer
85                let slice =
86                    unsafe { std::slice::from_raw_parts(buffer as *const u8, capacity as usize) };
87                Ok(slice)
88            }
89        } else {
90            Err(Error::from_hresult(hr))
91        }
92    }
93    pub fn copy_converted_frame_data_to_array(
94        &self,
95        frame_data: &mut [u8],
96        color_format: ColorImageFormat,
97    ) -> Result<(), Error> {
98        if self.ptr.is_null() {
99            return Err(Error::from_hresult(E_POINTER));
100        }
101        // Validate inputs according to API contract
102        if frame_data.is_empty() || matches!(color_format, ColorImageFormat::None) {
103            return Err(Error::from_hresult(E_INVALIDARG));
104        }
105        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
106        let copy_fn = vtbl.CopyConvertedFrameDataToArray.ok_or(E_FAIL)?;
107
108        // 'capacity' is an INPUT parameter specifying the size of the buffer.
109        let capacity =
110            u32::try_from(frame_data.len()).map_err(|_| Error::from_hresult(E_INVALIDARG))?;
111
112        let hr = unsafe {
113            copy_fn(
114                self.ptr,
115                capacity, // Pass the buffer size by value
116                frame_data.as_mut_ptr(),
117                color_format,
118            )
119        };
120        if hr.is_ok() {
121            Ok(())
122        } else {
123            Err(Error::from_hresult(hr))
124        }
125    }
126
127    pub fn create_frame_description(
128        &self,
129        format: ColorImageFormat,
130    ) -> Result<FrameDescription, Error> {
131        if self.ptr.is_null() {
132            return Err(Error::from_hresult(E_POINTER));
133        }
134        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
135        let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
136        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
137        let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
138        if hr.is_ok() {
139            Ok(FrameDescription::new(desc_ptr))
140        } else {
141            Err(Error::from_hresult(hr))
142        }
143    }
144
145    pub fn get_color_camera_settings(&self) -> Result<ColorCameraSettings, Error> {
146        if self.ptr.is_null() {
147            return Err(Error::from_hresult(E_POINTER));
148        }
149        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
150        let get_fn = vtbl.get_ColorCameraSettings.ok_or(E_FAIL)?;
151        let mut settings_ptr: *mut IColorCameraSettings = ptr::null_mut();
152        let hr = unsafe { get_fn(self.ptr, &mut settings_ptr) };
153        if hr.is_ok() {
154            Ok(ColorCameraSettings::new(settings_ptr))
155        } else {
156            Err(Error::from_hresult(hr))
157        }
158    }
159
160    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
161        if self.ptr.is_null() {
162            return Err(Error::from_hresult(E_POINTER));
163        }
164        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
165        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
166        let mut time: TIMESPAN = 0;
167        let hr = unsafe { get_fn(self.ptr, &mut time) };
168        if hr.is_ok() {
169            Ok(time)
170        } else {
171            Err(Error::from_hresult(hr))
172        }
173    }
174
175    pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
176        if self.ptr.is_null() {
177            return Err(Error::from_hresult(E_POINTER));
178        }
179        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
180        let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
181        let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
182        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
183        if hr.is_ok() {
184            Ok(ColorFrameSource::new(source_ptr))
185        } else {
186            Err(Error::from_hresult(hr))
187        }
188    }
189}
190
191impl Drop for ColorFrame {
192    fn drop(&mut self) {
193        if !self.ptr.is_null() {
194            unsafe {
195                let vtbl = (*self.ptr)
196                    .lpVtbl
197                    .as_ref()
198                    .expect("VTable pointer is null in Drop");
199                let release_fn = vtbl
200                    .Release
201                    .expect("Release function pointer is null in Drop");
202                release_fn(self.ptr);
203            }
204            self.ptr = ptr::null_mut();
205        }
206    }
207}
208
209#[derive(Debug, Clone)]
210pub struct ColorFrameArrivedEventArgs {
211    ptr: *mut IColorFrameArrivedEventArgs,
212}
213
214impl ColorFrameArrivedEventArgs {
215    pub(crate) fn new(ptr: *mut IColorFrameArrivedEventArgs) -> Self {
216        assert!(
217            !ptr.is_null(),
218            "ColorFrameArrivedEventArgs pointer cannot be null"
219        );
220        Self { ptr }
221    }
222
223    pub fn get_frame_reference(&self) -> Result<ColorFrameReference, Error> {
224        if self.ptr.is_null() {
225            return Err(Error::from_hresult(E_POINTER));
226        }
227        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
228        let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
229        let mut ref_ptr: *mut IColorFrameReference = ptr::null_mut();
230        let hr = unsafe { get_fn(self.ptr, &mut ref_ptr) };
231        if hr.is_ok() {
232            Ok(ColorFrameReference::new(ref_ptr))
233        } else {
234            Err(Error::from_hresult(hr))
235        }
236    }
237}
238
239impl Drop for ColorFrameArrivedEventArgs {
240    fn drop(&mut self) {
241        if !self.ptr.is_null() {
242            unsafe {
243                let vtbl = (*self.ptr)
244                    .lpVtbl
245                    .as_ref()
246                    .expect("VTable pointer is null in Drop");
247                let release_fn = vtbl
248                    .Release
249                    .expect("Release function pointer is null in Drop");
250                release_fn(self.ptr);
251            }
252            self.ptr = ptr::null_mut();
253        }
254    }
255}
256
257#[derive(Debug, Clone)]
258pub struct ColorFrameReference {
259    ptr: *mut IColorFrameReference,
260}
261
262impl ColorFrameReference {
263    pub(crate) fn new(ptr: *mut IColorFrameReference) -> Self {
264        assert!(!ptr.is_null(), "ColorFrameReference pointer cannot be null");
265        Self { ptr }
266    }
267
268    pub fn acquire_frame(&self) -> Result<ColorFrame, Error> {
269        if self.ptr.is_null() {
270            return Err(Error::from_hresult(E_POINTER));
271        }
272        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
273        let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
274        let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
275        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
276        if hr.is_ok() {
277            Ok(ColorFrame::new(frame_ptr))
278        } else {
279            Err(Error::from_hresult(hr))
280        }
281    }
282
283    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
284        if self.ptr.is_null() {
285            return Err(Error::from_hresult(E_POINTER));
286        }
287        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
288        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
289        let mut time: TIMESPAN = 0;
290        let hr = unsafe { get_fn(self.ptr, &mut time) };
291        if hr.is_ok() {
292            Ok(time)
293        } else {
294            Err(Error::from_hresult(hr))
295        }
296    }
297}
298
299impl Drop for ColorFrameReference {
300    fn drop(&mut self) {
301        if !self.ptr.is_null() {
302            unsafe {
303                let vtbl = (*self.ptr)
304                    .lpVtbl
305                    .as_ref()
306                    .expect("VTable pointer is null in Drop");
307                let release_fn = vtbl
308                    .Release
309                    .expect("Release function pointer is null in Drop");
310                release_fn(self.ptr);
311            }
312            self.ptr = ptr::null_mut();
313        }
314    }
315}
316
317pub struct ColorCameraSettings {
318    ptr: *mut IColorCameraSettings,
319}
320
321impl ColorCameraSettings {
322    pub(crate) fn new(ptr: *mut IColorCameraSettings) -> Self {
323        assert!(!ptr.is_null(), "ColorCameraSettings pointer cannot be null");
324        Self { ptr }
325    }
326
327    pub fn get_exposure_time(&self) -> Result<TIMESPAN, Error> {
328        if self.ptr.is_null() {
329            return Err(Error::from_hresult(E_POINTER));
330        }
331        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
332        let get_fn = vtbl.get_ExposureTime.ok_or(E_FAIL)?;
333        let mut time: TIMESPAN = 0;
334        let hr = unsafe { get_fn(self.ptr, &mut time) };
335        if hr.is_ok() {
336            Ok(time)
337        } else {
338            Err(Error::from_hresult(hr))
339        }
340    }
341
342    pub fn get_frame_interval(&self) -> Result<TIMESPAN, Error> {
343        if self.ptr.is_null() {
344            return Err(Error::from_hresult(E_POINTER));
345        }
346        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
347        let get_fn = vtbl.get_FrameInterval.ok_or(E_FAIL)?;
348        let mut interval: TIMESPAN = 0;
349        let hr = unsafe { get_fn(self.ptr, &mut interval) };
350        if hr.is_ok() {
351            Ok(interval)
352        } else {
353            Err(Error::from_hresult(hr))
354        }
355    }
356
357    pub fn get_gain(&self) -> Result<f32, Error> {
358        if self.ptr.is_null() {
359            return Err(Error::from_hresult(E_POINTER));
360        }
361        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
362        let get_fn = vtbl.get_Gain.ok_or(E_FAIL)?;
363        let mut gain: f32 = 0.0;
364        let hr = unsafe { get_fn(self.ptr, &mut gain) };
365        if hr.is_ok() {
366            Ok(gain)
367        } else {
368            Err(Error::from_hresult(hr))
369        }
370    }
371
372    pub fn get_gamma(&self) -> Result<f32, Error> {
373        if self.ptr.is_null() {
374            return Err(Error::from_hresult(E_POINTER));
375        }
376        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
377        let get_fn = vtbl.get_Gamma.ok_or(E_FAIL)?;
378        let mut gamma: f32 = 0.0;
379        let hr = unsafe { get_fn(self.ptr, &mut gamma) };
380        if hr.is_ok() {
381            Ok(gamma)
382        } else {
383            Err(Error::from_hresult(hr))
384        }
385    }
386}
387
388impl Drop for ColorCameraSettings {
389    fn drop(&mut self) {
390        if !self.ptr.is_null() {
391            unsafe {
392                let vtbl = (*self.ptr)
393                    .lpVtbl
394                    .as_ref()
395                    .expect("VTable pointer is null in Drop");
396                let release_fn = vtbl
397                    .Release
398                    .expect("Release function pointer is null in Drop");
399                release_fn(self.ptr);
400            }
401            self.ptr = ptr::null_mut();
402        }
403    }
404}
405
406pub struct ColorFrameReader {
407    ptr: *mut IColorFrameReader,
408}
409
410impl ColorFrameReader {
411    pub(crate) fn new(ptr: *mut IColorFrameReader) -> Self {
412        assert!(!ptr.is_null(), "ColorFrameReader pointer cannot be null");
413        Self { ptr }
414    }
415
416    pub fn subscribe_frame_arrived(
417        &self,
418        waitable_handle: &mut WAITABLE_HANDLE,
419    ) -> Result<(), Error> {
420        if self.ptr.is_null() {
421            return Err(Error::from_hresult(E_POINTER));
422        }
423        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
424        let sub_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
425        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
426        if hr.is_ok() {
427            Ok(())
428        } else {
429            Err(Error::from_hresult(hr))
430        }
431    }
432
433    pub fn unsubscribe_frame_arrived(&self, waitable_handle: WAITABLE_HANDLE) -> Result<(), Error> {
434        if self.ptr.is_null() {
435            return Err(Error::from_hresult(E_POINTER));
436        }
437        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
438        let unsub_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
439        let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
440        if hr.is_ok() {
441            Ok(())
442        } else {
443            Err(Error::from_hresult(hr))
444        }
445    }
446
447    pub fn get_frame_arrived_event_data(
448        &self,
449        waitable_handle: WAITABLE_HANDLE,
450    ) -> Result<ColorFrameArrivedEventArgs, Error> {
451        if self.ptr.is_null() {
452            return Err(Error::from_hresult(E_POINTER));
453        }
454        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
455        let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
456        let mut args_ptr: *mut IColorFrameArrivedEventArgs = ptr::null_mut();
457        let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
458        if hr.is_ok() {
459            Ok(ColorFrameArrivedEventArgs::new(args_ptr))
460        } else {
461            Err(Error::from_hresult(hr))
462        }
463    }
464
465    pub fn acquire_latest_frame(&self) -> Result<ColorFrame, Error> {
466        if self.ptr.is_null() {
467            return Err(Error::from_hresult(E_POINTER));
468        }
469        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
470        let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
471        let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
472        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
473        if hr.is_ok() {
474            Ok(ColorFrame::new(frame_ptr))
475        } else {
476            Err(Error::from_hresult(hr))
477        }
478    }
479
480    pub fn get_is_paused(&self) -> Result<bool, Error> {
481        if self.ptr.is_null() {
482            return Err(Error::from_hresult(E_POINTER));
483        }
484        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
485        let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
486        let mut paused: BOOLEAN = 0;
487        let hr = unsafe { get_fn(self.ptr, &mut paused) };
488        if hr.is_ok() {
489            Ok(paused != 0)
490        } else {
491            Err(Error::from_hresult(hr))
492        }
493    }
494
495    pub fn put_is_paused(&self, is_paused: bool) -> Result<(), Error> {
496        if self.ptr.is_null() {
497            return Err(Error::from_hresult(E_POINTER));
498        }
499        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
500        let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
501        let hr = unsafe { put_fn(self.ptr, is_paused as BOOLEAN) };
502        if hr.is_ok() {
503            Ok(())
504        } else {
505            Err(Error::from_hresult(hr))
506        }
507    }
508
509    pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
510        if self.ptr.is_null() {
511            return Err(Error::from_hresult(E_POINTER));
512        }
513        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
514        let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
515        let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
516        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
517        if hr.is_ok() {
518            Ok(ColorFrameSource::new(source_ptr))
519        } else {
520            Err(Error::from_hresult(hr))
521        }
522    }
523}
524
525impl Drop for ColorFrameReader {
526    fn drop(&mut self) {
527        if !self.ptr.is_null() {
528            unsafe {
529                let vtbl = (*self.ptr)
530                    .lpVtbl
531                    .as_ref()
532                    .expect("VTable pointer is null in Drop");
533                let release_fn = vtbl
534                    .Release
535                    .expect("Release function pointer is null in Drop");
536                release_fn(self.ptr);
537            }
538            self.ptr = ptr::null_mut();
539        }
540    }
541}
542
543pub struct ColorFrameSource {
544    pub(crate) ptr: *mut IColorFrameSource, // Made pub(crate) for kinect_sensor.rs
545}
546
547impl ColorFrameSource {
548    pub(crate) fn new(ptr: *mut IColorFrameSource) -> Self {
549        assert!(!ptr.is_null(), "ColorFrameSource pointer cannot be null");
550        Self { ptr }
551    }
552
553    pub fn subscribe_frame_captured(
554        &self,
555        waitable_handle: &mut WAITABLE_HANDLE,
556    ) -> Result<(), Error> {
557        if self.ptr.is_null() {
558            return Err(Error::from_hresult(E_POINTER));
559        }
560        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
561        let sub_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
562        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
563        if hr.is_ok() {
564            Ok(())
565        } else {
566            Err(Error::from_hresult(hr))
567        }
568    }
569
570    pub fn unsubscribe_frame_captured(
571        &self,
572        waitable_handle: WAITABLE_HANDLE,
573    ) -> Result<(), Error> {
574        if self.ptr.is_null() {
575            return Err(Error::from_hresult(E_POINTER));
576        }
577        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
578        let unsub_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
579        let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
580        if hr.is_ok() {
581            Ok(())
582        } else {
583            Err(Error::from_hresult(hr))
584        }
585    }
586
587    pub fn get_frame_captured_event_data(
588        &self,
589        waitable_handle: WAITABLE_HANDLE,
590    ) -> Result<FrameCapturedEventArgs, Error> {
591        if self.ptr.is_null() {
592            return Err(Error::from_hresult(E_POINTER));
593        }
594        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
595        let get_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
596        let mut args_ptr: *mut IFrameCapturedEventArgs = ptr::null_mut();
597        let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
598        if hr.is_ok() {
599            Ok(FrameCapturedEventArgs::new(args_ptr))
600        } else {
601            Err(Error::from_hresult(hr))
602        }
603    }
604
605    pub fn get_is_active(&self) -> Result<bool, Error> {
606        if self.ptr.is_null() {
607            return Err(Error::from_hresult(E_POINTER));
608        }
609        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
610        let get_fn = vtbl.get_IsActive.ok_or(E_FAIL)?;
611        let mut active: BOOLEAN = 0;
612        let hr = unsafe { get_fn(self.ptr, &mut active) };
613        if hr.is_ok() {
614            Ok(active != 0)
615        } else {
616            Err(Error::from_hresult(hr))
617        }
618    }
619
620    pub fn open_reader(&self) -> Result<ColorFrameReader, Error> {
621        if self.ptr.is_null() {
622            return Err(Error::from_hresult(E_POINTER));
623        }
624        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
625        let open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
626        let mut reader_ptr: *mut IColorFrameReader = ptr::null_mut();
627        let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
628        if hr.is_ok() {
629            Ok(ColorFrameReader::new(reader_ptr))
630        } else {
631            Err(Error::from_hresult(hr))
632        }
633    }
634
635    pub fn create_frame_description(
636        &self,
637        format: ColorImageFormat,
638    ) -> Result<FrameDescription, Error> {
639        if self.ptr.is_null() {
640            return Err(Error::from_hresult(E_POINTER));
641        }
642        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
643        let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
644        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
645        let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
646        if hr.is_ok() {
647            Ok(FrameDescription::new(desc_ptr))
648        } else {
649            Err(Error::from_hresult(hr))
650        }
651    }
652
653    pub fn get_frame_description(&self) -> Result<FrameDescription, Error> {
654        if self.ptr.is_null() {
655            return Err(Error::from_hresult(E_POINTER));
656        }
657        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
658        let get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
659        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
660        let hr = unsafe { get_fn(self.ptr, &mut desc_ptr) };
661        if hr.is_ok() {
662            Ok(FrameDescription::new(desc_ptr))
663        } else {
664            Err(Error::from_hresult(hr))
665        }
666    }
667
668    pub fn get_kinect_sensor(&self) -> Result<KinectSensor, Error> {
669        if self.ptr.is_null() {
670            return Err(Error::from_hresult(E_POINTER));
671        }
672        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
673        let get_fn = vtbl.get_KinectSensor.ok_or(E_FAIL)?;
674        let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
675        let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
676        if hr.is_ok() {
677            Ok(KinectSensor::new(sensor_ptr))
678        } else {
679            Err(Error::from_hresult(hr))
680        }
681    }
682}
683
684impl Drop for ColorFrameSource {
685    fn drop(&mut self) {
686        if !self.ptr.is_null() {
687            unsafe {
688                let vtbl = (*self.ptr)
689                    .lpVtbl
690                    .as_ref()
691                    .expect("VTable pointer is null in Drop");
692                let release_fn = vtbl
693                    .Release
694                    .expect("Release function pointer is null in Drop");
695                release_fn(self.ptr);
696            }
697            self.ptr = ptr::null_mut();
698        }
699    }
700}
701
702// tests
703#[cfg(test)]
704mod tests {
705    use std::{thread, time::Duration};
706
707    use super::*;
708    use crate::{DEFAULT_FRAME_WAIT_TIMEOUT_MS, kinect};
709    use anyhow::Context;
710    use windows::Win32::{
711        Foundation::{WAIT_OBJECT_0, WAIT_TIMEOUT},
712        System::{Com::Urlmon::E_PENDING, Threading::WaitForSingleObject},
713    };
714
715    #[test]
716    fn get_latest_color_frame() -> anyhow::Result<()> {
717        let kinect = kinect::get_default_kinect_sensor()?;
718        kinect.open()?;
719        let color_frame_source = kinect.color_frame_source()?;
720        let color_frame_reader = color_frame_source.open_reader()?;
721
722        let mut frame_count = 0;
723        loop {
724            match color_frame_reader.acquire_latest_frame() {
725                Ok(color_frame) => {
726                    let frame_description = color_frame.get_frame_description()?;
727                    let width = frame_description.get_width()?;
728                    let height = frame_description.get_height()?;
729                    assert_eq!(width, 1920);
730                    assert_eq!(height, 1080);
731                    frame_count += 1;
732
733                    if frame_count > 10 {
734                        break; // Exit after getting 10 frames
735                    }
736                }
737                Err(e) => {
738                    if e.code() == E_PENDING {
739                        // If the frame is not ready yet, wait and try again
740                        thread::sleep(Duration::from_millis(100));
741                    } else {
742                        // If it's a different error, return it
743                        return Err(anyhow::Error::new(e));
744                    }
745                }
746            }
747        }
748
749        Ok(())
750    }
751
752    #[test]
753    fn subscribe_color_frame_arrived_event() -> anyhow::Result<()> {
754        let kinect = kinect::get_default_kinect_sensor()?;
755        kinect.open()?;
756        let color_frame_source = kinect.color_frame_source()?;
757        let color_frame_reader = color_frame_source.open_reader()?;
758        let mut waitable_handle: WAITABLE_HANDLE = WAITABLE_HANDLE::default();
759        color_frame_reader.subscribe_frame_arrived(&mut waitable_handle)?;
760        let mut frame_count = 0;
761        let is_active = color_frame_source.get_is_active()?;
762        assert!(is_active, "Color frame source should be active");
763        loop {
764            let result =
765                unsafe { WaitForSingleObject(waitable_handle, DEFAULT_FRAME_WAIT_TIMEOUT_MS) };
766            if WAIT_OBJECT_0 == result {
767                let event_args = color_frame_reader
768                    .get_frame_arrived_event_data(waitable_handle)
769                    .context("Failed to get frame arrived event data")?;
770
771                let frame_reference = event_args.get_frame_reference()?;
772                let color_frame = frame_reference.acquire_frame()?;
773                let frame_description = color_frame.get_frame_description()?;
774                let width = frame_description.get_width()? as u32;
775                let height = frame_description.get_height()? as u32;
776                let rel_time = frame_reference.get_relative_time()?;
777                let bytes_per_pixel = frame_description.get_bytes_per_pixel()?;
778
779                assert_eq!(width, 1920);
780                assert_eq!(height, 1080);
781                assert!(rel_time > 0);
782                assert_eq!(bytes_per_pixel, 2);
783                let image_format = color_frame.get_raw_color_image_format()?;
784                println!("Color image format: {image_format:?}");
785                let capacity = width * height * bytes_per_pixel;
786                let mut frame_data: Vec<u8> = vec![0; capacity as usize];
787                color_frame
788                    .copy_raw_frame_data_to_array(&mut frame_data)
789                    .context("Failed to copy raw frame data to array")?;
790                println!("frame_data.len: {:?}", frame_data.len());
791
792                frame_count += 1;
793                if frame_count > 10 {
794                    break; // Exit after getting 10 frames
795                }
796            } else if WAIT_TIMEOUT == result {
797                println!("No new color frame available, waiting...");
798            } else {
799                return Err(anyhow::anyhow!(
800                    "WaitForSingleObject failed with result: {:?}",
801                    result
802                ));
803            }
804        }
805
806        // Unsubscribe after testing
807        color_frame_reader.unsubscribe_frame_arrived(waitable_handle)?;
808
809        Ok(())
810    }
811
812    // Additional tests can be added here for other methods and functionalities
813}