kinect_v2_sys/
kinect.rs

1use crate::audio::AudioSource;
2use crate::bindings::{
3    self, BOOLEAN, FrameSourceTypes, GetDefaultKinectSensor, IIsAvailableChangedEventArgs,
4    IKinectSensor, UINT, ULONG, WAITABLE_HANDLE, WCHAR,
5};
6use crate::body::BodyFrameSource;
7use crate::body_index::BodyIndexFrameSource;
8use crate::color::ColorFrameSource;
9use crate::coordinate::CoordinateMapper;
10use crate::depth::DepthFrameSource;
11use crate::infrared::InfraredFrameSource;
12use crate::long_exposure_infrared::LongExposureInfraredFrameSource;
13use crate::multi_source_frame::MultiSourceFrameReader;
14use std::os::windows::ffi::OsStringExt;
15use std::{ffi::OsString, ptr};
16use windows::Win32::Foundation::{E_FAIL, E_POINTER};
17use windows::core::Error;
18
19pub struct IsAvailableChangedEventArgs {
20    pub(crate) ptr: *mut IIsAvailableChangedEventArgs,
21}
22impl IsAvailableChangedEventArgs {
23    pub(crate) fn new(ptr: *mut IIsAvailableChangedEventArgs) -> Self {
24        assert!(!ptr.is_null());
25        Self { ptr }
26    }
27    // Add methods for IIsAvailableChangedEventArgs here, e.g., get_IsAvailable
28    pub fn get_is_available(&self) -> Result<bool, 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_IsAvailable.ok_or(E_FAIL)?;
34        let mut available: BOOLEAN = 0;
35        let hr = unsafe { get_fn(self.ptr, &mut available) };
36        if hr.is_ok() {
37            Ok(available != 0)
38        } else {
39            Err(Error::from_hresult(hr))
40        }
41    }
42}
43impl Drop for IsAvailableChangedEventArgs {
44    fn drop(&mut self) {
45        if !self.ptr.is_null() {
46            unsafe {
47                ((*(*self.ptr).lpVtbl).Release.unwrap())(self.ptr);
48            }
49            self.ptr = ptr::null_mut();
50        }
51    }
52}
53
54pub struct KinectSensor {
55    ptr: *mut IKinectSensor,
56}
57
58impl KinectSensor {
59    pub(crate) fn new(ptr: *mut IKinectSensor) -> Self {
60        assert!(!ptr.is_null(), "KinectSensor pointer cannot be null");
61        Self { ptr }
62    }
63
64    pub fn subscribe_is_available_changed(
65        &self,
66        waitable_handle: &mut WAITABLE_HANDLE,
67    ) -> Result<(), Error> {
68        if self.ptr.is_null() {
69            return Err(Error::from_hresult(E_POINTER));
70        }
71        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
72        let subscribe_fn = vtbl.SubscribeIsAvailableChanged.ok_or(E_FAIL)?;
73        let hr = unsafe { subscribe_fn(self.ptr, waitable_handle) };
74        if hr.is_ok() {
75            Ok(())
76        } else {
77            Err(Error::from_hresult(hr))
78        }
79    }
80
81    pub fn unsubscribe_is_available_changed(
82        &self,
83        waitable_handle: WAITABLE_HANDLE,
84    ) -> Result<(), Error> {
85        if self.ptr.is_null() {
86            return Err(Error::from_hresult(E_POINTER));
87        }
88        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
89        let unsubscribe_fn = vtbl.UnsubscribeIsAvailableChanged.ok_or(E_FAIL)?;
90        let hr = unsafe { unsubscribe_fn(self.ptr, waitable_handle) };
91        if hr.is_ok() {
92            Ok(())
93        } else {
94            Err(Error::from_hresult(hr))
95        }
96    }
97
98    pub fn get_is_available_changed_event_data(
99        &self,
100        waitable_handle: WAITABLE_HANDLE,
101    ) -> Result<IsAvailableChangedEventArgs, Error> {
102        if self.ptr.is_null() {
103            return Err(Error::from_hresult(E_POINTER));
104        }
105        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
106        let get_event_data_fn = vtbl.GetIsAvailableChangedEventData.ok_or(E_FAIL)?;
107        let mut event_data_ptr: *mut bindings::IIsAvailableChangedEventArgs = ptr::null_mut();
108        let hr = unsafe { get_event_data_fn(self.ptr, waitable_handle, &mut event_data_ptr) };
109        if hr.is_ok() {
110            Ok(IsAvailableChangedEventArgs::new(event_data_ptr))
111        } else {
112            Err(Error::from_hresult(hr))
113        }
114    }
115
116    pub fn open(&self) -> Result<(), Error> {
117        if self.ptr.is_null() {
118            return Err(Error::from_hresult(E_POINTER));
119        }
120        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
121        let open_fn = vtbl.Open.ok_or(E_FAIL)?;
122        let hr = unsafe { open_fn(self.ptr) };
123        if hr.is_ok() {
124            Ok(())
125        } else {
126            Err(Error::from_hresult(hr))
127        }
128    }
129
130    pub fn close(&self) -> Result<(), 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 close_fn = vtbl.Close.ok_or(E_FAIL)?;
136        let hr = unsafe { close_fn(self.ptr) };
137        if hr.is_ok() {
138            Ok(())
139        } else {
140            Err(Error::from_hresult(hr))
141        }
142    }
143
144    pub fn is_open(&self) -> Result<bool, Error> {
145        if self.ptr.is_null() {
146            return Err(Error::from_hresult(E_POINTER));
147        }
148        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
149        let get_is_open_fn = vtbl.get_IsOpen.ok_or(E_FAIL)?;
150        let mut is_open_val: BOOLEAN = 0;
151        let hr = unsafe { get_is_open_fn(self.ptr, &mut is_open_val) };
152        if hr.is_ok() {
153            Ok(is_open_val != 0)
154        } else {
155            Err(Error::from_hresult(hr))
156        }
157    }
158
159    pub fn is_available(&self) -> Result<bool, Error> {
160        if self.ptr.is_null() {
161            return Err(Error::from_hresult(E_POINTER));
162        }
163
164        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
165        let get_is_available_fn = vtbl.get_IsAvailable.ok_or(E_FAIL)?;
166        let mut is_available: BOOLEAN = 0;
167        let hr = unsafe { get_is_available_fn(self.ptr, &mut is_available) };
168        if hr.is_ok() {
169            Ok(is_available != 0)
170        } else {
171            Err(Error::from_hresult(hr))
172        }
173    }
174
175    pub fn 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 frame_source_ptr: *mut bindings::IColorFrameSource = ptr::null_mut();
182        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
183        if hr.is_ok() {
184            Ok(ColorFrameSource::new(frame_source_ptr))
185        } else {
186            Err(Error::from_hresult(hr))
187        }
188    }
189
190    pub fn depth_frame_source(&self) -> Result<DepthFrameSource, Error> {
191        if self.ptr.is_null() {
192            return Err(Error::from_hresult(E_POINTER));
193        }
194        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
195        let get_fn = vtbl.get_DepthFrameSource.ok_or(E_FAIL)?;
196        let mut frame_source_ptr: *mut bindings::IDepthFrameSource = ptr::null_mut();
197        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
198        if hr.is_ok() {
199            Ok(DepthFrameSource::new(frame_source_ptr))
200        } else {
201            Err(Error::from_hresult(hr))
202        }
203    }
204
205    pub fn body_frame_source(&self) -> Result<BodyFrameSource, Error> {
206        if self.ptr.is_null() {
207            return Err(Error::from_hresult(E_POINTER));
208        }
209        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
210        let get_fn = vtbl.get_BodyFrameSource.ok_or(E_FAIL)?;
211        let mut frame_source_ptr: *mut bindings::IBodyFrameSource = ptr::null_mut();
212        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
213        if hr.is_ok() {
214            Ok(BodyFrameSource::new(frame_source_ptr))
215        } else {
216            Err(Error::from_hresult(hr))
217        }
218    }
219
220    pub fn body_index_frame_source(&self) -> Result<BodyIndexFrameSource, 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
226            .get_BodyIndexFrameSource
227            .ok_or(Error::from_hresult(E_FAIL))?;
228        let mut frame_source_ptr: *mut bindings::IBodyIndexFrameSource = ptr::null_mut();
229        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
230        if hr.is_ok() {
231            Ok(BodyIndexFrameSource::new(frame_source_ptr))
232        } else {
233            Err(Error::from_hresult(hr))
234        }
235    }
236
237    pub fn infrared_frame_source(&self) -> Result<InfraredFrameSource, Error> {
238        if self.ptr.is_null() {
239            return Err(Error::from_hresult(E_POINTER));
240        }
241        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
242        let get_fn = vtbl
243            .get_InfraredFrameSource
244            .ok_or(Error::from_hresult(E_FAIL))?;
245        let mut frame_source_ptr: *mut bindings::IInfraredFrameSource = ptr::null_mut();
246        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
247        if hr.is_ok() {
248            Ok(InfraredFrameSource::new(frame_source_ptr))
249        } else {
250            Err(Error::from_hresult(hr))
251        }
252    }
253
254    pub fn long_exposure_infrared_frame_source(
255        &self,
256    ) -> Result<LongExposureInfraredFrameSource, Error> {
257        if self.ptr.is_null() {
258            return Err(Error::from_hresult(E_POINTER));
259        }
260        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
261        let get_fn = vtbl.get_LongExposureInfraredFrameSource.ok_or(E_FAIL)?;
262        let mut frame_source_ptr: *mut bindings::ILongExposureInfraredFrameSource = ptr::null_mut();
263        let hr = unsafe { get_fn(self.ptr, &mut frame_source_ptr) };
264        if hr.is_ok() {
265            Ok(LongExposureInfraredFrameSource::new(frame_source_ptr))
266        } else {
267            Err(Error::from_hresult(hr))
268        }
269    }
270
271    pub fn audio_source(&self) -> Result<AudioSource, Error> {
272        if self.ptr.is_null() {
273            return Err(Error::from_hresult(E_POINTER));
274        }
275        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
276        let get_fn = vtbl.get_AudioSource.ok_or(E_FAIL)?;
277        let mut source_ptr: *mut bindings::IAudioSource = ptr::null_mut();
278        let hr = unsafe { get_fn(self.ptr, &mut source_ptr) };
279        if hr.is_ok() {
280            Ok(AudioSource::new(source_ptr))
281        } else {
282            Err(Error::from_hresult(hr))
283        }
284    }
285
286    pub fn open_multi_source_frame_reader(
287        &self,
288        enabled_frame_source_types: FrameSourceTypes,
289    ) -> Result<MultiSourceFrameReader, Error> {
290        if self.ptr.is_null() {
291            return Err(Error::from_hresult(E_POINTER));
292        }
293        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
294        let open_fn = vtbl.OpenMultiSourceFrameReader.ok_or(E_FAIL)?;
295        let mut reader_ptr: *mut bindings::IMultiSourceFrameReader = ptr::null_mut();
296        let hr = unsafe { open_fn(self.ptr, enabled_frame_source_types, &mut reader_ptr) };
297        if hr.is_ok() {
298            Ok(MultiSourceFrameReader::new(reader_ptr))
299        } else {
300            Err(Error::from_hresult(hr))
301        }
302    }
303
304    pub fn coordinate_mapper(&self) -> Result<CoordinateMapper, Error> {
305        if self.ptr.is_null() {
306            return Err(Error::from_hresult(E_POINTER));
307        }
308        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
309        let get_fn = vtbl.get_CoordinateMapper.ok_or(E_FAIL)?;
310        let mut mapper_ptr: *mut bindings::ICoordinateMapper = ptr::null_mut();
311        let hr = unsafe { get_fn(self.ptr, &mut mapper_ptr) };
312        if hr.is_ok() {
313            Ok(CoordinateMapper::new(mapper_ptr))
314        } else {
315            Err(Error::from_hresult(hr))
316        }
317    }
318
319    pub fn unique_kinect_id(&self) -> Result<String, Error> {
320        if self.ptr.is_null() {
321            return Err(Error::from_hresult(E_POINTER));
322        }
323        const BUFFER_SIZE: usize = 256; // Recommended buffer size for UniqueKinectId
324        let mut buffer: [WCHAR; BUFFER_SIZE] = [0; BUFFER_SIZE];
325
326        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
327        let get_id_fn = vtbl.get_UniqueKinectId.ok_or(E_FAIL)?;
328        let hr = unsafe { get_id_fn(self.ptr, BUFFER_SIZE as UINT, buffer.as_mut_ptr()) };
329        if hr.is_ok() {
330            let len = buffer.iter().position(|&c| c == 0).unwrap_or(BUFFER_SIZE);
331            let id_slice = &buffer[..len];
332            Ok(OsString::from_wide(id_slice).to_string_lossy().into_owned())
333        } else {
334            Err(Error::from_hresult(hr))
335        }
336    }
337
338    pub fn kinect_capabilities(&self) -> Result<ULONG, Error> {
339        if self.ptr.is_null() {
340            return Err(Error::from_hresult(E_POINTER));
341        }
342        let vtbl = unsafe { (*self.ptr).lpVtbl.as_ref() }.ok_or(E_POINTER)?;
343        let get_fn = vtbl.get_KinectCapabilities.ok_or(E_FAIL)?;
344        let mut capabilities_val: ULONG = 0;
345        let hr = unsafe { get_fn(self.ptr, &mut capabilities_val) };
346        if hr.is_ok() {
347            Ok(capabilities_val)
348        } else {
349            Err(Error::from_hresult(hr))
350        }
351    }
352}
353
354impl Drop for KinectSensor {
355    fn drop(&mut self) {
356        if !self.ptr.is_null() {
357            unsafe {
358                let vtbl = (*self.ptr)
359                    .lpVtbl
360                    .as_ref()
361                    .expect("KinectSensor VTable pointer is null in Drop");
362                if let Some(release_fn) = vtbl.Release {
363                    release_fn(self.ptr);
364                } else {
365                    log::warn!("KinectSensor Release function pointer is null in Drop");
366                }
367            }
368            self.ptr = ptr::null_mut();
369        }
370    }
371}
372
373pub fn get_default_kinect_sensor() -> Result<KinectSensor, Error> {
374    let mut kinect_sensor_ptr: *mut IKinectSensor = ptr::null_mut();
375    let hr = unsafe { GetDefaultKinectSensor(&mut kinect_sensor_ptr) };
376    if hr.is_ok() {
377        if kinect_sensor_ptr.is_null() {
378            Err(Error::from_hresult(E_POINTER))
379        } else {
380            Ok(KinectSensor::new(kinect_sensor_ptr))
381        }
382    } else {
383        Err(Error::from_hresult(hr))
384    }
385}