Update WASAPI backend for addition of new stream `Data` type

This commit is contained in:
mitchmindtree 2020-01-19 19:17:40 +01:00
parent dbb1cc4140
commit 1b5cf579cb
2 changed files with 34 additions and 54 deletions

View File

@ -1,12 +1,10 @@
use crate::{ use crate::{
BackendSpecificError, BackendSpecificError,
Data,
DefaultFormatError, DefaultFormatError,
DeviceNameError, DeviceNameError,
DevicesError, DevicesError,
Format, Format,
InputData,
OutputData,
Sample,
SampleFormat, SampleFormat,
SampleRate, SampleRate,
SupportedFormat, SupportedFormat,
@ -106,30 +104,28 @@ impl DeviceTrait for Device {
Device::default_output_format(self) Device::default_output_format(self)
} }
fn build_input_stream<T, D, E>( fn build_input_stream<D, E>(
&self, &self,
format: &Format, format: &Format,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
where where
T: Sample, D: FnMut(&Data) + Send + 'static,
D: FnMut(InputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
let stream_inner = self.build_input_stream_inner(format)?; let stream_inner = self.build_input_stream_inner(format)?;
Ok(Stream::new_input(stream_inner, data_callback, error_callback)) Ok(Stream::new_input(stream_inner, data_callback, error_callback))
} }
fn build_output_stream<T, D, E>( fn build_output_stream<D, E>(
&self, &self,
format: &Format, format: &Format,
data_callback: D, data_callback: D,
error_callback: E, error_callback: E,
) -> Result<Self::Stream, BuildStreamError> ) -> Result<Self::Stream, BuildStreamError>
where where
T: Sample, D: FnMut(&mut Data) + Send + 'static,
D: FnMut(OutputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
let stream_inner = self.build_output_stream_inner(format)?; let stream_inner = self.build_output_stream_inner(format)?;

View File

@ -1,17 +1,14 @@
use crate::{ use crate::{
BackendSpecificError, BackendSpecificError,
InputData, Data,
OutputData,
PauseStreamError, PauseStreamError,
PlayStreamError, PlayStreamError,
Sample,
SampleFormat, SampleFormat,
StreamError, StreamError,
}; };
use crate::traits::StreamTrait; use crate::traits::StreamTrait;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::slice;
use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use super::check_result; use super::check_result;
@ -85,14 +82,13 @@ pub struct StreamInner {
} }
impl Stream { impl Stream {
pub(crate) fn new_input<T, D, E>( pub(crate) fn new_input<D, E>(
stream_inner: StreamInner, stream_inner: StreamInner,
mut data_callback: D, mut data_callback: D,
mut error_callback: E, mut error_callback: E,
) -> Stream ) -> Stream
where where
T: Sample, D: FnMut(&Data) + Send + 'static,
D: FnMut(InputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
let pending_scheduled_event = let pending_scheduled_event =
@ -115,14 +111,13 @@ impl Stream {
} }
} }
pub(crate) fn new_output<T, D, E>( pub(crate) fn new_output<D, E>(
stream_inner: StreamInner, stream_inner: StreamInner,
mut data_callback: D, mut data_callback: D,
mut error_callback: E, mut error_callback: E,
) -> Stream ) -> Stream
where where
T: Sample, D: FnMut(&mut Data) + Send + 'static,
D: FnMut(OutputData<T>) + Send + 'static,
E: FnMut(StreamError) + Send + 'static, E: FnMut(StreamError) + Send + 'static,
{ {
let pending_scheduled_event = let pending_scheduled_event =
@ -285,13 +280,11 @@ fn stream_error_from_hresult(hresult: winnt::HRESULT) -> Result<(), StreamError>
Ok(()) Ok(())
} }
fn run_input<T>( fn run_input(
mut run_ctxt: RunContext, mut run_ctxt: RunContext,
data_callback: &mut dyn FnMut(InputData<T>), data_callback: &mut dyn FnMut(&Data),
error_callback: &mut dyn FnMut(StreamError), error_callback: &mut dyn FnMut(StreamError),
) where ) {
T: Sample,
{
loop { loop {
match process_commands_and_await_signal(&mut run_ctxt, error_callback) { match process_commands_and_await_signal(&mut run_ctxt, error_callback) {
Some(ControlFlow::Break) => break, Some(ControlFlow::Break) => break,
@ -309,13 +302,11 @@ fn run_input<T>(
} }
} }
fn run_output<T>( fn run_output(
mut run_ctxt: RunContext, mut run_ctxt: RunContext,
data_callback: &mut dyn FnMut(OutputData<T>), data_callback: &mut dyn FnMut(&mut Data),
error_callback: &mut dyn FnMut(StreamError), error_callback: &mut dyn FnMut(StreamError),
) where ) {
T: Sample,
{
loop { loop {
match process_commands_and_await_signal(&mut run_ctxt, error_callback) { match process_commands_and_await_signal(&mut run_ctxt, error_callback) {
Some(ControlFlow::Break) => break, Some(ControlFlow::Break) => break,
@ -371,15 +362,12 @@ fn process_commands_and_await_signal(
} }
// The loop for processing pending input data. // The loop for processing pending input data.
fn process_input<T>( fn process_input(
stream: &StreamInner, stream: &StreamInner,
capture_client: *mut audioclient::IAudioCaptureClient, capture_client: *mut audioclient::IAudioCaptureClient,
data_callback: &mut dyn FnMut(InputData<T>), data_callback: &mut dyn FnMut(&Data),
error_callback: &mut dyn FnMut(StreamError), error_callback: &mut dyn FnMut(StreamError),
) -> ControlFlow ) -> ControlFlow {
where
T: Sample,
{
let mut frames_available = 0; let mut frames_available = 0;
unsafe { unsafe {
// Get the available data in the shared buffer. // Get the available data in the shared buffer.
@ -412,15 +400,13 @@ where
debug_assert!(!buffer.is_null()); debug_assert!(!buffer.is_null());
let buffer_len = frames_available as usize let data = buffer as *mut ();
let len = frames_available as usize
* stream.bytes_per_frame as usize * stream.bytes_per_frame as usize
/ mem::size_of::<T>(); / stream.sample_format.sample_size();
let data = Data::from_parts(data, len, stream.sample_format);
data_callback(&data);
// Simplify the capture callback sample format branches.
let buffer_data = buffer as *mut _ as *const T;
let slice = slice::from_raw_parts(buffer_data, buffer_len);
let input_data = InputData { buffer: slice };
data_callback(input_data);
// Release the buffer. // Release the buffer.
let hresult = (*capture_client).ReleaseBuffer(frames_available); let hresult = (*capture_client).ReleaseBuffer(frames_available);
if let Err(err) = stream_error_from_hresult(hresult) { if let Err(err) = stream_error_from_hresult(hresult) {
@ -432,15 +418,12 @@ where
} }
// The loop for writing output data. // The loop for writing output data.
fn process_output<T>( fn process_output(
stream: &StreamInner, stream: &StreamInner,
render_client: *mut audioclient::IAudioRenderClient, render_client: *mut audioclient::IAudioRenderClient,
data_callback: &mut dyn FnMut(OutputData<T>), data_callback: &mut dyn FnMut(&mut Data),
error_callback: &mut dyn FnMut(StreamError), error_callback: &mut dyn FnMut(StreamError),
) -> ControlFlow ) -> ControlFlow {
where
T: Sample,
{
// The number of frames available for writing. // The number of frames available for writing.
let frames_available = match get_available_frames(&stream) { let frames_available = match get_available_frames(&stream) {
Ok(0) => return ControlFlow::Continue, // TODO: Can this happen? Ok(0) => return ControlFlow::Continue, // TODO: Can this happen?
@ -462,13 +445,14 @@ where
} }
debug_assert!(!buffer.is_null()); debug_assert!(!buffer.is_null());
let buffer_len =
frames_available as usize * stream.bytes_per_frame as usize / mem::size_of::<T>();
let buffer_data = buffer as *mut T; let data = buffer as *mut ();
let slice = slice::from_raw_parts_mut(buffer_data, buffer_len); let len = frames_available as usize
let output_data = OutputData { buffer: slice }; * stream.bytes_per_frame as usize
data_callback(output_data); / stream.sample_format.sample_size();
let mut data = Data::from_parts(data, len, stream.sample_format);
data_callback(&mut data);
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) {
error_callback(err); error_callback(err);