cpal/src/lib.rs

478 lines
12 KiB
Rust
Raw Normal View History

2014-12-17 08:45:14 +00:00
/*!
# How to use cpal
2016-08-03 10:55:47 +00:00
In order to play a sound, first you need to create an `EventLoop` and a `Voice`.
2014-12-17 08:45:14 +00:00
```no_run
2015-09-01 15:47:55 +00:00
// getting the default sound output of the system (can return `None` if nothing is supported)
let endpoint = cpal::get_default_endpoint().unwrap();
// note that the user can at any moment disconnect the device, therefore all operations return
// a `Result` to handle this situation
// getting a format for the PCM
let format = endpoint.get_supported_formats_list().unwrap().next().unwrap();
2016-08-03 10:55:47 +00:00
let event_loop = cpal::EventLoop::new();
let (voice, mut samples_stream) = cpal::Voice::new(&endpoint, &format, &event_loop).unwrap();
2014-12-17 08:45:14 +00:00
```
2016-08-03 10:55:47 +00:00
The `voice` can be used to control the play/pause of the output, while the `samples_stream` can
be used to register a callback that will be called whenever the backend is ready to get data.
See the documentation of `futures-rs` for more info about how to use streams.
2014-12-17 08:45:14 +00:00
2016-09-30 16:18:28 +00:00
```no_run
# extern crate futures;
# extern crate cpal;
# use std::sync::Arc;
2016-08-03 10:55:47 +00:00
use futures::stream::Stream;
2016-09-30 16:18:28 +00:00
use futures::task;
# struct MyExecutor;
# impl task::Executor for MyExecutor {
# fn execute(&self, r: task::Run) {
# r.run();
# }
# }
# fn main() {
# let mut samples_stream: cpal::SamplesStream = unsafe { std::mem::uninitialized() };
# let my_executor = Arc::new(MyExecutor);
2016-08-03 10:55:47 +00:00
2016-09-30 16:18:28 +00:00
task::spawn(samples_stream.for_each(move |buffer| -> Result<_, ()> {
2016-08-03 10:55:47 +00:00
// write data to `buffer` here
Ok(())
2016-09-30 16:18:28 +00:00
})).execute(my_executor);
# }
2016-08-03 10:55:47 +00:00
```
2014-12-17 08:45:14 +00:00
2016-08-03 10:55:47 +00:00
TODO: add example
2014-12-17 08:45:14 +00:00
2016-08-03 10:55:47 +00:00
After you have registered a callback, call `play`:
2014-12-22 13:16:47 +00:00
```no_run
2015-09-01 15:47:55 +00:00
# let mut voice: cpal::Voice = unsafe { std::mem::uninitialized() };
2014-12-22 13:16:47 +00:00
voice.play();
```
2016-08-03 10:55:47 +00:00
And finally, run the event loop:
```no_run
# let mut event_loop: cpal::EventLoop = unsafe { std::mem::uninitialized() };
event_loop.run();
```
Calling `run()` will block the thread forever, so it's usually best done in a separate thread.
While `run()` is running, the audio device of the user will call the callbacks you registered
from time to time.
2014-12-17 08:45:14 +00:00
*/
2016-08-02 14:13:59 +00:00
extern crate futures;
#[macro_use]
extern crate lazy_static;
extern crate libc;
2017-10-11 11:24:49 +00:00
pub use samples_formats::{Sample, SampleFormat};
2014-12-17 07:47:19 +00:00
2017-10-11 11:24:49 +00:00
#[cfg(all(not(windows), not(target_os = "linux"), not(target_os = "freebsd"),
not(target_os = "macos"), not(target_os = "ios")))]
use null as cpal_impl;
use std::error::Error;
2017-10-11 11:24:49 +00:00
use std::fmt;
2015-01-05 09:52:59 +00:00
use std::ops::{Deref, DerefMut};
2016-08-02 14:13:59 +00:00
use futures::Poll;
2017-10-11 11:24:49 +00:00
use futures::stream::Stream;
2016-08-02 14:13:59 +00:00
mod null;
2014-12-17 07:47:19 +00:00
mod samples_formats;
2014-12-15 10:45:38 +00:00
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
2017-10-11 11:24:49 +00:00
#[path = "alsa/mod.rs"]
2014-12-17 08:13:58 +00:00
mod cpal_impl;
2015-02-22 13:50:06 +00:00
2014-12-11 13:22:55 +00:00
#[cfg(windows)]
2017-10-11 11:24:49 +00:00
#[path = "wasapi/mod.rs"]
2014-12-17 08:13:58 +00:00
mod cpal_impl;
2014-12-11 16:23:33 +00:00
2017-10-10 16:24:53 +00:00
#[cfg(any(target_os = "macos", target_os = "ios"))]
2017-10-11 11:24:49 +00:00
#[path = "coreaudio/mod.rs"]
2015-02-22 13:50:06 +00:00
mod cpal_impl;
/// An iterator for the list of formats that are supported by the backend.
pub struct EndpointsIterator(cpal_impl::EndpointsIterator);
impl Iterator for EndpointsIterator {
type Item = Endpoint;
2015-09-01 11:53:54 +00:00
#[inline]
fn next(&mut self) -> Option<Endpoint> {
self.0.next().map(Endpoint)
}
2015-09-01 11:53:54 +00:00
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
/// Return an iterator to the list of formats that are supported by the system.
2015-09-11 08:55:29 +00:00
#[inline]
pub fn endpoints() -> EndpointsIterator {
EndpointsIterator(Default::default())
}
/// Deprecated. Use `endpoints()` instead.
#[inline]
#[deprecated]
pub fn get_endpoints_list() -> EndpointsIterator {
EndpointsIterator(Default::default())
}
/// Return the default endpoint, or `None` if no device is available.
2015-09-11 08:55:29 +00:00
#[inline]
pub fn default_endpoint() -> Option<Endpoint> {
cpal_impl::default_endpoint().map(Endpoint)
}
/// Deprecated. Use `default_endpoint()` instead.
#[inline]
#[deprecated]
pub fn get_default_endpoint() -> Option<Endpoint> {
default_endpoint()
}
/// An opaque type that identifies an end point.
#[derive(Clone, PartialEq, Eq)]
pub struct Endpoint(cpal_impl::Endpoint);
2015-09-01 11:53:54 +00:00
impl Endpoint {
/// Returns an iterator that produces the list of formats that are supported by the backend.
2015-09-11 08:55:29 +00:00
#[inline]
2017-10-11 11:24:49 +00:00
pub fn supported_formats(&self) -> Result<SupportedFormatsIterator, FormatsEnumerationError> {
Ok(SupportedFormatsIterator(self.0.supported_formats()?))
}
/// Deprecated. Use `supported_formats` instead.
#[inline]
#[deprecated]
2017-10-11 11:24:49 +00:00
pub fn get_supported_formats_list(
&self)
-> Result<SupportedFormatsIterator, FormatsEnumerationError> {
self.supported_formats()
2015-09-01 11:53:54 +00:00
}
/// Returns the name of the endpoint.
#[inline]
pub fn name(&self) -> String {
self.0.name()
}
/// Deprecated. Use `name()` instead.
#[deprecated]
#[inline]
pub fn get_name(&self) -> String {
self.name()
}
2015-09-01 11:53:54 +00:00
}
/// Number of channels.
pub type ChannelsCount = u16;
2015-09-10 09:44:19 +00:00
/// Possible position of a channel.
#[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,
}
2015-09-01 11:53:54 +00:00
///
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SamplesRate(pub u32);
/// Describes a format.
2015-09-10 09:44:19 +00:00
#[derive(Debug, Clone, PartialEq, Eq)]
2015-09-01 11:53:54 +00:00
pub struct Format {
2015-09-10 09:44:19 +00:00
pub channels: Vec<ChannelPosition>,
2015-09-01 11:53:54 +00:00
pub samples_rate: SamplesRate,
pub data_type: SampleFormat,
}
/// An iterator that produces a list of formats supported by the endpoint.
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()
}
}
2016-08-02 14:13:59 +00:00
pub struct EventLoop(cpal_impl::EventLoop);
impl EventLoop {
#[inline]
pub fn new() -> EventLoop {
EventLoop(cpal_impl::EventLoop::new())
}
#[inline]
pub fn run(&self) {
self.0.run()
}
}
2014-12-11 17:09:48 +00:00
/// Represents a buffer that must be filled with audio data.
///
2014-12-17 08:45:14 +00:00
/// You should destroy this object as soon as possible. Data is only committed when it
/// is destroyed.
2014-12-26 09:39:19 +00:00
#[must_use]
2017-10-11 11:24:49 +00:00
pub struct Buffer<T>
where T: Sample
{
2014-12-15 14:29:59 +00:00
// also contains something, taken by `Drop`
2016-08-02 14:13:59 +00:00
target: Option<cpal_impl::Buffer<T>>,
2014-12-15 14:29:59 +00:00
}
2015-08-20 12:38:25 +00:00
/// This is the struct that is provided to you by cpal when you want to write samples to a buffer.
///
/// Since the type of data is only known at runtime, you have to fill the right buffer.
2016-08-02 14:13:59 +00:00
pub enum UnknownTypeBuffer {
2015-08-20 12:38:25 +00:00
/// Samples whose format is `u16`.
2016-08-02 14:13:59 +00:00
U16(Buffer<u16>),
2015-08-20 12:38:25 +00:00
/// Samples whose format is `i16`.
2016-08-02 14:13:59 +00:00
I16(Buffer<i16>),
2015-08-20 12:38:25 +00:00
/// Samples whose format is `f32`.
2016-08-02 14:13:59 +00:00
F32(Buffer<f32>),
2014-12-15 10:45:38 +00:00
}
2014-12-11 16:23:33 +00:00
2016-08-02 14:13:59 +00:00
impl UnknownTypeBuffer {
2015-09-10 19:21:46 +00:00
/// Returns the length of the buffer in number of samples.
2015-09-11 08:55:29 +00:00
#[inline]
2015-09-10 19:21:46 +00:00
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(),
}
}
}
2015-09-01 12:17:57 +00:00
/// Error that can happen when enumerating the list of supported formats.
#[derive(Debug)]
pub enum FormatsEnumerationError {
/// The device no longer exists. This can happen if the device is disconnected while the
/// program is running.
DeviceNotAvailable,
}
impl fmt::Display for FormatsEnumerationError {
2015-09-11 08:55:29 +00:00
#[inline]
2015-09-01 12:17:57 +00:00
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.description())
}
}
impl Error for FormatsEnumerationError {
2015-09-11 08:55:29 +00:00
#[inline]
2015-09-01 12:17:57 +00:00
fn description(&self) -> &str {
match self {
&FormatsEnumerationError::DeviceNotAvailable => {
"The requested device is no longer available (for example, it has been unplugged)."
},
}
}
}
/// Error that can happen when creating a `Voice`.
#[derive(Debug)]
pub enum CreationError {
/// The device no longer exists. This can happen if the device is disconnected while the
/// program is running.
DeviceNotAvailable,
/// The required format is not supported.
FormatNotSupported,
}
impl fmt::Display for CreationError {
2015-09-11 08:55:29 +00:00
#[inline]
2015-09-01 12:17:57 +00:00
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.description())
}
}
impl Error for CreationError {
2015-09-11 08:55:29 +00:00
#[inline]
2015-09-01 12:17:57 +00:00
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."
},
}
}
}
2015-08-20 12:38:25 +00:00
/// Controls a sound output. A typical application has one `Voice` for each sound
/// it wants to output.
///
/// A voice must be periodically filled with new data by calling `append_data`, or the sound
/// will stop playing.
///
/// Each `Voice` is bound to a specific number of channels, samples rate, and samples format,
/// which can be retreived by calling `get_channels`, `get_samples_rate` and `get_samples_format`.
/// If you call `append_data` with values different than these, then cpal will automatically
/// perform a conversion on your data.
///
/// If you have the possibility, you should try to match the format of the voice.
pub struct Voice {
voice: cpal_impl::Voice,
format: Format,
}
2015-08-20 12:38:25 +00:00
2014-12-17 08:16:26 +00:00
impl Voice {
2014-12-17 08:13:58 +00:00
/// Builds a new channel.
2015-09-01 11:53:54 +00:00
#[inline]
2016-08-02 14:13:59 +00:00
pub fn new(endpoint: &Endpoint, format: &Format, event_loop: &EventLoop)
2017-10-11 11:24:49 +00:00
-> Result<(Voice, SamplesStream), CreationError> {
let (voice, stream) = cpal_impl::Voice::new(&endpoint.0, format, &event_loop.0)?;
2016-08-02 14:13:59 +00:00
let voice = Voice {
voice: voice,
format: format.clone(),
2016-08-02 14:13:59 +00:00
};
let stream = SamplesStream(stream);
Ok((voice, stream))
}
/// Returns the format used by the voice.
#[inline]
pub fn format(&self) -> &Format {
&self.format
2014-12-11 16:23:33 +00:00
}
/// DEPRECATED: use `format` instead. Returns the number of channels.
2014-12-11 17:09:48 +00:00
///
2014-12-17 08:45:14 +00:00
/// You can add data with any number of channels, but matching the voice's native format
/// will lead to better performances.
#[deprecated]
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-11 18:02:04 +00:00
pub fn get_channels(&self) -> ChannelsCount {
self.format().channels.len() as ChannelsCount
2014-12-11 16:23:33 +00:00
}
/// DEPRECATED: use `format` instead. Returns the number of samples that are played per second.
2014-12-11 18:07:58 +00:00
///
2014-12-17 08:45:14 +00:00
/// You can add data with any samples rate, but matching the voice's native format
/// will lead to better performances.
#[deprecated]
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-15 10:45:38 +00:00
pub fn get_samples_rate(&self) -> SamplesRate {
self.format().samples_rate
2014-12-11 18:07:58 +00:00
}
/// DEPRECATED: use `format` instead. Returns the format of the samples that are accepted by the backend.
2014-12-11 18:07:58 +00:00
///
2014-12-17 08:45:14 +00:00
/// You can add data of any format, but matching the voice's native format
/// will lead to better performances.
#[deprecated]
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-11 18:07:58 +00:00
pub fn get_samples_format(&self) -> SampleFormat {
self.format().data_type
2014-12-11 18:07:58 +00:00
}
2014-12-22 13:16:47 +00:00
/// Sends a command to the audio device that it should start playing.
///
/// Has no effect is the voice was already playing.
///
/// Only call this after you have submitted some data, otherwise you may hear
/// some glitches.
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-22 13:16:47 +00:00
pub fn play(&mut self) {
self.voice.play()
2014-12-22 13:16:47 +00:00
}
/// Sends a command to the audio device that it should stop playing.
///
/// Has no effect is the voice was already paused.
///
/// If you call `play` afterwards, the playback will resume exactly where it was.
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-22 13:16:47 +00:00
pub fn pause(&mut self) {
self.voice.pause()
2014-12-22 13:16:47 +00:00
}
2016-08-02 14:13:59 +00:00
}
pub struct SamplesStream(cpal_impl::SamplesStream);
impl Stream for SamplesStream {
type Item = UnknownTypeBuffer;
type Error = ();
2015-09-10 19:03:40 +00:00
2015-09-22 15:52:35 +00:00
#[inline]
2016-09-30 16:18:28 +00:00
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.0.poll()
2015-09-10 19:03:40 +00:00
}
2014-12-11 16:23:33 +00:00
}
2017-10-11 11:24:49 +00:00
impl<T> Deref for Buffer<T>
where T: Sample
{
2015-01-05 09:52:59 +00:00
type Target = [T];
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-15 15:32:13 +00:00
fn deref(&self) -> &[T] {
panic!("It is forbidden to read from the audio buffer");
2014-12-11 16:23:33 +00:00
}
}
2017-10-11 11:24:49 +00:00
impl<T> DerefMut for Buffer<T>
where T: Sample
{
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-15 15:32:13 +00:00
fn deref_mut(&mut self) -> &mut [T] {
self.target.as_mut().unwrap().buffer()
2014-12-15 10:45:38 +00:00
}
}
2017-10-11 11:24:49 +00:00
impl<T> Drop for Buffer<T>
where T: Sample
{
2015-09-01 11:53:54 +00:00
#[inline]
2014-12-15 10:45:38 +00:00
fn drop(&mut self) {
2014-12-15 15:32:13 +00:00
self.target.take().unwrap().finish();
2014-12-11 16:23:33 +00:00
}
}