Initial work

This commit is contained in:
Serial 2021-07-19 14:15:56 -04:00
parent f7fa066698
commit 5e2d813470
10 changed files with 90 additions and 53 deletions

View file

@ -29,7 +29,7 @@ base64 = "0.13.0"
byteorder = "1.4.3"
cfg-if = "1.0.0"
lofty_attr = "0.1.8"
lofty_attr = {path = "lofty-attr"}
[features]
default = ["all_tags"]

View file

@ -64,6 +64,7 @@ pub fn impl_tag(input: TokenStream) -> TokenStream {
pub fn new() -> Self {
Self {
inner: #inner::default(),
properties: FileProperties::default(),
_format: #tag_type
}
}
@ -100,6 +101,7 @@ pub fn impl_tag(input: TokenStream) -> TokenStream {
fn from(inp: #inner) -> Self {
Self {
inner: inp,
properties: FileProperties::default(),
_format: #tag_type
}
}

View file

@ -3,9 +3,23 @@ pub(crate) mod tags;
use std::time::Duration;
/// Various audio properties
///
/// NOTE: All fields are invalidated after any type of conversion
pub struct FileProperties {
duration: Duration,
bitrate: u32,
sample_rate: u32,
channels: u8,
}
duration: Duration,
bitrate: Option<u32>,
sample_rate: Option<u32>,
channels: Option<u8>,
}
impl Default for FileProperties {
fn default() -> Self {
Self {
duration: Duration::ZERO,
bitrate: None,
sample_rate: None,
channels: None,
}
}
}

View file

@ -1,6 +1,7 @@
use crate::components::logic::aiff;
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, Result, TagType, ToAny,
ToAnyTag,
};
use std::fs::File;
@ -19,6 +20,7 @@ struct AiffInnerTag {
/// Represents Aiff Text Chunks
pub struct AiffTag {
inner: AiffInnerTag,
properties: FileProperties,
#[expected(TagType::AiffText)]
_format: TagType,
}
@ -38,6 +40,7 @@ impl AiffTag {
author_id,
copyright_id,
},
properties: FileProperties::default(), // TODO
_format: TagType::AiffText,
})
}

View file

@ -1,6 +1,7 @@
use crate::types::picture::{PicType, APE_PICTYPES};
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Picture, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, Picture, Result, TagType,
ToAny, ToAnyTag,
};
use std::borrow::Cow;
@ -15,6 +16,7 @@ use lofty_attr::{get_set_methods, LoftyTag};
/// Represents an APEv2 tag
pub struct ApeTag {
inner: ApeInnerTag,
properties: FileProperties,
#[expected(TagType::Ape)]
_format: TagType,
}
@ -28,6 +30,7 @@ impl ApeTag {
{
Ok(Self {
inner: ape::read_from(reader)?,
properties: FileProperties::default(), // TODO
_format: TagType::Ape,
})
}

View file

@ -1,7 +1,7 @@
use crate::tag::Id3Format;
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, LoftyError, MimeType, Picture,
PictureType, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, LoftyError, MimeType,
Picture, PictureType, Result, TagType, ToAny, ToAnyTag,
};
use std::borrow::Cow;
@ -17,6 +17,7 @@ use lofty_attr::LoftyTag;
/// Represents an ID3 tag
pub struct Id3v2Tag {
inner: Id3v2InnerTag,
properties: FileProperties,
#[expected(TagType::Id3v2(Id3Format::Mp3))]
_format: TagType,
}
@ -28,20 +29,17 @@ impl Id3v2Tag {
where
R: Read + Seek,
{
match format {
Id3Format::Mp3 => Ok(Self {
inner: Id3v2InnerTag::read_from(reader)?,
_format: TagType::Id3v2(format),
}),
Id3Format::Riff => Ok(Self {
inner: Id3v2InnerTag::read_from_wav_reader(reader)?,
_format: TagType::Id3v2(format),
}),
Id3Format::Aiff => Ok(Self {
inner: Id3v2InnerTag::read_from_aiff_reader(reader)?,
_format: TagType::Id3v2(format),
}),
}
let inner = match format {
Id3Format::Mp3 => Id3v2InnerTag::read_from(reader)?,
Id3Format::Riff => Id3v2InnerTag::read_from_wav_reader(reader)?,
Id3Format::Aiff => Id3v2InnerTag::read_from_aiff_reader(reader)?,
};
Ok(Self {
inner,
properties: FileProperties::default(), // TODO
_format: TagType::Id3v2(format),
})
}
}

View file

