Add tests and comments
This commit is contained in:
Родитель
332627554e
Коммит
20b6225e25
|
@ -7,7 +7,9 @@ Implementation of MacOS Audio backend in CoreAudio framework for [Cubeb][cubeb]
|
|||
- Create tests for later refactoring
|
||||
|
||||
## TODO
|
||||
- Test aggregate device
|
||||
- Test aggregate devices
|
||||
- Test for stream operations
|
||||
- Clean up the tests. Merge the duplicated pieces in to a function.
|
||||
|
||||
[cubeb]: https://github.com/kinetiknz/cubeb "Cross platform audio library"
|
||||
[cubeb-au]: https://github.com/kinetiknz/cubeb/blob/master/src/cubeb_audiounit.cpp "Cubeb AudioUnit"
|
|
@ -123,8 +123,10 @@ fn audiounit_get_default_device_datasource(devtype: DeviceType,
|
|||
}
|
||||
|
||||
let mut size = mem::size_of_val(data);
|
||||
// FIXIT: This is wrong. We will use output scope when dev_type
|
||||
// is unknown. Change it after C version is updated!
|
||||
// TODO: devtype includes input, output, and unknown. This is a bad style
|
||||
// to check type, although this function will early return for
|
||||
// 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
|
||||
|
@ -138,6 +140,9 @@ fn audiounit_get_default_device_datasource(devtype: DeviceType,
|
|||
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<()>
|
||||
|
@ -145,8 +150,10 @@ fn audiounit_get_default_device_name(stm: &AudioUnitStream,
|
|||
let mut data: u32 = 0;
|
||||
audiounit_get_default_device_datasource(devtype, &mut data)?;
|
||||
|
||||
// FIXIT: This is wrong. We will use output scope when dev_type
|
||||
// is unknown. Change it after C version is updated!
|
||||
// TODO: devtype includes input, output, and unknown. This is a bad style
|
||||
// to check type, although this function will early return for
|
||||
// unknown type since audiounit_get_default_device_datasource will
|
||||
// throw an error for unknown type.
|
||||
let name = if devtype == DeviceType::INPUT {
|
||||
&mut device.input_name
|
||||
} else {
|
||||
|
@ -155,8 +162,7 @@ fn audiounit_get_default_device_name(stm: &AudioUnitStream,
|
|||
// Leak the memory to the external code.
|
||||
*name = convert_uint32_into_string(data).into_raw();
|
||||
if name.is_null() {
|
||||
// FIXIT: This is wrong. We will use output scope when dev_type
|
||||
// is unknown. Change it after C version is updated!
|
||||
// TODO: Bad style to use scope as the above.
|
||||
cubeb_log!("({:p}) name of {} device is empty!", stm,
|
||||
if devtype == DeviceType::INPUT { "input" } else { "output" } );
|
||||
}
|
||||
|
@ -236,6 +242,7 @@ fn audiounit_get_channel_count(devid: AudioObjectID, scope: AudioObjectPropertyS
|
|||
count
|
||||
}
|
||||
|
||||
// TODO: It seems that it works no matter what scope is(see test.rs). Is it ok?
|
||||
fn audiounit_get_available_samplerate(devid: AudioObjectID, scope: AudioObjectPropertyScope,
|
||||
min: &mut u32, max: &mut u32, def: &mut u32)
|
||||
{
|
||||
|
|
|
@ -148,51 +148,51 @@ fn test_ops_context_device_collection_destroy() {
|
|||
// stream_stop: Some($crate::capi::capi_stream_stop::<$stm>),
|
||||
// stream_get_position: Some($crate::capi::capi_stream_get_position::<$stm>),
|
||||
|
||||
#[test]
|
||||
fn test_ops_stream_latency() {
|
||||
let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
let mut latency = u32::max_value();
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_get_latency.unwrap()(s, &mut latency) },
|
||||
ffi::CUBEB_OK
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
}
|
||||
// #[test]
|
||||
// fn test_ops_stream_latency() {
|
||||
// let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
// let mut latency = u32::max_value();
|
||||
// assert_eq!(
|
||||
// unsafe { OPS.stream_get_latency.unwrap()(s, &mut latency) },
|
||||
// ffi::CUBEB_OK
|
||||
// );
|
||||
// assert_eq!(latency, 0);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_ops_stream_set_volume() {
|
||||
let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
unsafe {
|
||||
OPS.stream_set_volume.unwrap()(s, 0.5);
|
||||
}
|
||||
}
|
||||
// #[test]
|
||||
// fn test_ops_stream_set_volume() {
|
||||
// let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
// unsafe {
|
||||
// OPS.stream_set_volume.unwrap()(s, 0.5);
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_ops_stream_set_panning() {
|
||||
let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
unsafe {
|
||||
OPS.stream_set_panning.unwrap()(s, 0.5);
|
||||
}
|
||||
}
|
||||
// #[test]
|
||||
// fn test_ops_stream_set_panning() {
|
||||
// let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
// unsafe {
|
||||
// OPS.stream_set_panning.unwrap()(s, 0.5);
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_ops_stream_current_device() {
|
||||
let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
let mut device: *mut ffi::cubeb_device = ptr::null_mut();
|
||||
assert_eq!(
|
||||
unsafe { OPS.stream_get_current_device.unwrap()(s, &mut device) },
|
||||
ffi::CUBEB_OK
|
||||
);
|
||||
assert_eq!(device, 0xDEAD_BEEF as *mut _);
|
||||
}
|
||||
// #[test]
|
||||
// fn test_ops_stream_current_device() {
|
||||
// let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
// let mut device: *mut ffi::cubeb_device = ptr::null_mut();
|
||||
// assert_eq!(
|
||||
// unsafe { OPS.stream_get_current_device.unwrap()(s, &mut device) },
|
||||
// ffi::CUBEB_OK
|
||||
// );
|
||||
// assert_eq!(device, 0xDEAD_BEEF as *mut _);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_ops_stream_device_destroy() {
|
||||
let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
unsafe {
|
||||
OPS.stream_device_destroy.unwrap()(s, 0xDEAD_BEEF as *mut _);
|
||||
}
|
||||
}
|
||||
// #[test]
|
||||
// fn test_ops_stream_device_destroy() {
|
||||
// let s: *mut ffi::cubeb_stream = ptr::null_mut();
|
||||
// unsafe {
|
||||
// OPS.stream_device_destroy.unwrap()(s, 0xDEAD_BEEF as *mut _);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Private APIs
|
||||
// ============================================================================
|
||||
|
@ -232,6 +232,111 @@ fn test_get_default_device_id() {
|
|||
)
|
||||
}
|
||||
|
||||
// convert_uint32_into_string
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_convert_uint32_into_string() {
|
||||
let empty = convert_uint32_into_string(0);
|
||||
assert_eq!(empty, CString::default());
|
||||
|
||||
let data: u32 = ('R' as u32) << 24 |
|
||||
('U' as u32) << 16 |
|
||||
('S' as u32) << 8 |
|
||||
'T' as u32;
|
||||
let data_string = convert_uint32_into_string(data);
|
||||
assert_eq!(data_string, CString::new("RUST").unwrap());
|
||||
}
|
||||
|
||||
|
||||
// audiounit_get_default_device_datasource
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_default_device_datasource() {
|
||||
let mut data = 0;
|
||||
|
||||
// unknown type:
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_datasource(
|
||||
DeviceType::UNKNOWN,
|
||||
&mut data
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// TODO: The following fail with some USB headsets (e.g., Plantronic .Audio 628).
|
||||
// Find a reliable way to test the input/output scope.
|
||||
|
||||
// input:
|
||||
data = 0;
|
||||
assert!(
|
||||
audiounit_get_default_device_datasource(
|
||||
DeviceType::INPUT,
|
||||
&mut data
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(data, 0);
|
||||
|
||||
// output:
|
||||
data = 0;
|
||||
assert!(
|
||||
audiounit_get_default_device_datasource(
|
||||
DeviceType::OUTPUT,
|
||||
&mut data
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(data, 0);
|
||||
}
|
||||
|
||||
// audiounit_get_default_device_name
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_default_device_name() {
|
||||
let ctx = AudioUnitContext { ops: ptr::null() };
|
||||
let stream = AudioUnitStream::new(&ctx).unwrap();
|
||||
let mut device = ffi::cubeb_device::default();
|
||||
|
||||
// unknown type:
|
||||
assert_eq!(
|
||||
audiounit_get_default_device_name(
|
||||
stream.as_ref(),
|
||||
&mut device,
|
||||
DeviceType::UNKNOWN
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// TODO: The following fail with some USB headsets (e.g., Plantronic .Audio 628).
|
||||
// Find a reliable way to test the input/output scope.
|
||||
|
||||
// input:
|
||||
device = ffi::cubeb_device::default();
|
||||
assert!(
|
||||
audiounit_get_default_device_name(
|
||||
stream.as_ref(),
|
||||
&mut device,
|
||||
DeviceType::INPUT
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(device.input_name, ptr::null_mut());
|
||||
assert_eq!(device.output_name, ptr::null_mut());
|
||||
|
||||
// output:
|
||||
device = ffi::cubeb_device::default();
|
||||
assert!(
|
||||
audiounit_get_default_device_name(
|
||||
stream.as_ref(),
|
||||
&mut device,
|
||||
DeviceType::OUTPUT
|
||||
).is_ok()
|
||||
);
|
||||
assert_eq!(device.input_name, ptr::null_mut());
|
||||
assert_ne!(device.output_name, ptr::null_mut());
|
||||
}
|
||||
|
||||
// strref_to_cstr_utf8
|
||||
// ------------------------------------
|
||||
// TODO
|
||||
|
||||
// get_channel_count
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
|
@ -247,6 +352,516 @@ fn test_get_channel_count() {
|
|||
}
|
||||
}
|
||||
|
||||
// get_available_samplerate
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_available_samplerate_unknown() {
|
||||
let mut defualt = 0;
|
||||
let mut min = 0;
|
||||
let mut max = 0;
|
||||
|
||||
// global scope:
|
||||
audiounit_get_available_samplerate(
|
||||
kAudioObjectUnknown,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
assert_eq!(defualt, 0);
|
||||
assert_eq!(min, 0);
|
||||
assert_eq!(max, 0);
|
||||
|
||||
// input scope:
|
||||
audiounit_get_available_samplerate(
|
||||
kAudioObjectUnknown,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
assert_eq!(defualt, 0);
|
||||
assert_eq!(min, 0);
|
||||
assert_eq!(max, 0);
|
||||
|
||||
// output scope:
|
||||
audiounit_get_available_samplerate(
|
||||
kAudioObjectUnknown,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
assert_eq!(defualt, 0);
|
||||
assert_eq!(min, 0);
|
||||
assert_eq!(max, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_available_samplerate_input() {
|
||||
let input_id = audiounit_get_default_device_id(DeviceType::INPUT);
|
||||
if !valid_id(input_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut defualt = 0;
|
||||
let mut min = 0;
|
||||
let mut max = 0;
|
||||
|
||||
// global scope:
|
||||
audiounit_get_available_samplerate(
|
||||
input_id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_input] <global> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
|
||||
// input scope:
|
||||
defualt = 0;
|
||||
min = 0;
|
||||
max = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
input_id,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_input] <input> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
|
||||
// output scope:
|
||||
defualt = 0;
|
||||
min = 0;
|
||||
max = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
input_id,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_input] <output> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
if is_output(input_id) {
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
} else {
|
||||
// assert_eq!(defualt, 0);
|
||||
// assert_eq!(min, 0);
|
||||
// assert_eq!(max, 0);
|
||||
|
||||
// Surprisingly it works!
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_available_samplerate_output() {
|
||||
let output_id = audiounit_get_default_device_id(DeviceType::OUTPUT);
|
||||
if !valid_id(output_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut defualt = 0;
|
||||
let mut min = 0;
|
||||
let mut max = 0;
|
||||
|
||||
// global scope:
|
||||
audiounit_get_available_samplerate(
|
||||
output_id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_output] <global> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
|
||||
// input scope:
|
||||
defualt = 0;
|
||||
min = 0;
|
||||
max = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
output_id,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_output] <input> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
if is_input(output_id) {
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
} else {
|
||||
// assert_eq!(defualt, 0);
|
||||
// assert_eq!(min, 0);
|
||||
// assert_eq!(max, 0);
|
||||
|
||||
// Surprisingly it works!
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
}
|
||||
|
||||
// output scope:
|
||||
defualt = 0;
|
||||
min = 0;
|
||||
max = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
output_id,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
&mut min,
|
||||
&mut max,
|
||||
&mut defualt
|
||||
);
|
||||
// println!("[samplerate_output] <output> default: {}, min: {}, max: {}", defualt, min, max);
|
||||
assert!(defualt > 0);
|
||||
assert!(min > 0);
|
||||
assert!(max > 0);
|
||||
assert!(min <= max);
|
||||
assert!(min <= defualt);
|
||||
assert!(defualt <= max);
|
||||
}
|
||||
|
||||
// get_device_presentation_latency
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_get_device_presentation_latency_unknown() {
|
||||
let mut latency = 0;
|
||||
|
||||
// global scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
kAudioObjectUnknown,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
|
||||
// input scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
kAudioObjectUnknown,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
|
||||
// output scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
kAudioObjectUnknown,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_device_presentation_latency_input() {
|
||||
let input_id = audiounit_get_default_device_id(DeviceType::INPUT);
|
||||
if !valid_id(input_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut latency = 0;
|
||||
|
||||
// global scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
input_id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
|
||||
// input scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
input_id,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
);
|
||||
assert!(latency > 0);
|
||||
|
||||
// output scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
input_id,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
);
|
||||
if is_output(input_id) {
|
||||
assert!(latency > 0);
|
||||
} else {
|
||||
assert_eq!(latency, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_device_presentation_latency_output() {
|
||||
let output_id = audiounit_get_default_device_id(DeviceType::OUTPUT);
|
||||
if !valid_id(output_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut latency = 0;
|
||||
|
||||
// global scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
output_id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
);
|
||||
assert_eq!(latency, 0);
|
||||
|
||||
// input scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
output_id,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
);
|
||||
if is_input(output_id) {
|
||||
assert!(latency > 0);
|
||||
} else {
|
||||
assert_eq!(latency, 0);
|
||||
}
|
||||
|
||||
// output scope:
|
||||
latency = audiounit_get_device_presentation_latency(
|
||||
output_id,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
);
|
||||
assert!(latency > 0);
|
||||
}
|
||||
|
||||
// create_device_from_hwdev
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
fn test_create_device_from_hwdev_unknown() {
|
||||
let mut info = ffi::cubeb_device_info::default();
|
||||
|
||||
// unknown
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
kAudioObjectUnknown,
|
||||
DeviceType::UNKNOWN,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// input
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
kAudioObjectUnknown,
|
||||
DeviceType::INPUT,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// output
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
kAudioObjectUnknown,
|
||||
DeviceType::OUTPUT,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_device_from_hwdev_input() {
|
||||
let input_id = audiounit_get_default_device_id(DeviceType::INPUT);
|
||||
if !valid_id(input_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut info = ffi::cubeb_device_info::default();
|
||||
|
||||
// unknown
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
input_id,
|
||||
DeviceType::UNKNOWN,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// input
|
||||
info = ffi::cubeb_device_info::default();
|
||||
assert!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
input_id,
|
||||
DeviceType::INPUT,
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(info.devid, ptr::null_mut());
|
||||
assert_ne!(info.device_id, ptr::null_mut());
|
||||
assert_eq!(info.group_id, info.device_id);
|
||||
assert_ne!(info.friendly_name, ptr::null_mut());
|
||||
assert_ne!(info.vendor_name, ptr::null_mut());
|
||||
assert_eq!(info.device_type, ffi::CUBEB_DEVICE_TYPE_INPUT);
|
||||
assert_eq!(info.state, ffi::CUBEB_DEVICE_STATE_ENABLED);
|
||||
assert_eq!(info.preferred, ffi::CUBEB_DEVICE_PREF_ALL);
|
||||
assert!(info.max_channels > 0);
|
||||
assert_eq!(info.default_format, ffi::CUBEB_DEVICE_FMT_F32NE);
|
||||
assert!(info.min_rate <= info.max_rate);
|
||||
assert!(info.min_rate <= info.default_rate);
|
||||
assert!(info.default_rate <= info.max_rate);
|
||||
assert!(info.latency_lo > 0);
|
||||
assert!(info.latency_hi > 0);
|
||||
assert!(info.latency_lo <= info.latency_hi);
|
||||
|
||||
// output
|
||||
info = ffi::cubeb_device_info::default();
|
||||
if is_output(input_id) {
|
||||
assert!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
input_id,
|
||||
DeviceType::OUTPUT,
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(info.devid, ptr::null_mut());
|
||||
assert_ne!(info.device_id, ptr::null_mut());
|
||||
assert_eq!(info.group_id, info.device_id);
|
||||
assert_ne!(info.friendly_name, ptr::null_mut());
|
||||
assert_ne!(info.vendor_name, ptr::null_mut());
|
||||
assert_eq!(info.device_type, ffi::CUBEB_DEVICE_TYPE_OUTPUT);
|
||||
assert_eq!(info.state, ffi::CUBEB_DEVICE_STATE_ENABLED);
|
||||
assert_eq!(info.preferred, ffi::CUBEB_DEVICE_PREF_ALL);
|
||||
assert!(info.max_channels > 0);
|
||||
assert_eq!(info.default_format, ffi::CUBEB_DEVICE_FMT_F32NE);
|
||||
assert!(info.min_rate <= info.max_rate);
|
||||
assert!(info.min_rate <= info.default_rate);
|
||||
assert!(info.default_rate <= info.max_rate);
|
||||
assert!(info.latency_lo > 0);
|
||||
assert!(info.latency_hi > 0);
|
||||
assert!(info.latency_lo <= info.latency_hi);
|
||||
} else {
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
input_id,
|
||||
DeviceType::OUTPUT,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_device_from_hwdev_output() {
|
||||
let output_id = audiounit_get_default_device_id(DeviceType::OUTPUT);
|
||||
if !valid_id(output_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut info = ffi::cubeb_device_info::default();
|
||||
|
||||
// unknown
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
output_id,
|
||||
DeviceType::UNKNOWN,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
|
||||
// input
|
||||
info = ffi::cubeb_device_info::default();
|
||||
if is_input(output_id) {
|
||||
assert!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
output_id,
|
||||
DeviceType::INPUT,
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(info.devid, ptr::null_mut());
|
||||
assert_ne!(info.device_id, ptr::null_mut());
|
||||
assert_eq!(info.group_id, info.device_id);
|
||||
assert_ne!(info.friendly_name, ptr::null_mut());
|
||||
assert_ne!(info.vendor_name, ptr::null_mut());
|
||||
assert_eq!(info.device_type, ffi::CUBEB_DEVICE_TYPE_INPUT);
|
||||
assert_eq!(info.state, ffi::CUBEB_DEVICE_STATE_ENABLED);
|
||||
assert_eq!(info.preferred, ffi::CUBEB_DEVICE_PREF_ALL);
|
||||
assert!(info.max_channels > 0);
|
||||
assert_eq!(info.default_format, ffi::CUBEB_DEVICE_FMT_F32NE);
|
||||
assert!(info.min_rate <= info.max_rate);
|
||||
assert!(info.min_rate <= info.default_rate);
|
||||
assert!(info.default_rate <= info.max_rate);
|
||||
assert!(info.latency_lo > 0);
|
||||
assert!(info.latency_hi > 0);
|
||||
assert!(info.latency_lo <= info.latency_hi);
|
||||
} else {
|
||||
assert_eq!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
output_id,
|
||||
DeviceType::INPUT,
|
||||
).unwrap_err(),
|
||||
Error::error()
|
||||
);
|
||||
}
|
||||
|
||||
// output
|
||||
info = ffi::cubeb_device_info::default();
|
||||
assert!(
|
||||
audiounit_create_device_from_hwdev(
|
||||
&mut info,
|
||||
output_id,
|
||||
DeviceType::OUTPUT,
|
||||
).is_ok()
|
||||
);
|
||||
assert_ne!(info.devid, ptr::null_mut());
|
||||
assert_ne!(info.device_id, ptr::null_mut());
|
||||
assert_eq!(info.group_id, info.device_id);
|
||||
assert_ne!(info.friendly_name, ptr::null_mut());
|
||||
assert_ne!(info.vendor_name, ptr::null_mut());
|
||||
assert_eq!(info.device_type, ffi::CUBEB_DEVICE_TYPE_OUTPUT);
|
||||
assert_eq!(info.state, ffi::CUBEB_DEVICE_STATE_ENABLED);
|
||||
assert_eq!(info.preferred, ffi::CUBEB_DEVICE_PREF_ALL);
|
||||
assert!(info.max_channels > 0);
|
||||
assert_eq!(info.default_format, ffi::CUBEB_DEVICE_FMT_F32NE);
|
||||
assert!(info.min_rate <= info.max_rate);
|
||||
assert!(info.min_rate <= info.default_rate);
|
||||
assert!(info.default_rate <= info.max_rate);
|
||||
assert!(info.latency_lo > 0);
|
||||
assert!(info.latency_hi > 0);
|
||||
assert!(info.latency_lo <= info.latency_hi);
|
||||
}
|
||||
|
||||
// is_aggregate_device
|
||||
// ------------------------------------
|
||||
// TODO
|
||||
|
||||
// get_devices_of_type
|
||||
// ------------------------------------
|
||||
#[test]
|
||||
|
@ -276,12 +891,16 @@ fn test_get_devices_of_type() {
|
|||
}
|
||||
}
|
||||
|
||||
// audiounit_create_device_from_hwdev
|
||||
// ------------------------------------
|
||||
// ...
|
||||
|
||||
// Utils
|
||||
// ------------------------------------
|
||||
fn valid_id(id: AudioObjectID) -> bool {
|
||||
id != kAudioObjectUnknown
|
||||
}
|
||||
}
|
||||
|
||||
fn is_input(id: AudioObjectID) -> bool {
|
||||
audiounit_get_channel_count(id, kAudioDevicePropertyScopeInput) > 0
|
||||
}
|
||||
|
||||
fn is_output(id: AudioObjectID) -> bool {
|
||||
audiounit_get_channel_count(id, kAudioDevicePropertyScopeOutput) > 0
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ pub fn allocate_array<T>(elements: usize) -> Vec<T> {
|
|||
array
|
||||
}
|
||||
|
||||
|
||||
pub fn get_leaked_vec<T>(mut v: Vec<T>) -> (*mut T, usize) {
|
||||
v.shrink_to_fit(); // Make sure the capacity is same as the length.
|
||||
let ptr_and_len = (v.as_mut_ptr(), v.len());
|
||||
|
|
Загрузка…
Ссылка в новой задаче