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