use super::{default_config, raw_cost_per_sec, Error};
use crate::input::{AudioStream, Input, LiveInput};
use std::io::{Read, Result as IoResult, Seek};
use streamcatcher::{Catcher, Config};
use symphonia_core::io::MediaSource;
#[derive(Clone)]
pub struct Memory {
pub raw: Catcher<Box<dyn MediaSource>>,
}
impl Memory {
pub async fn new(source: Input) -> Result<Self, Error> {
Self::with_config(source, None).await
}
pub async fn with_config(source: Input, config: Option<Config>) -> Result<Self, Error> {
let input = match source {
Input::Lazy(mut r) => {
let created = if r.should_create_async() {
r.create_async().await
} else {
tokio::task::spawn_blocking(move || r.create()).await?
};
created.map(|v| v.input).map_err(Error::from)
},
Input::Live(LiveInput::Raw(a), _rec) => Ok(a.input),
Input::Live(LiveInput::Wrapped(a), _rec) =>
Ok(Box::new(a.input) as Box<dyn MediaSource>),
Input::Live(LiveInput::Parsed(_), _) => Err(Error::StreamNotAtStart),
}?;
let cost_per_sec = raw_cost_per_sec(true);
let config = config.unwrap_or_else(|| default_config(cost_per_sec));
let raw = config.build(input)?;
Ok(Self { raw })
}
#[must_use]
pub fn new_handle(&self) -> Self {
Self {
raw: self.raw.new_handle(),
}
}
}
impl Read for Memory {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
self.raw.read(buf)
}
}
impl Seek for Memory {
fn seek(&mut self, pos: std::io::SeekFrom) -> IoResult<u64> {
self.raw.seek(pos)
}
}
impl MediaSource for Memory {
fn is_seekable(&self) -> bool {
true
}
fn byte_len(&self) -> Option<u64> {
if self.raw.is_finished() {
Some(self.raw.len() as u64)
} else {
None
}
}
}
impl From<Memory> for Input {
fn from(val: Memory) -> Input {
let input = Box::new(val);
Input::Live(LiveInput::Raw(AudioStream { input }), None)
}
}