Bug 1762036 - mach vendor rust r=cubeb-reviewers,kinetik

Depends on D142363

Differential Revision: https://phabricator.services.mozilla.com/D142364
This commit is contained in:
Chun-Min Chang 2022-03-29 23:01:49 +00:00
Родитель 89ecc5bcda
Коммит cc7684c67d
9 изменённых файлов: 188 добавлений и 153 удалений

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

@ -35,7 +35,7 @@ rev = "df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
[source."https://github.com/mozilla/cubeb-coreaudio-rs"]
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
replace-with = "vendored-sources"
rev = "e012b2151fb6f0ffd50e91baa7756e77a3c416d9"
rev = "39f7e696c11ff45503b50a49a36cd9f39900c27b"
[source."https://github.com/mozilla/audioipc-2"]
git = "https://github.com/mozilla/audioipc-2"

4
Cargo.lock сгенерированный
Просмотреть файл

@ -844,7 +844,7 @@ dependencies = [
[[package]]
name = "coreaudio-sys-utils"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=e012b2151fb6f0ffd50e91baa7756e77a3c416d9#e012b2151fb6f0ffd50e91baa7756e77a3c416d9"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=39f7e696c11ff45503b50a49a36cd9f39900c27b#39f7e696c11ff45503b50a49a36cd9f39900c27b"
dependencies = [
"core-foundation-sys",
"coreaudio-sys",
@ -1145,7 +1145,7 @@ dependencies = [
[[package]]
name = "cubeb-coreaudio"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=e012b2151fb6f0ffd50e91baa7756e77a3c416d9#e012b2151fb6f0ffd50e91baa7756e77a3c416d9"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=39f7e696c11ff45503b50a49a36cd9f39900c27b#39f7e696c11ff45503b50a49a36cd9f39900c27b"
dependencies = [
"atomic",
"audio-mixer",

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

@ -1 +1 @@
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"4671b9a0fbf47773cf01e40592ac5b5fe5cd93722f425f249e6c8b432ce3871c","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"cac9a7d588c2be0efa842c15d24c8cf0573bc9f9d73011662ba764dc9f6245e8","run_sanitizers.sh":"8828c73439dfd540cd21fc713c4a1011ec05baca6f282f285743f310ace39563","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"6faa5ed4f4ab378fd452105a655cd64d2459edec0cf9b3d70375df22cd79c7e8","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"12490043d978d3902927e739cf33905a3c756888a8ff991c2bae4c3792db02fd","src/backend/device_property.rs":"2a63837b98b9b6bfb314b4aa6dce919412b71e13e18c7b8f3477aa1482f70b29","src/backend/mixer.rs":"949c34927ba72b3365bc733a63b2f7950aef707ee08363f97242a4de6b7d4818","src/backend/mod.rs":"a4ea99bb92e42471db44801cec83833fa17c1b10bb606366e3cfdadaff4325dd","src/backend/resampler.rs":"8641c672d00f77be287d64f6cd4a2b2cd36f8630e2ded1eff6b39834b1b7ddc3","src/backend/tests/aggregate_device.rs":"d0b863fb67d3533501b3266f9fa944ec872efb02a457728b2fe7e92c47abb261","src/backend/tests/api.rs":"a6cd4e7c89be3fa820402714bbd1d792404fe2915928f70d626f887c9e2d7685","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"97555244a8081251f1447c6a677609d1e91f33c9c0f4fb3f8a4082005c68ae0c","src/backend/tests/device_property.rs":"373f76d3bee83b263db3f02be3b94b408bdf852d84e4b5153273fda34b11a374","src/backend/tests/interfaces.rs":"b48d646b6ea06ca1bf7ce4b0ada59a164bc094e40b0cd66bb63b269f9032b022","src/backend/tests/manual.rs":"8d485a6666a3f4518b03e39dab80bf2acfd760af2d2f43bad99023cb135b38ca","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"f9e1883660d6146b6e5075806561f5f689810e25c5e7764dfd28c9b939821a49","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"38f78f79758d43ca1b8ec41dd4b918c72eaacc4da7e94cf3b2629ba621497e55","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"e79e442241c5346737e7d52a9a7a1f824d2657855e8c44b42840f85956d8bfe7"},"package":null}
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"4671b9a0fbf47773cf01e40592ac5b5fe5cd93722f425f249e6c8b432ce3871c","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"cac9a7d588c2be0efa842c15d24c8cf0573bc9f9d73011662ba764dc9f6245e8","run_sanitizers.sh":"8828c73439dfd540cd21fc713c4a1011ec05baca6f282f285743f310ace39563","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"e822b4496e2ea5c6e1a288c6e92f57e598abf67cb0bdff813f859d57c63be5f9","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"12490043d978d3902927e739cf33905a3c756888a8ff991c2bae4c3792db02fd","src/backend/device_property.rs":"2a63837b98b9b6bfb314b4aa6dce919412b71e13e18c7b8f3477aa1482f70b29","src/backend/mixer.rs":"949c34927ba72b3365bc733a63b2f7950aef707ee08363f97242a4de6b7d4818","src/backend/mod.rs":"922d09452d9900b2578683cf47389d824d29bcb8a222f194f0d69cfbb1d28f76","src/backend/resampler.rs":"8641c672d00f77be287d64f6cd4a2b2cd36f8630e2ded1eff6b39834b1b7ddc3","src/backend/tests/aggregate_device.rs":"7542cbb1c82398d00a5cba5b335842c517af2cda887946ebb5aaf512fd06b527","src/backend/tests/api.rs":"6eafca24d61729cad108b34c01e339130f9c479ebbe1026dc9c65778c1d9cfe0","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"97555244a8081251f1447c6a677609d1e91f33c9c0f4fb3f8a4082005c68ae0c","src/backend/tests/device_property.rs":"373f76d3bee83b263db3f02be3b94b408bdf852d84e4b5153273fda34b11a374","src/backend/tests/interfaces.rs":"b48d646b6ea06ca1bf7ce4b0ada59a164bc094e40b0cd66bb63b269f9032b022","src/backend/tests/manual.rs":"8d485a6666a3f4518b03e39dab80bf2acfd760af2d2f43bad99023cb135b38ca","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"f9e1883660d6146b6e5075806561f5f689810e25c5e7764dfd28c9b939821a49","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"3c430e519c0e7a17dda6b57c110fab725a846da39606fd99274bad20a637cf35","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}

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

@ -78,7 +78,7 @@ impl AggregateDevice {
});
Self::set_sub_devices_sync(device_id, input_id, output_id)?;
Self::set_master_device(device_id)?;
Self::set_master_device(device_id, output_id)?;
Self::activate_clock_drift_compensation(device_id)?;
Self::workaround_for_airpod(device_id, input_id, output_id)?;
@ -466,18 +466,27 @@ impl AggregateDevice {
}
}
pub fn set_master_device(device_id: AudioDeviceID) -> std::result::Result<(), Error> {
pub fn set_master_device(
device_id: AudioDeviceID,
primary_id: AudioDeviceID,
) -> std::result::Result<(), Error> {
assert_ne!(device_id, kAudioObjectUnknown);
assert_ne!(primary_id, kAudioObjectUnknown);
cubeb_log!(
"Set master device of the aggregate device {} to device {}",
device_id,
primary_id
);
let address = AudioObjectPropertyAddress {
mSelector: kAudioAggregateDevicePropertyMasterSubDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster,
};
// Master become the 1st output sub device
let output_device_id = audiounit_get_default_device_id(DeviceType::OUTPUT);
assert_ne!(output_device_id, kAudioObjectUnknown);
let output_sub_devices = Self::get_sub_devices(output_device_id)?;
// Master become the 1st sub device of the primary device
let output_sub_devices = Self::get_sub_devices(primary_id)?;
assert!(!output_sub_devices.is_empty());
let master_sub_device_uid = get_device_global_uid(output_sub_devices[0]).unwrap();
let master_sub_device = master_sub_device_uid.get_raw();

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

@ -189,31 +189,22 @@ fn clamp_latency(latency_frames: u32) -> u32 {
)
}
fn create_device_info(id: AudioDeviceID, devtype: DeviceType) -> Result<device_info> {
assert_ne!(id, kAudioObjectSystemObject);
fn create_device_info(devid: AudioDeviceID, devtype: DeviceType) -> Option<device_info> {
assert_ne!(devid, kAudioObjectSystemObject);
let mut info = device_info {
id,
flags: match devtype {
DeviceType::INPUT => device_flags::DEV_INPUT,
DeviceType::OUTPUT => device_flags::DEV_OUTPUT,
_ => panic!("Only accept input or output type"),
},
let mut flags = match devtype {
DeviceType::INPUT => device_flags::DEV_INPUT,
DeviceType::OUTPUT => device_flags::DEV_OUTPUT,
_ => panic!("Only accept input or output type"),
};
let default_device_id = audiounit_get_default_device_id(devtype);
if default_device_id == kAudioObjectUnknown {
cubeb_log!("Could not find default audio device for {:?}", devtype);
return Err(Error::error());
if devid == kAudioObjectUnknown {
cubeb_log!("Use the system default device");
flags |= device_flags::DEV_SELECTED_DEFAULT;
get_default_device(devtype).map(|id| device_info { id, flags })
} else {
Some(device_info { id: devid, flags })
}
if id == kAudioObjectUnknown {
info.id = default_device_id;
cubeb_log!("Creating a default device info.");
info.flags |= device_flags::DEV_SELECTED_DEFAULT;
}
Ok(info)
}
fn create_stream_description(stream_params: &StreamParams) -> Result<AudioStreamBasicDescription> {
@ -443,6 +434,12 @@ extern "C" fn audiounit_input_callback(
ptr::null_mut(),
0,
);
if outframes < 0 {
stm.stopped.store(true, Ordering::SeqCst);
stm.core_stream_data.stop_audiounits();
stm.notify_state_changed(State::Error);
return handle;
}
if outframes < total_input_frames {
stm.draining.store(true, Ordering::SeqCst);
}
@ -768,7 +765,21 @@ extern "C" fn audiounit_property_listener_callback(
NO_ERR
}
fn audiounit_get_default_device_id(devtype: DeviceType) -> AudioObjectID {
fn get_default_device(devtype: DeviceType) -> Option<AudioObjectID> {
match get_default_device_id(devtype) {
Err(e) => {
cubeb_log!("Cannot get default {:?} device. Error: {}", devtype, e);
None
}
Ok(id) if id == kAudioObjectUnknown => {
cubeb_log!("Get an invalid default {:?} device: {}", devtype, id);
None
}
Ok(id) => Some(id),
}
}
fn get_default_device_id(devtype: DeviceType) -> std::result::Result<AudioObjectID, OSStatus> {
let address = get_property_address(
match devtype {
DeviceType::INPUT => Property::HardwareDefaultInputDevice,
@ -780,13 +791,13 @@ fn audiounit_get_default_device_id(devtype: DeviceType) -> AudioObjectID {
let mut devid: AudioDeviceID = kAudioObjectUnknown;
let mut size = mem::size_of::<AudioDeviceID>();
if audio_object_get_property_data(kAudioObjectSystemObject, &address, &mut size, &mut devid)
!= NO_ERR
{
return kAudioObjectUnknown;
let status =
audio_object_get_property_data(kAudioObjectSystemObject, &address, &mut size, &mut devid);
if status == NO_ERR {
Ok(devid)
} else {
Err(status)
}
devid
}
fn audiounit_convert_channel_layout(layout: &AudioChannelLayout) -> Vec<mixer::Channel> {
@ -1232,23 +1243,21 @@ fn convert_uint32_into_string(data: u32) -> CString {
CString::new(buffer).unwrap_or(empty)
}
fn audiounit_get_default_datasource_string(devtype: DeviceType) -> Result<CString> {
let id = audiounit_get_default_device_id(devtype);
if id == kAudioObjectUnknown {
return Err(Error::error());
}
let data = get_device_source(id, devtype).unwrap_or(0);
fn get_device_source_string(
id: AudioDeviceID,
devtype: DeviceType,
) -> std::result::Result<CString, OSStatus> {
let data = get_device_source(id, devtype)?;
Ok(convert_uint32_into_string(data))
}
fn get_channel_count(devid: AudioObjectID, devtype: DeviceType) -> Result<u32> {
fn get_channel_count(
devid: AudioObjectID,
devtype: DeviceType,
) -> std::result::Result<u32, OSStatus> {
assert_ne!(devid, kAudioObjectUnknown);
let buffers = get_device_stream_configuration(devid, devtype).map_err(|e| {
cubeb_log!("Cannot get the stream configuration. Error: {}", e);
Error::error()
})?;
let buffers = get_device_stream_configuration(devid, devtype)?;
let mut count = 0;
for buffer in buffers {
count += buffer.mNumberChannels;
@ -1411,7 +1420,10 @@ fn create_cubeb_device_info(
devid: AudioObjectID,
devtype: DeviceType,
) -> Result<ffi::cubeb_device_info> {
let channels = get_channel_count(devid, devtype)?;
let channels = get_channel_count(devid, devtype).map_err(|e| {
cubeb_log!("Cannot get the channel count. Error: {}", e);
Error::error()
})?;
if channels == 0 {
// Invalid type for this device.
return Err(Error::error());
@ -1493,10 +1505,9 @@ fn create_cubeb_device_info(
};
dev_info.state = ffi::CUBEB_DEVICE_STATE_ENABLED;
dev_info.preferred = if devid == audiounit_get_default_device_id(devtype) {
ffi::CUBEB_DEVICE_PREF_ALL
} else {
ffi::CUBEB_DEVICE_PREF_NONE
dev_info.preferred = match get_default_device(devtype) {
Some(id) if id == devid => ffi::CUBEB_DEVICE_PREF_ALL,
_ => ffi::CUBEB_DEVICE_PREF_NONE,
};
dev_info.format = ffi::CUBEB_DEVICE_FMT_ALL;
@ -1960,19 +1971,17 @@ impl ContextOps for AudioUnitContext {
}
#[cfg(not(target_os = "ios"))]
fn max_channel_count(&mut self) -> Result<u32> {
let device = audiounit_get_default_device_id(DeviceType::OUTPUT);
if device == kAudioObjectUnknown {
return Err(Error::error());
}
let format = get_device_stream_format(device, DeviceType::OUTPUT).map_err(|e| {
cubeb_log!(
"Cannot get the stream format of the default output device. Error: {}",
e
);
let device = match get_default_device(DeviceType::OUTPUT) {
None => {
cubeb_log!("Could not get default output device");
return Err(Error::error());
}
Some(id) => id,
};
get_channel_count(device, DeviceType::OUTPUT).map_err(|e| {
cubeb_log!("Cannot get the channel count. Error: {}", e);
Error::error()
})?;
Ok(format.mChannelsPerFrame)
})
}
#[cfg(target_os = "ios")]
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
@ -1980,11 +1989,13 @@ impl ContextOps for AudioUnitContext {
}
#[cfg(not(target_os = "ios"))]
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
let device = audiounit_get_default_device_id(DeviceType::OUTPUT);
if device == kAudioObjectUnknown {
cubeb_log!("Could not get default output device id.");
return Err(Error::error());
}
let device = match get_default_device(DeviceType::OUTPUT) {
None => {
cubeb_log!("Could not get default output device");
return Err(Error::error());
}
Some(id) => id,
};
let range =
get_device_buffer_frame_size_range(device, DeviceType::OUTPUT).map_err(|e| {
@ -2000,10 +2011,13 @@ impl ContextOps for AudioUnitContext {
}
#[cfg(not(target_os = "ios"))]
fn preferred_sample_rate(&mut self) -> Result<u32> {
let device = audiounit_get_default_device_id(DeviceType::OUTPUT);
if device == kAudioObjectUnknown {
return Err(Error::error());
}
let device = match get_default_device(DeviceType::OUTPUT) {
None => {
cubeb_log!("Could not get default output device");
return Err(Error::error());
}
Some(id) => id,
};
let rate = get_device_sample_rate(device, DeviceType::OUTPUT).map_err(|e| {
cubeb_log!(
"Cannot get the sample rate of the default output device. Error: {}",
@ -2091,11 +2105,14 @@ impl ContextOps for AudioUnitContext {
}
let in_stm_settings = if let Some(params) = input_stream_params {
let in_device = create_device_info(input_device as AudioDeviceID, DeviceType::INPUT)
.map_err(|e| {
cubeb_log!("Fail to create device info for input.");
e
})?;
let in_device =
match create_device_info(input_device as AudioDeviceID, DeviceType::INPUT) {
None => {
cubeb_log!("Fail to create device info for input");
return Err(Error::error());
}
Some(d) => d,
};
let stm_params = StreamParams::from(unsafe { *params.as_ptr() });
Some((stm_params, in_device))
} else {
@ -2103,11 +2120,14 @@ impl ContextOps for AudioUnitContext {
};
let out_stm_settings = if let Some(params) = output_stream_params {
let out_device = create_device_info(output_device as AudioDeviceID, DeviceType::OUTPUT)
.map_err(|e| {
cubeb_log!("Fail to create device info for output.");
e
})?;
let out_device =
match create_device_info(output_device as AudioDeviceID, DeviceType::OUTPUT) {
None => {
cubeb_log!("Fail to create device info for output");
return Err(Error::error());
}
Some(d) => d,
};
let stm_params = StreamParams::from(unsafe { *params.as_ptr() });
Some((stm_params, out_device))
} else {
@ -3294,16 +3314,16 @@ impl<'ctx> AudioUnitStream<'ctx> {
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
self.core_stream_data.output_device = create_device_info(kAudioObjectUnknown, DeviceType::OUTPUT).map_err(|e| {
self.core_stream_data.output_device.id = get_default_device_id(DeviceType::OUTPUT).map_err(|e| {
cubeb_log!(
"({:p}) Create output device info failed. This can happen when last media device is unplugged",
self.core_stream_data.stm_ptr
"({:p}) Cannot get default output device. Error: {}. This can happen when last media device is unplugged",
self.core_stream_data.stm_ptr, e
);
e
Error::error()
})?;
}
// Likewise, for the input seid
// Likewise, for the input side
if self.core_stream_data.has_input()
&& self
.core_stream_data
@ -3311,12 +3331,12 @@ impl<'ctx> AudioUnitStream<'ctx> {
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
self.core_stream_data.input_device = create_device_info(kAudioObjectUnknown, DeviceType::INPUT).map_err(|e| {
self.core_stream_data.input_device.id = get_default_device_id(DeviceType::INPUT).map_err(|e| {
cubeb_log!(
"({:p}) Create input device info failed. This can happen when last media device is unplugged",
self.core_stream_data.stm_ptr
"({:p}) Cannot get default input device. Error: {}. This can happen when last media device is unplugged",
self.core_stream_data.stm_ptr, e
);
e
Error::error()
})?;
}
@ -3593,18 +3613,41 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
}
#[cfg(not(target_os = "ios"))]
fn current_device(&mut self) -> Result<&DeviceRef> {
let input_name = audiounit_get_default_datasource_string(DeviceType::INPUT);
let output_name = audiounit_get_default_datasource_string(DeviceType::OUTPUT);
if input_name.is_err() && output_name.is_err() {
return Err(Error::error());
}
let output_device = match get_default_device(DeviceType::OUTPUT) {
None => {
cubeb_log!("Could not get default output device");
return Err(Error::error());
}
Some(id) => id,
};
let output_name =
get_device_source_string(output_device, DeviceType::OUTPUT).map_err(|e| {
cubeb_log!(
"Could not get device source string for default output device. Error: {}",
e
);
Error::error()
})?;
let input_device = match get_default_device(DeviceType::INPUT) {
None => {
cubeb_log!("Could not get default input device");
return Err(Error::error());
}
Some(id) => id,
};
let input_name =
get_device_source_string(input_device, DeviceType::INPUT).map_err(|e| {
cubeb_log!(
"Could not get device source string for default input device. Error: {}",
e
);
Error::error()
})?;
let mut device: Box<ffi::cubeb_device> = Box::new(ffi::cubeb_device::default());
let input_name = input_name.unwrap_or_default();
device.input_name = input_name.into_raw();
let output_name = output_name.unwrap_or_default();
device.output_name = output_name.into_raw();
Ok(unsafe { DeviceRef::from_ptr(Box::into_raw(device)) })

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

@ -66,7 +66,7 @@ fn test_aggregate_get_sub_devices_for_a_unknown_device() {
#[test]
#[should_panic]
fn test_aggregate_set_master_device_for_an_unknown_aggregate_device() {
assert!(AggregateDevice::set_master_device(kAudioObjectUnknown).is_err());
assert!(AggregateDevice::set_master_device(kAudioObjectUnknown, kAudioObjectUnknown).is_err());
}
// AggregateDevice::activate_clock_drift_compensation
@ -243,10 +243,9 @@ fn test_aggregate_set_master_device() {
let plugin = AggregateDevice::get_system_plugin_id().unwrap();
let device = AggregateDevice::create_blank_device_sync(plugin).unwrap();
assert!(AggregateDevice::set_sub_devices_sync(device, input_device, output_device).is_ok());
assert!(AggregateDevice::set_master_device(device).is_ok());
assert!(AggregateDevice::set_master_device(device, output_device).is_ok());
// Check if master is set to the first sub device of the default output device.
// TODO: What if the output device in the aggregate device is not the default output device?
let first_output_sub_device_uid =
get_device_uid(AggregateDevice::get_sub_devices(device).unwrap()[0]);
let master_device_uid = test_get_master_device(device);
@ -266,7 +265,7 @@ fn test_aggregate_set_master_device_for_a_blank_aggregate_device() {
let plugin = AggregateDevice::get_system_plugin_id().unwrap();
let device = AggregateDevice::create_blank_device_sync(plugin).unwrap();
assert!(AggregateDevice::set_master_device(device).is_ok());
assert!(AggregateDevice::set_master_device(device, output_device.unwrap()).is_ok());
// TODO: it's really weird the aggregate device actually own nothing
// but its master device can be set successfully!
@ -301,7 +300,7 @@ fn test_aggregate_activate_clock_drift_compensation() {
let plugin = AggregateDevice::get_system_plugin_id().unwrap();
let device = AggregateDevice::create_blank_device_sync(plugin).unwrap();
assert!(AggregateDevice::set_sub_devices_sync(device, input_device, output_device).is_ok());
assert!(AggregateDevice::set_master_device(device).is_ok());
assert!(AggregateDevice::set_master_device(device, output_device).is_ok());
assert!(AggregateDevice::activate_clock_drift_compensation(device).is_ok());
// Check the compensations.

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

@ -2,8 +2,8 @@ use super::utils::{
test_audiounit_get_buffer_frame_size, test_audiounit_scope_is_enabled, test_create_audiounit,
test_device_channels_in_scope, test_device_in_scope, test_get_all_devices,
test_get_default_audiounit, test_get_default_device, test_get_default_raw_stream,
test_get_default_source_name, test_get_devices_in_scope, test_get_raw_context,
ComponentSubType, DeviceFilter, PropertyScope, Scope,
test_get_devices_in_scope, test_get_raw_context, test_get_source_name, ComponentSubType,
DeviceFilter, PropertyScope, Scope,
};
use super::*;
@ -321,14 +321,14 @@ fn test_remove_listener_unknown_device() {
fn test_get_default_device_id() {
if test_get_default_device(Scope::Input).is_some() {
assert_ne!(
audiounit_get_default_device_id(DeviceType::INPUT),
get_default_device_id(DeviceType::INPUT).unwrap(),
kAudioObjectUnknown,
);
}
if test_get_default_device(Scope::Output).is_some() {
assert_ne!(
audiounit_get_default_device_id(DeviceType::OUTPUT),
get_default_device_id(DeviceType::OUTPUT).unwrap(),
kAudioObjectUnknown,
);
}
@ -337,19 +337,13 @@ fn test_get_default_device_id() {
#[test]
#[should_panic]
fn test_get_default_device_id_with_unknown_type() {
assert_eq!(
audiounit_get_default_device_id(DeviceType::UNKNOWN),
kAudioObjectUnknown,
);
assert!(get_default_device_id(DeviceType::UNKNOWN).is_err());
}
#[test]
#[should_panic]
fn test_get_default_device_id_with_inout_type() {
assert_eq!(
audiounit_get_default_device_id(DeviceType::INPUT | DeviceType::OUTPUT),
kAudioObjectUnknown,
);
assert!(get_default_device_id(DeviceType::INPUT | DeviceType::OUTPUT).is_err());
}
// convert_channel_layout
@ -982,22 +976,26 @@ fn test_convert_uint32_into_string() {
assert_eq!(data_string, CString::new("RUST").unwrap());
}
// get_default_datasource_string
// get_device_source_string
// ------------------------------------
#[test]
fn test_get_default_device_name() {
test_get_default_device_name_in_scope(Scope::Input);
test_get_default_device_name_in_scope(Scope::Output);
fn test_get_device_source_string() {
test_get_source_name_in_scope(Scope::Input);
test_get_source_name_in_scope(Scope::Output);
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);
fn test_get_source_name_in_scope(scope: Scope) {
if let Some(dev) = test_get_default_device(scope.clone()) {
if let Some(name) = test_get_source_name(dev, scope.clone()) {
let source = get_device_source_string(dev, scope.into())
.unwrap()
.into_string()
.unwrap();
assert_eq!(name, source);
} else {
println!("No source name for default {:?} device ", scope);
}
} else {
println!("No source name for {:?}", scope);
println!("No default {:?} device", scope);
}
}
}
@ -1052,10 +1050,7 @@ fn test_get_channel_count_of_output_for_a_input_only_deivce() {
#[test]
#[should_panic]
fn test_get_channel_count_of_unknown_device() {
assert_eq!(
get_channel_count(kAudioObjectUnknown, DeviceType::OUTPUT).unwrap_err(),
Error::error()
);
assert!(get_channel_count(kAudioObjectUnknown, DeviceType::OUTPUT).is_err());
}
#[test]
@ -1066,9 +1061,8 @@ fn test_get_channel_count_of_inout_type() {
fn test_channel_count(scope: Scope) {
if let Some(device) = test_get_default_device(scope.clone()) {
assert_eq!(
// Get a kAudioHardwareUnknownPropertyError in get_channel_count actually.
get_channel_count(device, DeviceType::INPUT | DeviceType::OUTPUT).unwrap_err(),
Error::error()
kAudioHardwareUnknownPropertyError as OSStatus
);
} else {
println!("No device for {:?}.", scope);
@ -1084,10 +1078,7 @@ fn test_get_channel_count_of_unknwon_type() {
fn test_channel_count(scope: Scope) {
if let Some(device) = test_get_default_device(scope.clone()) {
assert_eq!(
get_channel_count(device, DeviceType::UNKNOWN).unwrap_err(),
Error::error()
);
assert!(get_channel_count(device, DeviceType::UNKNOWN).is_err());
} else {
panic!("Panic by default: No device for {:?}.", scope);
}

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

@ -188,21 +188,15 @@ fn test_enable_audiounit_in_scope(
}
}
pub fn test_get_default_source_name(scope: Scope) -> Option<String> {
if let Some(source) = test_get_default_source_data(scope) {
pub fn test_get_source_name(device: AudioObjectID, scope: Scope) -> Option<String> {
if let Some(source) = test_get_source_data(device, scope) {
Some(u32_to_string(source))
} else {
None
}
}
pub fn test_get_default_source_data(scope: Scope) -> Option<u32> {
let device = test_get_default_device(scope.clone());
if device.is_none() {
return None;
}
let device = device.unwrap();
pub fn test_get_source_data(device: AudioObjectID, scope: Scope) -> Option<u32> {
let address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyDataSource,
mScope: match scope {

3
third_party/rust/cubeb-coreaudio/todo.md поставляемый
Просмотреть файл

@ -77,8 +77,6 @@ and create a new one. It's easier than the current implementation.
### Setting master device
- We always set the master device to the first subdevice of the default output device
but the output device (forming the aggregate device) may not be the default output device
- Check if the first subdevice of the default output device is in the list of
sub devices list of the aggregate device
- Check the `name: CFStringRef` of the master device is not `NULL`
@ -102,6 +100,7 @@ and create a new one. It's easier than the current implementation.
## [Cubeb Interface][cubeb-rs]
- `current_device` should be the in-use device of the current stream rather than default input and output device.
- Implement `From` trait for `enum cubeb_device_type` so we can use `devtype.into()` to get `ffi::CUBEB_DEVICE_TYPE_*`.
- Implement `to_owned` in [`StreamParamsRef`][cubeb-rs-stmparamsref]
- Check the passed parameters like what [cubeb.c does][cubeb-stm-check]!