Make the dynamic mixer drop finished sources

This commit is contained in:
Pierre Krieger 2017-02-07 11:11:14 +01:00
parent cd193a541b
commit 885caa6e74
4 changed files with 32 additions and 15 deletions

View file

@ -101,12 +101,21 @@ impl<S> Iterator for DynamicMixer<S> where S: Sample + Send + 'static {
return None;
}
let mut to_drop = Vec::new();
let mut sum = S::zero_value();
for src in self.current_sources.iter_mut() {
for (num, src) in self.current_sources.iter_mut().enumerate() {
if let Some(val) = src.next() {
sum += val;
} else {
to_drop.push(num);
}
}
for &td in to_drop.iter().rev() {
self.current_sources.remove(td);
}
Some(sum)
}

View file

@ -56,33 +56,42 @@ impl Engine {
pub fn start<S>(&self, endpoint: &Endpoint, source: S)
where S: Source<Item = f32> + Send + 'static
{
let mut voice_to_start = None;
let mixer = {
let mut end_points = self.end_points.lock().unwrap();
match end_points.entry(endpoint.get_name()) {
Entry::Vacant(e) => {
let arc = new_voice(endpoint, &self.events_loop);
e.insert(Arc::downgrade(&arc));
arc
let (mixer, voice) = new_voice(endpoint, &self.events_loop);
e.insert(Arc::downgrade(&mixer));
voice_to_start = Some(voice);
mixer
},
Entry::Occupied(mut e) => {
if let Some(m) = e.get().upgrade() {
m.clone()
} else {
let voice = new_voice(endpoint, &self.events_loop);
e.insert(Arc::downgrade(&voice));
voice
let (mixer, voice) = new_voice(endpoint, &self.events_loop);
e.insert(Arc::downgrade(&mixer));
voice_to_start = Some(voice);
mixer
}
},
}
};
mixer.add(source);
if let Some(mut voice) = voice_to_start {
voice.play();
}
}
}
// TODO: handle possible errors here
fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>) -> Arc<dynamic_mixer::DynamicMixerController<f32>> {
fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>)
-> (Arc<dynamic_mixer::DynamicMixerController<f32>>, Voice) {
// Determine the format to use for the new voice.
let format = endpoint.get_supported_formats_list()
.unwrap()
@ -113,7 +122,7 @@ fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>) -> Arc<dynamic_m
})
.expect("The endpoint doesn't support any format!?");
let (mut voice, stream) = Voice::new(&endpoint, &format, events_loop)
let (voice, stream) = Voice::new(&endpoint, &format, events_loop)
.unwrap();
let (mixer_tx, mut mixer_rx) = {
@ -152,9 +161,5 @@ fn new_voice(endpoint: &Endpoint, events_loop: &Arc<EventLoop>) -> Arc<dynamic_m
task::spawn(future_to_exec).execute(Arc::new(MyExecutor));
}
voice.play(); // TODO: don't do this now
// TODO: is there a chance that a context switch here starts playing the sound and
// immediately drops it?
mixer_tx
(mixer_tx, voice)
}

View file

@ -101,7 +101,7 @@ impl Sink {
/// Builds a new `Sink`.
#[inline]
pub fn new(endpoint: &Endpoint) -> Sink {
let (queue_tx, queue_rx) = queue::queue(false);
let (queue_tx, queue_rx) = queue::queue(true);
ENGINE.start(endpoint, queue_rx);
Sink {
@ -188,6 +188,8 @@ impl Sink {
impl Drop for Sink {
#[inline]
fn drop(&mut self) {
self.queue_tx.set_keep_alive_if_empty(false);
if !self.detached {
self.stopped.store(true, Ordering::Relaxed);
}

View file

@ -129,6 +129,7 @@ impl<S> Iterator for SourcesQueueOutput<S> where S: Sample + Send + 'static {
// Since `self.current` has finished, we need to pick the next sound.
// In order to avoid inlining this expensive operation, the code is in another function.
if self.go_next().is_err() {
println!("returned none");
return None;
}
}