gstreamer_pbutils/
element_properties.rs
1use std::ops::{Deref, DerefMut};
2
3use gst::prelude::*;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct ElementProperties(pub(crate) gst::Structure);
34
35impl Default for ElementProperties {
36 fn default() -> Self {
37 Self::builder_general().build()
38 }
39}
40
41impl Deref for ElementProperties {
42 type Target = gst::StructureRef;
43
44 #[inline]
45 fn deref(&self) -> &Self::Target {
46 self.0.as_ref()
47 }
48}
49
50impl From<ElementProperties> for gst::Structure {
51 #[inline]
52 fn from(e: ElementProperties) -> Self {
53 skip_assert_initialized!();
54
55 e.into_inner()
56 }
57}
58
59impl ElementProperties {
60 pub fn builder_general() -> ElementPropertiesGeneralBuilder {
66 assert_initialized_main_thread!();
67
68 ElementPropertiesGeneralBuilder {
69 structure: gst::Structure::new_empty("element-properties"),
70 }
71 }
72
73 pub fn builder_map() -> ElementPropertiesMapBuilder {
82 assert_initialized_main_thread!();
83
84 ElementPropertiesMapBuilder { map: Vec::new() }
85 }
86
87 pub fn is_general(&self) -> bool {
90 let structure_name = self.0.name();
91
92 if structure_name != "element-properties" {
93 debug_assert_eq!(structure_name, "element-properties-map");
94 return false;
95 }
96
97 true
98 }
99
100 pub fn is_map(&self) -> bool {
103 !self.is_general()
104 }
105
106 pub fn map(&self) -> Option<Vec<ElementPropertiesMapItem>> {
110 if !self.is_map() {
111 return None;
112 }
113
114 Some(
115 self.0
116 .get::<gst::List>("map")
117 .unwrap()
118 .as_slice()
119 .iter()
120 .map(|props_map| {
121 ElementPropertiesMapItem(props_map.get::<gst::Structure>().unwrap())
122 })
123 .collect::<Vec<_>>(),
124 )
125 }
126
127 #[inline]
128 pub fn into_inner(self) -> gst::Structure {
129 self.0
130 }
131}
132
133#[must_use = "The builder must be built to be used"]
134#[derive(Debug, Clone)]
135pub struct ElementPropertiesGeneralBuilder {
136 structure: gst::Structure,
137}
138
139impl ElementPropertiesGeneralBuilder {
140 pub fn field(
145 mut self,
146 property_name: impl glib::IntoGStr,
147 value: impl Into<glib::Value> + Send,
148 ) -> Self {
149 self.structure.set(property_name, value);
150 self
151 }
152
153 gst::impl_builder_gvalue_extra_setters!(field);
154
155 pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
156 self.structure.set_value(property_name, value);
157 self
158 }
159
160 pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
161 if let Some(value) = value {
162 self.field_value(property_name, value)
163 } else {
164 self
165 }
166 }
167
168 pub fn build(self) -> ElementProperties {
169 ElementProperties(self.structure)
170 }
171}
172
173#[must_use = "The builder must be built to be used"]
174#[derive(Debug, Clone)]
175pub struct ElementPropertiesMapBuilder {
176 map: Vec<glib::SendValue>,
177}
178
179impl ElementPropertiesMapBuilder {
180 pub fn item(mut self, item: ElementPropertiesMapItem) -> Self {
181 self.map.push(item.into_inner().to_send_value());
182 self
183 }
184
185 pub fn item_if(self, item: ElementPropertiesMapItem, predicate: bool) -> Self {
186 if predicate {
187 self.item(item)
188 } else {
189 self
190 }
191 }
192
193 pub fn item_if_some(self, item: Option<ElementPropertiesMapItem>) -> Self {
194 if let Some(item) = item {
195 self.item(item)
196 } else {
197 self
198 }
199 }
200
201 pub fn build(self) -> ElementProperties {
202 ElementProperties(
203 gst::Structure::builder("element-properties-map")
204 .field("map", gst::List::new(self.map))
205 .build(),
206 )
207 }
208}
209
210#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct ElementPropertiesMapItem(gst::Structure);
230
231impl Deref for ElementPropertiesMapItem {
232 type Target = gst::StructureRef;
233
234 #[inline]
235 fn deref(&self) -> &Self::Target {
236 self.0.as_ref()
237 }
238}
239
240impl DerefMut for ElementPropertiesMapItem {
241 #[inline]
242 fn deref_mut(&mut self) -> &mut Self::Target {
243 self.0.deref_mut()
244 }
245}
246
247impl From<ElementPropertiesMapItem> for gst::Structure {
248 #[inline]
249 fn from(e: ElementPropertiesMapItem) -> Self {
250 skip_assert_initialized!();
251
252 e.into_inner()
253 }
254}
255
256impl ElementPropertiesMapItem {
257 pub fn builder(factory_name: &str) -> ElementPropertiesMapItemBuilder {
258 assert_initialized_main_thread!();
259
260 ElementPropertiesMapItemBuilder {
261 structure: gst::Structure::new_empty(factory_name),
262 }
263 }
264
265 #[inline]
266 pub fn into_inner(self) -> gst::Structure {
267 self.0
268 }
269}
270
271#[must_use = "The builder must be built to be used"]
272#[derive(Debug, Clone)]
273pub struct ElementPropertiesMapItemBuilder {
274 structure: gst::Structure,
275}
276
277impl ElementPropertiesMapItemBuilder {
278 pub fn field(
283 mut self,
284 property_name: impl glib::IntoGStr,
285 value: impl Into<glib::Value> + Send,
286 ) -> Self {
287 self.structure.set(property_name, value);
288 self
289 }
290
291 gst::impl_builder_gvalue_extra_setters!(field);
292
293 pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
294 self.structure.set_value(property_name, value);
295 self
296 }
297
298 pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
299 if let Some(value) = value {
300 self.field_value(property_name, value)
301 } else {
302 self
303 }
304 }
305
306 pub fn build(self) -> ElementPropertiesMapItem {
307 ElementPropertiesMapItem(self.structure)
308 }
309}
310
311#[cfg(test)]
312mod test {
313 use super::*;
314
315 #[test]
316 fn element_properties_getters() {
317 gst::init().unwrap();
318
319 let elem_props_general = ElementProperties::builder_general()
320 .field("string-prop", "hi")
321 .field("boolean-prop", true)
322 .build();
323 assert!(elem_props_general.is_general());
324 assert!(!elem_props_general.is_map());
325 assert_eq!(elem_props_general.map(), None);
326
327 let elem_factory_props_map = ElementPropertiesMapItem::builder("vp8enc")
328 .field("cq-level", 13)
329 .field("resize-allowed", false)
330 .build();
331 let elem_props_map = ElementProperties::builder_map()
332 .item(elem_factory_props_map.clone())
333 .build();
334 assert!(elem_props_map.is_map());
335 assert!(!elem_props_map.is_general());
336 assert_eq!(elem_props_map.map(), Some(vec![elem_factory_props_map]));
337 }
338
339 #[test]
340 fn element_properties_general_builder() {
341 gst::init().unwrap();
342
343 let elem_props = ElementProperties::builder_general()
344 .field("string-prop", "hi")
345 .field("boolean-prop", true)
346 .build();
347 assert_eq!(elem_props.n_fields(), 2);
348 assert_eq!(elem_props.name(), "element-properties");
349 assert_eq!(elem_props.get::<String>("string-prop").unwrap(), "hi");
350 assert!(elem_props.get::<bool>("boolean-prop").unwrap());
351 }
352
353 #[test]
354 fn element_properties_map_builder() {
355 gst::init().unwrap();
356
357 let props_map = ElementPropertiesMapItem::builder("vp8enc")
358 .field("cq-level", 13)
359 .field("resize-allowed", false)
360 .build();
361 assert_eq!(props_map.n_fields(), 2);
362 assert_eq!(props_map.name(), "vp8enc");
363 assert_eq!(props_map.get::<i32>("cq-level").unwrap(), 13);
364 assert!(!props_map.get::<bool>("resize-allowed").unwrap());
365
366 let elem_props = ElementProperties::builder_map()
367 .item(props_map.clone())
368 .build();
369 assert_eq!(elem_props.n_fields(), 1);
370
371 let list = elem_props.map().unwrap();
372 assert_eq!(list.len(), 1);
373 assert_eq!(list.first().unwrap(), &props_map);
374 }
375}