fn stream_init()

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)
    }