cubeb_sys/
device.rs

1// Copyright © 2017-2018 Mozilla Foundation
2//
3// This program is made available under an ISC-style license.  See the
4// accompanying file LICENSE for details.
5
6use callbacks::cubeb_device_collection_changed_callback;
7use context::cubeb;
8use std::ffi::CStr;
9use std::os::raw::{c_char, c_int, c_uint, c_void};
10use std::{fmt, mem, ptr};
11
12cubeb_enum! {
13    pub enum cubeb_device_fmt {
14        CUBEB_DEVICE_FMT_S16LE          = 0x0010,
15        CUBEB_DEVICE_FMT_S16BE          = 0x0020,
16        CUBEB_DEVICE_FMT_F32LE          = 0x1000,
17        CUBEB_DEVICE_FMT_F32BE          = 0x2000,
18    }
19}
20
21#[cfg(target_endian = "big")]
22pub const CUBEB_DEVICE_FMT_S16NE: cubeb_device_fmt = CUBEB_DEVICE_FMT_S16BE;
23#[cfg(target_endian = "big")]
24pub const CUBEB_DEVICE_FMT_F32NE: cubeb_device_fmt = CUBEB_DEVICE_FMT_F32BE;
25#[cfg(target_endian = "little")]
26pub const CUBEB_DEVICE_FMT_S16NE: cubeb_device_fmt = CUBEB_DEVICE_FMT_S16LE;
27#[cfg(target_endian = "little")]
28pub const CUBEB_DEVICE_FMT_F32NE: cubeb_device_fmt = CUBEB_DEVICE_FMT_F32LE;
29
30pub const CUBEB_DEVICE_FMT_S16_MASK: cubeb_device_fmt =
31    CUBEB_DEVICE_FMT_S16LE | CUBEB_DEVICE_FMT_S16BE;
32pub const CUBEB_DEVICE_FMT_F32_MASK: cubeb_device_fmt =
33    CUBEB_DEVICE_FMT_F32LE | CUBEB_DEVICE_FMT_F32BE;
34pub const CUBEB_DEVICE_FMT_ALL: cubeb_device_fmt =
35    CUBEB_DEVICE_FMT_S16_MASK | CUBEB_DEVICE_FMT_F32_MASK;
36
37fn fmt_device_fmt(f: &cubeb_device_fmt) -> &'static str {
38    match *f {
39        CUBEB_DEVICE_FMT_S16LE => "S16LE",
40        CUBEB_DEVICE_FMT_S16BE => "S16BE",
41        CUBEB_DEVICE_FMT_F32LE => "F32LE",
42        CUBEB_DEVICE_FMT_F32BE => "F32BE",
43        CUBEB_DEVICE_FMT_S16_MASK => "S16LE | S16BE",
44        CUBEB_DEVICE_FMT_F32_MASK => "F32LE | F32BE",
45        CUBEB_DEVICE_FMT_ALL => "S16LE | S16BE | F32LE | F32BE",
46        _ => "Unexpected device format",
47    }
48}
49
50cubeb_enum! {
51    pub enum cubeb_device_pref  {
52        CUBEB_DEVICE_PREF_NONE          = 0x00,
53        CUBEB_DEVICE_PREF_MULTIMEDIA    = 0x01,
54        CUBEB_DEVICE_PREF_VOICE         = 0x02,
55        CUBEB_DEVICE_PREF_NOTIFICATION  = 0x04,
56        CUBEB_DEVICE_PREF_ALL           = 0x0F,
57    }
58}
59
60fn fmt_device_pref(p: &cubeb_device_pref) -> &'static str {
61    match *p {
62        CUBEB_DEVICE_PREF_NONE => "None",
63        CUBEB_DEVICE_PREF_MULTIMEDIA => "Multimedia",
64        CUBEB_DEVICE_PREF_VOICE => "Voice",
65        CUBEB_DEVICE_PREF_NOTIFICATION => "Notification",
66        CUBEB_DEVICE_PREF_ALL => "All",
67        _ => "Unexpected",
68    }
69}
70
71cubeb_enum! {
72    pub enum cubeb_device_state {
73        CUBEB_DEVICE_STATE_DISABLED,
74        CUBEB_DEVICE_STATE_UNPLUGGED,
75        CUBEB_DEVICE_STATE_ENABLED,
76    }
77}
78
79fn fmt_device_state(s: &cubeb_device_state) -> &'static str {
80    match *s {
81        CUBEB_DEVICE_STATE_DISABLED => "Disabled",
82        CUBEB_DEVICE_STATE_UNPLUGGED => "Unplugged",
83        CUBEB_DEVICE_STATE_ENABLED => "Enabled",
84        _ => "Unexpected",
85    }
86}
87
88cubeb_enum! {
89    pub enum cubeb_device_type {
90        CUBEB_DEVICE_TYPE_UNKNOWN,
91        CUBEB_DEVICE_TYPE_INPUT,
92        CUBEB_DEVICE_TYPE_OUTPUT,
93    }
94}
95
96fn fmt_device_type(t: &cubeb_device_type) -> &'static str {
97    match *t {
98        CUBEB_DEVICE_TYPE_UNKNOWN => "Unknown",
99        CUBEB_DEVICE_TYPE_INPUT => "Input",
100        CUBEB_DEVICE_TYPE_OUTPUT => "Output",
101        t if t == CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT => "Input+Output",
102        _ => "Unexpected",
103    }
104}
105
106pub type cubeb_devid = *const c_void;
107
108#[repr(C)]
109pub struct cubeb_device {
110    pub output_name: *mut c_char,
111    pub input_name: *mut c_char,
112}
113
114// Explicit Debug impl to work around bug in ctest
115impl Default for cubeb_device {
116    fn default() -> Self {
117        unsafe { mem::zeroed() }
118    }
119}
120
121impl fmt::Debug for cubeb_device {
122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123        f.debug_struct("cubeb_device")
124            .field("output_name", &self.output_name)
125            .field("input_name", &self.input_name)
126            .finish()
127    }
128}
129
130#[repr(C)]
131pub struct cubeb_device_collection {
132    pub device: *mut cubeb_device_info,
133    pub count: usize,
134}
135
136impl Default for cubeb_device_collection {
137    fn default() -> Self {
138        unsafe { mem::zeroed() }
139    }
140}
141
142impl fmt::Debug for cubeb_device_collection {
143    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144        let devices = ptr::slice_from_raw_parts(self.device, self.count);
145        let devices = unsafe { &*devices };
146        let mut dbg = f.debug_list();
147        for d in devices {
148            dbg.entry(d);
149        }
150        dbg.finish()
151    }
152}
153
154#[repr(C)]
155pub struct cubeb_device_info {
156    pub devid: cubeb_devid,
157    pub device_id: *const c_char,
158    pub friendly_name: *const c_char,
159    pub group_id: *const c_char,
160    pub vendor_name: *const c_char,
161
162    pub device_type: cubeb_device_type,
163    pub state: cubeb_device_state,
164    pub preferred: cubeb_device_pref,
165
166    pub format: cubeb_device_fmt,
167    pub default_format: cubeb_device_fmt,
168    pub max_channels: c_uint,
169    pub default_rate: c_uint,
170    pub max_rate: c_uint,
171    pub min_rate: c_uint,
172
173    pub latency_lo: c_uint,
174    pub latency_hi: c_uint,
175}
176
177impl Default for cubeb_device_info {
178    fn default() -> Self {
179        unsafe { mem::zeroed() }
180    }
181}
182
183impl fmt::Debug for cubeb_device_info {
184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185        fn optional_c_str(c_str: *const c_char) -> Option<*const c_char> {
186            (unsafe { c_str.as_ref() }).map(ptr::from_ref)
187        }
188        f.debug_struct("cubeb_device_info")
189            .field("devid", &(self.devid as u32))
190            .field(
191                "device_id",
192                &optional_c_str(self.device_id).map(|p| unsafe { CStr::from_ptr(p) }),
193            )
194            .field(
195                "friendly_name",
196                &optional_c_str(self.friendly_name).map(|p| unsafe { CStr::from_ptr(p) }),
197            )
198            .field(
199                "group_id",
200                &optional_c_str(self.group_id).map(|p| unsafe { CStr::from_ptr(p) }),
201            )
202            .field(
203                "vendor_name",
204                &optional_c_str(self.vendor_name).map(|p| unsafe { CStr::from_ptr(p) }),
205            )
206            .field("device_type", &fmt_device_type(&self.device_type))
207            .field("state", &fmt_device_state(&self.state))
208            .field("preferred", &fmt_device_pref(&self.preferred))
209            .field("format", &fmt_device_fmt(&self.format))
210            .field("default_format", &fmt_device_fmt(&self.default_format))
211            .field("max_channels", &self.max_channels)
212            .field("default_rate", &self.default_rate)
213            .field("max_rate", &self.max_rate)
214            .field("min_rate", &self.min_rate)
215            .field("latency_lo", &self.latency_lo)
216            .field("latency_hi", &self.latency_hi)
217            .finish()
218    }
219}
220
221extern "C" {
222    pub fn cubeb_enumerate_devices(
223        context: *mut cubeb,
224        devtype: cubeb_device_type,
225        collection: *mut cubeb_device_collection,
226    ) -> c_int;
227    pub fn cubeb_device_collection_destroy(
228        context: *mut cubeb,
229        collection: *mut cubeb_device_collection,
230    ) -> c_int;
231    pub fn cubeb_register_device_collection_changed(
232        context: *mut cubeb,
233        devtype: cubeb_device_type,
234        callback: cubeb_device_collection_changed_callback,
235        user_ptr: *mut c_void,
236    ) -> c_int;
237}