mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2025-03-04 06:47:12 +00:00
Start work to support back covers
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
79cbbd5339
commit
29ff3d8030
11 changed files with 300 additions and 93 deletions
|
@ -22,7 +22,7 @@ mp3-duration = {version = "0.1.10", optional = true} # Duration
|
|||
lewton = {version = "0.10.2", optional = true} # Decoding
|
||||
ogg = {version = "0.8.0", optional = true} # Encoding
|
||||
# Mp4
|
||||
mp4ameta = {version = "0.9.1", optional = true}
|
||||
mp4ameta = {version = "0.10.2", optional = true}
|
||||
# Flac
|
||||
metaflac = {version = "0.2.4", optional = true}
|
||||
# Opus
|
||||
|
|
|
@ -11,6 +11,7 @@ use ape::Item;
|
|||
use filepath::FilePath;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "duration")]
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -143,21 +144,42 @@ impl AudioTagEdit for ApeTag {
|
|||
self.remove_key("Album artist")
|
||||
}
|
||||
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
if let Some(val) = self.inner.item("Cover Art (Front)") {
|
||||
return get_picture(val);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
fn set_album_cover(&mut self, cover: Picture) {
|
||||
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
// TODO
|
||||
self.set_value("Cover Art (Front)", "TODO")
|
||||
}
|
||||
fn remove_album_cover(&mut self) {
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
self.remove_key("Cover Art (Front)")
|
||||
}
|
||||
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
if let Some(val) = self.inner.item("Cover Art (Back)") {
|
||||
return get_picture(val);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn remove_back_cover(&mut self) {
|
||||
self.remove_key("Cover Art (Back)")
|
||||
}
|
||||
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Track number and total tracks are stored together as num/total?
|
||||
fn track_number(&self) -> Option<u32> {
|
||||
let numbers = self.get_value("Track");
|
||||
|
|
|
@ -14,6 +14,7 @@ use std::convert::TryInto;
|
|||
use std::fs::File;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "duration")]
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -46,9 +47,9 @@ impl Id3v2Tag {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<id3::frame::Picture> for Picture {
|
||||
impl std::convert::TryFrom<&id3::frame::Picture> for Picture {
|
||||
type Error = Error;
|
||||
fn try_from(inp: id3::frame::Picture) -> Result<Self> {
|
||||
fn try_from(inp: &id3::frame::Picture) -> Result<Self> {
|
||||
let id3::frame::Picture {
|
||||
ref mime_type,
|
||||
data,
|
||||
|
@ -61,7 +62,19 @@ impl std::convert::TryFrom<id3::frame::Picture> for Picture {
|
|||
Ok(Self {
|
||||
pic_type,
|
||||
mime_type,
|
||||
data,
|
||||
data: data.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<Picture> for id3::frame::Picture {
|
||||
type Error = Error;
|
||||
fn try_from(inp: Picture) -> Result<Self> {
|
||||
Ok(Self {
|
||||
mime_type: String::from(inp.mime_type),
|
||||
picture_type: inp.pic_type.into(),
|
||||
description: "".to_string(),
|
||||
data: inp.data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +169,7 @@ impl AudioTagEdit for Id3v2Tag {
|
|||
self.inner.remove_album_artist()
|
||||
}
|
||||
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
self.inner
|
||||
.pictures()
|
||||
.find(|&pic| matches!(pic.picture_type, id3::frame::PictureType::CoverFront))
|
||||
|
@ -168,20 +181,65 @@ impl AudioTagEdit for Id3v2Tag {
|
|||
})
|
||||
})
|
||||
}
|
||||
fn set_album_cover(&mut self, cover: Picture) {
|
||||
self.remove_album_cover();
|
||||
self.inner.add_picture(id3::frame::Picture {
|
||||
mime_type: String::from(cover.mime_type),
|
||||
picture_type: id3::frame::PictureType::CoverFront,
|
||||
description: "".to_owned(),
|
||||
data: cover.data,
|
||||
});
|
||||
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
self.remove_front_cover();
|
||||
|
||||
if let Ok(pic) = cover.try_into() {
|
||||
self.inner.add_picture(pic)
|
||||
}
|
||||
}
|
||||
fn remove_album_cover(&mut self) {
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
self.inner
|
||||
.remove_picture_by_type(id3::frame::PictureType::CoverFront);
|
||||
}
|
||||
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
self.inner
|
||||
.pictures()
|
||||
.find(|&pic| matches!(pic.picture_type, id3::frame::PictureType::CoverBack))
|
||||
.and_then(|pic| {
|
||||
Some(Picture {
|
||||
pic_type: PictureType::CoverBack,
|
||||
data: pic.data.clone(),
|
||||
mime_type: (pic.mime_type.as_str()).try_into().ok()?,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
self.remove_back_cover();
|
||||
|
||||
if let Ok(pic) = cover.try_into() {
|
||||
self.inner.add_picture(pic)
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_back_cover(&mut self) {
|
||||
self.inner
|
||||
.remove_picture_by_type(id3::frame::PictureType::CoverBack);
|
||||
}
|
||||
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
let mut pictures = self.inner.pictures().peekable();
|
||||
|
||||
if pictures.peek().is_some() {
|
||||
let mut collection = Vec::new();
|
||||
|
||||
for pic in pictures {
|
||||
match TryInto::<Picture>::try_into(pic) {
|
||||
Ok(p) => collection.push(p),
|
||||
Err(_) => return None,
|
||||
}
|
||||
}
|
||||
|
||||
return Some(collection);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn track_number(&self) -> Option<u32> {
|
||||
self.inner.track()
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
Result, TagType, ToAny, ToAnyTag,
|
||||
};
|
||||
|
||||
pub use mp4ameta::{FourCC, Tag as Mp4InnerTag};
|
||||
pub use mp4ameta::{Fourcc, Tag as Mp4InnerTag};
|
||||
|
||||
use crate::types::picture::PictureType;
|
||||
use std::fs::File;
|
||||
|
@ -44,6 +44,11 @@ impl std::convert::TryFrom<mp4ameta::Data> for Picture {
|
|||
data,
|
||||
mime_type: MimeType::Jpeg,
|
||||
},
|
||||
mp4ameta::Data::Bmp(data) => Self {
|
||||
pic_type: PictureType::CoverFront,
|
||||
mime_type: MimeType::Bmp,
|
||||
data,
|
||||
},
|
||||
_ => return Err(Error::NotAPicture),
|
||||
})
|
||||
}
|
||||
|
@ -103,35 +108,59 @@ impl AudioTagEdit for Mp4Tag {
|
|||
fn remove_album_artists(&mut self) {
|
||||
self.inner.remove_album_artists();
|
||||
}
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
use mp4ameta::Data::{Jpeg, Png};
|
||||
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
self.inner.artwork().and_then(|data| match data {
|
||||
Jpeg(d) => Some(Picture {
|
||||
mp4ameta::Data::Jpeg(d) => Some(Picture {
|
||||
pic_type: PictureType::CoverFront, // TODO
|
||||
data: d.clone(),
|
||||
mime_type: MimeType::Jpeg,
|
||||
}),
|
||||
Png(d) => Some(Picture {
|
||||
mp4ameta::Data::Png(d) => Some(Picture {
|
||||
pic_type: PictureType::CoverFront, // TODO
|
||||
data: d.clone(),
|
||||
mime_type: MimeType::Png,
|
||||
}),
|
||||
mp4ameta::Data::Bmp(d) => Some(Picture {
|
||||
pic_type: PictureType::CoverFront, // TODO
|
||||
data: d.clone(),
|
||||
mime_type: MimeType::Bmp,
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_album_cover(&mut self, cover: Picture) {
|
||||
self.remove_album_cover();
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
self.remove_front_cover();
|
||||
|
||||
self.inner.add_artwork(match cover.mime_type {
|
||||
MimeType::Png => mp4ameta::Data::Png(cover.data),
|
||||
MimeType::Jpeg => mp4ameta::Data::Jpeg(cover.data),
|
||||
_ => panic!("Only png and jpeg are supported in m4a"),
|
||||
MimeType::Bmp => mp4ameta::Data::Bmp(cover.data),
|
||||
_ => panic!("Attempt to add an invalid image format to MP4"),
|
||||
});
|
||||
}
|
||||
fn remove_album_cover(&mut self) {
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
self.inner.remove_artwork();
|
||||
}
|
||||
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn remove_back_cover(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn remove_track(&mut self) {
|
||||
self.inner.remove_track(); // faster than removing separately
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::collections::HashMap;
|
|||
use std::fs::File;
|
||||
use std::io::{Cursor, Seek, SeekFrom, Write};
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "duration")]
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -143,15 +144,31 @@ impl AudioTagEdit for RiffTag {
|
|||
}
|
||||
|
||||
/// This will always return `None`, as this is non-standard
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
None
|
||||
}
|
||||
|
||||
/// This will not do anything, as this is non-standard
|
||||
fn set_album_cover(&mut self, _cover: Picture) {}
|
||||
fn set_front_cover(&mut self, _cover: Picture) {}
|
||||
|
||||
/// This will not do anything, as this is non-standard
|
||||
fn remove_album_cover(&mut self) {}
|
||||
fn remove_front_cover(&mut self) {}
|
||||
|
||||
/// This will always return `None`, as this is non-standard
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
None
|
||||
}
|
||||
|
||||
/// This will not do anything, as this is non-standard
|
||||
fn set_back_cover(&mut self, _cover: Picture) {}
|
||||
|
||||
/// This will not do anything, as this is non-standard
|
||||
fn remove_back_cover(&mut self) {}
|
||||
|
||||
/// This will always return `None`, as this is non-standard
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn track_number(&self) -> Option<u32> {
|
||||
if let Some(Ok(y)) = self.get_value("TrackNumber").map(str::parse::<u32>) {
|
||||
|
|
|
@ -359,50 +359,42 @@ impl AudioTagEdit for VorbisTag {
|
|||
self.inner.remove_key("ALBUMARTIST");
|
||||
}
|
||||
|
||||
fn album_cover(&self) -> Option<Picture> {
|
||||
match &self.inner.pictures {
|
||||
None => None,
|
||||
Some(pictures) => {
|
||||
for pic in pictures {
|
||||
if pic.pic_type == PictureType::CoverFront {
|
||||
return Some(pic.clone());
|
||||
}
|
||||
}
|
||||
fn front_cover(&self) -> Option<Picture> {
|
||||
get_cover(PictureType::CoverFront, &self.inner.pictures)
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
self.remove_front_cover();
|
||||
|
||||
let pictures = create_cover(cover, self.inner.pictures.clone());
|
||||
self.inner.pictures = pictures
|
||||
}
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
if let Some(mut p) = self.inner.pictures.clone() {
|
||||
p.retain(|pic| Some(pic) != self.front_cover().as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn set_album_cover(&mut self, cover: Picture) {
|
||||
self.remove_album_cover();
|
||||
let mime = String::from(cover.mime_type);
|
||||
let mime_len = (mime.len() as u32).to_le_bytes();
|
||||
fn back_cover(&self) -> Option<Picture> {
|
||||
get_cover(PictureType::CoverBack, &self.inner.pictures)
|
||||
}
|
||||
|
||||
let picture_type = 3_u32.to_le_bytes();
|
||||
let data = cover.data;
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
self.remove_front_cover();
|
||||
|
||||
let mut encoded = Vec::new();
|
||||
encoded.extend(picture_type.iter());
|
||||
encoded.extend(mime_len.iter());
|
||||
encoded.extend(mime.as_bytes().iter());
|
||||
encoded.extend(data.iter());
|
||||
let pictures = create_cover(cover, self.inner.pictures.clone());
|
||||
self.inner.pictures = pictures
|
||||
}
|
||||
|
||||
let encoded = base64::encode(encoded);
|
||||
|
||||
if let Ok(Some(pic)) = picture_from_data(&*encoded) {
|
||||
if let Some(mut pictures) = self.inner.pictures.clone() {
|
||||
pictures.retain(|p| p.pic_type != PictureType::CoverFront);
|
||||
pictures.push(pic);
|
||||
self.inner.pictures = Some(pictures)
|
||||
} else {
|
||||
self.inner.pictures = Some(vec![pic])
|
||||
}
|
||||
fn remove_back_cover(&mut self) {
|
||||
if let Some(mut p) = self.inner.pictures.clone() {
|
||||
p.retain(|pic| Some(pic) != self.back_cover().as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_album_cover(&mut self) {
|
||||
self.inner.remove_key("METADATA_BLOCK_PICTURE")
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
self.inner.pictures.clone()
|
||||
}
|
||||
|
||||
fn track_number(&self) -> Option<u32> {
|
||||
|
@ -464,6 +456,54 @@ impl AudioTagEdit for VorbisTag {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_cover(p_type: PictureType, pictures: &Option<Vec<Picture>>) -> Option<Picture> {
|
||||
match pictures {
|
||||
None => None,
|
||||
Some(pictures) => {
|
||||
for pic in pictures {
|
||||
if pic.pic_type == p_type {
|
||||
return Some(pic.clone());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cover(cover: Picture, pictures: Option<Vec<Picture>>) -> Option<Vec<Picture>> {
|
||||
let mime = String::from(cover.mime_type);
|
||||
let mime_len = (mime.len() as u32).to_le_bytes();
|
||||
|
||||
let picture_type = match cover.pic_type {
|
||||
PictureType::CoverFront => 3_u32.to_le_bytes(),
|
||||
PictureType::CoverBack => 4_u32.to_le_bytes(),
|
||||
PictureType::Other => unreachable!(),
|
||||
};
|
||||
|
||||
let data = cover.data;
|
||||
|
||||
let mut encoded = Vec::new();
|
||||
encoded.extend(picture_type.iter());
|
||||
encoded.extend(mime_len.iter());
|
||||
encoded.extend(mime.as_bytes().iter());
|
||||
encoded.extend(data.iter());
|
||||
|
||||
let encoded = base64::encode(encoded);
|
||||
|
||||
if let Ok(Some(pic)) = picture_from_data(&*encoded) {
|
||||
if let Some(mut pictures) = pictures {
|
||||
pictures.retain(|p| p.pic_type != PictureType::CoverBack);
|
||||
pictures.push(pic);
|
||||
Some(pictures)
|
||||
} else {
|
||||
Some(vec![pic])
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioTagWrite for VorbisTag {
|
||||
fn write_to(&self, file: &mut File) -> Result<()> {
|
||||
if let Some(format) = self.inner.format.clone() {
|
||||
|
|
|
@ -73,7 +73,7 @@ macro_rules! impl_tag {
|
|||
album: Album::new(
|
||||
inp.album_title(),
|
||||
inp.album_artists_vec(),
|
||||
inp.album_cover(),
|
||||
inp.album_covers(),
|
||||
),
|
||||
track_number: inp.track_number(),
|
||||
total_tracks: inp.total_tracks(),
|
||||
|
|
|
@ -57,7 +57,7 @@ pub trait AudioTagEdit {
|
|||
Album {
|
||||
title: self.album_title(),
|
||||
artists: self.album_artists_vec(),
|
||||
cover: self.album_cover(),
|
||||
covers: self.album_covers(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,12 +79,32 @@ pub trait AudioTagEdit {
|
|||
/// Removes the album artist string
|
||||
fn remove_album_artists(&mut self);
|
||||
|
||||
/// Returns the album cover
|
||||
fn album_cover(&self) -> Option<Picture>;
|
||||
/// Sets the album cover
|
||||
fn set_album_cover(&mut self, cover: Picture);
|
||||
/// Removes the album cover
|
||||
fn remove_album_cover(&mut self);
|
||||
/// Returns the front and back album covers
|
||||
fn album_covers(&self) -> (Option<Picture>, Option<Picture>) {
|
||||
(self.front_cover(), self.back_cover())
|
||||
}
|
||||
/// Removes both album covers
|
||||
fn remove_album_covers(&mut self) {
|
||||
self.remove_front_cover();
|
||||
self.remove_back_cover();
|
||||
}
|
||||
|
||||
/// Returns the front cover
|
||||
fn front_cover(&self) -> Option<Picture>;
|
||||
/// Sets the front cover
|
||||
fn set_front_cover(&mut self, cover: Picture);
|
||||
/// Removes the front cover
|
||||
fn remove_front_cover(&mut self);
|
||||
|
||||
/// Returns the front cover
|
||||
fn back_cover(&self) -> Option<Picture>;
|
||||
/// Sets the front cover
|
||||
fn set_back_cover(&mut self, cover: Picture);
|
||||
/// Removes the front cover
|
||||
fn remove_back_cover(&mut self);
|
||||
|
||||
/// Returns an `Iterator` over all pictures stored in the track
|
||||
fn pictures(&self) -> Option<Vec<Picture>>;
|
||||
|
||||
/// Returns the track number and total tracks
|
||||
fn track(&self) -> (Option<u32>, Option<u32>) {
|
||||
|
|
|
@ -8,8 +8,7 @@ pub struct Album<'a> {
|
|||
/// A `Vec` of the album artists
|
||||
pub artists: Option<Vec<&'a str>>,
|
||||
/// The album's front cover
|
||||
// TODO: also store the back cover
|
||||
pub cover: Option<Picture>,
|
||||
pub covers: (Option<Picture>, Option<Picture>),
|
||||
}
|
||||
|
||||
impl<'a> Default for Album<'a> {
|
||||
|
@ -17,7 +16,7 @@ impl<'a> Default for Album<'a> {
|
|||
Self {
|
||||
title: None,
|
||||
artists: None,
|
||||
cover: None,
|
||||
covers: (None, None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +26,12 @@ impl<'a> Album<'a> {
|
|||
pub fn new(
|
||||
title: Option<&'a str>,
|
||||
artists: Option<Vec<&'a str>>,
|
||||
cover: Option<Picture>,
|
||||
covers: (Option<Picture>, Option<Picture>),
|
||||
) -> Self {
|
||||
Self {
|
||||
title,
|
||||
artists,
|
||||
cover,
|
||||
covers,
|
||||
}
|
||||
}
|
||||
/// Create a new album with the specified title
|
||||
|
@ -40,7 +39,7 @@ impl<'a> Album<'a> {
|
|||
Self {
|
||||
title: Some(title),
|
||||
artists: None,
|
||||
cover: None,
|
||||
covers: (None, None),
|
||||
}
|
||||
}
|
||||
/// Set the album artists
|
||||
|
@ -60,12 +59,12 @@ impl<'a> Album<'a> {
|
|||
self.artists = None
|
||||
}
|
||||
/// Set the album cover
|
||||
pub fn set_cover(mut self, cover: Picture) {
|
||||
self.cover = Some(cover);
|
||||
pub fn set_covers(mut self, covers: (Option<Picture>, Option<Picture>)) {
|
||||
self.covers = covers
|
||||
}
|
||||
/// Clears the `cover` field
|
||||
pub fn remove_cover(mut self) {
|
||||
self.cover = None
|
||||
/// Clears the `covers` field
|
||||
pub fn remove_covers(mut self) {
|
||||
self.covers = (None, None)
|
||||
}
|
||||
/// Turns `artists` vec into a String
|
||||
pub fn artists_as_string(&self) -> Option<String> {
|
||||
|
|
|
@ -70,6 +70,16 @@ impl From<&id3PicType> for PictureType {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<PictureType> for id3PicType {
|
||||
fn from(inp: PictureType) -> Self {
|
||||
match inp {
|
||||
PictureType::CoverFront => id3PicType::CoverFront,
|
||||
PictureType::CoverBack => id3PicType::CoverBack,
|
||||
_ => id3PicType::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a picture, with its data and mime type.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Picture {
|
||||
|
|
32
tests/io.rs
32
tests/io.rs
|
@ -35,17 +35,29 @@ macro_rules! add_tags {
|
|||
println!("Setting album artists");
|
||||
tag.set_album_artist("foo album artist");
|
||||
|
||||
let cover = Picture {
|
||||
pic_type: PictureType::CoverFront,
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: vec![0; 10],
|
||||
};
|
||||
let covers = (
|
||||
Picture {
|
||||
pic_type: PictureType::CoverFront,
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: vec![0; 10],
|
||||
},
|
||||
Picture {
|
||||
pic_type: PictureType::CoverBack,
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: vec![0; 11],
|
||||
},
|
||||
);
|
||||
|
||||
let file_name = stringify!($file);
|
||||
|
||||
if file_name != stringify!("tests/assets/a.wav") {
|
||||
tag.set_album_cover(cover.clone());
|
||||
assert_eq!(tag.album_cover(), Some(cover));
|
||||
println!("Setting front cover");
|
||||
tag.set_front_cover(covers.0.clone());
|
||||
assert_eq!(tag.front_cover(), Some(covers.0));
|
||||
|
||||
println!("Setting back cover");
|
||||
tag.set_back_cover(covers.1.clone());
|
||||
assert_eq!(tag.back_cover(), Some(covers.1));
|
||||
}
|
||||
|
||||
println!("Writing");
|
||||
|
@ -113,9 +125,9 @@ macro_rules! remove_tags {
|
|||
assert!(tag.album_artists_vec().is_none());
|
||||
tag.remove_album_artists();
|
||||
|
||||
tag.remove_album_cover();
|
||||
assert!(tag.album_cover().is_none());
|
||||
tag.remove_album_cover();
|
||||
tag.remove_album_covers();
|
||||
assert_eq!(tag.album_covers(), (None, None));
|
||||
tag.remove_album_covers();
|
||||
|
||||
println!("Writing");
|
||||
tag.write_to_path($file).unwrap();
|
||||
|
|
Loading…
Add table
Reference in a new issue