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.
- 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 `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()
.unwrap()
.next()
.expect("Failed to get endpoint format");
.expect("Failed to get endpoint format")
.with_max_samples_rate();
let event_loop = cpal::EventLoop::new();
let voice_id = event_loop.build_voice(&endpoint, &format).unwrap();

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ use CreationError;
use Format;
use FormatsEnumerationError;
use Sample;
use SupportedFormat;
use UnknownTypeBuffer;
extern {
@ -182,9 +183,10 @@ impl Endpoint {
// 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
// this ever becomes more flexible, don't forget to change that
Ok(vec![Format {
Ok(vec![SupportedFormat {
channels: vec![::ChannelPosition::BackLeft, ::ChannelPosition::BackRight],
samples_rate: ::SamplesRate(44100),
min_samples_rate: ::SamplesRate(44100),
max_samples_rate: ::SamplesRate(44100),
data_type: ::SampleFormat::F32,
}].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 {
temporary_buffer: Vec<T>,

View File

@ -11,7 +11,8 @@ let endpoint = cpal::default_endpoint().unwrap();
// a `Result` to handle this situation
// 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();
@ -188,10 +189,10 @@ pub struct Format {
pub struct SupportedFormatsIterator(cpal_impl::SupportedFormatsIterator);
impl Iterator for SupportedFormatsIterator {
type Item = Format;
type Item = SupportedFormat;
#[inline]
fn next(&mut self) -> Option<Format> {
fn next(&mut self) -> Option<SupportedFormat> {
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);
impl EventLoop {

View File

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

View File

@ -8,17 +8,17 @@ use std::slice;
use std::sync::{Arc, Mutex, MutexGuard};
use ChannelPosition;
use Format;
use FormatsEnumerationError;
use SampleFormat;
use SamplesRate;
use SupportedFormat;
use super::check_result;
use super::com;
use super::ole32;
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.
#[derive(Copy, Clone)]
@ -236,9 +236,10 @@ impl Endpoint {
f => panic!("Unknown data format returned by GetMixFormat: {:?}", f),
};
Format {
SupportedFormat {
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,
}
};