Ilst: Create Ilst::is_* methods for flag atoms

This commit is contained in:
Serial 2024-09-14 16:15:42 -04:00 committed by Alex
parent 9eb35ae1b9
commit f87fa0a3f5
2 changed files with 95 additions and 91 deletions

View file

@ -1,92 +1,23 @@
// https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35
/// Identifiers for flag atoms
///
/// Any identifier in here will be treated as having [`AtomData::Bool`] as its data type when parsing.
/// See [`Ilst::set_flag`] for more information.
///
/// [`AtomData::Bool`]: crate::mp4::AtomData::Bool
/// [`Ilst::set_flag`]: crate::mp4::Ilst::set_flag
pub mod flags {
use crate::mp4::AtomIdent;
/// Reserved for use where no type needs to be indicated
pub const RESERVED: u32 = 0;
/// UTF-8 string without any count or NULL terminator
pub const UTF8: u32 = 1;
/// A big-endian UTF-16 string
pub const UTF16: u32 = 2;
/// Deprecated unless it is needed for special Japanese characters
pub const S_JIS: u32 = 3;
/// The UTF-8 variant storage of a string for sorting only
pub const UTF8_SORT: u32 = 4;
/// The UTF-16 variant storage of a string for sorting only
pub const UTF16_SORT: u32 = 5;
/// A JPEG in a JFIF wrapper
pub const JPEG: u32 = 13;
/// A PNG in a PNG wrapper
pub const PNG: u32 = 14;
/// A big-endian signed integer in 1,2,3 or 4 bytes
pub const BE_SIGNED_INTEGER: u32 = 21;
/// A big-endian unsigned integer in 1,2,3 or 4 bytes; size of value determines integer size
pub const BE_UNSIGNED_INTEGER: u32 = 22;
/// A big-endian 32-bit floating point value (IEEE754)
pub const BE_FLOAT32: u32 = 23;
/// A big-endian 64-bit floating point value (IEEE754)
pub const BE_FLOAT64: u32 = 24;
/// Windows bitmap format graphics
pub const BMP: u32 = 27;
/// A QuickTime metadata atom
pub const QUICKTIME_METADATA: u32 = 28;
/// An 8-bit signed integer
pub const SIGNED_8BIT_INTEGER: u32 = 65;
/// A big-endian 16-bit signed integer
pub const BE_16BIT_SIGNED_INTEGER: u32 = 66;
/// A big-endian 32-bit signed integer
pub const BE_32BIT_SIGNED_INTEGER: u32 = 67;
/// A block of data representing a two dimensional (2D) point with 32-bit big-endian floating point x and y coordinates. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 x;
/// BEFloat32 y;
/// }
/// ```
pub const BE_POINT_F32: u32 = 70;
/// A block of data representing 2D dimensions with 32-bit big-endian floating point width and height. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 width;
/// BEFloat32 height;
/// }
/// ```
pub const BE_DIMENSIONS_F32: u32 = 71;
/// A block of data representing a 2D rectangle with 32-bit big-endian floating point x and y coordinates and a 32-bit big-endian floating point width and height size. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 x;
/// BEFloat32 y;
/// BEFloat32 width;
/// BEFloat32 height;
/// }
/// ```
///
/// or the equivalent structure:
///
/// ```c
/// struct {
/// PointF32 origin;
/// DimensionsF32 size;
/// }
/// ```
pub const BE_RECT_F32: u32 = 72;
/// A big-endian 64-bit signed integer
pub const BE_64BIT_SIGNED_INTEGER: u32 = 74;
/// An 8-bit unsigned integer
pub const UNSIGNED_8BIT_INTEGER: u32 = 75;
/// A big-endian 16-bit unsigned integer
pub const BE_16BIT_UNSIGNED_INTEGER: u32 = 76;
/// A big-endian 32-bit unsigned integer
pub const BE_32BIT_UNSIGNED_INTEGER: u32 = 77;
/// A big-endian 64-bit unsigned integer
pub const BE_64BIT_UNSIGNED_INTEGER: u32 = 78;
/// A block of data representing a 3x3 transformation matrix. It has the structure:
///
/// ```c
/// struct {
/// BEFloat64 matrix[3][3];
/// }
/// ```
pub const AFFINE_TRANSFORM_F64: u32 = 79;
/// Podcast flag (`pcst`)
pub const PODCAST: AtomIdent<'_> = AtomIdent::Fourcc(*b"pcst");
/// Gapless playback flag (`pgap`)
pub const GAPLESS: AtomIdent<'_> = AtomIdent::Fourcc(*b"pgap");
/// Show work and movement flag (`shwm`)
pub const SHOW_WORK: AtomIdent<'_> = AtomIdent::Fourcc(*b"shwm");
/// HD video flag (`hdvd`)
pub const HD_VIDEO: AtomIdent<'_> = AtomIdent::Fourcc(*b"hdvd");
/// Compilation flag (`cpil`)
pub const COMPILATION: AtomIdent<'_> = AtomIdent::Fourcc(*b"cpil");
}
pub(crate) const WELL_KNOWN_TYPE_SET: u8 = 0;

View file

@ -64,6 +64,32 @@ macro_rules! impl_accessor {
}
}
macro_rules! impl_flag_accessors {
($($name:ident ($ident:ident)),+ $(,)?) => {
$(
paste::paste! {
#[doc = "Whether the `" $ident "` flag atom is set"]
///
/// # Examples
///
/// ```rust
#[doc = "use lofty::mp4::constants::flags::" $name ";"]
/// use lofty::mp4::{AtomIdent, Ilst};
///
/// let mut ilst = Ilst::new();
///
/// // I want to toggle this flag!
#[doc = "ilst.set_flag(" $name ", true);"]
///
#[doc = "assert!(ilst.is_" $name:lower "());"]
pub fn [<is_ $name:lower>](&self) -> bool {
self.get_flag(&constants::flags::$name).unwrap_or(false)
}
}
)+
};
}
/// ## Pictures
///
/// Unlike other formats, ilst does not store a [`PictureType`]. All pictures will have
@ -349,6 +375,53 @@ impl Ilst {
.retain(|a| !matches!(a.data().next(), Some(AtomData::Picture(_))))
}
/// Sets the value of a flag ([`AtomData::Bool`]) atom
///
/// For identifiers, see [`constants::flags`].
///
/// # Examples
///
/// ```rust
/// use lofty::mp4::constants::flags::COMPILATION;
/// use lofty::mp4::{AtomIdent, Ilst};
///
/// // This file part of a compilation!
/// let mut ilst = Ilst::new();
/// ilst.set_flag(COMPILATION, true);
///
/// assert!(ilst.is_compilation());
/// ```
pub fn set_flag(&mut self, ident: AtomIdent<'_>, value: bool) {
if !value {
// A flag with a value of `false` is equivalent to removing it.
let _ = self.remove(&ident);
return;
}
let data = AtomData::Bool(value);
self.replace_atom(Atom {
ident,
data: AtomDataStorage::Single(data),
});
}
fn get_flag(&self, ident: &AtomIdent<'_>) -> Option<bool> {
self.get(ident)
.and_then(|atom| atom.data().next())
.and_then(|data| match data {
AtomData::Bool(b) => Some(*b),
_ => None,
})
}
impl_flag_accessors!(
PODCAST(pcst),
GAPLESS(pgap),
SHOW_WORK(shwm),
HD_VIDEO(hdvd),
COMPILATION(cpil)
);
/// Returns the parental advisory rating according to the `rtng` atom
pub fn advisory_rating(&self) -> Option<AdvisoryRating> {
self.get(&ADVISORY_RATING)