Make set_buffer_size become a member function

This commit is contained in:
Chun-Min Chang 2019-04-22 16:45:08 -07:00
Родитель b6c149edfa
Коммит a5ccfd9eeb
2 изменённых файлов: 114 добавлений и 106 удалений

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

@ -1870,108 +1870,6 @@ extern fn buffer_size_changed_callback(in_client_data: *mut c_void,
}
}
fn audiounit_set_buffer_size(stm: &mut AudioUnitStream, new_size_frames: u32, side: io_side) -> Result<()>
{
// assert_ne!(new_size_frames, 0);
// Surprisingly, it's ok to set `new_size_frames` to zero without getting
// any error. However, the `buffer frames size` won't become 0 even it's
// ok to set it to 0. Maybe we should fix it!
let (au, au_scope, au_element) = if side == io_side::INPUT {
(stm.input_unit, kAudioUnitScope_Output, AU_IN_BUS)
} else {
(stm.output_unit, kAudioUnitScope_Input, AU_OUT_BUS)
};
// TODO: Check au is not null ?
let mut buffer_frames: u32 = 0;
let mut size = mem::size_of_val(&buffer_frames);
let mut r = audio_unit_get_property(au,
kAudioDevicePropertyBufferFrameSize,
au_scope,
au_element,
&mut buffer_frames,
&mut size);
if r != NO_ERR {
cubeb_log!("AudioUnitGetProperty/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
assert_ne!(buffer_frames, 0);
if new_size_frames == buffer_frames {
cubeb_log!("({:p}) No need to update {} buffer size already {} frames", stm as *const AudioUnitStream, side.to_string(), buffer_frames);
return Ok(());
}
r = audio_unit_add_property_listener(au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
stm as *mut AudioUnitStream as *mut c_void);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
*stm.buffer_size_change_state.get_mut() = false;
r = audio_unit_set_property(au,
kAudioDevicePropertyBufferFrameSize,
au_scope,
au_element,
&new_size_frames,
mem::size_of_val(&new_size_frames));
if r != NO_ERR {
cubeb_log!("AudioUnitSetProperty/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
r = audio_unit_remove_property_listener_with_user_data(au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
stm as *mut AudioUnitStream as *mut c_void);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
}
return Err(Error::error());
}
let mut count: u32 = 0;
while !*stm.buffer_size_change_state.get_mut() && count < 30 {
count += 1;
unsafe {
let req = libc::timespec {
tv_sec: 0,
tv_nsec: 100_000_000 // 0.1 sec
};
let mut rem = libc::timespec {
tv_sec: 0,
tv_nsec: 0
};
if libc::nanosleep(&req, &mut rem) < 0 {
cubeb_log!("({:p}) Warning: nanosleep call failed or interrupted. Remaining time {} nano secs", stm as *const AudioUnitStream, rem.tv_nsec);
}
}
cubeb_log!("({:p}) audiounit_set_buffer_size : wait count = {}", stm as *const AudioUnitStream, count);
}
r = audio_unit_remove_property_listener_with_user_data(au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
stm as *mut AudioUnitStream as *mut c_void);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
if !*stm.buffer_size_change_state.get_mut() && count >= 30 {
cubeb_log!("({:p}) Error, did not get buffer size change callback ...", stm as *const AudioUnitStream);
return Err(Error::error());
}
cubeb_log!("({:p}) {} buffer size changed to {} frames.", stm as *const AudioUnitStream, side.to_string(), new_size_frames);
Ok(())
}
fn audiounit_configure_input(stm: &mut AudioUnitStream) -> Result<()>
{
assert!(!stm.input_unit.is_null());
@ -2014,7 +1912,7 @@ fn audiounit_configure_input(stm: &mut AudioUnitStream) -> Result<()>
// set that. Maybe we should fix it!
// Use a temporary variable `latency_frames` to avoid borrowing issue.
let latency_frames = stm.latency_frames;
if let Err(r) = audiounit_set_buffer_size(stm, latency_frames, io_side::INPUT) {
if let Err(r) = stm.set_buffer_size(latency_frames, io_side::INPUT) {
cubeb_log!("({:p}) Error in change input buffer size.", stm as *const AudioUnitStream);
return Err(r);
}
@ -2155,7 +2053,7 @@ fn audiounit_configure_output(stm: &mut AudioUnitStream) -> Result<()>
// set that. Maybe we should fix it!
// Use a temporary variable `latency_frames` to avoid borrowing issue.
let latency_frames = stm.latency_frames;
if let Err(r) = audiounit_set_buffer_size(stm, latency_frames, io_side::OUTPUT) {
if let Err(r) = stm.set_buffer_size(latency_frames, io_side::OUTPUT) {
cubeb_log!("({:p}) Error in change output buffer size.", stm as *const AudioUnitStream);
return Err(r);
}
@ -3810,6 +3708,116 @@ impl<'ctx> AudioUnitStream<'ctx> {
SAFE_MIN_LATENCY_FRAMES)
}
fn set_buffer_size(&mut self, new_size_frames: u32, side: io_side) -> Result<()> {
// assert_ne!(new_size_frames, 0);
// Surprisingly, it's ok to set `new_size_frames` to zero without getting
// any error. However, the `buffer frames size` won't become 0 even it's
// ok to set it to 0. Maybe we should fix it!
let (au, au_scope, au_element) = if side == io_side::INPUT {
(self.input_unit, kAudioUnitScope_Output, AU_IN_BUS)
} else {
(self.output_unit, kAudioUnitScope_Input, AU_OUT_BUS)
};
// TODO: Check au is not null ?
let mut buffer_frames: u32 = 0;
let mut size = mem::size_of_val(&buffer_frames);
let mut r = audio_unit_get_property(
au,
kAudioDevicePropertyBufferFrameSize,
au_scope,
au_element,
&mut buffer_frames,
&mut size
);
if r != NO_ERR {
cubeb_log!("AudioUnitGetProperty/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
assert_ne!(buffer_frames, 0);
if new_size_frames == buffer_frames {
cubeb_log!("({:p}) No need to update {} buffer size already {} frames", self as *const AudioUnitStream, side.to_string(), buffer_frames);
return Ok(());
}
r = audio_unit_add_property_listener(
au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
self as *mut AudioUnitStream as *mut c_void
);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
*self.buffer_size_change_state.get_mut() = false;
r = audio_unit_set_property(
au,
kAudioDevicePropertyBufferFrameSize,
au_scope,
au_element,
&new_size_frames,
mem::size_of_val(&new_size_frames)
);
if r != NO_ERR {
cubeb_log!("AudioUnitSetProperty/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
r = audio_unit_remove_property_listener_with_user_data(
au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
self as *mut AudioUnitStream as *mut c_void
);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
}
return Err(Error::error());
}
let mut count: u32 = 0;
while !*self.buffer_size_change_state.get_mut() && count < 30 {
count += 1;
unsafe {
let req = libc::timespec {
tv_sec: 0,
tv_nsec: 100_000_000 // 0.1 sec
};
let mut rem = libc::timespec {
tv_sec: 0,
tv_nsec: 0
};
if libc::nanosleep(&req, &mut rem) < 0 {
cubeb_log!("({:p}) Warning: nanosleep call failed or interrupted. Remaining time {} nano secs", self as *const AudioUnitStream, rem.tv_nsec);
}
}
cubeb_log!("({:p}) audiounit_set_buffer_size : wait count = {}", self as *const AudioUnitStream, count);
}
r = audio_unit_remove_property_listener_with_user_data(
au,
kAudioDevicePropertyBufferFrameSize,
buffer_size_changed_callback,
self as *mut AudioUnitStream as *mut c_void
);
if r != NO_ERR {
cubeb_log!("AudioUnitAddPropertyListener/{}/kAudioDevicePropertyBufferFrameSize rv={}", side.to_string(), r);
return Err(Error::error());
}
if !*self.buffer_size_change_state.get_mut() && count >= 30 {
cubeb_log!("({:p}) Error, did not get buffer size change callback ...", self as *const AudioUnitStream);
return Err(Error::error());
}
cubeb_log!("({:p}) {} buffer size changed to {} frames.", self as *const AudioUnitStream, side.to_string(), new_size_frames);
Ok(())
}
fn close(&mut self) {
self.mutex.assert_current_thread_owns();

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

@ -1715,7 +1715,7 @@ fn test_set_buffer_size() {
test_audiounit_get_buffer_frame_size(unit, scope.clone(), prop_scope).unwrap();
assert_ne!(buffer_frames, 0);
buffer_frames *= 2;
assert!(audiounit_set_buffer_size(stream, buffer_frames, scope.into()).is_ok());
assert!(stream.set_buffer_size(buffer_frames, scope.into()).is_ok());
});
}
}
@ -1740,7 +1740,7 @@ fn test_set_buffer_size_by_scope_with_null_unit(scope: Scope) {
};
assert!(unit.is_null());
assert_eq!(
audiounit_set_buffer_size(stream, 2048, scope.into()).unwrap_err(),
stream.set_buffer_size(2048, scope.into()).unwrap_err(),
Error::error()
);
});