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