diff --git a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json index 4a4111f9b0bbc..71b32a4d8de15 100644 --- a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json +++ b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"cf6ebe6d41b022897360866b526d19ba8843aa82ae99a1d28393985576b6a782",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"2698cf87581d8d551ed3ac5875564720ed23d7b788e8d145d4281c8026203cd2","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":"d717e598c96e4911d9494b18382d6bd3a8d5038b7d68d3166ad4336e237a97d8","run_sanitizers.sh":"d6c3cde105ae0759e753cc31cab691eb417c4d0ad68f20da5e87fe0138a0d92f","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"0ab2c09549925e76389f7bc99320a7bd3685c743df91f2f998ba6e4643166944","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"314c3404f1a44f8c23856f96510779e7e64ebb7dde5abe444946c16d04af7c29","src/backend/device_property.rs":"f186017c7b4dc439250e5e3370ec052732907009f378b3ed09fc4770f9b4e4a9","src/backend/mixer.rs":"c7c08cab5ad59c3903c2c5de3839b7a50bb64edbebdb6a50f48b58314a4bbd2b","src/backend/mod.rs":"81a87a667e2abce5f4cc15bf4aad4a40e32008ba9ba2e5448fe86f4fa4c56a41","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"d61ca263bb6fe893b10561a0ba1519f667d91e083ea9c7f732c63cbe09914e12","src/backend/tests/api.rs":"35939515799c0642b5df0fccadd46d6aa0e20372de2d98827dcde24ee3ad8eb1","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"b1b4f7f71de99d07406a8a38dc67e46a43b883d4a845daaf356e72fbe0d5a08b","src/backend/tests/device_property.rs":"ea0be5f8834be494cb33f854ce9d334b5763dc5287f949bcb4bd025d8a8b2d3b","src/backend/tests/interfaces.rs":"cd58614435574444d8a1f039dc201cf371cccacd58efbae8ed8fbff919550d0a","src/backend/tests/manual.rs":"632026f25a003d053ab69ddd1000fba10dfd4a679cb853d98fa83365e33e2b28","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"504613b1b5fa4d67cbb2560cb8d8cef0a4e8929c28b31d9d4695ac5286969f38","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"15d17b5078ad725d429685a4c7898beb58f21f08a7016a743dca4b015f3fc280","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null} +{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"cf6ebe6d41b022897360866b526d19ba8843aa82ae99a1d28393985576b6a782",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"2698cf87581d8d551ed3ac5875564720ed23d7b788e8d145d4281c8026203cd2","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":"d717e598c96e4911d9494b18382d6bd3a8d5038b7d68d3166ad4336e237a97d8","run_sanitizers.sh":"d6c3cde105ae0759e753cc31cab691eb417c4d0ad68f20da5e87fe0138a0d92f","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"0ab2c09549925e76389f7bc99320a7bd3685c743df91f2f998ba6e4643166944","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"314c3404f1a44f8c23856f96510779e7e64ebb7dde5abe444946c16d04af7c29","src/backend/device_property.rs":"f186017c7b4dc439250e5e3370ec052732907009f378b3ed09fc4770f9b4e4a9","src/backend/mixer.rs":"c7c08cab5ad59c3903c2c5de3839b7a50bb64edbebdb6a50f48b58314a4bbd2b","src/backend/mod.rs":"f51e1315488fa13ec908c9f31877aee884b0f40652aaa1d07a416d35ad79fc10","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"d61ca263bb6fe893b10561a0ba1519f667d91e083ea9c7f732c63cbe09914e12","src/backend/tests/api.rs":"35939515799c0642b5df0fccadd46d6aa0e20372de2d98827dcde24ee3ad8eb1","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"b1b4f7f71de99d07406a8a38dc67e46a43b883d4a845daaf356e72fbe0d5a08b","src/backend/tests/device_property.rs":"ea0be5f8834be494cb33f854ce9d334b5763dc5287f949bcb4bd025d8a8b2d3b","src/backend/tests/interfaces.rs":"cd58614435574444d8a1f039dc201cf371cccacd58efbae8ed8fbff919550d0a","src/backend/tests/manual.rs":"632026f25a003d053ab69ddd1000fba10dfd4a679cb853d98fa83365e33e2b28","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"504613b1b5fa4d67cbb2560cb8d8cef0a4e8929c28b31d9d4695ac5286969f38","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"15d17b5078ad725d429685a4c7898beb58f21f08a7016a743dca4b015f3fc280","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null} diff --git a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs index 930a8dfbdea45..1fdb4d436e3c5 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs @@ -327,6 +327,85 @@ fn get_volume(unit: AudioUnit) -> Result { } } +fn set_input_mute(unit: AudioUnit, mute: bool) -> Result<()> { + assert!(!unit.is_null()); + let mute: UInt32 = mute.into(); + let r = audio_unit_set_property( + unit, + kAUVoiceIOProperty_MuteOutput, + kAudioUnitScope_Global, + AU_IN_BUS, + &mute, + mem::size_of::(), + ); + if r == NO_ERR { + Ok(()) + } else { + cubeb_log!( + "AudioUnitSetProperty/kAUVoiceIOProperty_MuteOutput rv={}", + r + ); + Err(Error::error()) + } + +} + +fn set_input_processing_params(unit: AudioUnit, params: InputProcessingParams) -> Result<()> { + assert!(!unit.is_null()); + let aec = params.contains(InputProcessingParams::ECHO_CANCELLATION); + let ns = params.contains(InputProcessingParams::NOISE_SUPPRESSION); + + // We don't use AGC, but keep it here for reference. + // See the comment in supported_input_processing_params. + let agc = params.contains(InputProcessingParams::AUTOMATIC_GAIN_CONTROL); + assert!(!agc); + + // AEC and NS are active as soon as VPIO is not bypassed. + // Therefore the only modes we can explicitly support are {} and {aec, ns}. + + if aec != ns { + // No control to turn on AEC without NS or vice versa. + return Err(Error::error()); + } + + let agc = u32::from(agc); + let r = audio_unit_set_property( + unit, + kAUVoiceIOProperty_VoiceProcessingEnableAGC, + kAudioUnitScope_Global, + AU_IN_BUS, + &agc, + mem::size_of::(), + ); + if r != NO_ERR { + cubeb_log!( + "AudioUnitSetProperty/kAUVoiceIOProperty_VoiceProcessingEnableAGC rv={}", + r + ); + return Err(Error::error()); + } + + let bypass = u32::from(!aec); + let r = audio_unit_set_property( + unit, + kAUVoiceIOProperty_BypassVoiceProcessing, + kAudioUnitScope_Global, + AU_IN_BUS, + &bypass, + mem::size_of::(), + ); + if r != NO_ERR { + cubeb_log!( + "AudioUnitSetProperty/kAUVoiceIOProperty_BypassVoiceProcessing rv={}", + r + ); + return Err(Error::error()); + } + + Ok(()) + +} + fn minimum_resampling_input_frames( input_rate: f64, output_rate: f64, @@ -4748,6 +4827,7 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> { } Ok(self.prev_position) } + #[cfg(target_os = "ios")] fn latency(&mut self) -> Result { Err(not_supported()) @@ -4760,12 +4840,6 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> { fn input_latency(&mut self) -> Result { Err(not_supported()) } - fn set_input_mute(&mut self, _mute: bool) -> Result<()> { - Err(Error::not_supported()) - } - fn set_input_processing_params(&mut self, _params: InputProcessingParams) -> Result<()> { - Err(Error::not_supported()) - } #[cfg(not(target_os = "ios"))] fn input_latency(&mut self) -> Result { let user_rate = self.core_stream_data.input_stream_params.rate(); @@ -4780,7 +4854,9 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> { } else { Err(Error::error()) } + } + fn set_volume(&mut self, volume: f32) -> Result<()> { // Execute set_volume in serial queue to avoid racing with destroy or reinit. let mut result = Err(Error::error()); @@ -4802,50 +4878,76 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> { fn set_name(&mut self, _: &CStr) -> Result<()> { Err(Error::not_supported()) } - #[cfg(target_os = "ios")] fn current_device(&mut self) -> Result<&DeviceRef> { - Err(not_supported()) + Err(Error::not_supported()) + } - #[cfg(not(target_os = "ios"))] - fn current_device(&mut self) -> Result<&DeviceRef> { - 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() - })?; + fn set_input_mute(&mut self, mute: bool) -> Result<()> { + if self.core_stream_data.input_unit.is_null() { + return Err(Error::invalid_parameter()); + } - 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() - })?; + if !self.core_stream_data.using_voice_processing_unit() { + return Err(Error::error()); + } + + // Execute set_input_mute in serial queue to avoid racing with destroy or reinit. + let mut result = Err(Error::error()); + let set = &mut result; + let stream = &self; + self.queue.run_sync(move || { + *set = set_input_mute(stream.core_stream_data.input_unit, mute); + }); + + result?; + + cubeb_log!( + "Cubeb stream ({:p}) set input mute to {}.", + self as *const AudioUnitStream, + mute + ); + Ok(()) + } + + fn set_input_processing_params(&mut self, params: InputProcessingParams) -> Result<()> { + // CUBEB_ERROR_INVALID_PARAMETER if a given param is not supported by + // this backend, or if this stream does not have an input device + if self.core_stream_data.input_unit.is_null() { + return Err(Error::invalid_parameter()); + } + + if self + .context + .supported_input_processing_params() + .unwrap() + .intersection(params) + != params + { + return Err(Error::invalid_parameter()); + } - let mut device: Box = Box::default(); + // CUBEB_ERROR if params could not be applied + // note: only works with VoiceProcessingIO + if !self.core_stream_data.using_voice_processing_unit() { + return Err(Error::error()); + } + + // Execute set_input_processing_params in serial queue to avoid racing with destroy or reinit. + let mut result = Err(Error::error()); + let set = &mut result; + let stream = &self; + self.queue.run_sync(move || { + *set = set_input_processing_params(stream.core_stream_data.input_unit, params); + }); - device.input_name = input_name.into_raw(); - device.output_name = output_name.into_raw(); + result?; - Ok(unsafe { DeviceRef::from_ptr(Box::into_raw(device)) }) + cubeb_log!( + "Cubeb stream ({:p}) set input processing params to {:?}.", + self as *const AudioUnitStream, + params + ); + Ok(()) } #[cfg(target_os = "ios")] fn device_destroy(&mut self, device: &DeviceRef) -> Result<()> { @@ -4884,6 +4986,7 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> { *callback = device_changed_callback; Ok(()) } + } }