Refactor get_default_datasource and it's friend
This commit is contained in:
Родитель
95ba4da316
Коммит
4f808a2931
|
@ -2809,64 +2809,33 @@ fn convert_uint32_into_string(data: u32) -> CString
|
|||
CString::new(buffer).unwrap_or(empty)
|
||||
}
|
||||
|
||||
fn audiounit_get_default_device_datasource(devtype: DeviceType,
|
||||
data: &mut u32) -> Result<()>
|
||||
fn audiounit_get_default_datasource(side: io_side) -> Result<(u32)>
|
||||
{
|
||||
let (devtype, address) = match side {
|
||||
io_side::INPUT => (DeviceType::INPUT, INPUT_DATA_SOURCE_PROPERTY_ADDRESS),
|
||||
io_side::OUTPUT => (DeviceType::OUTPUT, OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS),
|
||||
};
|
||||
let id = audiounit_get_default_device_id(devtype);
|
||||
if id == kAudioObjectUnknown {
|
||||
return Err(Error::error());
|
||||
}
|
||||
|
||||
let mut size = mem::size_of_val(data);
|
||||
assert_eq!(size, mem::size_of::<u32>());
|
||||
// TODO: devtype includes input, output, in-out, and unknown. This is a
|
||||
// bad style to check type, although this function will early return
|
||||
// for in-out and unknown type since audiounit_get_default_device_id
|
||||
// will gives a kAudioObjectUnknown for unknown type.
|
||||
/* This fails with some USB headsets (e.g., Plantronic .Audio 628). */
|
||||
let r = audio_object_get_property_data(id, if devtype == DeviceType::INPUT {
|
||||
&INPUT_DATA_SOURCE_PROPERTY_ADDRESS
|
||||
} else {
|
||||
&OUTPUT_DATA_SOURCE_PROPERTY_ADDRESS
|
||||
}, &mut size, data);
|
||||
if r != NO_ERR {
|
||||
*data = 0;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: This actually is the name converted from the bytes of the data source
|
||||
// (kAudioDevicePropertyDataSource), rather than the name of the audio
|
||||
// device(kAudioObjectPropertyName). The naming here is vague.
|
||||
fn audiounit_get_default_device_name(stm: &AudioUnitStream,
|
||||
device: &mut ffi::cubeb_device,
|
||||
devtype: DeviceType) -> Result<()>
|
||||
{
|
||||
let mut data: u32 = 0;
|
||||
audiounit_get_default_device_datasource(devtype, &mut data)?;
|
||||
|
||||
// TODO: devtype includes input, output, in-out, and unknown. This is a
|
||||
// bad style to check type, although this function will early return
|
||||
// for in-out and unknown type since
|
||||
// audiounit_get_default_device_datasource will throw an error for
|
||||
// in-out and unknown type.
|
||||
let name = if devtype == DeviceType::INPUT {
|
||||
&mut device.input_name
|
||||
} else {
|
||||
&mut device.output_name
|
||||
};
|
||||
// Leak the memory to the external code. Retrieve them in device_destroy.
|
||||
*name = convert_uint32_into_string(data).into_raw();
|
||||
if name.is_null() {
|
||||
// TODO: Bad style to use scope as the above.
|
||||
cubeb_log!("({:p}) name of {} device is empty!", stm as *const AudioUnitStream,
|
||||
if devtype == DeviceType::INPUT { "input" } else { "output" } );
|
||||
let mut size = mem::size_of::<u32>();
|
||||
/* This fails with some USB headsets (e.g., Plantronic .Audio 628). */
|
||||
let r = audio_object_get_property_data(id, &address, &mut size, &mut data);
|
||||
if r != NO_ERR {
|
||||
data = 0;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
|
||||
fn audiounit_get_default_datasource_string(side: io_side) -> Result<CString>
|
||||
{
|
||||
let data = audiounit_get_default_datasource(side)?;
|
||||
Ok(convert_uint32_into_string(data))
|
||||
}
|
||||
|
||||
fn audiounit_strref_to_cstr_utf8(strref: CFStringRef) -> CString
|
||||
{
|
||||
|
@ -4070,9 +4039,12 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
|
|||
}
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
fn current_device(&mut self) -> Result<&DeviceRef> {
|
||||
// Leak the memory to the external code. Retrieve them in device_destroy.
|
||||
let mut device: Box<ffi::cubeb_device> = Box::new(ffi::cubeb_device::default());
|
||||
audiounit_get_default_device_name(self, device.as_mut(), DeviceType::OUTPUT)?;
|
||||
audiounit_get_default_device_name(self, device.as_mut(), DeviceType::INPUT)?;
|
||||
let input_source = audiounit_get_default_datasource_string(io_side::INPUT)?;
|
||||
device.input_name = input_source.into_raw();
|
||||
let output_source = audiounit_get_default_datasource_string(io_side::OUTPUT)?;
|
||||
device.output_name = output_source.into_raw();
|
||||
Ok(unsafe { DeviceRef::from_ptr(Box::into_raw(device)) })
|
||||
}
|
||||
#[cfg(target_os = "ios")]
|
||||
|
|
|
@ -2096,99 +2096,43 @@ fn test_convert_uint32_into_string() {
|
|||
assert_eq!(data_string, CString::new("RUST").unwrap());
|
||||
}
|
||||
|
||||
// get_default_device_datasource
|
||||
// get_default_datasource
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_default_device_datasource() {
|
||||
// Input type.
|
||||
test_get_default_datasource_in_scope(Scope::Input);
|
||||
|
||||
// Output type.
|
||||
test_get_default_datasource_in_scope(Scope::Output);
|
||||
|
||||
// Unknown type.
|
||||
let mut data = 0;
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_datasource(DeviceType::UNKNOWN, &mut data).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// In-out type.
|
||||
let mut data = 0;
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_datasource(DeviceType::INPUT | DeviceType::OUTPUT, &mut data)
|
||||
.unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
fn test_get_default_datasource_in_scope(scope: Scope) {
|
||||
if let Some(source) = test_get_default_source_data(scope.clone()) {
|
||||
let mut data = 0;
|
||||
assert!(audiounit_get_default_device_datasource(scope.into(), &mut data).is_ok());
|
||||
assert_ne!(data, 0);
|
||||
assert_eq!(data, source);
|
||||
assert_eq!(
|
||||
audiounit_get_default_datasource(scope.into()).unwrap(),
|
||||
source
|
||||
);
|
||||
} else {
|
||||
println!("No source data for {:?}.", scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get_default_device_name
|
||||
// get_default_datasource_string
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_default_device_name() {
|
||||
test_get_empty_stream(|stream| {
|
||||
// Input type.
|
||||
test_get_default_device_name_in_scope(stream, Scope::Input);
|
||||
test_get_default_device_name_in_scope(Scope::Input);
|
||||
test_get_default_device_name_in_scope(Scope::Output);
|
||||
|
||||
// Output type.
|
||||
test_get_default_device_name_in_scope(stream, Scope::Output);
|
||||
|
||||
// Unknown type.
|
||||
let mut device = ffi::cubeb_device::default();
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_name(stream, &mut device, DeviceType::UNKNOWN)
|
||||
.unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
// No need to release the memory since device.{input, output}_name are nulls.
|
||||
|
||||
// FIXIT: Shouldn't we get both input and output name ?
|
||||
// In-out type.
|
||||
let mut device = ffi::cubeb_device::default();
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_name(
|
||||
&stream,
|
||||
&mut device,
|
||||
DeviceType::INPUT | DeviceType::OUTPUT
|
||||
)
|
||||
.unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
// No need to release the memory since device.{input, output}_name are nulls.
|
||||
|
||||
fn test_get_default_device_name_in_scope(stream: &mut AudioUnitStream, scope: Scope) {
|
||||
if let Some(name) = test_get_default_source_name(scope.clone()) {
|
||||
let mut device: Box<ffi::cubeb_device> = Box::new(ffi::cubeb_device::default());
|
||||
assert!(audiounit_get_default_device_name(
|
||||
stream,
|
||||
device.as_mut(),
|
||||
scope.clone().into()
|
||||
)
|
||||
.is_ok());
|
||||
let (target, rest) = match scope {
|
||||
Scope::Input => (device.input_name, device.output_name),
|
||||
Scope::Output => (device.output_name, device.input_name),
|
||||
};
|
||||
assert!(!target.is_null());
|
||||
assert!(rest.is_null());
|
||||
let cstring = unsafe { CString::from_raw(target) };
|
||||
assert_eq!(cstring.into_string().unwrap(), name);
|
||||
} else {
|
||||
println!("No source name for {:?}", scope);
|
||||
}
|
||||
fn test_get_default_device_name_in_scope(scope: Scope) {
|
||||
if let Some(name) = test_get_default_source_name(scope.clone()) {
|
||||
let source = audiounit_get_default_datasource_string(scope.into())
|
||||
.unwrap()
|
||||
.into_string()
|
||||
.unwrap();
|
||||
assert_eq!(name, source);
|
||||
} else {
|
||||
println!("No source name for {:?}", scope);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// strref_to_cstr_utf8
|
||||
|
|
|
@ -525,8 +525,14 @@ fn test_ops_stream_current_device() {
|
|||
assert!(!device.is_null());
|
||||
// Uncomment the below to print out the results.
|
||||
// let deviceref = unsafe { DeviceRef::from_ptr(device) };
|
||||
// println!("output: {}", deviceref.output_name().unwrap_or("(no device name)"));
|
||||
// println!("input: {}", deviceref.input_name().unwrap_or("(no device name)"));
|
||||
// println!(
|
||||
// "output: {}",
|
||||
// deviceref.output_name().unwrap_or("(no device name)")
|
||||
// );
|
||||
// println!(
|
||||
// "input: {}",
|
||||
// deviceref.input_name().unwrap_or("(no device name)")
|
||||
// );
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_device_destroy.unwrap()(stream, device) },
|
||||
ffi::CUBEB_OK
|
||||
|
|
Загрузка…
Ссылка в новой задаче