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