use std::{
io::{self, SeekFrom},
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread,
time::Duration,
};
pub(super) struct GrowingMediaSource {
pub(super) file: std::fs::File,
pub(super) writer_alive: Option<Arc<AtomicBool>>,
}
impl io::Read for GrowingMediaSource {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
loop {
match self.file.read(buf) {
Ok(0) => {
let still_writing = self
.writer_alive
.as_ref()
.is_some_and(|w| w.load(Ordering::SeqCst));
if !still_writing {
return Ok(0);
}
thread::sleep(Duration::from_millis(15));
}
result => return result,
}
}
}
}
impl io::Seek for GrowingMediaSource {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
if self.writer_alive.is_none() {
self.file.seek(pos)
} else {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"streaming source is not seekable",
))
}
}
}
impl symphonia::core::io::MediaSource for GrowingMediaSource {
fn is_seekable(&self) -> bool {
self.writer_alive.is_none()
}
fn byte_len(&self) -> Option<u64> {
if self.writer_alive.is_none() {
self.file.metadata().ok().map(|m| m.len())
} else {
None
}
}
}