mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 14:12:31 +00:00
Cover support for ape
This commit is contained in:
parent
26cfd2e59b
commit
16f4ecce0d
3 changed files with 58 additions and 11 deletions
|
@ -1,15 +1,17 @@
|
|||
#![cfg(feature = "monkey")]
|
||||
|
||||
use crate::{
|
||||
impl_tag, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, Picture, Result, TagType,
|
||||
ToAny, ToAnyTag,
|
||||
impl_tag, Album, AnyTag, AudioTag, AudioTagEdit, AudioTagWrite, MimeType, Picture, PictureType,
|
||||
Result, TagType, ToAny, ToAnyTag,
|
||||
};
|
||||
|
||||
pub use ape::Tag as ApeInnerTag;
|
||||
|
||||
use ape::Item;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use filepath::FilePath;
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Seek, SeekFrom};
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(feature = "duration")]
|
||||
|
@ -153,7 +155,11 @@ impl AudioTagEdit for ApeTag {
|
|||
}
|
||||
|
||||
fn set_front_cover(&mut self, cover: Picture) {
|
||||
// TODO
|
||||
self.remove_front_cover();
|
||||
|
||||
if let Ok(item) = ape::Item::from_binary("Cover Art (Front)", cover.data) {
|
||||
self.inner.set_item(item)
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_front_cover(&mut self) {
|
||||
|
@ -169,7 +175,11 @@ impl AudioTagEdit for ApeTag {
|
|||
}
|
||||
|
||||
fn set_back_cover(&mut self, cover: Picture) {
|
||||
// TODO
|
||||
self.remove_back_cover();
|
||||
|
||||
if let Ok(item) = ape::Item::from_binary("Cover Art (Back)", cover.data) {
|
||||
self.inner.set_item(item)
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_back_cover(&mut self) {
|
||||
|
@ -177,7 +187,8 @@ impl AudioTagEdit for ApeTag {
|
|||
}
|
||||
|
||||
fn pictures(&self) -> Option<Vec<Picture>> {
|
||||
todo!()
|
||||
// TODO
|
||||
None
|
||||
}
|
||||
|
||||
// Track number and total tracks are stored together as num/total?
|
||||
|
@ -274,7 +285,42 @@ impl AudioTagEdit for ApeTag {
|
|||
|
||||
fn get_picture(item: &Item) -> Option<Picture> {
|
||||
if let ape::ItemValue::Binary(bin) = &item.value {
|
||||
// TODO
|
||||
if !bin.is_empty() {
|
||||
let pic_type = match &*item.key {
|
||||
"Cover Art (Front)" => PictureType::CoverFront,
|
||||
"Cover Art (Back)" => PictureType::CoverBack,
|
||||
_ => PictureType::Other,
|
||||
};
|
||||
|
||||
let data_pos: Option<usize> =
|
||||
if bin.starts_with(&[b'\xff']) || bin.starts_with(&[b'\x89']) {
|
||||
Some(0)
|
||||
} else {
|
||||
bin.iter().find(|x| x == &&b'\0').map(|pos| *pos as usize)
|
||||
};
|
||||
|
||||
if let Some(pos) = data_pos {
|
||||
let mut cursor = Cursor::new(bin.clone());
|
||||
|
||||
if cursor.seek(SeekFrom::Start((pos + 1) as u64)).is_ok() {
|
||||
if let Ok(mime) = cursor.read_u32::<LittleEndian>() {
|
||||
if let Some(mime_type) = match &mime.to_le_bytes() {
|
||||
b"PNG\0" => Some(MimeType::Png),
|
||||
b"JPEG" => Some(MimeType::Jpeg),
|
||||
_ => None,
|
||||
} {
|
||||
cursor.set_position(0_u64);
|
||||
|
||||
return Some(Picture {
|
||||
pic_type,
|
||||
mime_type,
|
||||
data: cursor.into_inner(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
clippy::cast_precision_loss,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::clippy::cast_possible_truncation,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::module_name_repetitions,
|
||||
clippy::must_use_candidate,
|
||||
clippy::doc_markdown,
|
||||
|
|
|
@ -39,18 +39,19 @@ macro_rules! add_tags {
|
|||
Picture {
|
||||
pic_type: PictureType::CoverFront,
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: vec![0; 10],
|
||||
data: vec![0, 74, 80, 69, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
Picture {
|
||||
pic_type: PictureType::CoverBack,
|
||||
mime_type: MimeType::Jpeg,
|
||||
data: vec![0; 11],
|
||||
data: vec![0, 74, 80, 69, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
);
|
||||
|
||||
let file_name = stringify!($file);
|
||||
let file = stringify!($file);
|
||||
|
||||
if file_name != stringify!("tests/assets/a.wav") {
|
||||
// Skip this since RIFF INFO doesn't store images
|
||||
if file != stringify!("tests/assets/a.wav") {
|
||||
println!("Setting front cover");
|
||||
tag.set_front_cover(covers.0.clone());
|
||||
assert_eq!(tag.front_cover(), Some(covers.0));
|
||||
|
|
Loading…
Reference in a new issue