2021-04-14 03:29:13 +00:00
|
|
|
use crate::{components::tags::*, Album, AnyTag, Picture, Result, TagType};
|
2021-04-07 00:57:30 +00:00
|
|
|
use std::fs::File;
|
2020-10-27 14:38:31 +00:00
|
|
|
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait AudioTag: AudioTagEdit + AudioTagWrite + ToAnyTag {}
|
2020-10-27 14:38:31 +00:00
|
|
|
|
|
|
|
// pub trait TagIo {
|
2021-04-03 18:31:13 +00:00
|
|
|
// fn read_from_path(path: &str) -> Result<AnyTag>;
|
|
|
|
// fn write_to_path(path: &str) -> Result<()>;
|
2020-10-27 14:38:31 +00:00
|
|
|
// }
|
|
|
|
|
|
|
|
/// Implementors of this trait are able to read and write audio metadata.
|
|
|
|
///
|
|
|
|
/// Constructor methods e.g. `from_file` should be implemented separately.
|
2021-04-03 00:47:44 +00:00
|
|
|
pub trait AudioTagEdit {
|
|
|
|
fn title(&self) -> Option<&str>;
|
|
|
|
fn set_title(&mut self, title: &str);
|
|
|
|
fn remove_title(&mut self);
|
|
|
|
|
|
|
|
fn artist(&self) -> Option<&str>;
|
|
|
|
fn set_artist(&mut self, artist: &str);
|
2021-04-04 02:38:48 +00:00
|
|
|
fn add_artist(&mut self, artist: &str);
|
2021-04-03 00:47:44 +00:00
|
|
|
|
2021-04-04 02:38:48 +00:00
|
|
|
fn artists(&self) -> Option<Vec<&str>>;
|
|
|
|
fn remove_artist(&mut self);
|
2021-04-03 00:47:44 +00:00
|
|
|
|
|
|
|
fn year(&self) -> Option<u16>;
|
|
|
|
fn set_year(&mut self, year: u16);
|
|
|
|
fn remove_year(&mut self);
|
|
|
|
|
2021-04-04 02:38:48 +00:00
|
|
|
fn album(&self) -> Album<'_> {
|
|
|
|
Album {
|
|
|
|
title: self.album_title(),
|
|
|
|
artists: self.album_artists(),
|
2021-04-03 00:47:44 +00:00
|
|
|
cover: self.album_cover(),
|
2021-04-04 02:38:48 +00:00
|
|
|
}
|
2021-04-03 00:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn album_title(&self) -> Option<&str>;
|
|
|
|
fn set_album_title(&mut self, v: &str);
|
|
|
|
fn remove_album_title(&mut self);
|
|
|
|
|
2021-04-04 02:38:48 +00:00
|
|
|
fn album_artists(&self) -> Option<Vec<&str>>;
|
|
|
|
fn set_album_artists(&mut self, artists: String);
|
|
|
|
fn add_album_artist(&mut self, artist: &str);
|
|
|
|
fn remove_album_artists(&mut self);
|
2021-04-03 00:47:44 +00:00
|
|
|
|
|
|
|
fn album_cover(&self) -> Option<Picture>;
|
|
|
|
fn set_album_cover(&mut self, cover: Picture);
|
|
|
|
fn remove_album_cover(&mut self);
|
|
|
|
|
|
|
|
fn track(&self) -> (Option<u16>, Option<u16>) {
|
|
|
|
(self.track_number(), self.total_tracks())
|
|
|
|
}
|
|
|
|
fn set_track(&mut self, track: u16) {
|
|
|
|
self.set_track_number(track);
|
|
|
|
}
|
|
|
|
fn remove_track(&mut self) {
|
|
|
|
self.remove_track_number();
|
|
|
|
self.remove_total_tracks();
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
self.set_disc_number(disc);
|
|
|
|
}
|
|
|
|
fn remove_disc(&mut self) {
|
|
|
|
self.remove_disc_number();
|
|
|
|
self.remove_total_discs();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn disc_number(&self) -> Option<u16>;
|
|
|
|
fn set_disc_number(&mut self, disc_number: u16);
|
|
|
|
fn remove_disc_number(&mut self);
|
|
|
|
|
|
|
|
fn total_discs(&self) -> Option<u16>;
|
|
|
|
fn set_total_discs(&mut self, total_discs: u16);
|
|
|
|
fn remove_total_discs(&mut self);
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AudioTagWrite {
|
2021-04-03 18:31:13 +00:00
|
|
|
fn write_to(&mut self, file: &mut File) -> Result<()>;
|
2021-04-03 00:47:44 +00:00
|
|
|
// cannot use impl AsRef<Path>
|
2021-04-03 18:31:13 +00:00
|
|
|
fn write_to_path(&mut self, path: &str) -> Result<()>;
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
|
|
|
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait ToAnyTag: ToAny {
|
2021-04-03 00:47:44 +00:00
|
|
|
fn to_anytag(&self) -> AnyTag<'_>;
|
|
|
|
|
|
|
|
/// Convert the tag type, which can be lossy.
|
|
|
|
fn to_dyn_tag(&self, tag_type: TagType) -> Box<dyn AudioTag> {
|
|
|
|
// TODO: write a macro or something that implement this method for every tag type so that if the
|
|
|
|
// TODO: target type is the same, just return self
|
|
|
|
match tag_type {
|
2021-04-07 00:57:30 +00:00
|
|
|
#[cfg(feature = "mp3")]
|
2021-04-03 00:47:44 +00:00
|
|
|
TagType::Id3v2 => Box::new(Id3v2Tag::from(self.to_anytag())),
|
2021-04-07 00:57:30 +00:00
|
|
|
#[cfg(feature = "vorbis")]
|
|
|
|
TagType::Ogg => Box::new(VorbisTag::from(self.to_anytag())),
|
|
|
|
#[cfg(feature = "vorbis")]
|
|
|
|
TagType::Opus => Box::new(VorbisTag::from(self.to_anytag())),
|
|
|
|
#[cfg(feature = "vorbis")]
|
|
|
|
TagType::Flac => Box::new(VorbisTag::from(self.to_anytag())),
|
|
|
|
#[cfg(feature = "mp4")]
|
2021-04-03 00:47:44 +00:00
|
|
|
TagType::Mp4 => Box::new(Mp4Tag::from(self.to_anytag())),
|
|
|
|
}
|
|
|
|
}
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
2020-10-29 13:26:35 +00:00
|
|
|
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait ToAny {
|
2021-04-03 00:47:44 +00:00
|
|
|
fn to_any(&self) -> &dyn std::any::Any;
|
|
|
|
fn to_any_mut(&mut self) -> &mut dyn std::any::Any;
|
|
|
|
}
|
|
|
|
|
2021-04-07 00:57:30 +00:00
|
|
|
pub trait ReadPath {
|
2021-04-07 02:33:39 +00:00
|
|
|
fn from_path<P>(path: P, _tag_type: Option<TagType>) -> Result<Self>
|
|
|
|
where
|
|
|
|
P: AsRef<std::path::Path>,
|
|
|
|
Self: Sized;
|
|
|
|
}
|