use nonmax::NonMaxU32;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LoopState {
Infinite,
Finite(NonMaxU32),
}
impl Default for LoopState {
fn default() -> Self {
Self::Finite(NonMaxU32::ZERO)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
constants::test_data::FILE_WAV_TARGET,
driver::Driver,
input::File,
tracks::{PlayMode, Track, TrackState},
Config,
Event,
EventContext,
EventHandler,
TrackEvent,
};
use flume::Sender;
struct Looper {
tx: Sender<TrackState>,
}
#[async_trait::async_trait]
impl EventHandler for Looper {
async fn act(&self, ctx: &crate::EventContext<'_>) -> Option<Event> {
if let EventContext::Track(&[(state, _)]) = ctx {
drop(self.tx.send(state.clone()));
}
None
}
}
#[tokio::test]
#[ntest::timeout(15_000)]
async fn finite_track_loops_work() {
let (t_handle, config) = Config::test_cfg(true);
let mut driver = Driver::new(config.clone());
let file = File::new(FILE_WAV_TARGET);
let handle = driver
.play(Track::from(file).loops(LoopState::Finite(const { NonMaxU32::new(2).unwrap() })));
let (l_tx, l_rx) = flume::unbounded();
let (e_tx, e_rx) = flume::unbounded();
let _ = handle.add_event(Event::Track(TrackEvent::Loop), Looper { tx: l_tx });
let _ = handle.add_event(Event::Track(TrackEvent::End), Looper { tx: e_tx });
t_handle.spawn_ticker();
assert_eq!(
l_rx.recv_async().await.map(|v| v.loops),
Ok(LoopState::Finite(NonMaxU32::ONE))
);
assert_eq!(
l_rx.recv_async().await.map(|v| v.loops),
Ok(LoopState::Finite(NonMaxU32::ZERO))
);
let ended = e_rx.recv_async().await;
assert!(ended.is_ok());
let ended = ended.unwrap();
assert!(ended.play_time > 2 * ended.position);
}
#[tokio::test]
#[ntest::timeout(15_000)]
async fn infinite_track_loops_work() {
let (t_handle, config) = Config::test_cfg(true);
let mut driver = Driver::new(config.clone());
let file = File::new(FILE_WAV_TARGET);
let handle = driver.play(Track::from(file).loops(LoopState::Infinite));
let (l_tx, l_rx) = flume::unbounded();
let _ = handle.add_event(Event::Track(TrackEvent::Loop), Looper { tx: l_tx });
t_handle.spawn_ticker();
assert_eq!(
l_rx.recv_async().await.map(|v| v.loops),
Ok(LoopState::Infinite)
);
assert_eq!(
l_rx.recv_async().await.map(|v| v.loops),
Ok(LoopState::Infinite)
);
let final_state = l_rx.recv_async().await;
assert_eq!(
final_state.as_ref().map(|v| v.loops),
Ok(LoopState::Infinite)
);
let final_state = final_state.unwrap();
assert_eq!(final_state.playing, PlayMode::Play);
assert!(final_state.play_time > 2 * final_state.position);
}
}