Skip to content

Commit 91882e2

Browse files
committed
Remember input mute state after reinit
1 parent 32f71e6 commit 91882e2

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
@@ -285,7 +285,26 @@ fn get_volume(unit: AudioUnit) -> Result<f32> {
285285

286286
fn set_input_mute(unit: AudioUnit, mute: bool) -> Result<()> {
287287
assert!(!unit.is_null());
288-
let mute: UInt32 = mute.into();
288+
let mute: u32 = mute.into();
289+
let mut old_mute: u32 = 0;
290+
let r = audio_unit_get_property(
291+
unit,
292+
kAUVoiceIOProperty_MuteOutput,
293+
kAudioUnitScope_Global,
294+
AU_IN_BUS,
295+
&mut old_mute,
296+
&mut mem::size_of::<u32>(),
297+
);
298+
if r != NO_ERR {
299+
cubeb_log!(
300+
"AudioUnitGetProperty/kAUVoiceIOProperty_MuteOutput rv={}",
301+
r
302+
);
303+
return Err(Error::error());
304+
}
305+
if old_mute == mute {
306+
return Ok(());
307+
}
289308
let r = audio_unit_set_property(
290309
unit,
291310
kAUVoiceIOProperty_MuteOutput,
@@ -2536,6 +2555,7 @@ struct CoreStreamData<'ctx> {
25362555
input_device: device_info,
25372556
output_device: device_info,
25382557
input_processing_params: InputProcessingParams,
2558+
input_mute: bool,
25392559
input_buffer_manager: Option<BufferManager>,
25402560
// Listeners indicating what system events are monitored.
25412561
default_input_listener: Option<device_property_listener>,
@@ -2575,6 +2595,7 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
25752595
input_device: device_info::default(),
25762596
output_device: device_info::default(),
25772597
input_processing_params: InputProcessingParams::NONE,
2598+
input_mute: false,
25782599
input_buffer_manager: None,
25792600
default_input_listener: None,
25802601
default_output_listener: None,
@@ -2620,6 +2641,7 @@ impl<'ctx> CoreStreamData<'ctx> {
26202641
input_device: in_dev,
26212642
output_device: out_dev,
26222643
input_processing_params: InputProcessingParams::NONE,
2644+
input_mute: false,
26232645
input_buffer_manager: None,
26242646
default_input_listener: None,
26252647
default_output_listener: None,
@@ -3441,6 +3463,18 @@ impl<'ctx> CoreStreamData<'ctx> {
34413463
);
34423464
}
34433465

3466+
// Always try to remember the applied input mute state. If it cannot be applied
3467+
// to the new device pair, we notify the client of an error and it will have to
3468+
// open a new stream.
3469+
if let Err(r) = set_input_mute(self.input_unit, self.input_mute) {
3470+
cubeb_log!(
3471+
"({:p}) Failed to set mute state of voiceprocessing. Error: {}",
3472+
self.stm_ptr,
3473+
r
3474+
);
3475+
return Err(r);
3476+
}
3477+
34443478
// Always try to remember the applied input processing params. If they cannot
34453479
// be applied in the new device pair, we notify the client of an error and it
34463480
// will have to open a new stream.
@@ -4287,6 +4321,7 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
42874321
self as *const AudioUnitStream,
42884322
mute
42894323
);
4324+
self.core_stream_data.input_mute = mute;
42904325
Ok(())
42914326
}
42924327
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)