#[macro_use]
extern crate lazy_static;
extern crate libc;
pub use samples_formats::{SampleFormat, Sample};
#[cfg(all(not(windows), not(target_os = "linux"), not(target_os = "macos")))]
use null as cpal_impl;
use std::fmt;
use std::error::Error;
use std::ops::{Deref, DerefMut};
mod null;
mod samples_formats;
#[cfg(target_os = "linux")]
#[path="alsa/mod.rs"]
mod cpal_impl;
#[cfg(windows)]
#[path="wasapi/mod.rs"]
mod cpal_impl;
#[cfg(target_os = "macos")]
#[path="coreaudio/mod.rs"]
mod cpal_impl;
pub struct EndpointsIterator(cpal_impl::EndpointsIterator);
impl Iterator for EndpointsIterator {
type Item = Endpoint;
#[inline]
fn next(&mut self) -> Option<Endpoint> {
self.0.next().map(Endpoint)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
#[inline]
pub fn get_endpoints_list() -> EndpointsIterator {
EndpointsIterator(Default::default())
}
#[inline]
pub fn get_default_endpoint() -> Option<Endpoint> {
cpal_impl::get_default_endpoint().map(Endpoint)
}
#[derive(Clone, PartialEq, Eq)]
pub struct Endpoint(cpal_impl::Endpoint);
impl Endpoint {
#[inline]
pub fn get_supported_formats_list(&self) -> Result<SupportedFormatsIterator,
FormatsEnumerationError>
{
Ok(SupportedFormatsIterator(try!(self.0.get_supported_formats_list())))
}
#[inline]
pub fn get_name(&self) -> String {
self.0.get_name()
}
}
pub type ChannelsCount = u16;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ChannelPosition {
FrontLeft,
FrontRight,
FrontCenter,
LowFrequency,
BackLeft,
BackRight,
FrontLeftOfCenter,
FrontRightOfCenter,
BackCenter,
SideLeft,
SideRight,
TopCenter,
TopFrontLeft,
TopFrontCenter,
TopFrontRight,
TopBackLeft,
TopBackCenter,
TopBackRight,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SamplesRate(pub u32);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Format {
pub channels: Vec<ChannelPosition>,
pub samples_rate: SamplesRate,
pub data_type: SampleFormat,
}
pub struct SupportedFormatsIterator(cpal_impl::SupportedFormatsIterator);
impl Iterator for SupportedFormatsIterator {
type Item = Format;
#[inline]
fn next(&mut self) -> Option<Format> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
#[must_use]
pub struct Buffer<'a, T: 'a> where T: Sample {
target: Option<cpal_impl::Buffer<'a, T>>,
}
pub enum UnknownTypeBuffer<'a> {
U16(Buffer<'a, u16>),
I16(Buffer<'a, i16>),
F32(Buffer<'a, f32>),
}
impl<'a> UnknownTypeBuffer<'a> {
#[inline]
pub fn len(&self) -> usize {
match self {
&UnknownTypeBuffer::U16(ref buf) => buf.target.as_ref().unwrap().len(),
&UnknownTypeBuffer::I16(ref buf) => buf.target.as_ref().unwrap().len(),
&UnknownTypeBuffer::F32(ref buf) => buf.target.as_ref().unwrap().len(),
}
}
}
#[derive(Debug)]
pub enum FormatsEnumerationError {
DeviceNotAvailable,
}
impl fmt::Display for FormatsEnumerationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.description())
}
}
impl Error for FormatsEnumerationError {
#[inline]
fn description(&self) -> &str {
match self {
&FormatsEnumerationError::DeviceNotAvailable => {
"The requested device is no longer available (for example, it has been unplugged)."
},
}
}
}
#[derive(Debug)]
pub enum CreationError {
DeviceNotAvailable,
FormatNotSupported,
}
impl fmt::Display for CreationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.description())
}
}
impl Error for CreationError {
#[inline]
fn description(&self) -> &str {
match self {
&CreationError::DeviceNotAvailable => {
"The requested device is no longer available (for example, it has been unplugged)."
},
&CreationError::FormatNotSupported => {
"The requested samples format is not supported by the device."
},
}
}
}
pub struct Voice {
voice: cpal_impl::Voice,
format: Format,
}
impl Voice {
#[inline]
pub fn new(endpoint: &Endpoint, format: &Format) -> Result<Voice, CreationError> {
let channel = try!(cpal_impl::Voice::new(&endpoint.0, format));
Ok(Voice {
voice: channel,
format: format.clone(),
})
}
#[inline]
pub fn format(&self) -> &Format {
&self.format
}
#[inline]
pub fn get_channels(&self) -> ChannelsCount {
self.format().channels.len() as ChannelsCount
}
#[inline]
pub fn get_samples_rate(&self) -> SamplesRate {
self.format().samples_rate
}
#[inline]
pub fn get_samples_format(&self) -> SampleFormat {
self.format().data_type
}
#[inline]
pub fn get_period(&self) -> usize {
self.voice.get_period()
}
#[inline]
pub fn append_data(&mut self, max_samples: usize) -> UnknownTypeBuffer {
assert!(max_samples != 0);
match self.get_samples_format() {
SampleFormat::U16 => UnknownTypeBuffer::U16(Buffer {
target: Some(self.voice.append_data(max_samples))
}),
SampleFormat::I16 => UnknownTypeBuffer::I16(Buffer {
target: Some(self.voice.append_data(max_samples))
}),
SampleFormat::F32 => UnknownTypeBuffer::F32(Buffer {
target: Some(self.voice.append_data(max_samples))
}),
}
}
#[inline]
pub fn play(&mut self) {
self.voice.play()
}
#[inline]
pub fn pause(&mut self) {
self.voice.pause()
}
#[inline]
pub fn get_pending_samples(&self) -> usize {
self.voice.get_pending_samples()
}
#[inline]
pub fn underflowed(&self) -> bool {
self.voice.underflowed()
}
}
impl<'a, T> Deref for Buffer<'a, T> where T: Sample {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
panic!("It is forbidden to read from the audio buffer");
}
}
impl<'a, T> DerefMut for Buffer<'a, T> where T: Sample {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
self.target.as_mut().unwrap().get_buffer()
}
}
impl<'a, T> Drop for Buffer<'a, T> where T: Sample {
#[inline]
fn drop(&mut self) {
self.target.take().unwrap().finish();
}
}