Skip to main content

selene_core/
media_container.rs

1use std::path::{Path, PathBuf};
2
3use serde::{Deserialize, Serialize};
4
5mod codec;
6pub use codec::*;
7
8mod format;
9pub use format::*;
10
11mod sample_format;
12pub use sample_format::*;
13
14mod stream;
15pub use stream::*;
16use thiserror::Error;
17
18#[derive(Debug, Error)]
19pub enum ContainerError {
20    #[error("IoError: {0}")]
21    Io(#[from] std::io::Error),
22
23    #[error("Codec Error: {0}")]
24    Codec(#[from] CodecError),
25
26    #[error("Symphonia Error: {0}")]
27    Symphonia(#[from] symphonia::core::errors::Error),
28
29    #[error("File '{0}' has no tracks/streams")]
30    NoStream(PathBuf),
31
32    #[error("File '{0}' has an unsupported container")]
33    InvalidSource(PathBuf),
34
35    #[error("'{0:?}' is an unsupported container")]
36    UnsupportedContainer(ContainerFormat),
37
38    #[error("Couldn't find sample rate")]
39    NoSampleRate,
40
41    #[error("Couldn't find channel count'")]
42    NoChannelCount,
43}
44
45#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
46pub struct MediaContainer {
47    pub(crate) path: PathBuf,
48    pub(crate) format: ContainerFormat,
49    pub(crate) stream: Stream,
50}
51
52impl MediaContainer {
53    pub(crate) fn set_path(&mut self, path: PathBuf) {
54        self.path = path;
55    }
56}
57
58impl MediaContainer {
59    #[must_use]
60    pub fn path(&self) -> &Path {
61        &self.path
62    }
63
64    #[must_use]
65    pub fn format(&self) -> &ContainerFormat {
66        &self.format
67    }
68
69    /// Returns the file extension this [`MediaContainer`] uses. Returns [`Option::None`] for invalid or unrecognized pairs
70    #[must_use]
71    pub fn extension(&self) -> &'static str {
72        let format = self.format;
73        let codec = self.stream.codec_params.codec;
74        match format {
75            ContainerFormat::Flac if codec.is_flac() => "flac",
76            ContainerFormat::Mpa if codec.is_mp3() => "mp3",
77            ContainerFormat::Ogg if codec.is_vorbis() => "ogg",
78            ContainerFormat::Ogg if codec.is_opus() => "opus",
79            ContainerFormat::Ogg if codec.is_flac() => "oga",
80            ContainerFormat::Wav if codec.is_pcm() => "wav",
81            ContainerFormat::Aiff if codec.is_pcm() => "aiff",
82            ContainerFormat::Ape if codec.is_ape() => "ape",
83            _ => panic!("Invalid format/codec pairing: {format:?} + {codec:?}"),
84        }
85    }
86
87    #[must_use]
88    pub fn stream(&self) -> &Stream {
89        &self.stream
90    }
91}