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