diff --git a/CHANGELOG.md b/CHANGELOG.md index d657513d..a7afc491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Source::dither()` function for applying dithering - Added `64bit` feature to opt-in to 64-bit sample precision (`f64`). - Added `SampleRateConverter::inner` to get underlying iterator by ref. +- Added `Done::should_decrement` to allow Done to not decrement their number. ### Fixed - docs.rs will now document all features, including those that are optional. @@ -43,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed channel misalignment when sources end before their promised span length by padding with silence to complete frames. - Fixed `Empty` source to properly report exhaustion. - Fixed `Zero::current_span_len` returning remaining samples instead of span length. +- Fixed `Player::skip_one` not decreasing the player's length immediately. ### Changed - Breaking: _Sink_ terms are replaced with _Player_ and _Stream_ terms replaced diff --git a/src/player.rs b/src/player.rs index 9be3bfdc..262a8788 100644 --- a/src/player.rs +++ b/src/player.rs @@ -118,46 +118,50 @@ impl Player { let start_played = AtomicBool::new(false); - let source = source - .speed(1.0) - // Must be placed before pausable but after speed & delay - .track_position() - .pausable(false) - .amplify(1.0) - .skippable() - .stoppable() - // If you change the duration update the docs for try_seek! - .periodic_access(Duration::from_millis(5), move |src| { - if controls.stopped.load(Ordering::SeqCst) { - src.stop(); + let source = Done::new( + source + .speed(1.0) + // Must be placed before pausable but after speed & delay + .track_position() + .pausable(false) + .amplify(1.0) + .skippable() + .stoppable(), + self.sound_count.clone(), + ) + // If you change the duration update the docs for try_seek! + .periodic_access(Duration::from_millis(5), move |src| { + if controls.stopped.load(Ordering::SeqCst) { + src.inner_mut().stop(); + *controls.position.lock().unwrap() = Duration::ZERO; + } + { + let mut to_clear = controls.to_clear.lock().unwrap(); + if *to_clear > 0 { + src.inner_mut().inner_mut().skip(); + src.should_decrement(false); + *to_clear -= 1; *controls.position.lock().unwrap() = Duration::ZERO; + } else { + *controls.position.lock().unwrap() = + src.inner().inner().inner().inner().inner().get_pos(); } - { - let mut to_clear = controls.to_clear.lock().unwrap(); - if *to_clear > 0 { - src.inner_mut().skip(); - *to_clear -= 1; - *controls.position.lock().unwrap() = Duration::ZERO; - } else { - *controls.position.lock().unwrap() = - src.inner().inner().inner().inner().get_pos(); - } - } - 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() - .inner_mut() - .set_factor(*controls.speed.lock().unwrap()); - if let Some(seek) = controls.seek.lock().unwrap().take() { - seek.attempt(amp) - } - start_played.store(true, Ordering::SeqCst); - }); + } + let amp = src.inner_mut().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() + .inner_mut() + .set_factor(*controls.speed.lock().unwrap()); + if let Some(seek) = controls.seek.lock().unwrap().take() { + seek.attempt(amp) + } + start_played.store(true, Ordering::SeqCst); + }); + self.sound_count.fetch_add(1, Ordering::Relaxed); - let source = Done::new(source, self.sound_count.clone()); *self.sleep_until_end.lock().unwrap() = Some(self.queue_tx.append_with_signal(source)); } @@ -279,7 +283,7 @@ impl Player { pub fn clear(&self) { let len = self.sound_count.load(Ordering::SeqCst) as u32; *self.controls.to_clear.lock().unwrap() = len; - self.sleep_until_end(); + self.sound_count.store(0, Ordering::Relaxed); self.pause(); } @@ -294,6 +298,7 @@ impl Player { if len > *to_clear { *to_clear += 1; } + self.sound_count.fetch_sub(1, Ordering::SeqCst); } /// Stops the sink by emptying the queue. @@ -361,6 +366,23 @@ mod tests { use crate::math::nz; use crate::{Player, Source}; + #[test] + fn test_immediate_length_changes() { + let (player, mut source) = Player::new(); + + player.append(SamplesBuffer::new(nz!(1), nz!(1), vec![2.0, 3.0])); + player.append(SamplesBuffer::new(nz!(1), nz!(1), vec![1.0, 0.5])); + assert_eq!(player.len(), 2); + assert_eq!(source.next(), Some(2.0)); + + player.skip_one(); + assert_eq!(player.len(), 1); + assert_eq!(source.next(), Some(1.0)); + + player.clear(); + assert_eq!(player.len(), 0); + } + #[test] fn test_pause_and_stop() { let (player, mut source) = Player::new(); diff --git a/src/source/done.rs b/src/source/done.rs index 5bc922b7..4c040989 100644 --- a/src/source/done.rs +++ b/src/source/done.rs @@ -7,6 +7,7 @@ use crate::common::{ChannelCount, SampleRate}; use crate::Source; /// When the inner source is empty this decrements a `AtomicUsize`. +/// Decrementing can be toggled using [`should_decrement`](Self::should_decrement). #[derive(Debug, Clone)] pub struct Done { input: I, @@ -26,6 +27,14 @@ impl Done { } } + /// Controls whether the number decrement will happen. + /// + /// If this function is called with `true` after it has already decremented a number, + /// the number will be decremented again after it recieves a [`Iterator::next`] call. + pub fn should_decrement(&mut self, should_decrement: bool) { + self.signal_sent = !should_decrement; + } + /// Returns a reference to the inner source. #[inline] pub fn inner(&self) -> &I {