multitag/
data.rs

1//! Useful types for representing audio metadata information.
2//!
3//! The types in this module are typically returned by methods on [`Tag`](crate::Tag).
4
5use crate::{Error, Result};
6use id3::frame::Picture as Id3Picture;
7use id3::frame::Timestamp as Id3Timestamp;
8use metaflac::block::Picture as FlacPicture;
9use mp4ameta::Img as Mp4Picture;
10use mp4ameta::ImgFmt as Mp4ImageFmt;
11use oggmeta::Picture as OggPicture;
12use opusmeta::picture::Picture as OpusPicture;
13use std::str::FromStr;
14
15/// Represents the album that a song is part of.
16#[derive(Clone, Debug, Default)]
17pub struct Album {
18    pub title: Option<String>,
19    pub artist: Option<String>,
20    pub cover: Option<Picture>,
21}
22
23/// Stores picture data.
24#[derive(Clone, Debug)]
25pub struct Picture {
26    pub data: Vec<u8>,
27    pub mime_type: String,
28}
29
30impl From<Id3Picture> for Picture {
31    fn from(value: Id3Picture) -> Self {
32        Self {
33            data: value.data,
34            mime_type: value.mime_type,
35        }
36    }
37}
38
39impl From<FlacPicture> for Picture {
40    fn from(value: FlacPicture) -> Self {
41        Self {
42            data: value.data,
43            mime_type: value.mime_type,
44        }
45    }
46}
47
48impl From<Mp4Picture<&[u8]>> for Picture {
49    fn from(value: Mp4Picture<&[u8]>) -> Self {
50        Self {
51            data: value.data.to_vec(),
52            mime_type: match value.fmt {
53                Mp4ImageFmt::Bmp => "image/bmp".into(),
54                Mp4ImageFmt::Jpeg => "image/jpeg".into(),
55                Mp4ImageFmt::Png => "image/png".into(),
56            },
57        }
58    }
59}
60
61impl TryFrom<Picture> for Mp4Picture<Vec<u8>> {
62    type Error = Error;
63
64    fn try_from(value: Picture) -> Result<Self> {
65        let image_fmt = match value.mime_type.as_str() {
66            "image/bmp" => Ok(Mp4ImageFmt::Bmp),
67            "image/jpeg" => Ok(Mp4ImageFmt::Jpeg),
68            "image/png" => Ok(Mp4ImageFmt::Png),
69            _ => Err(Error::InvalidImageFormat),
70        }?;
71
72        Ok(Self {
73            fmt: image_fmt,
74            data: value.data,
75        })
76    }
77}
78
79impl From<OpusPicture> for Picture {
80    fn from(value: OpusPicture) -> Self {
81        Self {
82            data: value.data,
83            mime_type: value.mime_type,
84        }
85    }
86}
87
88impl From<OggPicture> for Picture {
89    fn from(value: OggPicture) -> Self {
90        Self {
91            data: value.data,
92            mime_type: value.media_type,
93        }
94    }
95}
96
97impl From<Picture> for OpusPicture {
98    fn from(value: Picture) -> Self {
99        let mut picture = OpusPicture::new();
100        picture.mime_type = value.mime_type;
101        picture.data = value.data;
102
103        picture
104    }
105}
106
107impl std::fmt::Display for Picture {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        write!(
110            f,
111            "Picture data ({}, {} bytes)",
112            self.mime_type,
113            self.data.len()
114        )
115    }
116}
117
118/// Represents a date and time according to the ID3v2.4 spec.
119#[derive(Clone, Copy, Debug, Default)]
120pub struct Timestamp {
121    pub year: i32,
122    pub month: Option<u8>,
123    pub day: Option<u8>,
124    pub hour: Option<u8>,
125    pub minute: Option<u8>,
126    pub second: Option<u8>,
127}
128
129impl From<Id3Timestamp> for Timestamp {
130    fn from(value: Id3Timestamp) -> Self {
131        Self {
132            year: value.year,
133            month: value.month,
134            day: value.day,
135            hour: value.hour,
136            minute: value.minute,
137            second: value.second,
138        }
139    }
140}
141
142impl From<Timestamp> for Id3Timestamp {
143    fn from(value: Timestamp) -> Self {
144        Self {
145            year: value.year,
146            month: value.month,
147            day: value.day,
148            hour: value.hour,
149            minute: value.minute,
150            second: value.second,
151        }
152    }
153}
154
155impl FromStr for Timestamp {
156    type Err = Error;
157
158    fn from_str(s: &str) -> Result<Self> {
159        Ok(Id3Timestamp::from_str(s)
160            .map_err(|_| Error::TimestampParseError)?
161            .into())
162    }
163}
164
165impl std::fmt::Display for Timestamp {
166    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167        write!(f, "{}", Id3Timestamp::from(*self))
168    }
169}