From a23aeaa4ff7686d0e3925588764398bb17100626 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 16 Oct 2015 15:38:10 +0200 Subject: [PATCH] Dropping the Sink now stops all sounds --- src/engine.rs | 12 +++++++----- src/lib.rs | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index 5216340..0c15dc6 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -100,7 +100,7 @@ impl Engine { // the iterator that produces sounds let next_sounds = Arc::new(Mutex::new(Vec::new())); let source = QueueIterator { current: Box::new(None.into_iter()), next: next_sounds.clone() }; - let source_id = &next_sounds as *const _ as *const u8 as usize; + let source_id = &*next_sounds as *const Mutex<_> as *const u8 as usize; // at each loop, the background thread will store the remaining time of the sound in this // value @@ -165,8 +165,10 @@ impl<'a> Handle<'a> { commands.send(Command::SetVolume(self.source_id, value)).unwrap(); } + // note that this method could take `self` instead of `&self`, but it makes `Sink`'s life + // easier not to take `self` #[inline] - pub fn stop(self) { + pub fn stop(&self) { let commands = self.engine.commands.lock().unwrap(); commands.send(Command::Stop(self.source_id)).unwrap(); @@ -222,7 +224,7 @@ fn background(rx: Receiver) { Command::Stop(decoder) => { for (_, &mut (_, ref mut sounds)) in voices.iter_mut() { sounds.retain(|dec| { - &*dec.0.next as *const _ as *const u8 as usize != decoder + &*dec.0.next as *const Mutex<_> as *const u8 as usize != decoder }) } }, @@ -230,7 +232,7 @@ fn background(rx: Receiver) { Command::SetVolume(decoder, volume) => { for (_, &mut (_, ref mut sounds)) in voices.iter_mut() { if let Some(d) = sounds.iter_mut() - .find(|dec| &*dec.0.next as *const _ as *const u8 as usize == decoder) + .find(|dec| &*dec.0.next as *const Mutex<_> as *const u8 as usize == decoder) { d.2 = volume; } @@ -242,7 +244,7 @@ fn background(rx: Receiver) { // removing sounds that have finished playing for decoder in mem::replace(&mut sounds_to_remove, Vec::new()) { for (_, &mut (_, ref mut sounds)) in voices.iter_mut() { - sounds.retain(|dec| &*dec.0.next as *const _ != decoder); + sounds.retain(|dec| &*dec.0.next as *const Mutex<_> != decoder); } } diff --git a/src/lib.rs b/src/lib.rs index 011741a..41d0a78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,20 +28,30 @@ lazy_static! { static ref ENGINE: engine::Engine = engine::Engine::new(); } -/// Handle to a playing sound. +/// Handle to an endpoint that outputs sounds. /// -/// Note that dropping the handle doesn't stop the sound. You must call `stop` explicitely. -pub struct Sink(engine::Handle<'static>); +/// Dropping the `Sink` stops all sounds. You can use `detach` if you want the sounds to continue +/// playing. +pub struct Sink { + handle: engine::Handle<'static>, + // if true, then the sound will stop playing at the end + stop: bool, +} impl Sink { + /// Builds a new `Sink`. pub fn new(endpoint: &Endpoint) -> Sink { - Sink(ENGINE.start(&endpoint)) + Sink { + handle: ENGINE.start(&endpoint), + stop: true, + } } + /// Appends a sound to the queue of sounds to play. pub fn append(&self, source: S) where S: Source + Send + 'static, S::Item: Sample, S::Item: Send { - self.0.append(source); + self.handle.append(source); } /// Changes the volume of the sound. @@ -50,13 +60,13 @@ impl Sink { /// multiply each sample by this value. #[inline] pub fn set_volume(&mut self, value: f32) { - self.0.set_volume(value); + self.handle.set_volume(value); } - /// Stops the sound. + /// Destroys the sink without stopping the sounds that are still playing. #[inline] - pub fn stop(self) { - self.0.stop() + pub fn detach(mut self) { + self.stop = false; } /// Returns the minimum duration before the end of the sounds submitted to this sink. @@ -64,7 +74,7 @@ impl Sink { /// Note that this is a minimum value, and the sound can last longer. #[inline] pub fn get_min_remaining_duration(&self) -> Duration { - self.0.get_min_remaining_duration() + self.handle.get_min_remaining_duration() } /// Sleeps the current thread until the sound ends. @@ -75,6 +85,15 @@ impl Sink { } } +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(endpoint: &Endpoint, input: R) -> Sink