1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ops;
4
5use glib::prelude::*;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct AudioConverterConfig(gst::Structure);
9
10impl ops::Deref for AudioConverterConfig {
11 type Target = gst::StructureRef;
12
13 #[inline]
14 fn deref(&self) -> &gst::StructureRef {
15 self.0.deref()
16 }
17}
18
19impl ops::DerefMut for AudioConverterConfig {
20 #[inline]
21 fn deref_mut(&mut self) -> &mut gst::StructureRef {
22 self.0.deref_mut()
23 }
24}
25
26impl AsRef<gst::StructureRef> for AudioConverterConfig {
27 #[inline]
28 fn as_ref(&self) -> &gst::StructureRef {
29 self.0.as_ref()
30 }
31}
32
33impl AsMut<gst::StructureRef> for AudioConverterConfig {
34 #[inline]
35 fn as_mut(&mut self) -> &mut gst::StructureRef {
36 self.0.as_mut()
37 }
38}
39
40impl Default for AudioConverterConfig {
41 #[inline]
42 fn default() -> Self {
43 Self::new()
44 }
45}
46
47impl TryFrom<gst::Structure> for AudioConverterConfig {
48 type Error = glib::BoolError;
49
50 fn try_from(v: gst::Structure) -> Result<Self, Self::Error> {
51 skip_assert_initialized!();
52 if v.name() == "GstAudioConverter" {
53 Ok(Self(v))
54 } else {
55 Err(glib::bool_error!("Structure is no AudioConverterConfig"))
56 }
57 }
58}
59
60impl<'a> TryFrom<&'a gst::StructureRef> for AudioConverterConfig {
61 type Error = glib::BoolError;
62
63 fn try_from(v: &'a gst::StructureRef) -> Result<Self, Self::Error> {
64 skip_assert_initialized!();
65 Self::try_from(v.to_owned())
66 }
67}
68
69impl From<AudioConverterConfig> for gst::Structure {
70 fn from(v: AudioConverterConfig) -> Self {
71 skip_assert_initialized!();
72 v.0
73 }
74}
75
76impl AudioConverterConfig {
77 pub fn new() -> Self {
78 Self(gst::Structure::new_empty("GstAudioConverter"))
79 }
80
81 pub fn set_dither_method(&mut self, v: crate::AudioDitherMethod) {
82 self.0
83 .set(glib::gstr!("GstAudioConverter.dither-method"), v);
84 }
85
86 #[doc(alias = "get_dither_method")]
87 pub fn dither_method(&self) -> crate::AudioDitherMethod {
88 self.0
89 .get_optional(glib::gstr!("GstAudioConverter.dither-method"))
90 .expect("Wrong type")
91 .unwrap_or(crate::AudioDitherMethod::None)
92 }
93
94 pub fn set_noise_shaping_method(&mut self, v: crate::AudioNoiseShapingMethod) {
95 self.0
96 .set(glib::gstr!("GstAudioConverter.noise-shaping-method"), v);
97 }
98
99 #[doc(alias = "get_noise_shaping_method")]
100 pub fn noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod {
101 self.0
102 .get_optional(glib::gstr!("GstAudioConverter.noise-shaping-method"))
103 .expect("Wrong type")
104 .unwrap_or(crate::AudioNoiseShapingMethod::None)
105 }
106
107 pub fn set_quantization(&mut self, v: u32) {
108 self.0.set(glib::gstr!("GstAudioConverter.quantization"), v);
109 }
110
111 #[doc(alias = "get_quantization")]
112 pub fn quantization(&self) -> u32 {
113 self.0
114 .get_optional(glib::gstr!("GstAudioConverter.quantization"))
115 .expect("Wrong type")
116 .unwrap_or(1)
117 }
118
119 pub fn set_resampler_method(&mut self, v: crate::AudioResamplerMethod) {
120 self.0
121 .set(glib::gstr!("GstAudioConverter.resampler-method"), v);
122 }
123
124 #[doc(alias = "get_resampler_method")]
125 pub fn resampler_method(&self) -> crate::AudioResamplerMethod {
126 self.0
127 .get_optional(glib::gstr!("GstAudioConverter.resampler-method"))
128 .expect("Wrong type")
129 .unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall)
130 }
131
132 pub fn set_mix_matrix(&mut self, v: &[impl AsRef<[f32]>]) {
133 let length = v.get(0).map(|v| v.as_ref().len()).unwrap_or(0);
134 let array = gst::Array::from_values(v.iter().map(|val| {
135 let val = val.as_ref();
136 assert_eq!(val.len(), length);
137 gst::Array::from_values(val.iter().map(|val| val.to_send_value())).to_send_value()
138 }));
139 self.0
140 .set(glib::gstr!("GstAudioConverter.mix-matrix"), array);
141 }
142
143 #[doc(alias = "get_mix_matrix")]
144 pub fn mix_matrix(&self) -> Vec<Vec<f32>> {
145 self.0
146 .get_optional::<gst::Array>(glib::gstr!("GstAudioConverter.mix-matrix"))
147 .expect("Wrong type")
148 .map(|array| {
149 array
150 .as_slice()
151 .iter()
152 .map(|val| {
153 let array = val.get::<gst::Array>().expect("Wrong type");
154
155 array
156 .as_slice()
157 .iter()
158 .map(|val| val.get::<f32>().expect("Wrong type"))
159 .collect::<Vec<_>>()
160 })
161 .collect::<Vec<_>>()
162 })
163 .unwrap_or_default()
164 }
165
166 #[cfg(feature = "v1_22")]
167 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
168 pub fn set_dither_threshold(&mut self, v: u32) {
169 self.0
170 .set(glib::gstr!("GstAudioConverter.dither-threshold"), v);
171 }
172
173 #[cfg(feature = "v1_22")]
174 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
175 #[doc(alias = "get_dither_threshold")]
176 pub fn dither_threshold(&self) -> u32 {
177 self.0
178 .get_optional(glib::gstr!("GstAudioConverter.dither-threshold"))
179 .expect("Wrong type")
180 .unwrap_or(20)
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use super::*;
187
188 #[test]
189 fn test_mix_matrix() {
190 const MATRIX: &[&[f32]] = &[&[1.2, 0.3], &[0.2, 0.8]];
191
192 gst::init().unwrap();
193
194 let mut config = AudioConverterConfig::new();
195 config.set_mix_matrix(MATRIX);
196
197 let matrix = config.mix_matrix();
198 assert_eq!(matrix, MATRIX);
199
200 config.set_mix_matrix(&matrix);
201 }
202}
203