Remove old `.rustfmt.toml` config. Run default `cargo fmt` on repo.

Seeing as a few large refactors have landed recently, I thought I'd take
this opportunity to do a `cargo fmt` run and standardise on the default
rustfmt settings.
This commit is contained in:
mitchmindtree 2020-01-20 20:35:23 +01:00
parent 95cda0dbe8
commit aab0d90add
20 changed files with 458 additions and 530 deletions

View File

@ -1,18 +0,0 @@
fn_args_density = "Compressed"
fn_args_layout = "Visual"
fn_brace_style = "SameLineWhere"
fn_call_style = "Visual"
fn_empty_single_line = false
format_strings = true
generics_indent = "Visual"
impl_empty_single_line = false
match_block_trailing_comma = true
reorder_imported_names = true
reorder_imports = true
reorder_imports_in_group = true
spaces_around_ranges = true
use_try_shorthand = true
where_density = "Tall"
where_style = "Legacy"
wrap_match_arms = false
write_mode = "Overwrite"

View File

@ -3,10 +3,10 @@ use std::env;
const CPAL_ASIO_DIR: &'static str = "CPAL_ASIO_DIR";
fn main() {
// If ASIO directory isn't set silently return early
// If ASIO directory isn't set silently return early
// otherwise set the asio config flag
match env::var(CPAL_ASIO_DIR) {
Err(_) => return,
Ok(_) => println!("cargo:rustc-cfg=asio"),
};
}
}

View File

@ -1,5 +1,5 @@
extern crate cpal;
extern crate anyhow;
extern crate cpal;
use cpal::traits::{DeviceTrait, HostTrait};
@ -30,12 +30,17 @@ fn main() -> Result<(), anyhow::Error> {
Err(e) => {
println!("Error: {:?}", e);
continue;
},
}
};
if input_formats.peek().is_some() {
println!(" All supported input stream formats:");
for (format_index, format) in input_formats.enumerate() {
println!(" {}.{}. {:?}", device_index + 1, format_index + 1, format);
println!(
" {}.{}. {:?}",
device_index + 1,
format_index + 1,
format
);
}
}
@ -48,12 +53,17 @@ fn main() -> Result<(), anyhow::Error> {
Err(e) => {
println!("Error: {:?}", e);
continue;
},
}
};
if output_formats.peek().is_some() {
println!(" All supported output stream formats:");
for (format_index, format) in output_formats.enumerate() {
println!(" {}.{}. {:?}", device_index + 1, format_index + 1, format);
println!(
" {}.{}. {:?}",
device_index + 1,
format_index + 1,
format
);
}
}
}

View File

@ -69,11 +69,14 @@ fn main() -> Result<(), anyhow::Error> {
Err(err) => {
input_fell_behind = Some(err);
0.0
},
}
};
}
if let Some(err) = input_fell_behind {
eprintln!("input stream fell behind: {:?}: try increasing latency", err);
eprintln!(
"input stream fell behind: {:?}: try increasing latency",
err
);
}
};

View File

