1use std::time::Duration;
23use crate::{Sample, Source};
45use super::SeekError;
67/// Builds a source that chains sources provided by an iterator.
8///
9/// The `iterator` parameter is an iterator that produces a source. The source is then played.
10/// Whenever the source ends, the `iterator` is used again in order to produce the source that is
11/// played next.
12///
13/// If the `iterator` produces `None`, then the sound ends.
14pub fn from_iter<I>(iterator: I) -> FromIter<I::IntoIter>
15where
16I: IntoIterator,
17{
18let mut iterator = iterator.into_iter();
19let first_source = iterator.next();
2021 FromIter {
22 iterator,
23 current_source: first_source,
24 }
25}
2627/// A source that chains sources provided by an iterator.
28#[derive(Clone)]
29pub struct FromIter<I>
30where
31I: Iterator,
32{
33// The iterator that provides sources.
34iterator: I,
35// Is only ever `None` if the first element of the iterator is `None`.
36current_source: Option<I::Item>,
37}
3839impl<I> Iterator for FromIter<I>
40where
41I: Iterator,
42 I::Item: Iterator + Source,
43 <I::Item as Iterator>::Item: Sample,
44{
45type Item = <I::Item as Iterator>::Item;
4647#[inline]
48fn next(&mut self) -> Option<<I::Item as Iterator>::Item> {
49loop {
50if let Some(src) = &mut self.current_source {
51if let Some(value) = src.next() {
52return Some(value);
53 }
54 }
5556if let Some(src) = self.iterator.next() {
57self.current_source = Some(src);
58 } else {
59return None;
60 }
61 }
62 }
6364#[inline]
65fn size_hint(&self) -> (usize, Option<usize>) {
66if let Some(cur) = &self.current_source {
67 (cur.size_hint().0, None)
68 } else {
69 (0, None)
70 }
71 }
72}
7374impl<I> Source for FromIter<I>
75where
76I: Iterator,
77 I::Item: Iterator + Source,
78 <I::Item as Iterator>::Item: Sample,
79{
80#[inline]
81fn current_frame_len(&self) -> Option<usize> {
82// This function is non-trivial because the boundary between the current source and the
83 // next must be a frame boundary as well.
84 //
85 // The current sound is free to return `None` for `current_frame_len()`, in which case
86 // we *should* return the number of samples remaining the current sound.
87 // This can be estimated with `size_hint()`.
88 //
89 // If the `size_hint` is `None` as well, we are in the worst case scenario. To handle this
90 // situation we force a frame to have a maximum number of samples indicate by this
91 // constant.
92const THRESHOLD: usize = 10240;
9394// Try the current `current_frame_len`.
95if let Some(src) = &self.current_source {
96if let Some(val) = src.current_frame_len() {
97if val != 0 {
98return Some(val);
99 }
100 }
101 }
102103// Try the size hint.
104if let Some(src) = &self.current_source {
105if let Some(val) = src.size_hint().1 {
106if val < THRESHOLD && val != 0 {
107return Some(val);
108 }
109 }
110 }
111112// Otherwise we use the constant value.
113Some(THRESHOLD)
114 }
115116#[inline]
117fn channels(&self) -> u16 {
118if let Some(src) = &self.current_source {
119 src.channels()
120 } else {
121// Dummy value that only happens if the iterator was empty.
1222
123}
124 }
125126#[inline]
127fn sample_rate(&self) -> u32 {
128if let Some(src) = &self.current_source {
129 src.sample_rate()
130 } else {
131// Dummy value that only happens if the iterator was empty.
13244100
133}
134 }
135136#[inline]
137fn total_duration(&self) -> Option<Duration> {
138None
139}
140141#[inline]
142fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
143if let Some(source) = self.current_source.as_mut() {
144 source.try_seek(pos)
145 } else {
146Ok(())
147 }
148 }
149}
150151#[cfg(test)]
152mod tests {
153use crate::buffer::SamplesBuffer;
154use crate::source::{from_iter, Source};
155156#[test]
157fn basic() {
158let mut rx = from_iter((0..2).map(|n| {
159if n == 0 {
160 SamplesBuffer::new(1, 48000, vec![10i16, -10, 10, -10])
161 } else if n == 1 {
162 SamplesBuffer::new(2, 96000, vec![5i16, 5, 5, 5])
163 } else {
164unreachable!()
165 }
166 }));
167168assert_eq!(rx.channels(), 1);
169assert_eq!(rx.sample_rate(), 48000);
170assert_eq!(rx.next(), Some(10));
171assert_eq!(rx.next(), Some(-10));
172assert_eq!(rx.next(), Some(10));
173assert_eq!(rx.next(), Some(-10));
174/*assert_eq!(rx.channels(), 2);
175 assert_eq!(rx.sample_rate(), 96000);*/
176 // FIXME: not working
177assert_eq!(rx.next(), Some(5));
178assert_eq!(rx.next(), Some(5));
179assert_eq!(rx.next(), Some(5));
180assert_eq!(rx.next(), Some(5));
181assert_eq!(rx.next(), None);
182 }
183}