2021-08-24 23:35:28 -04:00
|
|
|
use crate::logic::ape::ApeFile;
|
2021-08-24 23:38:56 -04:00
|
|
|
use crate::logic::iff::aiff::AiffFile;
|
|
|
|
use crate::logic::iff::wav::WavFile;
|
2021-10-01 19:30:51 -04:00
|
|
|
use crate::logic::mp3::Mp3File;
|
2021-09-05 19:22:29 -04:00
|
|
|
use crate::logic::mp4::Mp4File;
|
2021-08-24 23:38:56 -04:00
|
|
|
use crate::logic::ogg::flac::FlacFile;
|
2021-08-24 23:35:28 -04:00
|
|
|
use crate::logic::ogg::opus::OpusFile;
|
|
|
|
use crate::logic::ogg::vorbis::VorbisFile;
|
2021-08-19 15:07:40 -04:00
|
|
|
use crate::types::file::AudioFile;
|
|
|
|
use crate::{FileType, LoftyError, Result, TaggedFile};
|
2021-08-02 17:25:31 -04:00
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
use std::io::{Cursor, Read, Seek};
|
2021-08-02 17:25:31 -04:00
|
|
|
use std::path::Path;
|
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Provides a way to extract a [`FileType`] or [`TaggedFile`] from a reader
|
|
|
|
pub struct Probe;
|
2021-08-02 17:25:31 -04:00
|
|
|
|
|
|
|
impl Probe {
|
|
|
|
/// Create a new `Probe`
|
|
|
|
pub fn new() -> Self {
|
2021-08-19 15:07:40 -04:00
|
|
|
Self
|
2021-08-02 17:25:31 -04:00
|
|
|
}
|
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Attempts to get the [`FileType`] based on the data in the reader
|
|
|
|
pub fn file_type<R>(&self, reader: &mut R) -> Option<FileType>
|
|
|
|
where
|
|
|
|
R: Read + Seek,
|
|
|
|
{
|
|
|
|
FileType::try_from_sig(reader).ok()
|
|
|
|
}
|
2021-08-02 17:25:31 -04:00
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Attempts to get a [`FileType`] from a path
|
|
|
|
///
|
|
|
|
/// NOTE: This is based on the content of the file.
|
|
|
|
/// If you want to guess based on extension, see [`Probe::file_type_from_extension`](Self::file_type_from_extension)
|
|
|
|
pub fn file_type_from_path(&self, path: impl AsRef<Path>) -> Option<FileType> {
|
|
|
|
if let Ok(content) = std::fs::read(&path) {
|
|
|
|
let mut cursor = Cursor::new(content);
|
|
|
|
return self.file_type(&mut cursor);
|
|
|
|
}
|
2021-08-02 17:25:31 -04:00
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
None
|
2021-08-02 17:25:31 -04:00
|
|
|
}
|
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Attempts to get the [`FileType`] based on the file extension
|
2021-08-02 17:25:31 -04:00
|
|
|
///
|
2021-08-19 15:07:40 -04:00
|
|
|
/// NOTE: Since this only looks at the extension, the result could be incorrect.
|
|
|
|
pub fn file_type_from_extension(&self, path: impl AsRef<Path>) -> Option<FileType> {
|
|
|
|
if let Some(ext_os) = path.as_ref().extension() {
|
|
|
|
if let Some(ext) = ext_os.to_str() {
|
2021-08-19 18:26:58 -04:00
|
|
|
return FileType::try_from_ext(&*ext.to_lowercase()).ok();
|
2021-08-19 15:07:40 -04:00
|
|
|
}
|
|
|
|
}
|
2021-08-02 17:25:31 -04:00
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
None
|
2021-08-02 17:25:31 -04:00
|
|
|
}
|
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Attempts to extract a [`TaggedFile`] from a reader
|
2021-08-02 17:25:31 -04:00
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
2021-08-19 15:07:40 -04:00
|
|
|
/// * The format couldn't be determined
|
|
|
|
pub fn read_from<R>(self, reader: &mut R) -> Result<TaggedFile>
|
2021-08-02 17:25:31 -04:00
|
|
|
where
|
|
|
|
R: Read + Seek,
|
|
|
|
{
|
2021-08-19 15:07:40 -04:00
|
|
|
match FileType::try_from_sig(reader) {
|
2021-09-13 17:39:32 -04:00
|
|
|
Ok(f_type) => Ok(match f_type {
|
|
|
|
FileType::AIFF => AiffFile::read_from(reader)?.into(),
|
|
|
|
FileType::APE => ApeFile::read_from(reader)?.into(),
|
|
|
|
FileType::FLAC => FlacFile::read_from(reader)?.into(),
|
2021-10-01 19:30:51 -04:00
|
|
|
FileType::MP3 => Mp3File::read_from(reader)?.into(),
|
2021-09-13 17:39:32 -04:00
|
|
|
FileType::Opus => OpusFile::read_from(reader)?.into(),
|
|
|
|
FileType::Vorbis => VorbisFile::read_from(reader)?.into(),
|
|
|
|
FileType::WAV => WavFile::read_from(reader)?.into(),
|
|
|
|
FileType::MP4 => Mp4File::read_from(reader)?.into(),
|
|
|
|
}),
|
2021-08-19 15:07:40 -04:00
|
|
|
Err(_) => Err(LoftyError::UnknownFormat),
|
|
|
|
}
|
|
|
|
}
|
2021-08-02 17:25:31 -04:00
|
|
|
|
2021-08-19 15:07:40 -04:00
|
|
|
/// Attempts to extract a [`TaggedFile`] from a path
|
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
|
|
|
/// * `path` does not exist
|
|
|
|
/// * The format couldn't be determined
|
|
|
|
pub fn read_from_path(self, path: impl AsRef<Path>) -> Result<TaggedFile> {
|
|
|
|
let mut cursor = Cursor::new(std::fs::read(&path)?);
|
|
|
|
self.read_from(&mut cursor)
|
2021-08-02 17:25:31 -04:00
|
|
|
}
|
|
|
|
}
|