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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::connection::Connection;
use std::ffi::CStr;
use std::sync::atomic::{AtomicPtr, Ordering};
pub enum StreamVideoType {
Camera,
Screen,
Custom,
__Unknown,
}
impl From<ffi::otc_stream_video_type> for StreamVideoType {
fn from(type_: ffi::otc_stream_video_type) -> StreamVideoType {
match type_ {
ffi::otc_stream_video_type_OTC_STREAM_VIDEO_TYPE_CAMERA => StreamVideoType::Camera,
ffi::otc_stream_video_type_OTC_STREAM_VIDEO_TYPE_SCREEN => StreamVideoType::Screen,
ffi::otc_stream_video_type_OTC_STREAM_VIDEO_TYPE_CUSTOM => StreamVideoType::Custom,
_ => StreamVideoType::__Unknown,
}
}
}
pub struct Stream {
ptr: AtomicPtr<*const ffi::otc_stream>,
}
impl Stream {
pub fn inner(&self) -> *const ffi::otc_stream {
self.ptr.load(Ordering::Relaxed) as *const _
}
string_getter!(
=> (id, otc_stream_get_id)
);
string_getter!(
=> (name, otc_stream_get_name)
);
pub fn has_video(&self) -> bool {
unsafe { ffi::otc_stream_has_video(self.ptr.load(Ordering::Relaxed) as *const _) != 0 }
}
pub fn has_video_track(&self) -> bool {
unsafe {
ffi::otc_stream_has_video_track(self.ptr.load(Ordering::Relaxed) as *const _) != 0
}
}
pub fn has_audio(&self) -> bool {
unsafe { ffi::otc_stream_has_audio(self.ptr.load(Ordering::Relaxed) as *const _) != 0 }
}
pub fn has_audio_track(&self) -> bool {
unsafe {
ffi::otc_stream_has_audio_track(self.ptr.load(Ordering::Relaxed) as *const _) != 0
}
}
pub fn get_video_width(&self) -> i32 {
unsafe { ffi::otc_stream_get_video_width(self.ptr.load(Ordering::Relaxed) as *const _) }
}
pub fn get_video_height(&self) -> i32 {
unsafe { ffi::otc_stream_get_video_height(self.ptr.load(Ordering::Relaxed) as *const _) }
}
pub fn get_creation_time(&self) -> i64 {
unsafe { ffi::otc_stream_get_creation_time(self.ptr.load(Ordering::Relaxed) as *const _) }
}
pub fn get_video_type(&self) -> StreamVideoType {
unsafe { ffi::otc_stream_get_video_type(self.ptr.load(Ordering::Relaxed) as *const _) }
.into()
}
pub fn get_connection(&self) -> Connection {
unsafe { ffi::otc_stream_get_connection(self.ptr.load(Ordering::Relaxed) as *const _) }
.into()
}
}
impl Clone for Stream {
fn clone(&self) -> Self {
(self.ptr.load(Ordering::Relaxed) as *const ffi::otc_stream).into()
}
}
impl Drop for Stream {
fn drop(&mut self) {
let ptr = self.ptr.load(Ordering::Relaxed);
if ptr.is_null() {
return;
}
self.ptr.store(std::ptr::null_mut(), Ordering::Relaxed);
unsafe {
ffi::otc_stream_delete(ptr as *mut _);
}
}
}
impl From<*const ffi::otc_stream> for Stream {
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn from(ptr: *const ffi::otc_stream) -> Stream {
let ptr = unsafe { ffi::otc_stream_copy(ptr) };
Stream {
ptr: AtomicPtr::new(ptr as *mut _),
}
}
}