libspa/param/audio/
mod.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4mod raw;
5pub use raw::*;
6
7use std::ffi::CStr;
8use std::fmt::Debug;
9use std::ops::Range;
10
11pub const MAX_CHANNELS: usize = spa_sys::SPA_AUDIO_MAX_CHANNELS as usize;
12
13#[repr(transparent)]
14#[derive(PartialEq, PartialOrd, Eq, Clone, Copy)]
15pub struct AudioFormat(pub spa_sys::spa_audio_format);
16
17#[allow(non_upper_case_globals)]
18impl AudioFormat {
19    pub const Unknown: Self = Self(spa_sys::SPA_AUDIO_FORMAT_UNKNOWN);
20    pub const Encoded: Self = Self(spa_sys::SPA_AUDIO_FORMAT_ENCODED);
21    pub const S8: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S8);
22    pub const U8: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U8);
23    pub const S16LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16_LE);
24    pub const S16BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16_BE);
25    pub const U16LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U16_LE);
26    pub const U16BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U16_BE);
27    pub const S24_32LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_32_LE);
28    pub const S24_32BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_32_BE);
29    pub const U24_32LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24_32_LE);
30    pub const U24_32BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24_32_BE);
31    pub const S32LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S32_LE);
32    pub const S32BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S32_BE);
33    pub const U32LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U32_LE);
34    pub const U32BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U32_BE);
35    pub const S24LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_LE);
36    pub const S24BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_BE);
37    pub const U24LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24_LE);
38    pub const U24BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24_BE);
39    pub const S20LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S20_LE);
40    pub const S20BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S20_BE);
41    pub const U20LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U20_LE);
42    pub const U20BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U20_BE);
43    pub const S18LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S18_LE);
44    pub const S18BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S18_BE);
45    pub const U18LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U18_LE);
46    pub const U18BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U18_BE);
47    pub const F32LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F32_LE);
48    pub const F32BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F32_BE);
49    pub const F64LE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F64_LE);
50    pub const F64BE: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F64_BE);
51    pub const ULAW: Self = Self(spa_sys::SPA_AUDIO_FORMAT_ULAW);
52    pub const ALAW: Self = Self(spa_sys::SPA_AUDIO_FORMAT_ALAW);
53
54    pub const S16: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16);
55    pub const U16: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U16);
56    pub const S18: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S18);
57    pub const U18: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U18);
58    pub const S20: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S20);
59    pub const U20: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U20);
60    pub const S24: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24);
61    pub const U24: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U24);
62    pub const S32: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S32);
63    pub const U32: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U32);
64
65    pub const U8P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_U8P);
66    pub const S16P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S16P);
67    pub const S24_32P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24_32P);
68    pub const S32P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S32P);
69    pub const S24P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S24P);
70    pub const F32P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F32P);
71    pub const F64P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_F64P);
72    pub const S8P: Self = Self(spa_sys::SPA_AUDIO_FORMAT_S8P);
73
74    const INTERLEAVED_RANGE: Range<Self> = Self::S8..Self(spa_sys::SPA_AUDIO_FORMAT_START_Planar);
75    const PLANAR_RANGE: Range<Self> = Self::U8P..Self(spa_sys::SPA_AUDIO_FORMAT_START_Other);
76
77    pub fn is_interleaved(&self) -> bool {
78        Self::INTERLEAVED_RANGE.contains(self)
79    }
80
81    pub fn is_planar(&self) -> bool {
82        Self::PLANAR_RANGE.contains(self)
83    }
84
85    /// Obtain an [`AudioFormat`] from a raw `spa_audio_format` variant.
86    pub fn from_raw(raw: spa_sys::spa_audio_format) -> Self {
87        Self(raw)
88    }
89
90    /// Get the raw [`spa_sys::spa_audio_format`] representing this `AudioFormat`.
91    pub fn as_raw(&self) -> spa_sys::spa_audio_format {
92        self.0
93    }
94}
95
96impl Debug for AudioFormat {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match *self {
99            AudioFormat::Unknown => f.write_str("AudioFormat::Unknown"),
100            AudioFormat::Encoded => f.write_str("AudioFormat::Encoded"),
101            _ => {
102                let c_str = unsafe {
103                    let c_buf = spa_sys::spa_debug_type_find_short_name(
104                        spa_sys::spa_type_audio_format,
105                        self.as_raw(),
106                    );
107                    if c_buf.is_null() {
108                        return f.write_str("Unsupported");
109                    }
110                    CStr::from_ptr(c_buf)
111                };
112                let name = format!("AudioFormat::{}", c_str.to_str().unwrap());
113                f.write_str(&name)
114            }
115        }
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    #[cfg_attr(miri, ignore)]
125    fn debug_format() {
126        assert_eq!(
127            "AudioFormat::Unknown",
128            format!("{:?}", AudioFormat::Unknown)
129        );
130        assert_eq!(
131            "AudioFormat::S24_32LE",
132            format!("{:?}", AudioFormat::S24_32LE)
133        );
134    }
135}