mirror of
https://github.com/RustAudio/rodio
synced 2024-11-10 06:04:16 +00:00
* Clear and Skip functionality added Added a clear() and skip_one() method to the Sink impl * Use one lock for clear Return the length in the queue clear function so that we don't have to get a lock twice. * Rework skip to mark all sources as skippable --------- Co-authored-by: Nathan Abel <abel8706@kettering.edu> Co-authored-by: Ivar Kamsvåg <ivaka037@student.liu.se> Co-authored-by: est31 <est31@users.noreply.github.com>
This commit is contained in:
parent
56360d789c
commit
e9a85ec254
4 changed files with 150 additions and 10 deletions
|
@ -86,8 +86,15 @@ where
|
|||
self.keep_alive_if_empty
|
||||
.store(keep_alive_if_empty, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes all the sounds from the queue. Returns the number of sounds cleared.
|
||||
pub fn clear(&self) -> usize {
|
||||
let mut sounds = self.next_sounds.lock().unwrap();
|
||||
let len = sounds.len();
|
||||
sounds.clear();
|
||||
len
|
||||
}
|
||||
}
|
||||
/// The output of the queue. Implements `Source`.
|
||||
pub struct SourcesQueueOutput<S> {
|
||||
// The current iterator that produces samples.
|
||||
|
|
50
src/sink.rs
50
src/sink.rs
|
@ -26,6 +26,8 @@ struct Controls {
|
|||
volume: Mutex<f32>,
|
||||
stopped: AtomicBool,
|
||||
speed: Mutex<f32>,
|
||||
do_skip: AtomicBool,
|
||||
to_clear: Mutex<u32>,
|
||||
}
|
||||
|
||||
impl Sink {
|
||||
|
@ -50,6 +52,8 @@ impl Sink {
|
|||
volume: Mutex::new(1.0),
|
||||
stopped: AtomicBool::new(false),
|
||||
speed: Mutex::new(1.0),
|
||||
do_skip: AtomicBool::new(false),
|
||||
to_clear: Mutex::new(0),
|
||||
}),
|
||||
sound_count: Arc::new(AtomicUsize::new(0)),
|
||||
detached: false,
|
||||
|
@ -79,20 +83,29 @@ impl Sink {
|
|||
.speed(1.0)
|
||||
.pausable(false)
|
||||
.amplify(1.0)
|
||||
.skippable()
|
||||
.stoppable()
|
||||
.periodic_access(Duration::from_millis(5), move |src| {
|
||||
if controls.stopped.load(Ordering::SeqCst) {
|
||||
src.stop();
|
||||
} else {
|
||||
src.inner_mut().set_factor(*controls.volume.lock().unwrap());
|
||||
src.inner_mut()
|
||||
.inner_mut()
|
||||
.set_paused(controls.pause.load(Ordering::SeqCst));
|
||||
src.inner_mut()
|
||||
.inner_mut()
|
||||
.inner_mut()
|
||||
.set_factor(*controls.speed.lock().unwrap());
|
||||
}
|
||||
if controls.do_skip.load(Ordering::SeqCst) {
|
||||
let _ = src.inner_mut().skip();
|
||||
let mut to_clear = controls.to_clear.lock().unwrap();
|
||||
if *to_clear == 1 {
|
||||
controls.do_skip.store(false, Ordering::SeqCst);
|
||||
*to_clear = 0;
|
||||
} else if *to_clear > 0 {
|
||||
*to_clear -= 1;
|
||||
}
|
||||
}
|
||||
let amp = src.inner_mut().inner_mut();
|
||||
amp.set_factor(*controls.volume.lock().unwrap());
|
||||
amp.inner_mut()
|
||||
.set_paused(controls.pause.load(Ordering::SeqCst));
|
||||
amp.inner_mut()
|
||||
.inner_mut()
|
||||
.set_factor(*controls.speed.lock().unwrap());
|
||||
})
|
||||
.convert_samples();
|
||||
self.sound_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
@ -161,6 +174,25 @@ impl Sink {
|
|||
self.controls.pause.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Removes all currently loaded `Source`s from the `Sink`, and pauses it.
|
||||
///
|
||||
/// See `pause()` for information about pausing a `Sink`.
|
||||
pub fn clear(&self) {
|
||||
let len = self.sound_count.load(Ordering::SeqCst) as u32;
|
||||
*self.controls.to_clear.lock().unwrap() = len;
|
||||
self.skip_one();
|
||||
self.pause();
|
||||
}
|
||||
|
||||
/// Skips to the next `Source` in the `Sink`
|
||||
///
|
||||
/// If there are more `Source`s appended to the `Sink` at the time,
|
||||
/// it will play the next one. Otherwise, the `Sink` will finish as if
|
||||
/// it had finished playing a `Source` all the way through.
|
||||
pub fn skip_one(&self) {
|
||||
self.controls.do_skip.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
/// Stops the sink by emptying the queue.
|
||||
#[inline]
|
||||
pub fn stop(&self) {
|
||||
|
|
|
@ -24,6 +24,7 @@ pub use self::repeat::Repeat;
|
|||
pub use self::samples_converter::SamplesConverter;
|
||||
pub use self::sine::SineWave;
|
||||
pub use self::skip::SkipDuration;
|
||||
pub use self::skippable::Skippable;
|
||||
pub use self::spatial::Spatial;
|
||||
pub use self::speed::Speed;
|
||||
pub use self::stoppable::Stoppable;
|
||||
|
@ -49,6 +50,7 @@ mod repeat;
|
|||
mod samples_converter;
|
||||
mod sine;
|
||||
mod skip;
|
||||
mod skippable;
|
||||
mod spatial;
|
||||
mod speed;
|
||||
mod stoppable;
|
||||
|
@ -321,6 +323,13 @@ where
|
|||
stoppable::stoppable(self)
|
||||
}
|
||||
|
||||
fn skippable(self) -> Skippable<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
skippable::skippable(self)
|
||||
}
|
||||
|
||||
/// Applies a low-pass filter to the source.
|
||||
/// **Warning**: Probably buggy.
|
||||
#[inline]
|
||||
|
|
92
src/source/skippable.rs
Normal file
92
src/source/skippable.rs
Normal file
|
@ -0,0 +1,92 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::Sample;
|
||||
use crate::Source;
|
||||
|
||||
/// Internal function that builds a `Skippable` object.
|
||||
pub fn skippable<I>(source: I) -> Skippable<I> {
|
||||
Skippable {
|
||||
input: source,
|
||||
do_skip: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Skippable<I> {
|
||||
input: I,
|
||||
do_skip: bool,
|
||||
}
|
||||
|
||||
impl<I> Skippable<I> {
|
||||
/// Skips the current source
|
||||
#[inline]
|
||||
pub fn skip(&mut self) {
|
||||
self.do_skip = true;
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner source.
|
||||
#[inline]
|
||||
pub fn inner(&self) -> &I {
|
||||
&self.input
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner source.
|
||||
#[inline]
|
||||
pub fn inner_mut(&mut self) -> &mut I {
|
||||
&mut self.input
|
||||
}
|
||||
|
||||
/// Returns the inner source.
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> I {
|
||||
self.input
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator for Skippable<I>
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
type Item = I::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<I::Item> {
|
||||
if self.do_skip {
|
||||
None
|
||||
} else {
|
||||
self.input.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.input.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Source for Skippable<I>
|
||||
where
|
||||
I: Source,
|
||||
I::Item: Sample,
|
||||
{
|
||||
#[inline]
|
||||
fn current_frame_len(&self) -> Option<usize> {
|
||||
self.input.current_frame_len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn channels(&self) -> u16 {
|
||||
self.input.channels()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_rate(&self) -> u32 {
|
||||
self.input.sample_rate()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn total_duration(&self) -> Option<Duration> {
|
||||
self.input.total_duration()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue