gstreamer/
ghost_pad.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4
5use crate::{
6    ffi, prelude::*, FlowError, FlowSuccess, GhostPad, LoggableError, Pad, PadBuilder, PadFlags,
7    PadGetRangeSuccess, PadMode, StaticPadTemplate,
8};
9
10impl GhostPad {
11    /// Invoke the default activate mode function of a ghost pad.
12    /// ## `pad`
13    /// the [`Pad`][crate::Pad] to activate or deactivate.
14    /// ## `parent`
15    /// the parent of `pad` or [`None`]
16    /// ## `mode`
17    /// the requested activation mode
18    /// ## `active`
19    /// whether the pad should be active or not.
20    ///
21    /// # Returns
22    ///
23    /// [`true`] if the operation was successful.
24    #[doc(alias = "gst_ghost_pad_activate_mode_default")]
25    pub fn activate_mode_default<P: IsA<GhostPad>>(
26        pad: &P,
27        parent: Option<&impl IsA<crate::Object>>,
28        mode: PadMode,
29        active: bool,
30    ) -> Result<(), glib::BoolError> {
31        skip_assert_initialized!();
32        unsafe {
33            glib::result_from_gboolean!(
34                ffi::gst_ghost_pad_activate_mode_default(
35                    pad.to_glib_none().0 as *mut ffi::GstPad,
36                    parent.map(|p| p.as_ref()).to_glib_none().0,
37                    mode.into_glib(),
38                    active.into_glib(),
39                ),
40                "Failed to invoke the default activate mode function of the ghost pad"
41            )
42        }
43    }
44
45    /// Invoke the default activate mode function of a proxy pad that is
46    /// owned by a ghost pad.
47    /// ## `pad`
48    /// the [`Pad`][crate::Pad] to activate or deactivate.
49    /// ## `parent`
50    /// the parent of `pad` or [`None`]
51    /// ## `mode`
52    /// the requested activation mode
53    /// ## `active`
54    /// whether the pad should be active or not.
55    ///
56    /// # Returns
57    ///
58    /// [`true`] if the operation was successful.
59    #[doc(alias = "gst_ghost_pad_internal_activate_mode_default")]
60    pub fn internal_activate_mode_default<P: IsA<GhostPad>>(
61        pad: &P,
62        parent: Option<&impl IsA<crate::Object>>,
63        mode: PadMode,
64        active: bool,
65    ) -> Result<(), glib::BoolError> {
66        skip_assert_initialized!();
67        unsafe {
68            glib::result_from_gboolean!(
69                ffi::gst_ghost_pad_internal_activate_mode_default(
70                    pad.to_glib_none().0 as *mut ffi::GstPad,
71                    parent.map(|p| p.as_ref()).to_glib_none().0,
72                    mode.into_glib(),
73                    active.into_glib(),
74                ),
75                concat!(
76                    "Failed to invoke the default activate mode function of a proxy pad ",
77                    "that is owned by the ghost pad"
78                )
79            )
80        }
81    }
82
83    // rustdoc-stripper-ignore-next
84    /// Creates a new [`GhostPad`] with an automatically generated name.
85    ///
86    /// The [`Pad`] will be assigned the usual `gst::Object` generated unique name.
87    ///
88    /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder)
89    /// and define options.
90    // rustdoc-stripper-ignore-next-stop
91    /// Create a new ghostpad without a target with the given direction.
92    /// A target can be set on the ghostpad later with the
93    /// [`GhostPadExt::set_target()`][crate::prelude::GhostPadExt::set_target()] function.
94    ///
95    /// The created ghostpad will not have a padtemplate.
96    /// ## `name`
97    /// the name of the new pad, or [`None`] to assign a default name.
98    /// ## `dir`
99    /// the direction of the ghostpad
100    ///
101    /// # Returns
102    ///
103    /// a new [`Pad`][crate::Pad], or [`None`] in
104    /// case of an error.
105    #[doc(alias = "gst_ghost_pad_new_no_target")]
106    pub fn new(direction: crate::PadDirection) -> Self {
107        skip_assert_initialized!();
108        Self::builder(direction).build()
109    }
110
111    // rustdoc-stripper-ignore-next
112    /// Creates a [`PadBuilder`](crate::PadBuilder) with the specified [`PadDirection`](crate::PadDirection).
113    #[doc(alias = "gst_ghost_pad_new_no_target")]
114    pub fn builder(direction: crate::PadDirection) -> PadBuilder<Self> {
115        skip_assert_initialized!();
116        PadBuilder::new(direction)
117    }
118
119    // rustdoc-stripper-ignore-next
120    /// Creates a new [`GhostPad`] from the [`StaticPadTemplate`](crate::StaticPadTemplate).
121    ///
122    /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`,
123    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
124    /// the `GhostPad` will automatically be named after the `name_template`.
125    ///
126    /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder)
127    /// and define options.
128    ///
129    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
130    /// automatically generated unique name.
131    ///
132    /// # Panics
133    ///
134    /// Panics if the `name_template` is a wildcard-name.
135    #[doc(alias = "gst_ghost_pad_new_no_target_from_static_template")]
136    pub fn from_static_template(templ: &StaticPadTemplate) -> Self {
137        skip_assert_initialized!();
138        Self::builder_from_static_template(templ).build()
139    }
140
141    // rustdoc-stripper-ignore-next
142    /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`StaticPadTemplate`](crate::StaticPadTemplate).
143    ///
144    /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`,
145    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
146    /// the `GhostPad` will automatically be named after the `name_template`.
147    ///
148    /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some)
149    /// to specify a different name.
150    ///
151    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
152    /// automatically generated unique name.
153    #[doc(alias = "gst_ghost_pad_new_no_target_from_static_template")]
154    pub fn builder_from_static_template(templ: &StaticPadTemplate) -> PadBuilder<Self> {
155        skip_assert_initialized!();
156        PadBuilder::from_static_template(templ)
157    }
158
159    // rustdoc-stripper-ignore-next
160    /// Creates a new [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate).
161    ///
162    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
163    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
164    /// the `GhostPad` will automatically be named after the `name_template`.
165    ///
166    /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder)
167    /// and define options.
168    ///
169    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
170    /// automatically generated unique name.
171    ///
172    /// # Panics
173    ///
174    /// Panics if the `name_template` is a wildcard-name.
175    // rustdoc-stripper-ignore-next-stop
176    /// Create a new ghostpad based on `templ`, without setting a target. The
177    /// direction will be taken from the `templ`.
178    /// ## `name`
179    /// the name of the new pad, or [`None`] to assign a default name
180    /// ## `templ`
181    /// the [`PadTemplate`][crate::PadTemplate] to create the ghostpad from.
182    ///
183    /// # Returns
184    ///
185    /// a new [`Pad`][crate::Pad], or [`None`] in
186    /// case of an error.
187    #[doc(alias = "gst_ghost_pad_new_no_target_from_template")]
188    pub fn from_template(templ: &crate::PadTemplate) -> Self {
189        skip_assert_initialized!();
190        Self::builder_from_template(templ).build()
191    }
192
193    // rustdoc-stripper-ignore-next
194    /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate).
195    ///
196    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
197    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
198    /// the `GhostPad` will automatically be named after the `name_template`.
199    ///
200    /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some)
201    /// to specify a different name.
202    ///
203    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
204    /// automatically generated unique name.
205    #[doc(alias = "gst_ghost_pad_new_no_target_from_template")]
206    pub fn builder_from_template(templ: &crate::PadTemplate) -> PadBuilder<Self> {
207        skip_assert_initialized!();
208        PadBuilder::from_template(templ)
209    }
210
211    // rustdoc-stripper-ignore-next
212    /// Creates a new [`GhostPad`] from the specified `target` `Pad`.
213    ///
214    /// The `GhostPad` will automatically be named after the `target` `name`.
215    ///
216    /// Use [`GhostPad::builder_with_target()`] to get a [`PadBuilder`](crate::PadBuilder)
217    /// and define options.
218    ///
219    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
220    /// automatically generated unique name.
221    // rustdoc-stripper-ignore-next-stop
222    /// Create a new ghostpad with `target` as the target. The direction will be taken
223    /// from the target pad. `target` must be unlinked.
224    ///
225    /// Will ref the target.
226    /// ## `name`
227    /// the name of the new pad, or [`None`] to assign a default name
228    /// ## `target`
229    /// the pad to ghost.
230    ///
231    /// # Returns
232    ///
233    /// a new [`Pad`][crate::Pad], or [`None`] in
234    /// case of an error.
235    #[doc(alias = "gst_ghost_pad_new")]
236    pub fn with_target<P: IsA<Pad> + IsA<crate::Object>>(
237        target: &P,
238    ) -> Result<Self, glib::BoolError> {
239        skip_assert_initialized!();
240        Ok(Self::builder_with_target(target)?.build())
241    }
242
243    // rustdoc-stripper-ignore-next
244    /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the specified `target` `Pad`.
245    ///
246    /// The `GhostPad` will automatically be named after the `target` `name`.
247    ///
248    /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some)
249    /// to specify a different name.
250    ///
251    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
252    /// automatically generated unique name.
253    #[doc(alias = "gst_ghost_pad_new_no_target_from_template")]
254    pub fn builder_with_target<P: IsA<Pad> + IsA<crate::Object>>(
255        target: &P,
256    ) -> Result<PadBuilder<Self>, glib::BoolError> {
257        skip_assert_initialized!();
258        let builder = Self::builder(target.direction());
259        builder.with_target(target)
260    }
261
262    // rustdoc-stripper-ignore-next
263    /// Creates a new [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate)
264    /// with the specified `target` `Pad`.
265    ///
266    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
267    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
268    /// the `GhostPad` will automatically be named after the `name_template`.
269    ///
270    /// If the `name_template` is a wildcard-name, then the `target` `name` is used,
271    /// if it is compatible. Otherwise, a specific name must be provided using
272    /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some).
273    ///
274    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
275    /// automatically generated unique name.
276    // rustdoc-stripper-ignore-next-stop
277    /// Create a new ghostpad with `target` as the target. The direction will be taken
278    /// from the target pad. The template used on the ghostpad will be `template`.
279    ///
280    /// Will ref the target.
281    /// ## `name`
282    /// the name of the new pad, or [`None`] to assign a default name.
283    /// ## `target`
284    /// the pad to ghost.
285    /// ## `templ`
286    /// the [`PadTemplate`][crate::PadTemplate] to use on the ghostpad.
287    ///
288    /// # Returns
289    ///
290    /// a new [`Pad`][crate::Pad], or [`None`] in
291    /// case of an error.
292    #[doc(alias = "gst_ghost_pad_new_from_template")]
293    pub fn from_template_with_target<P: IsA<Pad> + IsA<crate::Object>>(
294        templ: &crate::PadTemplate,
295        target: &P,
296    ) -> Result<Self, glib::BoolError> {
297        skip_assert_initialized!();
298        Ok(Self::builder_from_template_with_target(templ, target)?.build())
299    }
300
301    // rustdoc-stripper-ignore-next
302    /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate)
303    /// with the specified `target` `Pad`.
304    ///
305    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
306    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
307    /// the `GhostPad` will automatically be named after the `name_template`.
308    ///
309    /// If the `name_template` is a wildcard-name, then the `target` `name` is used,
310    /// if it is compatible. Otherwise, a specific name must be provided using
311    /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some).
312    ///
313    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
314    /// automatically generated unique name.
315    #[doc(alias = "gst_ghost_pad_new_from_template")]
316    pub fn builder_from_template_with_target<P: IsA<Pad> + IsA<crate::Object>>(
317        templ: &crate::PadTemplate,
318        target: &P,
319    ) -> Result<PadBuilder<Self>, glib::BoolError> {
320        skip_assert_initialized!();
321
322        if target.direction() != templ.direction() {
323            return Err(glib::bool_error!(
324                "Template and target have different directions"
325            ));
326        }
327
328        Self::builder_from_template(templ).with_target(target)
329    }
330}
331
332impl<T: IsA<GhostPad> + IsA<Pad>> PadBuilder<T> {
333    #[doc(alias = "gst_pad_set_activate_function")]
334    pub fn proxy_pad_activate_function<F>(self, func: F) -> Self
335    where
336        F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> Result<(), LoggableError>
337            + Send
338            + Sync
339            + 'static,
340    {
341        unsafe {
342            let proxy = self
343                .pad
344                .unsafe_cast_ref::<crate::ProxyPad>()
345                .internal()
346                .unwrap();
347            proxy.set_activate_function(func);
348        }
349
350        self
351    }
352
353    #[doc(alias = "gst_pad_set_activate_function")]
354    pub fn proxy_pad_activate_function_if_some<F>(self, func: Option<F>) -> Self
355    where
356        F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> Result<(), LoggableError>
357            + Send
358            + Sync
359            + 'static,
360    {
361        if let Some(func) = func {
362            self.proxy_pad_activate_function(func)
363        } else {
364            self
365        }
366    }
367
368    #[doc(alias = "gst_pad_set_activatemode_function")]
369    pub fn proxy_pad_activatemode_function<F>(self, func: F) -> Self
370    where
371        F: Fn(
372                &crate::ProxyPad,
373                Option<&crate::Object>,
374                crate::PadMode,
375                bool,
376            ) -> Result<(), LoggableError>
377            + Send
378            + Sync
379            + 'static,
380    {
381        unsafe {
382            let proxy = self
383                .pad
384                .unsafe_cast_ref::<crate::ProxyPad>()
385                .internal()
386                .unwrap();
387            proxy.set_activatemode_function(func);
388        }
389
390        self
391    }
392
393    #[doc(alias = "gst_pad_set_activatemode_function")]
394    pub fn proxy_pad_activatemode_function_if_some<F>(self, func: Option<F>) -> Self
395    where
396        F: Fn(
397                &crate::ProxyPad,
398                Option<&crate::Object>,
399                crate::PadMode,
400                bool,
401            ) -> Result<(), LoggableError>
402            + Send
403            + Sync
404            + 'static,
405    {
406        if let Some(func) = func {
407            self.proxy_pad_activatemode_function(func)
408        } else {
409            self
410        }
411    }
412
413    #[doc(alias = "gst_pad_set_chain_function")]
414    pub fn proxy_pad_chain_function<F>(self, func: F) -> Self
415    where
416        F: Fn(
417                &crate::ProxyPad,
418                Option<&crate::Object>,
419                crate::Buffer,
420            ) -> Result<FlowSuccess, FlowError>
421            + Send
422            + Sync
423            + 'static,
424    {
425        unsafe {
426            let proxy = self
427                .pad
428                .unsafe_cast_ref::<crate::ProxyPad>()
429                .internal()
430                .unwrap();
431            proxy.set_chain_function(func);
432        }
433
434        self
435    }
436
437    #[doc(alias = "gst_pad_set_chain_function")]
438    pub fn proxy_pad_chain_function_if_some<F>(self, func: Option<F>) -> Self
439    where
440        F: Fn(
441                &crate::ProxyPad,
442                Option<&crate::Object>,
443                crate::Buffer,
444            ) -> Result<FlowSuccess, FlowError>
445            + Send
446            + Sync
447            + 'static,
448    {
449        if let Some(func) = func {
450            self.proxy_pad_chain_function(func)
451        } else {
452            self
453        }
454    }
455
456    #[doc(alias = "gst_pad_set_chain_list_function")]
457    pub fn proxy_pad_chain_list_function<F>(self, func: F) -> Self
458    where
459        F: Fn(
460                &crate::ProxyPad,
461                Option<&crate::Object>,
462                crate::BufferList,
463            ) -> Result<FlowSuccess, FlowError>
464            + Send
465            + Sync
466            + 'static,
467    {
468        unsafe {
469            let proxy = self
470                .pad
471                .unsafe_cast_ref::<crate::ProxyPad>()
472                .internal()
473                .unwrap();
474            proxy.set_chain_list_function(func);
475        }
476
477        self
478    }
479
480    #[doc(alias = "gst_pad_set_chain_list_function")]
481    pub fn proxy_pad_chain_list_function_if_some<F>(self, func: Option<F>) -> Self
482    where
483        F: Fn(
484                &crate::ProxyPad,
485                Option<&crate::Object>,
486                crate::BufferList,
487            ) -> Result<FlowSuccess, FlowError>
488            + Send
489            + Sync
490            + 'static,
491    {
492        if let Some(func) = func {
493            self.proxy_pad_chain_list_function(func)
494        } else {
495            self
496        }
497    }
498
499    #[doc(alias = "gst_pad_set_event_function")]
500    pub fn proxy_pad_event_function<F>(self, func: F) -> Self
501    where
502        F: Fn(&crate::ProxyPad, Option<&crate::Object>, crate::Event) -> bool
503            + Send
504            + Sync
505            + 'static,
506    {
507        unsafe {
508            let proxy = self
509                .pad
510                .unsafe_cast_ref::<crate::ProxyPad>()
511                .internal()
512                .unwrap();
513            proxy.set_event_function(func);
514        }
515
516        self
517    }
518
519    #[doc(alias = "gst_pad_set_event_function")]
520    pub fn proxy_pad_event_function_if_some<F>(self, func: Option<F>) -> Self
521    where
522        F: Fn(&crate::ProxyPad, Option<&crate::Object>, crate::Event) -> bool
523            + Send
524            + Sync
525            + 'static,
526    {
527        if let Some(func) = func {
528            self.proxy_pad_event_function(func)
529        } else {
530            self
531        }
532    }
533
534    #[doc(alias = "gst_pad_set_event_full_function")]
535    pub fn proxy_pad_event_full_function<F>(self, func: F) -> Self
536    where
537        F: Fn(
538                &crate::ProxyPad,
539                Option<&crate::Object>,
540                crate::Event,
541            ) -> Result<FlowSuccess, FlowError>
542            + Send
543            + Sync
544            + 'static,
545    {
546        unsafe {
547            let proxy = self
548                .pad
549                .unsafe_cast_ref::<crate::ProxyPad>()
550                .internal()
551                .unwrap();
552            proxy.set_event_full_function(func);
553        }
554
555        self
556    }
557
558    #[doc(alias = "gst_pad_set_event_full_function")]
559    pub fn proxy_pad_event_full_function_if_some<F>(self, func: Option<F>) -> Self
560    where
561        F: Fn(
562                &crate::ProxyPad,
563                Option<&crate::Object>,
564                crate::Event,
565            ) -> Result<FlowSuccess, FlowError>
566            + Send
567            + Sync
568            + 'static,
569    {
570        if let Some(func) = func {
571            self.proxy_pad_event_full_function(func)
572        } else {
573            self
574        }
575    }
576
577    #[doc(alias = "gst_pad_set_getrange_function")]
578    pub fn proxy_pad_getrange_function<F>(self, func: F) -> Self
579    where
580        F: Fn(
581                &crate::ProxyPad,
582                Option<&crate::Object>,
583                u64,
584                Option<&mut crate::BufferRef>,
585                u32,
586            ) -> Result<PadGetRangeSuccess, crate::FlowError>
587            + Send
588            + Sync
589            + 'static,
590    {
591        unsafe {
592            let proxy = self
593                .pad
594                .unsafe_cast_ref::<crate::ProxyPad>()
595                .internal()
596                .unwrap();
597            proxy.set_getrange_function(func);
598        }
599
600        self
601    }
602
603    #[doc(alias = "gst_pad_set_getrange_function")]
604    pub fn proxy_pad_getrange_function_if_some<F>(self, func: Option<F>) -> Self
605    where
606        F: Fn(
607                &crate::ProxyPad,
608                Option<&crate::Object>,
609                u64,
610                Option<&mut crate::BufferRef>,
611                u32,
612            ) -> Result<PadGetRangeSuccess, crate::FlowError>
613            + Send
614            + Sync
615            + 'static,
616    {
617        if let Some(func) = func {
618            self.proxy_pad_getrange_function(func)
619        } else {
620            self
621        }
622    }
623
624    #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
625    pub fn proxy_pad_iterate_internal_links_function<F>(self, func: F) -> Self
626    where
627        F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> crate::Iterator<Pad>
628            + Send
629            + Sync
630            + 'static,
631    {
632        unsafe {
633            let proxy = self
634                .pad
635                .unsafe_cast_ref::<crate::ProxyPad>()
636                .internal()
637                .unwrap();
638            proxy.set_iterate_internal_links_function(func);
639        }
640
641        self
642    }
643
644    #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
645    pub fn proxy_pad_iterate_internal_links_function_if_some<F>(self, func: Option<F>) -> Self
646    where
647        F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> crate::Iterator<Pad>
648            + Send
649            + Sync
650            + 'static,
651    {
652        if let Some(func) = func {
653            self.proxy_pad_iterate_internal_links_function(func)
654        } else {
655            self
656        }
657    }
658
659    #[doc(alias = "gst_pad_set_link_function")]
660    pub fn proxy_pad_link_function<F>(self, func: F) -> Self
661    where
662        F: Fn(
663                &crate::ProxyPad,
664                Option<&crate::Object>,
665                &Pad,
666            ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
667            + Send
668            + Sync
669            + 'static,
670    {
671        unsafe {
672            let proxy = self
673                .pad
674                .unsafe_cast_ref::<crate::ProxyPad>()
675                .internal()
676                .unwrap();
677            proxy.set_link_function(func);
678        }
679
680        self
681    }
682
683    #[doc(alias = "gst_pad_set_link_function")]
684    pub fn proxy_pad_link_function_if_some<F>(self, func: Option<F>) -> Self
685    where
686        F: Fn(
687                &crate::ProxyPad,
688                Option<&crate::Object>,
689                &Pad,
690            ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
691            + Send
692            + Sync
693            + 'static,
694    {
695        if let Some(func) = func {
696            self.proxy_pad_link_function(func)
697        } else {
698            self
699        }
700    }
701
702    #[doc(alias = "gst_pad_set_query_function")]
703    pub fn proxy_pad_query_function<F>(self, func: F) -> Self
704    where
705        F: Fn(&crate::ProxyPad, Option<&crate::Object>, &mut crate::QueryRef) -> bool
706            + Send
707            + Sync
708            + 'static,
709    {
710        unsafe {
711            let proxy = self
712                .pad
713                .unsafe_cast_ref::<crate::ProxyPad>()
714                .internal()
715                .unwrap();
716            proxy.set_query_function(func);
717        }
718
719        self
720    }
721
722    #[doc(alias = "gst_pad_set_query_function")]
723    pub fn proxy_pad_query_function_if_some<F>(self, func: Option<F>) -> Self
724    where
725        F: Fn(&crate::ProxyPad, Option<&crate::Object>, &mut crate::QueryRef) -> bool
726            + Send
727            + Sync
728            + 'static,
729    {
730        if let Some(func) = func {
731            self.proxy_pad_query_function(func)
732        } else {
733            self
734        }
735    }
736
737    #[doc(alias = "gst_pad_set_unlink_function")]
738    pub fn proxy_pad_unlink_function<F>(self, func: F) -> Self
739    where
740        F: Fn(&crate::ProxyPad, Option<&crate::Object>) + Send + Sync + 'static,
741    {
742        unsafe {
743            let proxy = self
744                .pad
745                .unsafe_cast_ref::<crate::ProxyPad>()
746                .internal()
747                .unwrap();
748            proxy.set_unlink_function(func);
749        }
750
751        self
752    }
753
754    #[doc(alias = "gst_pad_set_unlink_function")]
755    pub fn proxy_pad_unlink_function_if_some<F>(self, func: Option<F>) -> Self
756    where
757        F: Fn(&crate::ProxyPad, Option<&crate::Object>) + Send + Sync + 'static,
758    {
759        if let Some(func) = func {
760            self.proxy_pad_unlink_function(func)
761        } else {
762            self
763        }
764    }
765
766    pub fn proxy_pad_flags(self, flags: PadFlags) -> Self {
767        unsafe {
768            let proxy = self
769                .pad
770                .unsafe_cast_ref::<crate::ProxyPad>()
771                .internal()
772                .unwrap();
773            proxy.set_pad_flags(flags);
774        }
775
776        self
777    }
778
779    pub fn proxy_pad_flags_if_some(self, flags: Option<PadFlags>) -> Self {
780        if let Some(flags) = flags {
781            self.proxy_pad_flags(flags)
782        } else {
783            self
784        }
785    }
786
787    // rustdoc-stripper-ignore-next
788    /// Specifies a `target` [`Pad`](crate::Pad) for the [`GhostPad`].
789    ///
790    /// If the [`PadBuilder`](crate::PadBuilder) was created from
791    /// a [`PadTemplate`](crate::PadTemplate) and the `PadTemplate` has a specific `name_template`,
792    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
793    /// the `GhostPad` will automatically be named after the `name_template`.
794    ///
795    /// If the `name_template` is a wildcard-name, then the `target` `name` is used,
796    /// if it is compatible. Otherwise, a specific name must be provided using
797    /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::name_if_some`](crate::PadBuilder::name_if_some).
798    ///
799    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
800    /// automatically generated unique name.
801    pub fn with_target<P: IsA<Pad> + IsA<crate::Object>>(
802        mut self,
803        target: &P,
804    ) -> Result<Self, glib::BoolError> {
805        assert_eq!(self.pad.direction(), target.direction());
806
807        self.pad.set_target(Some(target))?;
808        self.name =
809            crate::pad::PadBuilderName::CandidateForWildcardTemplate(target.name().to_string());
810
811        Ok(self)
812    }
813}
814
815#[cfg(test)]
816mod tests {
817    use super::*;
818
819    #[test]
820    fn no_template_no_target() {
821        crate::init().unwrap();
822
823        let ghost_pad = GhostPad::new(crate::PadDirection::Sink);
824        assert!(ghost_pad.name().starts_with("ghostpad"));
825
826        let ghost_pad = GhostPad::builder(crate::PadDirection::Sink).build();
827        assert!(ghost_pad.name().starts_with("ghostpad"));
828
829        let ghost_pad = GhostPad::builder(crate::PadDirection::Sink)
830            .name("sink")
831            .build();
832        assert_eq!(ghost_pad.name(), "sink");
833    }
834
835    #[test]
836    fn from_template() {
837        crate::init().unwrap();
838
839        let caps = crate::Caps::new_any();
840        let wildcard_templ = crate::PadTemplate::new(
841            "sink_%u",
842            crate::PadDirection::Sink,
843            crate::PadPresence::Request,
844            &caps,
845        )
846        .unwrap();
847
848        let ghost_pad = GhostPad::builder_from_template(&wildcard_templ)
849            .name("my-ghostpad")
850            .build();
851        assert_eq!(ghost_pad.name(), "my-ghostpad");
852
853        let caps = crate::Caps::new_any();
854        let templ = crate::PadTemplate::new(
855            "sink",
856            crate::PadDirection::Sink,
857            crate::PadPresence::Always,
858            &caps,
859        )
860        .unwrap();
861
862        let ghost_pad = GhostPad::from_template(&templ);
863        assert_eq!(ghost_pad.name(), "sink");
864
865        let ghost_pad = GhostPad::builder_from_template(&templ).build();
866        assert!(ghost_pad.name().starts_with("sink"));
867
868        let ghost_pad = GhostPad::builder_from_template(&templ)
869            .name("my-sink")
870            .build();
871        assert_eq!(ghost_pad.name(), "my-sink");
872    }
873
874    #[test]
875    #[should_panic]
876    fn from_template_missing_name() {
877        crate::init().unwrap();
878
879        let caps = crate::Caps::new_any();
880        let templ = crate::PadTemplate::new(
881            "audio_%u",
882            crate::PadDirection::Sink,
883            crate::PadPresence::Request,
884            &caps,
885        )
886        .unwrap();
887
888        // Panic: attempt to build from a wildcard-named template
889        //        without providing a name.
890        let _ghost_pad = GhostPad::from_template(&templ);
891    }
892
893    #[test]
894    #[should_panic]
895    fn from_template_builder_missing_name() {
896        crate::init().unwrap();
897
898        let caps = crate::Caps::new_any();
899        let templ = crate::PadTemplate::new(
900            "audio_%u",
901            crate::PadDirection::Sink,
902            crate::PadPresence::Request,
903            &caps,
904        )
905        .unwrap();
906
907        // Panic: attempt to build from a wildcard-named template
908        //        without providing a name.
909        let _ghost_pad = GhostPad::builder_from_template(&templ).build();
910    }
911
912    #[test]
913    fn with_target() {
914        crate::init().unwrap();
915
916        let caps = crate::Caps::new_any();
917        let templ = crate::PadTemplate::new(
918            "test",
919            crate::PadDirection::Sink,
920            crate::PadPresence::Always,
921            &caps,
922        )
923        .unwrap();
924
925        let target = crate::Pad::builder_from_template(&templ).build();
926        let ghost_pad = GhostPad::with_target(&target).unwrap();
927        assert_eq!(ghost_pad.name(), "test");
928
929        let target = crate::Pad::from_template(&templ);
930        let ghost_pad = GhostPad::builder_with_target(&target).unwrap().build();
931        assert_eq!(ghost_pad.name(), "test");
932
933        let target = crate::Pad::from_template(&templ);
934        let ghost_pad = GhostPad::builder_with_target(&target)
935            .unwrap()
936            .name("ghost_test")
937            .build();
938        assert_eq!(ghost_pad.name(), "ghost_test");
939
940        let target = crate::Pad::from_template(&templ);
941        let ghost_pad = GhostPad::builder_with_target(&target)
942            .unwrap()
943            .generated_name()
944            .build();
945        assert!(ghost_pad.name().starts_with("ghostpad"));
946    }
947
948    #[test]
949    fn from_template_with_target() {
950        crate::init().unwrap();
951
952        let caps = crate::Caps::new_any();
953        let sink_templ = crate::PadTemplate::new(
954            "sink",
955            crate::PadDirection::Sink,
956            crate::PadPresence::Always,
957            &caps,
958        )
959        .unwrap();
960
961        // # No conversion specifier, Always template
962        let ghost_templ = crate::PadTemplate::new(
963            "ghost_sink",
964            crate::PadDirection::Sink,
965            crate::PadPresence::Always,
966            &caps,
967        )
968        .unwrap();
969
970        let target = crate::Pad::from_template(&sink_templ);
971        let ghost_pad = GhostPad::from_template_with_target(&ghost_templ, &target).unwrap();
972        assert_eq!(ghost_pad.name(), "ghost_sink");
973
974        let target = crate::Pad::from_template(&sink_templ);
975        let ghost_pad = GhostPad::builder_from_template_with_target(&ghost_templ, &target)
976            .unwrap()
977            .build();
978        assert_eq!(ghost_pad.name(), "ghost_sink");
979
980        let target = crate::Pad::from_template(&sink_templ);
981        let ghost_pad = GhostPad::builder_from_template_with_target(&ghost_templ, &target)
982            .unwrap()
983            .name("my-sink")
984            .build();
985        assert_eq!(ghost_pad.name(), "my-sink");
986
987        let target = crate::Pad::from_template(&sink_templ);
988        let ghost_pad = GhostPad::builder_from_template_with_target(&ghost_templ, &target)
989            .unwrap()
990            .generated_name()
991            .build();
992        assert!(ghost_pad.name().starts_with("ghostpad"));
993
994        // # Request template %u
995        let wildcard_u_templ = crate::PadTemplate::new(
996            "sink_%u",
997            crate::PadDirection::Sink,
998            crate::PadPresence::Request,
999            &caps,
1000        )
1001        .unwrap();
1002
1003        // ## Incompatible target but specific name
1004        let target = crate::Pad::from_template(&sink_templ);
1005        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target)
1006            .unwrap()
1007            .name("sink_0")
1008            .build();
1009        assert_eq!(ghost_pad.name(), "sink_0");
1010
1011        // ## Compatible target
1012        let sink_0_templ = crate::PadTemplate::new(
1013            "sink_0",
1014            crate::PadDirection::Sink,
1015            crate::PadPresence::Always,
1016            &caps,
1017        )
1018        .unwrap();
1019        let target = crate::Pad::from_template(&sink_0_templ);
1020        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target)
1021            .unwrap()
1022            .build();
1023        assert_eq!(ghost_pad.name(), "sink_0");
1024
1025        let target = crate::Pad::from_template(&sink_0_templ);
1026        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target)
1027            .unwrap()
1028            .generated_name()
1029            .build();
1030        assert!(ghost_pad.name().starts_with("ghostpad"));
1031
1032        // # Request template %d_%u
1033        let wildcard_u_templ = crate::PadTemplate::new(
1034            "sink_%d_%u",
1035            crate::PadDirection::Sink,
1036            crate::PadPresence::Request,
1037            &caps,
1038        )
1039        .unwrap();
1040
1041        // ## Incompatible target but specific name
1042        let target = crate::Pad::from_template(&sink_templ);
1043        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target)
1044            .unwrap()
1045            .name("sink_-1_0")
1046            .build();
1047        assert_eq!(ghost_pad.name(), "sink_-1_0");
1048
1049        // ## Compatible target
1050        let sink_m2_0_templ = crate::PadTemplate::new(
1051            "sink_-2_0",
1052            crate::PadDirection::Sink,
1053            crate::PadPresence::Always,
1054            &caps,
1055        )
1056        .unwrap();
1057        let target = crate::Pad::from_template(&sink_m2_0_templ);
1058        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target)
1059            .unwrap()
1060            .build();
1061        assert_eq!(ghost_pad.name(), "sink_-2_0");
1062
1063        // # Request template %s
1064        let wildcard_s_templ = crate::PadTemplate::new(
1065            "sink_%s",
1066            crate::PadDirection::Sink,
1067            crate::PadPresence::Request,
1068            &caps,
1069        )
1070        .unwrap();
1071
1072        // ## Incompatible target but specific name
1073        let target = crate::Pad::from_template(&sink_templ);
1074        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_s_templ, &target)
1075            .unwrap()
1076            .name("sink_ghost_test")
1077            .build();
1078        assert_eq!(ghost_pad.name(), "sink_ghost_test");
1079
1080        // ## Compatible target
1081        let sink_test_templ = crate::PadTemplate::new(
1082            "sink_test",
1083            crate::PadDirection::Sink,
1084            crate::PadPresence::Always,
1085            &caps,
1086        )
1087        .unwrap();
1088        let target = crate::Pad::from_template(&sink_test_templ);
1089        let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_s_templ, &target)
1090            .unwrap()
1091            .build();
1092        assert_eq!(ghost_pad.name(), "sink_test");
1093    }
1094
1095    #[test]
1096    #[should_panic]
1097    fn from_template_with_target_incompatible_prefix() {
1098        crate::init().unwrap();
1099
1100        let caps = crate::Caps::new_any();
1101        let wildcard_templ = crate::PadTemplate::new(
1102            "sink_%u",
1103            crate::PadDirection::Sink,
1104            crate::PadPresence::Request,
1105            &caps,
1106        )
1107        .unwrap();
1108
1109        let templ = crate::PadTemplate::new(
1110            "audio_0",
1111            crate::PadDirection::Sink,
1112            crate::PadPresence::Always,
1113            &caps,
1114        )
1115        .unwrap();
1116
1117        let target = crate::Pad::from_template(&templ);
1118        // Panic: attempt to build from a wildcard-named template
1119        //        with a target name with a different prefix
1120        //        without providing a name.
1121        let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target)
1122            .unwrap()
1123            .build();
1124    }
1125
1126    #[test]
1127    #[should_panic]
1128    fn from_template_with_target_missing_part() {
1129        crate::init().unwrap();
1130
1131        let caps = crate::Caps::new_any();
1132        let wildcard_templ = crate::PadTemplate::new(
1133            "sink_%u_%s",
1134            crate::PadDirection::Sink,
1135            crate::PadPresence::Request,
1136            &caps,
1137        )
1138        .unwrap();
1139
1140        let templ = crate::PadTemplate::new(
1141            "sink_0",
1142            crate::PadDirection::Sink,
1143            crate::PadPresence::Always,
1144            &caps,
1145        )
1146        .unwrap();
1147
1148        let target = crate::Pad::from_template(&templ);
1149        // Panic: attempt to build from a wildcard-named template
1150        //        with a target name missing a part
1151        //        without providing a name.
1152        let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target)
1153            .unwrap()
1154            .build();
1155    }
1156
1157    #[test]
1158    #[should_panic]
1159    fn from_template_with_target_incompatible_conversion_unsigned() {
1160        crate::init().unwrap();
1161
1162        let caps = crate::Caps::new_any();
1163        let wildcard_templ = crate::PadTemplate::new(
1164            "sink_%u",
1165            crate::PadDirection::Sink,
1166            crate::PadPresence::Request,
1167            &caps,
1168        )
1169        .unwrap();
1170
1171        let templ = crate::PadTemplate::new(
1172            "sink_-1",
1173            crate::PadDirection::Sink,
1174            crate::PadPresence::Always,
1175            &caps,
1176        )
1177        .unwrap();
1178
1179        let target = crate::Pad::from_template(&templ);
1180        // Panic: attempt to build from a wildcard-named template
1181        //        with a target name %d, expecting %u
1182        //        without providing a name.
1183        let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target)
1184            .unwrap()
1185            .build();
1186    }
1187
1188    #[test]
1189    #[should_panic]
1190    fn from_template_with_target_incompatible_conversion_decimal() {
1191        crate::init().unwrap();
1192
1193        let caps = crate::Caps::new_any();
1194        let wildcard_templ = crate::PadTemplate::new(
1195            "sink_%u",
1196            crate::PadDirection::Sink,
1197            crate::PadPresence::Request,
1198            &caps,
1199        )
1200        .unwrap();
1201
1202        let templ = crate::PadTemplate::new(
1203            "sink_test",
1204            crate::PadDirection::Sink,
1205            crate::PadPresence::Always,
1206            &caps,
1207        )
1208        .unwrap();
1209
1210        let target = crate::Pad::from_template(&templ);
1211        // Panic: attempt to build from a wildcard-named template
1212        //        with a target name with %s, expecting %d
1213        //        without providing a name.
1214        let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target)
1215            .unwrap()
1216            .build();
1217    }
1218
1219    #[test]
1220    #[should_panic]
1221    fn from_template_with_target_incompatible_missing_decimal() {
1222        crate::init().unwrap();
1223
1224        let caps = crate::Caps::new_any();
1225        let wildcard_templ = crate::PadTemplate::new(
1226            "sink_%d",
1227            crate::PadDirection::Sink,
1228            crate::PadPresence::Request,
1229            &caps,
1230        )
1231        .unwrap();
1232
1233        let templ = crate::PadTemplate::new(
1234            "sink_",
1235            crate::PadDirection::Sink,
1236            crate::PadPresence::Always,
1237            &caps,
1238        )
1239        .unwrap();
1240
1241        let target = crate::Pad::from_template(&templ);
1242        // Panic: attempt to build from a wildcard-named template
1243        //        with a target name missing a number, expecting %d
1244        //        without providing a name.
1245        let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target)
1246            .unwrap()
1247            .build();
1248    }
1249}