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                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
196                    && let Some(release_fn) = vtbl.Release
197                {
198                    release_fn(self.ptr);
199                }
200            }
201            self.ptr = ptr::null_mut();
202        }
203    }
204}
205
206#[derive(Debug, Clone)]
207pub struct ColorFrameArrivedEventArgs {
208    ptr: *mut IColorFrameArrivedEventArgs,
209}
210
211impl ColorFrameArrivedEventArgs {
212    pub(crate) fn new(ptr: *mut IColorFrameArrivedEventArgs) -> Self {
213        assert!(
214            !ptr.is_null(),
215            "ColorFrameArrivedEventArgs pointer cannot be null"
216        );
217        Self { ptr }
218    }
219
220    pub fn get_frame_reference(&self) -> Result<ColorFrameReference, Error> {
221        if self.ptr.is_null() {
222            return Err(Error::from_hresult(E_POINTER));
223        }
224        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
225        let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
226        let mut ref_ptr: *mut IColorFrameReference = ptr::null_mut();
227        let hr = unsafe { get_fn(self.ptr, &mut ref_ptr) };
228        if hr.is_ok() {
229            Ok(ColorFrameReference::new(ref_ptr))
230        } else {
231            Err(Error::from_hresult(hr))
232        }
233    }
234}
235
236impl Drop for ColorFrameArrivedEventArgs {
237    fn drop(&mut self) {
238        if !self.ptr.is_null() {
239            unsafe {
240                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
241                    && let Some(release_fn) = vtbl.Release
242                {
243                    release_fn(self.ptr);
244                }
245            }
246            self.ptr = ptr::null_mut();
247        }
248    }
249}
250
251#[derive(Debug, Clone)]
252pub struct ColorFrameReference {
253    ptr: *mut IColorFrameReference,
254}
255
256impl ColorFrameReference {
257    pub(crate) fn new(ptr: *mut IColorFrameReference) -> Self {
258        assert!(!ptr.is_null(), "ColorFrameReference pointer cannot be null");
259        Self { ptr }
260    }
261
262    pub fn acquire_frame(&self) -> Result<ColorFrame, Error> {
263        if self.ptr.is_null() {
264            return Err(Error::from_hresult(E_POINTER));
265        }
266        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
267        let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
268        let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
269        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
270        if hr.is_ok() {
271            Ok(ColorFrame::new(frame_ptr))
272        } else {
273            Err(Error::from_hresult(hr))
274        }
275    }
276
277    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
278        if self.ptr.is_null() {
279            return Err(Error::from_hresult(E_POINTER));
280        }
281        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
282        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
283        let mut time: TIMESPAN = 0;
284        let hr = unsafe { get_fn(self.ptr, &mut time) };
285        if hr.is_ok() {
286            Ok(time)
287        } else {
288            Err(Error::from_hresult(hr))
289        }
290    }
291}
292
293impl Drop for ColorFrameReference {
294    fn drop(&mut self) {
295        if !self.ptr.is_null() {
296            unsafe {
297                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
298                    && let Some(release_fn) = vtbl.Release
299                {
300                    release_fn(self.ptr);
301                }
302            }
303            self.ptr = ptr::null_mut();
304        }
305    }
306}
307
308pub struct ColorCameraSettings {
309    ptr: *mut IColorCameraSettings,
310}
311
312impl ColorCameraSettings {
313    pub(crate) fn new(ptr: *mut IColorCameraSettings) -> Self {
314        assert!(!ptr.is_null(), "ColorCameraSettings pointer cannot be null");
315        Self { ptr }
316    }
317
318    pub fn get_exposure_time(&self) -> Result<TIMESPAN, Error> {
319        if self.ptr.is_null() {
320            return Err(Error::from_hresult(E_POINTER));
321        }
322        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
323        let get_fn = vtbl.get_ExposureTime.ok_or(E_FAIL)?;
324        let mut time: TIMESPAN = 0;
325        let hr = unsafe { get_fn(self.ptr, &mut time) };
326        if hr.is_ok() {
327            Ok(time)
328        } else {
329            Err(Error::from_hresult(hr))
330        }
331    }
332
333    pub fn get_frame_interval(&self) -> Result<TIMESPAN, Error> {
334        if self.ptr.is_null() {
335            return Err(Error::from_hresult(E_POINTER));
336        }
337        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
338        let get_fn = vtbl.get_FrameInterval.ok_or(E_FAIL)?;
339        let mut interval: TIMESPAN = 0;
340        let hr = unsafe { get_fn(self.ptr, &mut interval) };
341        if hr.is_ok() {
342            Ok(interval)
343        } else {
344            Err(Error::from_hresult(hr))
345        }
346    }
347
348    pub fn get_gain(&self) -> Result<f32, Error> {
349        if self.ptr.is_null() {
350            return Err(Error::from_hresult(E_POINTER));
351        }
352        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
353        let get_fn = vtbl.get_Gain.ok_or(E_FAIL)?;
354        let mut gain: f32 = 0.0;
355        let hr = unsafe { get_fn(self.ptr, &mut gain) };
356        if hr.is_ok() {
357            Ok(gain)
358        } else {
359            Err(Error::from_hresult(hr))
360        }
361    }
362
363    pub fn get_gamma(&self) -> Result<f32, Error> {
364        if self.ptr.is_null() {
365            return Err(Error::from_hresult(E_POINTER));
366        }
367        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
368        let get_fn = vtbl.get_Gamma.ok_or(E_FAIL)?;
369        let mut gamma: f32 = 0.0;
370        let hr = unsafe { get_fn(self.ptr, &mut gamma) };
371        if hr.is_ok() {
372            Ok(gamma)
373        } else {
374            Err(Error::from_hresult(hr))
375        }
376    }
377}
378
379impl Drop for ColorCameraSettings {
380    fn drop(&mut self) {
381        if !self.ptr.is_null() {
382            unsafe {
383                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
384                    && let Some(release_fn) = vtbl.Release
385                {
386                    release_fn(self.ptr);
387                }
388            }
389            self.ptr = ptr::null_mut();
390        }
391    }
392}
393
394pub struct ColorFrameReader {
395    ptr: *mut IColorFrameReader,
396}
397
398impl ColorFrameReader {
399    pub(crate) fn new(ptr: *mut IColorFrameReader) -> Self {
400        assert!(!ptr.is_null(), "ColorFrameReader pointer cannot be null");
401        Self { ptr }
402    }
403
404    pub fn subscribe_frame_arrived(
405        &self,
406        waitable_handle: &mut WAITABLE_HANDLE,
407    ) -> Result<(), Error> {
408        if self.ptr.is_null() {
409            return Err(Error::from_hresult(E_POINTER));
410        }
411        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
412        let sub_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
413        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
414        if hr.is_ok() {
415            Ok(())
416        } else {
417            Err(Error::from_hresult(hr))
418        }
419    }
420
421    pub fn unsubscribe_frame_arrived(&self, waitable_handle: WAITABLE_HANDLE) -> Result<(), Error> {
422        if self.ptr.is_null() {
423            return Err(Error::from_hresult(E_POINTER));
424        }
425        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
426        let unsub_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
427        let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
428        if hr.is_ok() {
429            Ok(())
430        } else {
431            Err(Error::from_hresult(hr))
432        }
433    }
434
435    pub fn get_frame_arrived_event_data(
436        &self,
437        waitable_handle: WAITABLE_HANDLE,
438    ) -> Result<ColorFrameArrivedEventArgs, Error> {
439        if self.ptr.is_null() {
440            return Err(Error::from_hresult(E_POINTER));
441        }
442        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
443        let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
444        let mut args_ptr: *mut IColorFrameArrivedEventArgs = ptr::null_mut();
445        let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
446        if hr.is_ok() {
447            Ok(ColorFrameArrivedEventArgs::new(args_ptr))
448        } else {
449            Err(Error::from_hresult(hr))
450        }
451    }
452
453    pub fn acquire_latest_frame(&self) -> Result<ColorFrame, Error> {
454        if self.ptr.is_null() {
455            return Err(Error::from_hresult(E_POINTER));
456        }
457        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
458        let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
459        let mut frame_ptr: *mut IColorFrame = ptr::null_mut();
460        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
461        if hr.is_ok() {
462            Ok(ColorFrame::new(frame_ptr))
463        } else {
464            Err(Error::from_hresult(hr))
465        }
466    }
467
468    pub fn get_is_paused(&self) -> Result<bool, Error> {
469        if self.ptr.is_null() {
470            return Err(Error::from_hresult(E_POINTER));
471        }
472        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
473        let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
474        let mut paused: BOOLEAN = 0;
475        let hr = unsafe { get_fn(self.ptr, &mut paused) };
476        if hr.is_ok() {
477            Ok(paused != 0)
478        } else {
479            Err(Error::from_hresult(hr))
480        }
481    }
482
483    pub fn put_is_paused(&self, is_paused: bool) -> Result<(), Error> {
484        if self.ptr.is_null() {
485            return Err(Error::from_hresult(E_POINTER));
486        }
487        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
488        let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
489        let hr = unsafe { put_fn(self.ptr, is_paused as BOOLEAN) };
490        if hr.is_ok() {
491            Ok(())
492        } else {
493            Err(Error::from_hresult(hr))
494        }
495    }
496
497    pub fn get_color_frame_source(&self) -> Result<ColorFrameSource, Error> {
498        if self.ptr.is_null() {
499            return Err(Error::from_hresult(E_POINTER));
500        }
501        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
502        let get_fn = vtbl.get_ColorFrameSource.ok_or(E_FAIL)?;
503        let mut source_ptr: *mut IColorFrameSource = ptr::null_mut();
504        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
505        if hr.is_ok() {
506            Ok(ColorFrameSource::new(source_ptr))
507        } else {
508            Err(Error::from_hresult(hr))
509        }
510    }
511}
512
513impl Drop for ColorFrameReader {
514    fn drop(&mut self) {
515        if !self.ptr.is_null() {
516            unsafe {
517                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref()
518                    && let Some(release_fn) = vtbl.Release
519                {
520                    release_fn(self.ptr);
521                }
522            }
523            self.ptr = ptr::null_mut();
524        }
525    }
526}
527
528pub struct ColorFrameSource {
529    pub(crate) ptr: *mut IColorFrameSource, // Made pub(crate) for kinect_sensor.rs
530}
531
532impl ColorFrameSource {
533    pub(crate) fn new(ptr: *mut IColorFrameSource) -> Self {
534        assert!(!ptr.is_null(), "ColorFrameSource pointer cannot be null");
535        Self { ptr }
536    }
537
538    pub fn subscribe_frame_captured(
539        &self,
540        waitable_handle: &mut WAITABLE_HANDLE,
541    ) -> Result<(), Error> {
542        if self.ptr.is_null() {
543            return Err(Error::from_hresult(E_POINTER));
544        }
545        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
546        let sub_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
547        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
548        if hr.is_ok() {
549            Ok(())
550        } else {
551            Err(Error::from_hresult(hr))
552        }
553    }
554
555    pub fn unsubscribe_frame_captured(
556        &self,
557        waitable_handle: WAITABLE_HANDLE,
558    ) -> Result<(), Error> {
559        if self.ptr.is_null() {
560            return Err(Error::from_hresult(E_POINTER));
561        }
562        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
563        let unsub_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
564        let hr = unsafe { unsub_fn(self.ptr, waitable_handle) };
565        if hr.is_ok() {
566            Ok(())
567        } else {
568            Err(Error::from_hresult(hr))
569        }
570    }
571
572    pub fn get_frame_captured_event_data(
573        &self,
574        waitable_handle: WAITABLE_HANDLE,
575    ) -> Result<FrameCapturedEventArgs, Error> {
576        if self.ptr.is_null() {
577            return Err(Error::from_hresult(E_POINTER));
578        }
579        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
580        let get_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
581        let mut args_ptr: *mut IFrameCapturedEventArgs = ptr::null_mut();
582        let hr = unsafe { get_fn(self.ptr, waitable_handle, &mut args_ptr) };
583        if hr.is_ok() {
584            Ok(FrameCapturedEventArgs::new(args_ptr))
585        } else {
586            Err(Error::from_hresult(hr))
587        }
588    }
589
590    pub fn get_is_active(&self) -> Result<bool, 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.get_IsActive.ok_or(E_FAIL)?;
596        let mut active: BOOLEAN = 0;
597        let hr = unsafe { get_fn(self.ptr, &mut active) };
598        if hr.is_ok() {
599            Ok(active != 0)
600        } else {
601            Err(Error::from_hresult(hr))
602        }
603    }
604
605    pub fn open_reader(&self) -> Result<ColorFrameReader, 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 open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
611        let mut reader_ptr: *mut IColorFrameReader = ptr::null_mut();
612        let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
613        if hr.is_ok() {
614            Ok(ColorFrameReader::new(reader_ptr))
615        } else {
616            Err(Error::from_hresult(hr))
617        }
618    }
619
620    pub fn create_frame_description(
621        &self,
622        format: ColorImageFormat,
623    ) -> Result<FrameDescription, Error> {
624        if self.ptr.is_null() {
625            return Err(Error::from_hresult(E_POINTER));
626        }
627        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
628        let create_fn = vtbl.CreateFrameDescription.ok_or(E_FAIL)?;
629        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
630        let hr = unsafe { create_fn(self.ptr, format, &mut desc_ptr) };
631        if hr.is_ok() {
632            Ok(FrameDescription::new(desc_ptr))
633        } else {
634            Err(Error::from_hresult(hr))
635        }
636    }
637
638    pub fn get_frame_description(&self) -> 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 get_fn = vtbl.get_FrameDescription.ok_or(E_FAIL)?;
644        let mut desc_ptr: *mut IFrameDescription = ptr::null_mut();
645        let hr = unsafe { get_fn(self.ptr, &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_kinect_sensor(&self) -> Result<KinectSensor, 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_KinectSensor.ok_or(E_FAIL)?;
659        let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
660        let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
661        if hr.is_ok() {
662            Ok(KinectSensor::new(sensor_ptr))
663        } else {
664            Err(Error::from_hresult(hr))
665        }
666    }
667}
668
669impl Drop for ColorFrameSource {
670    fn drop(&mut self) {
671        if !self.ptr.is_null() {
672            unsafe {
673                let vtbl = (*self.ptr)
674                    .lpVtbl
675                    .as_ref()
676                    .expect("VTable pointer is null in Drop");
677                let release_fn = vtbl
678                    .Release
679                    .expect("Release function pointer is null in Drop");
680                release_fn(self.ptr);
681            }
682            self.ptr = ptr::null_mut();
683        }
684    }
685}
686
687// tests
688#[cfg(test)]
689mod tests {
690    use std::{thread, time::Duration};
691
692    use super::*;
693    use crate::{DEFAULT_FRAME_WAIT_TIMEOUT_MS, kinect};
694    use anyhow::Context;
695    use windows::Win32::{
696        Foundation::{WAIT_OBJECT_0, WAIT_TIMEOUT},
697        System::{Com::Urlmon::E_PENDING, Threading::WaitForSingleObject},
698    };
699
700    #[test]
701    fn get_latest_color_frame() -> anyhow::Result<()> {
702        let kinect = kinect::get_default_kinect_sensor()?;
703        kinect.open()?;
704        let color_frame_source = kinect.color_frame_source()?;
705        let color_frame_reader = color_frame_source.open_reader()?;
706
707        let mut frame_count = 0;
708        loop {
709            match color_frame_reader.acquire_latest_frame() {
710                Ok(color_frame) => {
711                    let frame_description = color_frame.get_frame_description()?;
712                    let width = frame_description.get_width()?;
713                    let height = frame_description.get_height()?;
714                    assert_eq!(width, 1920);
715                    assert_eq!(height, 1080);
716                    frame_count += 1;
717
718                    if frame_count > 10 {
719                        break; // Exit after getting 10 frames
720                    }
721                }
722                Err(e) => {
723                    if e.code() == E_PENDING {
724                        // If the frame is not ready yet, wait and try again
725                        thread::sleep(Duration::from_millis(100));
726                    } else {
727                        // If it's a different error, return it
728                        return Err(anyhow::Error::new(e));
729                    }
730                }
731            }
732        }
733
734        Ok(())
735    }
736
737    #[test]
738    fn subscribe_color_frame_arrived_event() -> anyhow::Result<()> {
739        let kinect = kinect::get_default_kinect_sensor()?;
740        kinect.open()?;
741        let color_frame_source = kinect.color_frame_source()?;
742        let color_frame_reader = color_frame_source.open_reader()?;
743        let mut waitable_handle: WAITABLE_HANDLE = WAITABLE_HANDLE::default();
744        color_frame_reader.subscribe_frame_arrived(&mut waitable_handle)?;
745        let mut frame_count = 0;
746        let is_active = color_frame_source.get_is_active()?;
747        assert!(is_active, "Color frame source should be active");
748        loop {
749            let result =
750                unsafe { WaitForSingleObject(waitable_handle, DEFAULT_FRAME_WAIT_TIMEOUT_MS) };
751            if WAIT_OBJECT_0 == result {
752                let event_args = color_frame_reader
753                    .get_frame_arrived_event_data(waitable_handle)
754                    .context("Failed to get frame arrived event data")?;
755
756                let frame_reference = event_args.get_frame_reference()?;
757                let color_frame = frame_reference.acquire_frame()?;
758                let frame_description = color_frame.get_frame_description()?;
759                let width = frame_description.get_width()? as u32;
760                let height = frame_description.get_height()? as u32;
761                let rel_time = frame_reference.get_relative_time()?;
762                let bytes_per_pixel = frame_description.get_bytes_per_pixel()?;
763
764                assert_eq!(width, 1920);
765                assert_eq!(height, 1080);
766                assert!(rel_time > 0);
767                assert_eq!(bytes_per_pixel, 2);
768                let image_format = color_frame.get_raw_color_image_format()?;
769                println!("Color image format: {image_format:?}");
770                let capacity = width * height * bytes_per_pixel;
771                let mut frame_data: Vec<u8> = vec![0; capacity as usize];
772                color_frame
773                    .copy_raw_frame_data_to_array(&mut frame_data)
774                    .context("Failed to copy raw frame data to array")?;
775                println!("frame_data.len: {:?}", frame_data.len());
776
777                frame_count += 1;
778                if frame_count > 10 {
779                    break; // Exit after getting 10 frames
780                }
781            } else if WAIT_TIMEOUT == result {
782                println!("No new color frame available, waiting...");
783            } else {
784                return Err(anyhow::anyhow!(
785                    "WaitForSingleObject failed with result: {:?}",
786                    result
787                ));
788            }
789        }
790
791        // Unsubscribe after testing
792        color_frame_reader.unsubscribe_frame_arrived(waitable_handle)?;
793
794        Ok(())
795    }
796
797    // Additional tests can be added here for other methods and functionalities
798}