Update ASIO implementation for new error handling and Host API
This is currently untested and will almost certainly not build. I'm about to move into a Windows VM to get everything running properly again.
This commit is contained in:
parent
2bc9f85970
commit
09fd5562be
|
@ -4,11 +4,12 @@ pub type SupportedOutputFormats = std::vec::IntoIter<SupportedFormat>;
|
||||||
|
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use DefaultFormatError;
|
use DefaultFormatError;
|
||||||
|
use DeviceNameError;
|
||||||
use Format;
|
use Format;
|
||||||
use FormatsEnumerationError;
|
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use SampleRate;
|
use SampleRate;
|
||||||
use SupportedFormat;
|
use SupportedFormat;
|
||||||
|
use SupportedFormatsError;
|
||||||
use super::sys;
|
use super::sys;
|
||||||
|
|
||||||
/// A ASIO Device
|
/// A ASIO Device
|
||||||
|
@ -40,8 +41,8 @@ impl Hash for Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> Result<String, DeviceNameError> {
|
||||||
self.name.clone()
|
Ok(self.name.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the supported input formats.
|
/// Gets the supported input formats.
|
||||||
|
@ -49,11 +50,11 @@ impl Device {
|
||||||
/// Need to find all possible formats.
|
/// Need to find all possible formats.
|
||||||
pub fn supported_input_formats(
|
pub fn supported_input_formats(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<SupportedInputFormats, FormatsEnumerationError> {
|
) -> Result<SupportedInputFormats, SupportedFormatsError> {
|
||||||
// Retrieve the default format for the total supported channels and supported sample
|
// Retrieve the default format for the total supported channels and supported sample
|
||||||
// format.
|
// format.
|
||||||
let mut f = match self.default_input_format() {
|
let mut f = match self.default_input_format() {
|
||||||
Err(_) => return Err(FormatsEnumerationError::DeviceNotAvailable),
|
Err(_) => return Err(SupportedFormatsError::DeviceNotAvailable),
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,11 +78,11 @@ impl Device {
|
||||||
/// Need to find all possible formats.
|
/// Need to find all possible formats.
|
||||||
pub fn supported_output_formats(
|
pub fn supported_output_formats(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<SupportedOutputFormats, FormatsEnumerationError> {
|
) -> Result<SupportedOutputFormats, SupportedFormatsError> {
|
||||||
// Retrieve the default format for the total supported channels and supported sample
|
// Retrieve the default format for the total supported channels and supported sample
|
||||||
// format.
|
// format.
|
||||||
let mut f = match self.default_output_format() {
|
let mut f = match self.default_output_format() {
|
||||||
Err(_) => return Err(FormatsEnumerationError::DeviceNotAvailable),
|
Err(_) => return Err(SupportedFormatsError::DeviceNotAvailable),
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,12 +141,12 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Devices {
|
impl Devices {
|
||||||
fn default() -> Devices {
|
pub fn new() -> Result<Self, DevicesError> {
|
||||||
let driver_names = online_devices();
|
let driver_names = online_devices();
|
||||||
Devices {
|
Ok(Devices {
|
||||||
drivers: driver_names.into_iter(),
|
drivers: driver_names.into_iter(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
extern crate asio_sys as sys;
|
||||||
|
|
||||||
|
use {
|
||||||
|
BuildStreamError,
|
||||||
|
DefaultFormatError,
|
||||||
|
Device as DeviceTrait,
|
||||||
|
DeviceNameError,
|
||||||
|
DevicesError,
|
||||||
|
EventLoop as EventLoopTrait,
|
||||||
|
Host as HostTrait,
|
||||||
|
PauseStreamError,
|
||||||
|
PlayStreamError,
|
||||||
|
StreamDataResult,
|
||||||
|
StreamId as StreamIdTrait,
|
||||||
|
SupportedFormatsError,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::device::{Device, Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device};
|
||||||
|
pub use self::stream::{EventLoop, StreamId};
|
||||||
|
|
||||||
|
mod device;
|
||||||
|
mod stream;
|
||||||
|
mod asio_utils;
|
||||||
|
|
||||||
|
/// The host for ASIO.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Host;
|
||||||
|
|
||||||
|
impl Host {
|
||||||
|
pub fn new() -> Result<Self, crate::HostUnavailable> {
|
||||||
|
unimplemented!("asio as an initialisation and termination process that needs to be impld");
|
||||||
|
//Ok(Host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HostTrait for Host {
|
||||||
|
type Devices = Devices;
|
||||||
|
type Device = Device;
|
||||||
|
type EventLoop = EventLoop;
|
||||||
|
|
||||||
|
fn is_available() -> bool {
|
||||||
|
unimplemented!("check how to do this using asio-sys")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn devices(&self) -> Result<Self::Devices, DevicesError> {
|
||||||
|
Devices::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_input_device(&self) -> Option<Self::Device> {
|
||||||
|
default_input_device()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_output_device(&self) -> Option<Self::Device> {
|
||||||
|
default_output_device()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event_loop(&self) -> Self::EventLoop {
|
||||||
|
EventLoop::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceTrait for Device {
|
||||||
|
type SupportedInputFormats = SupportedInputFormats;
|
||||||
|
type SupportedOutputFormats = SupportedOutputFormats;
|
||||||
|
|
||||||
|
fn name(&self) -> Result<String, DeviceNameError> {
|
||||||
|
Device::name(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
|
||||||
|
Device::supported_input_formats(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
|
||||||
|
Device::supported_output_formats(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
|
||||||
|
Device::default_input_format(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
|
||||||
|
Device::default_output_format(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventLoopTrait for EventLoop {
|
||||||
|
type Device = Device;
|
||||||
|
type StreamId = StreamId;
|
||||||
|
|
||||||
|
fn build_input_stream(
|
||||||
|
&self,
|
||||||
|
device: &Self::Device,
|
||||||
|
format: &Format,
|
||||||
|
) -> Result<Self::StreamId, BuildStreamError> {
|
||||||
|
EventLoop::build_input_stream(self, device, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_output_stream(
|
||||||
|
&self,
|
||||||
|
device: &Self::Device,
|
||||||
|
format: &Format,
|
||||||
|
) -> Result<Self::StreamId, BuildStreamError> {
|
||||||
|
EventLoop::build_output_stream(self, device, format)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_stream(&self, stream: Self::StreamId) -> Result<(), PlayStreamError> {
|
||||||
|
EventLoop::play_stream(self, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pause_stream(&self, stream: Self::StreamId) -> Result<(), PauseStreamError> {
|
||||||
|
EventLoop::pause_stream(self, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn destroy_stream(&self, stream: Self::StreamId) {
|
||||||
|
EventLoop::destroy_stream(self, stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run<F>(&self, callback: F) -> !
|
||||||
|
where
|
||||||
|
F: FnMut(Self::StreamId, StreamDataResult) + Send,
|
||||||
|
{
|
||||||
|
EventLoop::run(self, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamIdTrait for StreamId {}
|
|
@ -10,10 +10,13 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use CreationError;
|
use BuildStreamError;
|
||||||
use Format;
|
use Format;
|
||||||
|
use PauseStreamError;
|
||||||
|
use PlayStreamError;
|
||||||
use SampleFormat;
|
use SampleFormat;
|
||||||
use StreamData;
|
use StreamData;
|
||||||
|
use StreamDataResult;
|
||||||
use UnknownTypeInputBuffer;
|
use UnknownTypeInputBuffer;
|
||||||
use UnknownTypeOutputBuffer;
|
use UnknownTypeOutputBuffer;
|
||||||
|
|
||||||
|
@ -26,7 +29,7 @@ pub struct EventLoop {
|
||||||
/// Total stream count
|
/// Total stream count
|
||||||
stream_count: AtomicUsize,
|
stream_count: AtomicUsize,
|
||||||
/// The CPAL callback that the user gives to fill the buffers.
|
/// The CPAL callback that the user gives to fill the buffers.
|
||||||
callbacks: Arc<Mutex<Option<&'static mut (FnMut(StreamId, StreamData) + Send)>>>,
|
callbacks: Arc<Mutex<Option<&'static mut (FnMut(StreamId, StreamDataResult) + Send)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Id for each stream.
|
/// Id for each stream.
|
||||||
|
@ -35,13 +38,6 @@ pub struct EventLoop {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct StreamId(usize);
|
pub struct StreamId(usize);
|
||||||
|
|
||||||
pub struct InputBuffer<'a, T: 'a> {
|
|
||||||
buffer: &'a [T],
|
|
||||||
}
|
|
||||||
pub struct OutputBuffer<'a, T: 'a> {
|
|
||||||
buffer: &'a mut [T],
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CPAL stream.
|
/// CPAL stream.
|
||||||
/// This decouples the many cpal streams
|
/// This decouples the many cpal streams
|
||||||
/// from the single input and single output
|
/// from the single input and single output
|
||||||
|
@ -92,8 +88,8 @@ impl EventLoop {
|
||||||
&self,
|
&self,
|
||||||
drivers: &sys::Drivers,
|
drivers: &sys::Drivers,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
num_asio_channels: u16,
|
num_asio_channels: u16,
|
||||||
) -> Result<(), CreationError> {
|
) -> Result<(), BuildStreamError> {
|
||||||
let Format {
|
let Format {
|
||||||
channels,
|
channels,
|
||||||
sample_rate,
|
sample_rate,
|
||||||
|
@ -107,16 +103,16 @@ impl EventLoop {
|
||||||
.set_sample_rate(sample_rate)
|
.set_sample_rate(sample_rate)
|
||||||
.expect("Unsupported sample rate");
|
.expect("Unsupported sample rate");
|
||||||
} else {
|
} else {
|
||||||
return Err(CreationError::FormatNotSupported);
|
return Err(BuildStreamError::FormatNotSupported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// unsigned formats are not supported by asio
|
// unsigned formats are not supported by asio
|
||||||
match data_type {
|
match data_type {
|
||||||
SampleFormat::I16 | SampleFormat::F32 => (),
|
SampleFormat::I16 | SampleFormat::F32 => (),
|
||||||
SampleFormat::U16 => return Err(CreationError::FormatNotSupported),
|
SampleFormat::U16 => return Err(BuildStreamError::FormatNotSupported),
|
||||||
}
|
}
|
||||||
if *channels > num_asio_channels {
|
if *channels > num_asio_channels {
|
||||||
return Err(CreationError::FormatNotSupported);
|
return Err(BuildStreamError::FormatNotSupported);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -129,13 +125,13 @@ impl EventLoop {
|
||||||
drivers: &sys::Drivers,
|
drivers: &sys::Drivers,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
) -> Result<usize, CreationError> {
|
) -> Result<usize, BuildStreamError> {
|
||||||
match device.default_input_format() {
|
match device.default_input_format() {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
let num_asio_channels = f.channels;
|
let num_asio_channels = f.channels;
|
||||||
self.check_format(drivers, format, num_asio_channels)
|
self.check_format(drivers, format, num_asio_channels)
|
||||||
},
|
},
|
||||||
Err(_) => Err(CreationError::FormatNotSupported),
|
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
||||||
}?;
|
}?;
|
||||||
let num_channels = format.channels as usize;
|
let num_channels = format.channels as usize;
|
||||||
let ref mut streams = *self.asio_streams.lock().unwrap();
|
let ref mut streams = *self.asio_streams.lock().unwrap();
|
||||||
|
@ -156,7 +152,7 @@ impl EventLoop {
|
||||||
bs
|
bs
|
||||||
}).map_err(|ref e| {
|
}).map_err(|ref e| {
|
||||||
println!("Error preparing stream: {}", e);
|
println!("Error preparing stream: {}", e);
|
||||||
CreationError::DeviceNotAvailable
|
BuildStreamError::DeviceNotAvailable
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,13 +166,13 @@ impl EventLoop {
|
||||||
drivers: &sys::Drivers,
|
drivers: &sys::Drivers,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
) -> Result<usize, CreationError> {
|
) -> Result<usize, BuildStreamError> {
|
||||||
match device.default_output_format() {
|
match device.default_output_format() {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
let num_asio_channels = f.channels;
|
let num_asio_channels = f.channels;
|
||||||
self.check_format(drivers, format, num_asio_channels)
|
self.check_format(drivers, format, num_asio_channels)
|
||||||
},
|
},
|
||||||
Err(_) => Err(CreationError::FormatNotSupported),
|
Err(_) => Err(BuildStreamError::FormatNotSupported),
|
||||||
}?;
|
}?;
|
||||||
let num_channels = format.channels as usize;
|
let num_channels = format.channels as usize;
|
||||||
let ref mut streams = *self.asio_streams.lock().unwrap();
|
let ref mut streams = *self.asio_streams.lock().unwrap();
|
||||||
|
@ -197,18 +193,18 @@ impl EventLoop {
|
||||||
bs
|
bs
|
||||||
}).map_err(|ref e| {
|
}).map_err(|ref e| {
|
||||||
println!("Error preparing stream: {}", e);
|
println!("Error preparing stream: {}", e);
|
||||||
CreationError::DeviceNotAvailable
|
BuildStreamError::DeviceNotAvailable
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a new cpal input stream
|
/// Builds a new cpal input stream
|
||||||
pub fn build_input_stream(
|
pub fn build_input_stream(
|
||||||
&self,
|
&self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, BuildStreamError> {
|
||||||
let Device { drivers, .. } = device;
|
let Device { drivers, .. } = device;
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
@ -328,7 +324,7 @@ impl EventLoop {
|
||||||
$SampleTypeIdent:ident,
|
$SampleTypeIdent:ident,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
(*$Sample as f64 * ::std::$SampleTypeIdent::MAX as f64) as $SampleType
|
(*$Sample as f64 * ::std::$SampleTypeIdent::MAX as f64) as $SampleType
|
||||||
};
|
};
|
||||||
(f64,
|
(f64,
|
||||||
$SampleType:ty,
|
$SampleType:ty,
|
||||||
|
@ -396,18 +392,14 @@ impl EventLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the buffer in the CPAL type
|
|
||||||
let buff = InputBuffer {
|
|
||||||
buffer: &mut $Buffers.cpal,
|
|
||||||
};
|
|
||||||
// Call the users callback with the buffer
|
// Call the users callback with the buffer
|
||||||
callback(
|
callback(
|
||||||
StreamId(count),
|
StreamId(count),
|
||||||
StreamData::Input {
|
Ok(StreamData::Input {
|
||||||
buffer: UnknownTypeInputBuffer::$SampleFormat(::InputBuffer {
|
buffer: UnknownTypeInputBuffer::$SampleFormat(::InputBuffer {
|
||||||
buffer: Some(super::super::InputBuffer::Asio(buff)),
|
buffer: &$Buffers.cpal,
|
||||||
}),
|
}),
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -542,7 +534,7 @@ impl EventLoop {
|
||||||
&self,
|
&self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
format: &Format,
|
format: &Format,
|
||||||
) -> Result<StreamId, CreationError> {
|
) -> Result<StreamId, BuildStreamError> {
|
||||||
let Device { drivers, .. } = device;
|
let Device { drivers, .. } = device;
|
||||||
let num_channels = format.channels.clone();
|
let num_channels = format.channels.clone();
|
||||||
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
let stream_type = drivers.get_data_type().expect("Couldn't load data type");
|
||||||
|
@ -626,28 +618,28 @@ impl EventLoop {
|
||||||
f32,
|
f32,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
*$Sample as f64
|
*$Sample as f64
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
f32,
|
f32,
|
||||||
f64,
|
f64,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
*$Sample as f32
|
*$Sample as f32
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
$AsioType:ty,
|
$AsioType:ty,
|
||||||
f32,
|
f32,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
(*$Sample as f64 * ::std::$AsioTypeIdent::MAX as f64) as $AsioType
|
(*$Sample as f64 * ::std::$AsioTypeIdent::MAX as f64) as $AsioType
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
$AsioType:ty,
|
$AsioType:ty,
|
||||||
f64,
|
f64,
|
||||||
$Sample:expr
|
$Sample:expr
|
||||||
) => {
|
) => {
|
||||||
(*$Sample as f64 * ::std::$AsioTypeIdent::MAX as f64) as $AsioType
|
(*$Sample as f64 * ::std::$AsioTypeIdent::MAX as f64) as $AsioType
|
||||||
};
|
};
|
||||||
($AsioTypeIdent:ident,
|
($AsioTypeIdent:ident,
|
||||||
f32,
|
f32,
|
||||||
|
@ -695,15 +687,13 @@ impl EventLoop {
|
||||||
// users data
|
// users data
|
||||||
callback(
|
callback(
|
||||||
StreamId(count),
|
StreamId(count),
|
||||||
StreamData::Output {
|
Ok(StreamData::Output {
|
||||||
buffer: UnknownTypeOutputBuffer::$SampleFormat(
|
buffer: UnknownTypeOutputBuffer::$SampleFormat(
|
||||||
::OutputBuffer {
|
::OutputBuffer {
|
||||||
target: Some(super::super::OutputBuffer::Asio(
|
buffer: &mut my_buffers.cpal,
|
||||||
buff,
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Deinter all the channels
|
// Deinter all the channels
|
||||||
|
@ -897,7 +887,7 @@ impl EventLoop {
|
||||||
|
|
||||||
/// Play the cpal stream for the given ID.
|
/// Play the cpal stream for the given ID.
|
||||||
/// Also play The ASIO streams if they are not already.
|
/// Also play The ASIO streams if they are not already.
|
||||||
pub fn play_stream(&self, stream_id: StreamId) {
|
pub fn play_stream(&self, stream_id: StreamId) -> Result<(), PlayStreamError> {
|
||||||
let mut streams = self.cpal_streams.lock().unwrap();
|
let mut streams = self.cpal_streams.lock().unwrap();
|
||||||
if let Some(s) = streams.get_mut(stream_id.0).expect("Bad play stream index") {
|
if let Some(s) = streams.get_mut(stream_id.0).expect("Bad play stream index") {
|
||||||
s.playing = true;
|
s.playing = true;
|
||||||
|
@ -908,7 +898,7 @@ impl EventLoop {
|
||||||
|
|
||||||
/// Pause the cpal stream for the given ID.
|
/// Pause the cpal stream for the given ID.
|
||||||
/// Pause the ASIO streams if there are no CPAL streams palying.
|
/// Pause the ASIO streams if there are no CPAL streams palying.
|
||||||
pub fn pause_stream(&self, stream_id: StreamId) {
|
pub fn pause_stream(&self, stream_id: StreamId) -> Result<(), PauseStreamError> {
|
||||||
let mut streams = self.cpal_streams.lock().unwrap();
|
let mut streams = self.cpal_streams.lock().unwrap();
|
||||||
if let Some(s) = streams
|
if let Some(s) = streams
|
||||||
.get_mut(stream_id.0)
|
.get_mut(stream_id.0)
|
||||||
|
@ -933,9 +923,9 @@ impl EventLoop {
|
||||||
/// Run the cpal callbacks
|
/// Run the cpal callbacks
|
||||||
pub fn run<F>(&self, mut callback: F) -> !
|
pub fn run<F>(&self, mut callback: F) -> !
|
||||||
where
|
where
|
||||||
F: FnMut(StreamId, StreamData) + Send,
|
F: FnMut(StreamId, StreamDataResult) + Send,
|
||||||
{
|
{
|
||||||
let callback: &mut (FnMut(StreamId, StreamData) + Send) = &mut callback;
|
let callback: &mut (FnMut(StreamId, StreamDataResult) + Send) = &mut callback;
|
||||||
// Transmute needed to convince the compiler that the callback has a static lifetime
|
// Transmute needed to convince the compiler that the callback has a static lifetime
|
||||||
*self.callbacks.lock().unwrap() = Some(unsafe { mem::transmute(callback) });
|
*self.callbacks.lock().unwrap() = Some(unsafe { mem::transmute(callback) });
|
||||||
loop {
|
loop {
|
||||||
|
@ -958,25 +948,6 @@ impl Drop for EventLoop {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> InputBuffer<'a, T> {
|
|
||||||
pub fn buffer(&self) -> &[T] {
|
|
||||||
&self.buffer
|
|
||||||
}
|
|
||||||
pub fn finish(self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> OutputBuffer<'a, T> {
|
|
||||||
pub fn buffer(&mut self) -> &mut [T] {
|
|
||||||
&mut self.buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.buffer.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn finish(self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to convert to system endianness
|
/// Helper function to convert to system endianness
|
||||||
fn convert_endian_to<T: PrimInt>(sample: T, endian: Endian) -> T {
|
fn convert_endian_to<T: PrimInt>(sample: T, endian: Endian) -> T {
|
||||||
match endian {
|
match endian {
|
|
@ -1,5 +1,7 @@
|
||||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||||
pub(crate) mod alsa;
|
pub(crate) mod alsa;
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub(crate) mod asio;
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
pub(crate) mod coreaudio;
|
pub(crate) mod coreaudio;
|
||||||
#[cfg(target_os = "emscripten")]
|
#[cfg(target_os = "emscripten")]
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
/// The cpal::os module provides operating-system-specific
|
|
||||||
/// functionality. If you are using this module within a
|
|
||||||
/// cross-platform project, you may wish to use
|
|
||||||
/// cfg(target_os = "<os_name>") to ensure that you only
|
|
||||||
/// use the OS-specific items when compiling for that OS.
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub mod windows;
|
|
|
@ -1,36 +0,0 @@
|
||||||
/// This allows you to choose either Wasapi or ASIO
|
|
||||||
/// as your back end. Wasapi is the default.
|
|
||||||
/// The CPAL_ASIO_DIR must be set to the ASIO SDK
|
|
||||||
/// directory for use_asio_backend to be available.
|
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum BackEnd {
|
|
||||||
Wasapi,
|
|
||||||
Asio,
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref BACK_END: Mutex<BackEnd> = Mutex::new(BackEnd::Wasapi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See which beackend is currently set.
|
|
||||||
pub fn which_backend() -> BackEnd {
|
|
||||||
(*BACK_END.lock().unwrap()).clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(asio)]
|
|
||||||
/// Choose ASIO as the backend
|
|
||||||
pub fn use_asio_backend() -> Result<(), BackEndError> {
|
|
||||||
*BACK_END.lock().unwrap() = BackEnd::Asio;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Choose Wasapi as the backend
|
|
||||||
pub fn use_wasapi_backend() -> Result<(), BackEndError> {
|
|
||||||
*BACK_END.lock().unwrap() = BackEnd::Wasapi;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BackEndError;
|
|
|
@ -516,6 +516,15 @@ mod platform_impl {
|
||||||
// TODO: Add `Asio asio` once #221 lands.
|
// TODO: Add `Asio asio` once #221 lands.
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod platform_impl {
|
mod platform_impl {
|
||||||
|
pub use crate::host::asio::{
|
||||||
|
Device as AsioDevice,
|
||||||
|
Devices as AsioDevices,
|
||||||
|
EventLoop as AsioEventLoop,
|
||||||
|
Host as AsioHost,
|
||||||
|
StreamId as AsioStreamId,
|
||||||
|
SupportedInputFormats as AsioSupportedInputFormats,
|
||||||
|
SupportedOutputFormats as AsioSupportedOutputFormats,
|
||||||
|
};
|
||||||
pub use crate::host::wasapi::{
|
pub use crate::host::wasapi::{
|
||||||
Device as WasapiDevice,
|
Device as WasapiDevice,
|
||||||
Devices as WasapiDevices,
|
Devices as WasapiDevices,
|
||||||
|
@ -526,7 +535,7 @@ mod platform_impl {
|
||||||
SupportedOutputFormats as WasapiSupportedOutputFormats,
|
SupportedOutputFormats as WasapiSupportedOutputFormats,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl_platform_host!(Wasapi wasapi);
|
impl_platform_host!(Asio asio, Wasapi wasapi);
|
||||||
|
|
||||||
/// The default host for the current compilation target platform.
|
/// The default host for the current compilation target platform.
|
||||||
pub fn default_host() -> Host {
|
pub fn default_host() -> Host {
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
extern crate asio_sys as sys;
|
|
||||||
|
|
||||||
pub use self::device::{Device, Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device};
|
|
||||||
|
|
||||||
pub use self::stream::{InputBuffer, OutputBuffer, EventLoop, StreamId};
|
|
||||||
|
|
||||||
mod device;
|
|
||||||
mod stream;
|
|
||||||
mod asio_utils;
|
|
|
@ -1,2 +0,0 @@
|
||||||
#[cfg(windows)]
|
|
||||||
mod asio;
|
|
Loading…
Reference in New Issue