mirror of
https://github.com/RustAudio/rodio
synced 2024-11-10 14:14:21 +00:00
refactor tests, add seek beyond stream test
This commit is contained in:
parent
9a4dcb0c41
commit
eb22ec5dac
4 changed files with 57 additions and 23 deletions
|
@ -88,7 +88,7 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn can_seek(&self) -> bool {
|
fn can_seek(&self) -> bool {
|
||||||
true
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ impl Source for SymphoniaDecoder {
|
||||||
.seek(
|
.seek(
|
||||||
SeekMode::Accurate,
|
SeekMode::Accurate,
|
||||||
SeekTo::Time {
|
SeekTo::Time {
|
||||||
time: Time::new(pos.as_secs(), dbg!(pos_fract)),
|
time: Time::new(pos.as_secs(), pos_fract),
|
||||||
track_id: None,
|
track_id: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
10
src/sink.rs
10
src/sink.rs
|
@ -201,19 +201,19 @@ impl Sink {
|
||||||
/// Try to seek to a pos, returns [`SeekNotSupported`] if seeking is not
|
/// Try to seek to a pos, returns [`SeekNotSupported`] if seeking is not
|
||||||
/// supported by the current source.
|
/// supported by the current source.
|
||||||
///
|
///
|
||||||
/// We do not expose a `can_seek()` method here on purpose as its impossible to
|
/// We do not expose a `can_seek()` method here on purpose as its impossible to
|
||||||
/// use correctly. In between checking if the playing source supports seeking and
|
/// use correctly. In between checking if the playing source supports seeking and
|
||||||
/// actually seeking the sink can switch to a new source that potentially does not
|
/// actually seeking the sink can switch to a new source that potentially does not
|
||||||
/// support seeking. If you find a reason you need `Sink::can_seek()` here please
|
/// support seeking. If you find a reason you need `Sink::can_seek()` here please
|
||||||
/// open an issue
|
/// open an issue
|
||||||
pub fn try_seek(&self, pos: Duration) -> Result<(), SeekNotSupported> {
|
pub fn try_seek(&self, pos: Duration) -> Result<(), SeekNotSupported> {
|
||||||
let (order, feedback) = SeekOrder::new(pos);
|
let (order, feedback) = SeekOrder::new(pos);
|
||||||
*self.controls.seek.lock().unwrap() = Some(order);
|
*self.controls.seek.lock().unwrap() = Some(order);
|
||||||
match feedback.recv() {
|
match feedback.recv() {
|
||||||
Ok(seek_res) => seek_res,
|
Ok(seek_res) => seek_res,
|
||||||
// The feedback channel closed. Probably another seekorder was set
|
// The feedback channel closed. Probably another seekorder was set
|
||||||
// invalidating this one and closing the feedback channel
|
// invalidating this one and closing the feedback channel
|
||||||
// ... or the audio thread panicked.
|
// ... or the audio thread panicked.
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,37 @@
|
||||||
use std::io::BufReader;
|
use std::io::{BufReader, Read, Seek};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::Once;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use rodio::source::SeekNotSupported;
|
use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink, Source};
|
||||||
|
|
||||||
fn play_and_seek(asset_path: &Path) -> Result<(), SeekNotSupported> {
|
static mut STREAM: Option<OutputStream> = None;
|
||||||
let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
|
static mut STREAM_HANDLE: Option<OutputStreamHandle> = None;
|
||||||
let sink = rodio::Sink::try_new(&handle).unwrap();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
let file = std::fs::File::open(asset_path).unwrap();
|
fn global_stream_handle() -> &'static OutputStreamHandle {
|
||||||
sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
|
// mutable global access is guarded by Once therefore
|
||||||
sink.try_seek(Duration::from_secs(2))
|
// can only happen Once and will not race
|
||||||
|
unsafe {
|
||||||
|
INIT.call_once(|| {
|
||||||
|
let (stream, handle) = rodio::OutputStream::try_default().unwrap();
|
||||||
|
STREAM = Some(stream);
|
||||||
|
STREAM_HANDLE = Some(handle);
|
||||||
|
});
|
||||||
|
STREAM_HANDLE.as_ref().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn sink_and_decoder(format: &str) -> (Sink, Decoder<impl Read + Seek>) {
|
||||||
fn seek_returns_err_if_unsupported() {
|
let sink = rodio::Sink::try_new(global_stream_handle()).unwrap();
|
||||||
let formats = [
|
let asset = Path::new("assets/music").with_extension(format);
|
||||||
|
let file = std::fs::File::open(asset).unwrap();
|
||||||
|
let decoder = rodio::Decoder::new(BufReader::new(file)).unwrap();
|
||||||
|
(sink, decoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_decoder_info() -> &'static [(&'static str, bool, &'static str)] {
|
||||||
|
&[
|
||||||
#[cfg(feature = "minimp3")]
|
#[cfg(feature = "minimp3")]
|
||||||
("mp3", true, "minimp3"),
|
("mp3", true, "minimp3"),
|
||||||
#[cfg(feature = "symphonia-mp3")]
|
#[cfg(feature = "symphonia-mp3")]
|
||||||
|
@ -34,12 +50,30 @@ fn seek_returns_err_if_unsupported() {
|
||||||
("flac", true, "symphonia"),
|
("flac", true, "symphonia"),
|
||||||
#[cfg(feature = "symphonia-isomp4")]
|
#[cfg(feature = "symphonia-isomp4")]
|
||||||
("m4a", true, "_"),
|
("m4a", true, "_"),
|
||||||
];
|
]
|
||||||
|
}
|
||||||
|
|
||||||
for (format, supported, decoder) in formats {
|
#[test]
|
||||||
println!("trying: {format} by {decoder}, should support seek: {supported}");
|
fn seek_returns_err_if_unsupported() {
|
||||||
let asset = Path::new("assets/music").with_extension(format);
|
for (format, supported, decoder) in format_decoder_info().iter().cloned() {
|
||||||
let res = play_and_seek(&asset);
|
println!("trying: {format},\t\tby: {decoder},\t\tshould support seek: {supported}");
|
||||||
|
let (sink, decoder) = sink_and_decoder(format);
|
||||||
|
assert_eq!(decoder.can_seek(), supported);
|
||||||
|
sink.append(decoder);
|
||||||
|
let res = sink.try_seek(Duration::from_secs(2));
|
||||||
assert_eq!(res.is_ok(), supported);
|
assert_eq!(res.is_ok(), supported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn seek_beyond_end_does_not_crash() {
|
||||||
|
for (format, _, decoder_name) in format_decoder_info().iter().cloned() {
|
||||||
|
let (sink, decoder) = sink_and_decoder(format);
|
||||||
|
if !decoder.can_seek() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
println!("seeking beyond end for: {format}\t decoded by: {decoder_name}");
|
||||||
|
sink.append(decoder);
|
||||||
|
sink.try_seek(Duration::from_secs(999)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue