mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-12 21:52:33 +00:00
Add rtng
atom support
This commit is contained in:
parent
c70e8ee454
commit
4c0b7c2273
4 changed files with 86 additions and 9 deletions
|
@ -63,6 +63,38 @@ pub enum AtomData {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
/// The parental advisory rating
|
||||
pub enum AdvisoryRating {
|
||||
/// A rating of 0
|
||||
None,
|
||||
/// A rating of 2
|
||||
Clean,
|
||||
/// A rating of (1 || > 2)
|
||||
Explicit,
|
||||
}
|
||||
|
||||
impl AdvisoryRating {
|
||||
/// Returns the rating as it appears in the `rtng` atom
|
||||
pub fn as_u8(&self) -> u8 {
|
||||
match self {
|
||||
AdvisoryRating::None => 0,
|
||||
AdvisoryRating::Clean => 2,
|
||||
AdvisoryRating::Explicit => 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for AdvisoryRating {
|
||||
fn from(input: u8) -> Self {
|
||||
match input {
|
||||
0 => Self::None,
|
||||
2 => Self::Clean,
|
||||
_ => Self::Explicit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AtomRef<'a> {
|
||||
pub(crate) ident: AtomIdentRef<'a>,
|
||||
pub(crate) data: AtomDataRef<'a>,
|
||||
|
|
|
@ -3,12 +3,13 @@ pub(super) mod constants;
|
|||
pub(super) mod read;
|
||||
pub(crate) mod write;
|
||||
|
||||
use super::constants::BE_SIGNED_INTEGER;
|
||||
use super::AtomIdent;
|
||||
use crate::error::{LoftyError, Result};
|
||||
use crate::types::item::{ItemKey, ItemValue, TagItem};
|
||||
use crate::types::picture::{Picture, PictureType};
|
||||
use crate::types::tag::{Accessor, Tag, TagIO, TagType};
|
||||
use atom::{Atom, AtomData, AtomDataRef, AtomIdentRef, AtomRef};
|
||||
use atom::{AdvisoryRating, Atom, AtomData, AtomDataRef, AtomIdentRef, AtomRef};
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, OpenOptions};
|
||||
|
@ -142,6 +143,34 @@ impl Ilst {
|
|||
.retain(|a| !matches!(a.data(), AtomData::Picture(_)))
|
||||
}
|
||||
|
||||
/// Returns the parental advisory rating according to the `rtng` atom
|
||||
pub fn advisory_rating(&self) -> Option<AdvisoryRating> {
|
||||
if let Some(Atom { data, .. }) = self.atom(&AtomIdent::Fourcc(*b"rtng")) {
|
||||
let rating = match data {
|
||||
AtomData::SignedInteger(si) => *si as u8,
|
||||
AtomData::Unknown { data: c, .. } if !c.is_empty() => c[0],
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
return Some(AdvisoryRating::from(rating));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Sets the advisory rating
|
||||
pub fn set_advisory_rating(&mut self, advisory_rating: AdvisoryRating) {
|
||||
let byte = advisory_rating.as_u8();
|
||||
|
||||
self.replace_atom(Atom {
|
||||
ident: AtomIdent::Fourcc(*b"rtng"),
|
||||
data: AtomData::Unknown {
|
||||
code: BE_SIGNED_INTEGER,
|
||||
data: vec![byte],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the track number
|
||||
pub fn track_number(&self) -> Option<u16> {
|
||||
self.extract_number(*b"trkn", 4)
|
||||
|
@ -188,7 +217,8 @@ impl TagIO for Ilst {
|
|||
}
|
||||
|
||||
fn save_to_path<P: AsRef<Path>>(&self, path: P) -> std::result::Result<(), Self::Err> {
|
||||
self.save_to(&mut OpenOptions::new().read(true).write(true).open(path)?)
|
||||
let mut f = OpenOptions::new().read(true).write(true).open(path)?;
|
||||
self.save_to(&mut f)
|
||||
}
|
||||
|
||||
fn save_to(&self, file: &mut File) -> std::result::Result<(), Self::Err> {
|
||||
|
@ -410,9 +440,14 @@ fn item_key_to_ident(key: &ItemKey) -> Option<AtomIdentRef<'_>> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::mp4::{Atom, AtomData, AtomIdent, Ilst};
|
||||
use crate::mp4::{AdvisoryRating, Atom, AtomData, AtomIdent, Ilst};
|
||||
use crate::{ItemKey, Tag, TagIO, TagType};
|
||||
|
||||
fn read_ilst(path: &str) -> Ilst {
|
||||
let tag = crate::tag_utils::test_utils::read_path(path);
|
||||
super::read::parse_ilst(&mut &tag[..], tag.len() as u64).unwrap()
|
||||
}
|
||||
|
||||
fn verify_atom(ilst: &Ilst, ident: [u8; 4], data: &AtomData) {
|
||||
let atom = ilst.atom(&AtomIdent::Fourcc(ident)).unwrap();
|
||||
assert_eq!(atom.data(), data);
|
||||
|
@ -481,8 +516,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn ilst_re_read() {
|
||||
let tag = crate::tag_utils::test_utils::read_path("tests/tags/assets/test.ilst");
|
||||
let parsed_tag = super::read::parse_ilst(&mut &tag[..], tag.len() as u64).unwrap();
|
||||
let parsed_tag = read_ilst("tests/tags/assets/test.ilst");
|
||||
|
||||
let mut writer = Vec::new();
|
||||
parsed_tag.dump_to(&mut writer).unwrap();
|
||||
|
@ -562,9 +596,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn issue_34() {
|
||||
let tag_bytes = crate::tag_utils::test_utils::read_path("tests/tags/assets/issue_34.ilst");
|
||||
|
||||
let ilst = super::read::parse_ilst(&mut &tag_bytes[..], tag_bytes.len() as u64).unwrap();
|
||||
let ilst = read_ilst("tests/tags/assets/issue_34.ilst");
|
||||
|
||||
verify_atom(
|
||||
&ilst,
|
||||
|
@ -580,4 +612,17 @@ mod tests {
|
|||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn advisory_rating() {
|
||||
let ilst = read_ilst("tests/tags/assets/advisory_rating.ilst");
|
||||
|
||||
verify_atom(
|
||||
&ilst,
|
||||
*b"\xa9ART",
|
||||
&AtomData::UTF8(String::from("Foo artist")),
|
||||
);
|
||||
|
||||
assert_eq!(ilst.advisory_rating(), Some(AdvisoryRating::Explicit));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ cfg_if::cfg_if! {
|
|||
pub(crate) mod ilst;
|
||||
|
||||
pub use atom_info::AtomIdent;
|
||||
pub use ilst::atom::{Atom, AtomData};
|
||||
pub use ilst::atom::{Atom, AtomData, AdvisoryRating};
|
||||
pub use ilst::Ilst;
|
||||
|
||||
/// This module contains the codes for all of the [Well-known data types](https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW34)
|
||||
|
|
BIN
tests/tags/assets/advisory_rating.ilst
Normal file
BIN
tests/tags/assets/advisory_rating.ilst
Normal file
Binary file not shown.
Loading…
Reference in a new issue