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(
|
||||
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,
|
||||
)?;
|
||||
stream.play()?;
|
||||
|
|
|
@ -46,7 +46,7 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
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;
|
||||
for &sample in data {
|
||||
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;
|
||||
for sample in data {
|
||||
*sample = match consumer.pop() {
|
||||
|
|
|
@ -43,17 +43,17 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
let stream = match config.sample_format() {
|
||||
cpal::SampleFormat::F32 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data| write_input_data::<f32, f32>(data, &writer_2),
|
||||
move |data, _: &_| write_input_data::<f32, f32>(data, &writer_2),
|
||||
err_fn,
|
||||
)?,
|
||||
cpal::SampleFormat::I16 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data| write_input_data::<i16, i16>(data, &writer_2),
|
||||
move |data, _: &_| write_input_data::<i16, i16>(data, &writer_2),
|
||||
err_fn,
|
||||
)?,
|
||||
cpal::SampleFormat::U16 => device.build_input_stream(
|
||||
&config.into(),
|
||||
move |data| write_input_data::<u16, i16>(data, &writer_2),
|
||||
move |data, _: &_| write_input_data::<u16, i16>(data, &writer_2),
|
||||
err_fn,
|
||||
)?,
|
||||
};
|
||||
|
|
|
@ -4,9 +4,9 @@ extern crate libc;
|
|||
use self::alsa::poll::Descriptors;
|
||||
use crate::{
|
||||
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
||||
DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate,
|
||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||
SupportedStreamConfigsError,
|
||||
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedStreamConfig,
|
||||
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
};
|
||||
use std::cmp;
|
||||
use std::sync::Arc;
|
||||
|
@ -90,7 +90,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let stream_inner =
|
||||
|
@ -107,7 +107,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let stream_inner =
|
||||
|
@ -464,7 +464,7 @@ struct StreamWorkerContext {
|
|||
fn input_stream_worker(
|
||||
rx: TriggerReceiver,
|
||||
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),
|
||||
) {
|
||||
let mut ctxt = StreamWorkerContext::default();
|
||||
|
@ -499,7 +499,7 @@ fn input_stream_worker(
|
|||
fn output_stream_worker(
|
||||
rx: TriggerReceiver,
|
||||
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),
|
||||
) {
|
||||
let mut ctxt = StreamWorkerContext::default();
|
||||
|
@ -636,14 +636,15 @@ fn poll_descriptors_and_prepare_buffer(
|
|||
fn process_input(
|
||||
stream: &StreamInner,
|
||||
buffer: &mut [u8],
|
||||
data_callback: &mut (dyn FnMut(&Data) + Send + 'static),
|
||||
data_callback: &mut (dyn FnMut(&Data, &InputCallbackInfo) + Send + 'static),
|
||||
) -> Result<(), BackendSpecificError> {
|
||||
stream.channel.io().readi(buffer)?;
|
||||
let sample_format = stream.sample_format;
|
||||
let data = buffer.as_mut_ptr() as *mut ();
|
||||
let len = buffer.len() / sample_format.sample_size();
|
||||
let data = unsafe { Data::from_parts(data, len, sample_format) };
|
||||
data_callback(&data);
|
||||
let info = crate::InputCallbackInfo {};
|
||||
data_callback(&data, &info);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -655,7 +656,7 @@ fn process_output(
|
|||
stream: &StreamInner,
|
||||
buffer: &mut [u8],
|
||||
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),
|
||||
) {
|
||||
{
|
||||
|
@ -664,7 +665,8 @@ fn process_output(
|
|||
let data = buffer.as_mut_ptr() as *mut ();
|
||||
let len = buffer.len() / sample_format.sample_size();
|
||||
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 {
|
||||
match stream.channel.io().writei(buffer) {
|
||||
|
@ -700,7 +702,7 @@ impl Stream {
|
|||
mut error_callback: E,
|
||||
) -> Stream
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let (tx, rx) = trigger();
|
||||
|
@ -722,7 +724,7 @@ impl Stream {
|
|||
mut error_callback: E,
|
||||
) -> Stream
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let (tx, rx) = trigger();
|
||||
|
|
|
@ -3,8 +3,8 @@ extern crate parking_lot;
|
|||
|
||||
use crate::{
|
||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
||||
SupportedStreamConfig, SupportedStreamConfigsError,
|
||||
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigsError,
|
||||
};
|
||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
|
||||
|
@ -90,7 +90,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||
|
@ -104,7 +104,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
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 super::parking_lot::Mutex;
|
||||
use super::Device;
|
||||
use crate::{
|
||||
BackendSpecificError, BuildStreamError, Data, InputCallbackInfo, OutputCallbackInfo,
|
||||
PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError,
|
||||
SupportedStreamConfig,
|
||||
};
|
||||
use std;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
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.
|
||||
trait Silence {
|
||||
|
@ -66,7 +61,7 @@ impl Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
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 len = interleaved.len();
|
||||
let data = Data::from_parts(data, len, B::FORMAT);
|
||||
callback(&data);
|
||||
let info = InputCallbackInfo {};
|
||||
callback(&data, &info);
|
||||
}
|
||||
|
||||
match (&stream_type, sample_format) {
|
||||
|
@ -233,7 +229,7 @@ impl Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
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 len = interleaved.len();
|
||||
let mut data = Data::from_parts(data, len, A::FORMAT);
|
||||
let info = OutputCallbackInfo {};
|
||||
callback(&mut data);
|
||||
|
||||
// 2. Silence ASIO channels if necessary.
|
||||
|
|
|
@ -21,9 +21,9 @@ use self::coreaudio::sys::{
|
|||
use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
use crate::{
|
||||
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
|
||||
DeviceNameError, DevicesError, PauseStreamError, PlayStreamError, SampleFormat, SampleRate,
|
||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||
SupportedStreamConfigsError,
|
||||
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedStreamConfig,
|
||||
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::CStr;
|
||||
|
@ -111,7 +111,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
Device::build_input_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||
|
@ -125,7 +125,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
Device::build_output_stream_raw(self, config, sample_format, data_callback, error_callback)
|
||||
|
@ -486,7 +486,7 @@ impl Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
// The scope and element for working with a device's input stream.
|
||||
|
@ -653,7 +653,8 @@ impl Device {
|
|||
let data = data as *mut ();
|
||||
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
||||
let data = Data::from_parts(data, len, sample_format);
|
||||
data_callback(&data);
|
||||
let info = InputCallbackInfo {};
|
||||
data_callback(&data, &info);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
@ -674,7 +675,7 @@ impl Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let mut audio_unit = audio_unit_from_device(self, false)?;
|
||||
|
@ -704,7 +705,8 @@ impl Device {
|
|||
let data = data as *mut ();
|
||||
let len = (data_byte_size as usize / bytes_per_channel) as usize;
|
||||
let mut data = Data::from_parts(data, len, sample_format);
|
||||
data_callback(&mut data);
|
||||
let info = OutputCallbackInfo {};
|
||||
data_callback(&mut data, &info);
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@ use stdweb::Reference;
|
|||
|
||||
use crate::{
|
||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
||||
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||
SupportedStreamConfigsError,
|
||||
};
|
||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
|
||||
|
@ -160,7 +161,7 @@ impl DeviceTrait for Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
unimplemented!()
|
||||
|
@ -174,7 +175,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
assert_eq!(
|
||||
|
@ -224,7 +225,7 @@ impl StreamTrait for Stream {
|
|||
// and to the `callback` parameter that was passed to `run`.
|
||||
fn audio_callback_fn<D, E>(user_data_ptr: *mut c_void)
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
unsafe {
|
||||
|
@ -241,7 +242,8 @@ where
|
|||
let data = temporary_buffer.as_mut_ptr() as *mut ();
|
||||
let sample_format = SampleFormat::F32;
|
||||
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
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||
PauseStreamError, PlayStreamError, SampleFormat, StreamConfig, StreamError,
|
||||
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
InputCallbackInfo, OutputCallbackInfo, PauseStreamError, PlayStreamError, SampleFormat,
|
||||
StreamConfig, StreamError, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||
SupportedStreamConfigsError,
|
||||
};
|
||||
use traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
|
||||
|
@ -74,7 +75,7 @@ impl DeviceTrait for Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
unimplemented!()
|
||||
|
@ -89,7 +90,7 @@ impl DeviceTrait for Device {
|
|||
_error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
unimplemented!()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
BackendSpecificError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||
SampleFormat, SampleRate, StreamConfig, SupportedStreamConfig, SupportedStreamConfigRange,
|
||||
SupportedStreamConfigsError, COMMON_SAMPLE_RATES,
|
||||
InputCallbackInfo, OutputCallbackInfo, SampleFormat, SampleRate, StreamConfig,
|
||||
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
COMMON_SAMPLE_RATES,
|
||||
};
|
||||
use std;
|
||||
use std::ffi::OsString;
|
||||
|
@ -104,7 +105,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let stream_inner = self.build_input_stream_raw_inner(config, sample_format)?;
|
||||
|
@ -123,7 +124,7 @@ impl DeviceTrait for Device {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
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 crate::traits::StreamTrait;
|
||||
use crate::{
|
||||
BackendSpecificError, Data, PauseStreamError, PlayStreamError, SampleFormat, StreamError,
|
||||
BackendSpecificError, Data, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
|
||||
PlayStreamError, SampleFormat, StreamError,
|
||||
};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
@ -83,7 +84,7 @@ impl Stream {
|
|||
mut error_callback: E,
|
||||
) -> Stream
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let pending_scheduled_event =
|
||||
|
@ -112,7 +113,7 @@ impl Stream {
|
|||
mut error_callback: E,
|
||||
) -> Stream
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
let pending_scheduled_event =
|
||||
|
@ -277,7 +278,7 @@ fn stream_error_from_hresult(hresult: winnt::HRESULT) -> Result<(), StreamError>
|
|||
|
||||
fn run_input(
|
||||
mut run_ctxt: RunContext,
|
||||
data_callback: &mut dyn FnMut(&Data),
|
||||
data_callback: &mut dyn FnMut(&Data, &InputCallbackInfo),
|
||||
error_callback: &mut dyn FnMut(StreamError),
|
||||
) {
|
||||
loop {
|
||||
|
@ -304,7 +305,7 @@ fn run_input(
|
|||
|
||||
fn run_output(
|
||||
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),
|
||||
) {
|
||||
loop {
|
||||
|
@ -370,7 +371,7 @@ fn process_commands_and_await_signal(
|
|||
fn process_input(
|
||||
stream: &StreamInner,
|
||||
capture_client: *mut audioclient::IAudioCaptureClient,
|
||||
data_callback: &mut dyn FnMut(&Data),
|
||||
data_callback: &mut dyn FnMut(&Data, &InputCallbackInfo),
|
||||
error_callback: &mut dyn FnMut(StreamError),
|
||||
) -> ControlFlow {
|
||||
let mut frames_available = 0;
|
||||
|
@ -409,7 +410,8 @@ fn process_input(
|
|||
let len = frames_available as usize * stream.bytes_per_frame as usize
|
||||
/ stream.sample_format.sample_size();
|
||||
let data = Data::from_parts(data, len, stream.sample_format);
|
||||
data_callback(&data);
|
||||
let info = InputCallbackInfo {};
|
||||
data_callback(&data, &info);
|
||||
|
||||
// Release the buffer.
|
||||
let hresult = (*capture_client).ReleaseBuffer(frames_available);
|
||||
|
@ -425,7 +427,7 @@ fn process_input(
|
|||
fn process_output(
|
||||
stream: &StreamInner,
|
||||
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),
|
||||
) -> ControlFlow {
|
||||
// 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
|
||||
/ stream.sample_format.sample_size();
|
||||
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);
|
||||
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 stream = device.build_output_stream(
|
||||
//! &config,
|
||||
//! move |data: &mut [f32]| {
|
||||
//! move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||
//! // react to stream events and read or write stream data here.
|
||||
//! },
|
||||
//! move |err| {
|
||||
|
@ -102,7 +102,7 @@
|
|||
//! SampleFormat::U16 => device.build_output_stream(&config, write_silence::<u16>, err_fn),
|
||||
//! }.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() {
|
||||
//! *sample = Sample::from(&0.0);
|
||||
//! }
|
||||
|
@ -119,7 +119,7 @@
|
|||
//! # let supported_config = device.default_output_config().unwrap();
|
||||
//! # let sample_format = supported_config.sample_format();
|
||||
//! # 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 stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
||||
//! stream.play().unwrap();
|
||||
|
@ -135,7 +135,7 @@
|
|||
//! # let supported_config = device.default_output_config().unwrap();
|
||||
//! # let sample_format = supported_config.sample_format();
|
||||
//! # 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 stream = device.build_output_stream_raw(&config, sample_format, data_fn, err_fn).unwrap();
|
||||
//! stream.pause().unwrap();
|
||||
|
@ -220,6 +220,14 @@ pub struct Data {
|
|||
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 {
|
||||
pub fn channels(&self) -> ChannelCount {
|
||||
self.channels
|
||||
|
|
|
@ -263,7 +263,7 @@ macro_rules! impl_platform_host {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, crate::BuildStreamError>
|
||||
where
|
||||
D: FnMut(&crate::Data) + Send + 'static,
|
||||
D: FnMut(&crate::Data, &crate::InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(crate::StreamError) + Send + 'static,
|
||||
{
|
||||
match self.0 {
|
||||
|
@ -289,7 +289,7 @@ macro_rules! impl_platform_host {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, crate::BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut crate::Data) + Send + 'static,
|
||||
D: FnMut(&mut crate::Data, &crate::OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(crate::StreamError) + Send + 'static,
|
||||
{
|
||||
match self.0 {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//! The suite of traits allowing CPAL to abstract over hosts, devices, event loops and stream IDs.
|
||||
|
||||
use {
|
||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError, InputDevices,
|
||||
OutputDevices, PauseStreamError, PlayStreamError, Sample, SampleFormat, StreamConfig,
|
||||
StreamError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
BuildStreamError, Data, DefaultStreamConfigError, DeviceNameError, DevicesError,
|
||||
InputCallbackInfo, InputDevices, OutputCallbackInfo, OutputDevices, PauseStreamError,
|
||||
PlayStreamError, Sample, SampleFormat, StreamConfig, StreamError, SupportedStreamConfig,
|
||||
SupportedStreamConfigRange, SupportedStreamConfigsError,
|
||||
};
|
||||
|
||||
/// A **Host** provides access to the available audio devices on the system.
|
||||
|
@ -122,16 +123,17 @@ pub trait DeviceTrait {
|
|||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
T: Sample,
|
||||
D: FnMut(&[T]) + Send + 'static,
|
||||
D: FnMut(&[T], &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
self.build_input_stream_raw(
|
||||
config,
|
||||
T::FORMAT,
|
||||
move |data| {
|
||||
move |data, info| {
|
||||
data_callback(
|
||||
data.as_slice()
|
||||
.expect("host supplied incorrect sample type"),
|
||||
info,
|
||||
)
|
||||
},
|
||||
error_callback,
|
||||
|
@ -147,16 +149,17 @@ pub trait DeviceTrait {
|
|||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
T: Sample,
|
||||
D: FnMut(&mut [T]) + Send + 'static,
|
||||
D: FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static,
|
||||
{
|
||||
self.build_output_stream_raw(
|
||||
config,
|
||||
T::FORMAT,
|
||||
move |data| {
|
||||
move |data, info| {
|
||||
data_callback(
|
||||
data.as_slice_mut()
|
||||
.expect("host supplied incorrect sample type"),
|
||||
info,
|
||||
)
|
||||
},
|
||||
error_callback,
|
||||
|
@ -172,7 +175,7 @@ pub trait DeviceTrait {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&Data) + Send + 'static,
|
||||
D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static;
|
||||
|
||||
/// Create a dynamically typed output stream.
|
||||
|
@ -184,7 +187,7 @@ pub trait DeviceTrait {
|
|||
error_callback: E,
|
||||
) -> Result<Self::Stream, BuildStreamError>
|
||||
where
|
||||
D: FnMut(&mut Data) + Send + 'static,
|
||||
D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
|
||||
E: FnMut(StreamError) + Send + 'static;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue