diff --git a/gstreamer-pbutils/src/element_properties.rs b/gstreamer-pbutils/src/element_properties.rs index dfe82ae43..82f01c0b3 100644 --- a/gstreamer-pbutils/src/element_properties.rs +++ b/gstreamer-pbutils/src/element_properties.rs @@ -1,6 +1,6 @@ use gst::prelude::*; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; // rustdoc-stripper-ignore-next /// Wrapper around `gst::Structure` for `element-properties` @@ -17,11 +17,11 @@ use std::ops::Deref; /// ``` /// /// ```rust -/// # use gstreamer_pbutils::ElementProperties; +/// # use gstreamer_pbutils::{ElementProperties, ElementPropertiesMapItem}; /// # gst::init().unwrap(); /// ElementProperties::builder_map() /// .item( -/// gst::Structure::builder("vp8enc") +/// ElementPropertiesMapItem::builder("vp8enc") /// .field("max-quantizer", 17) /// .field("buffer-size", 20000) /// .field("threads", 16) @@ -41,7 +41,7 @@ impl Default for ElementProperties { impl Deref for ElementProperties { type Target = gst::StructureRef; - fn deref(&self) -> &gst::StructureRef { + fn deref(&self) -> &Self::Target { self.0.as_ref() } } @@ -102,9 +102,9 @@ impl ElementProperties { } // rustdoc-stripper-ignore-next - /// Returns the inner list of `gst::Structure` if self is_general() - /// or `None` if self is_map(). - pub fn map(&self) -> Option> { + /// Returns the inner vec of `ElementPropertiesMapItem` if self is_map() + /// or `None` if self is_general(). + pub fn map(&self) -> Option> { if !self.is_map() { return None; } @@ -115,7 +115,9 @@ impl ElementProperties { .unwrap() .as_slice() .iter() - .map(|props_map| props_map.get::().unwrap()) + .map(|props_map| { + ElementPropertiesMapItem(props_map.get::().unwrap()) + }) .collect::>(), ) } @@ -140,6 +142,11 @@ impl ElementPropertiesGeneralBuilder { self } + pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self { + self.structure.set_value(property_name, value); + self + } + pub fn build(self) -> ElementProperties { ElementProperties(self.structure) } @@ -152,13 +159,8 @@ pub struct ElementPropertiesMapBuilder { } impl ElementPropertiesMapBuilder { - // rustdoc-stripper-ignore-next - /// Insert a new `element-properties-map` map item. - /// - /// The `structure`s name is the element factory's name - /// and each field corresponds to a property-value pair. - pub fn item(mut self, structure: gst::Structure) -> Self { - self.map.push(structure.to_send_value()); + pub fn item(mut self, item: ElementPropertiesMapItem) -> Self { + self.map.push(item.into_inner().to_send_value()); self } @@ -171,6 +173,88 @@ impl ElementPropertiesMapBuilder { } } +// rustdoc-stripper-ignore-next +/// Wrapper around `gst::Structure` for `element-properties-map` map item. +/// +/// # Examples +/// +/// ```rust +/// # use gstreamer_pbutils::{ElementProperties, ElementPropertiesMapItem}; +/// # gst::init().unwrap(); +/// ElementProperties::builder_map() +/// .item( +/// ElementPropertiesMapItem::builder("vp8enc") +/// .field("max-quantizer", 17) +/// .field("buffer-size", 20000) +/// .field("threads", 16) +/// .build(), +/// ) +/// .build(); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ElementPropertiesMapItem(gst::Structure); + +impl Deref for ElementPropertiesMapItem { + type Target = gst::StructureRef; + + fn deref(&self) -> &Self::Target { + self.0.as_ref() + } +} + +impl DerefMut for ElementPropertiesMapItem { + fn deref_mut(&mut self) -> &mut Self::Target { + self.0.deref_mut() + } +} + +impl From for gst::Structure { + fn from(e: ElementPropertiesMapItem) -> Self { + skip_assert_initialized!(); + + e.into_inner() + } +} + +impl ElementPropertiesMapItem { + pub fn builder(factory_name: &str) -> ElementPropertiesMapItemBuilder { + assert_initialized_main_thread!(); + + ElementPropertiesMapItemBuilder { + structure: gst::Structure::new_empty(factory_name), + } + } + + pub fn into_inner(self) -> gst::Structure { + self.0 + } +} + +#[must_use = "The builder must be built to be used"] +#[derive(Debug, Clone)] +pub struct ElementPropertiesMapItemBuilder { + structure: gst::Structure, +} + +impl ElementPropertiesMapItemBuilder { + pub fn field(mut self, property_name: &str, value: T) -> Self + where + T: ToSendValue + Sync, + { + self.structure.set(property_name, value); + self + } + + pub fn field_value(mut self, property_name: &str, value: glib::SendValue) -> Self { + self.structure.set_value(property_name, value); + self + } + + pub fn build(self) -> ElementPropertiesMapItem { + ElementPropertiesMapItem(self.structure) + } +} + #[cfg(test)] mod test { use super::*; @@ -187,7 +271,7 @@ mod test { assert!(!elem_props_general.is_map()); assert_eq!(elem_props_general.map(), None); - let elem_factory_props_map = gst::Structure::builder("vp8enc") + let elem_factory_props_map = ElementPropertiesMapItem::builder("vp8enc") .field("cq-level", 13) .field("resize-allowed", false) .build(); @@ -217,7 +301,7 @@ mod test { fn element_properties_map_builder() { gst::init().unwrap(); - let props_map = gst::Structure::builder("vp8enc") + let props_map = ElementPropertiesMapItem::builder("vp8enc") .field("cq-level", 13) .field("resize-allowed", false) .build(); diff --git a/gstreamer-pbutils/src/lib.rs b/gstreamer-pbutils/src/lib.rs index 7ab801a08..647104275 100644 --- a/gstreamer-pbutils/src/lib.rs +++ b/gstreamer-pbutils/src/lib.rs @@ -46,7 +46,7 @@ pub use crate::auto::*; #[cfg(feature = "v1_20")] mod element_properties; #[cfg(feature = "v1_20")] -pub use crate::element_properties::ElementProperties; +pub use crate::element_properties::{ElementProperties, ElementPropertiesMapItem}; #[cfg(feature = "serde")] mod flag_serde;