@ -7,9 +7,9 @@ extern crate cpal;
extern crate hound;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::io::BufWriter;
use std::sync::{Arc, Mutex};
fn main() -> Result<(), anyhow::Error> {
// Use the default host for working with audio devices.
@ -40,12 +40,10 @@ fn main() -> Result<(), anyhow::Error> {
eprintln!("an error occurred on stream: {}", err);
};
let data_fn = move |data: &cpal::Data| {
match data.sample_format() {
cpal::SampleFormat::F32 => write_input_data::<f32, f32>(data, &writer_2),
cpal::SampleFormat::I16 => write_input_data::<i16, i16>(data, &writer_2),
cpal::SampleFormat::U16 => write_input_data::<u16, i16>(data, &writer_2),
}
let data_fn = move |data: &cpal::Data| match data.sample_format() {
cpal::SampleFormat::F32 => write_input_data::<f32, f32>(data, &writer_2),
cpal::SampleFormat::I16 => write_input_data::<i16, i16>(data, &writer_2),
cpal::SampleFormat::U16 => write_input_data::<u16, i16>(data, &writer_2),
};
let stream = device.build_input_stream(&format, data_fn, err_fn)?;

View File

@ -1,9 +1,9 @@
use {BackendSpecificError, DevicesError};
use super::Device;
use super::alsa;
use super::check_errors;
use super::Device;
use std::ffi::CString;
use std::ptr;
use {BackendSpecificError, DevicesError};
/// ALSA implementation for `Devices`.
pub struct Devices {
@ -36,10 +36,8 @@ impl Devices {
}
}
unsafe impl Send for Devices {
}
unsafe impl Sync for Devices {
}
unsafe impl Send for Devices {}
unsafe impl Sync for Devices {}
impl Drop for Devices {
#[inline]
@ -61,8 +59,10 @@ impl Iterator for Devices {
}
let name = {
let n_ptr = alsa::snd_device_name_get_hint(*self.next_str as *const _,
b"NAME\0".as_ptr() as *const _);
let n_ptr = alsa::snd_device_name_get_hint(
*self.next_str as *const _,
b"NAME\0".as_ptr() as *const _,
);
if !n_ptr.is_null() {
let bytes = CString::from_raw(n_ptr).into_bytes();
let string = String::from_utf8(bytes).unwrap();
@ -73,8 +73,10 @@ impl Iterator for Devices {
};
let io = {
let n_ptr = alsa::snd_device_name_get_hint(*self.next_str as *const _,
b"IOID\0".as_ptr() as *const _);
let n_ptr = alsa::snd_device_name_get_hint(
*self.next_str as *const _,
b"IOID\0".as_ptr() as *const _,
);
if !n_ptr.is_null() {
let bytes = CString::from_raw(n_ptr).into_bytes();
let string = String::from_utf8(bytes).unwrap();
@ -99,7 +101,7 @@ impl Iterator for Devices {
continue;
}
name
},
}
_ => continue,
};

View File

@ -2,26 +2,14 @@ extern crate alsa_sys as alsa;
extern crate libc;
use crate::{
BackendSpecificError,
BuildStreamError,
ChannelCount,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
PauseStreamError,
PlayStreamError,
SampleFormat,
SampleRate,
StreamError,
SupportedFormat,
SupportedFormatsError,
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultFormatError,
DeviceNameError, DevicesError, Format, PauseStreamError, PlayStreamError, SampleFormat,
SampleRate, StreamError, SupportedFormat, SupportedFormatsError,
};
use std::{cmp, ffi, io, ptr};
use std::sync::Arc;
use std::thread::{self, JoinHandle};
use std::vec::IntoIter as VecIntoIter;
use std::{cmp, ffi, io, ptr};
use traits::{DeviceTrait, HostTrait, StreamTrait};
pub use self::enumerate::{default_input_device, default_output_device, Devices};
@ -72,11 +60,15 @@ impl DeviceTrait for Device {
Device::name(self)
}
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
fn supported_input_formats(
&self,
) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
Device::supported_input_formats(self)
}
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
fn supported_output_formats(
&self,
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
Device::supported_output_formats(self)
}
@ -119,7 +111,6 @@ impl DeviceTrait for Device {
}
}
struct TriggerSender(libc::c_int);
struct TriggerReceiver(libc::c_int);
@ -247,8 +238,7 @@ impl Device {
unsafe fn supported_formats(
&self,
stream_t: alsa::snd_pcm_stream_t,
) -> Result<VecIntoIter<SupportedFormat>, SupportedFormatsError>
{
) -> Result<VecIntoIter<SupportedFormat>, SupportedFormatsError> {
let mut handle = ptr::null_mut();
let device_name = match ffi::CString::new(&self.0[..]) {
Ok(name) => name,
@ -284,14 +274,13 @@ impl Device {
};
// TODO: check endianess
const FORMATS: [(SampleFormat, alsa::snd_pcm_format_t); 3] =
[
//SND_PCM_FORMAT_S8,
//SND_PCM_FORMAT_U8,
(SampleFormat::I16, alsa::SND_PCM_FORMAT_S16_LE),
//SND_PCM_FORMAT_S16_BE,
(SampleFormat::U16, alsa::SND_PCM_FORMAT_U16_LE),
//SND_PCM_FORMAT_U16_BE,
const FORMATS: [(SampleFormat, alsa::snd_pcm_format_t); 3] = [
//SND_PCM_FORMAT_S8,
//SND_PCM_FORMAT_U8,
(SampleFormat::I16, alsa::SND_PCM_FORMAT_S16_LE),
//SND_PCM_FORMAT_S16_BE,
(SampleFormat::U16, alsa::SND_PCM_FORMAT_U16_LE),
//SND_PCM_FORMAT_U16_BE,
/*SND_PCM_FORMAT_S24_LE,
SND_PCM_FORMAT_S24_BE,
SND_PCM_FORMAT_U24_LE,
@ -300,37 +289,34 @@ impl Device {
SND_PCM_FORMAT_S32_BE,
SND_PCM_FORMAT_U32_LE,
SND_PCM_FORMAT_U32_BE,*/
(SampleFormat::F32, alsa::SND_PCM_FORMAT_FLOAT_LE) /*SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_FLOAT64_LE,
SND_PCM_FORMAT_FLOAT64_BE,
SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
SND_PCM_FORMAT_MU_LAW,
SND_PCM_FORMAT_A_LAW,
SND_PCM_FORMAT_IMA_ADPCM,
SND_PCM_FORMAT_MPEG,
SND_PCM_FORMAT_GSM,
SND_PCM_FORMAT_SPECIAL,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_U24_3LE,
SND_PCM_FORMAT_U24_3BE,
SND_PCM_FORMAT_S20_3LE,
SND_PCM_FORMAT_S20_3BE,
SND_PCM_FORMAT_U20_3LE,
SND_PCM_FORMAT_U20_3BE,
SND_PCM_FORMAT_S18_3LE,
SND_PCM_FORMAT_S18_3BE,
SND_PCM_FORMAT_U18_3LE,
SND_PCM_FORMAT_U18_3BE,*/,
];
(SampleFormat::F32, alsa::SND_PCM_FORMAT_FLOAT_LE), /*SND_PCM_FORMAT_FLOAT_BE,
SND_PCM_FORMAT_FLOAT64_LE,
SND_PCM_FORMAT_FLOAT64_BE,
SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
SND_PCM_FORMAT_MU_LAW,
SND_PCM_FORMAT_A_LAW,
SND_PCM_FORMAT_IMA_ADPCM,
SND_PCM_FORMAT_MPEG,
SND_PCM_FORMAT_GSM,
SND_PCM_FORMAT_SPECIAL,
SND_PCM_FORMAT_S24_3LE,
SND_PCM_FORMAT_S24_3BE,
SND_PCM_FORMAT_U24_3LE,
SND_PCM_FORMAT_U24_3BE,
SND_PCM_FORMAT_S20_3LE,
SND_PCM_FORMAT_S20_3BE,
SND_PCM_FORMAT_U20_3LE,
SND_PCM_FORMAT_U20_3BE,
SND_PCM_FORMAT_S18_3LE,
SND_PCM_FORMAT_S18_3BE,
SND_PCM_FORMAT_U18_3LE,
SND_PCM_FORMAT_U18_3BE,*/
];
let mut supported_formats = Vec::new();
for &(sample_format, alsa_format) in FORMATS.iter() {
if alsa::snd_pcm_hw_params_test_format(handle,
hw_params.0,
alsa_format) == 0
{
if alsa::snd_pcm_hw_params_test_format(handle, hw_params.0, alsa_format) == 0 {
supported_formats.push(sample_format);
}
}
@ -357,34 +343,19 @@ impl Device {
return Err(err.into());
}
let sample_rates = if min_rate == max_rate ||
alsa::snd_pcm_hw_params_test_rate(handle, hw_params.0, min_rate + 1, 0) == 0
let sample_rates = if min_rate == max_rate
|| alsa::snd_pcm_hw_params_test_rate(handle, hw_params.0, min_rate + 1, 0) == 0
{
vec![(min_rate, max_rate)]
} else {
const RATES: [libc::c_uint; 13] = [
5512,
8000,
11025,
16000,
22050,
32000,
44100,
48000,
64000,
88200,
96000,
176400,
5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000, 176400,
192000,
];
let mut rates = Vec::new();
for &rate in RATES.iter() {
if alsa::snd_pcm_hw_params_test_rate(handle,
hw_params.0,
rate,
0) == 0
{
if alsa::snd_pcm_hw_params_test_rate(handle, hw_params.0, rate, 0) == 0 {
rates.push((rate, rate));
}
}
@ -397,44 +368,48 @@ impl Device {
};
let mut min_channels = 0;
if let Err(desc) = check_errors(alsa::snd_pcm_hw_params_get_channels_min(hw_params.0, &mut min_channels)) {
if let Err(desc) = check_errors(alsa::snd_pcm_hw_params_get_channels_min(
hw_params.0,
&mut min_channels,
)) {
let description = format!("unable to get minimum supported channel count: {}", desc);
let err = BackendSpecificError { description };
return Err(err.into());
}
let mut max_channels = 0;
if let Err(desc) = check_errors(alsa::snd_pcm_hw_params_get_channels_max(hw_params.0, &mut max_channels)) {
if let Err(desc) = check_errors(alsa::snd_pcm_hw_params_get_channels_max(
hw_params.0,
&mut max_channels,
)) {
let description = format!("unable to get maximum supported channel count: {}", desc);
let err = BackendSpecificError { description };
return Err(err.into());
}
let max_channels = cmp::min(max_channels, 32); // TODO: limiting to 32 channels or too much stuff is returned
let supported_channels = (min_channels .. max_channels + 1)
.filter_map(|num| if alsa::snd_pcm_hw_params_test_channels(
handle,
hw_params.0,
num,
) == 0
{
Some(num as ChannelCount)
} else {
None
let supported_channels = (min_channels..max_channels + 1)
.filter_map(|num| {
if alsa::snd_pcm_hw_params_test_channels(handle, hw_params.0, num) == 0 {
Some(num as ChannelCount)
} else {
None
}
})
.collect::<Vec<_>>();
let mut output = Vec::with_capacity(supported_formats.len() * supported_channels.len() *
sample_rates.len());
let mut output = Vec::with_capacity(
supported_formats.len() * supported_channels.len() * sample_rates.len(),
);
for &data_type in supported_formats.iter() {
for channels in supported_channels.iter() {
for &(min_rate, max_rate) in sample_rates.iter() {
output.push(SupportedFormat {
channels: channels.clone(),
min_sample_rate: SampleRate(min_rate as u32),
max_sample_rate: SampleRate(max_rate as u32),
data_type: data_type,
});
channels: channels.clone(),
min_sample_rate: SampleRate(min_rate as u32),
max_sample_rate: SampleRate(max_rate as u32),
data_type: data_type,
});
}
}
}
@ -445,15 +420,11 @@ impl Device {
}
fn supported_input_formats(&self) -> Result<SupportedInputFormats, SupportedFormatsError> {
unsafe {
self.supported_formats(alsa::SND_PCM_STREAM_CAPTURE)
}
unsafe { self.supported_formats(alsa::SND_PCM_STREAM_CAPTURE) }
}
fn supported_output_formats(&self) -> Result<SupportedOutputFormats, SupportedFormatsError> {
unsafe {
self.supported_formats(alsa::SND_PCM_STREAM_PLAYBACK)
}
unsafe { self.supported_formats(alsa::SND_PCM_STREAM_PLAYBACK) }
}
// ALSA does not offer default stream formats, so instead we compare all supported formats by
@ -461,13 +432,12 @@ impl Device {
fn default_format(
&self,
stream_t: alsa::snd_pcm_stream_t,
) -> Result<Format, DefaultFormatError>
{
) -> Result<Format, DefaultFormatError> {
let mut formats: Vec<_> = unsafe {
match self.supported_formats(stream_t) {
Err(SupportedFormatsError::DeviceNotAvailable) => {
return Err(DefaultFormatError::DeviceNotAvailable);
},
}
Err(SupportedFormatsError::InvalidArgument) => {
// this happens sometimes when querying for input and output capabilities but
// the device supports only one
@ -492,8 +462,8 @@ impl Device {
format.sample_rate = HZ_44100;
}
Ok(format)
},
None => Err(DefaultFormatError::StreamTypeNotSupported)
}
None => Err(DefaultFormatError::StreamTypeNotSupported),
}
}
@ -536,7 +506,10 @@ unsafe impl Send for StreamInner {}
unsafe impl Sync for StreamInner {}
#[derive(Debug, Eq, PartialEq)]
enum StreamType { Input, Output }
enum StreamType {
Input,
Output,
}
pub struct Stream {
/// The high-priority audio processing thread calling callbacks.
@ -567,7 +540,10 @@ fn input_stream_worker(
match poll_descriptors_and_prepare_buffer(&rx, stream, &mut ctxt, error_callback) {
PollDescriptorsFlow::Continue => continue,
PollDescriptorsFlow::Return => return,
PollDescriptorsFlow::Ready { available_frames, stream_type } => {
PollDescriptorsFlow::Ready {
available_frames,
stream_type,
} => {
assert_eq!(
stream_type,
StreamType::Input,
@ -596,7 +572,10 @@ fn output_stream_worker(
match poll_descriptors_and_prepare_buffer(&rx, stream, &mut ctxt, error_callback) {
PollDescriptorsFlow::Continue => continue,
PollDescriptorsFlow::Return => return,
PollDescriptorsFlow::Ready { available_frames, stream_type } => {
PollDescriptorsFlow::Ready {
available_frames,
stream_type,
} => {
assert_eq!(
stream_type,
StreamType::Output,
@ -620,7 +599,7 @@ enum PollDescriptorsFlow {
Ready {
stream_type: StreamType,
available_frames: usize,
}
},
}
// This block is shared between both input and output stream worker functions.
@ -661,7 +640,11 @@ fn poll_descriptors_and_prepare_buffer(
let res = unsafe {
// Don't timeout, wait forever.
libc::poll(descriptors.as_mut_ptr(), descriptors.len() as libc::nfds_t, -1)
libc::poll(
descriptors.as_mut_ptr(),
descriptors.len() as libc::nfds_t,
-1,
)
};
if res < 0 {
let description = format!("`libc::poll()` failed: {}", io::Error::last_os_error());
@ -684,7 +667,7 @@ fn poll_descriptors_and_prepare_buffer(
Ok(None) => {
// Nothing to process, poll again
return PollDescriptorsFlow::Continue;
},
}
Err(err) => {
error_callback(err.into());
return PollDescriptorsFlow::Continue;
@ -739,9 +722,7 @@ fn process_input(
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)
};
let data = unsafe { Data::from_parts(data, len, sample_format) };
data_callback(&data);
}
@ -760,9 +741,7 @@ fn process_output(
let sample_format = stream.sample_format;
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)
};
let mut data = unsafe { Data::from_parts(data, len, sample_format) };
data_callback(&mut data);
}
loop {
@ -784,9 +763,8 @@ fn process_output(
} else if result as usize != available_frames {
let description = format!(
"unexpected number of frames written: expected {}, \
result {} (this should never happen)",
available_frames,
result,
result {} (this should never happen)",
available_frames, result,
);
error_callback(BackendSpecificError { description }.into());
continue;
@ -857,7 +835,7 @@ impl StreamTrait for Stream {
// TODO: error handling
Ok(())
}
fn pause(&self)-> Result<(), PauseStreamError> {
fn pause(&self) -> Result<(), PauseStreamError> {
unsafe {
alsa::snd_pcm_pause(self.inner.channel, 1);
}
@ -888,8 +866,7 @@ fn check_for_pollout_or_pollin(
(revent, res)
};
if let Err(desc) = check_errors(res) {
let description =
format!("`snd_pcm_poll_descriptors_revents` failed: {}",desc);
let description = format!("`snd_pcm_poll_descriptors_revents` failed: {}", desc);
let err = BackendSpecificError { description };
return Err(err);
}
@ -905,9 +882,7 @@ fn check_for_pollout_or_pollin(
// Determine the number of samples that are available to read/write.
fn get_available_samples(stream: &StreamInner) -> Result<usize, BackendSpecificError> {
let available = unsafe {
alsa::snd_pcm_avail_update(stream.channel)
};
let available = unsafe { alsa::snd_pcm_avail_update(stream.channel) };
if available == -32 {
// buffer underrun
// TODO: Notify the user some how.
@ -929,9 +904,11 @@ unsafe fn set_hw_params_from_format(
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_any(pcm_handle, hw_params.0)) {
return Err(format!("errors on pcm handle: {}", e));
}
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_access(pcm_handle,
hw_params.0,
alsa::SND_PCM_ACCESS_RW_INTERLEAVED)) {
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_access(
pcm_handle,
hw_params.0,
alsa::SND_PCM_ACCESS_RW_INTERLEAVED,
)) {
return Err(format!("handle not acessible: {}", e));
}
@ -949,21 +926,26 @@ unsafe fn set_hw_params_from_format(
}
};
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_format(pcm_handle,
hw_params.0,
data_type)) {
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_format(
pcm_handle,
hw_params.0,
data_type,
)) {
return Err(format!("format could not be set: {}", e));
}
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_rate(pcm_handle,
hw_params.0,
format.sample_rate.0 as libc::c_uint,
0)) {
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_rate(
pcm_handle,
hw_params.0,
format.sample_rate.0 as libc::c_uint,
0,
)) {
return Err(format!("sample rate could not be set: {}", e));
}
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_channels(pcm_handle,
hw_params.0,
format.channels as
libc::c_uint)) {
if let Err(e) = check_errors(alsa::snd_pcm_hw_params_set_channels(
pcm_handle,
hw_params.0,
format.channels as libc::c_uint,
)) {
return Err(format!("channel count could not be set: {}", e));
}
@ -987,8 +969,7 @@ unsafe fn set_hw_params_from_format(
unsafe fn set_sw_params_from_format(
pcm_handle: *mut alsa::snd_pcm_t,
format: &Format,
) -> Result<(usize, usize), String>
{
) -> Result<(usize, usize), String> {
let mut sw_params = ptr::null_mut(); // TODO: RAII
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_malloc(&mut sw_params)) {
return Err(format!("snd_pcm_sw_params_malloc failed: {}", e));
@ -996,20 +977,31 @@ unsafe fn set_sw_params_from_format(
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_current(pcm_handle, sw_params)) {
return Err(format!("snd_pcm_sw_params_current failed: {}", e));
}
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 0)) {
return Err(format!("snd_pcm_sw_params_set_start_threshold failed: {}", e));
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_set_start_threshold(
pcm_handle, sw_params, 0,
)) {
return Err(format!(
"snd_pcm_sw_params_set_start_threshold failed: {}",
e
));
}
let (buffer_len, period_len) = {
let mut buffer = 0;
let mut period = 0;
if let Err(e) = check_errors(alsa::snd_pcm_get_params(pcm_handle, &mut buffer, &mut period)) {
if let Err(e) = check_errors(alsa::snd_pcm_get_params(
pcm_handle,
&mut buffer,
&mut period,
)) {
return Err(format!("failed to initialize buffer: {}", e));
}
if buffer == 0 {
return Err(format!("initialization resulted in a null buffer"));
}
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_set_avail_min(pcm_handle, sw_params, period)) {
if let Err(e) = check_errors(alsa::snd_pcm_sw_params_set_avail_min(
pcm_handle, sw_params, period,
)) {
return Err(format!("snd_pcm_sw_params_set_avail_min failed: {}", e));
}
let buffer = buffer as usize * format.channels as usize;

View File

@ -2,8 +2,10 @@ use std;
pub type SupportedInputFormats = std::vec::IntoIter<SupportedFormat>;
pub type SupportedOutputFormats = std::vec::IntoIter<SupportedFormat>;
use super::parking_lot::Mutex;
use super::sys;
use std::hash::{Hash, Hasher};
use std::sync::{Arc};
use std::sync::Arc;
use BackendSpecificError;
use DefaultFormatError;
use DeviceNameError;
@ -13,8 +15,6 @@ use SampleFormat;
use SampleRate;
use SupportedFormat;
use SupportedFormatsError;
use super::sys;
use super::parking_lot::Mutex;
/// A ASIO Device
pub struct Device {
@ -55,9 +55,7 @@ impl Device {
/// Gets the supported input formats.
/// TODO currently only supports the default.
/// Need to find all possible formats.
pub fn supported_input_formats(
&self,
) -> Result<SupportedInputFormats, SupportedFormatsError> {
pub fn supported_input_formats(&self) -> Result<SupportedInputFormats, SupportedFormatsError> {
// Retrieve the default format for the total supported channels and supported sample
// format.
let mut f = match self.default_input_format() {
@ -68,7 +66,12 @@ impl Device {
// Collect a format for every combination of supported sample rate and number of channels.
let mut supported_formats = vec![];
for &rate in ::COMMON_SAMPLE_RATES {
if !self.driver.can_sample_rate(rate.0.into()).ok().unwrap_or(false) {
if !self
.driver
.can_sample_rate(rate.0.into())
.ok()
.unwrap_or(false)
{
continue;
}
for channels in 1..f.channels + 1 {
@ -96,7 +99,12 @@ impl Device {
// Collect a format for every combination of supported sample rate and number of channels.
let mut supported_formats = vec![];
for &rate in ::COMMON_SAMPLE_RATES {
if !self.driver.can_sample_rate(rate.0.into()).ok().unwrap_or(false) {
if !self
.driver
.can_sample_rate(rate.0.into())
.ok()
.unwrap_or(false)
{
continue;
}
for channels in 1..f.channels + 1 {
@ -114,8 +122,8 @@ impl Device {
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_format_err)? as _);
// Map th ASIO sample type to a CPAL sample type
let data_type = self.driver.input_data_type().map_err(default_format_err)?;
let data_type = convert_data_type(&data_type)
.ok_or(DefaultFormatError::StreamTypeNotSupported)?;
let data_type =
convert_data_type(&data_type).ok_or(DefaultFormatError::StreamTypeNotSupported)?;
Ok(Format {
channels,
sample_rate,
@ -128,8 +136,8 @@ impl Device {
let channels = self.driver.channels().map_err(default_format_err)?.outs as u16;
let sample_rate = SampleRate(self.driver.sample_rate().map_err(default_format_err)? as _);
let data_type = self.driver.output_data_type().map_err(default_format_err)?;
let data_type = convert_data_type(&data_type)
.ok_or(DefaultFormatError::StreamTypeNotSupported)?;
let data_type =
convert_data_type(&data_type).ok_or(DefaultFormatError::StreamTypeNotSupported)?;
Ok(Format {
channels,
sample_rate,
@ -159,10 +167,13 @@ impl Iterator for Devices {
input: None,
output: None,
}));
return Some(Device { driver, asio_streams });
return Some(Device {
driver,
asio_streams,
});
}
Err(_) => continue,
}
},
None => return None,
}
}
@ -193,8 +204,9 @@ pub(crate) fn convert_data_type(ty: &sys::AsioSampleType) -> Option<SampleFormat
fn default_format_err(e: sys::AsioError) -> DefaultFormatError {
match e {
sys::AsioError::NoDrivers |
sys::AsioError::HardwareMalfunction => DefaultFormatError::DeviceNotAvailable,
sys::AsioError::NoDrivers | sys::AsioError::HardwareMalfunction => {
DefaultFormatError::DeviceNotAvailable
}
sys::AsioError::NoRate => DefaultFormatError::StreamTypeNotSupported,
err => {
let description = format!("{}", err);

View File

@ -2,22 +2,10 @@ extern crate asio_sys as sys;
extern crate parking_lot;
use crate::{
BuildStreamError,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
PauseStreamError,
PlayStreamError,
StreamError,
SupportedFormatsError,
};
use traits::{
DeviceTrait,
HostTrait,
StreamTrait,
BuildStreamError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
PauseStreamError, PlayStreamError, StreamError, SupportedFormatsError,
};
use traits::{DeviceTrait, HostTrait, StreamTrait};
pub use self::device::{Device, Devices, SupportedInputFormats, SupportedOutputFormats};
pub use self::stream::Stream;
@ -73,11 +61,15 @@ impl DeviceTrait for Device {
Device::name(self)
}
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
fn supported_input_formats(
&self,
) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
Device::supported_input_formats(self)
}
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
fn supported_output_formats(
&self,
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
Device::supported_output_formats(self)
}
@ -97,7 +89,7 @@ impl DeviceTrait for Device {
) -> Result<Self::Stream, BuildStreamError>
where
D: FnMut(&Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static
E: FnMut(StreamError) + Send + 'static,
{
Device::build_input_stream(self, format, data_callback, error_callback)
}
@ -110,7 +102,7 @@ impl DeviceTrait for Device {
) -> Result<Self::Stream, BuildStreamError>
where
D: FnMut(&mut Data) + Send + 'static,
E: FnMut(StreamError) + Send + 'static
E: FnMut(StreamError) + Send + 'static,
{
Device::build_output_stream(self, format, data_callback, error_callback)
}

View File

@ -2,11 +2,11 @@ extern crate asio_sys as sys;
extern crate num_traits;
use self::num_traits::PrimInt;
use super::parking_lot::Mutex;
use super::Device;
use std;
use std::sync::atomic::{Ordering, AtomicBool};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use super::parking_lot::Mutex;
use BackendSpecificError;
use BuildStreamError;
use Data;
@ -93,7 +93,7 @@ impl Device {
let callback_id = self.driver.add_callback(move |buffer_index| unsafe {
// If not playing return early.
if !playing.load(Ordering::SeqCst) {
return
return;
}
// There is 0% chance of lock contention the host only locks when recreating streams.
@ -111,8 +111,7 @@ impl Device {
asio_stream: &sys::AsioStream,
buffer_index: usize,
from_endianness: F,
)
where
) where
A: AsioSample,
B: Sample,
D: FnMut(&Data) + Send + 'static,
@ -157,8 +156,8 @@ impl Device {
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
// trait for the `to_le` and `to_be` methods, but this does not support floats.
(&sys::AsioSampleType::ASIOSTFloat32LSB, SampleFormat::F32) |
(&sys::AsioSampleType::ASIOSTFloat32MSB, SampleFormat::F32) => {
(&sys::AsioSampleType::ASIOSTFloat32LSB, SampleFormat::F32)
| (&sys::AsioSampleType::ASIOSTFloat32MSB, SampleFormat::F32) => {
process_input_callback::<f32, f32, _, _>(
&mut data_callback,
&mut interleaved,
@ -191,8 +190,8 @@ impl Device {
}
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
// trait for the `to_le` and `to_be` methods, but this does not support floats.
(&sys::AsioSampleType::ASIOSTFloat64LSB, SampleFormat::F32) |
(&sys::AsioSampleType::ASIOSTFloat64MSB, SampleFormat::F32) => {
(&sys::AsioSampleType::ASIOSTFloat64LSB, SampleFormat::F32)
| (&sys::AsioSampleType::ASIOSTFloat64MSB, SampleFormat::F32) => {
process_input_callback::<f64, f32, _, _>(
&mut data_callback,
&mut interleaved,
@ -202,10 +201,11 @@ impl Device {
);
}
unsupported_format_pair => {
unreachable!("`build_input_stream` should have returned with unsupported \
format {:?}", unsupported_format_pair)
}
unsupported_format_pair => unreachable!(
"`build_input_stream` should have returned with unsupported \
format {:?}",
unsupported_format_pair
),
}
});
@ -258,7 +258,7 @@ impl Device {
let callback_id = self.driver.add_callback(move |buffer_index| unsafe {
// If not playing, return early.
if !playing.load(Ordering::SeqCst) {
return
return;
}
// There is 0% chance of lock contention the host only locks when recreating streams.
@ -301,8 +301,7 @@ impl Device {
asio_stream: &sys::AsioStream,
buffer_index: usize,
to_endianness: F,
)
where
) where
A: Sample,
B: AsioSample,
D: FnMut(&mut Data) + Send + 'static,
@ -321,7 +320,9 @@ impl Device {
for ch_ix in 0..n_channels {
let asio_channel =
asio_channel_slice_mut::<B>(asio_stream, buffer_index, ch_ix);
asio_channel.iter_mut().for_each(|s| *s = to_endianness(B::SILENCE));
asio_channel
.iter_mut()
.for_each(|s| *s = to_endianness(B::SILENCE));
}
}
@ -359,8 +360,8 @@ impl Device {
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
// trait for the `to_le` and `to_be` methods, but this does not support floats.
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32LSB) |
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32MSB) => {
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32LSB)
| (SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat32MSB) => {
process_output_callback::<f32, f32, _, _>(
&mut data_callback,
&mut interleaved,
@ -396,8 +397,8 @@ impl Device {
}
// TODO: Handle endianness conversion for floats? We currently use the `PrimInt`
// trait for the `to_le` and `to_be` methods, but this does not support floats.
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64LSB) |
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64MSB) => {
(SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64LSB)
| (SampleFormat::F32, &sys::AsioSampleType::ASIOSTFloat64MSB) => {
process_output_callback::<f32, f64, _, _>(
&mut data_callback,
&mut interleaved,
@ -408,10 +409,11 @@ impl Device {
);
}
unsupported_format_pair => {
unreachable!("`build_output_stream` should have returned with unsupported \
format {:?}", unsupported_format_pair)
}
unsupported_format_pair => unreachable!(
"`build_output_stream` should have returned with unsupported \
format {:?}",
unsupported_format_pair
),
}
});
@ -434,15 +436,12 @@ impl Device {
/// If there is no existing ASIO Input Stream it will be created.
///
/// On success, the buffer size of the stream is returned.
fn get_or_create_input_stream(
&self,
format: &Format,
) -> Result<usize, BuildStreamError> {
fn get_or_create_input_stream(&self, format: &Format) -> Result<usize, BuildStreamError> {
match self.default_input_format() {
Ok(f) => {
let num_asio_channels = f.channels;
check_format(&self.driver, format, num_asio_channels)
},
}
Err(_) => Err(BuildStreamError::FormatNotSupported),
}?;
let num_channels = format.channels as usize;
@ -462,7 +461,8 @@ impl Device {
};
*streams = new_streams;
bs
}).map_err(|ref e| {
})
.map_err(|ref e| {
println!("Error preparing stream: {}", e);
BuildStreamError::DeviceNotAvailable
})
@ -473,15 +473,12 @@ impl Device {
/// Create a new CPAL Output Stream.
///
/// If there is no existing ASIO Output Stream it will be created.
fn get_or_create_output_stream(
&self,
format: &Format,
) -> Result<usize, BuildStreamError> {
fn get_or_create_output_stream(&self, format: &Format) -> Result<usize, BuildStreamError> {
match self.default_output_format() {
Ok(f) => {
let num_asio_channels = f.channels;
check_format(&self.driver, format, num_asio_channels)
},
}
Err(_) => Err(BuildStreamError::FormatNotSupported),
}?;
let num_channels = format.channels as usize;
@ -501,7 +498,8 @@ impl Device {
};
*streams = new_streams;
bs
}).map_err(|ref e| {
})
.map_err(|ref e| {
println!("Error preparing stream: {}", e);
BuildStreamError::DeviceNotAvailable
})
@ -588,7 +586,10 @@ fn check_format(
// Try and set the sample rate to what the user selected.
let sample_rate = sample_rate.0.into();
if sample_rate != driver.sample_rate().map_err(build_stream_err)? {
if driver.can_sample_rate(sample_rate).map_err(build_stream_err)? {
if driver
.can_sample_rate(sample_rate)
.map_err(build_stream_err)?
{
driver
.set_sample_rate(sample_rate)
.map_err(build_stream_err)?;
@ -656,19 +657,17 @@ unsafe fn asio_channel_slice_mut<T>(
buffer_index: usize,
channel_index: usize,
) -> &mut [T] {
let buff_ptr: *mut T = asio_stream
.buffer_infos[channel_index]
.buffers[buffer_index as usize]
as *mut _;
let buff_ptr: *mut T =
asio_stream.buffer_infos[channel_index].buffers[buffer_index as usize] as *mut _;
std::slice::from_raw_parts_mut(buff_ptr, asio_stream.buffer_size as usize)
}
fn build_stream_err(e: sys::AsioError) -> BuildStreamError {
match e {
sys::AsioError::NoDrivers |
sys::AsioError::HardwareMalfunction => BuildStreamError::DeviceNotAvailable,
sys::AsioError::InvalidInput |
sys::AsioError::BadMode => BuildStreamError::InvalidArgument,
sys::AsioError::NoDrivers | sys::AsioError::HardwareMalfunction => {
BuildStreamError::DeviceNotAvailable
}
sys::AsioError::InvalidInput | sys::AsioError::BadMode => BuildStreamError::InvalidArgument,
err => {
let description = format!("{}", err);
BackendSpecificError { description }.into()

View File

@ -1,22 +1,15 @@
use {BackendSpecificError, DevicesError, SupportedFormat};
use super::coreaudio::sys::{
kAudioHardwareNoError, kAudioHardwarePropertyDefaultInputDevice,
kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDevices,
kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject,
AudioDeviceID, AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize,
AudioObjectPropertyAddress, OSStatus,
};
use super::Device;
use std::mem;
use std::ptr::null;
use std::vec::IntoIter as VecIntoIter;
use super::coreaudio::sys::{
AudioDeviceID,
AudioObjectPropertyAddress,
AudioObjectGetPropertyData,
AudioObjectGetPropertyDataSize,
kAudioHardwareNoError,
kAudioHardwarePropertyDefaultInputDevice,
kAudioHardwarePropertyDefaultOutputDevice,
kAudioHardwarePropertyDevices,
kAudioObjectPropertyElementMaster,
kAudioObjectPropertyScopeGlobal,
kAudioObjectSystemObject,
OSStatus,
};
use super::Device;
use {BackendSpecificError, DevicesError, SupportedFormat};
unsafe fn audio_devices() -> Result<Vec<AudioDeviceID>, OSStatus> {
let property_address = AudioObjectPropertyAddress {
@ -80,15 +73,15 @@ impl Devices {
}
}
unsafe impl Send for Devices {
}
unsafe impl Sync for Devices {
}
unsafe impl Send for Devices {}
unsafe impl Sync for Devices {}
impl Iterator for Devices {
type Item = Device;
fn next(&mut self) -> Option<Device> {
self.0.next().map(|id| Device { audio_device_id: id })
self.0.next().map(|id| Device {
audio_device_id: id,
})
}
}

View File

@ -1,67 +1,33 @@
extern crate coreaudio;
extern crate core_foundation_sys;
extern crate coreaudio;
use crate::{
ChannelCount,
BackendSpecificError,
BuildStreamError,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
PauseStreamError,
PlayStreamError,
SampleFormat,
SampleRate,
StreamError,
SupportedFormat,
SupportedFormatsError,
use self::core_foundation_sys::string::{CFStringGetCStringPtr, CFStringRef};
use self::coreaudio::audio_unit::render_callback::{self, data};
use self::coreaudio::audio_unit::{AudioUnit, Element, Scope};
use self::coreaudio::sys::{
kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceNameCFString,
kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput,
kAudioDevicePropertyStreamConfiguration, kAudioDevicePropertyStreamFormat,
kAudioFormatFlagIsFloat, kAudioFormatFlagIsPacked, kAudioFormatLinearPCM,
kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput,
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO,
kAudioUnitProperty_StreamFormat, kCFStringEncodingUTF8, AudioBuffer, AudioBufferList,
AudioDeviceID, AudioObjectAddPropertyListener, AudioObjectGetPropertyData,
AudioObjectGetPropertyDataSize, AudioObjectID, AudioObjectPropertyAddress,
AudioObjectPropertyScope, AudioObjectRemovePropertyListener, AudioObjectSetPropertyData,
AudioStreamBasicDescription, AudioValueRange, OSStatus,
};
use crate::traits::{DeviceTrait, HostTrait, StreamTrait};
use self::coreaudio::audio_unit::{AudioUnit, Scope, Element};
use self::coreaudio::audio_unit::render_callback::{self, data};
use self::coreaudio::sys::{
AudioBuffer,
AudioBufferList,
AudioDeviceID,
AudioObjectAddPropertyListener,
AudioObjectGetPropertyData,
AudioObjectGetPropertyDataSize,
AudioObjectID,
AudioObjectPropertyAddress,
AudioObjectPropertyScope,
AudioObjectRemovePropertyListener,
AudioObjectSetPropertyData,
AudioStreamBasicDescription,
AudioValueRange,
kAudioDevicePropertyAvailableNominalSampleRates,
kAudioDevicePropertyDeviceNameCFString,
kAudioDevicePropertyNominalSampleRate,
kAudioObjectPropertyScopeInput,
kAudioObjectPropertyScopeGlobal,
kAudioDevicePropertyScopeOutput,
kAudioDevicePropertyStreamConfiguration,
kAudioDevicePropertyStreamFormat,
kAudioFormatFlagIsFloat,
kAudioFormatFlagIsPacked,
kAudioFormatLinearPCM,
kAudioObjectPropertyElementMaster,
kAudioObjectPropertyScopeOutput,
kAudioOutputUnitProperty_CurrentDevice,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitProperty_StreamFormat,
kCFStringEncodingUTF8,
OSStatus,
};
use self::core_foundation_sys::string::{
CFStringRef,
CFStringGetCStringPtr,
use crate::{
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultFormatError,
DeviceNameError, DevicesError, Format, PauseStreamError, PlayStreamError, SampleFormat,
SampleRate, StreamError, SupportedFormat, SupportedFormatsError,
};
use std::cell::RefCell;
use std::ffi::CStr;
use std::fmt;
use std::mem;
use std::cell::RefCell;
use std::os::raw::c_char;
use std::ptr::null;
use std::slice;
@ -70,7 +36,10 @@ use std::time::Duration;
mod enumerate;
pub use self::enumerate::{Devices, SupportedInputFormats, SupportedOutputFormats, default_input_device, default_output_device};
pub use self::enumerate::{
default_input_device, default_output_device, Devices, SupportedInputFormats,
SupportedOutputFormats,
};
/// Coreaudio host, the default host on macOS and iOS.
#[derive(Debug)]
@ -107,17 +76,21 @@ impl HostTrait for Host {
impl DeviceTrait for Device {
type SupportedInputFormats = SupportedInputFormats;
type SupportedOutputFormats = SupportedOutputFormats;
type Stream = Stream;
type Stream = Stream;
fn name(&self) -> Result<String, DeviceNameError> {
Device::name(self)
}
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
fn supported_input_formats(
&self,
) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
Device::supported_input_formats(self)
}
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
fn supported_output_formats(
&self,
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
Device::supported_output_formats(self)
}
@ -196,8 +169,7 @@ impl Device {
fn supported_formats(
&self,
scope: AudioObjectPropertyScope,
) -> Result<SupportedOutputFormats, SupportedFormatsError>
{
) -> Result<SupportedOutputFormats, SupportedFormatsError> {
let mut property_address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyStreamConfiguration,
mScope: scope,
@ -307,17 +279,18 @@ impl Device {
fn default_format(
&self,
scope: AudioObjectPropertyScope,
) -> Result<Format, DefaultFormatError>
{
) -> Result<Format, DefaultFormatError> {
fn default_format_error_from_os_status(status: OSStatus) -> Result<(), DefaultFormatError> {
let err = match coreaudio::Error::from_os_status(status) {
Err(err) => err,
Ok(_) => return Ok(()),
};
match err {
coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::FormatNotSupported) |
coreaudio::Error::AudioCodec(_) |
coreaudio::Error::AudioFormat(_) => {
coreaudio::Error::AudioUnit(
coreaudio::error::AudioUnitError::FormatNotSupported,
)
| coreaudio::Error::AudioCodec(_)
| coreaudio::Error::AudioFormat(_) => {
Err(DefaultFormatError::StreamTypeNotSupported)
}
coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::NoConnection) => {
@ -412,11 +385,11 @@ struct StreamInner {
impl From<coreaudio::Error> for BuildStreamError {
fn from(err: coreaudio::Error) -> BuildStreamError {
match err {
coreaudio::Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat |
coreaudio::Error::NoKnownSubtype |
coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::FormatNotSupported) |
coreaudio::Error::AudioCodec(_) |
coreaudio::Error::AudioFormat(_) => BuildStreamError::FormatNotSupported,
coreaudio::Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat
| coreaudio::Error::NoKnownSubtype
| coreaudio::Error::AudioUnit(coreaudio::error::AudioUnitError::FormatNotSupported)
| coreaudio::Error::AudioCodec(_)
| coreaudio::Error::AudioFormat(_) => BuildStreamError::FormatNotSupported,
_ => BuildStreamError::DeviceNotAvailable,
}
}
@ -513,8 +486,8 @@ impl Device {
// Get the current sample rate.
let mut property_address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyNominalSampleRate,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster,
};
let sample_rate: f64 = 0.0;
let data_size = mem::size_of::<f64>() as u32;
@ -558,9 +531,9 @@ impl Device {
// Now that we have the available ranges, pick the one matching the desired rate.
let sample_rate = format.sample_rate.0;
let maybe_index = ranges
.iter()
.position(|r| r.mMinimum as u32 == sample_rate && r.mMaximum as u32 == sample_rate);
let maybe_index = ranges.iter().position(|r| {
r.mMinimum as u32 == sample_rate && r.mMaximum as u32 == sample_rate
});
let range_index = match maybe_index {
None => return Err(BuildStreamError::FormatNotSupported),
Some(i) => i,
@ -583,8 +556,8 @@ impl Device {
let data_size = mem::size_of::<f64>();
let property_address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyNominalSampleRate,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster,
};
AudioObjectGetPropertyData(
device_id,
@ -624,7 +597,8 @@ impl Device {
let timer = ::std::time::Instant::now();
while sample_rate != reported_rate {
if timer.elapsed() > Duration::from_secs(1) {
let description = "timeout waiting for sample rate update for device".into();
let description =
"timeout waiting for sample rate update for device".into();
let err = BackendSpecificError { description };
return Err(err.into());
}
@ -662,7 +636,7 @@ impl Device {
let AudioBuffer {
mNumberChannels: _num_channels,
mDataByteSize: data_byte_size,
mData: data
mData: data,
} = buffers[0];
let data = data as *mut ();
@ -713,7 +687,7 @@ impl Device {
let AudioBuffer {
mNumberChannels: _num_channels,
mDataByteSize: data_byte_size,
mData: data
mData: data,
} = (*args.data.data).mBuffers[0];
let data = data as *mut ();

View File

@ -2,23 +2,14 @@ use std::mem;
use std::os::raw::c_void;
use std::slice::from_raw_parts;
use stdweb;
use stdweb::Reference;
use stdweb::unstable::TryInto;
use stdweb::web::TypedArray;
use stdweb::web::set_timeout;
use stdweb::web::TypedArray;
use stdweb::Reference;
use crate::{
BuildStreamError,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
PauseStreamError,
PlayStreamError,
SampleFormat,
StreamError,
SupportedFormat,
BuildStreamError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
PauseStreamError, PlayStreamError, SampleFormat, StreamError, SupportedFormat,
SupportedFormatsError,
};
use traits::{DeviceTrait, HostTrait, StreamTrait};
@ -83,16 +74,13 @@ impl Device {
//
// UPDATE: We can do this now. Might be best to use `crate::COMMON_SAMPLE_RATES` and
// filter out those that lay outside the range specified above.
Ok(
vec![
SupportedFormat {
channels: 2,
min_sample_rate: ::SampleRate(44100),
max_sample_rate: ::SampleRate(44100),
data_type: ::SampleFormat::F32,
},
].into_iter(),
)
Ok(vec![SupportedFormat {
channels: 2,
min_sample_rate: ::SampleRate(44100),
max_sample_rate: ::SampleRate(44100),
data_type: ::SampleFormat::F32,
}]
.into_iter())
}
fn default_input_format(&self) -> Result<Format, DefaultFormatError> {
@ -101,13 +89,11 @@ impl Device {
fn default_output_format(&self) -> Result<Format, DefaultFormatError> {
// TODO: because it is hard coded, see supported_output_formats.
Ok(
Format {
channels: 2,
sample_rate: ::SampleRate(44100),
data_type: ::SampleFormat::F32,
},
)
Ok(Format {
channels: 2,
sample_rate: ::SampleRate(44100),
data_type: ::SampleFormat::F32,
})
}
}
@ -142,11 +128,15 @@ impl DeviceTrait for Device {
Device::name(self)
}
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
fn supported_input_formats(
&self,
) -> Result<Self::SupportedInputFormats, SupportedFormatsError> {
Device::supported_input_formats(self)
}
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
fn supported_output_formats(
&self,
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError> {
Device::supported_output_formats(self)
}
@ -201,7 +191,10 @@ impl DeviceTrait for Device {
//
// See also: The call to `set_timeout` at the end of the `audio_callback_fn` which creates
// the loop.
set_timeout(|| audio_callback_fn::<D, E>(user_data_ptr as *mut c_void), 10);
set_timeout(
|| audio_callback_fn::<D, E>(user_data_ptr as *mut c_void),
10,
);
Ok(stream)
}
@ -323,9 +316,10 @@ fn default_output_device() -> Option<Device> {
fn is_webaudio_available() -> bool {
stdweb::initialize();
js!(if (!AudioContext) {
return false;
} else {
return true;
}).try_into()
.unwrap()
return false;
} else {
return true;
})
.try_into()
.unwrap()
}

View File

@ -1,15 +1,6 @@
use crate::{
BuildStreamError,
Data,
DefaultFormatError,
DevicesError,
DeviceNameError,
Format,
PauseStreamError,
PlayStreamError,
StreamError,
SupportedFormatsError,
SupportedFormat,
BuildStreamError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
PauseStreamError, PlayStreamError, StreamError, SupportedFormat, SupportedFormatsError,
};
use traits::{DeviceTrait, HostTrait, StreamTrait};

View File

@ -1,15 +1,6 @@
use crate::{
BackendSpecificError,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
SampleFormat,
SampleRate,
SupportedFormat,
SupportedFormatsError,
COMMON_SAMPLE_RATES,
BackendSpecificError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
SampleFormat, SampleRate, SupportedFormat, SupportedFormatsError, COMMON_SAMPLE_RATES,
};
use std;
use std::ffi::OsString;
@ -115,7 +106,11 @@ impl DeviceTrait for Device {
E: FnMut(StreamError) + Send + 'static,
{
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<D, E>(
@ -129,7 +124,11 @@ impl DeviceTrait for Device {
E: FnMut(StreamError) + Send + 'static,
{
let stream_inner = self.build_output_stream_inner(format)?;
Ok(Stream::new_output(stream_inner, data_callback, error_callback))
Ok(Stream::new_output(
stream_inner,
data_callback,
error_callback,
))
}
}
@ -716,8 +715,7 @@ impl Device {
// Building a `IAudioCaptureClient` that will be used to read captured samples.
let capture_client = {
let mut capture_client: *mut audioclient::IAudioCaptureClient =
ptr::null_mut();
let mut capture_client: *mut audioclient::IAudioCaptureClient = ptr::null_mut();
let hresult = (*audio_client).GetService(
&audioclient::IID_IAudioCaptureClient,
&mut capture_client as *mut *mut audioclient::IAudioCaptureClient as *mut _,

View File

@ -1,16 +1,3 @@
use crate::{
BackendSpecificError,
Data,
PauseStreamError,
PlayStreamError,
SampleFormat,
StreamError,
};
use crate::traits::StreamTrait;
use std::mem;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread::{self, JoinHandle};
use super::check_result;
use super::winapi::shared::basetsd::UINT32;
use super::winapi::shared::minwindef::{BYTE, FALSE, WORD};
@ -19,6 +6,14 @@ use super::winapi::um::handleapi;
use super::winapi::um::synchapi;
use super::winapi::um::winbase;
use super::winapi::um::winnt;
use crate::traits::StreamTrait;
use crate::{
BackendSpecificError, Data, PauseStreamError, PlayStreamError, SampleFormat, StreamError,
};
use std::mem;
use std::ptr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread::{self, JoinHandle};
pub struct Stream {
/// The high-priority audio processing thread calling callbacks.
@ -295,7 +290,12 @@ fn run_input(
AudioClientFlow::Capture { capture_client } => capture_client,
_ => unreachable!(),
};
match process_input(&mut run_ctxt.stream, capture_client, data_callback, error_callback) {
match process_input(
&mut run_ctxt.stream,
capture_client,
data_callback,
error_callback,
) {
ControlFlow::Break => break,
ControlFlow::Continue => continue,
}
@ -317,7 +317,12 @@ fn run_output(
AudioClientFlow::Render { render_client } => render_client,
_ => unreachable!(),
};
match process_output(&mut run_ctxt.stream, render_client, data_callback, error_callback) {
match process_output(
&mut run_ctxt.stream,
render_client,
data_callback,
error_callback,
) {
ControlFlow::Break => break,
ControlFlow::Continue => continue,
}
@ -401,8 +406,7 @@ fn process_input(
debug_assert!(!buffer.is_null());
let data = buffer as *mut ();
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();
let data = Data::from_parts(data, len, stream.sample_format);
data_callback(&data);
@ -436,8 +440,7 @@ fn process_output(
unsafe {
let mut buffer: *mut BYTE = ptr::null_mut();
let hresult =
(*render_client).GetBuffer(frames_available, &mut buffer as *mut *mut _);
let hresult = (*render_client).GetBuffer(frames_available, &mut buffer as *mut *mut _);
if let Err(err) = stream_error_from_hresult(hresult) {
error_callback(err);
@ -447,8 +450,7 @@ fn process_output(
debug_assert!(!buffer.is_null());
let data = buffer as *mut ();
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();
let mut data = Data::from_parts(data, len, stream.sample_format);
data_callback(&mut data);

View File

@ -149,8 +149,8 @@ extern crate thiserror;
pub use error::*;
pub use platform::{
ALL_HOSTS, available_hosts, default_host, Device, Devices, Host, host_from_id,
HostId, Stream, SupportedInputFormats, SupportedOutputFormats,
available_hosts, default_host, host_from_id, Device, Devices, Host, HostId, Stream,
SupportedInputFormats, SupportedOutputFormats, ALL_HOSTS,
};
pub use samples_formats::{Sample, SampleFormat};
@ -218,7 +218,11 @@ impl Data {
len: usize,
sample_format: SampleFormat,
) -> Self {
Data { data, len, sample_format }
Data {
data,
len,
sample_format,
}
}
/// The sample format of the internal audio data.
@ -241,9 +245,7 @@ impl Data {
let len = self.len * self.sample_format.sample_size();
// The safety of this block relies on correct construction of the `Data` instance. See
// the unsafe `from_parts` constructor for these requirements.
unsafe {
std::slice::from_raw_parts(self.data as *const u8, len)
}
unsafe { std::slice::from_raw_parts(self.data as *const u8, len) }
}
/// The raw slice of memory representing the underlying audio data as a slice of bytes.
@ -253,9 +255,7 @@ impl Data {
let len = self.len * self.sample_format.sample_size();
// The safety of this block relies on correct construction of the `Data` instance. See
// the unsafe `from_parts` constructor for these requirements.
unsafe {
std::slice::from_raw_parts_mut(self.data as *mut u8, len)
}
unsafe { std::slice::from_raw_parts_mut(self.data as *mut u8, len) }
}
/// Access the data as a slice of sample type `T`.
@ -268,9 +268,7 @@ impl Data {
if T::FORMAT == self.sample_format {
// The safety of this block relies on correct construction of the `Data` instance. See
// the unsafe `from_parts` constructor for these requirements.
unsafe {
Some(std::slice::from_raw_parts(self.data as *const T, self.len))
}
unsafe { Some(std::slice::from_raw_parts(self.data as *const T, self.len)) }
} else {
None
}
@ -287,7 +285,10 @@ impl Data {
// The safety of this block relies on correct construction of the `Data` instance. See
// the unsafe `from_parts` constructor for these requirements.
unsafe {
Some(std::slice::from_raw_parts_mut(self.data as *mut T, self.len))
Some(std::slice::from_raw_parts_mut(
self.data as *mut T,
self.len,
))
}
} else {
None
@ -365,10 +366,9 @@ impl SupportedFormat {
}
const HZ_44100: SampleRate = SampleRate(44_100);
let r44100_in_self = self.min_sample_rate <= HZ_44100
&& HZ_44100 <= self.max_sample_rate;
let r44100_in_other = other.min_sample_rate <= HZ_44100
&& HZ_44100 <= other.max_sample_rate;
let r44100_in_self = self.min_sample_rate <= HZ_44100 && HZ_44100 <= self.max_sample_rate;
let r44100_in_other =
other.min_sample_rate <= HZ_44100 && HZ_44100 <= other.max_sample_rate;
let cmp_r44100 = r44100_in_self.cmp(&r44100_in_other);
if cmp_r44100 != Equal {
return cmp_r44100;

View File

@ -435,10 +435,7 @@ macro_rules! impl_platform_host {
#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))]
mod platform_impl {
pub use crate::host::alsa::{
Device as AlsaDevice,
Devices as AlsaDevices,
Host as AlsaHost,
Stream as AlsaStream,
Device as AlsaDevice, Devices as AlsaDevices, Host as AlsaHost, Stream as AlsaStream,
SupportedInputFormats as AlsaSupportedInputFormats,
SupportedOutputFormats as AlsaSupportedOutputFormats,
};
@ -453,15 +450,11 @@ mod platform_impl {
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod platform_impl {
pub use crate::host::coreaudio::{
Device as CoreAudioDevice,
Devices as CoreAudioDevices,
Host as CoreAudioHost,
Stream as CoreAudioStream,
SupportedInputFormats as CoreAudioSupportedInputFormats,
Device as CoreAudioDevice, Devices as CoreAudioDevices, Host as CoreAudioHost,
Stream as CoreAudioStream, SupportedInputFormats as CoreAudioSupportedInputFormats,
SupportedOutputFormats as CoreAudioSupportedOutputFormats,
};
@ -478,11 +471,8 @@ mod platform_impl {
#[cfg(target_os = "emscripten")]
mod platform_impl {
pub use crate::host::emscripten::{
Device as EmscriptenDevice,
Devices as EmscriptenDevices,
Host as EmscriptenHost,
Stream as EmscriptenStream,
SupportedInputFormats as EmscriptenSupportedInputFormats,
Device as EmscriptenDevice, Devices as EmscriptenDevices, Host as EmscriptenHost,
Stream as EmscriptenStream, SupportedInputFormats as EmscriptenSupportedInputFormats,
SupportedOutputFormats as EmscriptenSupportedOutputFormats,
};
@ -500,19 +490,13 @@ mod platform_impl {
mod platform_impl {
#[cfg(feature = "asio")]
pub use crate::host::asio::{
Device as AsioDevice,
Devices as AsioDevices,
Stream as AsioStream,
Host as AsioHost,
Device as AsioDevice, Devices as AsioDevices, Host as AsioHost, Stream as AsioStream,
SupportedInputFormats as AsioSupportedInputFormats,
SupportedOutputFormats as AsioSupportedOutputFormats,
};
pub use crate::host::wasapi::{
Device as WasapiDevice,
Devices as WasapiDevices,
Stream as WasapiStream,
Host as WasapiHost,
SupportedInputFormats as WasapiSupportedInputFormats,
Device as WasapiDevice, Devices as WasapiDevices, Host as WasapiHost,
Stream as WasapiStream, SupportedInputFormats as WasapiSupportedInputFormats,
SupportedOutputFormats as WasapiSupportedOutputFormats,
};
@ -530,16 +514,19 @@ mod platform_impl {
}
}
#[cfg(not(any(windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "macos",
target_os = "ios", target_os = "emscripten")))]
#[cfg(not(any(
windows,
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "macos",
target_os = "ios",
target_os = "emscripten"
)))]
mod platform_impl {
pub use crate::host::null::{
Device as NullDevice,
Devices as NullDevices,
EventLoop as NullEventLoop,
Host as NullHost,
StreamId as NullStreamId,
SupportedInputFormats as NullSupportedInputFormats,
Device as NullDevice, Devices as NullDevices, EventLoop as NullEventLoop, Host as NullHost,
StreamId as NullStreamId, SupportedInputFormats as NullSupportedInputFormats,
SupportedOutputFormats as NullSupportedOutputFormats,
};

View File

@ -37,7 +37,8 @@ pub unsafe trait Sample: Copy + Clone {
/// Converts any sample type to this one by calling `to_i16`, `to_u16` or `to_f32`.
fn from<S>(&S) -> Self
where S: Sample;
where
S: Sample;
}
unsafe impl Sample for u16 {
@ -64,7 +65,8 @@ unsafe impl Sample for u16 {
#[inline]
fn from<S>(sample: &S) -> Self
where S: Sample
where
S: Sample,
{
sample.to_u16()
}
@ -98,7 +100,8 @@ unsafe impl Sample for i16 {
#[inline]
fn from<S>(sample: &S) -> Self
where S: Sample
where
S: Sample,
{
sample.to_i16()
}
@ -128,7 +131,8 @@ unsafe impl Sample for f32 {
#[inline]
fn from<S>(sample: &S) -> Self
where S: Sample
where
S: Sample,
{
sample.to_f32()
}

View File

@ -1,18 +1,8 @@
//! The suite of traits allowing CPAL to abstract over hosts, devices, event loops and stream IDs.
use {
BuildStreamError,
Data,
DefaultFormatError,
DeviceNameError,
DevicesError,
Format,
InputDevices,
OutputDevices,
PauseStreamError,
PlayStreamError,
StreamError,
SupportedFormat,
BuildStreamError, Data, DefaultFormatError, DeviceNameError, DevicesError, Format,
InputDevices, OutputDevices, PauseStreamError, PlayStreamError, StreamError, SupportedFormat,
SupportedFormatsError,
};
@ -65,7 +55,8 @@ pub trait HostTrait {
/// Can be empty if the system does not support audio input.
fn input_devices(&self) -> Result<InputDevices<Self::Devices>, DevicesError> {
fn supports_input<D: DeviceTrait>(device: &D) -> bool {
device.supported_input_formats()
device
.supported_input_formats()
.map(|mut iter| iter.next().is_some())
.unwrap_or(false)
}
@ -78,7 +69,8 @@ pub trait HostTrait {
/// Can be empty if the system does not support audio output.
fn output_devices(&self) -> Result<OutputDevices<Self::Devices>, DevicesError> {
fn supports_output<D: DeviceTrait>(device: &D) -> bool {
device.supported_output_formats()
device
.supported_output_formats()
.map(|mut iter| iter.next().is_some())
.unwrap_or(false)
}
@ -104,12 +96,15 @@ pub trait DeviceTrait {
/// An iterator yielding formats that are supported by the backend.
///
/// Can return an error if the device is no longer valid (eg. it has been disconnected).
fn supported_input_formats(&self) -> Result<Self::SupportedInputFormats, SupportedFormatsError>;
fn supported_input_formats(&self)
-> Result<Self::SupportedInputFormats, SupportedFormatsError>;
/// An iterator yielding output stream formats that are supported by the device.
///
/// Can return an error if the device is no longer valid (eg. it has been disconnected).
fn supported_output_formats(&self) -> Result<Self::SupportedOutputFormats, SupportedFormatsError>;
fn supported_output_formats(
&self,
) -> Result<Self::SupportedOutputFormats, SupportedFormatsError>;
/// The default input stream format for the device.
fn default_input_format(&self) -> Result<Format, DefaultFormatError>;