1use std::str;
4
5use crate::ffi;
6use glib::translate::{from_glib, IntoGlib};
7use once_cell::sync::Lazy;
8
9#[cfg(feature = "v1_18")]
17pub static AUDIO_FORMATS_ALL: Lazy<Box<[crate::AudioFormat]>> = Lazy::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: Lazy<Box<[crate::AudioFormat]>> = Lazy::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
235pub struct AudioFormatIterator {
236 idx: usize,
237 len: usize,
238}
239
240impl Default for AudioFormatIterator {
241 fn default() -> Self {
242 Self {
243 idx: 0,
244 len: AUDIO_FORMATS_ALL.len(),
245 }
246 }
247}
248
249impl Iterator for AudioFormatIterator {
250 type Item = crate::AudioFormat;
251
252 fn next(&mut self) -> Option<Self::Item> {
253 if self.idx >= self.len {
254 None
255 } else {
256 let fmt = AUDIO_FORMATS_ALL[self.idx];
257 self.idx += 1;
258 Some(fmt)
259 }
260 }
261
262 fn size_hint(&self) -> (usize, Option<usize>) {
263 let remaining = self.len - self.idx;
264
265 (remaining, Some(remaining))
266 }
267
268 fn count(self) -> usize {
269 self.len - self.idx
270 }
271
272 fn nth(&mut self, n: usize) -> Option<Self::Item> {
273 let (end, overflow) = self.idx.overflowing_add(n);
274 if end >= self.len || overflow {
275 self.idx = self.len;
276 None
277 } else {
278 self.idx = end + 1;
279 Some(AUDIO_FORMATS_ALL[end])
280 }
281 }
282
283 fn last(self) -> Option<Self::Item> {
284 if self.idx == self.len {
285 None
286 } else {
287 Some(AUDIO_FORMATS_ALL[self.len - 1])
288 }
289 }
290}
291
292impl ExactSizeIterator for AudioFormatIterator {}
293
294impl std::iter::FusedIterator for AudioFormatIterator {}
295
296impl DoubleEndedIterator for AudioFormatIterator {
297 fn next_back(&mut self) -> Option<Self::Item> {
298 if self.idx >= self.len {
299 None
300 } else {
301 self.len -= 1;
302 let fmt = AUDIO_FORMATS_ALL[self.len];
303 Some(fmt)
304 }
305 }
306
307 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
308 let (end, overflow) = self.len.overflowing_sub(n);
309 if end <= self.idx || overflow {
310 self.idx = self.len;
311 None
312 } else {
313 self.len = end - 1;
314 let fmt = AUDIO_FORMATS_ALL[self.len];
315 Some(fmt)
316 }
317 }
318}
319pub trait AudioFormatIteratorExt {
320 fn into_audio_caps(
321 self,
322 layout: crate::AudioLayout,
323 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
324}
325
326impl<T> AudioFormatIteratorExt for T
327where
328 T: Iterator<Item = crate::AudioFormat>,
329{
330 fn into_audio_caps(
331 self,
332 layout: crate::AudioLayout,
333 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
334 let formats: Vec<crate::AudioFormat> = self.collect();
335 if !formats.is_empty() {
336 Some(crate::functions::audio_make_raw_caps(&formats, layout))
337 } else {
338 None
339 }
340 }
341}
342
343pub trait AudioFormatIteratorExtRef {
344 fn into_audio_caps(
345 self,
346 layout: crate::AudioLayout,
347 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>>;
348}
349
350impl<'a, T> AudioFormatIteratorExtRef for T
351where
352 T: Iterator<Item = &'a crate::AudioFormat>,
353{
354 fn into_audio_caps(
355 self,
356 layout: crate::AudioLayout,
357 ) -> Option<crate::AudioCapsBuilder<gst::caps::NoFeature>> {
358 let formats: Vec<crate::AudioFormat> = self.copied().collect();
359 if !formats.is_empty() {
360 Some(crate::functions::audio_make_raw_caps(&formats, layout))
361 } else {
362 None
363 }
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use itertools::Itertools;
370
371 #[test]
372 fn test_display() {
373 gst::init().unwrap();
374
375 assert_eq!(format!("{}", crate::AudioFormat::S16be), "S16BE");
376 assert_eq!(format!("{:?}", crate::AudioFormat::S16be), "S16be");
377 }
378
379 #[test]
380 fn iter() {
381 use super::*;
382 gst::init().unwrap();
383
384 assert!(crate::AudioFormat::iter_raw().count() > 0);
385 assert_eq!(
386 crate::AudioFormat::iter_raw().count(),
387 crate::AudioFormat::iter_raw().len()
388 );
389
390 let mut i = crate::AudioFormat::iter_raw();
391 let mut count = 0;
392 loop {
393 if i.next().is_none() {
394 break;
395 }
396 count += 1;
397 if i.next_back().is_none() {
398 break;
399 }
400 count += 1;
401 }
402 assert_eq!(count, crate::AudioFormat::iter_raw().len());
403
404 assert!(crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::F64be));
405 assert!(!crate::AudioFormat::iter_raw().any(|f| f == crate::AudioFormat::Encoded));
406
407 let caps = crate::AudioFormat::iter_raw().into_audio_caps(crate::AudioLayout::Interleaved);
408 assert!(caps.is_some());
409
410 let caps = crate::AudioFormat::iter_raw()
411 .filter(|f| crate::AudioFormatInfo::from_format(*f).is_little_endian())
412 .into_audio_caps(crate::AudioLayout::Interleaved);
413 assert!(caps.is_some());
414
415 let caps = crate::AudioFormat::iter_raw()
416 .skip(1000)
417 .into_audio_caps(crate::AudioLayout::Interleaved);
418 assert!(caps.is_none());
419
420 let caps = [crate::AudioFormat::S16le, crate::AudioFormat::S16be]
421 .iter()
422 .into_audio_caps(crate::AudioLayout::Interleaved)
423 .unwrap()
424 .build();
425 assert_eq!(caps.to_string(), "audio/x-raw, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], layout=(string)interleaved, format=(string){ S16LE, S16BE }");
426 }
427
428 #[test]
429 fn sort() {
430 gst::init().unwrap();
431
432 assert!(
433 crate::AudioFormatInfo::from_format(crate::AudioFormat::F64be)
434 > crate::AudioFormatInfo::from_format(crate::AudioFormat::U8)
435 );
436 assert!(crate::AudioFormat::S20be > crate::AudioFormat::S18be);
437
438 let sorted: Vec<crate::AudioFormat> =
439 crate::AudioFormat::iter_raw().sorted().rev().collect();
440 assert_eq!(
442 sorted,
443 crate::AudioFormat::iter_raw().collect::<Vec<crate::AudioFormat>>()
444 );
445 }
446}