@ -1,6 +1,6 @@
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, LoftyError, MimeType, Picture,
PictureType, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, LoftyError, MimeType,
Picture, PictureType, Result, TagType, ToAny, ToAnyTag,
};
use std::borrow::Cow;
@ -14,6 +14,7 @@ pub use mp4ameta::{Fourcc, Tag as Mp4InnerTag};
/// Represents an MPEG-4 tag
pub struct Mp4Tag {
inner: Mp4InnerTag,
properties: FileProperties,
#[expected(TagType::Mp4)]
_format: TagType,
}
@ -25,8 +26,21 @@ impl Mp4Tag {
where
R: Read + Seek,
{
let inner = Mp4InnerTag::read_from(reader)?;
let duration = inner.info.duration;
let bitrate = inner.info.avg_bitrate;
let channels = inner.info.channel_config.map(|cc| cc.value());
let sample_rate = inner.info.sample_rate.map(|sr| sr.hz());
Ok(Self {
inner: Mp4InnerTag::read_from(reader)?,
inner,
properties: FileProperties {
duration: duration.unwrap_or_default(),
bitrate,
sample_rate,
channels,
},
_format: TagType::Mp4,
})
}

View file

@ -7,8 +7,8 @@ use crate::components::logic::ogg::constants::{OPUSHEAD, OPUSTAGS};
#[cfg(feature = "format-vorbis")]
use crate::components::logic::ogg::constants::{VORBIS_COMMENT_HEAD, VORBIS_IDENT_HEAD};
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, LoftyError, OggFormat, Picture,
PictureType, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, LoftyError, OggFormat,
Picture, PictureType, Result, TagType, ToAny, ToAnyTag,
};
#[cfg(any(feature = "format-opus", feature = "format-vorbis"))]
@ -81,6 +81,7 @@ cfg_if::cfg_if! {
/// Represents vorbis comments from multiple OGG formats
pub struct OggTag {
inner: OggInnerTag,
properties: FileProperties,
#[expected(TagType::Ogg(OggFormat::Opus))]
_format: TagType,
}
@ -89,6 +90,7 @@ cfg_if::cfg_if! {
/// Represents vorbis comments from multiple OGG formats
pub struct OggTag {
inner: OggInnerTag,
properties: FileProperties,
#[expected(TagType::Ogg(OggFormat::Vorbis))]
_format: TagType,
}
@ -97,6 +99,7 @@ cfg_if::cfg_if! {
/// Represents vorbis comments from multiple OGG formats
pub struct OggTag {
inner: OggInnerTag,
properties: FileProperties,
#[expected(TagType::Ogg(OggFormat::Flac))]
_format: TagType,
}
@ -108,21 +111,19 @@ impl TryFrom<OGGTags> for OggTag {
type Error = LoftyError;
fn try_from(inp: OGGTags) -> Result<Self> {
let mut tag = Self::new();
let vendor = inp.0;
let pictures = inp.1;
let comments = inp.2;
tag._format = TagType::Ogg(inp.3);
tag.inner = OggInnerTag {
vendor,
comments,
pictures: (!pictures.is_empty()).then(|| Cow::from(pictures)),
};
Ok(tag)
Ok(Self {
inner: OggInnerTag {
vendor,
comments,
pictures: (!pictures.is_empty()).then(|| Cow::from(pictures)),
},
properties: FileProperties::default(), // TODO
_format: TagType::Ogg(inp.3),
})
}
}
@ -131,8 +132,6 @@ impl TryFrom<metaflac::Tag> for OggTag {
type Error = LoftyError;
fn try_from(inp: metaflac::Tag) -> Result<Self> {
let mut tag = Self::new();
if let Some(comments) = inp.vorbis_comments() {
let mut user_comments = comments.comments.clone();
@ -154,15 +153,15 @@ impl TryFrom<metaflac::Tag> for OggTag {
}
}
tag._format = TagType::Ogg(OggFormat::Flac);
tag.inner = OggInnerTag {
vendor: comments.vendor_string.clone(),
comments: comment_collection,
pictures: Some(Cow::from(pictures)),
};
return Ok(tag);
return Ok(Self {
inner: OggInnerTag {
vendor: comments.vendor_string.clone(),
comments: comment_collection,
pictures: Some(Cow::from(pictures)),
},
properties: FileProperties::default(), // TODO
_format: TagType::Ogg(OggFormat::Flac),
})
}
Err(LoftyError::InvalidData(
@ -180,6 +179,7 @@ impl OggTag {
{
Ok(Self {
inner: OggInnerTag::read_from(reader, &format)?,
properties: FileProperties::default(), // TODO
_format: TagType::Ogg(format),
})
}

View file

@ -1,6 +1,7 @@
use crate::components::logic::riff;
use crate::{
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Result, TagType, ToAny, ToAnyTag,
Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, FileProperties, Result, TagType, ToAny,
ToAnyTag,
};
use std::collections::HashMap;
@ -25,6 +26,7 @@ impl Default for RiffInnerTag {
/// Represents a RIFF INFO LIST
pub struct RiffTag {
inner: RiffInnerTag,
properties: FileProperties,
#[expected(TagType::RiffInfo)]
_format: TagType,
}
@ -40,6 +42,7 @@ impl RiffTag {
inner: RiffInnerTag {
data: riff::read_from(reader)?,
},
properties: FileProperties::default(),
_format: TagType::RiffInfo,
})
}

View file

@ -146,7 +146,7 @@ mod error;
pub use crate::error::{LoftyError, Result};
mod components;
pub use crate::components::tags::*;
pub use crate::components::{tags::*, FileProperties};
mod traits;
pub use crate::traits::{AudioTag, AudioTagEdit, AudioTagWrite, ToAny, ToAnyTag};