1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use uvc_sys::*;
use crate::device::DeviceHandle;
use crate::error::{Error, Result};
use crate::frame::Frame;
use std::os::raw::c_void;
unsafe impl<'a> Send for StreamHandle<'a> {}
unsafe impl<'a> Sync for StreamHandle<'a> {}
#[derive(Debug)]
pub struct StreamHandle<'a> {
pub(crate) handle: uvc_stream_ctrl_t,
pub(crate) devh: &'a DeviceHandle<'a>,
}
struct Vtable<U> {
func: Box<dyn Fn(&Frame, &mut U)>,
data: U,
}
unsafe impl<'a, U: Send + Sync> Send for ActiveStream<'a, U> {}
unsafe impl<'a, U: Send + Sync> Sync for ActiveStream<'a, U> {}
#[derive(Debug)]
pub struct ActiveStream<'a, U: Send + Sync> {
devh: &'a crate::DeviceHandle<'a>,
#[allow(unused)]
vtable: *mut Vtable<U>,
}
impl<'a, U: Send + Sync> ActiveStream<'a, U> {
pub fn stop(self) {
}
}
impl<'a, U: Send + Sync> Drop for ActiveStream<'a, U> {
fn drop(&mut self) {
unsafe {
uvc_stop_streaming(self.devh.devh.as_ptr());
let _vtable = Box::from_raw(self.vtable);
}
}
}
unsafe extern "C" fn trampoline<F, U>(frame: *mut uvc_frame, userdata: *mut c_void)
where
F: 'static + Send + Sync + Fn(&Frame, &mut U),
U: 'static + Send + Sync,
{
let panic = std::panic::catch_unwind(|| {
if frame.is_null() {
panic!("Frame is null");
}
let frame = std::mem::ManuallyDrop::new(Frame::from_raw(frame));
if userdata.is_null() {
panic!("Userdata is null");
}
let vtable = userdata as *mut Vtable<U>;
let func = &(*vtable).func;
let data = &mut (*vtable).data;
func(&frame, data);
});
if panic.is_err() {
eprintln!("User defined function panicked");
std::process::abort();
}
}
impl<'a> StreamHandle<'a> {
pub fn start_stream<F, U>(&'a mut self, cb: F, user_data: U) -> Result<ActiveStream<'a, U>>
where
F: 'static + Send + Sync + Fn(&Frame, &mut U),
U: 'static + Send + Sync,
{
let tuple = Box::new(Vtable::<U> {
func: Box::new(cb),
data: user_data,
});
let tuple = Box::into_raw(tuple);
unsafe {
let err = uvc_start_streaming(
self.devh.devh.as_ptr(),
&mut self.handle,
Some(trampoline::<F, U>),
tuple as *mut c_void,
0,
)
.into();
if err == Error::Success {
Ok(ActiveStream {
devh: self.devh,
vtable: tuple,
})
} else {
Err(err)
}
}
}
}