1use gst::glib::translate::*;
2use std::ptr;
3
4pub struct ExtendedComment {
5 pub key: Option<glib::GString>,
6 pub lang: Option<glib::GString>,
7 pub value: glib::GString,
8}
9
10#[doc(alias = "gst_tag_parse_extended_comment")]
11pub fn tag_parse_extended_comment(
12 ext_comment: &str,
13 fail_if_no_key: bool,
14) -> Result<ExtendedComment, gst::glib::BoolError> {
15 skip_assert_initialized!();
16 unsafe {
17 let mut c_key = ptr::null_mut();
18 let mut c_lang = ptr::null_mut();
19 let mut c_value = ptr::null_mut();
20 let res: bool = from_glib(crate::ffi::gst_tag_parse_extended_comment(
21 ext_comment.to_glib_none().0,
22 &mut c_key,
23 &mut c_lang,
24 &mut c_value,
25 fail_if_no_key.into_glib(),
26 ));
27 if !res {
28 Err(glib::bool_error!("Failed to parse extended comment"))
29 } else {
30 let key = from_glib_full(c_key);
31 let lang = from_glib_full(c_lang);
32 let value = from_glib_full(c_value);
33
34 Ok(ExtendedComment { key, lang, value })
35 }
36 }
37}
38
39#[inline]
40fn ensure_tags_registered() {
41 static ONCE: std::sync::Once = std::sync::Once::new();
42 skip_assert_initialized!();
43 ONCE.call_once(
44 #[inline]
45 || {
46 unsafe { crate::ffi::gst_tag_register_musicbrainz_tags() };
47 },
48 );
49}
50
51macro_rules! impl_tag(
52 ($name:ident, $t:ty, $gst_tag:ident) => {
53 pub enum $name {}
54 impl<'a> gst::Tag<'a> for $name {
55 type TagType = $t;
56 const TAG_NAME: &'static glib::GStr = unsafe { glib::GStr::from_utf8_with_nul_unchecked($crate::ffi::$gst_tag) };
57 #[inline]
58 fn ensure() {
59 crate::tags::ensure_tags_registered();
60 }
61 }
62 };
63);
64
65pub mod acoustid {
66 impl_tag!(Fingerprint, &'a str, GST_TAG_ACOUSTID_FINGERPRINT);
67 impl_tag!(Id, &'a str, GST_TAG_ACOUSTID_ID);
68}
69
70pub mod capturing {
71 impl_tag!(Contrast, &'a str, GST_TAG_CAPTURING_CONTRAST);
72 impl_tag!(DigitalZoomRatio, f64, GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO);
73 impl_tag!(
74 ExposureCompensation,
75 f64,
76 GST_TAG_CAPTURING_EXPOSURE_COMPENSATION
77 );
78 impl_tag!(ExposureMode, &'a str, GST_TAG_CAPTURING_EXPOSURE_MODE);
79 impl_tag!(ExposureProgram, &'a str, GST_TAG_CAPTURING_EXPOSURE_PROGRAM);
80 impl_tag!(FlashFired, bool, GST_TAG_CAPTURING_FLASH_FIRED);
81 impl_tag!(FlashMode, &'a str, GST_TAG_CAPTURING_FLASH_MODE);
82 impl_tag!(FocalLength, f64, GST_TAG_CAPTURING_FOCAL_LENGTH);
83 impl_tag!(FocalLength35MM, f64, GST_TAG_CAPTURING_FOCAL_LENGTH_35_MM);
84 impl_tag!(FocalRatio, f64, GST_TAG_CAPTURING_FOCAL_RATIO);
85 impl_tag!(GainAdjustment, &'a str, GST_TAG_CAPTURING_GAIN_ADJUSTMENT);
86 impl_tag!(IsoSpeed, i32, GST_TAG_CAPTURING_ISO_SPEED);
87 impl_tag!(LightSource, &'a str, GST_TAG_CAPTURING_LIGHT_SOURCE);
88 impl_tag!(MeteringMode, &'a str, GST_TAG_CAPTURING_METERING_MODE);
89 impl_tag!(Saturation, &'a str, GST_TAG_CAPTURING_SATURATION);
90 impl_tag!(
91 SceneCaptureType,
92 &'a str,
93 GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE
94 );
95 impl_tag!(Sharpness, &'a str, GST_TAG_CAPTURING_SHARPNESS);
96 impl_tag!(ShutterSpeed, gst::Fraction, GST_TAG_CAPTURING_SHUTTER_SPEED);
97 impl_tag!(Source, &'a str, GST_TAG_CAPTURING_SOURCE);
98 impl_tag!(WhiteBalance, &'a str, GST_TAG_CAPTURING_WHITE_BALANCE);
99}
100
101pub mod cdda {
102 impl_tag!(CddbDiscid, &'a str, GST_TAG_CDDA_CDDB_DISCID);
103 impl_tag!(CddbDiscidFull, &'a str, GST_TAG_CDDA_CDDB_DISCID_FULL);
104 impl_tag!(MusicbrainzDiscid, &'a str, GST_TAG_CDDA_MUSICBRAINZ_DISCID);
105 impl_tag!(
106 MusicbrainzDiscidFull,
107 &'a str,
108 GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL
109 );
110}
111
112pub mod image {
113 impl_tag!(HorizontalPPI, f64, GST_TAG_IMAGE_HORIZONTAL_PPI);
114 impl_tag!(VerticalPPI, f64, GST_TAG_IMAGE_VERTICAL_PPI);
115}
116
117impl_tag!(MusicalKey, &'a str, GST_TAG_MUSICAL_KEY);
118
119pub mod musicbrainz {
120 impl_tag!(AlbumArtistId, &'a str, GST_TAG_MUSICBRAINZ_ALBUMARTISTID);
121 impl_tag!(AlbumId, &'a str, GST_TAG_MUSICBRAINZ_ALBUMID);
122 impl_tag!(ArtistId, &'a str, GST_TAG_MUSICBRAINZ_ARTISTID);
123 impl_tag!(ReleaseGroupId, &'a str, GST_TAG_MUSICBRAINZ_RELEASEGROUPID);
124 impl_tag!(ReleaseTrackId, &'a str, GST_TAG_MUSICBRAINZ_RELEASETRACKID);
125 impl_tag!(TrackId, &'a str, GST_TAG_MUSICBRAINZ_TRACKID);
126 impl_tag!(TrmId, &'a str, GST_TAG_MUSICBRAINZ_TRMID);
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_tags_are_registered_automatically() {
135 const B_MINOR: &str = "Bm";
136 gst::init().unwrap();
137 let mut tags = gst::TagList::new();
138
139 tags.get_mut()
140 .unwrap()
141 .add::<MusicalKey>(&B_MINOR, gst::TagMergeMode::Replace);
142
143 assert_eq!(B_MINOR, tags.get::<MusicalKey>().unwrap().get());
144 }
145}