Dropping the Sink now stops all sounds

This commit is contained in:
Pierre Krieger 2015-10-16 15:38:10 +02:00
parent d786f79e02
commit a23aeaa4ff
2 changed files with 36 additions and 15 deletions

View file

@ -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>) {
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>) {
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<Command>) {
// 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);
}
}

View file

@ -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<S>(&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<R>(endpoint: &Endpoint, input: R) -> Sink