1use std::ops::{Deref, DerefMut};
2
3use gst::{IdStr, 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 pub fn field_with_static(
158 mut self,
159 property_name: impl AsRef<glib::GStr> + 'static,
160 value: impl Into<glib::Value> + Send,
161 ) -> Self {
162 self.structure.set_with_static(property_name, value);
163 self
164 }
165
166 pub fn field_with_id(
171 mut self,
172 property_name: impl AsRef<IdStr>,
173 value: impl Into<glib::Value> + Send,
174 ) -> Self {
175 self.structure.set_with_id(property_name, value);
176 self
177 }
178
179 gst::impl_builder_gvalue_extra_setters!(field);
180
181 pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
182 self.structure.set_value(property_name, value);
183 self
184 }
185
186 pub fn field_value_with_static(
187 mut self,
188 property_name: impl AsRef<glib::GStr> + 'static,
189 value: glib::SendValue,
190 ) -> Self {
191 self.structure.set_value_with_static(property_name, value);
192 self
193 }
194
195 pub fn field_value_with_id(
196 mut self,
197 property_name: impl AsRef<IdStr>,
198 value: glib::SendValue,
199 ) -> Self {
200 self.structure.set_value_with_id(property_name, value);
201 self
202 }
203
204 pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
205 if let Some(value) = value {
206 self.field_value(property_name, value)
207 } else {
208 self
209 }
210 }
211
212 pub fn field_value_with_static_if_some(
213 self,
214 property_name: impl AsRef<glib::GStr> + 'static,
215 value: Option<glib::SendValue>,
216 ) -> Self {
217 if let Some(value) = value {
218 self.field_value_with_static(property_name, value)
219 } else {
220 self
221 }
222 }
223
224 pub fn field_value_with_id_if_some(
225 self,
226 property_name: impl AsRef<IdStr>,
227 value: Option<glib::SendValue>,
228 ) -> Self {
229 if let Some(value) = value {
230 self.field_value_with_id(property_name, value)
231 } else {
232 self
233 }
234 }
235
236 pub fn build(self) -> ElementProperties {
237 ElementProperties(self.structure)
238 }
239}
240
241#[must_use = "The builder must be built to be used"]
242#[derive(Debug, Clone)]
243pub struct ElementPropertiesMapBuilder {
244 map: Vec<glib::SendValue>,
245}
246
247impl ElementPropertiesMapBuilder {
248 pub fn item(mut self, item: ElementPropertiesMapItem) -> Self {
249 self.map.push(item.into_inner().to_send_value());
250 self
251 }
252
253 pub fn item_if(self, item: ElementPropertiesMapItem, predicate: bool) -> Self {
254 if predicate { self.item(item) } else { self }
255 }
256
257 pub fn item_if_some(self, item: Option<ElementPropertiesMapItem>) -> Self {
258 if let Some(item) = item {
259 self.item(item)
260 } else {
261 self
262 }
263 }
264
265 pub fn build(self) -> ElementProperties {
266 ElementProperties(
267 gst::Structure::builder("element-properties-map")
268 .field("map", gst::List::new(self.map))
269 .build(),
270 )
271 }
272}
273
274#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct ElementPropertiesMapItem(gst::Structure);
294
295impl Deref for ElementPropertiesMapItem {
296 type Target = gst::StructureRef;
297
298 #[inline]
299 fn deref(&self) -> &Self::Target {
300 self.0.as_ref()
301 }
302}
303
304impl DerefMut for ElementPropertiesMapItem {
305 #[inline]
306 fn deref_mut(&mut self) -> &mut Self::Target {
307 self.0.deref_mut()
308 }
309}
310
311impl From<ElementPropertiesMapItem> for gst::Structure {
312 #[inline]
313 fn from(e: ElementPropertiesMapItem) -> Self {
314 skip_assert_initialized!();
315
316 e.into_inner()
317 }
318}
319
320impl ElementPropertiesMapItem {
321 pub fn builder(factory_name: &str) -> ElementPropertiesMapItemBuilder {
322 assert_initialized_main_thread!();
323
324 ElementPropertiesMapItemBuilder {
325 structure: gst::Structure::new_empty(factory_name),
326 }
327 }
328
329 #[inline]
330 pub fn into_inner(self) -> gst::Structure {
331 self.0
332 }
333}
334
335#[must_use = "The builder must be built to be used"]
336#[derive(Debug, Clone)]
337pub struct ElementPropertiesMapItemBuilder {
338 structure: gst::Structure,
339}
340
341impl ElementPropertiesMapItemBuilder {
342 pub fn field(
347 mut self,
348 property_name: impl glib::IntoGStr,
349 value: impl Into<glib::Value> + Send,
350 ) -> Self {
351 self.structure.set(property_name, value);
352 self
353 }
354
355 pub fn field_with_static(
360 mut self,
361 property_name: impl AsRef<glib::GStr> + 'static,
362 value: impl Into<glib::Value> + Send,
363 ) -> Self {
364 self.structure.set_with_static(property_name, value);
365 self
366 }
367
368 pub fn field_with_id(
373 mut self,
374 property_name: impl AsRef<IdStr>,
375 value: impl Into<glib::Value> + Send,
376 ) -> Self {
377 self.structure.set_with_id(property_name, value);
378 self
379 }
380
381 gst::impl_builder_gvalue_extra_setters!(field);
382
383 pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self {
384 self.structure.set_value(property_name, value);
385 self
386 }
387
388 pub fn field_value_with_static(
389 mut self,
390 property_name: impl AsRef<glib::GStr> + 'static,
391 value: glib::SendValue,
392 ) -> Self {
393 self.structure.set_value_with_static(property_name, value);
394 self
395 }
396
397 pub fn field_value_with_id(
398 mut self,
399 property_name: impl AsRef<IdStr>,
400 value: glib::SendValue,
401 ) -> Self {
402 self.structure.set_value_with_id(property_name, value);
403 self
404 }
405
406 pub fn field_value_if_some(self, property_name: &str, value: Option<glib::SendValue>) -> Self {
407 if let Some(value) = value {
408 self.field_value(property_name, value)
409 } else {
410 self
411 }
412 }
413
414 pub fn field_value_with_static_if_some(
415 self,
416 property_name: impl AsRef<glib::GStr> + 'static,
417 value: Option<glib::SendValue>,
418 ) -> Self {
419 if let Some(value) = value {
420 self.field_value_with_static(property_name, value)
421 } else {
422 self
423 }
424 }
425
426 pub fn field_value_with_id_if_some(
427 self,
428 property_name: impl AsRef<IdStr>,
429 value: Option<glib::SendValue>,
430 ) -> Self {
431 if let Some(value) = value {
432 self.field_value_with_id(property_name, value)
433 } else {
434 self
435 }
436 }
437
438 pub fn build(self) -> ElementPropertiesMapItem {
439 ElementPropertiesMapItem(self.structure)
440 }
441}
442
443#[cfg(test)]
444mod test {
445 use super::*;
446 use gst::idstr;
447
448 #[test]
449 fn element_properties_getters() {
450 gst::init().unwrap();
451
452 let elem_props_general = ElementProperties::builder_general()
453 .field("string-prop", "hi")
454 .field("boolean-prop", true)
455 .build();
456 assert!(elem_props_general.is_general());
457 assert!(!elem_props_general.is_map());
458 assert_eq!(elem_props_general.map(), None);
459
460 let elem_factory_props_map = ElementPropertiesMapItem::builder("vp8enc")
461 .field_with_id(idstr!("cq-level"), 13)
462 .field("resize-allowed", false)
463 .build();
464 let elem_props_map = ElementProperties::builder_map()
465 .item(elem_factory_props_map.clone())
466 .build();
467 assert!(elem_props_map.is_map());
468 assert!(!elem_props_map.is_general());
469 assert_eq!(elem_props_map.map(), Some(vec![elem_factory_props_map]));
470 }
471
472 #[test]
473 fn element_properties_general_builder() {
474 gst::init().unwrap();
475
476 let elem_props = ElementProperties::builder_general()
477 .field("string-prop", "hi")
478 .field("boolean-prop", true)
479 .build();
480 assert_eq!(elem_props.n_fields(), 2);
481 assert_eq!(elem_props.name(), "element-properties");
482 assert_eq!(elem_props.get::<String>("string-prop").unwrap(), "hi");
483 assert!(elem_props.get::<bool>("boolean-prop").unwrap());
484 }
485
486 #[test]
487 fn element_properties_map_builder() {
488 gst::init().unwrap();
489
490 let props_map = ElementPropertiesMapItem::builder("vp8enc")
491 .field("cq-level", 13)
492 .field("resize-allowed", false)
493 .build();
494 assert_eq!(props_map.n_fields(), 2);
495 assert_eq!(props_map.name(), "vp8enc");
496 assert_eq!(props_map.get::<i32>("cq-level").unwrap(), 13);
497 assert!(!props_map.get::<bool>("resize-allowed").unwrap());
498
499 let elem_props = ElementProperties::builder_map()
500 .item(props_map.clone())
501 .build();
502 assert_eq!(elem_props.n_fields(), 1);
503
504 let list = elem_props.map().unwrap();
505 assert_eq!(list.len(), 1);
506 assert_eq!(list.first().unwrap(), &props_map);
507 }
508}