libspa/param/audio/
raw.rs1use crate::param::audio::AudioFormat;
5use crate::pod::{Property, Value, ValueArray};
6use crate::utils::{
7 self,
8 result::{Error, SpaResult, SpaSuccess},
9};
10use std::fmt::Debug;
11
12bitflags::bitflags! {
13 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
14 pub struct AudioInfoRawFlags: u32 {
15 const UNPOSITIONED = 1<<0;
17 }
18}
19
20#[repr(transparent)]
22#[derive(PartialEq, Eq, Clone, Copy)]
23pub struct AudioInfoRaw(spa_sys::spa_audio_info_raw);
24
25impl AudioInfoRaw {
26 pub fn new() -> Self {
27 Self(spa_sys::spa_audio_info_raw {
28 format: AudioFormat::Unknown.as_raw(),
29 flags: AudioInfoRawFlags::UNPOSITIONED.bits(),
30 rate: 0,
31 channels: 0,
32 position: [0; spa_sys::SPA_AUDIO_MAX_CHANNELS as usize],
33 })
34 }
35
36 pub fn set_format(&mut self, format: AudioFormat) {
37 self.0.format = format.as_raw();
38 }
39
40 pub fn format(&self) -> AudioFormat {
41 AudioFormat::from_raw(self.0.format)
42 }
43
44 pub fn set_flags(&mut self, flags: AudioInfoRawFlags) {
45 self.0.flags = flags.bits();
46 }
47
48 pub fn flags(&self) -> AudioInfoRawFlags {
49 AudioInfoRawFlags::from_bits_retain(self.0.flags)
50 }
51
52 pub fn set_rate(&mut self, rate: u32) {
53 self.0.rate = rate;
54 }
55
56 pub fn rate(&self) -> u32 {
57 self.0.rate
58 }
59
60 pub fn set_channels(&mut self, channels: u32) {
61 self.0.channels = channels;
62 }
63
64 pub fn channels(&self) -> u32 {
65 self.0.channels
66 }
67
68 pub fn set_position(&mut self, position: [u32; spa_sys::SPA_AUDIO_MAX_CHANNELS as usize]) {
69 self.0.position = position;
70 if position[0] == 0 {
71 self.0.flags |= AudioInfoRawFlags::UNPOSITIONED.bits();
72 } else {
73 self.0.flags &= AudioInfoRawFlags::UNPOSITIONED.complement().bits();
74 };
75 }
76
77 pub fn position(&self) -> [u32; spa_sys::SPA_AUDIO_MAX_CHANNELS as usize] {
78 self.0.position
79 }
80
81 pub fn parse(&mut self, format: &crate::pod::Pod) -> Result<SpaSuccess, Error> {
83 let res = unsafe { spa_sys::spa_format_audio_raw_parse(format.as_raw_ptr(), &mut self.0) };
84 SpaResult::from_c(res).into_result()
85 }
86
87 pub fn from_raw(raw: spa_sys::spa_audio_info_raw) -> Self {
89 Self(raw)
90 }
91
92 pub fn as_raw(&self) -> spa_sys::spa_audio_info_raw {
94 self.0
95 }
96}
97
98impl Default for AudioInfoRaw {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl From<AudioInfoRaw> for Vec<Property> {
105 fn from(value: AudioInfoRaw) -> Self {
106 let mut props = Vec::with_capacity(6);
107 props.push(Property::new(
108 spa_sys::SPA_FORMAT_mediaType,
109 Value::Id(utils::Id(spa_sys::SPA_MEDIA_TYPE_audio)),
110 ));
111 props.push(Property::new(
112 spa_sys::SPA_FORMAT_mediaSubtype,
113 Value::Id(utils::Id(spa_sys::SPA_MEDIA_SUBTYPE_raw)),
114 ));
115
116 if value.format() != AudioFormat::Unknown {
117 props.push(Property::new(
118 spa_sys::SPA_FORMAT_AUDIO_format,
119 Value::Id(utils::Id(value.format().as_raw())),
120 ));
121 }
122
123 if value.rate() != 0 {
124 props.push(Property::new(
125 spa_sys::SPA_FORMAT_AUDIO_rate,
126 Value::Int(value.rate() as i32),
127 ));
128 }
129
130 if value.channels() != 0 {
131 props.push(Property::new(
132 spa_sys::SPA_FORMAT_AUDIO_channels,
133 Value::Int(value.channels() as i32),
134 ));
135 if !value.flags().contains(AudioInfoRawFlags::UNPOSITIONED) {
136 let array = value.position()[0..value.channels() as usize]
137 .iter()
138 .copied()
139 .map(utils::Id)
140 .collect();
141 props.push(Property::new(
142 spa_sys::SPA_FORMAT_AUDIO_position,
143 Value::ValueArray(ValueArray::Id(array)),
144 ));
145 }
146 }
147
148 props
149 }
150}
151
152impl Debug for AudioInfoRaw {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 f.debug_struct("AudioInfoRaw")
155 .field("format", &self.format())
156 .field("flags", &self.flags())
157 .field("rate", &self.rate())
158 .field("channels", &self.channels())
159 .field("position", &self.position())
160 .finish()
161 }
162}