mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 06:02:32 +00:00
v0.2.3
This commit is contained in:
parent
dfc8f4f395
commit
d2d1bedafa
9 changed files with 115 additions and 40 deletions
|
@ -1,4 +1,8 @@
|
|||
## [0.2.2] 2020-10-28
|
||||
## [0.2.3] 2020-10-27
|
||||
|
||||
- multiple artists
|
||||
|
||||
## [0.2.2] 2020-10-27
|
||||
|
||||
- Conversion between tag types without macro; removed the macro introduced in v0.2.0
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "audiotags"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
||||
edition = "2018"
|
||||
description = "Unified IO for different types of audio metadata"
|
||||
|
|
15
README.md
15
README.md
|
@ -87,13 +87,22 @@ fn main() {
|
|||
mp4tag.write_to_path(M4A_FILE).unwrap();
|
||||
|
||||
// reload the tag from the m4a file; this time specifying the tag type (you can also use `default()`)
|
||||
let mp4tag_reload = Tag::with_tag_type(TagType::Mp4)
|
||||
let mut mp4tag = Tag::with_tag_type(TagType::Mp4)
|
||||
.read_from_path(M4A_FILE)
|
||||
.unwrap();
|
||||
// the tag originated from an mp3 file is successfully written to an m4a file!
|
||||
assert_eq!(mp4tag_reload.title(), Some("title from mp3 file"));
|
||||
assert_eq!(mp4tag.title(), Some("title from mp3 file"));
|
||||
// multiple artists
|
||||
mp4tag.add_artist("artist1 of mp4");
|
||||
mp4tag.add_artist("artist2 of mp4");
|
||||
assert_eq!(
|
||||
mp4tag.artists(),
|
||||
Some(vec!["artist1 of mp4", "artist2 of mp4"])
|
||||
);
|
||||
// convert to id3 tag, which does not support multiple artists
|
||||
let mp3tag = mp4tag.into_tag(TagType::Id3v2);
|
||||
assert_eq!(mp3tag.artist(), Some("artist1 of mp4;artist2 of mp4"));
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Supported Formats
|
||||
|
|
|
@ -9,22 +9,26 @@ impl<'a> From<AnyTag<'a>> for FlacTag {
|
|||
fn from(inp: AnyTag<'a>) -> Self {
|
||||
let mut t = FlacTag::default();
|
||||
inp.title().map(|v| t.set_title(v));
|
||||
inp.artists().map(|i| {
|
||||
inp.artists()
|
||||
.map(|i| {
|
||||
i.iter().fold(String::new(), |mut v, a| {
|
||||
v.push_str(&a);
|
||||
v.push_str(SEP_ARTIST);
|
||||
v
|
||||
})
|
||||
});
|
||||
})
|
||||
.map(|v| t.set_artist(&v[..v.len() - 1]));
|
||||
inp.year.map(|v| t.set_year(v));
|
||||
inp.album_title().map(|v| t.set_album_title(v));
|
||||
inp.album_artists().map(|i| {
|
||||
inp.album_artists()
|
||||
.map(|i| {
|
||||
i.iter().fold(String::new(), |mut v, a| {
|
||||
v.push_str(&a);
|
||||
v.push_str(SEP_ARTIST);
|
||||
v
|
||||
})
|
||||
});
|
||||
})
|
||||
.map(|v| t.set_album_artist(&v[..v.len() - 1]));
|
||||
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));
|
||||
|
|
|
@ -64,22 +64,26 @@ impl<'a> From<AnyTag<'a>> for id3::Tag {
|
|||
fn from(inp: AnyTag<'a>) -> Self {
|
||||
let mut t = id3::Tag::new();
|
||||
inp.title().map(|v| t.set_title(v));
|
||||
inp.artists().map(|i| {
|
||||
inp.artists()
|
||||
.map(|i| {
|
||||
i.iter().fold(String::new(), |mut v, a| {
|
||||
v.push_str(&a);
|
||||
v.push_str(SEP_ARTIST);
|
||||
v
|
||||
})
|
||||
});
|
||||
})
|
||||
.map(|v| t.set_artist(&v[..v.len() - 1]));
|
||||
inp.year.map(|v| t.set_year(v));
|
||||
inp.album_title().map(|v| t.set_album(v));
|
||||
inp.album_artists().map(|i| {
|
||||
inp.album_artists()
|
||||
.map(|i| {
|
||||
i.iter().fold(String::new(), |mut v, a| {
|
||||
v.push_str(&a);
|
||||
v.push_str(SEP_ARTIST);
|
||||
v
|
||||
})
|
||||
});
|
||||
})
|
||||
.map(|v| t.set_album_artist(&v[..v.len() - 1]));
|
||||
inp.track_number().map(|v| t.set_track(v as u32));
|
||||
inp.total_tracks().map(|v| t.set_total_tracks(v as u32));
|
||||
inp.disc_number().map(|v| t.set_disc(v as u32));
|
||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -400,6 +400,13 @@ pub trait AudioTagIo {
|
|||
fn set_artist(&mut self, artist: &str);
|
||||
fn remove_artist(&mut self);
|
||||
|
||||
fn artists(&self) -> Option<Vec<&str>> {
|
||||
self.artist().map(|v| vec![v])
|
||||
}
|
||||
fn add_artist(&mut self, artist: &str) {
|
||||
self.set_artist(artist);
|
||||
}
|
||||
|
||||
fn year(&self) -> Option<i32>;
|
||||
fn set_year(&mut self, year: i32);
|
||||
fn remove_year(&mut self);
|
||||
|
@ -438,6 +445,13 @@ pub trait AudioTagIo {
|
|||
fn set_album_artist(&mut self, v: &str);
|
||||
fn remove_album_artist(&mut self);
|
||||
|
||||
fn album_artists(&self) -> Option<Vec<&str>> {
|
||||
self.artist().map(|v| vec![v])
|
||||
}
|
||||
fn add_album_artist(&mut self, artist: &str) {
|
||||
self.set_album_artist(artist);
|
||||
}
|
||||
|
||||
fn album_cover(&self) -> Option<Picture>;
|
||||
fn set_album_cover(&mut self, cover: Picture);
|
||||
fn remove_album_cover(&mut self);
|
||||
|
|
|
@ -117,6 +117,20 @@ impl AudioTagIo for Mp4Tag {
|
|||
fn set_artist(&mut self, artist: &str) {
|
||||
self.inner.set_artist(artist)
|
||||
}
|
||||
fn artists(&self) -> Option<Vec<&str>> {
|
||||
let v = self.inner.artists().fold(Vec::new(), |mut v, a| {
|
||||
v.push(a);
|
||||
v
|
||||
});
|
||||
if v.len() > 0 {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn add_artist(&mut self, v: &str) {
|
||||
self.inner.add_artist(v);
|
||||
}
|
||||
|
||||
fn year(&self) -> Option<i32> {
|
||||
self.inner.year().and_then(|x| str::parse(x).ok())
|
||||
|
@ -139,6 +153,21 @@ impl AudioTagIo for Mp4Tag {
|
|||
self.inner.set_album_artist(v)
|
||||
}
|
||||
|
||||
fn album_artists(&self) -> Option<Vec<&str>> {
|
||||
let v = self.inner.album_artists().fold(Vec::new(), |mut v, a| {
|
||||
v.push(a);
|
||||
v
|
||||
});
|
||||
if v.len() > 0 {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn add_album_artist(&mut self, v: &str) {
|
||||
self.inner.add_album_artist(v);
|
||||
}
|
||||
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
use mp4ameta::Data::*;
|
||||
self.inner.artwork().and_then(|data| match data {
|
||||
|
|
|
@ -14,9 +14,19 @@ fn test_convert_mp3_to_mp4() {
|
|||
mp4tag.write_to_path(M4A_FILE).unwrap();
|
||||
|
||||
// reload the tag from the m4a file; this time specifying the tag type (you can also use `default()`)
|
||||
let mp4tag_reload = Tag::with_tag_type(TagType::Mp4)
|
||||
let mut mp4tag = Tag::with_tag_type(TagType::Mp4)
|
||||
.read_from_path(M4A_FILE)
|
||||
.unwrap();
|
||||
// the tag originated from an mp3 file is successfully written to an m4a file!
|
||||
assert_eq!(mp4tag_reload.title(), Some("title from mp3 file"));
|
||||
assert_eq!(mp4tag.title(), Some("title from mp3 file"));
|
||||
// multiple artists
|
||||
mp4tag.add_artist("artist1 of mp4");
|
||||
mp4tag.add_artist("artist2 of mp4");
|
||||
assert_eq!(
|
||||
mp4tag.artists(),
|
||||
Some(vec!["artist1 of mp4", "artist2 of mp4"])
|
||||
);
|
||||
// convert to id3 tag, which does not support multiple artists
|
||||
let mp3tag = mp4tag.into_tag(TagType::Id3v2);
|
||||
assert_eq!(mp3tag.artist(), Some("artist1 of mp4;artist2 of mp4"));
|
||||
}
|
||||
|
|
19
tests/io.rs
19
tests/io.rs
|
@ -1,4 +1,5 @@
|
|||
use audiotags::{MimeType, Picture, Tag};
|
||||
use beef::lean::Cow;
|
||||
|
||||
macro_rules! test_file {
|
||||
( $function:ident, $file:expr ) => {
|
||||
|
@ -35,16 +36,16 @@ macro_rules! test_file {
|
|||
assert!(tags.album_artist().is_none());
|
||||
tags.remove_album_artist();
|
||||
|
||||
// let cover = Picture {
|
||||
// mime_type: MimeType::Jpeg,
|
||||
// data: vec![0u8; 10],
|
||||
// };
|
||||
let cover = Picture {
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: Cow::owned(vec![0u8; 10]),
|
||||
};
|
||||
|
||||
// tags.set_album_cover(cover.clone());
|
||||
// assert_eq!(tags.album_cover(), Some(cover));
|
||||
// tags.remove_album_cover();
|
||||
// assert!(tags.album_cover().is_none());
|
||||
// tags.remove_album_cover();
|
||||
tags.set_album_cover(cover.clone());
|
||||
assert_eq!(tags.album_cover(), Some(cover));
|
||||
tags.remove_album_cover();
|
||||
assert!(tags.album_cover().is_none());
|
||||
tags.remove_album_cover();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue