cubeb_core/
context.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 ffi;
7use std::ffi::CStr;
8use std::os::raw::c_void;
9use std::{ptr, str};
10use util::opt_bytes;
11use {
12    DeviceCollection, DeviceId, DeviceType, InputProcessingParams, Result, Stream, StreamParamsRef,
13};
14
15macro_rules! as_ptr {
16    ($e:expr) => {
17        $e.map(|s| s.as_ptr()).unwrap_or(ptr::null_mut())
18    };
19}
20
21ffi_type_heap! {
22    type CType = ffi::cubeb;
23    fn drop = ffi::cubeb_destroy;
24    pub struct Context;
25    pub struct ContextRef;
26}
27
28impl Context {
29    pub fn init(context_name: Option<&CStr>, backend_name: Option<&CStr>) -> Result<Context> {
30        let mut context: *mut ffi::cubeb = ptr::null_mut();
31        let context_name = as_ptr!(context_name);
32        let backend_name = as_ptr!(backend_name);
33        unsafe {
34            call!(ffi::cubeb_init(&mut context, context_name, backend_name))?;
35            Ok(Context::from_ptr(context))
36        }
37    }
38}
39
40impl ContextRef {
41    pub fn backend_id(&self) -> &str {
42        str::from_utf8(self.backend_id_bytes()).unwrap()
43    }
44
45    pub fn backend_id_bytes(&self) -> &[u8] {
46        unsafe { opt_bytes(ffi::cubeb_get_backend_id(self.as_ptr())).unwrap() }
47    }
48
49    pub fn max_channel_count(&self) -> Result<u32> {
50        let mut channel_count = 0u32;
51        unsafe {
52            call!(ffi::cubeb_get_max_channel_count(
53                self.as_ptr(),
54                &mut channel_count
55            ))?;
56        }
57        Ok(channel_count)
58    }
59
60    pub fn min_latency(&self, params: &StreamParamsRef) -> Result<u32> {
61        let mut latency = 0u32;
62        unsafe {
63            call!(ffi::cubeb_get_min_latency(
64                self.as_ptr(),
65                params.as_ptr(),
66                &mut latency
67            ))?;
68        }
69        Ok(latency)
70    }
71
72    pub fn preferred_sample_rate(&self) -> Result<u32> {
73        let mut rate = 0u32;
74        unsafe {
75            call!(ffi::cubeb_get_preferred_sample_rate(
76                self.as_ptr(),
77                &mut rate
78            ))?;
79        }
80        Ok(rate)
81    }
82
83    pub fn supported_input_processing_params(&self) -> Result<InputProcessingParams> {
84        let mut params = ffi::CUBEB_INPUT_PROCESSING_PARAM_NONE;
85        unsafe {
86            call!(ffi::cubeb_get_supported_input_processing_params(
87                self.as_ptr(),
88                &mut params
89            ))?;
90        };
91        Ok(InputProcessingParams::from_bits_truncate(params))
92    }
93
94    /// # Safety
95    ///
96    /// This function is unsafe because it dereferences the given `data_callback`, `state_callback`, and `user_ptr` pointers.
97    /// The caller should ensure those pointers are valid.
98    #[allow(clippy::too_many_arguments)]
99    pub unsafe fn stream_init(
100        &self,
101        stream_name: Option<&CStr>,
102        input_device: DeviceId,
103        input_stream_params: Option<&StreamParamsRef>,
104        output_device: DeviceId,
105        output_stream_params: Option<&StreamParamsRef>,
106        latency_frames: u32,
107        data_callback: ffi::cubeb_data_callback,
108        state_callback: ffi::cubeb_state_callback,
109        user_ptr: *mut c_void,
110    ) -> Result<Stream> {
111        let mut stm: *mut ffi::cubeb_stream = ptr::null_mut();
112
113        let stream_name = as_ptr!(stream_name);
114        let input_stream_params = as_ptr!(input_stream_params);
115        let output_stream_params = as_ptr!(output_stream_params);
116
117        call!(ffi::cubeb_stream_init(
118            self.as_ptr(),
119            &mut stm,
120            stream_name,
121            input_device,
122            input_stream_params,
123            output_device,
124            output_stream_params,
125            latency_frames,
126            data_callback,
127            state_callback,
128            user_ptr
129        ))?;
130        Ok(Stream::from_ptr(stm))
131    }
132
133    pub fn enumerate_devices(&self, devtype: DeviceType) -> Result<DeviceCollection<'_>> {
134        let mut coll = ffi::cubeb_device_collection::default();
135        unsafe {
136            call!(ffi::cubeb_enumerate_devices(
137                self.as_ptr(),
138                devtype.bits(),
139                &mut coll
140            ))?;
141        }
142        Ok(DeviceCollection::init_with_ctx(self, coll))
143    }
144
145    /// # Safety
146    ///
147    /// This function is unsafe because it dereferences the given `callback` and  `user_ptr` pointers.
148    /// The caller should ensure those pointers are valid.
149    pub unsafe fn register_device_collection_changed(
150        &self,
151        devtype: DeviceType,
152        callback: ffi::cubeb_device_collection_changed_callback,
153        user_ptr: *mut c_void,
154    ) -> Result<()> {
155        call!(ffi::cubeb_register_device_collection_changed(
156            self.as_ptr(),
157            devtype.bits(),
158            callback,
159            user_ptr
160        ))?;
161
162        Ok(())
163    }
164}