in src/backend/mod.rs [1491:1601]
fn set_buffer_size_sync(unit: AudioUnit, devtype: DeviceType, frames: u32) -> Result<()> {
let current_frames = get_buffer_size(unit, devtype).map_err(|e| {
cubeb_log!(
"Cannot get buffer size of AudioUnit {:?} for {:?}. Error: {}",
unit,
devtype,
e
);
Error::error()
})?;
if frames == current_frames {
cubeb_log!(
"The buffer frame size of AudioUnit {:?} for {:?} is already {}",
unit,
devtype,
frames
);
return Ok(());
}
let waiting_time = Duration::from_millis(100);
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let mut pair2 = pair.clone();
let pair_ptr = &mut pair2;
assert_eq!(
audio_unit_add_property_listener(
unit,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
pair_ptr,
),
NO_ERR
);
let _teardown = finally(|| {
assert_eq!(
audio_unit_remove_property_listener_with_user_data(
unit,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
pair_ptr,
),
NO_ERR
);
});
set_buffer_size(unit, devtype, frames).map_err(|e| {
cubeb_log!(
"Failed to set buffer size for AudioUnit {:?} for {:?}. Error: {}",
unit,
devtype,
e
);
Error::error()
})?;
let (lock, cvar) = &*pair;
let changed = lock.lock().unwrap();
if !*changed {
let (chg, timeout_res) = cvar.wait_timeout(changed, waiting_time).unwrap();
if timeout_res.timed_out() {
cubeb_log!(
"Timed out for waiting the buffer frame size setting of AudioUnit {:?} for {:?}",
unit,
devtype
);
}
if !*chg {
return Err(Error::error());
}
}
let new_frames = get_buffer_size(unit, devtype).map_err(|e| {
cubeb_log!(
"Cannot get new buffer size of AudioUnit {:?} for {:?}. Error: {}",
unit,
devtype,
e
);
Error::error()
})?;
cubeb_log!(
"The new buffer frames size of AudioUnit {:?} for {:?} is {}",
unit,
devtype,
new_frames
);
extern "C" fn buffer_size_changed_callback(
in_client_data: *mut c_void,
_in_unit: AudioUnit,
in_property_id: AudioUnitPropertyID,
in_scope: AudioUnitScope,
in_element: AudioUnitElement,
) {
if in_scope == 0 {
// filter out the callback for global scope.
return;
}
assert!(in_element == AU_IN_BUS || in_element == AU_OUT_BUS);
assert_eq!(in_property_id, kAudioDevicePropertyBufferFrameSize);
let pair = unsafe { &mut *(in_client_data as *mut Arc<(Mutex<bool>, Condvar)>) };
let (lock, cvar) = &**pair;
let mut changed = lock.lock().unwrap();
*changed = true;
cvar.notify_one();
}
Ok(())
}