1use std::str;
4
5use crate::ffi;
6use glib::translate::{from_glib, IntoGlib};
7use std::sync::LazyLock;
8
9#[cfg(feature = "v1_18")]
17pub static AUDIO_FORMATS_ALL: LazyLock<Box<[crate::AudioFormat]>> = LazyLock::new(|| unsafe {
18 let mut len: u32 = 0;
19 let mut res = Vec::with_capacity(len as usize);
20 let formats = ffi::gst_audio_formats_raw(&mut len);
21 for i in 0..len {
22 let format = formats.offset(i as isize);
23 res.push(from_glib(*format));
24 }
25 res.into_boxed_slice()
26});
27
28#[cfg(not(feature = "v1_18"))]
29pub static AUDIO_FORMATS_ALL: LazyLock<Box<[crate::AudioFormat]>> = LazyLock::new(|| {
30 #[cfg(target_endian = "little")]
31 {
32 Box::new([
33 crate::AudioFormat::F64le,
34 crate::AudioFormat::F64be,
35 crate::AudioFormat::F32le,
36 crate::AudioFormat::F32be,
37 crate::AudioFormat::S32le,
38 crate::AudioFormat::S32be,
39 crate::AudioFormat::U32le,
40 crate::AudioFormat::U32be,
41 crate::AudioFormat::S2432le,
42 crate::AudioFormat::S2432be,
43 crate::AudioFormat::U2432le,
44 crate::AudioFormat::U2432be,
45 crate::AudioFormat::S24le,
46 crate::AudioFormat::S24be,
47 crate::AudioFormat::U24le,
48 crate::AudioFormat::U24be,
49 crate::AudioFormat::S20le,
50 crate::AudioFormat::S20be,
51 crate::AudioFormat::U20le,
52 crate::AudioFormat::U20be,
53 crate::AudioFormat::S18le,
54 crate::AudioFormat::S18be,
55 crate::AudioFormat::U18le,
56 crate::AudioFormat::U18be,
57 crate::AudioFormat::S16le,
58 crate::AudioFormat::S16be,
59 crate::AudioFormat::U16le,
60 crate::AudioFormat::U16be,
61 crate::AudioFormat::S8,
62 crate::AudioFormat::U8,
63 ])
64 }
65 #[cfg(target_endian = "big")]
66 {
67 Box::new([
68 crate::AudioFormat::F64be,
69 crate::AudioFormat::F64le,
70 crate::AudioFormat::F32be,
71 crate::AudioFormat::F32le,
72 crate::AudioFormat::S32be,
73 crate::AudioFormat::S32le,
74 crate::AudioFormat::U32be,
75 crate::AudioFormat::U32le,
76 crate::AudioFormat::S2432be,
77 crate::AudioFormat::S2432le,
78 crate::AudioFormat::U2432be,
79 crate::AudioFormat::U2432le,
80 crate::AudioFormat::S24be,
81 crate::AudioFormat::S24le,
82 crate::AudioFormat::U24be,
83 crate::AudioFormat::U24le,
84 crate::AudioFormat::S20be,
85 crate::AudioFormat::S20le,
86 crate::AudioFormat::U20be,
87 crate::AudioFormat::U20le,
88 crate::AudioFormat::S18be,
89 crate::AudioFormat::S18le,
90 crate::AudioFormat::U18be,
91 crate::AudioFormat::U18le,
92 crate::AudioFormat::S16be,
93 crate::AudioFormat::S16le,
94 crate::AudioFormat::U16be,
95 crate::AudioFormat::U16le,
96 crate::AudioFormat::S8,
97 crate::AudioFormat::U8,
98 ])
99 }
100});
101
102impl crate::AudioFormat {
103 #[doc(alias = "gst_audio_format_build_integer")]
104 pub fn build_integer(
105 sign: bool,
106 endianness: crate::AudioEndianness,
107 width: i32,
108 depth: i32,
109 ) -> Self {
110 assert_initialized_main_thread!();
111
112 unsafe {
113 from_glib(ffi::gst_audio_format_build_integer(
114 sign.into_glib(),
115 endianness.into_glib(),
116 width,
117 depth,
118 ))
119 }
120 }
121
122 #[doc(alias = "gst_audio_format_to_string")]
123 pub fn to_str<'a>(self) -> &'a glib::GStr {
124 if self == Self::Unknown {
125 return glib::gstr!("UNKNOWN");
126 }
127 unsafe {
128 glib::GStr::from_ptr(
129 ffi::gst_audio_format_to_string(self.into_glib())
130 .as_ref()
131 .expect("gst_audio_format_to_string returned NULL"),
132 )
133 }
134 }
135
136 pub fn iter_raw() -> AudioFormatIterator {
137 AudioFormatIterator::default()
138 }
139}
140
141impl str::FromStr for crate::AudioFormat {
142 type Err = glib::BoolError;
143
144 fn from_str(s: &str) -> Result<Self, Self::Err> {
145 skip_assert_initialized!();
146
147 let fmt = Self::from_string(s);
148 if fmt == Self::Unknown {
149 Err(glib::bool_error!(
150 "Failed to parse audio format from string"
151 ))
152 } else {
153 Ok(fmt)
154 }
155 }
156}
157
158impl PartialOrd for crate::AudioFormat {
159 #[inline]
160 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
161 Some(self.cmp(other))
162 }
163}
164
165impl Ord for crate::AudioFormat {
166 #[inline]
167 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
168 crate::AudioFormatInfo::from_format(*self).cmp(&crate::AudioFormatInfo::from_format(*other))
169 }
170}
171
172pub const AUDIO_FORMAT_UNKNOWN: crate::AudioFormat = crate::AudioFormat::Unknown;
173pub const AUDIO_FORMAT_ENCODED: crate::AudioFormat = crate::AudioFormat::Encoded;
174pub const AUDIO_FORMAT_S8: crate::AudioFormat = crate::AudioFormat::S8;
175pub const AUDIO_FORMAT_U8: crate::AudioFormat = crate::AudioFormat::U8;
176
177#[cfg(target_endian = "big")]
178pub const AUDIO_FORMAT_S16: crate::AudioFormat = crate::AudioFormat::S16be;
179#[cfg(target_endian = "big")]
180pub const AUDIO_FORMAT_U16: crate::AudioFormat = crate::AudioFormat::U16be;
181#[cfg(target_endian = "big")]
182pub const AUDIO_FORMAT_S2432: crate::AudioFormat = crate::AudioFormat::S2432be;
183#[cfg(target_endian = "big")]
184pub const AUDIO_FORMAT_U2432: crate::AudioFormat = crate::AudioFormat::U2432be;
185#[cfg(target_endian = "big")]
186pub const AUDIO_FORMAT_S32: crate::AudioFormat = crate::AudioFormat::S32be;
187#[cfg(target_endian = "big")]
188pub const AUDIO_FORMAT_U32: crate::AudioFormat = crate::AudioFormat::U32be;
189#[cfg(target_endian = "big")]
190pub const AUDIO_FORMAT_S24: crate::AudioFormat = crate::AudioFormat::S24be;
191#[cfg(target_endian = "big")]
192pub const AUDIO_FORMAT_U24: crate::AudioFormat = crate::AudioFormat::U24be;
193#[cfg(target_endian = "big")]
194pub const AUDIO_FORMAT_S20: crate::AudioFormat = crate::AudioFormat::S20be;
195#[cfg(target_endian = "big")]
196pub const AUDIO_FORMAT_U20: crate::AudioFormat = crate::AudioFormat::U20be;
197#[cfg(target_endian = "big")]
198pub const AUDIO_FORMAT_S18: crate::AudioFormat = crate::AudioFormat::S18be;
199#[cfg(target_endian = "big")]
200pub const AUDIO_FORMAT_U18: crate::AudioFormat = crate::AudioFormat::U18be;
201#[cfg(target_endian = "big")]
202pub const AUDIO_FORMAT_F32: crate::AudioFormat = crate::AudioFormat::F32be;
203#[cfg(target_endian = "big")]
204pub const AUDIO_FORMAT_F64: crate::AudioFormat = crate::AudioFormat::F64be;
205#[cfg(all(target_endian = "big", feature = "v1_28"))]
206pub const AUDIO_FORMAT_S20_32: crate::AudioFormat = crate::AudioFormat::S2032be;
207#[cfg(all(target_endian = "big", feature = "v1_28"))]
208pub const AUDIO_FORMAT_U20_32: crate::AudioFormat = crate::AudioFormat::U2032be;
209
210#[cfg(target_endian = "little")]
211pub const AUDIO_FORMAT_S16: crate::AudioFormat = crate::AudioFormat::S16le;
212#[cfg(target_endian = "little")]
213pub const AUDIO_FORMAT_U16: crate::AudioFormat = crate::AudioFormat::U16le;
214#[cfg(target_endian = "little")]
215pub const AUDIO_FORMAT_S2432: crate::AudioFormat = crate::AudioFormat::S2432le;
216#[cfg(target_endian = "little")]
217pub const AUDIO_FORMAT_U2432: crate::AudioFormat = crate::AudioFormat::U2432le;
218#[cfg(target_endian = "little")]
219pub const AUDIO_FORMAT_S32: crate::AudioFormat = crate::AudioFormat::S32le;
220#[cfg(target_endian = "little")]
221pub const AUDIO_FORMAT_U32: crate::AudioFormat = crate::AudioFormat::U32le;
222#[cfg(target_endian = "little")]
223pub const AUDIO_FORMAT_S24: crate::AudioFormat = crate::AudioFormat::S24le;
224#[cfg(target_endian = "little")]
225pub const AUDIO_FORMAT_U24: crate::AudioFormat = crate::AudioFormat::U24le;
226#[cfg(target_endian = "little")]
227pub const AUDIO_FORMAT_S20: crate::AudioFormat = crate::AudioFormat::S20le;
228#[cfg(target_endian = "little")]
229pub const AUDIO_FORMAT_U20: crate::AudioFormat = crate::AudioFormat::U20le;
230#[cfg(target_endian = "little")]
231pub const AUDIO_FORMAT_S18: crate::AudioFormat = crate::AudioFormat::S18le;
232#[cfg(target_endian = "little")]
233pub const AUDIO_FORMAT_U18: crate::AudioFormat = crate::AudioFormat::U18le;
234#[cfg(target_endian = "little")]
235pub const AUDIO_FORMAT_F32: crate::AudioFormat = crate::AudioFormat::F32le;
236#[cfg(target_endian = "little")]
237pub const AUDIO_FORMAT_F64: crate::AudioFormat = crate::AudioFormat::F64le;
238#[cfg(all(target_endian = "little", feature = "v1_28"))]
239pub const AUDIO_FORMAT_S20_32: crate::AudioFormat = crate::AudioFormat::S2032le;
240#[cfg(all(target_endian = "little", feature = "v1_28"))]
241pub const AUDIO_FORMAT_U20_32: crate::AudioFormat = crate::AudioFormat::U2032le;
242
243#[must_use = "iterators are lazy and do nothing unless consumed"]
244pub struct AudioFormatIterator {
245 idx: usize,
246 len: usize,
247}
248
249impl Default for AudioFormatIterator {
250 fn default() -> Self {
251 Self {
252 idx: 0,
253 len: AUDIO_FORMATS_ALL.len(),
254 }
255 }
256}
257
258impl Iterator for AudioFormatIterator {
259 type Item = crate::AudioFormat;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 if self.idx >= self.len {
263 None
264 } else {
265 let fmt = AUDIO_FORMATS_ALL[self.idx];
266 self.idx += 1;
267 Some(fmt)
268 }
269 }
270
271 fn size_hint(&self) -> (usize, Option<usize>) {
272 let remaining = self.len - self.idx;
273
274 (remaining, Some(remaining))
275 }
276
277 fn count(self) -> usize {
278 self.len - self.idx
279 }
280
281 fn nth(&mut self, n: usize) -> Option<Self::Item> {
282 let (end, overflow) = self.idx.overflowing_add(n);
283 if end >= self.len || overflow {
284 self.idx = self.len;
285 None
286 } else {
287 self.idx = end + 1;
288 Some(AUDIO_FORMATS_ALL[end])
289 }
290 }
291
292 fn last(self) -> Option<Self::Item> {
293 if self.idx == self.len {
294 None
295 } else {
296 Some(AUDIO_FORMATS_ALL[self.len - 1])
297 }
298 }
299}
300
301impl ExactSizeIterator for AudioFormatIterator {}
302
303impl std::iter::FusedIterator for AudioFormatIterator {}
304
305impl DoubleEndedIterator for AudioFormatIterator {
306 fn next_back(&mut self) -> Option<Self::Item> {
307 if self.idx >= self.len {
308 None
309 } else {
310 self.len -= 1;
311 let fmt = AUDIO_FORMATS_ALL[self.len];
312 Some(fmt)
313 }
314 }
315
316 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
317 let (end, overflow) = self.len.overflowing_sub(n);
318 if end <= self.idx || overflow {
319 self.idx = self.len;
320 None
321 } else {
322 self.len = end - 1;
323 let fmt = AUDIO_FORMATS_ALL[self.len];
324 Some(fmt)
325 }
326 }
327}
328pub trait AudioFormatIteratorExt {
329 fn into_audio_caps(
330 self,
331 layout: crate::AudioLayout,
332 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
333}
334
335impl<T> AudioFormatIteratorExt for T
336where
337 T: Iterator<Item = crate::AudioFormat>,
338{
339 fn into_audio_caps(
340 self,
341 layout: crate::AudioLayout,
342 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
343 let formats: Vec<crate::AudioFormat> = self.collect();
344 if !formats.is_empty() {
345 Some(crate::functions::audio_make_raw_caps(&formats, layout))
346 } else {
347 None
348 }
349 }
350}
351
352pub trait AudioFormatIteratorExtRef {
353 fn into_audio_caps(
354 self,
355 layout: crate::AudioLayout,
356 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
357}
358
359impl<'a, T> AudioFormatIteratorExtRef for T
360where
361 T: Iterator<Item = &'a crate::AudioFormat>,
362{
363 fn into_audio_caps(
364 self,
365 layout: crate::AudioLayout,
366 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
367 let formats: Vec<crate::AudioFormat> = self.copied().collect();
368 if !formats.is_empty() {
369 Some(crate::functions::audio_make_raw_caps(&formats, layout))
370 } else {
371 None
372 }
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use itertools::Itertools;
379
380 #[test]
381 fn test_display() {
382 gst::init().unwrap();
383
384 assert_eq!(format!("{}", crate::AudioFormat::S16be), "S16BE");
385 assert_eq!(format!("{:?}", crate::AudioFormat::S16be), "S16be");
386 }
387
388 #[test]
389 fn iter() {
390 use super::*;
391 gst::init().unwrap();
392
393 assert!(crate::AudioFormat::iter_raw().count() > 0);
394 assert_eq!(
395 crate::AudioFormat::iter_raw().count(),
396 crate::AudioFormat::iter_raw().len()
397 );
398
399 let mut i = crate::AudioFormat::iter_raw();
400 let mut count = 0;
401 loop {
402 if i.next().is_none() {
403 break;
404 }
405 count += 1;
406 if i.next_back().is_none() {
407 break;
408 }
409 count += 1;
410 }
411 assert_eq!(count, crate::AudioFormat::iter_raw().len());
412
413 assert!(crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::F64be));
414 assert!(!crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::Encoded));
415
416 let caps = crate::AudioFormat::iter_raw().into_audio_caps(crate::AudioLayout::Interleaved);
417 assert!(caps.is_some());
418
419 let caps = crate::AudioFormat::iter_raw()
420 .filter(|f| crate::AudioFormatInfo::from_format(*f).is_little_endian())
421 .into_audio_caps(crate::AudioLayout::Interleaved);
422 assert!(caps.is_some());
423
424 let caps = crate::AudioFormat::iter_raw()
425 .skip(1000)
426 .into_audio_caps(crate::AudioLayout::Interleaved);
427 assert!(caps.is_none());
428
429 let caps = [crate::AudioFormat::S16le, crate::AudioFormat::S16be]
430 .iter()
431 .into_audio_caps(crate::AudioLayout::Interleaved)
432 .unwrap()
433 .build();
434 assert_eq!(caps.to_string(), "audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved, format=(string){ S16LE, S16BE }");
435 }
436
437 #[test]
438 fn sort() {
439 gst::init().unwrap();
440
441 assert!(
442 crate::AudioFormatInfo::from_format(crate::AudioFormat::F64be)
443 > crate::AudioFormatInfo::from_format(crate::AudioFormat::U8)
444 );
445 assert!(crate::AudioFormat::S20be > crate::AudioFormat::S18be);
446
447 let sorted: Vec<crate::AudioFormat> =
448 crate::AudioFormat::iter_raw().sorted().rev().collect();
449 assert_eq!(
451 sorted,
452 crate::AudioFormat::iter_raw().collect::<Vec<crate::AudioFormat>>()
453 );
454 }
455}