Add SupportedFormat (#168)

This commit is contained in:
tomaka 2017-10-20 21:18:40 +02:00 committed by GitHub
parent 393206bde9
commit 87949d859b
9 changed files with 75 additions and 30 deletions

View File

@ -6,3 +6,5 @@
and `EventLoop::pause` that can be used to create, destroy, play and pause voices. and `EventLoop::pause` that can be used to create, destroy, play and pause voices.
- Added a `VoiceId` struct that is now used to identify a voice owned by an `EventLoop`. - Added a `VoiceId` struct that is now used to identify a voice owned by an `EventLoop`.
- Changed `EventLoop::run()` to take a callback that is called whenever a voice requires sound data. - Changed `EventLoop::run()` to take a callback that is called whenever a voice requires sound data.
- Changed `supported_formats()` to produce a list of `SupportedFormat` instead of `Format`. A
`SupportedFormat` must then be turned into a `Format` in order to build a voice.

View File

@ -6,7 +6,8 @@ fn main() {
.supported_formats() .supported_formats()
.unwrap() .unwrap()
.next() .next()
.expect("Failed to get endpoint format"); .expect("Failed to get endpoint format")
.with_max_samples_rate();
let event_loop = cpal::EventLoop::new(); let event_loop = cpal::EventLoop::new();
let voice_id = event_loop.build_voice(&endpoint, &format).unwrap(); let voice_id = event_loop.build_voice(&endpoint, &format).unwrap();

View File

@ -9,6 +9,7 @@ use Format;
use FormatsEnumerationError; use FormatsEnumerationError;
use SampleFormat; use SampleFormat;
use SamplesRate; use SamplesRate;
use SupportedFormat;
use UnknownTypeBuffer; use UnknownTypeBuffer;
use std::{cmp, ffi, iter, mem, ptr}; use std::{cmp, ffi, iter, mem, ptr};
@ -16,7 +17,7 @@ use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::vec::IntoIter as VecIntoIter; use std::vec::IntoIter as VecIntoIter;
pub type SupportedFormatsIterator = VecIntoIter<Format>; pub type SupportedFormatsIterator = VecIntoIter<SupportedFormat>;
mod enumerate; mod enumerate;
@ -152,10 +153,9 @@ impl Endpoint {
.expect("unable to get maximum supported rate"); .expect("unable to get maximum supported rate");
let samples_rates = if min_rate == max_rate { let samples_rates = if min_rate == max_rate {
vec![min_rate] vec![(min_rate, max_rate)]
/*} else if alsa::snd_pcm_hw_params_test_rate(playback_handle, hw_params.0, min_rate + 1, 0) == 0 { } else if alsa::snd_pcm_hw_params_test_rate(playback_handle, hw_params.0, min_rate + 1, 0) == 0 {
(min_rate .. max_rate + 1).collect()*/ vec![(min_rate, max_rate)]
// TODO: code is correct but returns lots of stuff
} else { } else {
const RATES: [libc::c_uint; 13] = [ const RATES: [libc::c_uint; 13] = [
5512, 5512,
@ -180,15 +180,15 @@ impl Endpoint {
rate, rate,
0) == 0 0) == 0
{ {
rates.push(rate); rates.push((rate, rate));
} }
} }
/*if rates.len() == 0 { if rates.len() == 0 {
(min_rate .. max_rate + 1).collect() vec![(min_rate, max_rate)]
} else {*/ } else {
rates // TODO: code is correct but returns lots of stuff rates
//} }
}; };
let mut min_channels = mem::uninitialized(); let mut min_channels = mem::uninitialized();
@ -227,10 +227,11 @@ impl Endpoint {
samples_rates.len()); samples_rates.len());
for &data_type in supported_formats.iter() { for &data_type in supported_formats.iter() {
for channels in supported_channels.iter() { for channels in supported_channels.iter() {
for &rate in samples_rates.iter() { for &(min_rate, max_rate) in samples_rates.iter() {
output.push(Format { output.push(SupportedFormat {
channels: channels.clone(), channels: channels.clone(),
samples_rate: SamplesRate(rate as u32), min_samples_rate: SamplesRate(min_rate as u32),
max_samples_rate: SamplesRate(max_rate as u32),
data_type: data_type, data_type: data_type,
}); });
} }

View File

@ -1,6 +1,7 @@
use super::Endpoint; use super::Endpoint;
use Format; use Format;
use SupportedFormat;
use std::vec::IntoIter as VecIntoIter; use std::vec::IntoIter as VecIntoIter;
@ -33,4 +34,4 @@ pub fn default_endpoint() -> Option<Endpoint> {
Some(Endpoint) Some(Endpoint)
} }
pub type SupportedFormatsIterator = VecIntoIter<Format>; pub type SupportedFormatsIterator = VecIntoIter<SupportedFormat>;

View File

@ -7,6 +7,7 @@ use FormatsEnumerationError;
use Sample; use Sample;
use SampleFormat; use SampleFormat;
use SamplesRate; use SamplesRate;
use SupportedFormat;
use UnknownTypeBuffer; use UnknownTypeBuffer;
use std::mem; use std::mem;
@ -30,9 +31,10 @@ impl Endpoint {
-> Result<SupportedFormatsIterator, FormatsEnumerationError> { -> Result<SupportedFormatsIterator, FormatsEnumerationError> {
Ok( Ok(
vec![ vec![
Format { SupportedFormat {
channels: vec![ChannelPosition::FrontLeft, ChannelPosition::FrontRight], channels: vec![ChannelPosition::FrontLeft, ChannelPosition::FrontRight],
samples_rate: SamplesRate(44100), min_samples_rate: SamplesRate(44100),
max_samples_rate: SamplesRate(44100),
data_type: SampleFormat::F32, data_type: SampleFormat::F32,
}, },
].into_iter(), ].into_iter(),

View File

@ -7,6 +7,7 @@ use CreationError;
use Format; use Format;
use FormatsEnumerationError; use FormatsEnumerationError;
use Sample; use Sample;
use SupportedFormat;
use UnknownTypeBuffer; use UnknownTypeBuffer;
extern { extern {
@ -182,9 +183,10 @@ impl Endpoint {
// TODO: right now cpal's API doesn't allow flexibility here // TODO: right now cpal's API doesn't allow flexibility here
// "44100" and "2" (channels) have also been hard-coded in the rest of the code ; if // "44100" and "2" (channels) have also been hard-coded in the rest of the code ; if
// this ever becomes more flexible, don't forget to change that // this ever becomes more flexible, don't forget to change that
Ok(vec![Format { Ok(vec![SupportedFormat {
channels: vec![::ChannelPosition::BackLeft, ::ChannelPosition::BackRight], channels: vec![::ChannelPosition::BackLeft, ::ChannelPosition::BackRight],
samples_rate: ::SamplesRate(44100), min_samples_rate: ::SamplesRate(44100),
max_samples_rate: ::SamplesRate(44100),
data_type: ::SampleFormat::F32, data_type: ::SampleFormat::F32,
}].into_iter()) }].into_iter())
} }
@ -195,7 +197,7 @@ impl Endpoint {
} }
} }
pub type SupportedFormatsIterator = ::std::vec::IntoIter<Format>; pub type SupportedFormatsIterator = ::std::vec::IntoIter<SupportedFormat>;
pub struct Buffer<'a, T: 'a> where T: Sample { pub struct Buffer<'a, T: 'a> where T: Sample {
temporary_buffer: Vec<T>, temporary_buffer: Vec<T>,

View File

@ -11,7 +11,8 @@ let endpoint = cpal::default_endpoint().unwrap();
// a `Result` to handle this situation // a `Result` to handle this situation
// getting a format for the PCM // getting a format for the PCM
let format = endpoint.supported_formats().unwrap().next().unwrap(); let supported_formats_range = endpoint.supported_formats().unwrap().next().unwrap();
let format = supported_formats_range.with_max_samples_rate();
let event_loop = cpal::EventLoop::new(); let event_loop = cpal::EventLoop::new();
@ -188,10 +189,10 @@ pub struct Format {
pub struct SupportedFormatsIterator(cpal_impl::SupportedFormatsIterator); pub struct SupportedFormatsIterator(cpal_impl::SupportedFormatsIterator);
impl Iterator for SupportedFormatsIterator { impl Iterator for SupportedFormatsIterator {
type Item = Format; type Item = SupportedFormat;
#[inline] #[inline]
fn next(&mut self) -> Option<Format> { fn next(&mut self) -> Option<SupportedFormat> {
self.0.next() self.0.next()
} }
@ -201,6 +202,39 @@ impl Iterator for SupportedFormatsIterator {
} }
} }
/// Describes a format.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SupportedFormat {
pub channels: Vec<ChannelPosition>,
pub min_samples_rate: SamplesRate,
pub max_samples_rate: SamplesRate,
pub data_type: SampleFormat,
}
impl SupportedFormat {
/// Builds a corresponding `Format` corresponding to the maximum samples rate.
#[inline]
pub fn with_max_samples_rate(self) -> Format {
Format {
channels: self.channels,
samples_rate: self.max_samples_rate,
data_type: self.data_type,
}
}
}
impl From<Format> for SupportedFormat {
#[inline]
fn from(format: Format) -> SupportedFormat {
SupportedFormat {
channels: format.channels,
min_samples_rate: format.samples_rate,
max_samples_rate: format.samples_rate,
data_type: format.data_type,
}
}
}
pub struct EventLoop(cpal_impl::EventLoop); pub struct EventLoop(cpal_impl::EventLoop);
impl EventLoop { impl EventLoop {

View File

@ -5,6 +5,7 @@ use std::marker::PhantomData;
use CreationError; use CreationError;
use Format; use Format;
use FormatsEnumerationError; use FormatsEnumerationError;
use SupportedFormat;
use UnknownTypeBuffer; use UnknownTypeBuffer;
pub struct EventLoop; pub struct EventLoop;
@ -84,10 +85,10 @@ impl Endpoint {
pub struct SupportedFormatsIterator; pub struct SupportedFormatsIterator;
impl Iterator for SupportedFormatsIterator { impl Iterator for SupportedFormatsIterator {
type Item = Format; type Item = SupportedFormat;
#[inline] #[inline]
fn next(&mut self) -> Option<Format> { fn next(&mut self) -> Option<SupportedFormat> {
None None
} }
} }

View File

@ -8,17 +8,17 @@ use std::slice;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use ChannelPosition; use ChannelPosition;
use Format;
use FormatsEnumerationError; use FormatsEnumerationError;
use SampleFormat; use SampleFormat;
use SamplesRate; use SamplesRate;
use SupportedFormat;
use super::check_result; use super::check_result;
use super::com; use super::com;
use super::ole32; use super::ole32;
use super::winapi; use super::winapi;
pub type SupportedFormatsIterator = OptionIntoIter<Format>; pub type SupportedFormatsIterator = OptionIntoIter<SupportedFormat>;
/// Wrapper because of that stupid decision to remove `Send` and `Sync` from raw pointers. /// Wrapper because of that stupid decision to remove `Send` and `Sync` from raw pointers.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -236,9 +236,10 @@ impl Endpoint {
f => panic!("Unknown data format returned by GetMixFormat: {:?}", f), f => panic!("Unknown data format returned by GetMixFormat: {:?}", f),
}; };
Format { SupportedFormat {
channels: channels, channels: channels,
samples_rate: SamplesRate((*format_ptr).nSamplesPerSec), min_samples_rate: SamplesRate((*format_ptr).nSamplesPerSec),
max_samples_rate: SamplesRate((*format_ptr).nSamplesPerSec),
data_type: data_type, data_type: data_type,
} }
}; };