Move more tests from test.rs to api.rs

This commit is contained in:
Chun-Min Chang 2019-03-15 14:26:27 -07:00
Родитель 7cc1819ece
Коммит 8308025ae2
2 изменённых файлов: 411 добавлений и 521 удалений

Просмотреть файл

@ -492,3 +492,414 @@ fn test_set_device_info_and_get_default_device(
// property_listener_callback
// ------------------------------------
// TODO
// add_listener (for default output device)
// ------------------------------------
#[test]
fn test_add_listener_unknown_device() {
extern "C" fn callback(
_id: AudioObjectID,
_number_of_addresses: u32,
_addresses: *const AudioObjectPropertyAddress,
_data: *mut c_void,
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
test_get_empty_stream(|stream| {
let mut listener = property_listener::new(
kAudioObjectUnknown,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
callback,
stream,
);
assert_eq!(
audiounit_add_listener(&mut listener),
kAudioHardwareBadObjectError as OSStatus
);
});
}
// remove_listener (for default output device)
// ------------------------------------
#[test]
fn test_add_listener_then_remove_system_device() {
extern "C" fn callback(
_id: AudioObjectID,
_number_of_addresses: u32,
_addresses: *const AudioObjectPropertyAddress,
_data: *mut c_void,
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
test_get_empty_stream(|stream| {
let mut listener = property_listener::new(
kAudioObjectSystemObject,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
callback,
stream,
);
assert_eq!(audiounit_add_listener(&mut listener), NO_ERR);
assert_eq!(audiounit_remove_listener(&mut listener), NO_ERR);
});
}
#[test]
fn test_remove_listener_without_adding_any_listener_before_system_device() {
extern "C" fn callback(
_id: AudioObjectID,
_number_of_addresses: u32,
_addresses: *const AudioObjectPropertyAddress,
_data: *mut c_void,
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
test_get_empty_stream(|stream| {
let mut listener = property_listener::new(
kAudioObjectSystemObject,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
callback,
stream,
);
assert_eq!(audiounit_remove_listener(&mut listener), NO_ERR);
});
}
#[test]
fn test_remove_listener_unknown_device() {
extern "C" fn callback(
_id: AudioObjectID,
_number_of_addresses: u32,
_addresses: *const AudioObjectPropertyAddress,
_data: *mut c_void,
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
test_get_empty_stream(|stream| {
let mut listener = property_listener::new(
kAudioObjectUnknown,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
callback,
stream,
);
assert_eq!(
audiounit_remove_listener(&mut listener),
kAudioHardwareBadObjectError as OSStatus
);
});
}
// install_system_changed_callback
// ------------------------------------
// TODO
// uninstall_system_changed_callback
// ------------------------------------
// TODO
// get_acceptable_latency_range
// ------------------------------------
#[test]
fn test_get_acceptable_latency_range() {
let mut latency_range = AudioValueRange::default();
let default_output = test_get_default_device(Scope::Output);
if default_output.is_none() {
assert_eq!(
audiounit_get_acceptable_latency_range(&mut latency_range).unwrap_err(),
Error::error()
);
return;
}
assert!(audiounit_get_acceptable_latency_range(&mut latency_range).is_ok());
assert!(latency_range.mMinimum > 0.0);
assert!(latency_range.mMaximum > 0.0);
assert!(latency_range.mMaximum > latency_range.mMinimum);
}
// get_default_device_id
// ------------------------------------
#[test]
fn test_get_default_device_id() {
// Invalid types:
assert_eq!(
audiounit_get_default_device_id(DeviceType::UNKNOWN),
kAudioObjectUnknown,
);
assert_eq!(
audiounit_get_default_device_id(DeviceType::INPUT | DeviceType::OUTPUT),
kAudioObjectUnknown,
);
if test_get_default_device(Scope::Input).is_some() {
assert_ne!(
audiounit_get_default_device_id(DeviceType::INPUT),
kAudioObjectUnknown,
);
}
if test_get_default_device(Scope::Output).is_some() {
assert_ne!(
audiounit_get_default_device_id(DeviceType::OUTPUT),
kAudioObjectUnknown,
);
}
}
// convert_channel_layout
// ------------------------------------
#[test]
fn test_convert_channel_layout() {
let pairs = [
// The single channel is mapped to mono now.
(vec![kAudioObjectUnknown], ChannelLayout::MONO),
(vec![kAudioChannelLabel_Mono], ChannelLayout::MONO),
// The dual channels are mapped to stereo now.
(
vec![kAudioChannelLabel_Mono, kAudioChannelLabel_LFEScreen],
ChannelLayout::STEREO,
),
(
vec![kAudioChannelLabel_Left, kAudioChannelLabel_Right],
ChannelLayout::STEREO,
),
// The Layouts containing any unknonwn channel will be mapped to UNDEFINED.
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Unknown,
],
ChannelLayout::UNDEFINED,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Unused,
],
ChannelLayout::UNDEFINED,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_ForeignLanguage,
],
ChannelLayout::UNDEFINED,
),
// The SMPTE layouts.
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::STEREO_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
],
ChannelLayout::_3F,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_CenterSurround,
],
ChannelLayout::_2F1,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_2F1_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_CenterSurround,
],
ChannelLayout::_3F1,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F1_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_2F2,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_2F2_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
],
ChannelLayout::QUAD,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::QUAD_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F2,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F2_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_Center,
],
ChannelLayout::_3F2_BACK,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F2_LFE_BACK,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F3R_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F4_LFE,
),
];
const MAX_CHANNELS: usize = 10;
// A Rust mapping structure of the AudioChannelLayout with MAX_CHANNELS channels
// https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.13.sdk/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudioTypes.h#L1332
#[repr(C)]
struct TestLayout {
tag: AudioChannelLayoutTag,
map: AudioChannelBitmap,
number_channel_descriptions: UInt32,
channel_descriptions: [AudioChannelDescription; MAX_CHANNELS],
}
impl Default for TestLayout {
fn default() -> Self {
Self {
tag: AudioChannelLayoutTag::default(),
map: AudioChannelBitmap::default(),
number_channel_descriptions: UInt32::default(),
channel_descriptions: [AudioChannelDescription::default(); MAX_CHANNELS],
}
}
}
let mut layout = TestLayout::default();
layout.tag = kAudioChannelLayoutTag_UseChannelDescriptions;
for (labels, expected_layout) in pairs.iter() {
assert!(labels.len() <= MAX_CHANNELS);
layout.number_channel_descriptions = labels.len() as u32;
for (idx, label) in labels.iter().enumerate() {
layout.channel_descriptions[idx].mChannelLabel = *label;
}
let layout_ref = unsafe { &(*(&layout as *const TestLayout as *const AudioChannelLayout)) };
assert_eq!(
audiounit_convert_channel_layout(layout_ref),
*expected_layout
);
}
}

