1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
//! # Usage //! //! There are two main concepts in this library: //! //! - Sources, represented with the `Source` trait, that provide sound data. //! - Sinks, which accept sound data. //! //! In order to play a sound, you need to create a source, a sink, and connect the two. For example //! here is how you play a sound file: //! //! ```no_run //! use std::io::BufReader; //! //! let endpoint = rodio::get_default_endpoint().unwrap(); //! let sink = rodio::Sink::new(&endpoint); //! //! let file = std::fs::File::open("music.ogg").unwrap(); //! let source = rodio::Decoder::new(BufReader::new(file)).unwrap(); //! sink.append(source); //! ``` //! //! The `append` method takes ownership of the source and starts playing it. If a sink is already //! playing a sound when you call `append`, the sound is added to a queue and will start playing //! when the existing source is over. //! //! If you want to play multiple sounds simultaneously, you should create multiple sinks. //! //! # How it works //! //! Rodio spawns a background thread that is dedicated to reading from the sources and sending //! the output to the endpoint. //! //! All the sounds are mixed together by rodio before being sent. Since this is handled by the //! software, there is no restriction for the number of sinks that can be created. //! //! # Adding effects //! //! The `Source` trait provides various filters, similarly to the standard `Iterator` trait. //! //! Example: //! //! ```ignore //! use rodio::Source; //! use std::time::Duration; //! //! // repeats the first five seconds of this sound forever //! let source = source.take_duration(Duration::from_secs(5)).repeat_infinite(); //! ``` #![cfg_attr(test, deny(missing_docs))] extern crate cpal; extern crate futures; extern crate hound; #[macro_use] extern crate lazy_static; extern crate lewton; extern crate ogg; pub use cpal::{Endpoint, get_endpoints_list, get_default_endpoint}; pub use conversions::Sample; pub use decoder::Decoder; pub use source::Source; use std::io::{Read, Seek}; mod conversions; mod engine; pub mod decoder; pub mod source; lazy_static! { static ref ENGINE: engine::Engine = engine::Engine::new(); } /// Handle to an endpoint that outputs sounds. /// /// Dropping the `Sink` stops all sounds. You can use `detach` if you want the sounds to continue /// playing. pub struct Sink { handle: engine::Handle, // if true, then the sound will stop playing at the end stop: bool, } impl Sink { /// Builds a new `Sink`. #[inline] pub fn new(endpoint: &Endpoint) -> Sink { Sink { handle: ENGINE.start(&endpoint), stop: true, } } /// Appends a sound to the queue of sounds to play. #[inline] pub fn append<S>(&self, source: S) where S: Source + Send + 'static, S::Item: Sample, S::Item: Send { self.handle.append(source); } /// Changes the volume of the sound. /// /// The value `1.0` is the "normal" volume (unfiltered input). Any value other than 1.0 will /// multiply each sample by this value. #[inline] pub fn set_volume(&mut self, value: f32) { self.handle.set_volume(value); } /// Destroys the sink without stopping the sounds that are still playing. #[inline] pub fn detach(mut self) { self.stop = false; } /// Sleeps the current thread until the sound ends. #[inline] pub fn sleep_until_end(&self) { self.handle.sleep_until_end(); } } impl Drop for Sink { #[inline] fn drop(&mut self) { if self.stop { self.handle.stop(); } } } /// Plays a sound once. Returns a `Sink` that can be used to control the sound. #[inline] pub fn play_once<R>(endpoint: &Endpoint, input: R) -> Result<Sink, decoder::DecoderError> where R: Read + Seek + Send + 'static { let input = try!(decoder::Decoder::new(input)); let sink = Sink::new(endpoint); sink.append(input); Ok(sink) }