libspa/utils/
mod.rs

1//! Miscellaneous and utility items.
2
3pub mod dict;
4mod direction;
5pub use direction::*;
6pub mod hook;
7pub mod list;
8pub mod result;
9
10use bitflags::bitflags;
11use convert_case::{Case, Casing};
12use std::{ffi::CStr, fmt::Debug, os::raw::c_uint};
13
14pub use spa_sys::spa_fraction as Fraction;
15pub use spa_sys::spa_rectangle as Rectangle;
16
17use crate::pod::CanonicalFixedSizedPod;
18
19/// An enumerated value in a pod
20#[derive(Debug, Copy, Clone, Eq, PartialEq)]
21pub struct Id(pub u32);
22
23/// A file descriptor in a pod
24#[derive(Debug, Copy, Clone, Eq, PartialEq)]
25#[repr(transparent)]
26pub struct Fd(pub i64);
27
28#[derive(Debug, Eq, PartialEq, Clone)]
29/// the flags and choice of a choice pod.
30pub struct Choice<T: CanonicalFixedSizedPod>(pub ChoiceFlags, pub ChoiceEnum<T>);
31
32bitflags! {
33    /// [`Choice`] flags
34    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
35    pub struct ChoiceFlags: u32 {
36        // no flags defined yet but we need at least one to keep bitflags! happy
37        #[doc(hidden)]
38        const _FAKE = 1;
39    }
40}
41
42#[derive(Debug, PartialEq, Eq, Clone)]
43/// a choice in a pod.
44pub enum ChoiceEnum<T: CanonicalFixedSizedPod> {
45    /// no choice.
46    None(T),
47    /// range.
48    Range {
49        /// default value.
50        default: T,
51        /// minimum value.
52        min: T,
53        /// maximum value.
54        max: T,
55    },
56    /// range with step.
57    Step {
58        /// default value.
59        default: T,
60        /// minimum value.
61        min: T,
62        /// maximum value.
63        max: T,
64        /// step.
65        step: T,
66    },
67    /// list.
68    Enum {
69        /// default value.
70        default: T,
71        /// alternative values.
72        alternatives: Vec<T>,
73    },
74    /// flags.
75    Flags {
76        /// default value.
77        default: T,
78        /// possible flags.
79        flags: Vec<T>,
80    },
81}
82
83#[derive(Copy, Clone, PartialEq, Eq)]
84pub struct SpaTypes(pub c_uint);
85
86#[allow(non_upper_case_globals)]
87impl SpaTypes {
88    /* Basic types */
89    pub const None: Self = Self(spa_sys::SPA_TYPE_None);
90    pub const Bool: Self = Self(spa_sys::SPA_TYPE_Bool);
91    pub const Id: Self = Self(spa_sys::SPA_TYPE_Id);
92    pub const Int: Self = Self(spa_sys::SPA_TYPE_Int);
93    pub const Long: Self = Self(spa_sys::SPA_TYPE_Long);
94    pub const Float: Self = Self(spa_sys::SPA_TYPE_Float);
95    pub const Double: Self = Self(spa_sys::SPA_TYPE_Double);
96    pub const String: Self = Self(spa_sys::SPA_TYPE_String);
97    pub const Bytes: Self = Self(spa_sys::SPA_TYPE_Bytes);
98    pub const Rectangle: Self = Self(spa_sys::SPA_TYPE_Rectangle);
99    pub const Fraction: Self = Self(spa_sys::SPA_TYPE_Fraction);
100    pub const Bitmap: Self = Self(spa_sys::SPA_TYPE_Bitmap);
101    pub const Array: Self = Self(spa_sys::SPA_TYPE_Array);
102    pub const Struct: Self = Self(spa_sys::SPA_TYPE_Struct);
103    pub const Object: Self = Self(spa_sys::SPA_TYPE_Object);
104    pub const Sequence: Self = Self(spa_sys::SPA_TYPE_Sequence);
105    pub const Pointer: Self = Self(spa_sys::SPA_TYPE_Pointer);
106    pub const Fd: Self = Self(spa_sys::SPA_TYPE_Fd);
107    pub const Choice: Self = Self(spa_sys::SPA_TYPE_Choice);
108    pub const Pod: Self = Self(spa_sys::SPA_TYPE_Pod);
109
110    /* Pointers */
111    pub const PointerBuffer: Self = Self(spa_sys::SPA_TYPE_POINTER_Buffer);
112    pub const PointerMeta: Self = Self(spa_sys::SPA_TYPE_POINTER_Meta);
113    pub const PointerDict: Self = Self(spa_sys::SPA_TYPE_POINTER_Dict);
114
115    /* Events */
116    pub const EventDevice: Self = Self(spa_sys::SPA_TYPE_EVENT_Device);
117    pub const EventNode: Self = Self(spa_sys::SPA_TYPE_EVENT_Node);
118
119    /* Commands */
120    pub const CommandDevice: Self = Self(spa_sys::SPA_TYPE_COMMAND_Device);
121    pub const CommandNode: Self = Self(spa_sys::SPA_TYPE_COMMAND_Node);
122
123    /* Objects */
124    pub const ObjectParamPropInfo: Self = Self(spa_sys::SPA_TYPE_OBJECT_PropInfo);
125    pub const ObjectParamProps: Self = Self(spa_sys::SPA_TYPE_OBJECT_Props);
126    pub const ObjectParamFormat: Self = Self(spa_sys::SPA_TYPE_OBJECT_Format);
127    pub const ObjectParamBuffers: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamBuffers);
128    pub const ObjectParamMeta: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamMeta);
129    pub const ObjectParamIO: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamIO);
130    pub const ObjectParamProfile: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamProfile);
131    pub const ObjectParamPortConfig: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamPortConfig);
132    pub const ObjectParamRoute: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamRoute);
133    pub const ObjectProfiler: Self = Self(spa_sys::SPA_TYPE_OBJECT_Profiler);
134    pub const ObjectParamLatency: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamLatency);
135    pub const ObjectParamProcessLatency: Self = Self(spa_sys::SPA_TYPE_OBJECT_ParamProcessLatency);
136
137    /* vendor extensions */
138    pub const VendorPipeWire: Self = Self(spa_sys::SPA_TYPE_VENDOR_PipeWire);
139
140    pub const VendorOther: Self = Self(spa_sys::SPA_TYPE_VENDOR_Other);
141
142    /// Obtain a [`SpaTypes`] from a raw `c_uint` variant.
143    pub fn from_raw(raw: c_uint) -> Self {
144        Self(raw)
145    }
146
147    /// Get the raw [`c_uint`] representing this `SpaTypes`.
148    pub fn as_raw(&self) -> c_uint {
149        self.0
150    }
151}
152
153impl Debug for SpaTypes {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        match *self {
156            SpaTypes::VendorPipeWire => f.write_str("SpaTypes::VendorPipeWire"),
157            SpaTypes::VendorOther => f.write_str("SpaTypes::VendorOther"),
158            _ => {
159                let c_str = unsafe {
160                    let c_buf =
161                        spa_sys::spa_debug_type_find_name(spa_sys::spa_types, self.as_raw());
162                    if c_buf.is_null() {
163                        return f.write_str("Unknown");
164                    }
165                    CStr::from_ptr(c_buf)
166                };
167                let name = format!(
168                    "SpaTypes::{}",
169                    c_str
170                        .to_string_lossy()
171                        .replace("Spa:Pointer", "Pointer")
172                        .replace("Spa:Pod:Object:Event", "Event")
173                        .replace("Spa:Pod:Object:Command", "Command")
174                        .replace("Spa:Pod:Object", "Object")
175                        .replace("Spa:Pod:", "")
176                        .replace("Spa:", "")
177                        .replace(':', " ")
178                        .to_case(Case::Pascal)
179                );
180                f.write_str(&name)
181            }
182        }
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189
190    #[test]
191    #[cfg_attr(miri, ignore)]
192    fn debug_format() {
193        assert_eq!("SpaTypes::None", format!("{:?}", SpaTypes::None));
194        assert_eq!(
195            "SpaTypes::PointerBuffer",
196            format!("{:?}", SpaTypes::PointerBuffer)
197        );
198        assert_eq!(
199            "SpaTypes::EventDevice",
200            format!("{:?}", SpaTypes::EventDevice)
201        );
202        assert_eq!(
203            "SpaTypes::CommandDevice",
204            format!("{:?}", SpaTypes::CommandDevice)
205        );
206        assert_eq!(
207            "SpaTypes::ObjectParamPropInfo",
208            format!("{:?}", SpaTypes::ObjectParamPropInfo)
209        );
210        assert_eq!(
211            "SpaTypes::ObjectProfiler",
212            format!("{:?}", SpaTypes::ObjectProfiler)
213        );
214        assert_eq!(
215            "SpaTypes::ObjectParamProcessLatency",
216            format!("{:?}", SpaTypes::ObjectParamProcessLatency)
217        );
218        assert_eq!(
219            "SpaTypes::VendorPipeWire",
220            format!("{:?}", SpaTypes::VendorPipeWire)
221        );
222        assert_eq!(
223            "SpaTypes::VendorOther",
224            format!("{:?}", SpaTypes::VendorOther)
225        );
226    }
227}