in src/backend/mod.rs [4713:4801]
fn reinit(&mut self) -> Result<()> {
self.queue.debug_assert_is_current();
// Call stop_audiounits to avoid potential data race. If there is a running data callback,
// which locks a mutex inside CoreAudio framework, then this call will block the current
// thread until the callback is finished since this call asks to lock a mutex inside
// CoreAudio framework that is used by the data callback.
if !self.stopped.load(Ordering::SeqCst) {
self.core_stream_data.stop_audiounits();
}
if self.stopped.load(Ordering::SeqCst) {
// Something stopped the stream, reinit on next start
self.delayed_reinit = true;
return Ok(());
}
debug_assert!(
!self.core_stream_data.input_unit.is_null()
|| !self.core_stream_data.output_unit.is_null()
);
let vol_rv = if self.core_stream_data.output_unit.is_null() {
Err(Error::error())
} else {
get_volume(self.core_stream_data.output_unit)
};
self.core_stream_data.close();
// Use the new default device if this stream was set to follow the output device.
if self.core_stream_data.has_output()
&& self
.core_stream_data
.output_device
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
cubeb_log!("Using new default output device");
self.core_stream_data.output_device =
match create_device_info(kAudioObjectUnknown, DeviceType::OUTPUT) {
None => {
cubeb_log!("Fail to create device info for output");
return Err(Error::error());
}
Some(d) => d,
};
}
// Likewise, for the input side
if self.core_stream_data.has_input()
&& self
.core_stream_data
.input_device
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
cubeb_log!("Using new default input device");
self.core_stream_data.input_device =
match create_device_info(kAudioObjectUnknown, DeviceType::INPUT) {
None => {
cubeb_log!("Fail to create device info for input");
return Err(Error::error());
}
Some(d) => d,
}
}
cubeb_log!("Reinit: setup");
self.core_stream_data
.setup(&mut self.context.shared_voice_processing_unit)
.inspect_err(|_| {
cubeb_log!("({:p}) Setup failed.", self.core_stream_data.stm_ptr);
})?;
if let Ok(volume) = vol_rv {
set_volume(self.core_stream_data.output_unit, volume);
}
// If the stream was running, start it again.
if !self.stopped.load(Ordering::SeqCst) {
self.core_stream_data.start_audiounits().inspect_err(|_| {
cubeb_log!(
"({:p}) Start audiounit failed.",
self.core_stream_data.stm_ptr
);
})?;
}
Ok(())
}