Skip to content

Commit 09be421

Browse files
committed
Remember input mute state after reinit
1 parent daf38b7 commit 09be421

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

src/backend/mod.rs

+36-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,26 @@ fn get_volume(unit: AudioUnit) -> Result<f32> {
287287

288288
fn set_input_mute(unit: AudioUnit, mute: bool) -> Result<()> {
289289
assert!(!unit.is_null());
290-
let mute: UInt32 = mute.into();
290+
let mute: u32 = mute.into();
291+
let mut old_mute: u32 = 0;
292+
let r = audio_unit_get_property(
293+
unit,
294+
kAUVoiceIOProperty_MuteOutput,
295+
kAudioUnitScope_Global,
296+
AU_IN_BUS,
297+
&mut old_mute,
298+
&mut mem::size_of::<u32>(),
299+
);
300+
if r != NO_ERR {
301+
cubeb_log!(
302+
"AudioUnitGetProperty/kAUVoiceIOProperty_MuteOutput rv={}",
303+
r
304+
);
305+
return Err(Error::error());
306+
}
307+
if old_mute == mute {
308+
return Ok(());
309+
}
291310
let r = audio_unit_set_property(
292311
unit,
293312
kAUVoiceIOProperty_MuteOutput,
@@ -2547,6 +2566,7 @@ struct CoreStreamData<'ctx> {
25472566
input_device: device_info,
25482567
output_device: device_info,
25492568
input_processing_params: InputProcessingParams,
2569+
input_mute: bool,
25502570
input_buffer_manager: Option<BufferManager>,
25512571
// Listeners indicating what system events are monitored.
25522572
default_input_listener: Option<device_property_listener>,
@@ -2586,6 +2606,7 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
25862606
input_device: device_info::default(),
25872607
output_device: device_info::default(),
25882608
input_processing_params: InputProcessingParams::NONE,
2609+
input_mute: false,
25892610
input_buffer_manager: None,
25902611
default_input_listener: None,
25912612
default_output_listener: None,
@@ -2631,6 +2652,7 @@ impl<'ctx> CoreStreamData<'ctx> {
26312652
input_device: in_dev,
26322653
output_device: out_dev,
26332654
input_processing_params: InputProcessingParams::NONE,
2655+
input_mute: false,
26342656
input_buffer_manager: None,
26352657
default_input_listener: None,
26362658
default_output_listener: None,
@@ -3451,6 +3473,18 @@ impl<'ctx> CoreStreamData<'ctx> {
34513473
);
34523474
}
34533475

3476+
// Always try to remember the applied input mute state. If it cannot be applied
3477+
// to the new device pair, we notify the client of an error and it will have to
3478+
// open a new stream.
3479+
if let Err(r) = set_input_mute(self.input_unit, self.input_mute) {
3480+
cubeb_log!(
3481+
"({:p}) Failed to set mute state of voiceprocessing. Error: {}",
3482+
self.stm_ptr,
3483+
r
3484+
);
3485+
return Err(r);
3486+
}
3487+
34543488
// Always try to remember the applied input processing params. If they cannot
34553489
// be applied in the new device pair, we notify the client of an error and it
34563490
// will have to open a new stream.
@@ -4297,6 +4331,7 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
42974331
self as *const AudioUnitStream,
42984332
mute
42994333
);
4334+
self.core_stream_data.input_mute = mute;
43004335
Ok(())
43014336
}
43024337
fn set_input_processing_params(&mut self, params: InputProcessingParams) -> Result<()> {

src/backend/tests/interfaces.rs

+48
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,54 @@ fn test_ops_duplex_voice_stream_set_input_mute() {
10181018
});
10191019
}
10201020

1021+
#[test]
1022+
fn test_ops_duplex_voice_stream_set_input_mute_before_start() {
1023+
test_default_duplex_voice_stream_operation(
1024+
"duplex voice stream: mute before start",
1025+
|stream| {
1026+
assert_eq!(
1027+
unsafe { OPS.stream_set_input_mute.unwrap()(stream, 1) },
1028+
ffi::CUBEB_OK
1029+
);
1030+
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
1031+
},
1032+
);
1033+
}
1034+
1035+
#[test]
1036+
fn test_ops_duplex_voice_stream_set_input_mute_before_start_with_reinit() {
1037+
test_default_duplex_voice_stream_operation(
1038+
"duplex voice stream: mute before start with reinit",
1039+
|stream| {
1040+
assert_eq!(
1041+
unsafe { OPS.stream_set_input_mute.unwrap()(stream, 1) },
1042+
ffi::CUBEB_OK
1043+
);
1044+
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
1045+
1046+
// Hacky cast, but testing this here was simplest for now.
1047+
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
1048+
stm.reinit_async();
1049+
let queue = stm.queue.clone();
1050+
let mut mute_after_reinit = false;
1051+
queue.run_sync(|| {
1052+
let mut mute: u32 = 0;
1053+
let r = audio_unit_get_property(
1054+
stm.core_stream_data.input_unit,
1055+
kAUVoiceIOProperty_MuteOutput,
1056+
kAudioUnitScope_Global,
1057+
AU_IN_BUS,
1058+
&mut mute,
1059+
&mut mem::size_of::<u32>(),
1060+
);
1061+
assert_eq!(r, NO_ERR);
1062+
mute_after_reinit = mute == 1;
1063+
});
1064+
assert_eq!(mute_after_reinit, true);
1065+
},
1066+
);
1067+
}
1068+
10211069
#[test]
10221070
fn test_ops_duplex_voice_stream_set_input_mute_after_start() {
10231071
test_default_duplex_voice_stream_operation("duplex voice stream: mute after start", |stream| {

0 commit comments

Comments
 (0)