This commit is contained in:
Tianyi 2020-10-27 13:09:41 +00:00
commit 7eb57f1874
6 changed files with 46 additions and 81 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "audiotags"
version = "0.2.7"
version = "0.2.71"
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
edition = "2018"
description = "Unified IO for different types of audio metadata"
@ -13,6 +13,5 @@ repository = "https://github.com/TianyiShi2001/audiotags"
id3 = "0.5.1"
mp4ameta = "0.6"
metaflac = "0.2"
beef = "0.4.4"
thiserror = "1.0.21"
audiotags-dev-macro = {path = "./audiotags-dev-macro", version = "0.1.1"}

View file

@ -39,15 +39,11 @@ impl<'a> From<AnyTag<'a>> for FlacTag {
impl<'a> From<&'a FlacTag> for AnyTag<'a> {
fn from(inp: &'a FlacTag) -> Self {
let mut t = Self::default();
t.title = inp.title().map(Cow::borrowed);
t.artists = inp
.artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>());
t.title = inp.title();
t.artists = inp.artists();
t.year = inp.year();
t.album_title = inp.album_title().map(Cow::borrowed);
t.album_artists = inp
.album_artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>());
t.album_title = inp.album_title();
t.album_artists = inp.album_artists();
t.album_cover = inp.album_cover();
t.track_number = inp.track_number();
t.total_tracks = inp.total_tracks();
@ -130,7 +126,7 @@ impl AudioTag for FlacTag {
.next()
.and_then(|pic| {
Some(Picture {
data: Cow::borrowed(&pic.data),
data: &pic.data,
mime_type: (pic.mime_type.as_str()).try_into().ok()?,
})
})
@ -140,7 +136,7 @@ impl AudioTag for FlacTag {
let mime = String::from(cover.mime_type);
let picture_type = metaflac::block::PictureType::CoverFront;
self.inner
.add_picture(mime, picture_type, cover.data.into_owned());
.add_picture(mime, picture_type, (cover.data).to_owned());
}
fn track_number(&self) -> Option<u16> {

View file

@ -10,15 +10,11 @@ impl<'a> From<&'a Id3v2Tag> for AnyTag<'a> {
Self {
config: inp.config.clone(),
title: inp.title().map(Cow::borrowed),
artists: inp
.artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>()),
title: inp.title(),
artists: inp.artists(),
year: inp.year(),
album_title: inp.album_title().map(Cow::borrowed),
album_artists: inp
.album_artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>()),
album_title: inp.album_title(),
album_artists: inp.album_artists(),
album_cover: inp.album_cover(),
track_number: inp.track_number(),
total_tracks: inp.total_tracks(),
@ -75,21 +71,7 @@ impl<'a> std::convert::TryFrom<&'a id3::frame::Picture> for Picture<'a> {
} = inp;
let mime_type: MimeType = mime_type.as_str().try_into()?;
Ok(Self {
data: Cow::borrowed(&data),
mime_type,
})
}
}
impl<'a> std::convert::TryFrom<id3::frame::Picture> for Picture<'a> {
type Error = crate::Error;
fn try_from(inp: id3::frame::Picture) -> crate::Result<Self> {
let id3::frame::Picture {
mime_type, data, ..
} = inp;
let mime_type: MimeType = mime_type.as_str().try_into()?;
Ok(Self {
data: Cow::owned(data),
data: &data,
mime_type,
})
}
@ -154,7 +136,7 @@ impl AudioTag for Id3v2Tag {
.next()
.and_then(|pic| {
Some(Picture {
data: Cow::borrowed(&pic.data),
data: &pic.data,
mime_type: (pic.mime_type.as_str()).try_into().ok()?,
})
})
@ -165,7 +147,7 @@ impl AudioTag for Id3v2Tag {
mime_type: String::from(cover.mime_type),
picture_type: id3::frame::PictureType::CoverFront,
description: "".to_owned(),
data: cover.data.into_owned(),
data: cover.data.to_owned(),
});
}
fn remove_album_cover(&mut self) {

View file

@ -38,8 +38,6 @@ use std::convert::From;
use std::fs::File;
use std::path::Path;
use beef::lean::Cow;
use std::convert::{TryFrom, TryInto};
#[derive(Clone, Copy, Debug)]
@ -175,51 +173,44 @@ impl From<MimeType> for String {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Picture<'a> {
pub data: Cow<'a, [u8]>,
pub data: &'a [u8],
pub mime_type: MimeType,
}
impl<'a> Picture<'a> {
pub fn new(data: &'a [u8], mime_type: MimeType) -> Self {
Self {
data: Cow::borrowed(data),
mime_type,
}
Self { data, mime_type }
}
}
/// A struct for representing an album for convinience.
#[derive(Debug)]
pub struct Album<'a> {
pub title: Cow<'a, str>,
pub artist: Option<Cow<'a, str>>,
pub title: &'a str,
pub artist: Option<&'a str>,
pub cover: Option<Picture<'a>>,
}
impl<'a> Album<'a> {
pub fn with_title(title: impl Into<String>) -> Self {
pub fn with_title(title: &'a str) -> Self {
Self {
title: Cow::owned(title.into()),
title: title,
artist: None,
cover: None,
}
}
pub fn and_artist(mut self, artist: impl Into<String>) -> Self {
self.artist = Some(Cow::owned(artist.into()));
pub fn and_artist(mut self, artist: &'a str) -> Self {
self.artist = Some(artist);
self
}
pub fn and_cover(mut self, cover: Picture<'a>) -> Self {
self.cover = Some(cover);
self
}
pub fn with_all(
title: impl Into<String>,
artist: impl Into<String>,
cover: Picture<'a>,
) -> Self {
pub fn with_all(title: &'a str, artist: &'a str, cover: Picture<'a>) -> Self {
Self {
title: Cow::owned(title.into()),
artist: Some(Cow::owned(artist.into())),
title,
artist: Some(artist),
cover: Some(cover),
}
}
@ -228,11 +219,11 @@ impl<'a> Album<'a> {
#[derive(Default)]
pub struct AnyTag<'a> {
pub config: Config,
pub title: Option<Cow<'a, str>>,
pub artists: Option<Vec<Cow<'a, str>>>, // ? iterator
pub title: Option<&'a str>,
pub artists: Option<Vec<&'a str>>, // ? iterator
pub year: Option<i32>,
pub album_title: Option<Cow<'a, str>>,
pub album_artists: Option<Vec<Cow<'a, str>>>, // ? iterator
pub album_title: Option<&'a str>,
pub album_artists: Option<Vec<&'a str>>, // ? iterator
pub album_cover: Option<Picture<'a>>,
pub track_number: Option<u16>,
pub total_tracks: Option<u16>,
@ -244,7 +235,7 @@ impl AnyTag<'_> {
pub fn title(&self) -> Option<&str> {
self.title.as_deref()
}
pub fn artists(&self) -> Option<&[Cow<str>]> {
pub fn artists(&self) -> Option<&[&str]> {
self.artists.as_deref()
}
pub fn year(&self) -> Option<i32> {
@ -253,7 +244,7 @@ impl AnyTag<'_> {
pub fn album_title(&self) -> Option<&str> {
self.album_title.as_deref()
}
pub fn album_artists(&self) -> Option<&[Cow<str>]> {
pub fn album_artists(&self) -> Option<&[&str]> {
self.album_artists.as_deref()
}
pub fn track_number(&self) -> Option<u16> {
@ -316,8 +307,8 @@ pub trait AudioTag: AudioTagCommon {
fn album(&self) -> Option<Album<'_>> {
self.album_title().map(|title| Album {
title: Cow::borrowed(title),
artist: self.album_artist().map(Cow::borrowed),
title,
artist: self.album_artist(),
cover: self.album_cover(),
})
}

View file

@ -7,15 +7,13 @@ impl_tag!(Mp4Tag, InnerTag);
impl<'a> From<&'a Mp4Tag> for AnyTag<'a> {
fn from(inp: &'a Mp4Tag) -> Self {
let title = inp.title().map(Cow::borrowed);
let artists = inp
.artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>());
let title = inp.title();
let artists = inp.artists().map(|i| i.into_iter().collect::<Vec<_>>());
let year = inp.year();
let album_title = inp.album_title().map(Cow::borrowed);
let album_title = inp.album_title();
let album_artists = inp
.album_artists()
.map(|i| i.into_iter().map(Cow::borrowed).collect::<Vec<_>>());
.map(|i| i.into_iter().collect::<Vec<_>>());
let album_cover = inp.album_cover();
let (a, b) = inp.track();
let track_number = a;
@ -47,11 +45,11 @@ impl<'a> From<AnyTag<'a>> for Mp4Tag {
let mut t = mp4ameta::Tag::default();
inp.title().map(|v| t.set_title(v));
inp.artists()
.map(|i| i.iter().for_each(|a| t.add_artist(a.as_ref())));
.map(|i| i.iter().for_each(|&a| t.add_artist(a)));
inp.year.map(|v| t.set_year(v.to_string()));
inp.album_title().map(|v| t.set_album(v));
inp.album_artists()
.map(|i| i.iter().for_each(|a| t.add_album_artist(a.as_ref())));
.map(|i| i.iter().for_each(|&a| t.add_album_artist(a)));
inp.track_number().map(|v| t.set_track_number(v));
inp.total_tracks().map(|v| t.set_total_tracks(v));
inp.disc_number().map(|v| t.set_disc_number(v));
@ -67,11 +65,11 @@ impl<'a> std::convert::TryFrom<&'a mp4ameta::Data> for Picture<'a> {
fn try_from(inp: &'a mp4ameta::Data) -> crate::Result<Self> {
Ok(match *inp {
mp4ameta::Data::Png(ref data) => Self {
data: Cow::borrowed(data),
data,
mime_type: MimeType::Png,
},
mp4ameta::Data::Jpeg(ref data) => Self {
data: Cow::borrowed(data),
data,
mime_type: MimeType::Jpeg,
},
_ => return Err(crate::Error::NotAPicture),
@ -148,11 +146,11 @@ impl AudioTag for Mp4Tag {
use mp4ameta::Data::*;
self.inner.artwork().and_then(|data| match data {
Jpeg(d) => Some(Picture {
data: Cow::borrowed(d),
data: d,
mime_type: MimeType::Jpeg,
}),
Png(d) => Some(Picture {
data: Cow::borrowed(d),
data: d,
mime_type: MimeType::Png,
}),
_ => None,
@ -161,8 +159,8 @@ impl AudioTag for Mp4Tag {
fn set_album_cover(&mut self, cover: Picture) {
self.remove_album_cover();
self.inner.add_artwork(match cover.mime_type {
MimeType::Png => mp4ameta::Data::Png(cover.data.into_owned()),
MimeType::Jpeg => mp4ameta::Data::Jpeg(cover.data.into_owned()),
MimeType::Png => mp4ameta::Data::Png(cover.data.to_owned()),
MimeType::Jpeg => mp4ameta::Data::Jpeg(cover.data.to_owned()),
_ => panic!("Only png and jpeg are supported in m4a"),
});
}

View file

@ -1,5 +1,4 @@
use audiotags::{MimeType, Picture, Tag};
use beef::lean::Cow;
macro_rules! test_file {
( $function:ident, $file:expr ) => {
@ -38,7 +37,7 @@ macro_rules! test_file {
let cover = Picture {
mime_type: MimeType::Jpeg,
data: Cow::owned(vec![0u8; 10]),
data: &vec![0u8; 10],
};
tags.set_album_cover(cover.clone());