mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-12 13:42:34 +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
|
- Conversion between tag types without macro; removed the macro introduced in v0.2.0
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "audiotags"
|
name = "audiotags"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Unified IO for different types of audio metadata"
|
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();
|
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()`)
|
// 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)
|
.read_from_path(M4A_FILE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// the tag originated from an mp3 file is successfully written to an m4a file!
|
// 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
|
## Supported Formats
|
||||||
|
|
|
@ -9,22 +9,26 @@ impl<'a> From<AnyTag<'a>> for FlacTag {
|
||||||
fn from(inp: AnyTag<'a>) -> Self {
|
fn from(inp: AnyTag<'a>) -> Self {
|
||||||
let mut t = FlacTag::default();
|
let mut t = FlacTag::default();
|
||||||
inp.title().map(|v| t.set_title(v));
|
inp.title().map(|v| t.set_title(v));
|
||||||
inp.artists().map(|i| {
|
inp.artists()
|
||||||
i.iter().fold(String::new(), |mut v, a| {
|
.map(|i| {
|
||||||
v.push_str(&a);
|
i.iter().fold(String::new(), |mut v, a| {
|
||||||
v.push_str(SEP_ARTIST);
|
v.push_str(&a);
|
||||||
v
|
v.push_str(SEP_ARTIST);
|
||||||
|
v
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
.map(|v| t.set_artist(&v[..v.len() - 1]));
|
||||||
inp.year.map(|v| t.set_year(v));
|
inp.year.map(|v| t.set_year(v));
|
||||||
inp.album_title().map(|v| t.set_album_title(v));
|
inp.album_title().map(|v| t.set_album_title(v));
|
||||||
inp.album_artists().map(|i| {
|
inp.album_artists()
|
||||||
i.iter().fold(String::new(), |mut v, a| {
|
.map(|i| {
|
||||||
v.push_str(&a);
|
i.iter().fold(String::new(), |mut v, a| {
|
||||||
v.push_str(SEP_ARTIST);
|
v.push_str(&a);
|
||||||
v
|
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.track_number().map(|v| t.set_track_number(v));
|
||||||
inp.total_tracks().map(|v| t.set_total_tracks(v));
|
inp.total_tracks().map(|v| t.set_total_tracks(v));
|
||||||
inp.disc_number().map(|v| t.set_disc_number(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 {
|
fn from(inp: AnyTag<'a>) -> Self {
|
||||||
let mut t = id3::Tag::new();
|
let mut t = id3::Tag::new();
|
||||||
inp.title().map(|v| t.set_title(v));
|
inp.title().map(|v| t.set_title(v));
|
||||||
inp.artists().map(|i| {
|
inp.artists()
|
||||||
i.iter().fold(String::new(), |mut v, a| {
|
.map(|i| {
|
||||||
v.push_str(&a);
|
i.iter().fold(String::new(), |mut v, a| {
|
||||||
v.push_str(SEP_ARTIST);
|
v.push_str(&a);
|
||||||
v
|
v.push_str(SEP_ARTIST);
|
||||||
|
v
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
.map(|v| t.set_artist(&v[..v.len() - 1]));
|
||||||
inp.year.map(|v| t.set_year(v));
|
inp.year.map(|v| t.set_year(v));
|
||||||
inp.album_title().map(|v| t.set_album(v));
|
inp.album_title().map(|v| t.set_album(v));
|
||||||
inp.album_artists().map(|i| {
|
inp.album_artists()
|
||||||
i.iter().fold(String::new(), |mut v, a| {
|
.map(|i| {
|
||||||
v.push_str(&a);
|
i.iter().fold(String::new(), |mut v, a| {
|
||||||
v.push_str(SEP_ARTIST);
|
v.push_str(&a);
|
||||||
v
|
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.track_number().map(|v| t.set_track(v as u32));
|
||||||
inp.total_tracks().map(|v| t.set_total_tracks(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));
|
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 set_artist(&mut self, artist: &str);
|
||||||
fn remove_artist(&mut self);
|
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 year(&self) -> Option<i32>;
|
||||||
fn set_year(&mut self, year: i32);
|
fn set_year(&mut self, year: i32);
|
||||||
fn remove_year(&mut self);
|
fn remove_year(&mut self);
|
||||||
|
@ -438,6 +445,13 @@ pub trait AudioTagIo {
|
||||||
fn set_album_artist(&mut self, v: &str);
|
fn set_album_artist(&mut self, v: &str);
|
||||||
fn remove_album_artist(&mut self);
|
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 album_cover(&self) -> Option<Picture>;
|
||||||
fn set_album_cover(&mut self, cover: Picture);
|
fn set_album_cover(&mut self, cover: Picture);
|
||||||
fn remove_album_cover(&mut self);
|
fn remove_album_cover(&mut self);
|
||||||
|
|
|
@ -117,6 +117,20 @@ impl AudioTagIo for Mp4Tag {
|
||||||
fn set_artist(&mut self, artist: &str) {
|
fn set_artist(&mut self, artist: &str) {
|
||||||
self.inner.set_artist(artist)
|
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> {
|
fn year(&self) -> Option<i32> {
|
||||||
self.inner.year().and_then(|x| str::parse(x).ok())
|
self.inner.year().and_then(|x| str::parse(x).ok())
|
||||||
|
@ -139,6 +153,21 @@ impl AudioTagIo for Mp4Tag {
|
||||||
self.inner.set_album_artist(v)
|
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> {
|
fn album_cover(&self) -> Option<Picture> {
|
||||||
use mp4ameta::Data::*;
|
use mp4ameta::Data::*;
|
||||||
self.inner.artwork().and_then(|data| match 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();
|
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()`)
|
// 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)
|
.read_from_path(M4A_FILE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// the tag originated from an mp3 file is successfully written to an m4a file!
|
// 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 audiotags::{MimeType, Picture, Tag};
|
||||||
|
use beef::lean::Cow;
|
||||||
|
|
||||||
macro_rules! test_file {
|
macro_rules! test_file {
|
||||||
( $function:ident, $file:expr ) => {
|
( $function:ident, $file:expr ) => {
|
||||||
|
@ -35,16 +36,16 @@ macro_rules! test_file {
|
||||||
assert!(tags.album_artist().is_none());
|
assert!(tags.album_artist().is_none());
|
||||||
tags.remove_album_artist();
|
tags.remove_album_artist();
|
||||||
|
|
||||||
// let cover = Picture {
|
let cover = Picture {
|
||||||
// mime_type: MimeType::Jpeg,
|
mime_type: MimeType::Jpeg,
|
||||||
// data: vec![0u8; 10],
|
data: Cow::owned(vec![0u8; 10]),
|
||||||
// };
|
};
|
||||||
|
|
||||||
// tags.set_album_cover(cover.clone());
|
tags.set_album_cover(cover.clone());
|
||||||
// assert_eq!(tags.album_cover(), Some(cover));
|
assert_eq!(tags.album_cover(), Some(cover));
|
||||||
// tags.remove_album_cover();
|
tags.remove_album_cover();
|
||||||
// assert!(tags.album_cover().is_none());
|
assert!(tags.album_cover().is_none());
|
||||||
// tags.remove_album_cover();
|
tags.remove_album_cover();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue