mirror of
https://github.com/RustAudio/rodio
synced 2024-12-12 13:12:30 +00:00
Add Handle type
This commit is contained in:
parent
824b4f0041
commit
de741115fd
4 changed files with 60 additions and 14 deletions
|
@ -2,8 +2,15 @@ extern crate rodio;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file = std::fs::File::open("examples/beep.wav").unwrap();
|
let file = std::fs::File::open("examples/beep.wav").unwrap();
|
||||||
|
let beep1 = rodio::play_once(file);
|
||||||
|
|
||||||
|
std::thread::sleep_ms(1000);
|
||||||
|
|
||||||
|
let file = std::fs::File::open("examples/beep2.wav").unwrap();
|
||||||
rodio::play_once(file);
|
rodio::play_once(file);
|
||||||
|
|
||||||
std::thread::sleep_ms(10000);
|
std::thread::sleep_ms(1000);
|
||||||
|
beep1.stop();
|
||||||
|
|
||||||
|
std::thread::sleep_ms(8000);
|
||||||
}
|
}
|
||||||
|
|
BIN
examples/beep2.wav
Normal file
BIN
examples/beep2.wav
Normal file
Binary file not shown.
|
@ -1,31 +1,58 @@
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::sync::mpsc::{self, Sender, Receiver};
|
use std::sync::mpsc::{self, Sender, Receiver};
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use cpal::Voice;
|
use cpal::Voice;
|
||||||
use decoder::Decoder;
|
use decoder::Decoder;
|
||||||
|
|
||||||
pub enum Command {
|
|
||||||
Play(Box<Decoder + Send>)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
|
/// Communication with the background thread.
|
||||||
commands: Mutex<Sender<Command>>,
|
commands: Mutex<Sender<Command>>,
|
||||||
|
/// Counter that is incremented whenever a sound starts playing.
|
||||||
|
sound_ids: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
thread::spawn(move || background(rx));
|
thread::spawn(move || background(rx));
|
||||||
Engine { commands: Mutex::new(tx) }
|
Engine { commands: Mutex::new(tx), sound_ids: AtomicUsize::new(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn play_once(&self, decoder: Box<Decoder + Send>) {
|
pub fn play(&self, decoder: Box<Decoder + Send>) -> Handle {
|
||||||
|
let sound_id = self.sound_ids.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
let commands = self.commands.lock().unwrap();
|
let commands = self.commands.lock().unwrap();
|
||||||
commands.send(Command::Play(decoder)).unwrap();
|
commands.send(Command::Play(sound_id, decoder)).unwrap();
|
||||||
|
|
||||||
|
Handle {
|
||||||
|
engine: self,
|
||||||
|
id: sound_id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle to a playing sound.
|
||||||
|
///
|
||||||
|
/// Note that dropping the handle doesn't stop the sound. You must call `stop` explicitely.
|
||||||
|
pub struct Handle<'a> {
|
||||||
|
engine: &'a Engine,
|
||||||
|
id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Handle<'a> {
|
||||||
|
pub fn stop(self) {
|
||||||
|
let commands = self.engine.commands.lock().unwrap();
|
||||||
|
commands.send(Command::Stop(self.id)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Command {
|
||||||
|
Play(usize, Box<Decoder + Send>),
|
||||||
|
Stop(usize),
|
||||||
|
}
|
||||||
|
|
||||||
fn background(rx: Receiver<Command>) {
|
fn background(rx: Receiver<Command>) {
|
||||||
let mut sounds = Vec::new();
|
let mut sounds = Vec::new();
|
||||||
|
|
||||||
|
@ -33,11 +60,12 @@ fn background(rx: Receiver<Command>) {
|
||||||
// polling for new sounds
|
// polling for new sounds
|
||||||
if let Ok(command) = rx.try_recv() {
|
if let Ok(command) = rx.try_recv() {
|
||||||
match command {
|
match command {
|
||||||
Command::Play(decoder) => sounds.push((Voice::new(), decoder)),
|
Command::Play(id, decoder) => sounds.push((id, Voice::new(), decoder)),
|
||||||
|
Command::Stop(id) => sounds.retain(|&(id2, _, _)| id2 != id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for &mut (ref mut voice, ref mut decoder) in sounds.iter_mut() {
|
for &mut (_, ref mut voice, ref mut decoder) in sounds.iter_mut() {
|
||||||
decoder.write(voice);
|
decoder.write(voice);
|
||||||
voice.play();
|
voice.play();
|
||||||
}
|
}
|
||||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -12,8 +12,19 @@ lazy_static! {
|
||||||
static ref ENGINE: engine::Engine = engine::Engine::new();
|
static ref ENGINE: engine::Engine = engine::Engine::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Plays a sound once. There's no way to stop the sound except by exiting the program.
|
/// Handle to a playing sound.
|
||||||
pub fn play_once<R>(input: R) where R: Read + Send + 'static {
|
///
|
||||||
let decoder = decoder::decode(input);
|
/// Note that dropping the handle doesn't stop the sound. You must call `stop` explicitely.
|
||||||
ENGINE.play_once(decoder);
|
pub struct Handle(engine::Handle<'static>);
|
||||||
|
|
||||||
|
impl Handle {
|
||||||
|
pub fn stop(self) {
|
||||||
|
self.0.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Plays a sound once. There's no way to stop the sound except by exiting the program.
|
||||||
|
pub fn play_once<R>(input: R) -> Handle where R: Read + Send + 'static {
|
||||||
|
let decoder = decoder::decode(input);
|
||||||
|
Handle(ENGINE.play(decoder))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue