1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::time::Duration;

use crate::{Sample, Source};

use super::SeekError;

/// Builds a `Pausable` object.
pub fn pausable<I>(source: I, paused: bool) -> Pausable<I>
where
    I: Source,
    I::Item: Sample,
{
    let paused_channels = if paused {
        Some(source.channels())
    } else {
        None
    };
    Pausable {
        input: source,
        paused_channels,
        remaining_paused_samples: 0,
    }
}

/// Wraps a source and makes it pausable by calling [`Pausable::set_paused`] on
/// this object. When the source is paused it returns zero value samples.
///
/// You can usually still use this from another source wrapping this one by
/// calling `inner_mut` on it. Similarly this provides [`Pausable::inner`] and
/// mutable/destructing variants for accessing the underlying source.
#[derive(Clone, Debug)]
pub struct Pausable<I> {
    input: I,
    paused_channels: Option<u16>,
    remaining_paused_samples: u16,
}

impl<I> Pausable<I>
where
    I: Source,
    I::Item: Sample,
{
    /// Sets whether the filter applies.
    ///
    /// If set to true, the inner sound stops playing and no samples are processed from it.
    #[inline]
    pub fn set_paused(&mut self, paused: bool) {
        match (self.paused_channels, paused) {
            (None, true) => self.paused_channels = Some(self.input.channels()),
            (Some(_), false) => self.paused_channels = None,
            _ => (),
        }
    }

    /// 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 Pausable<I>
where
    I: Source,
    I::Item: Sample,
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<I::Item> {
        if self.remaining_paused_samples > 0 {
            self.remaining_paused_samples -= 1;
            return Some(I::Item::zero_value());
        }

        if let Some(paused_channels) = self.paused_channels {
            self.remaining_paused_samples = paused_channels - 1;
            return Some(I::Item::zero_value());
        }

        self.input.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

impl<I> Source for Pausable<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()
    }

    #[inline]
    fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
        self.input.try_seek(pos)
    }
}