Finally separate VorbisTag::read_from_path from the other tags

Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
Serial 2021-04-18 14:07:26 -04:00
parent 48e6182e3a
commit b072f0b0e5
8 changed files with 141 additions and 94 deletions

View file

@ -4,13 +4,13 @@ use crate::{
impl_tag, traits::ReadPath, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Picture,
Result, TagType, ToAny, ToAnyTag,
};
use std::{fs::File, path::Path};
pub use ape::Tag as ApeInnerTag;
use filepath::FilePath;
use std::{fs::File, path::Path};
impl ReadPath for ApeInnerTag {
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P) -> Result<Self>
where
P: AsRef<std::path::Path>,
Self: Sized,
@ -21,6 +21,16 @@ impl ReadPath for ApeInnerTag {
impl_tag!(ApeTag, ApeInnerTag, TagType::Ape);
impl ApeTag {
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(ApeInnerTag::from_path(path)?))
}
}
impl<'a> From<&'a ApeTag> for AnyTag<'a> {
fn from(inp: &'a ApeTag) -> Self {
Self {

View file

@ -4,12 +4,14 @@ use crate::{
impl_tag, traits::ReadPath, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Error,
MimeType, Picture, Result, TagType, ToAny, ToAnyTag,
};
use std::{convert::TryInto, fs::File, path::Path};
pub use id3::Tag as Id3v2InnerTag;
use std::convert::TryInto;
use std::fs::File;
use std::path::Path;
impl ReadPath for Id3v2InnerTag {
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P) -> Result<Self>
where
P: AsRef<std::path::Path>,
Self: Sized,
@ -20,6 +22,16 @@ impl ReadPath for Id3v2InnerTag {
impl_tag!(Id3v2Tag, Id3v2InnerTag, TagType::Id3v2);
impl Id3v2Tag {
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(Id3v2InnerTag::from_path(path)?))
}
}
impl<'a> From<&'a Id3v2Tag> for AnyTag<'a> {
fn from(inp: &'a Id3v2Tag) -> Self {
Self {

View file

@ -4,12 +4,13 @@ use crate::{
impl_tag, traits::ReadPath, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Error,
MimeType, Picture, Result, TagType, ToAny, ToAnyTag,
};
use std::{fs::File, path::Path};
pub use mp4ameta::{FourCC, Tag as Mp4InnerTag};
use std::fs::File;
use std::path::Path;
impl ReadPath for Mp4InnerTag {
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P) -> Result<Self>
where
P: AsRef<std::path::Path>,
Self: Sized,
@ -20,6 +21,16 @@ impl ReadPath for Mp4InnerTag {
impl_tag!(Mp4Tag, Mp4InnerTag, TagType::Mp4);
impl Mp4Tag {
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(Mp4InnerTag::from_path(path)?))
}
}
impl<'a> From<&'a Mp4Tag> for AnyTag<'a> {
fn from(inp: &'a Mp4Tag) -> Self {
let title = inp.title();

View file

@ -1,24 +1,21 @@
#![cfg(feature = "vorbis")]
use crate::{
components::logic, impl_tag, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Picture,
Result, TagType, ToAny, ToAnyTag,
};
use std::{
borrow::BorrowMut,
collections::HashMap,
fs::File,
fs::OpenOptions,
io::Write,
io::{Cursor, Seek, SeekFrom},
path::Path,
components::logic, impl_tag, tag::VorbisFormat, Album, AnyTag, AudioTag, AudioTagEdit,
AudioTagWrite, Picture, Result, TagType, ToAny, ToAnyTag,
};
use std::borrow::BorrowMut;
use std::collections::HashMap;
use std::fs::{File, OpenOptions};
use std::io::{Cursor, Seek, SeekFrom, Write};
use std::path::Path;
const START_SIGNATURE: [u8; 7] = [3, 118, 111, 114, 98, 105, 115];
const END_BYTE: u8 = 1;
struct VorbisInnerTag {
tag_type: Option<TagType>,
format: Option<VorbisFormat>,
vendor: String,
comments: HashMap<String, String>,
}
@ -26,7 +23,7 @@ struct VorbisInnerTag {
impl Default for VorbisInnerTag {
fn default() -> Self {
Self {
tag_type: None,
format: None,
vendor: "".to_string(),
comments: std::collections::HashMap::default(),
}
@ -59,63 +56,71 @@ impl VorbisInnerTag {
self.comments = comments;
}
fn from_path<P>(path: P, tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P, format: VorbisFormat) -> Result<Self>
where
P: AsRef<Path>,
{
if let Some(tag_type) = tag_type {
match tag_type {
TagType::Ogg => {
let headers =
lewton::inside_ogg::OggStreamReader::new(File::open(path)?).unwrap();
match format {
VorbisFormat::Ogg => {
let headers = lewton::inside_ogg::OggStreamReader::new(File::open(path)?).unwrap();
let vendor = headers.comment_hdr.vendor;
let vendor = headers.comment_hdr.vendor;
let comments: HashMap<String, String> =
headers.comment_hdr.comment_list.into_iter().collect();
let comments: HashMap<String, String> =
headers.comment_hdr.comment_list.into_iter().collect();
Ok(Self {
tag_type: Some(tag_type),
vendor,
comments,
})
},
TagType::Opus => {
let headers = opus_headers::parse_from_path(path)?;
let vendor = headers.comments.vendor;
Ok(Self {
format: Some(format),
vendor,
comments,
})
},
VorbisFormat::Opus => {
let headers = opus_headers::parse_from_path(path)?;
let vendor = headers.comments.vendor;
Ok(Self {
tag_type: Some(tag_type),
vendor,
comments: headers.comments.user_comments,
})
},
TagType::Flac => {
let headers = metaflac::Tag::read_from_path(path)?;
let comments = headers.vorbis_comments().unwrap();
let mut comment_collection = Vec::new();
Ok(Self {
format: Some(format),
vendor,
comments: headers.comments.user_comments,
})
},
VorbisFormat::Flac => {
let headers = metaflac::Tag::read_from_path(path)?;
let comments = headers.vorbis_comments().unwrap();
let mut comment_collection = Vec::new();
for (k, v) in comments.comments.clone() {
for e in v {
comment_collection.push((k.clone(), e.clone()))
}
for (k, v) in comments.comments.clone() {
for e in v {
comment_collection.push((k.clone(), e.clone()))
}
}
Ok(Self {
tag_type: Some(tag_type),
vendor: comments.vendor_string.clone(),
comments: comment_collection.into_iter().collect(),
})
},
_ => unreachable!(),
}
} else {
unreachable!()
Ok(Self {
format: Some(format),
vendor: comments.vendor_string.clone(),
comments: comment_collection.into_iter().collect(),
})
},
}
}
}
impl_tag!(VorbisTag, VorbisInnerTag, TagType::Ogg);
impl_tag!(
VorbisTag,
VorbisInnerTag,
TagType::Vorbis(VorbisFormat::Ogg)
);
impl VorbisTag {
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P, format: VorbisFormat) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(VorbisInnerTag::from_path(path, format)?))
}
}
impl<'a> From<AnyTag<'a>> for VorbisTag {
fn from(inp: AnyTag<'a>) -> Self {
@ -196,7 +201,7 @@ impl From<metaflac::Tag> for VorbisTag {
};
tag.0 = VorbisInnerTag {
tag_type: Some(TagType::Flac),
format: Some(VorbisFormat::Flac),
vendor,
comments,
};
@ -396,9 +401,9 @@ impl AudioTagEdit for VorbisTag {
impl AudioTagWrite for VorbisTag {
fn write_to(&self, file: &mut File) -> Result<()> {
if let Some(tag_type) = self.0.tag_type.clone() {
match tag_type {
TagType::Ogg => {
if let Some(format) = self.0.format.clone() {
match format {
VorbisFormat::Ogg => {
let vendor = self.0.vendor.clone();
let vendor_bytes = vendor.as_bytes();
@ -442,16 +447,14 @@ impl AudioTagWrite for VorbisTag {
file.set_len(0)?;
file.write_all(&data)?;
},
TagType::Flac => {
VorbisFormat::Flac => {
let mut flac_tag: metaflac::Tag = self.into();
flac_tag.write_to(file)?;
},
TagType::Opus => {
VorbisFormat::Opus => {
todo!()
},
TagType::Mp4 => {},
_ => unreachable!(),
}
}

View file

@ -13,7 +13,7 @@ struct WavInnerTag {
}
impl ReadPath for WavInnerTag {
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P) -> Result<Self>
where
P: AsRef<std::path::Path>,
Self: Sized,
@ -32,6 +32,8 @@ impl Default for WavInnerTag {
}
}
impl_tag!(WavTag, WavInnerTag, TagType::Wav);
impl<'a> From<AnyTag<'a>> for WavTag {
fn from(inp: AnyTag<'a>) -> Self {
let mut tag = WavTag::default();
@ -84,7 +86,15 @@ impl<'a> From<&'a WavTag> for AnyTag<'a> {
}
}
impl_tag!(WavTag, WavInnerTag, TagType::Wav);
impl WavTag {
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(WavInnerTag::from_path(path)?))
}
}
impl WavTag {
fn get_value(&self, key: &str) -> Option<&str> {

View file

@ -15,13 +15,6 @@ macro_rules! impl_tag {
pub fn new() -> Self {
Self::default()
}
#[allow(clippy::missing_errors_doc)]
pub fn read_from_path<P>(path: P, tag_type: Option<TagType>) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self($inner::from_path(path, tag_type)?))
}
}
use std::any::Any;

View file

@ -38,15 +38,15 @@ impl Tag {
.unwrap_or(&TagType::try_from_ext(extension_str)?)
{
#[cfg(feature = "ape")]
TagType::Ape => Ok(Box::new(ApeTag::read_from_path(path, None)?)),
TagType::Ape => Ok(Box::new(ApeTag::read_from_path(path)?)),
#[cfg(feature = "mp3")]
TagType::Id3v2 => Ok(Box::new(Id3v2Tag::read_from_path(path, None)?)),
TagType::Id3v2 => Ok(Box::new(Id3v2Tag::read_from_path(path)?)),
#[cfg(feature = "mp4")]
TagType::Mp4 => Ok(Box::new(Mp4Tag::read_from_path(path, None)?)),
TagType::Mp4 => Ok(Box::new(Mp4Tag::read_from_path(path)?)),
#[cfg(feature = "wav")]
TagType::Wav => Ok(Box::new(WavTag::read_from_path(path, None)?)),
#[cfg(feature = "vorbis")] // TODO: this isn't ideal, make this better somehow
id => Ok(Box::new(VorbisTag::read_from_path(path, Some(id.clone()))?)),
TagType::Wav => Ok(Box::new(WavTag::read_from_path(path)?)),
#[cfg(feature = "vorbis")]
TagType::Vorbis(format) => Ok(Box::new(VorbisTag::read_from_path(path, format.clone())?)),
}
}
}
@ -63,6 +63,17 @@ pub enum TagType {
#[cfg(feature = "mp4")]
/// Common file extensions: `.mp4, .m4a, .m4p, .m4b, .m4r, .m4v`
Mp4,
#[cfg(feature = "vorbis")]
/// Represents multiple formats, see [`VorbisFormat`] for extensions.
Vorbis(VorbisFormat),
#[cfg(feature = "wav")]
/// Common file extensions: `.wav, .wave`
Wav,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg(feature = "vorbis")]
pub enum VorbisFormat {
#[cfg(feature = "vorbis")]
/// Common file extensions: `.ogg, .oga`
Ogg,
@ -72,9 +83,6 @@ pub enum TagType {
#[cfg(feature = "vorbis")]
/// Common file extensions: `.flac`
Flac,
#[cfg(feature = "wav")]
/// Common file extensions: `.wav, .wave`
Wav,
}
impl TagType {
@ -85,11 +93,11 @@ impl TagType {
#[cfg(feature = "mp3")]
"mp3" => Ok(Self::Id3v2),
#[cfg(feature = "vorbis")]
"opus" => Ok(Self::Opus),
"opus" => Ok(Self::Vorbis(VorbisFormat::Opus)),
#[cfg(feature = "vorbis")]
"flac" => Ok(Self::Flac),
"flac" => Ok(Self::Vorbis(VorbisFormat::Flac)),
#[cfg(feature = "vorbis")]
"ogg" | "oga" => Ok(Self::Ogg),
"ogg" | "oga" => Ok(Self::Vorbis(VorbisFormat::Ogg)),
#[cfg(feature = "mp4")]
"m4a" | "m4b" | "m4p" | "m4v" | "isom" | "mp4" => Ok(Self::Mp4),
#[cfg(feature = "wav")]

View file

@ -1,6 +1,6 @@
use crate::WavTag;
#[allow(clippy::wildcard_imports)]
use crate::{components::tags::*, Album, AnyTag, Picture, Result, TagType};
use std::fs::File;
pub trait AudioTag: AudioTagEdit + AudioTagWrite + ToAnyTag {}
@ -114,7 +114,7 @@ pub trait ToAnyTag: ToAny {
#[cfg(feature = "mp4")]
TagType::Mp4 => Box::new(Mp4Tag::from(self.to_anytag())),
#[cfg(feature = "vorbis")]
TagType::Ogg | TagType::Opus | TagType::Flac => Box::new(VorbisTag::from(self.to_anytag())),
TagType::Vorbis(_) => Box::new(VorbisTag::from(self.to_anytag())),
#[cfg(feature = "wav")]
TagType::Wav => Box::new(WavTag::from(self.to_anytag())),
}
@ -127,7 +127,7 @@ pub trait ToAny {
}
pub trait ReadPath {
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
fn from_path<P>(path: P) -> Result<Self>
where
P: AsRef<std::path::Path>,
Self: Sized;