Просмотреть файл

@ -231,527 +231,6 @@ fn test_context_register_device_collection_changed_twice_inout() {
// Private APIs
// ============================================================================
// add_listener
// ------------------------------------
#[test]
fn test_add_listener_for_unknown_device() {
extern fn listener(
_: AudioObjectID,
_: u32,
_: *const AudioObjectPropertyAddress,
_: *mut c_void
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
// We need to initialize the members with type OwnedCriticalSection in
// AudioUnitContext and AudioUnitStream, since those OwnedCriticalSection
// will be used when AudioUnitStream::drop/destroy is called.
let mut ctx = AudioUnitContext::new();
ctx.init();
// Add a stream to the context. `AudioUnitStream::drop()` will check
// the context has at least one stream.
{
// Create a `mutext_ptr` here to avoid borrowing issues for `ctx`.
let mutex_ptr = &mut ctx.mutex as *mut OwnedCriticalSection;
// The scope of `_lock` is a critical section.
let _lock = AutoLock::new(unsafe { &mut (*mutex_ptr) });
audiounit_increment_active_streams(&mut ctx);
}
let mut stream = AudioUnitStream::new(
&mut ctx,
ptr::null_mut(),
None,
None,
0
);
stream.init();
let mut listener = property_listener::new(
kAudioObjectUnknown,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
listener,
&mut stream
);
assert_eq!(
audiounit_add_listener(&mut listener),
kAudioHardwareBadObjectError as OSStatus
);
}
// remove_listener
// ------------------------------------
#[test]
fn test_remove_listener_for_unknown_device() {
extern fn listener(
_: AudioObjectID,
_: u32,
_: *const AudioObjectPropertyAddress,
_: *mut c_void
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
// We need to initialize the members with type OwnedCriticalSection in
// AudioUnitContext and AudioUnitStream, since those OwnedCriticalSection
// will be used when AudioUnitStream::drop/destroy is called.
let mut ctx = AudioUnitContext::new();
ctx.init();
// Add a stream to the context. `AudioUnitStream::drop()` will check
// the context has at least one stream.
{
// Create a `mutext_ptr` here to avoid borrowing issues for `ctx`.
let mutex_ptr = &mut ctx.mutex as *mut OwnedCriticalSection;
// The scope of `_lock` is a critical section.
let _lock = AutoLock::new(unsafe { &mut (*mutex_ptr) });
audiounit_increment_active_streams(&mut ctx);
}
let mut stream = AudioUnitStream::new(
&mut ctx,
ptr::null_mut(),
None,
None,
0
);
stream.init();
let mut listener = property_listener::new(
kAudioObjectUnknown,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
listener,
&mut stream
);
assert_eq!(
audiounit_remove_listener(&mut listener),
kAudioHardwareBadObjectError as OSStatus
);
}
#[test]
fn test_remove_listener_without_adding_any_listener() {
extern fn listener(
_: AudioObjectID,
_: u32,
_: *const AudioObjectPropertyAddress,
_: *mut c_void
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
// We need to initialize the members with type OwnedCriticalSection in
// AudioUnitContext and AudioUnitStream, since those OwnedCriticalSection
// will be used when AudioUnitStream::drop/destroy is called.
let mut ctx = AudioUnitContext::new();
ctx.init();
// Add a stream to the context. `AudioUnitStream::drop()` will check
// the context has at least one stream.
{
// Create a `mutext_ptr` here to avoid borrowing issues for `ctx`.
let mutex_ptr = &mut ctx.mutex as *mut OwnedCriticalSection;
// The scope of `_lock` is a critical section.
let _lock = AutoLock::new(unsafe { &mut (*mutex_ptr) });
audiounit_increment_active_streams(&mut ctx);
}
let mut stream = AudioUnitStream::new(
&mut ctx,
ptr::null_mut(),
None,
None,
0
);
stream.init();
let mut listener = property_listener::new(
kAudioObjectSystemObject,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
listener,
&mut stream
);
assert_eq!(
audiounit_remove_listener(&mut listener),
0
);
}
#[test]
fn test_add_then_remove_listener() {
extern fn listener(
_: AudioObjectID,
_: u32,
_: *const AudioObjectPropertyAddress,
_: *mut c_void
) -> OSStatus {
assert!(false, "Should not be called.");
kAudioHardwareUnspecifiedError as OSStatus
}
// We need to initialize the members with type OwnedCriticalSection in
// AudioUnitContext and AudioUnitStream, since those OwnedCriticalSection
// will be used when AudioUnitStream::drop/destroy is called.
let mut ctx = AudioUnitContext::new();
ctx.init();
// Add a stream to the context. `AudioUnitStream::drop()` will check
// the context has at least one stream.
{
// Create a `mutext_ptr` here to avoid borrowing issues for `ctx`.
let mutex_ptr = &mut ctx.mutex as *mut OwnedCriticalSection;
// The scope of `_lock` is a critical section.
let _lock = AutoLock::new(unsafe { &mut (*mutex_ptr) });
audiounit_increment_active_streams(&mut ctx);
}
let mut stream = AudioUnitStream::new(
&mut ctx,
ptr::null_mut(),
None,
None,
0
);
stream.init();
let mut listener = property_listener::new(
kAudioObjectSystemObject,
&DEFAULT_OUTPUT_DEVICE_PROPERTY_ADDRESS,
listener,
&mut stream
);
assert_eq!(
audiounit_add_listener(&mut listener),
0
);
assert_eq!(
audiounit_remove_listener(&mut listener),
0
);
}
// install_system_changed_callback
// ------------------------------------
// TODO
// uninstall_system_changed_callback
// ------------------------------------
// TODO
// get_acceptable_latency_range
// ------------------------------------
#[test]
fn test_get_acceptable_latency_range() {
let mut latency_range = AudioValueRange::default();
// Get an error if there is no avaiable output device.
let output_id = audiounit_get_default_device_id(DeviceType::OUTPUT);
if !valid_id(output_id) {
assert_eq!(
audiounit_get_acceptable_latency_range(
&mut latency_range
).unwrap_err(),
Error::error()
);
return;
}
assert!(
audiounit_get_acceptable_latency_range(
&mut latency_range
).is_ok()
);
assert!(latency_range.mMinimum > 0.0);
assert!(latency_range.mMaximum > 0.0);
assert!(latency_range.mMaximum > latency_range.mMinimum);
}
// get_default_device_id
// ------------------------------------
#[test]
fn test_get_default_device_id() {
// Invalid types:
assert_eq!(
audiounit_get_default_device_id(DeviceType::UNKNOWN),
kAudioObjectUnknown,
);
assert_eq!(
audiounit_get_default_device_id(DeviceType::INPUT | DeviceType::OUTPUT),
kAudioObjectUnknown,
);
// Valid types:
// P.S. Works only when there is available default input and output.
assert_ne!(
audiounit_get_default_device_id(DeviceType::INPUT),
kAudioObjectUnknown,
);
assert_ne!(
audiounit_get_default_device_id(DeviceType::OUTPUT),
kAudioObjectUnknown,
)
}
// convert_channel_layout
// ------------------------------------
#[test]
fn test_convert_channel_layout() {
let pairs = [
// The single channel is mapped to mono now.
(vec![kAudioObjectUnknown], ChannelLayout::MONO),
(vec![kAudioChannelLabel_Mono], ChannelLayout::MONO),
// The dual channels are mapped to stereo now.
(
vec![kAudioChannelLabel_Mono, kAudioChannelLabel_LFEScreen],
ChannelLayout::STEREO,
),
(
vec![kAudioChannelLabel_Left, kAudioChannelLabel_Right],
ChannelLayout::STEREO,
),
// The Layouts containing any unknonwn channel will be mapped to UNDEFINED.
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Unknown,
],
ChannelLayout::UNDEFINED,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Unused,
],
ChannelLayout::UNDEFINED,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_ForeignLanguage,
],
ChannelLayout::UNDEFINED,
),
// The SMPTE layouts.
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::STEREO_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
],
ChannelLayout::_3F,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_CenterSurround,
],
ChannelLayout::_2F1,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_2F1_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_CenterSurround,
],
ChannelLayout::_3F1,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F1_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_2F2,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_2F2_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
],
ChannelLayout::QUAD,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::QUAD_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F2,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F2_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_Center,
],
ChannelLayout::_3F2_BACK,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
],
ChannelLayout::_3F2_LFE_BACK,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
kAudioChannelLabel_CenterSurround,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F3R_LFE,
),
(
vec![
kAudioChannelLabel_Left,
kAudioChannelLabel_Right,
kAudioChannelLabel_Center,
kAudioChannelLabel_LFEScreen,
kAudioChannelLabel_LeftSurround,
kAudioChannelLabel_RightSurround,
kAudioChannelLabel_LeftSurroundDirect,
kAudioChannelLabel_RightSurroundDirect,
],
ChannelLayout::_3F4_LFE,
),
];
const MAX_CHANNELS: usize = 10;
// A Rust mapping structure of the AudioChannelLayout with MAX_CHANNELS channels
// https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.13.sdk/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudioTypes.h#L1332
#[repr(C)]
struct TestLayout {
tag: AudioChannelLayoutTag,
map: AudioChannelBitmap,
number_channel_descriptions: UInt32,
channel_descriptions: [AudioChannelDescription; MAX_CHANNELS],
}
impl Default for TestLayout {
fn default() -> Self {
Self {
tag: AudioChannelLayoutTag::default(),
map: AudioChannelBitmap::default(),
number_channel_descriptions: UInt32::default(),
channel_descriptions: [AudioChannelDescription::default(); MAX_CHANNELS],
}
}
}
let mut layout = TestLayout::default();
layout.tag = kAudioChannelLayoutTag_UseChannelDescriptions;
for (labels, expected_layout) in pairs.iter() {
assert!(labels.len() <= MAX_CHANNELS);
layout.number_channel_descriptions = labels.len() as u32;
for (idx, label) in labels.iter().enumerate() {
layout.channel_descriptions[idx].mChannelLabel = *label;
}
let layout_ref = unsafe { &(*(&layout as *const TestLayout as *const AudioChannelLayout)) };
assert_eq!(
audiounit_convert_channel_layout(layout_ref),
*expected_layout
);
}
}
// get_preferred_channel_layout
// ------------------------------------
// TODO: Should it be prevented ? The AudioUnitElement is for output only.