in src/backend/mod.rs [2786:2917]
fn stream_init(
&mut self,
_stream_name: Option<&CStr>,
input_device: DeviceId,
input_stream_params: Option<&StreamParamsRef>,
output_device: DeviceId,
output_stream_params: Option<&StreamParamsRef>,
latency_frames: u32,
data_callback: ffi::cubeb_data_callback,
state_callback: ffi::cubeb_state_callback,
user_ptr: *mut c_void,
) -> Result<Stream> {
if !input_device.is_null() && input_stream_params.is_none() {
cubeb_log!("Cannot init an input device without input stream params");
return Err(Error::invalid_parameter());
}
if !output_device.is_null() && output_stream_params.is_none() {
cubeb_log!("Cannot init an output device without output stream params");
return Err(Error::invalid_parameter());
}
if input_stream_params.is_none() && output_stream_params.is_none() {
cubeb_log!("Cannot init a stream without any stream params");
return Err(Error::invalid_parameter());
}
if data_callback.is_none() {
cubeb_log!("Cannot init a stream without a data callback");
return Err(Error::invalid_parameter());
}
let in_stm_settings = if let Some(params) = input_stream_params {
let in_device = match self
.serial_queue
.run_sync(|| {
create_device_info(
get_device_from_devid(input_device).unwrap(),
DeviceType::INPUT,
)
})
.unwrap()
{
None => {
cubeb_log!("Fail to create device info for input");
return Err(Error::error());
}
Some(d) => d,
};
let stm_params = StreamParams::from(unsafe { *params.as_ptr() });
Some((stm_params, in_device))
} else {
None
};
let out_stm_settings = if let Some(params) = output_stream_params {
let out_device = match self
.serial_queue
.run_sync(|| {
create_device_info(
get_device_from_devid(output_device).unwrap(),
DeviceType::OUTPUT,
)
})
.unwrap()
{
None => {
cubeb_log!("Fail to create device info for output");
return Err(Error::error());
}
Some(d) => d,
};
let stm_params = StreamParams::from(unsafe { *params.as_ptr() });
Some((stm_params, out_device))
} else {
None
};
// Latency cannot change if another stream is operating in parallel. In this case
// latency is set to the other stream value.
let global_latency_frames = self.update_latency_by_adding_stream(latency_frames);
if global_latency_frames != latency_frames {
cubeb_log!(
"Use global latency {} instead of the requested latency {}.",
global_latency_frames,
latency_frames
);
}
let mut boxed_stream = Box::new(AudioUnitStream::new(
self,
user_ptr,
data_callback,
state_callback,
global_latency_frames,
));
// Rename the task queue to be an unique label.
let queue_label = format!(
"{}.stream.{:p}",
DISPATCH_QUEUE_LABEL,
boxed_stream.as_ref()
);
boxed_stream.queue = Queue::new_with_target(queue_label.as_str(), &boxed_stream.queue);
boxed_stream.core_stream_data =
CoreStreamData::new(boxed_stream.as_ref(), in_stm_settings, out_stm_settings);
let result = boxed_stream
.queue
.clone()
.run_sync(|| {
boxed_stream
.core_stream_data
.setup(&mut boxed_stream.context.shared_voice_processing_unit)
})
.unwrap();
if let Err(r) = result {
cubeb_log!(
"({:p}) Could not setup the audiounit stream.",
boxed_stream.as_ref()
);
return Err(r);
}
let cubeb_stream = unsafe { Stream::from_ptr(Box::into_raw(boxed_stream) as *mut _) };
cubeb_log!(
"({:p}) Cubeb stream init successful.",
cubeb_stream.as_ref()
);
Ok(cubeb_stream)
}