Add a `CallbackInfo` argument to the stream data callback
I began on an implementation of the timestamp API described in #363 but quickly realised that it might be best to land the API for providing extra information to the user's callback first. This PR adds two new types: `InputCallbackInfo` and `OutputCallbackInfo`. These types are delivered to the user's data callback as a new, second argument. While these types are currently empty, the intention is for these types to provide information relevant to the current request for or delivery of data. This includes: - Timestamp information #363. - Flags related to the state of the stream (e.g buffer underflow/overflow). In order to maintain flexibility to avoid breaking things, I figure we can keep the fields of these types private and provide methods for retrieving this info. @Ralith, @ishitatsuyuki does this seem OK to you?
This commit is contained in:
parent
608d23adc6
commit
bcf962c447
|
@ -37,7 +37,9 @@ where
|
||||||
|
|
||||||
let stream = device.build_output_stream(
|
let stream = device.build_output_stream(
|
||||||
config,
|
config,
|
||||||
move |data: &mut [T]| write_data(data, channels, &mut next_value),
|
move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
|
||||||
|
write_data(data, channels, &mut next_value)
|
||||||
|
},
|
||||||
err_fn,
|
err_fn,
|
||||||
)?;
|
)?;
|
||||||
stream.play()?;
|
stream.play()?;
|
||||||
|
|
|
@ -46,7 +46,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
producer.push(0.0).unwrap();
|
producer.push(0.0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let input_data_fn = move |data: &[f32]| {
|
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
|
||||||
let mut output_fell_behind = false;
|
let mut output_fell_behind = false;
|
||||||
for &sample in data {
|
for &sample in data {
|
||||||
if producer.push(sample).is_err() {
|
if producer.push(sample).is_err() {
|
||||||
|
@ -58,7 +58,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_data_fn = move |data: &mut [f32]| {
|
let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||||
let mut input_fell_behind = None;
|
let mut input_fell_behind = None;
|
||||||
for sample in data {
|
for sample in data {
|
||||||
*sample = match consumer.pop() {
|
*sample = match consumer.pop() {
|
||||||
|
|
|
@ -43,17 +43,17 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
let stream = match config.sample_format() {
|
let stream = match config.sample_format() {
|
||||||
cpal::SampleFormat::F32 => device.build_input_stream(
|
cpal::SampleFormat::F32 => device.build_input_stream(
|
||||||
&config.into(),
|
&config.into(),
|
||||||
move |data| write_input_data::<f32, f32>(data, &writer_2),
|
move |data, _: &_| write_input_data::<f32, f32>(data, &writer_2),
|
||||||
err_fn,
|
err_fn,
|
||||||
)?,
|
)?,
|
||||||
cpal::SampleFormat::I16 => device.build_input_stream(
|
cpal::SampleFormat::I16 => device.build_input_stream(
|
||||||
&config.into(),
|
&config.into(),
|
||||||
move |data| write_input_data::<i16, i16>(data, &writer_2),
|
move |data, _: &_| write_input_data::<i16, i16>(data, &writer_2),
|
||||||
err_fn,
|
err_fn,
|
||||||
)?,
|
)?,
|
||||||
cpal::SampleFormat::U16 => device.build_input_stream(
|
cpal::SampleFormat::U16 => device.build_input_stream(
|
||||||
&config.into(),
|
&config.into(),
|
||||||
move |data| write_input_data::<u16, i16>(data, &writer_2),
|
move |data, _: &_| write_input_data::<u16, i16>(data, &writer_2),
|
||||||
err_fn,
|
err_fn,
|
||||||
)?,
|
)?,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,9 @@ extern crate libc;
|
||||||
use self::alsa::poll::Descriptors;
|
use self::alsa::poll::Descriptors;
|
||||||
use crate::{
|
use crate::{
|
||||||
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
||||||
DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate,
|
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedStreamConfig,
|
||||||
SupportedStreamConfigsError,
|
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -90,7 +90,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_inner =
|
let stream_inner =
|
||||||
|
@ -107,7 +107,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_inner =
|
let stream_inner =
|
||||||
|
@ -464,7 +464,7 @@ struct StreamWorkerContext {
|
||||||
fn input_stream_worker(
|
fn input_stream_worker(
|
||||||
rx: TriggerReceiver,
|
rx: TriggerReceiver,
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
data_callback: &mut (dyn FnMut(&Data) + Send + 'static),
|
data_callback: &mut (dyn FnMut(&Data, &InputCallbackInfo) + Send + 'static),
|
||||||
error_callback: &mut (dyn FnMut(StreamError) + Send + 'static),
|
error_callback: &mut (dyn FnMut(StreamError) + Send + 'static),
|
||||||
) {
|
) {
|
||||||
let mut ctxt = StreamWorkerContext::default();
|
let mut ctxt = StreamWorkerContext::default();
|
||||||
|
@ -499,7 +499,7 @@ fn input_stream_worker(
|
||||||
fn output_stream_worker(
|
fn output_stream_worker(
|
||||||
rx: TriggerReceiver,
|
rx: TriggerReceiver,
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
data_callback: &mut (dyn FnMut(&mut Data) + Send + 'static),
|
data_callback: &mut (dyn FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static),
|
||||||
error_callback: &mut (dyn FnMut(StreamError) + Send + 'static),
|
error_callback: &mut (dyn FnMut(StreamError) + Send + 'static),
|
||||||
) {
|
) {
|
||||||
let mut ctxt = StreamWorkerContext::default();
|
let mut ctxt = StreamWorkerContext::default();
|
||||||
|
@ -636,14 +636,15 @@ fn poll_descriptors_and_prepare_buffer(
|
||||||
fn process_input(
|
fn process_input(
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
data_callback: &mut (dyn FnMut(&Data) + Send + 'static),
|
data_callback: &mut (dyn FnMut(&Data, &InputCallbackInfo) + Send + 'static),
|
||||||
) -> Result<(), BackendSpecificError> {
|
) -> Result<(), BackendSpecificError> {
|
||||||
stream.channel.io().readi(buffer)?;
|
stream.channel.io().readi(buffer)?;
|
||||||
let sample_format = stream.sample_format;
|
let sample_format = stream.sample_format;
|
||||||
let data = buffer.as_mut_ptr() as *mut ();
|
let data = buffer.as_mut_ptr() as *mut ();
|
||||||
let len = buffer.len() / sample_format.sample_size();
|
let len = buffer.len() / sample_format.sample_size();
|
||||||
let data = unsafe { Data::from_parts(data, len, sample_format) };
|
let data = unsafe { Data::from_parts(data, len, sample_format) };
|
||||||
data_callback(&data);
|
let info = crate::InputCallbackInfo {};
|
||||||
|
data_callback(&data, &info);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -655,7 +656,7 @@ fn process_output(
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
available_frames: usize,
|
available_frames: usize,
|
||||||
data_callback: &mut (dyn FnMut(&mut Data) + Send + 'static),
|
data_callback: &mut (dyn FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static),
|
||||||
error_callback: &mut dyn FnMut(StreamError),
|
error_callback: &mut dyn FnMut(StreamError),
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
|
@ -664,7 +665,8 @@ fn process_output(
|
||||||
let data = buffer.as_mut_ptr() as *mut ();
|
let data = buffer.as_mut_ptr() as *mut ();
|
||||||
let len = buffer.len() / sample_format.sample_size();
|
let len = buffer.len() / sample_format.sample_size();
|
||||||
let mut data = unsafe { Data::from_parts(data, len, sample_format) };
|
let mut data = unsafe { Data::from_parts(data, len, sample_format) };
|
||||||
data_callback(&mut data);
|
let info = crate::OutputCallbackInfo {};
|
||||||
|
data_callback(&mut data, &info);
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
match stream.channel.io().writei(buffer) {
|
match stream.channel.io().writei(buffer) {
|
||||||
|
@ -700,7 +702,7 @@ impl Stream {
|
||||||
mut error_callback: E,
|
mut error_callback: E,
|
||||||
) -> Stream
|
) -> Stream
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = trigger();
|
let (tx, rx) = trigger();
|
||||||
|
@ -722,7 +724,7 @@ impl Stream {
|
||||||
mut error_callback: E,
|
mut error_callback: E,
|
||||||
) -> Stream
|
) -> Stream
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let (tx, rx) = trigger();
|
let (tx, rx) = trigger();
|
||||||
|
|
|
@ -3,8 +3,8 @@ extern crate parking_lot;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||||
SupportedStreamConfig, SupportedStreamConfigsError,
|
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||||
|
@ -104,7 +104,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
|
Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||||
|
|
|
@ -4,19 +4,14 @@ extern crate num_traits;
|
||||||
use self::num_traits::PrimInt;
|
use self::num_traits::PrimInt;
|
||||||
use super::parking_lot::Mutex;
|
use super::parking_lot::Mutex;
|
||||||
use super::Device;
|
use super::Device;
|
||||||
|
use crate::{
|
||||||
|
BackendSpecificError, BuildStreamError, Data, InputCallbackInfo, OutputCallbackInfo,
|
||||||
|
PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError,
|
||||||
|
SupportedStreamConfig,
|
||||||
|
};
|
||||||
use std;
|
use std;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use BackendSpecificError;
|
|
||||||
use BuildStreamError;
|
|
||||||
use Data;
|
|
||||||
use PauseStreamError;
|
|
||||||
use PlayStreamError;
|
|
||||||
use Sample;
|
|
||||||
use SampleFormat;
|
|
||||||
use StreamConfig;
|
|
||||||
use StreamError;
|
|
||||||
use SupportedStreamConfig;
|
|
||||||
|
|
||||||
/// Sample types whose constant silent value is known.
|
/// Sample types whose constant silent value is known.
|
||||||
trait Silence {
|
trait Silence {
|
||||||
|
@ -66,7 +61,7 @@ impl Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_type = self.driver.input_data_type().map_err(build_stream_err)?;
|
let stream_type = self.driver.input_data_type().map_err(build_stream_err)?;
|
||||||
|
@ -133,7 +128,8 @@ impl Device {
|
||||||
let data = interleaved.as_mut_ptr() as *mut ();
|
let data = interleaved.as_mut_ptr() as *mut ();
|
||||||
let len = interleaved.len();
|
let len = interleaved.len();
|
||||||
let data = Data::from_parts(data, len, B::FORMAT);
|
let data = Data::from_parts(data, len, B::FORMAT);
|
||||||
callback(&data);
|
let info = InputCallbackInfo {};
|
||||||
|
callback(&data, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
match (&stream_type, sample_format) {
|
match (&stream_type, sample_format) {
|
||||||
|
@ -233,7 +229,7 @@ impl Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_type = self.driver.output_data_type().map_err(build_stream_err)?;
|
let stream_type = self.driver.output_data_type().map_err(build_stream_err)?;
|
||||||
|
@ -315,6 +311,7 @@ impl Device {
|
||||||
let data = interleaved.as_mut_ptr() as *mut ();
|
let data = interleaved.as_mut_ptr() as *mut ();
|
||||||
let len = interleaved.len();
|
let len = interleaved.len();
|
||||||
let mut data = Data::from_parts(data, len, A::FORMAT);
|
let mut data = Data::from_parts(data, len, A::FORMAT);
|
||||||
|
let info = OutputCallbackInfo {};
|
||||||
callback(&mut data);
|
callback(&mut data);
|
||||||
|
|
||||||
// 2. Silence ASIO channels if necessary.
|
// 2. Silence ASIO channels if necessary.
|
||||||
|
|
|
@ -21,9 +21,9 @@ use self::coreaudio::sys::{
|
||||||
use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
|
use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
use crate::{
|
use crate::{
|
||||||
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
||||||
DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate,
|
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedStreamConfig,
|
||||||
SupportedStreamConfigsError,
|
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -111,7 +111,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||||
|
@ -125,7 +125,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
|
Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||||
|
@ -486,7 +486,7 @@ impl Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
// The scope and element for working with a device's input stream.
|
// The scope and element for working with a device's input stream.
|
||||||
|
@ -653,7 +653,8 @@ impl Device {
|
||||||
let data = data as *mut ();
|
let data = data as *mut ();
|
||||||
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
||||||
let data = Data::from_parts(data, len, sample_format);
|
let data = Data::from_parts(data, len, sample_format);
|
||||||
data_callback(&data);
|
let info = InputCallbackInfo {};
|
||||||
|
data_callback(&data, &info);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -674,7 +675,7 @@ impl Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Stream, BuildStreamError>
|
) -> Result<Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let mut audio_unit = audio_unit_from_device(self, false)?;
|
let mut audio_unit = audio_unit_from_device(self, false)?;
|
||||||
|
@ -704,7 +705,8 @@ impl Device {
|
||||||
let data = data as *mut ();
|
let data = data as *mut ();
|
||||||
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
||||||
let mut data = Data::from_parts(data, len, sample_format);
|
let mut data = Data::from_parts(data, len, sample_format);
|
||||||
data_callback(&mut data);
|
let info = OutputCallbackInfo {};
|
||||||
|
data_callback(&mut data, &info);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,9 @@ use stdweb::Reference;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||||
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||||
|
SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ impl DeviceTrait for Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -174,7 +175,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -224,7 +225,7 @@ impl StreamTrait for Stream {
|
||||||
// and to the `callback` parameter that was passed to `run`.
|
// and to the `callback` parameter that was passed to `run`.
|
||||||
fn audio_callback_fn<D, E>(user_data_ptr: *mut c_void)
|
fn audio_callback_fn<D, E>(user_data_ptr: *mut c_void)
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -241,7 +242,8 @@ where
|
||||||
let data = temporary_buffer.as_mut_ptr() as *mut ();
|
let data = temporary_buffer.as_mut_ptr() as *mut ();
|
||||||
let sample_format = SampleFormat::F32;
|
let sample_format = SampleFormat::F32;
|
||||||
let mut data = Data::from_parts(data, len, sample_format);
|
let mut data = Data::from_parts(data, len, sample_format);
|
||||||
data_cb(&mut data);
|
let info = OutputCallbackInfo {};
|
||||||
|
data_cb(&mut data, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: directly use a TypedArray<f32> once this is supported by stdweb
|
// TODO: directly use a TypedArray<f32> once this is supported by stdweb
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||||
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||||
|
SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ impl DeviceTrait for Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -89,7 +90,7 @@ impl DeviceTrait for Device {
|
||||||
_error_callback: E,
|
_error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
BackendSpecificError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
BackendSpecificError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
SampleFormat, SampleRate, StreamConfig, SupportedStreamConfig, SupportedStreamConfigRange,
|
InputCallbackInfo, OutputCallbackInfo, SampleFormat, SampleRate, StreamConfig,
|
||||||
SupportedStreamConfigsError, COMMON_SAMPLE_RATES,
|
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||||
|
COMMON_SAMPLE_RATES,
|
||||||
};
|
};
|
||||||
use std;
|
use std;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
@ -104,7 +105,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_inner = self.build_input_stream_raw_inner(config, sample_format)?;
|
let stream_inner = self.build_input_stream_raw_inner(config, sample_format)?;
|
||||||
|
@ -123,7 +124,7 @@ impl DeviceTrait for Device {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let stream_inner = self.build_output_stream_raw_inner(config, sample_format)?;
|
let stream_inner = self.build_output_stream_raw_inner(config, sample_format)?;
|
||||||
|
|
|
@ -8,7 +8,8 @@ use super::winapi::um::winbase;
|
||||||
use super::winapi::um::winnt;
|
use super::winapi::um::winnt;
|
||||||
use crate::traits::StreamTrait;
|
use crate::traits::StreamTrait;
|
||||||
use crate::{
|
use crate::{
|
||||||
BackendSpecificError, Data, PauseStreamError, PlayStreamError, SampleFormat, StreamError,
|
BackendSpecificError, Data, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||||
|
PlayStreamError, SampleFormat, StreamError,
|
||||||
};
|
};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -83,7 +84,7 @@ impl Stream {
|
||||||
mut error_callback: E,
|
mut error_callback: E,
|
||||||
) -> Stream
|
) -> Stream
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let pending_scheduled_event =
|
let pending_scheduled_event =
|
||||||
|
@ -112,7 +113,7 @@ impl Stream {
|
||||||
mut error_callback: E,
|
mut error_callback: E,
|
||||||
) -> Stream
|
) -> Stream
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
let pending_scheduled_event =
|
let pending_scheduled_event =
|
||||||
|
@ -277,7 +278,7 @@ fn stream_error_from_hresult(hresult: winnt::HRESULT) -> Result<(), StreamError>
|
||||||
|
|
||||||
fn run_input(
|
fn run_input(
|
||||||
mut run_ctxt: RunContext,
|
mut run_ctxt: RunContext,
|
||||||
data_callback: &mut dyn FnMut(&Data),
|
data_callback: &mut dyn FnMut(&Data, &InputCallbackInfo),
|
||||||
error_callback: &mut dyn FnMut(StreamError),
|
error_callback: &mut dyn FnMut(StreamError),
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
|
@ -304,7 +305,7 @@ fn run_input(
|
||||||
|
|
||||||
fn run_output(
|
fn run_output(
|
||||||
mut run_ctxt: RunContext,
|
mut run_ctxt: RunContext,
|
||||||
data_callback: &mut dyn FnMut(&mut Data),
|
data_callback: &mut dyn FnMut(&mut Data, &OutputCallbackInfo),
|
||||||
error_callback: &mut dyn FnMut(StreamError),
|
error_callback: &mut dyn FnMut(StreamError),
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
|
@ -370,7 +371,7 @@ fn process_commands_and_await_signal(
|
||||||
fn process_input(
|
fn process_input(
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
capture_client: *mut audioclient::IAudioCaptureClient,
|
capture_client: *mut audioclient::IAudioCaptureClient,
|
||||||
data_callback: &mut dyn FnMut(&Data),
|
data_callback: &mut dyn FnMut(&Data, &InputCallbackInfo),
|
||||||
error_callback: &mut dyn FnMut(StreamError),
|
error_callback: &mut dyn FnMut(StreamError),
|
||||||
) -> ControlFlow {
|
) -> ControlFlow {
|
||||||
let mut frames_available = 0;
|
let mut frames_available = 0;
|
||||||
|
@ -409,7 +410,8 @@ fn process_input(
|
||||||
let len = frames_available as usize * stream.bytes_per_frame as usize
|
let len = frames_available as usize * stream.bytes_per_frame as usize
|
||||||
/ stream.sample_format.sample_size();
|
/ stream.sample_format.sample_size();
|
||||||
let data = Data::from_parts(data, len, stream.sample_format);
|
let data = Data::from_parts(data, len, stream.sample_format);
|
||||||
data_callback(&data);
|
let info = InputCallbackInfo {};
|
||||||
|
data_callback(&data, &info);
|
||||||
|
|
||||||
// Release the buffer.
|
// Release the buffer.
|
||||||
let hresult = (*capture_client).ReleaseBuffer(frames_available);
|
let hresult = (*capture_client).ReleaseBuffer(frames_available);
|
||||||
|
@ -425,7 +427,7 @@ fn process_input(
|
||||||
fn process_output(
|
fn process_output(
|
||||||
stream: &StreamInner,
|
stream: &StreamInner,
|
||||||
render_client: *mut audioclient::IAudioRenderClient,
|
render_client: *mut audioclient::IAudioRenderClient,
|
||||||
data_callback: &mut dyn FnMut(&mut Data),
|
data_callback: &mut dyn FnMut(&mut Data, &OutputCallbackInfo),
|
||||||
error_callback: &mut dyn FnMut(StreamError),
|
error_callback: &mut dyn FnMut(StreamError),
|
||||||
) -> ControlFlow {
|
) -> ControlFlow {
|
||||||
// The number of frames available for writing.
|
// The number of frames available for writing.
|
||||||
|
@ -453,7 +455,8 @@ fn process_output(
|
||||||
let len = frames_available as usize * stream.bytes_per_frame as usize
|
let len = frames_available as usize * stream.bytes_per_frame as usize
|
||||||
/ stream.sample_format.sample_size();
|
/ stream.sample_format.sample_size();
|
||||||
let mut data = Data::from_parts(data, len, stream.sample_format);
|
let mut data = Data::from_parts(data, len, stream.sample_format);
|
||||||
data_callback(&mut data);
|
let info = OutputCallbackInfo {};
|
||||||
|
data_callback(&mut data, &info);
|
||||||
|
|
||||||
let hresult = (*render_client).ReleaseBuffer(frames_available as u32, 0);
|
let hresult = (*render_client).ReleaseBuffer(frames_available as u32, 0);
|
||||||
if let Err(err) = stream_error_from_hresult(hresult) {
|
if let Err(err) = stream_error_from_hresult(hresult) {
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -63,7 +63,7 @@
|
||||||
//! # let config = device.default_output_config().unwrap().into();
|
//! # let config = device.default_output_config().unwrap().into();
|
||||||
//! let stream = device.build_output_stream(
|
//! let stream = device.build_output_stream(
|
||||||
//! &config,
|
//! &config,
|
||||||
//! move |data: &mut [f32]| {
|
//! move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||||
//! // react to stream events and read or write stream data here.
|
//! // react to stream events and read or write stream data here.
|
||||||
//! },
|
//! },
|
||||||
//! move |err| {
|
//! move |err| {
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
//! SampleFormat::U16 => device.build_output_stream(&config, write_silence::<u16>, err_fn),
|
//! SampleFormat::U16 => device.build_output_stream(&config, write_silence::<u16>, err_fn),
|
||||||
//! }.unwrap();
|
//! }.unwrap();
|
||||||
//!
|
//!
|
||||||
//! fn write_silence<T: Sample>(data: &mut [T]) {
|
//! fn write_silence<T: Sample>(data: &mut [T], _: &cpal::OutputCallbackInfo) {
|
||||||
//! for sample in data.iter_mut() {
|
//! for sample in data.iter_mut() {
|
||||||
//! *sample = Sample::from(&0.0);
|
//! *sample = Sample::from(&0.0);
|
||||||
//! }
|
//! }
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
//! # let supported_config = device.default_output_config().unwrap();
|
//! # let supported_config = device.default_output_config().unwrap();
|
||||||
//! # let sample_format = supported_config.sample_format();
|
//! # let sample_format = supported_config.sample_format();
|
||||||
//! # let config = supported_config.into();
|
//! # let config = supported_config.into();
|
||||||
//! # let data_fn = move |_data: &mut cpal::Data| {};
|
//! # let data_fn = move |_data: &mut cpal::Data, _: &cpal::OutputCallbackInfo| {};
|
||||||
//! # let err_fn = move |_err| {};
|
//! # let err_fn = move |_err| {};
|
||||||
//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
||||||
//! stream.play().unwrap();
|
//! stream.play().unwrap();
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
//! # let supported_config = device.default_output_config().unwrap();
|
//! # let supported_config = device.default_output_config().unwrap();
|
||||||
//! # let sample_format = supported_config.sample_format();
|
//! # let sample_format = supported_config.sample_format();
|
||||||
//! # let config = supported_config.into();
|
//! # let config = supported_config.into();
|
||||||
//! # let data_fn = move |_data: &mut cpal::Data| {};
|
//! # let data_fn = move |_data: &mut cpal::Data, _: &cpal::OutputCallbackInfo| {};
|
||||||
//! # let err_fn = move |_err| {};
|
//! # let err_fn = move |_err| {};
|
||||||
//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
//! # let stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
||||||
//! stream.pause().unwrap();
|
//! stream.pause().unwrap();
|
||||||
|
@ -220,6 +220,14 @@ pub struct Data {
|
||||||
sample_format: SampleFormat,
|
sample_format: SampleFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information relevant to a single call to the user's output stream data callback.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct OutputCallbackInfo {}
|
||||||
|
|
||||||
|
/// Information relevant to a single call to the user's input stream data callback.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct InputCallbackInfo {}
|
||||||
|
|
||||||
impl SupportedStreamConfig {
|
impl SupportedStreamConfig {
|
||||||
pub fn channels(&self) -> ChannelCount {
|
pub fn channels(&self) -> ChannelCount {
|
||||||
self.channels
|
self.channels
|
||||||
|
|
|
@ -263,7 +263,7 @@ macro_rules! impl_platform_host {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, crate::BuildStreamError>
|
) -> Result<Self::Stream, crate::BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&crate::Data) + Send + 'static,
|
D: FnMut(&crate::Data, &crate::InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(crate::StreamError) + Send + 'static,
|
E: FnMut(crate::StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
@ -289,7 +289,7 @@ macro_rules! impl_platform_host {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, crate::BuildStreamError>
|
) -> Result<Self::Stream, crate::BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut crate::Data) + Send + 'static,
|
D: FnMut(&mut crate::Data, &crate::OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(crate::StreamError) + Send + 'static,
|
E: FnMut(crate::StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
match self.0 {
|
match self.0 {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
//! The suite of traits allowing CPAL to abstract over hosts, devices, event loops and stream IDs.
|
//! The suite of traits allowing CPAL to abstract over hosts, devices, event loops and stream IDs.
|
||||||
|
|
||||||
use {
|
use {
|
||||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, InputDevices,
|
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||||
OutputDevices, PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig,
|
InputCallbackInfo, InputDevices, OutputCallbackInfo, OutputDevices, PauseStreamError,
|
||||||
StreamError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError, SupportedStreamConfig,
|
||||||
|
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A **Host** provides access to the available audio devices on the system.
|
/// A **Host** provides access to the available audio devices on the system.
|
||||||
|
@ -122,16 +123,17 @@ pub trait DeviceTrait {
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
T: Sample,
|
T: Sample,
|
||||||
D: FnMut(&[T]) + Send + 'static,
|
D: FnMut(&[T], &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
self.build_input_stream_raw(
|
self.build_input_stream_raw(
|
||||||
config,
|
config,
|
||||||
T::FORMAT,
|
T::FORMAT,
|
||||||
move |data| {
|
move |data, info| {
|
||||||
data_callback(
|
data_callback(
|
||||||
data.as_slice()
|
data.as_slice()
|
||||||
.expect("host supplied incorrect sample type"),
|
.expect("host supplied incorrect sample type"),
|
||||||
|
info,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
error_callback,
|
error_callback,
|
||||||
|
@ -147,16 +149,17 @@ pub trait DeviceTrait {
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
T: Sample,
|
T: Sample,
|
||||||
D: FnMut(&mut [T]) + Send + 'static,
|
D: FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static,
|
E: FnMut(StreamError) + Send + 'static,
|
||||||
{
|
{
|
||||||
self.build_output_stream_raw(
|
self.build_output_stream_raw(
|
||||||
config,
|
config,
|
||||||
T::FORMAT,
|
T::FORMAT,
|
||||||
move |data| {
|
move |data, info| {
|
||||||
data_callback(
|
data_callback(
|
||||||
data.as_slice_mut()
|
data.as_slice_mut()
|
||||||
.expect("host supplied incorrect sample type"),
|
.expect("host supplied incorrect sample type"),
|
||||||
|
info,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
error_callback,
|
error_callback,
|
||||||
|
@ -172,7 +175,7 @@ pub trait DeviceTrait {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&Data) + Send + 'static,
|
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static;
|
E: FnMut(StreamError) + Send + 'static;
|
||||||
|
|
||||||
/// Create a dynamically typed output stream.
|
/// Create a dynamically typed output stream.
|
||||||
|
@ -184,7 +187,7 @@ pub trait DeviceTrait {
|
||||||
error_callback: E,
|
error_callback: E,
|
||||||
) -> Result<Self::Stream, BuildStreamError>
|
) -> Result<Self::Stream, BuildStreamError>
|
||||||
where
|
where
|
||||||
D: FnMut(&mut Data) + Send + 'static,
|
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||||
E: FnMut(StreamError) + Send + 'static;
|
E: FnMut(StreamError) + Send + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue