Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
98 changes: 60 additions & 38 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down Expand Up @@ -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();
}

Expand All @@ -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.
Expand Down Expand Up @@ -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();
Expand Down
9 changes: 9 additions & 0 deletions src/source/done.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<I> {
input: I,
Expand All @@ -26,6 +27,14 @@ impl<I> Done<I> {
}
}

/// 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 {
Expand Down