kinect_v2_sys/
body.rs

1use crate::bindings::{
2    self, BOOLEAN, CreateBodyHandPair, DetectionResult, FrameEdges, HandState, HandType, IBody,
3    IBodyFrame, IBodyFrameArrivedEventArgs, IBodyFrameReader, IBodyFrameReference,
4    IBodyFrameSource, IBodyHandPair, IFrameCapturedEventArgs, IKinectSensor, INT32, Joint,
5    JointOrientation, TIMESPAN, TrackingConfidence, UINT, WAITABLE_HANDLE,
6};
7use crate::frame::FrameCapturedEventArgs;
8use crate::kinect::KinectSensor;
9use std::ptr;
10use windows::Win32::Foundation::{E_FAIL, E_POINTER};
11use windows::core::Error;
12
13pub struct Body {
14    ptr: *mut IBody,
15}
16
17impl Body {
18    pub(crate) fn new(ptr: *mut IBody) -> Self {
19        assert!(!ptr.is_null());
20        Self { ptr }
21    }
22
23    pub fn get_joints(&self, joints: &mut [Joint]) -> Result<(), Error> {
24        if self.ptr.is_null() {
25            return Err(Error::from_hresult(E_POINTER));
26        }
27        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
28        let get_fn = vtbl.GetJoints.ok_or(E_FAIL)?;
29        let capacity = joints.len() as UINT;
30        let hr = unsafe { get_fn(self.ptr, capacity, joints.as_mut_ptr()) };
31        if hr.is_ok() {
32            Ok(())
33        } else {
34            Err(Error::from_hresult(hr))
35        }
36    }
37
38    pub fn get_joint_orientations(
39        &self,
40        joint_orientations: &mut [JointOrientation],
41    ) -> Result<(), Error> {
42        if self.ptr.is_null() {
43            return Err(Error::from_hresult(E_POINTER));
44        }
45        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
46        let get_fn = vtbl.GetJointOrientations.ok_or(E_FAIL)?;
47        let capacity = joint_orientations.len() as UINT;
48        let hr = unsafe { get_fn(self.ptr, capacity, joint_orientations.as_mut_ptr()) };
49        if hr.is_ok() {
50            Ok(())
51        } else {
52            Err(Error::from_hresult(hr))
53        }
54    }
55
56    pub fn get_engaged(&self) -> Result<DetectionResult, Error> {
57        if self.ptr.is_null() {
58            return Err(Error::from_hresult(E_POINTER));
59        }
60        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
61        let get_fn = vtbl.get_Engaged.ok_or(E_FAIL)?;
62        let mut detection_result: DetectionResult = unsafe { std::mem::zeroed() };
63        let hr = unsafe { get_fn(self.ptr, &mut detection_result) };
64        if hr.is_ok() {
65            Ok(detection_result)
66        } else {
67            Err(Error::from_hresult(hr))
68        }
69    }
70
71    pub fn get_expression_detection_results(
72        &self,
73        detection_results: &mut [DetectionResult],
74    ) -> Result<(), Error> {
75        if self.ptr.is_null() {
76            return Err(Error::from_hresult(E_POINTER));
77        }
78        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
79        let get_fn = vtbl.GetExpressionDetectionResults.ok_or(E_FAIL)?;
80        let capacity = detection_results.len() as UINT;
81        let hr = unsafe { get_fn(self.ptr, capacity, detection_results.as_mut_ptr()) };
82        if hr.is_ok() {
83            Ok(())
84        } else {
85            Err(Error::from_hresult(hr))
86        }
87    }
88
89    pub fn get_activity_detection_results(
90        &self,
91        detection_results: &mut [DetectionResult],
92    ) -> Result<(), Error> {
93        if self.ptr.is_null() {
94            return Err(Error::from_hresult(E_POINTER));
95        }
96        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
97        let get_fn = vtbl.GetActivityDetectionResults.ok_or(E_FAIL)?;
98        let capacity = detection_results.len() as UINT;
99        let hr = unsafe { get_fn(self.ptr, capacity, detection_results.as_mut_ptr()) };
100        if hr.is_ok() {
101            Ok(())
102        } else {
103            Err(Error::from_hresult(hr))
104        }
105    }
106
107    pub fn get_appearance_detection_results(
108        &self,
109        detection_results: &mut [DetectionResult],
110    ) -> Result<(), Error> {
111        if self.ptr.is_null() {
112            return Err(Error::from_hresult(E_POINTER));
113        }
114        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
115        let get_fn = vtbl.GetAppearanceDetectionResults.ok_or(E_FAIL)?;
116        let capacity = detection_results.len() as UINT;
117        let hr = unsafe { get_fn(self.ptr, capacity, detection_results.as_mut_ptr()) };
118        if hr.is_ok() {
119            Ok(())
120        } else {
121            Err(Error::from_hresult(hr))
122        }
123    }
124
125    pub fn get_hand_left_state(&self) -> Result<HandState, Error> {
126        if self.ptr.is_null() {
127            return Err(Error::from_hresult(E_POINTER));
128        }
129        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
130        let get_fn = vtbl.get_HandLeftState.ok_or(E_FAIL)?;
131        let mut hand_state: HandState = unsafe { std::mem::zeroed() };
132        let hr = unsafe { get_fn(self.ptr, &mut hand_state) };
133        if hr.is_ok() {
134            Ok(hand_state)
135        } else {
136            Err(Error::from_hresult(hr))
137        }
138    }
139
140    pub fn get_hand_left_confidence(&self) -> Result<TrackingConfidence, Error> {
141        if self.ptr.is_null() {
142            return Err(Error::from_hresult(E_POINTER));
143        }
144        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
145        let get_fn = vtbl.get_HandLeftConfidence.ok_or(E_FAIL)?;
146        let mut confidence: TrackingConfidence = unsafe { std::mem::zeroed() };
147        let hr = unsafe { get_fn(self.ptr, &mut confidence) };
148        if hr.is_ok() {
149            Ok(confidence)
150        } else {
151            Err(Error::from_hresult(hr))
152        }
153    }
154
155    pub fn get_hand_right_state(&self) -> Result<HandState, Error> {
156        if self.ptr.is_null() {
157            return Err(Error::from_hresult(E_POINTER));
158        }
159        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
160        let get_fn = vtbl.get_HandRightState.ok_or(E_FAIL)?;
161        let mut hand_state: HandState = unsafe { std::mem::zeroed() };
162        let hr = unsafe { get_fn(self.ptr, &mut hand_state) };
163        if hr.is_ok() {
164            Ok(hand_state)
165        } else {
166            Err(Error::from_hresult(hr))
167        }
168    }
169
170    pub fn get_hand_right_confidence(&self) -> Result<TrackingConfidence, Error> {
171        if self.ptr.is_null() {
172            return Err(Error::from_hresult(E_POINTER));
173        }
174        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
175        let get_fn = vtbl.get_HandRightConfidence.ok_or(E_FAIL)?;
176        let mut confidence: TrackingConfidence = unsafe { std::mem::zeroed() };
177        let hr = unsafe { get_fn(self.ptr, &mut confidence) };
178        if hr.is_ok() {
179            Ok(confidence)
180        } else {
181            Err(Error::from_hresult(hr))
182        }
183    }
184
185    pub fn get_clipped_edges(&self) -> Result<FrameEdges, Error> {
186        if self.ptr.is_null() {
187            return Err(Error::from_hresult(E_POINTER));
188        }
189        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
190        let get_fn = vtbl.get_ClippedEdges.ok_or(E_FAIL)?;
191        let mut clipped_edges: FrameEdges = unsafe { std::mem::zeroed() };
192        let hr = unsafe { get_fn(self.ptr, &mut clipped_edges) };
193        if hr.is_ok() {
194            Ok(clipped_edges)
195        } else {
196            Err(Error::from_hresult(hr))
197        }
198    }
199
200    pub fn get_tracking_id(&self) -> Result<u64, Error> {
201        if self.ptr.is_null() {
202            return Err(Error::from_hresult(E_POINTER));
203        }
204        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
205        let get_fn = vtbl.get_TrackingId.ok_or(E_FAIL)?;
206        let mut tracking_id: bindings::UINT64 = 0;
207        let hr = unsafe { get_fn(self.ptr, &mut tracking_id) };
208        if hr.is_ok() {
209            Ok(tracking_id)
210        } else {
211            Err(Error::from_hresult(hr))
212        }
213    }
214
215    pub fn get_is_tracked(&self) -> Result<bool, Error> {
216        if self.ptr.is_null() {
217            return Err(Error::from_hresult(E_POINTER));
218        }
219        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
220        let get_fn = vtbl.get_IsTracked.ok_or(E_FAIL)?;
221        let mut tracked: BOOLEAN = 0;
222        let hr = unsafe { get_fn(self.ptr, &mut tracked) };
223        if hr.is_ok() {
224            Ok(tracked != 0)
225        } else {
226            Err(Error::from_hresult(hr))
227        }
228    }
229
230    pub fn get_is_restricted(&self) -> Result<bool, Error> {
231        if self.ptr.is_null() {
232            return Err(Error::from_hresult(E_POINTER));
233        }
234        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
235        let get_fn = vtbl.get_IsRestricted.ok_or(E_FAIL)?;
236        let mut is_restricted: BOOLEAN = 0;
237        let hr = unsafe { get_fn(self.ptr, &mut is_restricted) };
238        if hr.is_ok() {
239            Ok(is_restricted != 0)
240        } else {
241            Err(Error::from_hresult(hr))
242        }
243    }
244
245    pub fn get_lean(&self) -> Result<bindings::PointF, Error> {
246        if self.ptr.is_null() {
247            return Err(Error::from_hresult(E_POINTER));
248        }
249        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
250        let get_fn = vtbl.get_Lean.ok_or(E_FAIL)?;
251        let mut amount: bindings::PointF = unsafe { std::mem::zeroed() };
252        let hr = unsafe { get_fn(self.ptr, &mut amount) };
253        if hr.is_ok() {
254            Ok(amount)
255        } else {
256            Err(Error::from_hresult(hr))
257        }
258    }
259
260    pub fn get_lean_tracking_state(&self) -> Result<bindings::TrackingState, Error> {
261        if self.ptr.is_null() {
262            return Err(Error::from_hresult(E_POINTER));
263        }
264        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
265        let get_fn = vtbl.get_LeanTrackingState.ok_or(E_FAIL)?;
266        let mut tracking_state: bindings::TrackingState = unsafe { std::mem::zeroed() };
267        let hr = unsafe { get_fn(self.ptr, &mut tracking_state) };
268        if hr.is_ok() {
269            Ok(tracking_state)
270        } else {
271            Err(Error::from_hresult(hr))
272        }
273    }
274}
275
276impl Drop for Body {
277    fn drop(&mut self) {
278        if !self.ptr.is_null() {
279            unsafe {
280                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
281                    if let Some(release_fn) = vtbl.Release {
282                        release_fn(self.ptr);
283                    }
284                }
285            }
286            self.ptr = ptr::null_mut();
287        }
288    }
289}
290
291pub struct BodyHandPair {
292    ptr: *mut IBodyHandPair,
293}
294
295impl BodyHandPair {
296    pub(crate) fn new(ptr: *mut IBodyHandPair) -> Self {
297        assert!(!ptr.is_null());
298        Self { ptr }
299    }
300
301    pub fn get_body_tracking_id(&self) -> Result<u64, Error> {
302        if self.ptr.is_null() {
303            return Err(Error::from_hresult(E_POINTER));
304        }
305        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
306        let get_fn = vtbl.get_BodyTrackingId.ok_or(E_FAIL)?;
307        let mut value: bindings::UINT64 = 0;
308        let hr = unsafe { get_fn(self.ptr, &mut value) };
309        if hr.is_ok() {
310            Ok(value)
311        } else {
312            Err(Error::from_hresult(hr))
313        }
314    }
315
316    pub fn put_body_tracking_id(&self, value: u64) -> Result<(), Error> {
317        if self.ptr.is_null() {
318            return Err(Error::from_hresult(E_POINTER));
319        }
320        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
321        let put_fn = vtbl.put_BodyTrackingId.ok_or(E_FAIL)?;
322        let hr = unsafe { put_fn(self.ptr, value) };
323        if hr.is_ok() {
324            Ok(())
325        } else {
326            Err(Error::from_hresult(hr))
327        }
328    }
329
330    pub fn get_hand_type(&self) -> Result<HandType, Error> {
331        if self.ptr.is_null() {
332            return Err(Error::from_hresult(E_POINTER));
333        }
334        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
335        let get_fn = vtbl.get_HandType.ok_or(E_FAIL)?;
336        let mut value: HandType = unsafe { std::mem::zeroed() };
337        let hr = unsafe { get_fn(self.ptr, &mut value) };
338        if hr.is_ok() {
339            Ok(value)
340        } else {
341            Err(Error::from_hresult(hr))
342        }
343    }
344
345    pub fn put_hand_type(&self, value: HandType) -> Result<(), Error> {
346        if self.ptr.is_null() {
347            return Err(Error::from_hresult(E_POINTER));
348        }
349        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
350        let put_fn = vtbl.put_HandType.ok_or(E_FAIL)?;
351        let hr = unsafe { put_fn(self.ptr, value) };
352        if hr.is_ok() {
353            Ok(())
354        } else {
355            Err(Error::from_hresult(hr))
356        }
357    }
358}
359
360impl Drop for BodyHandPair {
361    fn drop(&mut self) {
362        if !self.ptr.is_null() {
363            unsafe {
364                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
365                    if let Some(release_fn) = vtbl.Release {
366                        release_fn(self.ptr);
367                    }
368                }
369            }
370            self.ptr = ptr::null_mut();
371        }
372    }
373}
374
375pub struct BodyFrameSource {
376    ptr: *mut IBodyFrameSource,
377}
378impl BodyFrameSource {
379    pub(crate) fn new(ptr: *mut IBodyFrameSource) -> Self {
380        assert!(!ptr.is_null());
381        Self { ptr }
382    }
383
384    pub fn subscribe_frame_captured(
385        &self,
386        waitable_handle: &mut WAITABLE_HANDLE,
387    ) -> Result<(), Error> {
388        if self.ptr.is_null() {
389            return Err(Error::from_hresult(E_POINTER));
390        }
391        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
392        let sub_fn = vtbl.SubscribeFrameCaptured.ok_or(E_FAIL)?;
393        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
394        if hr.is_ok() {
395            Ok(())
396        } else {
397            Err(Error::from_hresult(hr))
398        }
399    }
400
401    pub fn unsubscribe_frame_captured(&self, handle: WAITABLE_HANDLE) -> Result<(), Error> {
402        if self.ptr.is_null() {
403            return Err(Error::from_hresult(E_POINTER));
404        }
405        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
406        let unsub_fn = vtbl.UnsubscribeFrameCaptured.ok_or(E_FAIL)?;
407        let hr = unsafe { unsub_fn(self.ptr, handle) };
408        if hr.is_ok() {
409            Ok(())
410        } else {
411            Err(Error::from_hresult(hr))
412        }
413    }
414
415    pub fn get_frame_captured_event_data(
416        &self,
417        handle: WAITABLE_HANDLE,
418    ) -> Result<FrameCapturedEventArgs, Error> {
419        if self.ptr.is_null() {
420            return Err(Error::from_hresult(E_POINTER));
421        }
422        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
423        let get_fn = vtbl.GetFrameCapturedEventData.ok_or(E_FAIL)?;
424        let mut event_data_ptr: *mut IFrameCapturedEventArgs = ptr::null_mut();
425        let hr = unsafe { get_fn(self.ptr, handle, &mut event_data_ptr) };
426        if hr.is_ok() {
427            if event_data_ptr.is_null() {
428                return Err(Error::from_hresult(E_FAIL));
429            }
430            Ok(FrameCapturedEventArgs::new(event_data_ptr))
431        } else {
432            Err(Error::from_hresult(hr))
433        }
434    }
435
436    pub fn get_is_active(&self) -> Result<bool, Error> {
437        if self.ptr.is_null() {
438            return Err(Error::from_hresult(E_POINTER));
439        }
440        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
441        let get_fn = vtbl.get_IsActive.ok_or(E_FAIL)?;
442        let mut is_active: BOOLEAN = 0;
443        let hr = unsafe { get_fn(self.ptr, &mut is_active) };
444        if hr.is_ok() {
445            Ok(is_active != 0)
446        } else {
447            Err(Error::from_hresult(hr))
448        }
449    }
450
451    pub fn get_body_count(&self) -> Result<i32, Error> {
452        if self.ptr.is_null() {
453            return Err(Error::from_hresult(E_POINTER));
454        }
455        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
456        let get_fn = vtbl.get_BodyCount.ok_or(E_FAIL)?;
457        let mut count: INT32 = 0;
458        let hr = unsafe { get_fn(self.ptr, &mut count) };
459        if hr.is_ok() {
460            Ok(count)
461        } else {
462            Err(Error::from_hresult(hr))
463        }
464    }
465
466    pub fn open_reader(&self) -> Result<BodyFrameReader, Error> {
467        if self.ptr.is_null() {
468            return Err(Error::from_hresult(E_POINTER));
469        }
470        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
471        let open_fn = vtbl.OpenReader.ok_or(E_FAIL)?;
472        let mut reader_ptr: *mut IBodyFrameReader = ptr::null_mut();
473        let hr = unsafe { open_fn(self.ptr, &mut reader_ptr) };
474        if hr.is_ok() {
475            if reader_ptr.is_null() {
476                return Err(Error::from_hresult(E_FAIL));
477            }
478            Ok(BodyFrameReader::new(reader_ptr))
479        } else {
480            Err(Error::from_hresult(hr))
481        }
482    }
483
484    pub fn get_kinect_sensor(&self) -> Result<KinectSensor, Error> {
485        if self.ptr.is_null() {
486            return Err(Error::from_hresult(E_POINTER));
487        }
488        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
489        let get_fn = vtbl.get_KinectSensor.ok_or(E_FAIL)?;
490        let mut sensor_ptr: *mut IKinectSensor = ptr::null_mut();
491        let hr = unsafe { get_fn(self.ptr, &mut sensor_ptr) };
492        if hr.is_ok() {
493            if sensor_ptr.is_null() {
494                return Err(Error::from_hresult(E_FAIL));
495            }
496            Ok(KinectSensor::new(sensor_ptr))
497        } else {
498            Err(Error::from_hresult(hr))
499        }
500    }
501
502    pub fn override_hand_tracking(&self, tracking_id: u64) -> Result<(), Error> {
503        if self.ptr.is_null() {
504            return Err(Error::from_hresult(E_POINTER));
505        }
506        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
507        let override_fn = vtbl.OverrideHandTracking.ok_or(E_FAIL)?;
508        let hr = unsafe { override_fn(self.ptr, tracking_id) };
509        if hr.is_ok() {
510            Ok(())
511        } else {
512            Err(Error::from_hresult(hr))
513        }
514    }
515
516    pub fn override_and_replace_hand_tracking(
517        &self,
518        old_tracking_id: u64,
519        new_tracking_id: u64,
520    ) -> Result<(), Error> {
521        if self.ptr.is_null() {
522            return Err(Error::from_hresult(E_POINTER));
523        }
524        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
525        let override_fn = vtbl.OverrideAndReplaceHandTracking.ok_or(E_FAIL)?;
526        let hr = unsafe { override_fn(self.ptr, old_tracking_id, new_tracking_id) };
527        if hr.is_ok() {
528            Ok(())
529        } else {
530            Err(Error::from_hresult(hr))
531        }
532    }
533}
534impl Drop for BodyFrameSource {
535    fn drop(&mut self) {
536        if !self.ptr.is_null() {
537            unsafe {
538                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
539                    if let Some(release_fn) = vtbl.Release {
540                        release_fn(self.ptr);
541                    }
542                }
543            }
544            self.ptr = ptr::null_mut();
545        }
546    }
547}
548
549pub struct BodyFrameReference {
550    ptr: *mut IBodyFrameReference,
551}
552
553impl BodyFrameReference {
554    pub(crate) fn new(ptr: *mut IBodyFrameReference) -> Self {
555        assert!(!ptr.is_null());
556        Self { ptr }
557    }
558
559    pub fn acquire_frame(&self) -> Result<BodyFrame, Error> {
560        if self.ptr.is_null() {
561            return Err(Error::from_hresult(E_POINTER));
562        }
563        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
564        let acquire_fn = vtbl.AcquireFrame.ok_or(E_FAIL)?;
565        let mut frame_ptr: *mut IBodyFrame = ptr::null_mut();
566        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
567        if hr.is_ok() {
568            if frame_ptr.is_null() {
569                return Err(Error::from_hresult(E_FAIL));
570            }
571            Ok(BodyFrame::new(frame_ptr))
572        } else {
573            Err(Error::from_hresult(hr))
574        }
575    }
576
577    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
578        if self.ptr.is_null() {
579            return Err(Error::from_hresult(E_POINTER));
580        }
581        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
582        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
583        let mut time: TIMESPAN = 0;
584        let hr = unsafe { get_fn(self.ptr, &mut time) };
585        if hr.is_ok() {
586            Ok(time)
587        } else {
588            Err(Error::from_hresult(hr))
589        }
590    }
591}
592impl Drop for BodyFrameReference {
593    fn drop(&mut self) {
594        if !self.ptr.is_null() {
595            unsafe {
596                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
597                    if let Some(release_fn) = vtbl.Release {
598                        release_fn(self.ptr);
599                    }
600                }
601            }
602            self.ptr = ptr::null_mut();
603        }
604    }
605}
606
607pub struct BodyFrameReader {
608    ptr: *mut IBodyFrameReader,
609}
610
611impl BodyFrameReader {
612    pub(crate) fn new(ptr: *mut IBodyFrameReader) -> Self {
613        assert!(!ptr.is_null());
614        Self { ptr }
615    }
616
617    pub fn acquire_latest_frame(&self) -> Result<BodyFrame, Error> {
618        if self.ptr.is_null() {
619            return Err(Error::from_hresult(E_POINTER));
620        }
621        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
622        let acquire_fn = vtbl.AcquireLatestFrame.ok_or(E_FAIL)?;
623        let mut frame_ptr: *mut IBodyFrame = ptr::null_mut();
624        let hr = unsafe { acquire_fn(self.ptr, &mut frame_ptr) };
625        if hr.is_ok() {
626            if frame_ptr.is_null() {
627                return Err(Error::from_hresult(hr));
628            }
629            Ok(BodyFrame::new(frame_ptr))
630        } else {
631            Err(Error::from_hresult(hr))
632        }
633    }
634
635    pub fn subscribe_frame_arrived(
636        &self,
637        waitable_handle: &mut WAITABLE_HANDLE,
638    ) -> Result<(), 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 sub_fn = vtbl.SubscribeFrameArrived.ok_or(E_FAIL)?;
644        let hr = unsafe { sub_fn(self.ptr, waitable_handle) };
645        if hr.is_ok() {
646            Ok(())
647        } else {
648            Err(Error::from_hresult(hr))
649        }
650    }
651
652    pub fn unsubscribe_frame_arrived(&self, handle: WAITABLE_HANDLE) -> Result<(), Error> {
653        if self.ptr.is_null() {
654            return Err(Error::from_hresult(E_POINTER));
655        }
656        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
657        let unsub_fn = vtbl.UnsubscribeFrameArrived.ok_or(E_FAIL)?;
658        let hr = unsafe { unsub_fn(self.ptr, handle) };
659        if hr.is_ok() {
660            Ok(())
661        } else {
662            Err(Error::from_hresult(hr))
663        }
664    }
665
666    pub fn get_frame_arrived_event_data(
667        &self,
668        handle: WAITABLE_HANDLE,
669    ) -> Result<BodyFrameArrivedEventArgs, Error> {
670        if self.ptr.is_null() {
671            return Err(Error::from_hresult(E_POINTER));
672        }
673        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
674        let get_fn = vtbl.GetFrameArrivedEventData.ok_or(E_FAIL)?;
675        let mut event_data_ptr: *mut IBodyFrameArrivedEventArgs = ptr::null_mut();
676        let hr = unsafe { get_fn(self.ptr, handle, &mut event_data_ptr) };
677        if hr.is_ok() {
678            if event_data_ptr.is_null() {
679                return Err(Error::from_hresult(E_FAIL));
680            }
681            Ok(BodyFrameArrivedEventArgs::new(event_data_ptr))
682        } else {
683            Err(Error::from_hresult(hr))
684        }
685    }
686
687    pub fn get_is_paused(&self) -> Result<bool, Error> {
688        if self.ptr.is_null() {
689            return Err(Error::from_hresult(E_POINTER));
690        }
691        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
692        let get_fn = vtbl.get_IsPaused.ok_or(E_FAIL)?;
693        let mut is_paused: BOOLEAN = 0;
694        let hr = unsafe { get_fn(self.ptr, &mut is_paused) };
695        if hr.is_ok() {
696            Ok(is_paused != 0)
697        } else {
698            Err(Error::from_hresult(hr))
699        }
700    }
701
702    pub fn put_is_paused(&self, is_paused: bool) -> Result<(), Error> {
703        if self.ptr.is_null() {
704            return Err(Error::from_hresult(E_POINTER));
705        }
706        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
707        let put_fn = vtbl.put_IsPaused.ok_or(E_FAIL)?;
708        let hr = unsafe { put_fn(self.ptr, is_paused as BOOLEAN) };
709        if hr.is_ok() {
710            Ok(())
711        } else {
712            Err(Error::from_hresult(hr))
713        }
714    }
715
716    pub fn get_body_frame_source(&self) -> Result<BodyFrameSource, Error> {
717        if self.ptr.is_null() {
718            return Err(Error::from_hresult(E_POINTER));
719        }
720        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
721        let get_fn = vtbl.get_BodyFrameSource.ok_or(E_FAIL)?;
722        let mut source_ptr: *mut IBodyFrameSource = ptr::null_mut();
723        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
724        if hr.is_ok() {
725            if source_ptr.is_null() {
726                return Err(Error::from_hresult(E_FAIL));
727            }
728            Ok(BodyFrameSource::new(source_ptr))
729        } else {
730            Err(Error::from_hresult(hr))
731        }
732    }
733}
734impl Drop for BodyFrameReader {
735    fn drop(&mut self) {
736        if !self.ptr.is_null() {
737            unsafe {
738                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
739                    if let Some(release_fn) = vtbl.Release {
740                        release_fn(self.ptr);
741                    }
742                }
743            }
744            self.ptr = ptr::null_mut();
745        }
746    }
747}
748
749pub struct BodyFrame {
750    ptr: *mut IBodyFrame,
751}
752
753impl BodyFrame {
754    pub(crate) fn new(ptr: *mut IBodyFrame) -> Self {
755        assert!(!ptr.is_null());
756        Self { ptr }
757    }
758
759    pub fn get_floor_clip_plane(&self) -> Result<bindings::Vector4, Error> {
760        if self.ptr.is_null() {
761            return Err(Error::from_hresult(E_POINTER));
762        }
763        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
764        let get_fn = vtbl.get_FloorClipPlane.ok_or(E_FAIL)?;
765        let mut floor_clip_plane: bindings::Vector4 = unsafe { std::mem::zeroed() };
766        let hr = unsafe { get_fn(self.ptr, &mut floor_clip_plane) };
767        if hr.is_ok() {
768            Ok(floor_clip_plane)
769        } else {
770            Err(Error::from_hresult(hr))
771        }
772    }
773    pub fn get_and_refresh_body_data(&self) -> Result<Vec<Body>, Error> {
774        if self.ptr.is_null() {
775            return Err(Error::from_hresult(E_POINTER));
776        }
777
778        // Get the body frame source to determine body count
779        let body_source = self.get_body_frame_source()?;
780        let body_count = body_source.get_body_count()? as usize;
781
782        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
783        let get_fn = vtbl.GetAndRefreshBodyData.ok_or(E_FAIL)?;
784
785        // Create null pointers for the API to fill
786        let mut raw_ptrs: Vec<*mut IBody> = vec![ptr::null_mut(); body_count];
787        let hr = unsafe { get_fn(self.ptr, body_count as UINT, raw_ptrs.as_mut_ptr()) };
788
789        if hr.is_ok() {
790            // Convert non-null pointers to Body objects
791            let bodies: Vec<Body> = raw_ptrs
792                .into_iter()
793                .filter(|&ptr| !ptr.is_null())
794                .map(Body::new)
795                .collect();
796            Ok(bodies)
797        } else {
798            Err(Error::from_hresult(hr))
799        }
800    }
801
802    pub fn get_body_frame_source(&self) -> Result<BodyFrameSource, Error> {
803        if self.ptr.is_null() {
804            return Err(Error::from_hresult(E_POINTER));
805        }
806        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
807        let get_fn = vtbl.get_BodyFrameSource.ok_or(E_FAIL)?;
808        let mut source_ptr: *mut IBodyFrameSource = ptr::null_mut();
809        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
810        if hr.is_ok() {
811            if source_ptr.is_null() {
812                return Err(Error::from_hresult(E_FAIL));
813            }
814            Ok(BodyFrameSource::new(source_ptr))
815        } else {
816            Err(Error::from_hresult(hr))
817        }
818    }
819
820    pub fn get_relative_time(&self) -> Result<TIMESPAN, Error> {
821        if self.ptr.is_null() {
822            return Err(Error::from_hresult(E_POINTER));
823        }
824        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
825        let get_fn = vtbl.get_RelativeTime.ok_or(E_FAIL)?;
826        let mut time: TIMESPAN = 0;
827        let hr = unsafe { get_fn(self.ptr, &mut time) };
828        if hr.is_ok() {
829            Ok(time)
830        } else {
831            Err(Error::from_hresult(hr))
832        }
833    }
834}
835impl Drop for BodyFrame {
836    fn drop(&mut self) {
837        if !self.ptr.is_null() {
838            unsafe {
839                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
840                    if let Some(release_fn) = vtbl.Release {
841                        release_fn(self.ptr);
842                    }
843                }
844            }
845            self.ptr = ptr::null_mut();
846        }
847    }
848}
849
850pub struct BodyFrameArrivedEventArgs {
851    ptr: *mut IBodyFrameArrivedEventArgs,
852}
853
854impl BodyFrameArrivedEventArgs {
855    pub(crate) fn new(ptr: *mut IBodyFrameArrivedEventArgs) -> Self {
856        assert!(!ptr.is_null());
857        Self { ptr }
858    }
859
860    pub fn get_frame_reference(&self) -> Result<BodyFrameReference, Error> {
861        if self.ptr.is_null() {
862            return Err(Error::from_hresult(E_POINTER));
863        }
864        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
865        let get_fn = vtbl.get_FrameReference.ok_or(E_FAIL)?;
866        let mut frame_ref_ptr: *mut IBodyFrameReference = ptr::null_mut();
867        let hr = unsafe { get_fn(self.ptr, &mut frame_ref_ptr) };
868        if hr.is_ok() {
869            if frame_ref_ptr.is_null() {
870                return Err(Error::from_hresult(E_FAIL));
871            }
872            Ok(BodyFrameReference::new(frame_ref_ptr))
873        } else {
874            Err(Error::from_hresult(hr))
875        }
876    }
877}
878
879impl Drop for BodyFrameArrivedEventArgs {
880    fn drop(&mut self) {
881        if !self.ptr.is_null() {
882            unsafe {
883                if let Some(vtbl) = (*self.ptr).lpVtbl.as_ref() {
884                    if let Some(release_fn) = vtbl.Release {
885                        release_fn(self.ptr);
886                    }
887                }
888            }
889            self.ptr = ptr::null_mut();
890        }
891    }
892}
893
894pub fn create_body_hand_pair(
895    body_tracking_id: u64,
896    hand_type: HandType,
897) -> Result<BodyHandPair, Error> {
898    let mut pair_ptr: *mut IBodyHandPair = ptr::null_mut();
899    let hr = unsafe { CreateBodyHandPair(body_tracking_id, hand_type, &mut pair_ptr) };
900    if hr.is_ok() {
901        if pair_ptr.is_null() {
902            Err(Error::from_hresult(E_POINTER))
903        } else {
904            Ok(BodyHandPair::new(pair_ptr))
905        }
906    } else {
907        Err(Error::from_hresult(hr))
908    }
909}