gstreamer/
pad_template.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ffi::CStr;
4
5use glib::{prelude::*, translate::*};
6
7use crate::{ffi, Caps, PadDirection, PadPresence, PadTemplate, StaticPadTemplate};
8
9impl PadTemplate {
10    /// Converts a [`StaticPadTemplate`][crate::StaticPadTemplate] into a [`PadTemplate`][crate::PadTemplate] with a type.
11    /// ## `pad_template`
12    /// the static pad template
13    /// ## `pad_type`
14    /// The `GType` of the pad to create
15    ///
16    /// # Returns
17    ///
18    /// a new [`PadTemplate`][crate::PadTemplate].
19    #[doc(alias = "gst_pad_template_new_from_static_pad_template_with_gtype")]
20    pub fn from_static_pad_template_with_gtype(
21        pad_template: &StaticPadTemplate,
22        pad_type: glib::types::Type,
23    ) -> Result<PadTemplate, glib::BoolError> {
24        skip_assert_initialized!();
25        unsafe {
26            Option::<_>::from_glib_none(
27                ffi::gst_pad_template_new_from_static_pad_template_with_gtype(
28                    mut_override(pad_template.to_glib_none().0),
29                    pad_type.into_glib(),
30                ),
31            )
32            .ok_or_else(|| glib::bool_error!("Failed to create PadTemplate"))
33        }
34    }
35
36    /// Gets the capabilities of the pad template.
37    ///
38    /// # Returns
39    ///
40    /// the [`Caps`][crate::Caps] of the pad template.
41    /// Unref after usage.
42    #[doc(alias = "gst_pad_template_get_caps")]
43    #[doc(alias = "get_caps")]
44    pub fn caps(&self) -> &Caps {
45        unsafe {
46            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
47            &*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
48        }
49    }
50
51    /// See [`set_documentation_caps()`][Self::set_documentation_caps()].
52    ///
53    /// # Returns
54    ///
55    /// The caps to document. For convenience, this will return
56    ///  [`caps()`][Self::caps()] when no documentation caps were set.
57    #[cfg(feature = "v1_18")]
58    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
59    #[doc(alias = "gst_pad_template_get_documentation_caps")]
60    #[doc(alias = "get_documentation_caps")]
61    pub fn documentation_caps(&self) -> &Caps {
62        unsafe {
63            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
64            if !templ.ABI.abi.documentation_caps.is_null() {
65                &*(&templ.ABI.abi.documentation_caps as *const *mut ffi::GstCaps as *const Caps)
66            } else {
67                &*(&templ.caps as *const *mut ffi::GstCaps as *const Caps)
68            }
69        }
70    }
71
72    pub fn direction(&self) -> PadDirection {
73        unsafe {
74            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
75            from_glib(templ.direction)
76        }
77    }
78
79    pub fn gtype(&self) -> glib::types::Type {
80        unsafe {
81            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
82            from_glib(templ.ABI.abi.gtype)
83        }
84    }
85
86    #[doc(alias = "name-template")]
87    pub fn name_template(&self) -> &str {
88        unsafe {
89            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
90            CStr::from_ptr(templ.name_template).to_str().unwrap()
91        }
92    }
93
94    pub fn presence(&self) -> PadPresence {
95        unsafe {
96            let templ = &*(self.as_ptr() as *const ffi::GstPadTemplate);
97            from_glib(templ.presence)
98        }
99    }
100
101    pub fn builder<'a>(
102        name_template: &'a str,
103        direction: PadDirection,
104        presence: PadPresence,
105        caps: &'a Caps,
106    ) -> PadTemplateBuilder<'a> {
107        skip_assert_initialized!();
108
109        PadTemplateBuilder {
110            name_template,
111            direction,
112            presence,
113            caps,
114            gtype: None,
115            #[cfg(feature = "v1_18")]
116            #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
117            documentation_caps: None,
118        }
119    }
120}
121
122#[must_use = "The builder must be built to be used"]
123#[derive(Debug)]
124pub struct PadTemplateBuilder<'a> {
125    name_template: &'a str,
126    direction: PadDirection,
127    presence: PadPresence,
128    caps: &'a Caps,
129    gtype: Option<glib::Type>,
130    #[cfg(feature = "v1_18")]
131    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
132    documentation_caps: Option<&'a Caps>,
133}
134
135#[allow(clippy::needless_lifetimes)]
136impl<'a> PadTemplateBuilder<'a> {
137    pub fn gtype(self, gtype: glib::Type) -> Self {
138        PadTemplateBuilder {
139            gtype: Some(gtype),
140            ..self
141        }
142    }
143
144    pub fn gtype_if(self, gtype: glib::Type, predicate: bool) -> Self {
145        if predicate {
146            PadTemplateBuilder {
147                gtype: Some(gtype),
148                ..self
149            }
150        } else {
151            self
152        }
153    }
154
155    pub fn gtype_if_some(self, gtype: Option<glib::Type>) -> Self {
156        if let Some(gtype) = gtype {
157            self.gtype(gtype)
158        } else {
159            self
160        }
161    }
162
163    #[cfg(feature = "v1_18")]
164    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
165    pub fn documentation_caps(self, documentation_caps: &'a Caps) -> Self {
166        PadTemplateBuilder {
167            documentation_caps: Some(documentation_caps),
168            ..self
169        }
170    }
171
172    #[cfg(feature = "v1_18")]
173    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
174    pub fn documentation_caps_if(self, documentation_caps: &'a Caps, predicate: bool) -> Self {
175        if predicate {
176            PadTemplateBuilder {
177                documentation_caps: Some(documentation_caps),
178                ..self
179            }
180        } else {
181            self
182        }
183    }
184
185    #[cfg(feature = "v1_18")]
186    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
187    pub fn documentation_caps_if_some(self, documentation_caps: Option<&'a Caps>) -> Self {
188        if let Some(documentation_caps) = documentation_caps {
189            self.documentation_caps(documentation_caps)
190        } else {
191            self
192        }
193    }
194
195    pub fn build(self) -> Result<PadTemplate, glib::BoolError> {
196        let templ = if let Some(gtype) = self.gtype {
197            PadTemplate::with_gtype(
198                self.name_template,
199                self.direction,
200                self.presence,
201                self.caps,
202                gtype,
203            )?
204        } else {
205            PadTemplate::new(self.name_template, self.direction, self.presence, self.caps)?
206        };
207
208        #[cfg(feature = "v1_18")]
209        #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
210        if let Some(documentation_caps) = self.documentation_caps {
211            unsafe {
212                ffi::gst_pad_template_set_documentation_caps(
213                    templ.to_glib_none().0,
214                    documentation_caps.to_glib_none().0,
215                );
216            }
217        }
218
219        Ok(templ)
220    }
221}