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 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; 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}