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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
use ffi;
use std::str;
use util::opt_bytes;
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
pub enum DeviceState {
Disabled,
Unplugged,
Enabled,
}
bitflags! {
pub struct DeviceFormat: ffi::cubeb_device_fmt {
const S16LE = ffi::CUBEB_DEVICE_FMT_S16LE;
const S16BE = ffi::CUBEB_DEVICE_FMT_S16BE;
const F32LE = ffi::CUBEB_DEVICE_FMT_F32LE;
const F32BE = ffi::CUBEB_DEVICE_FMT_F32BE;
}
}
bitflags! {
pub struct DevicePref: ffi::cubeb_device_pref {
const NONE = ffi::CUBEB_DEVICE_PREF_NONE;
const MULTIMEDIA = ffi::CUBEB_DEVICE_PREF_MULTIMEDIA;
const VOICE = ffi::CUBEB_DEVICE_PREF_VOICE;
const NOTIFICATION = ffi::CUBEB_DEVICE_PREF_NOTIFICATION;
const ALL = ffi::CUBEB_DEVICE_PREF_ALL;
}
}
bitflags! {
pub struct DeviceType: ffi::cubeb_device_type {
const UNKNOWN = ffi::CUBEB_DEVICE_TYPE_UNKNOWN as _;
const INPUT = ffi::CUBEB_DEVICE_TYPE_INPUT as _;
const OUTPUT = ffi::CUBEB_DEVICE_TYPE_OUTPUT as _;
}
}
pub type DeviceId = ffi::cubeb_devid;
ffi_type_heap! {
type CType = ffi::cubeb_device;
#[derive(Debug)]
pub struct Device;
pub struct DeviceRef;
}
impl DeviceRef {
fn get_ref(&self) -> &ffi::cubeb_device {
unsafe { &*self.as_ptr() }
}
pub fn output_name(&self) -> Option<&str> {
self.output_name_bytes().map(|b| str::from_utf8(b).unwrap())
}
pub fn output_name_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().output_name) }
}
pub fn input_name(&self) -> Option<&str> {
self.input_name_bytes().map(|b| str::from_utf8(b).unwrap())
}
pub fn input_name_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().input_name) }
}
}
ffi_type_stack! {
type CType = ffi::cubeb_device_info;
pub struct DeviceInfo;
pub struct DeviceInfoRef;
}
impl DeviceInfoRef {
fn get_ref(&self) -> &ffi::cubeb_device_info {
unsafe { &*self.as_ptr() }
}
pub fn devid(&self) -> DeviceId {
self.get_ref().devid
}
pub fn device_id(&self) -> Option<&str> {
self.device_id_bytes().map(|b| str::from_utf8(b).unwrap())
}
pub fn device_id_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().device_id) }
}
pub fn friendly_name(&self) -> Option<&str> {
self.friendly_name_bytes()
.map(|b| str::from_utf8(b).unwrap())
}
pub fn friendly_name_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().friendly_name) }
}
pub fn group_id(&self) -> Option<&str> {
self.group_id_bytes().map(|b| str::from_utf8(b).unwrap())
}
pub fn group_id_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().group_id) }
}
pub fn vendor_name(&self) -> Option<&str> {
self.vendor_name_bytes().map(|b| str::from_utf8(b).unwrap())
}
pub fn vendor_name_bytes(&self) -> Option<&[u8]> {
unsafe { opt_bytes(self.get_ref().vendor_name) }
}
pub fn device_type(&self) -> DeviceType {
DeviceType::from_bits_truncate(self.get_ref().device_type)
}
pub fn state(&self) -> DeviceState {
let state = self.get_ref().state;
macro_rules! check( ($($raw:ident => $real:ident),*) => (
$(if state == ffi::$raw {
DeviceState::$real
}) else *
else {
panic!("unknown device state: {}", state)
}
));
check!(CUBEB_DEVICE_STATE_DISABLED => Disabled,
CUBEB_DEVICE_STATE_UNPLUGGED => Unplugged,
CUBEB_DEVICE_STATE_ENABLED => Enabled)
}
pub fn preferred(&self) -> DevicePref {
DevicePref::from_bits(self.get_ref().preferred).unwrap()
}
pub fn format(&self) -> DeviceFormat {
DeviceFormat::from_bits(self.get_ref().format).unwrap()
}
pub fn default_format(&self) -> DeviceFormat {
DeviceFormat::from_bits(self.get_ref().default_format).unwrap()
}
pub fn max_channels(&self) -> u32 {
self.get_ref().max_channels
}
pub fn default_rate(&self) -> u32 {
self.get_ref().default_rate
}
pub fn max_rate(&self) -> u32 {
self.get_ref().max_rate
}
pub fn min_rate(&self) -> u32 {
self.get_ref().min_rate
}
pub fn latency_lo(&self) -> u32 {
self.get_ref().latency_lo
}
pub fn latency_hi(&self) -> u32 {
self.get_ref().latency_hi
}
}
#[cfg(test)]
mod tests {
use Device;
use ffi::cubeb_device;
#[test]
fn device_device_ref_same_ptr() {
let ptr: *mut cubeb_device = 0xDEAD_BEEF as *mut _;
let device = unsafe { Device::from_ptr(ptr) };
assert_eq!(device.as_ptr(), ptr);
assert_eq!(device.as_ptr(), device.as_ref().as_ptr());
}
}