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
206#[cfg(target_endian = "little")]
207pub const AUDIO_FORMAT_S16: crate::AudioFormat = crate::AudioFormat::S16le;
208#[cfg(target_endian = "little")]
209pub const AUDIO_FORMAT_U16: crate::AudioFormat = crate::AudioFormat::U16le;
210#[cfg(target_endian = "little")]
211pub const AUDIO_FORMAT_S2432: crate::AudioFormat = crate::AudioFormat::S2432le;
212#[cfg(target_endian = "little")]
213pub const AUDIO_FORMAT_U2432: crate::AudioFormat = crate::AudioFormat::U2432le;
214#[cfg(target_endian = "little")]
215pub const AUDIO_FORMAT_S32: crate::AudioFormat = crate::AudioFormat::S32le;
216#[cfg(target_endian = "little")]
217pub const AUDIO_FORMAT_U32: crate::AudioFormat = crate::AudioFormat::U32le;
218#[cfg(target_endian = "little")]
219pub const AUDIO_FORMAT_S24: crate::AudioFormat = crate::AudioFormat::S24le;
220#[cfg(target_endian = "little")]
221pub const AUDIO_FORMAT_U24: crate::AudioFormat = crate::AudioFormat::U24le;
222#[cfg(target_endian = "little")]
223pub const AUDIO_FORMAT_S20: crate::AudioFormat = crate::AudioFormat::S20le;
224#[cfg(target_endian = "little")]
225pub const AUDIO_FORMAT_U20: crate::AudioFormat = crate::AudioFormat::U20le;
226#[cfg(target_endian = "little")]
227pub const AUDIO_FORMAT_S18: crate::AudioFormat = crate::AudioFormat::S18le;
228#[cfg(target_endian = "little")]
229pub const AUDIO_FORMAT_U18: crate::AudioFormat = crate::AudioFormat::U18le;
230#[cfg(target_endian = "little")]
231pub const AUDIO_FORMAT_F32: crate::AudioFormat = crate::AudioFormat::F32le;
232#[cfg(target_endian = "little")]
233pub const AUDIO_FORMAT_F64: crate::AudioFormat = crate::AudioFormat::F64le;
234
235#[must_use = "iterators are lazy and do nothing unless consumed"]
236pub struct AudioFormatIterator {
237 idx: usize,
238 len: usize,
239}
240
241impl Default for AudioFormatIterator {
242 fn default() -> Self {
243 Self {
244 idx: 0,
245 len: AUDIO_FORMATS_ALL.len(),
246 }
247 }
248}
249
250impl Iterator for AudioFormatIterator {
251 type Item = crate::AudioFormat;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 if self.idx >= self.len {
255 None
256 } else {
257 let fmt = AUDIO_FORMATS_ALL[self.idx];
258 self.idx += 1;
259 Some(fmt)
260 }
261 }
262
263 fn size_hint(&self) -> (usize, Option<usize>) {
264 let remaining = self.len - self.idx;
265
266 (remaining, Some(remaining))
267 }
268
269 fn count(self) -> usize {
270 self.len - self.idx
271 }
272
273 fn nth(&mut self, n: usize) -> Option<Self::Item> {
274 let (end, overflow) = self.idx.overflowing_add(n);
275 if end >= self.len || overflow {
276 self.idx = self.len;
277 None
278 } else {
279 self.idx = end + 1;
280 Some(AUDIO_FORMATS_ALL[end])
281 }
282 }
283
284 fn last(self) -> Option<Self::Item> {
285 if self.idx == self.len {
286 None
287 } else {
288 Some(AUDIO_FORMATS_ALL[self.len - 1])
289 }
290 }
291}
292
293impl ExactSizeIterator for AudioFormatIterator {}
294
295impl std::iter::FusedIterator for AudioFormatIterator {}
296
297impl DoubleEndedIterator for AudioFormatIterator {
298 fn next_back(&mut self) -> Option<Self::Item> {
299 if self.idx >= self.len {
300 None
301 } else {
302 self.len -= 1;
303 let fmt = AUDIO_FORMATS_ALL[self.len];
304 Some(fmt)
305 }
306 }
307
308 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
309 let (end, overflow) = self.len.overflowing_sub(n);
310 if end <= self.idx || overflow {
311 self.idx = self.len;
312 None
313 } else {
314 self.len = end - 1;
315 let fmt = AUDIO_FORMATS_ALL[self.len];
316 Some(fmt)
317 }
318 }
319}
320pub trait AudioFormatIteratorExt {
321 fn into_audio_caps(
322 self,
323 layout: crate::AudioLayout,
324 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
325}
326
327impl<T> AudioFormatIteratorExt for T
328where
329 T: Iterator<Item = crate::AudioFormat>,
330{
331 fn into_audio_caps(
332 self,
333 layout: crate::AudioLayout,
334 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
335 let formats: Vec<crate::AudioFormat> = self.collect();
336 if !formats.is_empty() {
337 Some(crate::functions::audio_make_raw_caps(&formats, layout))
338 } else {
339 None
340 }
341 }
342}
343
344pub trait AudioFormatIteratorExtRef {
345 fn into_audio_caps(
346 self,
347 layout: crate::AudioLayout,
348 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
349}
350
351impl<'a, T> AudioFormatIteratorExtRef for T
352where
353 T: Iterator<Item = &'a crate::AudioFormat>,
354{
355 fn into_audio_caps(
356 self,
357 layout: crate::AudioLayout,
358 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
359 let formats: Vec<crate::AudioFormat> = self.copied().collect();
360 if !formats.is_empty() {
361 Some(crate::functions::audio_make_raw_caps(&formats, layout))
362 } else {
363 None
364 }
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use itertools::Itertools;
371
372 #[test]
373 fn test_display() {
374 gst::init().unwrap();
375
376 assert_eq!(format!("{}", crate::AudioFormat::S16be), "S16BE");
377 assert_eq!(format!("{:?}", crate::AudioFormat::S16be), "S16be");
378 }
379
380 #[test]
381 fn iter() {
382 use super::*;
383 gst::init().unwrap();
384
385 assert!(crate::AudioFormat::iter_raw().count() > 0);
386 assert_eq!(
387 crate::AudioFormat::iter_raw().count(),
388 crate::AudioFormat::iter_raw().len()
389 );
390
391 let mut i = crate::AudioFormat::iter_raw();
392 let mut count = 0;
393 loop {
394 if i.next().is_none() {
395 break;
396 }
397 count += 1;
398 if i.next_back().is_none() {
399 break;
400 }
401 count += 1;
402 }
403 assert_eq!(count, crate::AudioFormat::iter_raw().len());
404
405 assert!(crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::F64be));
406 assert!(!crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::Encoded));
407
408 let caps = crate::AudioFormat::iter_raw().into_audio_caps(crate::AudioLayout::Interleaved);
409 assert!(caps.is_some());
410
411 let caps = crate::AudioFormat::iter_raw()
412 .filter(|f| crate::AudioFormatInfo::from_format(*f).is_little_endian())
413 .into_audio_caps(crate::AudioLayout::Interleaved);
414 assert!(caps.is_some());
415
416 let caps = crate::AudioFormat::iter_raw()
417 .skip(1000)
418 .into_audio_caps(crate::AudioLayout::Interleaved);
419 assert!(caps.is_none());
420
421 let caps = [crate::AudioFormat::S16le, crate::AudioFormat::S16be]
422 .iter()
423 .into_audio_caps(crate::AudioLayout::Interleaved)
424 .unwrap()
425 .build();
426 assert_eq!(caps.to_string(), "audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved, format=(string){ S16LE, S16BE }");
427 }
428
429 #[test]
430 fn sort() {
431 gst::init().unwrap();
432
433 assert!(
434 crate::AudioFormatInfo::from_format(crate::AudioFormat::F64be)
435 > crate::AudioFormatInfo::from_format(crate::AudioFormat::U8)
436 );
437 assert!(crate::AudioFormat::S20be > crate::AudioFormat::S18be);
438
439 let sorted: Vec<crate::AudioFormat> =
440 crate::AudioFormat::iter_raw().sorted().rev().collect();
441 assert_eq!(
443 sorted,
444 crate::AudioFormat::iter_raw().collect::<Vec<crate::AudioFormat>>()
445 );
446 }
447}