gstreamer-rs/gstreamer/src/pad_template.rs
François Laignel 8527c0e39e Add new setters for collection Value setters in Builders
E.g. (also applies to `property`):

* `field_from_iter()`,
* `field_if_not_empty()`.

Use a macro to factorize implementation & documentation of `field` / `property`
convenience setters.

Also:

* add some `*_if_not_empty` for some iterator based setters.
* add `*_if` for predicate based setters.

Related to https://github.com/gtk-rs/gtk-rs-core/pull/1377

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1431>
2024-06-14 17:00:36 +02:00

199 lines
5.9 KiB
Rust

// Take a look at the license at the top of the repository in the LICENSE file.
use std::ffi::CStr;
use glib::{prelude::*, translate::*};
use crate::{ffi, Caps, PadDirection, PadPresence, PadTemplate, StaticPadTemplate};
impl PadTemplate {
#[doc(alias = "gst_pad_template_new_from_static_pad_template_with_gtype")]
pub fn from_static_pad_template_with_gtype(
pad_template: &StaticPadTemplate,
pad_type: glib::types::Type,
) -> Result<PadTemplate, glib::BoolError> {
skip_assert_initialized!();
unsafe {
Option::<_>::from_glib_none(
ffi::gst_pad_template_new_from_static_pad_template_with_gtype(
mut_override(pad_template.to_glib_none().0),
pad_type.into_glib(),
),
)
.ok_or_else(|| glib::bool_error!("Failed to create PadTemplate"))
}
}
#[doc(alias = "gst_pad_template_get_caps")]
#[doc(alias = "get_caps")]
pub fn caps(&self) -> &Caps {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
&*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
#[doc(alias = "gst_pad_template_get_documentation_caps")]
#[doc(alias = "get_documentation_caps")]
pub fn documentation_caps(&self) -> &Caps {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
if !templ.ABI.abi.documentation_caps.is_null() {
&*(&templ.ABI.abi.documentation_caps as *const *mut ffi::GstCaps as *const Caps)
} else {
&*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
}
}
}
pub fn direction(&self) -> PadDirection {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.direction)
}
}
pub fn gtype(&self) -> glib::types::Type {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.ABI.abi.gtype)
}
}
#[doc(alias = "name-template")]
pub fn name_template(&self) -> &str {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
CStr::from_ptr(templ.name_template).to_str().unwrap()
}
}
pub fn presence(&self) -> PadPresence {
unsafe {
let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
from_glib(templ.presence)
}
}
pub fn builder<'a>(
name_template: &'a str,
direction: PadDirection,
presence: PadPresence,
caps: &'a Caps,
) -> PadTemplateBuilder<'a> {
skip_assert_initialized!();
PadTemplateBuilder {
name_template,
direction,
presence,
caps,
gtype: None,
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
documentation_caps: None,
}
}
}
#[must_use = "The builder must be built to be used"]
#[derive(Debug)]
pub struct PadTemplateBuilder<'a> {
name_template: &'a str,
direction: PadDirection,
presence: PadPresence,
caps: &'a Caps,
gtype: Option<glib::Type>,
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
documentation_caps: Option<&'a Caps>,
}
impl<'a> PadTemplateBuilder<'a> {
pub fn gtype(self, gtype: glib::Type) -> Self {
PadTemplateBuilder {
gtype: Some(gtype),
..self
}
}
pub fn gtype_if(self, gtype: glib::Type, predicate: bool) -> Self {
if predicate {
PadTemplateBuilder {
gtype: Some(gtype),
..self
}
} else {
self
}
}
pub fn gtype_if_some(self, gtype: Option<glib::Type>) -> Self {
if let Some(gtype) = gtype {
self.gtype(gtype)
} else {
self
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
pub fn documentation_caps(self, documentation_caps: &'a Caps) -> Self {
PadTemplateBuilder {
documentation_caps: Some(documentation_caps),
..self
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
pub fn documentation_caps_if(self, documentation_caps: &'a Caps, predicate: bool) -> Self {
if predicate {
PadTemplateBuilder {
documentation_caps: Some(documentation_caps),
..self
}
} else {
self
}
}
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
pub fn documentation_caps_if_some(self, documentation_caps: Option<&'a Caps>) -> Self {
if let Some(documentation_caps) = documentation_caps {
self.documentation_caps(documentation_caps)
} else {
self
}
}
pub fn build(self) -> Result<PadTemplate, glib::BoolError> {
let templ = if let Some(gtype) = self.gtype {
PadTemplate::with_gtype(
self.name_template,
self.direction,
self.presence,
self.caps,
gtype,
)?
} else {
PadTemplate::new(self.name_template, self.direction, self.presence, self.caps)?
};
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
if let Some(documentation_caps) = self.documentation_caps {
unsafe {
ffi::gst_pad_template_set_documentation_caps(
templ.to_glib_none().0,
documentation_caps.to_glib_none().0,
);
}
}
Ok(templ)
}
}