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