use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
mod codec;
pub use codec::*;
mod format;
pub use format::*;
mod sample_format;
pub use sample_format::*;
mod stream;
pub use stream::*;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ContainerError {
#[error("IoError: {0}")]
Io(#[from] std::io::Error),
#[error("Codec Error: {0}")]
Codec(#[from] CodecError),
#[error("Symphonia Error: {0}")]
Symphonia(#[from] symphonia::core::errors::Error),
#[error("File '{0}' has no tracks/streams")]
NoStream(PathBuf),
#[error("File '{0}' has an unsupported container")]
InvalidSource(PathBuf),
#[error("'{0:?}' is an unsupported container")]
UnsupportedContainer(ContainerFormat),
#[error("Couldn't find sample rate")]
NoSampleRate,
#[error("Couldn't find channel count'")]
NoChannelCount,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct MediaContainer {
pub(crate) path: PathBuf,
pub(crate) format: ContainerFormat,
pub(crate) stream: Stream,
}
impl MediaContainer {
pub(crate) fn set_path(&mut self, path: PathBuf) {
self.path = path;
}
}
impl MediaContainer {
#[must_use]
pub fn path(&self) -> &Path {
&self.path
}
#[must_use]
pub fn format(&self) -> &ContainerFormat {
&self.format
}
#[must_use]
pub fn extension(&self) -> &'static str {
let format = self.format;
let codec = self.stream.codec_params.codec;
match format {
ContainerFormat::Flac if codec.is_flac() => "flac",
ContainerFormat::Mpa if codec.is_mp3() => "mp3",
ContainerFormat::Ogg if codec.is_vorbis() => "ogg",
ContainerFormat::Ogg if codec.is_opus() => "opus",
ContainerFormat::Ogg if codec.is_flac() => "oga",
ContainerFormat::Wav if codec.is_pcm() => "wav",
ContainerFormat::Aiff if codec.is_pcm() => "aiff",
ContainerFormat::Ape if codec.is_ape() => "ape",
_ => panic!("Invalid format/codec pairing: {format:?} + {codec:?}"),
}
}
#[must_use]
pub fn stream(&self) -> &Stream {
&self.stream
}
}