2021-04-14 16:17:38 +00:00
|
|
|
#[allow(clippy::wildcard_imports)]
|
2021-04-21 16:56:35 +00:00
|
|
|
use crate::components::tags::*;
|
|
|
|
use crate::{Album, AnyTag, Picture, Result, TagType};
|
|
|
|
|
2021-05-16 03:43:31 +00:00
|
|
|
use std::fs::{File, OpenOptions};
|
2020-10-27 14:38:31 +00:00
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Combination of [`AudioTagEdit`], [`AudioTagWrite`], and [`ToAnyTag`]
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait AudioTag: AudioTagEdit + AudioTagWrite + ToAnyTag {}
|
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 {
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the track title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn title(&self) -> Option<&str>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the track title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn set_title(&mut self, title: &str);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the track title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_title(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the artist(s) as a string
|
2021-04-18 19:32:59 +00:00
|
|
|
fn artist_str(&self) -> Option<&str>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the artist string
|
2021-04-03 00:47:44 +00:00
|
|
|
fn set_artist(&mut self, artist: &str);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Splits the artist string into a `Vec`
|
2021-04-18 19:32:59 +00:00
|
|
|
fn artists_vec(&self) -> Option<Vec<&str>> {
|
|
|
|
self.artist_str().map(|a| a.split('/').collect())
|
|
|
|
}
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the artist string
|
2021-04-04 02:38:48 +00:00
|
|
|
fn remove_artist(&mut self);
|
2021-04-03 00:47:44 +00:00
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the track year
|
2021-04-14 16:17:38 +00:00
|
|
|
fn year(&self) -> Option<i32>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the track year
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_year(&mut self, year: i32);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the track year
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_year(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the track's [`Album`]
|
2021-04-04 02:38:48 +00:00
|
|
|
fn album(&self) -> Album<'_> {
|
|
|
|
Album {
|
|
|
|
title: self.album_title(),
|
2021-04-18 19:32:59 +00:00
|
|
|
artists: self.album_artists_vec(),
|
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
|
|
|
}
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the album title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn album_title(&self) -> Option<&str>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the album title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn set_album_title(&mut self, v: &str);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the album title
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_album_title(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the album artist string
|
2021-04-18 19:32:59 +00:00
|
|
|
fn album_artist_str(&self) -> Option<&str>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Splits the artist string into a `Vec`
|
2021-04-18 19:32:59 +00:00
|
|
|
fn album_artists_vec(&self) -> Option<Vec<&str>> {
|
|
|
|
self.album_artist_str().map(|a| a.split('/').collect())
|
|
|
|
}
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the album artist string
|
2021-04-18 19:32:59 +00:00
|
|
|
fn set_album_artist(&mut self, artist: &str);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the album artist string
|
2021-04-04 02:38:48 +00:00
|
|
|
fn remove_album_artists(&mut self);
|
2021-04-03 00:47:44 +00:00
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the album cover
|
2021-04-03 00:47:44 +00:00
|
|
|
fn album_cover(&self) -> Option<Picture>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the album cover
|
2021-04-03 00:47:44 +00:00
|
|
|
fn set_album_cover(&mut self, cover: Picture);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the album cover
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_album_cover(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the track number and total tracks
|
2021-04-14 16:17:38 +00:00
|
|
|
fn track(&self) -> (Option<u32>, Option<u32>) {
|
2021-04-03 00:47:44 +00:00
|
|
|
(self.track_number(), self.total_tracks())
|
|
|
|
}
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the track number
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_track(&mut self, track: u32) {
|
2021-04-03 00:47:44 +00:00
|
|
|
self.set_track_number(track);
|
|
|
|
}
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the track number and total tracks
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_track(&mut self) {
|
|
|
|
self.remove_track_number();
|
|
|
|
self.remove_total_tracks();
|
|
|
|
}
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the track number
|
2021-04-14 16:17:38 +00:00
|
|
|
fn track_number(&self) -> Option<u32>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the track number
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_track_number(&mut self, track_number: u32);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the track number
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_track_number(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the total tracks
|
2021-04-14 16:17:38 +00:00
|
|
|
fn total_tracks(&self) -> Option<u32>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the total tracks
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_total_tracks(&mut self, total_track: u32);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the total tracks
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_total_tracks(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the disc number and total discs
|
2021-04-14 16:17:38 +00:00
|
|
|
fn disc(&self) -> (Option<u32>, Option<u32>) {
|
2021-04-03 00:47:44 +00:00
|
|
|
(self.disc_number(), self.total_discs())
|
|
|
|
}
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the disc number and total discs
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_disc(&mut self) {
|
|
|
|
self.remove_disc_number();
|
|
|
|
self.remove_total_discs();
|
|
|
|
}
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the disc number
|
2021-04-14 16:17:38 +00:00
|
|
|
fn disc_number(&self) -> Option<u32>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the disc number
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_disc_number(&mut self, disc_number: u32);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the disc number
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_disc_number(&mut self);
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Returns the total discs
|
2021-04-14 16:17:38 +00:00
|
|
|
fn total_discs(&self) -> Option<u32>;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Sets the total discs
|
2021-04-14 16:17:38 +00:00
|
|
|
fn set_total_discs(&mut self, total_discs: u32);
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Removes the total discs
|
2021-04-03 00:47:44 +00:00
|
|
|
fn remove_total_discs(&mut self);
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Functions for writing to a file
|
2020-10-27 14:38:31 +00:00
|
|
|
pub trait AudioTagWrite {
|
2021-04-15 15:53:10 +00:00
|
|
|
/// Write tag to a [`File`][std::fs::File]
|
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
|
|
|
/// Will return `Err` if unable to write to the `File`
|
2021-04-14 15:14:08 +00:00
|
|
|
fn write_to(&self, file: &mut File) -> Result<()>;
|
2021-04-15 15:53:10 +00:00
|
|
|
/// Write tag to a path
|
|
|
|
///
|
|
|
|
/// # Errors
|
|
|
|
///
|
|
|
|
/// Will return `Err` if `path` doesn't exist
|
2021-05-16 03:43:31 +00:00
|
|
|
fn write_to_path(&self, path: &str) -> Result<()> {
|
|
|
|
self.write_to(&mut OpenOptions::new().read(true).write(true).open(path)?)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Conversions between tag types
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait ToAnyTag: ToAny {
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Converts the tag to [`AnyTag`]
|
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-15 17:26:06 +00:00
|
|
|
#[cfg(feature = "ape")]
|
|
|
|
TagType::Ape => Box::new(ApeTag::from(self.to_anytag())),
|
2021-04-21 18:22:52 +00:00
|
|
|
#[cfg(feature = "id3")]
|
2021-04-22 16:57:20 +00:00
|
|
|
TagType::Id3v2(_) => Box::new(Id3v2Tag::from(self.to_anytag())),
|
2021-04-07 00:57:30 +00:00
|
|
|
#[cfg(feature = "mp4")]
|
2021-04-03 00:47:44 +00:00
|
|
|
TagType::Mp4 => Box::new(Mp4Tag::from(self.to_anytag())),
|
2021-04-21 18:22:52 +00:00
|
|
|
#[cfg(any(feature = "vorbis", feature = "flac", feature = "opus"))]
|
2021-04-18 18:07:26 +00:00
|
|
|
TagType::Vorbis(_) => Box::new(VorbisTag::from(self.to_anytag())),
|
2021-04-21 18:22:52 +00:00
|
|
|
#[cfg(feature = "riff")]
|
2021-04-22 16:57:20 +00:00
|
|
|
TagType::RiffInfo => Box::new(RiffTag::from(self.to_anytag())),
|
2021-04-03 00:47:44 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-27 14:38:31 +00:00
|
|
|
}
|
2020-10-29 13:26:35 +00:00
|
|
|
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Tag conversion to `Any`
|
2020-10-29 18:01:21 +00:00
|
|
|
pub trait ToAny {
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Convert tag to `Any`
|
2021-04-03 00:47:44 +00:00
|
|
|
fn to_any(&self) -> &dyn std::any::Any;
|
2021-05-16 04:39:19 +00:00
|
|
|
/// Mutably convert tag to `Any`
|
2021-04-23 02:57:47 +00:00
|
|
|
#[allow(clippy::wrong_self_convention)]
|
2021-04-03 00:47:44 +00:00
|
|
|
fn to_any_mut(&mut self) -> &mut dyn std::any::Any;
|
|
|
|
}
|