mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-11-10 06:34:18 +00:00
0.2.2
This commit is contained in:
parent
b4f2ae38ef
commit
bf71a050df
5 changed files with 33 additions and 77 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "audiotags"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
authors = ["Tianyi <ShiTianyi2001@outlook.com>"]
|
||||
edition = "2018"
|
||||
description = "Unified IO for different types of audio metadata"
|
||||
|
@ -12,7 +12,6 @@ repository = "https://github.com/TianyiShi2001/audiotags"
|
|||
[dependencies]
|
||||
id3 = "0.5.1"
|
||||
mp4ameta = "0.6"
|
||||
strum = {version = "0.19.5", features = ["derive"]}
|
||||
metaflac = "0.2"
|
||||
beef = "0.4.4"
|
||||
thiserror = "1.0.21"
|
||||
|
|
63
README.md
63
README.md
|
@ -64,7 +64,7 @@ fn main() {
|
|||
You can convert between different tag types:
|
||||
|
||||
```rust
|
||||
use audiotags::{convert, AudioTagIo, Mp4Tag, Tag, TagType};
|
||||
use audiotags::{Tag, TagType};
|
||||
|
||||
fn main() {
|
||||
// we have an mp3 and an m4a file
|
||||
|
@ -75,7 +75,7 @@ fn main() {
|
|||
// set the title
|
||||
mp3tag.set_title("title from mp3 file");
|
||||
// we can convert it to an mp4 tag and save it to an m4a file.
|
||||
let mut mp4tag = convert_tag!(mp3tag, Mp4Tag);
|
||||
let mut mp4tag = mp3tag.into_tag(TagType::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()`)
|
||||
|
@ -85,6 +85,7 @@ fn main() {
|
|||
// the tag originated from an mp3 file is successfully written to an m4a file!
|
||||
assert_eq!(mp4tag_reload.title(), Some("title from mp3 file"));
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Supported Formats
|
||||
|
@ -95,7 +96,7 @@ fn main() {
|
|||
| `m4a/mp4/...` | MPEG-4 audio metadata | [**mp4ameta**](https://github.com/Saecki/rust-mp4ameta) |
|
||||
| `flac` | Vorbis comment | [**metaflac**](https://github.com/jameshurst/rust-metaflac) |
|
||||
|
||||
## Supported Methods
|
||||
## Getters and Setters
|
||||
|
||||
```rust
|
||||
pub trait AudioTagIo {
|
||||
|
@ -108,68 +109,30 @@ pub trait AudioTagIo {
|
|||
fn year(&self) -> Option<i32>;
|
||||
fn set_year(&mut self, year: i32);
|
||||
fn remove_year(&mut self);
|
||||
fn album(&self) -> Option<Album> {
|
||||
self.album_title().map(|title| Album {
|
||||
title: title.to_owned(),
|
||||
artist: self.album_artist().map(|x| x.to_owned()),
|
||||
cover: self.album_cover(),
|
||||
})
|
||||
}
|
||||
fn remove_album(&mut self) {
|
||||
self.remove_album_title();
|
||||
self.remove_album_artist();
|
||||
self.remove_album_cover();
|
||||
}
|
||||
fn album(&self) -> Option<Album>;
|
||||
fn remove_album(&mut self);
|
||||
fn album_title(&self) -> Option<&str>;
|
||||
fn remove_album_title(&mut self);
|
||||
fn album_artist(&self) -> Option<&str>;
|
||||
fn remove_album_artist(&mut self);
|
||||
fn album_cover(&self) -> Option<Picture>;
|
||||
fn remove_album_cover(&mut self);
|
||||
fn set_album(&mut self, album: Album) {
|
||||
self.set_album_title(&album.title);
|
||||
if let Some(artist) = album.artist {
|
||||
self.set_album_artist(&artist)
|
||||
} else {
|
||||
self.remove_album_artist()
|
||||
}
|
||||
if let Some(pic) = album.cover {
|
||||
self.set_album_cover(pic)
|
||||
} else {
|
||||
self.remove_album_cover()
|
||||
}
|
||||
}
|
||||
fn set_album(&mut self, album: Album);
|
||||
fn set_album_title(&mut self, v: &str);
|
||||
fn set_album_artist(&mut self, v: &str);
|
||||
fn set_album_cover(&mut self, cover: Picture);
|
||||
fn track(&self) -> (Option<u16>, Option<u16>) {
|
||||
(self.track_number(), self.total_tracks())
|
||||
}
|
||||
fn set_track(&mut self, track: (u16, u16)) {
|
||||
self.set_track_number(track.0);
|
||||
self.set_total_tracks(track.1);
|
||||
}
|
||||
fn remove_track(&mut self) {
|
||||
self.remove_track_number();
|
||||
self.remove_total_tracks();
|
||||
}
|
||||
fn track(&self) -> (Option<u16>, Option<u16>);
|
||||
fn set_track(&mut self, track: (u16, u16));
|
||||
fn remove_track(&mut self);
|
||||
fn track_number(&self) -> Option<u16>;
|
||||
fn set_track_number(&mut self, track_number: u16);
|
||||
fn remove_track_number(&mut self);
|
||||
fn total_tracks(&self) -> Option<u16>;
|
||||
fn set_total_tracks(&mut self, total_track: u16);
|
||||
fn remove_total_tracks(&mut self);
|
||||
fn disc(&self) -> (Option<u16>, Option<u16>) {
|
||||
(self.disc_number(), self.total_discs())
|
||||
}
|
||||
fn set_disc(&mut self, disc: (u16, u16)) {
|
||||
self.set_disc_number(disc.0);
|
||||
self.set_total_discs(disc.1);
|
||||
}
|
||||
fn remove_disc(&mut self) {
|
||||
self.remove_disc_number();
|
||||
self.remove_total_discs();
|
||||
}
|
||||
fn disc(&self) -> (Option<u16>, Option<u16>);
|
||||
fn set_disc(&mut self, disc: (u16, u16));
|
||||
fn remove_disc(&mut self);
|
||||
fn disc_number(&self) -> Option<u16>;
|
||||
fn set_disc_number(&mut self, disc_number: u16);
|
||||
fn remove_disc_number(&mut self);
|
||||
|
|
33
src/lib.rs
33
src/lib.rs
|
@ -58,14 +58,6 @@ use beef::lean::Cow;
|
|||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! convert_tag {
|
||||
($tag:expr, $target:ty) => {{
|
||||
let target_tag: $target = $tag.into_anytag().into();
|
||||
target_tag
|
||||
}};
|
||||
}
|
||||
|
||||
type BoxedError = Box<dyn std::error::Error>;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -291,13 +283,6 @@ pub trait TagIo {
|
|||
// }
|
||||
// }
|
||||
|
||||
pub struct SuperTag<T>
|
||||
where
|
||||
T: AudioTagIo,
|
||||
{
|
||||
inner: T,
|
||||
}
|
||||
|
||||
/// Implementors of this trait are able to read and write audio metadata.
|
||||
///
|
||||
/// Constructor methods e.g. `from_file` should be implemented separately.
|
||||
|
@ -397,11 +382,23 @@ pub trait AudioTagIo {
|
|||
fn write_to_path(&mut self, path: &str) -> crate::Result<()>;
|
||||
|
||||
fn into_anytag(&self) -> AnyTag<'_>;
|
||||
|
||||
/// Convert the tag type, which can be lossy.
|
||||
fn into_tag(&self, tag_type: TagType) -> Box<dyn AudioTagIo> {
|
||||
match tag_type {
|
||||
TagType::Id3v2 => Box::new(Id3v2Tag::from(self.into_anytag())),
|
||||
TagType::Mp4 => Box::new(Mp4Tag::from(self.into_anytag())),
|
||||
TagType::Flac => Box::new(FlacTag::from(self.into_anytag())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoTag<'a>: AudioTagIo {
|
||||
fn into_tag<T: From<AnyTag<'a>>>(&self) -> T;
|
||||
}
|
||||
// pub trait IntoAnyTag {
|
||||
// fn into_anytag<'a>(&'a self) -> AnyTag<'a>;
|
||||
// fn into_tag<'a, T: From<AnyTag<'a>>>(&'a self) -> T {
|
||||
// self.into_anytag().into()
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub trait IntoTag: AudioTagIo {
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
//use strum::Display;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error types that could occur in this library.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
|
@ -16,9 +13,9 @@ pub enum Error {
|
|||
#[error(transparent)]
|
||||
IOError(#[from] std::io::Error),
|
||||
|
||||
#[error("")]
|
||||
#[error("Unsupported format: {0}")]
|
||||
UnsupportedFormat(String),
|
||||
#[error("")]
|
||||
#[error("Unsupported mime type: {0}")]
|
||||
UnsupportedMimeType(String),
|
||||
#[error("")]
|
||||
NotAPicture,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use audiotags::{convert_tag, AudioTagIo, Mp4Tag, Tag, TagType};
|
||||
use audiotags::{Tag, TagType};
|
||||
|
||||
#[test]
|
||||
fn test_convert_mp3_to_mp4() {
|
||||
|
@ -10,7 +10,7 @@ fn test_convert_mp3_to_mp4() {
|
|||
// set the title
|
||||
mp3tag.set_title("title from mp3 file");
|
||||
// we can convert it to an mp4 tag and save it to an m4a file.
|
||||
let mut mp4tag = convert_tag!(mp3tag, Mp4Tag);
|
||||
let mut mp4tag = mp3tag.into_tag(TagType::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()`)
|
||||
|
|
Loading…
Reference in a new issue