gstreamer/
pad.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{
4    mem,
5    num::NonZeroU64,
6    ops::ControlFlow,
7    panic::{self, AssertUnwindSafe},
8    ptr,
9};
10
11use glib::{ffi::gpointer, prelude::*, translate::*};
12
13use crate::{
14    ffi,
15    format::{FormattedValue, SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic},
16    prelude::*,
17    Buffer, BufferList, Event, FlowError, FlowReturn, FlowSuccess, Format, GenericFormattedValue,
18    LoggableError, Pad, PadFlags, PadProbeReturn, PadProbeType, Query, QueryRef, StaticPadTemplate,
19};
20
21#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct PadProbeId(NonZeroU64);
23
24impl IntoGlib for PadProbeId {
25    type GlibType = libc::c_ulong;
26
27    #[inline]
28    fn into_glib(self) -> libc::c_ulong {
29        self.0.get() as libc::c_ulong
30    }
31}
32
33impl FromGlib<libc::c_ulong> for PadProbeId {
34    #[inline]
35    unsafe fn from_glib(val: libc::c_ulong) -> PadProbeId {
36        skip_assert_initialized!();
37        debug_assert_ne!(val, 0);
38        PadProbeId(NonZeroU64::new_unchecked(val as _))
39    }
40}
41
42impl PadProbeId {
43    #[inline]
44    pub fn as_raw(&self) -> libc::c_ulong {
45        self.0.get() as libc::c_ulong
46    }
47}
48
49#[doc(alias = "GstPadProbeInfo")]
50#[derive(Debug)]
51pub struct PadProbeInfo<'a> {
52    pub mask: PadProbeType,
53    pub id: Option<PadProbeId>,
54    pub offset: u64,
55    pub size: u32,
56    pub data: Option<PadProbeData<'a>>,
57    pub flow_res: Result<FlowSuccess, FlowError>,
58}
59
60impl PadProbeInfo<'_> {
61    pub fn buffer(&self) -> Option<&Buffer> {
62        match self.data {
63            Some(PadProbeData::Buffer(ref buffer)) => Some(buffer),
64            _ => None,
65        }
66    }
67
68    pub fn buffer_mut(&mut self) -> Option<&mut Buffer> {
69        match self.data {
70            Some(PadProbeData::Buffer(ref mut buffer)) => Some(buffer),
71            _ => None,
72        }
73    }
74
75    pub fn buffer_list(&self) -> Option<&BufferList> {
76        match self.data {
77            Some(PadProbeData::BufferList(ref buffer_list)) => Some(buffer_list),
78            _ => None,
79        }
80    }
81
82    pub fn buffer_list_mut(&mut self) -> Option<&mut BufferList> {
83        match self.data {
84            Some(PadProbeData::BufferList(ref mut buffer_list)) => Some(buffer_list),
85            _ => None,
86        }
87    }
88
89    pub fn query(&self) -> Option<&QueryRef> {
90        match self.data {
91            Some(PadProbeData::Query(ref query)) => Some(*query),
92            _ => None,
93        }
94    }
95
96    pub fn query_mut(&mut self) -> Option<&mut QueryRef> {
97        match self.data {
98            Some(PadProbeData::Query(ref mut query)) => Some(*query),
99            _ => None,
100        }
101    }
102
103    pub fn event(&self) -> Option<&Event> {
104        match self.data {
105            Some(PadProbeData::Event(ref event)) => Some(event),
106            _ => None,
107        }
108    }
109
110    pub fn event_mut(&mut self) -> Option<&mut Event> {
111        match self.data {
112            Some(PadProbeData::Event(ref mut event)) => Some(event),
113            _ => None,
114        }
115    }
116
117    // rustdoc-stripper-ignore-next
118    /// Takes over the buffer in the probe info. As the data is no longer valid for the caller, the
119    /// probe will be considered dropped after this point.
120    pub fn take_buffer(&mut self) -> Option<Buffer> {
121        if matches!(self.data, Some(PadProbeData::Buffer(..))) {
122            match self.data.take() {
123                Some(PadProbeData::Buffer(b)) => Some(b),
124                _ => unreachable!(),
125            }
126        } else {
127            None
128        }
129    }
130
131    // rustdoc-stripper-ignore-next
132    /// Takes over the buffer in the probe info. As the data is no longer valid for the caller, the
133    /// probe will be considered dropped after this point.
134    pub fn take_buffer_list(&mut self) -> Option<BufferList> {
135        if matches!(self.data, Some(PadProbeData::BufferList(..))) {
136            match self.data.take() {
137                Some(PadProbeData::BufferList(b)) => Some(b),
138                _ => unreachable!(),
139            }
140        } else {
141            None
142        }
143    }
144    // rustdoc-stripper-ignore-next
145    /// Takes over the event in the probe info. As the data is no longer valid for the caller, the
146    /// probe will be considered dropped after this point.
147    pub fn take_event(&mut self) -> Option<Event> {
148        if matches!(self.data, Some(PadProbeData::Event(..))) {
149            match self.data.take() {
150                Some(PadProbeData::Event(e)) => Some(e),
151                _ => unreachable!(),
152            }
153        } else {
154            None
155        }
156    }
157}
158
159#[derive(Debug)]
160pub enum PadProbeData<'a> {
161    Buffer(Buffer),
162    BufferList(BufferList),
163    Query(&'a mut QueryRef),
164    Event(Event),
165    #[doc(hidden)]
166    __Unknown(*mut ffi::GstMiniObject),
167}
168
169unsafe impl Send for PadProbeData<'_> {}
170unsafe impl Sync for PadProbeData<'_> {}
171
172#[derive(Debug)]
173#[must_use = "if unused the StreamLock will immediately unlock"]
174pub struct StreamLock<'a>(&'a Pad);
175impl Drop for StreamLock<'_> {
176    #[inline]
177    fn drop(&mut self) {
178        unsafe {
179            let pad: *mut ffi::GstPad = self.0.to_glib_none().0;
180            glib::ffi::g_rec_mutex_unlock(&mut (*pad).stream_rec_lock);
181        }
182    }
183}
184
185#[derive(Debug)]
186pub enum PadGetRangeSuccess {
187    FilledBuffer,
188    NewBuffer(crate::Buffer),
189}
190
191#[derive(Debug)]
192pub enum EventForeachAction {
193    Keep,
194    Remove,
195    Replace(Event),
196}
197
198pub trait PadExtManual: IsA<Pad> + 'static {
199    /// Be notified of different states of pads. The provided callback is called for
200    /// every state that matches `mask`.
201    ///
202    /// Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are
203    /// called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only
204    /// exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called
205    /// immediately if the pad is already idle while calling [`add_probe()`][Self::add_probe()].
206    /// In each of the groups, probes are called in the order in which they were
207    /// added.
208    /// ## `mask`
209    /// the probe mask
210    /// ## `callback`
211    /// `GstPadProbeCallback` that will be called with
212    ///  notifications of the pad state
213    /// ## `destroy_data`
214    /// `GDestroyNotify` for user_data
215    ///
216    /// # Returns
217    ///
218    /// an id or 0 if no probe is pending. The id can be used to remove the
219    /// probe with [`remove_probe()`][Self::remove_probe()]. When using GST_PAD_PROBE_TYPE_IDLE it can
220    /// happen that the probe can be run immediately and if the probe returns
221    /// GST_PAD_PROBE_REMOVE this functions returns 0.
222    ///
223    /// MT safe.
224    #[doc(alias = "gst_pad_add_probe")]
225    fn add_probe<F>(&self, mask: PadProbeType, func: F) -> Option<PadProbeId>
226    where
227        F: Fn(&Self, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
228    {
229        unsafe {
230            let func_box: Box<F> = Box::new(func);
231            let id = ffi::gst_pad_add_probe(
232                self.as_ref().to_glib_none().0,
233                mask.into_glib(),
234                Some(trampoline_pad_probe::<Self, F>),
235                Box::into_raw(func_box) as gpointer,
236                Some(destroy_closure::<F>),
237            );
238
239            if id == 0 {
240                None
241            } else {
242                Some(from_glib(id))
243            }
244        }
245    }
246
247    /// Remove the probe with `id` from `self`.
248    ///
249    /// MT safe.
250    /// ## `id`
251    /// the probe id to remove
252    #[doc(alias = "gst_pad_remove_probe")]
253    fn remove_probe(&self, id: PadProbeId) {
254        unsafe {
255            ffi::gst_pad_remove_probe(self.as_ref().to_glib_none().0, id.into_glib());
256        }
257    }
258
259    /// Pulls a `buffer` from the peer pad or fills up a provided buffer.
260    ///
261    /// This function will first trigger the pad block signal if it was
262    /// installed.
263    ///
264    /// When `self` is not linked [`FlowReturn::NotLinked`][crate::FlowReturn::NotLinked] is returned else this
265    /// function returns the result of [`range()`][Self::range()] on the peer pad.
266    /// See [`range()`][Self::range()] for a list of return values and for the
267    /// semantics of the arguments of this function.
268    ///
269    /// If `buffer` points to a variable holding [`None`], a valid new [`Buffer`][crate::Buffer] will be
270    /// placed in `buffer` when this function returns [`FlowReturn::Ok`][crate::FlowReturn::Ok]. The new buffer
271    /// must be freed with `gst_buffer_unref()` after usage. When this function
272    /// returns any other result value, `buffer` will still point to [`None`].
273    ///
274    /// When `buffer` points to a variable that points to a valid [`Buffer`][crate::Buffer], the
275    /// buffer will be filled with the result data when this function returns
276    /// [`FlowReturn::Ok`][crate::FlowReturn::Ok]. When this function returns any other result value,
277    /// `buffer` will be unchanged. If the provided buffer is larger than `size`, only
278    /// `size` bytes will be filled in the result buffer and its size will be updated
279    /// accordingly.
280    ///
281    /// Note that less than `size` bytes can be returned in `buffer` when, for example,
282    /// an EOS condition is near or when `buffer` is not large enough to hold `size`
283    /// bytes. The caller should check the result buffer size to get the result size.
284    /// ## `offset`
285    /// The start offset of the buffer
286    /// ## `size`
287    /// The length of the buffer
288    ///
289    /// # Returns
290    ///
291    /// a [`FlowReturn`][crate::FlowReturn] from the peer pad.
292    ///
293    /// MT safe.
294    ///
295    /// ## `buffer`
296    /// a pointer to hold the [`Buffer`][crate::Buffer], returns
297    ///  GST_FLOW_ERROR if [`None`].
298    #[doc(alias = "gst_pad_pull_range")]
299    fn pull_range(&self, offset: u64, size: u32) -> Result<Buffer, FlowError> {
300        unsafe {
301            let mut buffer = ptr::null_mut();
302            FlowSuccess::try_from_glib(ffi::gst_pad_pull_range(
303                self.as_ref().to_glib_none().0,
304                offset,
305                size,
306                &mut buffer,
307            ))
308            .map(|_| from_glib_full(buffer))
309        }
310    }
311
312    fn pull_range_fill(
313        &self,
314        offset: u64,
315        buffer: &mut crate::BufferRef,
316        size: u32,
317    ) -> Result<(), FlowError> {
318        assert!(buffer.size() >= size as usize);
319
320        unsafe {
321            let mut buffer_ref = buffer.as_mut_ptr();
322            FlowSuccess::try_from_glib(ffi::gst_pad_pull_range(
323                self.as_ref().to_glib_none().0,
324                offset,
325                size,
326                &mut buffer_ref,
327            ))
328            .and_then(|_| {
329                if buffer.as_mut_ptr() != buffer_ref {
330                    ffi::gst_mini_object_unref(buffer_ref as *mut _);
331                    Err(crate::FlowError::Error)
332                } else {
333                    Ok(())
334                }
335            })
336        }
337    }
338
339    /// When `self` is flushing this function returns [`FlowReturn::Flushing`][crate::FlowReturn::Flushing]
340    /// immediately and `buffer` is [`None`].
341    ///
342    /// Calls the getrange function of `self`, see `GstPadGetRangeFunction` for a
343    /// description of a getrange function. If `self` has no getrange function
344    /// installed (see `gst_pad_set_getrange_function()`) this function returns
345    /// [`FlowReturn::NotSupported`][crate::FlowReturn::NotSupported].
346    ///
347    /// If `buffer` points to a variable holding [`None`], a valid new [`Buffer`][crate::Buffer] will be
348    /// placed in `buffer` when this function returns [`FlowReturn::Ok`][crate::FlowReturn::Ok]. The new buffer
349    /// must be freed with `gst_buffer_unref()` after usage.
350    ///
351    /// When `buffer` points to a variable that points to a valid [`Buffer`][crate::Buffer], the
352    /// buffer will be filled with the result data when this function returns
353    /// [`FlowReturn::Ok`][crate::FlowReturn::Ok]. If the provided buffer is larger than `size`, only
354    /// `size` bytes will be filled in the result buffer and its size will be updated
355    /// accordingly.
356    ///
357    /// Note that less than `size` bytes can be returned in `buffer` when, for example,
358    /// an EOS condition is near or when `buffer` is not large enough to hold `size`
359    /// bytes. The caller should check the result buffer size to get the result size.
360    ///
361    /// When this function returns any other result value than [`FlowReturn::Ok`][crate::FlowReturn::Ok], `buffer`
362    /// will be unchanged.
363    ///
364    /// This is a lowlevel function. Usually [`pull_range()`][Self::pull_range()] is used.
365    /// ## `offset`
366    /// The start offset of the buffer
367    /// ## `size`
368    /// The length of the buffer
369    ///
370    /// # Returns
371    ///
372    /// a [`FlowReturn`][crate::FlowReturn] from the pad.
373    ///
374    /// MT safe.
375    ///
376    /// ## `buffer`
377    /// a pointer to hold the [`Buffer`][crate::Buffer],
378    ///  returns [`FlowReturn::Error`][crate::FlowReturn::Error] if [`None`].
379    #[doc(alias = "get_range")]
380    #[doc(alias = "gst_pad_get_range")]
381    fn range(&self, offset: u64, size: u32) -> Result<Buffer, FlowError> {
382        unsafe {
383            let mut buffer = ptr::null_mut();
384            FlowSuccess::try_from_glib(ffi::gst_pad_get_range(
385                self.as_ref().to_glib_none().0,
386                offset,
387                size,
388                &mut buffer,
389            ))
390            .map(|_| from_glib_full(buffer))
391        }
392    }
393
394    #[doc(alias = "get_range_fill")]
395    fn range_fill(
396        &self,
397        offset: u64,
398        buffer: &mut crate::BufferRef,
399        size: u32,
400    ) -> Result<(), FlowError> {
401        assert!(buffer.size() >= size as usize);
402
403        unsafe {
404            let mut buffer_ref = buffer.as_mut_ptr();
405            FlowSuccess::try_from_glib(ffi::gst_pad_get_range(
406                self.as_ref().to_glib_none().0,
407                offset,
408                size,
409                &mut buffer_ref,
410            ))
411            .and_then(|_| {
412                if buffer.as_mut_ptr() != buffer_ref {
413                    ffi::gst_mini_object_unref(buffer_ref as *mut _);
414                    Err(crate::FlowError::Error)
415                } else {
416                    Ok(())
417                }
418            })
419        }
420    }
421
422    /// Performs [`query()`][Self::query()] on the peer of `self`.
423    ///
424    /// The caller is responsible for both the allocation and deallocation of
425    /// the query structure.
426    /// ## `query`
427    /// the [`Query`][crate::Query] to perform.
428    ///
429    /// # Returns
430    ///
431    /// [`true`] if the query could be performed. This function returns [`false`]
432    /// if `self` has no peer.
433    #[doc(alias = "gst_pad_peer_query")]
434    fn peer_query(&self, query: &mut QueryRef) -> bool {
435        unsafe {
436            from_glib(ffi::gst_pad_peer_query(
437                self.as_ref().to_glib_none().0,
438                query.as_mut_ptr(),
439            ))
440        }
441    }
442
443    /// Dispatches a query to a pad. The query should have been allocated by the
444    /// caller via one of the type-specific allocation functions. The element that
445    /// the pad belongs to is responsible for filling the query with an appropriate
446    /// response, which should then be parsed with a type-specific query parsing
447    /// function.
448    ///
449    /// Again, the caller is responsible for both the allocation and deallocation of
450    /// the query structure.
451    ///
452    /// Please also note that some queries might need a running pipeline to work.
453    /// ## `query`
454    /// the [`Query`][crate::Query] to perform.
455    ///
456    /// # Returns
457    ///
458    /// [`true`] if the query could be performed.
459    #[doc(alias = "gst_pad_query")]
460    fn query(&self, query: &mut QueryRef) -> bool {
461        unsafe {
462            from_glib(ffi::gst_pad_query(
463                self.as_ref().to_glib_none().0,
464                query.as_mut_ptr(),
465            ))
466        }
467    }
468
469    /// Calls [`PadExt::query_caps()`][crate::prelude::PadExt::query_caps()] for all internally linked pads of `self` and returns
470    /// the intersection of the results.
471    ///
472    /// This function is useful as a default caps query function for an element
473    /// that can handle any stream format, but requires all its pads to have
474    /// the same caps. Two such elements are tee and adder.
475    /// ## `query`
476    /// a CAPS [`Query`][crate::Query].
477    ///
478    /// # Returns
479    ///
480    /// [`true`] if `query` could be executed
481    #[doc(alias = "gst_pad_proxy_query_caps")]
482    fn proxy_query_caps(&self, query: &mut QueryRef) -> bool {
483        unsafe {
484            from_glib(ffi::gst_pad_proxy_query_caps(
485                self.as_ref().to_glib_none().0,
486                query.as_mut_ptr(),
487            ))
488        }
489    }
490
491    /// Checks if all internally linked pads of `self` accepts the caps in `query` and
492    /// returns the intersection of the results.
493    ///
494    /// This function is useful as a default accept caps query function for an element
495    /// that can handle any stream format, but requires caps that are acceptable for
496    /// all opposite pads.
497    /// ## `query`
498    /// an ACCEPT_CAPS [`Query`][crate::Query].
499    ///
500    /// # Returns
501    ///
502    /// [`true`] if `query` could be executed
503    #[doc(alias = "gst_pad_proxy_query_accept_caps")]
504    fn proxy_query_accept_caps(&self, query: &mut QueryRef) -> bool {
505        unsafe {
506            from_glib(ffi::gst_pad_proxy_query_accept_caps(
507                self.as_ref().to_glib_none().0,
508                query.as_mut_ptr(),
509            ))
510        }
511    }
512
513    /// Sends the event to the peer of the given pad. This function is
514    /// mainly used by elements to send events to their peer
515    /// elements.
516    ///
517    /// This function takes ownership of the provided event so you should
518    /// `gst_event_ref()` it if you want to reuse the event after this call.
519    /// ## `event`
520    /// the [`Event`][crate::Event] to send to the pad.
521    ///
522    /// # Returns
523    ///
524    /// [`true`] if the event was handled.
525    ///
526    /// MT safe.
527    #[doc(alias = "gst_pad_push_event")]
528    fn push_event(&self, event: impl Into<Event>) -> bool {
529        unsafe {
530            from_glib(ffi::gst_pad_push_event(
531                self.as_ref().to_glib_none().0,
532                event.into().into_glib_ptr(),
533            ))
534        }
535    }
536
537    /// Sends the event to the pad. This function can be used
538    /// by applications to send events in the pipeline.
539    ///
540    /// If `self` is a source pad, `event` should be an upstream event. If `self` is a
541    /// sink pad, `event` should be a downstream event. For example, you would not
542    /// send a [`EventType::Eos`][crate::EventType::Eos] on a src pad; EOS events only propagate downstream.
543    /// Furthermore, some downstream events have to be serialized with data flow,
544    /// like EOS, while some can travel out-of-band, like [`EventType::FlushStart`][crate::EventType::FlushStart]. If
545    /// the event needs to be serialized with data flow, this function will take the
546    /// pad's stream lock while calling its event function.
547    ///
548    /// To find out whether an event type is upstream, downstream, or downstream and
549    /// serialized, see [`EventTypeFlags`][crate::EventTypeFlags], [`EventType::flags()`][crate::EventType::flags()],
550    /// `GST_EVENT_IS_UPSTREAM`, `GST_EVENT_IS_DOWNSTREAM`, and
551    /// `GST_EVENT_IS_SERIALIZED`. Note that in practice that an application or
552    /// plugin doesn't need to bother itself with this information; the core handles
553    /// all necessary locks and checks.
554    ///
555    /// This function takes ownership of the provided event so you should
556    /// `gst_event_ref()` it if you want to reuse the event after this call.
557    /// ## `event`
558    /// the [`Event`][crate::Event] to send to the pad.
559    ///
560    /// # Returns
561    ///
562    /// [`true`] if the event was handled.
563    #[doc(alias = "gst_pad_send_event")]
564    fn send_event(&self, event: impl Into<Event>) -> bool {
565        unsafe {
566            from_glib(ffi::gst_pad_send_event(
567                self.as_ref().to_glib_none().0,
568                event.into().into_glib_ptr(),
569            ))
570        }
571    }
572
573    #[doc(alias = "gst_pad_iterate_internal_links")]
574    fn iterate_internal_links(&self) -> crate::Iterator<Pad> {
575        unsafe {
576            from_glib_full(ffi::gst_pad_iterate_internal_links(
577                self.as_ref().to_glib_none().0,
578            ))
579        }
580    }
581
582    fn stream_lock(&self) -> StreamLock {
583        unsafe {
584            let ptr: &mut ffi::GstPad = &mut *(self.as_ptr() as *mut _);
585            glib::ffi::g_rec_mutex_lock(&mut ptr.stream_rec_lock);
586            StreamLock(self.upcast_ref())
587        }
588    }
589
590    #[doc(alias = "gst_pad_set_activate_function")]
591    #[doc(alias = "gst_pad_set_activate_function_full")]
592    unsafe fn set_activate_function<F>(&self, func: F)
593    where
594        F: Fn(&Self, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
595    {
596        let func_box: Box<F> = Box::new(func);
597        ffi::gst_pad_set_activate_function_full(
598            self.as_ref().to_glib_none().0,
599            Some(trampoline_activate_function::<Self, F>),
600            Box::into_raw(func_box) as gpointer,
601            Some(destroy_closure::<F>),
602        );
603    }
604
605    #[doc(alias = "gst_pad_set_activatemode_function")]
606    #[doc(alias = "gst_pad_set_activatemode_function_full")]
607    unsafe fn set_activatemode_function<F>(&self, func: F)
608    where
609        F: Fn(&Self, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
610            + Send
611            + Sync
612            + 'static,
613    {
614        let func_box: Box<F> = Box::new(func);
615        ffi::gst_pad_set_activatemode_function_full(
616            self.as_ref().to_glib_none().0,
617            Some(trampoline_activatemode_function::<Self, F>),
618            Box::into_raw(func_box) as gpointer,
619            Some(destroy_closure::<F>),
620        );
621    }
622
623    #[doc(alias = "gst_pad_set_chain_function")]
624    #[doc(alias = "gst_pad_set_chain_function_full")]
625    unsafe fn set_chain_function<F>(&self, func: F)
626    where
627        F: Fn(&Self, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
628            + Send
629            + Sync
630            + 'static,
631    {
632        let func_box: Box<F> = Box::new(func);
633        ffi::gst_pad_set_chain_function_full(
634            self.as_ref().to_glib_none().0,
635            Some(trampoline_chain_function::<Self, F>),
636            Box::into_raw(func_box) as gpointer,
637            Some(destroy_closure::<F>),
638        );
639    }
640
641    #[doc(alias = "gst_pad_set_chain_list_function")]
642    #[doc(alias = "gst_pad_set_chain_list_function_full")]
643    unsafe fn set_chain_list_function<F>(&self, func: F)
644    where
645        F: Fn(&Self, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
646            + Send
647            + Sync
648            + 'static,
649    {
650        let func_box: Box<F> = Box::new(func);
651        ffi::gst_pad_set_chain_list_function_full(
652            self.as_ref().to_glib_none().0,
653            Some(trampoline_chain_list_function::<Self, F>),
654            Box::into_raw(func_box) as gpointer,
655            Some(destroy_closure::<F>),
656        );
657    }
658
659    #[doc(alias = "gst_pad_set_event_function")]
660    #[doc(alias = "gst_pad_set_event_function_full")]
661    unsafe fn set_event_function<F>(&self, func: F)
662    where
663        F: Fn(&Self, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
664    {
665        let func_box: Box<F> = Box::new(func);
666        ffi::gst_pad_set_event_function_full(
667            self.as_ref().to_glib_none().0,
668            Some(trampoline_event_function::<Self, F>),
669            Box::into_raw(func_box) as gpointer,
670            Some(destroy_closure::<F>),
671        );
672    }
673
674    #[doc(alias = "gst_pad_set_event_full_function")]
675    #[doc(alias = "gst_pad_set_event_full_function_full")]
676    unsafe fn set_event_full_function<F>(&self, func: F)
677    where
678        F: Fn(&Self, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
679            + Send
680            + Sync
681            + 'static,
682    {
683        let func_box: Box<F> = Box::new(func);
684        ffi::gst_pad_set_event_full_function_full(
685            self.as_ref().to_glib_none().0,
686            Some(trampoline_event_full_function::<Self, F>),
687            Box::into_raw(func_box) as gpointer,
688            Some(destroy_closure::<F>),
689        );
690    }
691
692    #[doc(alias = "gst_pad_set_getrange_function")]
693    #[doc(alias = "gst_pad_set_getrange_function_full")]
694    unsafe fn set_getrange_function<F>(&self, func: F)
695    where
696        F: Fn(
697                &Self,
698                Option<&crate::Object>,
699                u64,
700                Option<&mut crate::BufferRef>,
701                u32,
702            ) -> Result<PadGetRangeSuccess, crate::FlowError>
703            + Send
704            + Sync
705            + 'static,
706    {
707        let func_box: Box<F> = Box::new(func);
708        ffi::gst_pad_set_getrange_function_full(
709            self.as_ref().to_glib_none().0,
710            Some(trampoline_getrange_function::<Self, F>),
711            Box::into_raw(func_box) as gpointer,
712            Some(destroy_closure::<F>),
713        );
714    }
715
716    #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
717    #[doc(alias = "gst_pad_set_iterate_internal_links_function_full")]
718    unsafe fn set_iterate_internal_links_function<F>(&self, func: F)
719    where
720        F: Fn(&Self, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
721    {
722        let func_box: Box<F> = Box::new(func);
723        ffi::gst_pad_set_iterate_internal_links_function_full(
724            self.as_ref().to_glib_none().0,
725            Some(trampoline_iterate_internal_links_function::<Self, F>),
726            Box::into_raw(func_box) as gpointer,
727            Some(destroy_closure::<F>),
728        );
729    }
730
731    #[doc(alias = "gst_pad_set_link_function")]
732    #[doc(alias = "gst_pad_set_link_function_full")]
733    unsafe fn set_link_function<F>(&self, func: F)
734    where
735        F: Fn(
736                &Self,
737                Option<&crate::Object>,
738                &Pad,
739            ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
740            + Send
741            + Sync
742            + 'static,
743    {
744        let func_box: Box<F> = Box::new(func);
745        ffi::gst_pad_set_link_function_full(
746            self.as_ref().to_glib_none().0,
747            Some(trampoline_link_function::<Self, F>),
748            Box::into_raw(func_box) as gpointer,
749            Some(destroy_closure::<F>),
750        );
751    }
752
753    #[doc(alias = "gst_pad_set_query_function")]
754    #[doc(alias = "gst_pad_set_query_function_full")]
755    unsafe fn set_query_function<F>(&self, func: F)
756    where
757        F: Fn(&Self, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
758    {
759        let func_box: Box<F> = Box::new(func);
760        ffi::gst_pad_set_query_function_full(
761            self.as_ref().to_glib_none().0,
762            Some(trampoline_query_function::<Self, F>),
763            Box::into_raw(func_box) as gpointer,
764            Some(destroy_closure::<F>),
765        );
766    }
767
768    #[doc(alias = "gst_pad_set_unlink_function")]
769    #[doc(alias = "gst_pad_set_unlink_function_full")]
770    unsafe fn set_unlink_function<F>(&self, func: F)
771    where
772        F: Fn(&Self, Option<&crate::Object>) + Send + Sync + 'static,
773    {
774        let func_box: Box<F> = Box::new(func);
775        ffi::gst_pad_set_unlink_function_full(
776            self.as_ref().to_glib_none().0,
777            Some(trampoline_unlink_function::<Self, F>),
778            Box::into_raw(func_box) as gpointer,
779            Some(destroy_closure::<F>),
780        );
781    }
782
783    /// Starts a task that repeatedly calls `func` with `user_data`. This function
784    /// is mostly used in pad activation functions to start the dataflow.
785    /// The `GST_PAD_STREAM_LOCK` of `self` will automatically be acquired
786    /// before `func` is called.
787    /// ## `func`
788    /// the task function to call
789    /// ## `notify`
790    /// called when `user_data` is no longer referenced
791    ///
792    /// # Returns
793    ///
794    /// a [`true`] if the task could be started.
795    #[doc(alias = "gst_pad_start_task")]
796    fn start_task<F: FnMut() + Send + 'static>(&self, func: F) -> Result<(), glib::BoolError> {
797        unsafe extern "C" fn trampoline_pad_task<F: FnMut() + Send + 'static>(func: gpointer) {
798            let (func, pad) = &mut *(func as *mut (F, *mut ffi::GstPad));
799            let pad = Pad::from_glib_borrow(*pad);
800            let result = panic::catch_unwind(AssertUnwindSafe(func));
801
802            if let Err(err) = result {
803                let element = match pad.parent_element() {
804                    Some(element) => element,
805                    None => panic::resume_unwind(err),
806                };
807
808                if pad.pause_task().is_err() {
809                    crate::error!(crate::CAT_RUST, "could not stop pad task on panic");
810                }
811
812                crate::subclass::post_panic_error_message(&element, pad.upcast_ref(), Some(err));
813            }
814        }
815
816        fn into_raw_pad_task<F: FnMut() + Send + 'static>(
817            func: F,
818            pad: *mut ffi::GstPad,
819        ) -> gpointer {
820            #[allow(clippy::type_complexity)]
821            let func: Box<(F, *mut ffi::GstPad)> = Box::new((func, pad));
822            Box::into_raw(func) as gpointer
823        }
824
825        unsafe extern "C" fn destroy_closure_pad_task<F>(ptr: gpointer) {
826            let _ = Box::<(F, *mut ffi::GstPad)>::from_raw(ptr as *mut _);
827        }
828
829        unsafe {
830            glib::result_from_gboolean!(
831                ffi::gst_pad_start_task(
832                    self.as_ref().to_glib_none().0,
833                    Some(trampoline_pad_task::<F>),
834                    into_raw_pad_task(func, self.upcast_ref().as_ptr()),
835                    Some(destroy_closure_pad_task::<F>),
836                ),
837                "Failed to start pad task",
838            )
839        }
840    }
841    /// Queries the peer pad of a given sink pad to convert `src_val` in `src_format`
842    /// to `dest_format`.
843    /// ## `src_format`
844    /// a [`Format`][crate::Format] to convert from.
845    /// ## `src_val`
846    /// a value to convert.
847    /// ## `dest_format`
848    /// the [`Format`][crate::Format] to convert to.
849    ///
850    /// # Returns
851    ///
852    /// [`true`] if the query could be performed.
853    ///
854    /// ## `dest_val`
855    /// a pointer to the result.
856    #[doc(alias = "gst_pad_peer_query_convert")]
857    fn peer_query_convert<U: SpecificFormattedValueFullRange>(
858        &self,
859        src_val: impl FormattedValue,
860    ) -> Option<U> {
861        unsafe {
862            let mut dest_val = mem::MaybeUninit::uninit();
863            let ret = from_glib(ffi::gst_pad_peer_query_convert(
864                self.as_ref().to_glib_none().0,
865                src_val.format().into_glib(),
866                src_val.into_raw_value(),
867                U::default_format().into_glib(),
868                dest_val.as_mut_ptr(),
869            ));
870            if ret {
871                Some(U::from_raw(U::default_format(), dest_val.assume_init()))
872            } else {
873                None
874            }
875        }
876    }
877
878    #[doc(alias = "gst_pad_peer_query_convert")]
879    fn peer_query_convert_generic(
880        &self,
881        src_val: impl FormattedValue,
882        dest_format: Format,
883    ) -> Option<GenericFormattedValue> {
884        unsafe {
885            let mut dest_val = mem::MaybeUninit::uninit();
886            let ret = from_glib(ffi::gst_pad_peer_query_convert(
887                self.as_ref().to_glib_none().0,
888                src_val.format().into_glib(),
889                src_val.into_raw_value(),
890                dest_format.into_glib(),
891                dest_val.as_mut_ptr(),
892            ));
893            if ret {
894                Some(GenericFormattedValue::new(
895                    dest_format,
896                    dest_val.assume_init(),
897                ))
898            } else {
899                None
900            }
901        }
902    }
903
904    /// Queries the peer pad of a given sink pad for the total stream duration.
905    /// ## `format`
906    /// the [`Format`][crate::Format] requested
907    ///
908    /// # Returns
909    ///
910    /// [`true`] if the query could be performed.
911    ///
912    /// ## `duration`
913    /// a location in which to store the total
914    ///  duration, or [`None`].
915    #[doc(alias = "gst_pad_peer_query_duration")]
916    fn peer_query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
917        unsafe {
918            let mut duration = mem::MaybeUninit::uninit();
919            let ret = from_glib(ffi::gst_pad_peer_query_duration(
920                self.as_ref().to_glib_none().0,
921                T::default_format().into_glib(),
922                duration.as_mut_ptr(),
923            ));
924            if ret {
925                try_from_glib(duration.assume_init()).ok()
926            } else {
927                None
928            }
929        }
930    }
931
932    #[doc(alias = "gst_pad_peer_query_duration")]
933    fn peer_query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
934        unsafe {
935            let mut duration = mem::MaybeUninit::uninit();
936            let ret = from_glib(ffi::gst_pad_peer_query_duration(
937                self.as_ref().to_glib_none().0,
938                format.into_glib(),
939                duration.as_mut_ptr(),
940            ));
941            if ret {
942                Some(GenericFormattedValue::new(format, duration.assume_init()))
943            } else {
944                None
945            }
946        }
947    }
948
949    /// Queries the peer of a given sink pad for the stream position.
950    /// ## `format`
951    /// the [`Format`][crate::Format] requested
952    ///
953    /// # Returns
954    ///
955    /// [`true`] if the query could be performed.
956    ///
957    /// ## `cur`
958    /// a location in which to store the current
959    ///  position, or [`None`].
960    #[doc(alias = "gst_pad_peer_query_position")]
961    fn peer_query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
962        unsafe {
963            let mut cur = mem::MaybeUninit::uninit();
964            let ret = from_glib(ffi::gst_pad_peer_query_position(
965                self.as_ref().to_glib_none().0,
966                T::default_format().into_glib(),
967                cur.as_mut_ptr(),
968            ));
969            if ret {
970                try_from_glib(cur.assume_init()).ok()
971            } else {
972                None
973            }
974        }
975    }
976
977    #[doc(alias = "gst_pad_peer_query_position")]
978    fn peer_query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
979        unsafe {
980            let mut cur = mem::MaybeUninit::uninit();
981            let ret = from_glib(ffi::gst_pad_peer_query_position(
982                self.as_ref().to_glib_none().0,
983                format.into_glib(),
984                cur.as_mut_ptr(),
985            ));
986            if ret {
987                Some(GenericFormattedValue::new(format, cur.assume_init()))
988            } else {
989                None
990            }
991        }
992    }
993
994    /// Queries a pad to convert `src_val` in `src_format` to `dest_format`.
995    /// ## `src_format`
996    /// a [`Format`][crate::Format] to convert from.
997    /// ## `src_val`
998    /// a value to convert.
999    /// ## `dest_format`
1000    /// the [`Format`][crate::Format] to convert to.
1001    ///
1002    /// # Returns
1003    ///
1004    /// [`true`] if the query could be performed.
1005    ///
1006    /// ## `dest_val`
1007    /// a pointer to the result.
1008    #[doc(alias = "gst_pad_query_convert")]
1009    fn query_convert<U: SpecificFormattedValueFullRange>(
1010        &self,
1011        src_val: impl FormattedValue,
1012    ) -> Option<U> {
1013        unsafe {
1014            let mut dest_val = mem::MaybeUninit::uninit();
1015            let ret = from_glib(ffi::gst_pad_query_convert(
1016                self.as_ref().to_glib_none().0,
1017                src_val.format().into_glib(),
1018                src_val.into_raw_value(),
1019                U::default_format().into_glib(),
1020                dest_val.as_mut_ptr(),
1021            ));
1022            if ret {
1023                Some(U::from_raw(U::default_format(), dest_val.assume_init()))
1024            } else {
1025                None
1026            }
1027        }
1028    }
1029
1030    #[doc(alias = "gst_pad_query_convert")]
1031    fn query_convert_generic(
1032        &self,
1033        src_val: impl FormattedValue,
1034        dest_format: Format,
1035    ) -> Option<GenericFormattedValue> {
1036        unsafe {
1037            let mut dest_val = mem::MaybeUninit::uninit();
1038            let ret = from_glib(ffi::gst_pad_query_convert(
1039                self.as_ref().to_glib_none().0,
1040                src_val.format().into_glib(),
1041                src_val.into_raw_value(),
1042                dest_format.into_glib(),
1043                dest_val.as_mut_ptr(),
1044            ));
1045            if ret {
1046                Some(GenericFormattedValue::new(
1047                    dest_format,
1048                    dest_val.assume_init(),
1049                ))
1050            } else {
1051                None
1052            }
1053        }
1054    }
1055
1056    /// Queries a pad for the total stream duration.
1057    /// ## `format`
1058    /// the [`Format`][crate::Format] requested
1059    ///
1060    /// # Returns
1061    ///
1062    /// [`true`] if the query could be performed.
1063    ///
1064    /// ## `duration`
1065    /// a location in which to store the total
1066    ///  duration, or [`None`].
1067    #[doc(alias = "gst_pad_query_duration")]
1068    fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
1069        unsafe {
1070            let mut duration = mem::MaybeUninit::uninit();
1071            let ret = from_glib(ffi::gst_pad_query_duration(
1072                self.as_ref().to_glib_none().0,
1073                T::default_format().into_glib(),
1074                duration.as_mut_ptr(),
1075            ));
1076            if ret {
1077                try_from_glib(duration.assume_init()).ok()
1078            } else {
1079                None
1080            }
1081        }
1082    }
1083
1084    #[doc(alias = "gst_pad_query_duration")]
1085    fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
1086        unsafe {
1087            let mut duration = mem::MaybeUninit::uninit();
1088            let ret = from_glib(ffi::gst_pad_query_duration(
1089                self.as_ref().to_glib_none().0,
1090                format.into_glib(),
1091                duration.as_mut_ptr(),
1092            ));
1093            if ret {
1094                Some(GenericFormattedValue::new(format, duration.assume_init()))
1095            } else {
1096                None
1097            }
1098        }
1099    }
1100
1101    /// Queries a pad for the stream position.
1102    /// ## `format`
1103    /// the [`Format`][crate::Format] requested
1104    ///
1105    /// # Returns
1106    ///
1107    /// [`true`] if the query could be performed.
1108    ///
1109    /// ## `cur`
1110    /// A location in which to store the current position, or [`None`].
1111    #[doc(alias = "gst_pad_query_position")]
1112    fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
1113        unsafe {
1114            let mut cur = mem::MaybeUninit::uninit();
1115            let ret = from_glib(ffi::gst_pad_query_position(
1116                self.as_ref().to_glib_none().0,
1117                T::default_format().into_glib(),
1118                cur.as_mut_ptr(),
1119            ));
1120            if ret {
1121                try_from_glib(cur.assume_init()).ok()
1122            } else {
1123                None
1124            }
1125        }
1126    }
1127
1128    #[doc(alias = "gst_pad_query_position")]
1129    fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
1130        unsafe {
1131            let mut cur = mem::MaybeUninit::uninit();
1132            let ret = from_glib(ffi::gst_pad_query_position(
1133                self.as_ref().to_glib_none().0,
1134                format.into_glib(),
1135                cur.as_mut_ptr(),
1136            ));
1137            if ret {
1138                Some(GenericFormattedValue::new(format, cur.assume_init()))
1139            } else {
1140                None
1141            }
1142        }
1143    }
1144
1145    #[doc(alias = "get_mode")]
1146    #[doc(alias = "GST_PAD_MODE")]
1147    fn mode(&self) -> crate::PadMode {
1148        unsafe {
1149            let ptr: &ffi::GstPad = &*(self.as_ptr() as *const _);
1150            from_glib(ptr.mode)
1151        }
1152    }
1153
1154    /// Iterates all sticky events on `self` and calls `foreach_func` for every
1155    /// event. If `foreach_func` returns [`false`] the iteration is immediately stopped.
1156    /// ## `foreach_func`
1157    /// the
1158    ///  `GstPadStickyEventsForeachFunction` that should be called for every event.
1159    #[doc(alias = "gst_pad_sticky_events_foreach")]
1160    fn sticky_events_foreach<
1161        F: FnMut(&Event) -> ControlFlow<EventForeachAction, EventForeachAction>,
1162    >(
1163        &self,
1164        func: F,
1165    ) {
1166        unsafe extern "C" fn trampoline<
1167            F: FnMut(&Event) -> ControlFlow<EventForeachAction, EventForeachAction>,
1168        >(
1169            _pad: *mut ffi::GstPad,
1170            event: *mut *mut ffi::GstEvent,
1171            user_data: glib::ffi::gpointer,
1172        ) -> glib::ffi::gboolean {
1173            let func = user_data as *mut F;
1174            let res = (*func)(&from_glib_borrow(*event));
1175
1176            let (do_continue, ev_action) = match res {
1177                ControlFlow::Continue(ev_action) => (glib::ffi::GTRUE, ev_action),
1178                ControlFlow::Break(ev_action) => (glib::ffi::GFALSE, ev_action),
1179            };
1180
1181            use EventForeachAction::*;
1182
1183            match ev_action {
1184                Keep => (), // do nothing
1185                Remove => {
1186                    ffi::gst_mini_object_unref(*event as *mut _);
1187                    *event = ptr::null_mut();
1188                }
1189                Replace(ev) => {
1190                    ffi::gst_mini_object_unref(*event as *mut _);
1191                    *event = ev.into_glib_ptr();
1192                }
1193            }
1194
1195            do_continue
1196        }
1197
1198        unsafe {
1199            let mut func = func;
1200            let func_ptr = &mut func as *mut F as glib::ffi::gpointer;
1201
1202            ffi::gst_pad_sticky_events_foreach(
1203                self.as_ref().to_glib_none().0,
1204                Some(trampoline::<F>),
1205                func_ptr,
1206            );
1207        }
1208    }
1209
1210    /// Returns a new reference of the sticky event of type `event_type`
1211    /// from the event.
1212    /// ## `event_type`
1213    /// the [`EventType`][crate::EventType] that should be retrieved.
1214    /// ## `idx`
1215    /// the index of the event
1216    ///
1217    /// # Returns
1218    ///
1219    /// a [`Event`][crate::Event] of type
1220    /// `event_type` or [`None`] when no event of `event_type` was on
1221    /// `self`. Unref after usage.
1222    #[doc(alias = "gst_pad_get_sticky_event")]
1223    #[doc(alias = "get_sticky_event")]
1224    fn sticky_event<T: crate::event::StickyEventType>(&self, idx: u32) -> Option<T::Owned> {
1225        unsafe {
1226            let ptr = ffi::gst_pad_get_sticky_event(
1227                self.as_ref().to_glib_none().0,
1228                T::TYPE.into_glib(),
1229                idx,
1230            );
1231
1232            if ptr.is_null() {
1233                None
1234            } else {
1235                Some(T::from_event(from_glib_full(ptr)))
1236            }
1237        }
1238    }
1239
1240    fn set_pad_flags(&self, flags: PadFlags) {
1241        unsafe {
1242            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1243            let _guard = self.as_ref().object_lock();
1244            (*ptr).flags |= flags.into_glib();
1245        }
1246    }
1247
1248    fn unset_pad_flags(&self, flags: PadFlags) {
1249        unsafe {
1250            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1251            let _guard = self.as_ref().object_lock();
1252            (*ptr).flags &= !flags.into_glib();
1253        }
1254    }
1255
1256    #[doc(alias = "get_pad_flags")]
1257    fn pad_flags(&self) -> PadFlags {
1258        unsafe {
1259            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1260            let _guard = self.as_ref().object_lock();
1261            from_glib((*ptr).flags)
1262        }
1263    }
1264}
1265
1266impl<O: IsA<Pad>> PadExtManual for O {}
1267
1268unsafe fn create_probe_info<'a>(
1269    info: *mut ffi::GstPadProbeInfo,
1270) -> (PadProbeInfo<'a>, Option<glib::Type>) {
1271    let mut data_type = None;
1272    let flow_res = try_from_glib((*info).ABI.abi.flow_ret);
1273    let info = PadProbeInfo {
1274        mask: from_glib((*info).type_),
1275        id: Some(PadProbeId(NonZeroU64::new_unchecked((*info).id as _))),
1276        offset: (*info).offset,
1277        size: (*info).size,
1278        data: if (*info).data.is_null() {
1279            None
1280        } else {
1281            let data = (*info).data as *mut ffi::GstMiniObject;
1282            (*info).data = ptr::null_mut();
1283            if (*data).type_ == Buffer::static_type().into_glib() {
1284                data_type = Some(Buffer::static_type());
1285                Some(PadProbeData::Buffer(from_glib_full(
1286                    data as *const ffi::GstBuffer,
1287                )))
1288            } else if (*data).type_ == BufferList::static_type().into_glib() {
1289                data_type = Some(BufferList::static_type());
1290                Some(PadProbeData::BufferList(from_glib_full(
1291                    data as *const ffi::GstBufferList,
1292                )))
1293            } else if (*data).type_ == Query::static_type().into_glib() {
1294                data_type = Some(Query::static_type());
1295                Some(PadProbeData::Query(QueryRef::from_mut_ptr(
1296                    data as *mut ffi::GstQuery,
1297                )))
1298            } else if (*data).type_ == Event::static_type().into_glib() {
1299                data_type = Some(Event::static_type());
1300                Some(PadProbeData::Event(from_glib_full(
1301                    data as *const ffi::GstEvent,
1302                )))
1303            } else {
1304                Some(PadProbeData::__Unknown(data))
1305            }
1306        },
1307        flow_res,
1308    };
1309    (info, data_type)
1310}
1311
1312unsafe fn update_probe_info(
1313    ret: PadProbeReturn,
1314    probe_info: PadProbeInfo,
1315    data_type: Option<glib::Type>,
1316    info: *mut ffi::GstPadProbeInfo,
1317) {
1318    if ret == PadProbeReturn::Handled {
1319        // Handled queries need to be returned
1320        // Handled buffers and buffer lists are consumed
1321        // No other types can safely be used here
1322
1323        match probe_info.data {
1324            Some(PadProbeData::Query(query)) => {
1325                assert_eq!(data_type, Some(Query::static_type()));
1326                (*info).data = query.as_mut_ptr() as *mut libc::c_void;
1327            }
1328            Some(PadProbeData::Buffer(_)) => {
1329                assert_eq!(data_type, Some(Buffer::static_type()));
1330                // Buffer not consumed by probe; consume it here
1331            }
1332            Some(PadProbeData::BufferList(_)) => {
1333                assert_eq!(data_type, Some(BufferList::static_type()));
1334                // BufferList not consumed by probe; consume it here
1335            }
1336            Some(PadProbeData::Event(_)) => {
1337                assert_eq!(data_type, Some(Event::static_type()));
1338                // Event not consumed by probe; consume it here
1339            }
1340            None if data_type == Some(Buffer::static_type())
1341                || data_type == Some(BufferList::static_type())
1342                || data_type == Some(Event::static_type()) =>
1343            {
1344                // Buffer or Event consumed by probe
1345                (*info).data = ptr::null_mut();
1346            }
1347            other => panic!("Bad data for {data_type:?} pad probe returning Handled: {other:?}"),
1348        }
1349    } else if ret == PadProbeReturn::Drop {
1350        // We may have consumed the object via PadProbeInfo::take_*() functions
1351        match probe_info.data {
1352            None if data_type == Some(Buffer::static_type())
1353                || data_type == Some(BufferList::static_type())
1354                || data_type == Some(Event::static_type()) =>
1355            {
1356                (*info).data = ptr::null_mut();
1357            }
1358            _ => {
1359                // Nothing to do, it's going to be dropped
1360            }
1361        }
1362    } else {
1363        match probe_info.data {
1364            Some(PadProbeData::Buffer(buffer)) => {
1365                assert_eq!(data_type, Some(Buffer::static_type()));
1366                (*info).data = buffer.into_glib_ptr() as *mut libc::c_void;
1367            }
1368            Some(PadProbeData::BufferList(bufferlist)) => {
1369                assert_eq!(data_type, Some(BufferList::static_type()));
1370                (*info).data = bufferlist.into_glib_ptr() as *mut libc::c_void;
1371            }
1372            Some(PadProbeData::Event(event)) => {
1373                assert_eq!(data_type, Some(Event::static_type()));
1374                (*info).data = event.into_glib_ptr() as *mut libc::c_void;
1375            }
1376            Some(PadProbeData::Query(query)) => {
1377                assert_eq!(data_type, Some(Query::static_type()));
1378                (*info).data = query.as_mut_ptr() as *mut libc::c_void;
1379            }
1380            Some(PadProbeData::__Unknown(ptr)) => {
1381                assert_eq!(data_type, None);
1382                (*info).data = ptr as *mut libc::c_void;
1383            }
1384            None => {
1385                assert_eq!(data_type, None);
1386            }
1387        }
1388    }
1389
1390    let flow_ret: FlowReturn = probe_info.flow_res.into();
1391    (*info).ABI.abi.flow_ret = flow_ret.into_glib();
1392}
1393
1394unsafe extern "C" fn trampoline_pad_probe<
1395    T,
1396    F: Fn(&T, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
1397>(
1398    pad: *mut ffi::GstPad,
1399    info: *mut ffi::GstPadProbeInfo,
1400    func: gpointer,
1401) -> ffi::GstPadProbeReturn
1402where
1403    T: IsA<Pad>,
1404{
1405    let func: &F = &*(func as *const F);
1406
1407    let (mut probe_info, data_type) = create_probe_info(info);
1408
1409    let ret = func(
1410        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1411        &mut probe_info,
1412    );
1413
1414    update_probe_info(ret, probe_info, data_type, info);
1415
1416    ret.into_glib()
1417}
1418
1419unsafe extern "C" fn trampoline_activate_function<
1420    T,
1421    F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
1422>(
1423    pad: *mut ffi::GstPad,
1424    parent: *mut ffi::GstObject,
1425) -> glib::ffi::gboolean
1426where
1427    T: IsA<Pad>,
1428{
1429    let func: &F = &*((*pad).activatedata as *const F);
1430
1431    match func(
1432        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1433        Option::<crate::Object>::from_glib_borrow(parent)
1434            .as_ref()
1435            .as_ref(),
1436    ) {
1437        Ok(()) => true,
1438        Err(err) => {
1439            err.log_with_object(&*Pad::from_glib_borrow(pad));
1440            false
1441        }
1442    }
1443    .into_glib()
1444}
1445
1446unsafe extern "C" fn trampoline_activatemode_function<
1447    T,
1448    F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
1449        + Send
1450        + Sync
1451        + 'static,
1452>(
1453    pad: *mut ffi::GstPad,
1454    parent: *mut ffi::GstObject,
1455    mode: ffi::GstPadMode,
1456    active: glib::ffi::gboolean,
1457) -> glib::ffi::gboolean
1458where
1459    T: IsA<Pad>,
1460{
1461    let func: &F = &*((*pad).activatemodedata as *const F);
1462
1463    match func(
1464        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1465        Option::<crate::Object>::from_glib_borrow(parent)
1466            .as_ref()
1467            .as_ref(),
1468        from_glib(mode),
1469        from_glib(active),
1470    ) {
1471        Ok(()) => true,
1472        Err(err) => {
1473            err.log_with_object(&*Pad::from_glib_borrow(pad));
1474            false
1475        }
1476    }
1477    .into_glib()
1478}
1479
1480unsafe extern "C" fn trampoline_chain_function<
1481    T,
1482    F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
1483        + Send
1484        + Sync
1485        + 'static,
1486>(
1487    pad: *mut ffi::GstPad,
1488    parent: *mut ffi::GstObject,
1489    buffer: *mut ffi::GstBuffer,
1490) -> ffi::GstFlowReturn
1491where
1492    T: IsA<Pad>,
1493{
1494    let func: &F = &*((*pad).chaindata as *const F);
1495
1496    let res: FlowReturn = func(
1497        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1498        Option::<crate::Object>::from_glib_borrow(parent)
1499            .as_ref()
1500            .as_ref(),
1501        from_glib_full(buffer),
1502    )
1503    .into();
1504    res.into_glib()
1505}
1506
1507unsafe extern "C" fn trampoline_chain_list_function<
1508    T,
1509    F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
1510        + Send
1511        + Sync
1512        + 'static,
1513>(
1514    pad: *mut ffi::GstPad,
1515    parent: *mut ffi::GstObject,
1516    list: *mut ffi::GstBufferList,
1517) -> ffi::GstFlowReturn
1518where
1519    T: IsA<Pad>,
1520{
1521    let func: &F = &*((*pad).chainlistdata as *const F);
1522
1523    let res: FlowReturn = func(
1524        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1525        Option::<crate::Object>::from_glib_borrow(parent)
1526            .as_ref()
1527            .as_ref(),
1528        from_glib_full(list),
1529    )
1530    .into();
1531    res.into_glib()
1532}
1533
1534unsafe extern "C" fn trampoline_event_function<
1535    T,
1536    F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
1537>(
1538    pad: *mut ffi::GstPad,
1539    parent: *mut ffi::GstObject,
1540    event: *mut ffi::GstEvent,
1541) -> glib::ffi::gboolean
1542where
1543    T: IsA<Pad>,
1544{
1545    let func: &F = &*((*pad).eventdata as *const F);
1546
1547    func(
1548        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1549        Option::<crate::Object>::from_glib_borrow(parent)
1550            .as_ref()
1551            .as_ref(),
1552        from_glib_full(event),
1553    )
1554    .into_glib()
1555}
1556
1557unsafe extern "C" fn trampoline_event_full_function<
1558    T,
1559    F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
1560        + Send
1561        + Sync
1562        + 'static,
1563>(
1564    pad: *mut ffi::GstPad,
1565    parent: *mut ffi::GstObject,
1566    event: *mut ffi::GstEvent,
1567) -> ffi::GstFlowReturn
1568where
1569    T: IsA<Pad>,
1570{
1571    let func: &F = &*((*pad).eventdata as *const F);
1572
1573    let res: FlowReturn = func(
1574        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1575        Option::<crate::Object>::from_glib_borrow(parent)
1576            .as_ref()
1577            .as_ref(),
1578        from_glib_full(event),
1579    )
1580    .into();
1581    res.into_glib()
1582}
1583
1584#[allow(clippy::needless_option_as_deref)]
1585unsafe extern "C" fn trampoline_getrange_function<
1586    T,
1587    F: Fn(
1588            &T,
1589            Option<&crate::Object>,
1590            u64,
1591            Option<&mut crate::BufferRef>,
1592            u32,
1593        ) -> Result<PadGetRangeSuccess, crate::FlowError>
1594        + Send
1595        + Sync
1596        + 'static,
1597>(
1598    pad: *mut ffi::GstPad,
1599    parent: *mut ffi::GstObject,
1600    offset: u64,
1601    length: u32,
1602    buffer: *mut *mut ffi::GstBuffer,
1603) -> ffi::GstFlowReturn
1604where
1605    T: IsA<Pad>,
1606{
1607    let func: &F = &*((*pad).getrangedata as *const F);
1608
1609    debug_assert!(!buffer.is_null());
1610
1611    let pad = Pad::from_glib_borrow(pad);
1612    let pad = pad.unsafe_cast_ref();
1613    let mut passed_buffer = if (*buffer).is_null() {
1614        None
1615    } else {
1616        Some(crate::BufferRef::from_mut_ptr(*buffer))
1617    };
1618
1619    match func(
1620        pad,
1621        Option::<crate::Object>::from_glib_borrow(parent)
1622            .as_ref()
1623            .as_ref(),
1624        offset,
1625        passed_buffer.as_deref_mut(),
1626        length,
1627    ) {
1628        Ok(PadGetRangeSuccess::NewBuffer(new_buffer)) => {
1629            if let Some(passed_buffer) = passed_buffer {
1630                crate::debug!(
1631                    crate::CAT_PERFORMANCE,
1632                    obj = pad.unsafe_cast_ref::<glib::Object>(),
1633                    "Returned new buffer from getrange function, copying into passed buffer"
1634                );
1635
1636                let mut map = match passed_buffer.map_writable() {
1637                    Ok(map) => map,
1638                    Err(_) => {
1639                        crate::error!(
1640                            crate::CAT_RUST,
1641                            obj = pad.unsafe_cast_ref::<glib::Object>(),
1642                            "Failed to map passed buffer writable"
1643                        );
1644                        return ffi::GST_FLOW_ERROR;
1645                    }
1646                };
1647
1648                let copied_size = new_buffer.copy_to_slice(0, &mut map);
1649                drop(map);
1650
1651                if let Err(copied_size) = copied_size {
1652                    passed_buffer.set_size(copied_size);
1653                }
1654
1655                match new_buffer.copy_into(passed_buffer, crate::BUFFER_COPY_METADATA, ..) {
1656                    Ok(_) => FlowReturn::Ok.into_glib(),
1657                    Err(_) => {
1658                        crate::error!(
1659                            crate::CAT_RUST,
1660                            obj = pad.unsafe_cast_ref::<glib::Object>(),
1661                            "Failed to copy buffer metadata"
1662                        );
1663
1664                        FlowReturn::Error.into_glib()
1665                    }
1666                }
1667            } else {
1668                *buffer = new_buffer.into_glib_ptr();
1669                FlowReturn::Ok.into_glib()
1670            }
1671        }
1672        Ok(PadGetRangeSuccess::FilledBuffer) => {
1673            assert!(passed_buffer.is_some());
1674            FlowReturn::Ok.into_glib()
1675        }
1676        Err(ret) => FlowReturn::from_error(ret).into_glib(),
1677    }
1678}
1679
1680unsafe extern "C" fn trampoline_iterate_internal_links_function<
1681    T,
1682    F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
1683>(
1684    pad: *mut ffi::GstPad,
1685    parent: *mut ffi::GstObject,
1686) -> *mut ffi::GstIterator
1687where
1688    T: IsA<Pad>,
1689{
1690    let func: &F = &*((*pad).iterintlinkdata as *const F);
1691
1692    // Steal the iterator and return it
1693    let ret = func(
1694        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1695        Option::<crate::Object>::from_glib_borrow(parent)
1696            .as_ref()
1697            .as_ref(),
1698    );
1699
1700    ret.into_glib_ptr()
1701}
1702
1703unsafe extern "C" fn trampoline_link_function<
1704    T,
1705    F: Fn(
1706            &T,
1707            Option<&crate::Object>,
1708            &crate::Pad,
1709        ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
1710        + Send
1711        + Sync
1712        + 'static,
1713>(
1714    pad: *mut ffi::GstPad,
1715    parent: *mut ffi::GstObject,
1716    peer: *mut ffi::GstPad,
1717) -> ffi::GstPadLinkReturn
1718where
1719    T: IsA<Pad>,
1720{
1721    let func: &F = &*((*pad).linkdata as *const F);
1722
1723    let res: crate::PadLinkReturn = func(
1724        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1725        Option::<crate::Object>::from_glib_borrow(parent)
1726            .as_ref()
1727            .as_ref(),
1728        &from_glib_borrow(peer),
1729    )
1730    .into();
1731    res.into_glib()
1732}
1733
1734unsafe extern "C" fn trampoline_query_function<
1735    T,
1736    F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
1737>(
1738    pad: *mut ffi::GstPad,
1739    parent: *mut ffi::GstObject,
1740    query: *mut ffi::GstQuery,
1741) -> glib::ffi::gboolean
1742where
1743    T: IsA<Pad>,
1744{
1745    let func: &F = &*((*pad).querydata as *const F);
1746
1747    func(
1748        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1749        Option::<crate::Object>::from_glib_borrow(parent)
1750            .as_ref()
1751            .as_ref(),
1752        crate::QueryRef::from_mut_ptr(query),
1753    )
1754    .into_glib()
1755}
1756
1757unsafe extern "C" fn trampoline_unlink_function<
1758    T,
1759    F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
1760>(
1761    pad: *mut ffi::GstPad,
1762    parent: *mut ffi::GstObject,
1763) where
1764    T: IsA<Pad>,
1765{
1766    let func: &F = &*((*pad).unlinkdata as *const F);
1767
1768    func(
1769        Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1770        Option::<crate::Object>::from_glib_borrow(parent)
1771            .as_ref()
1772            .as_ref(),
1773    )
1774}
1775
1776unsafe extern "C" fn destroy_closure<F>(ptr: gpointer) {
1777    let _ = Box::<F>::from_raw(ptr as *mut _);
1778}
1779
1780impl Pad {
1781    // rustdoc-stripper-ignore-next
1782    /// Creates a new [`Pad`] with the specified [`PadDirection`](crate::PadDirection).
1783    ///
1784    /// The [`Pad`] will be assigned the usual `gst::Object` generated unique name.
1785    ///
1786    /// Use [`Pad::builder()`] to get a [`PadBuilder`] and define options.
1787    // rustdoc-stripper-ignore-next-stop
1788    /// Creates a new pad with the given name in the given direction.
1789    /// If name is [`None`], a guaranteed unique name (across all pads)
1790    /// will be assigned.
1791    /// This function makes a copy of the name so you can safely free the name.
1792    /// ## `name`
1793    /// the name of the new pad.
1794    /// ## `direction`
1795    /// the [`PadDirection`][crate::PadDirection] of the pad.
1796    ///
1797    /// # Returns
1798    ///
1799    /// a new [`Pad`][crate::Pad].
1800    ///
1801    /// MT safe.
1802    #[doc(alias = "gst_pad_new")]
1803    pub fn new(direction: crate::PadDirection) -> Self {
1804        skip_assert_initialized!();
1805        Self::builder(direction).build()
1806    }
1807
1808    // rustdoc-stripper-ignore-next
1809    /// Creates a [`PadBuilder`] with the specified [`PadDirection`](crate::PadDirection).
1810    #[doc(alias = "gst_pad_new")]
1811    pub fn builder(direction: crate::PadDirection) -> PadBuilder<Self> {
1812        skip_assert_initialized!();
1813        PadBuilder::new(direction)
1814    }
1815
1816    // rustdoc-stripper-ignore-next
1817    /// Creates a new [`Pad`] from the [`StaticPadTemplate`](crate::StaticPadTemplate).
1818    ///
1819    /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`,
1820    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
1821    /// the `Pad` will automatically be named after the `name_template`.
1822    ///
1823    /// Use [`Pad::builder_from_static_template()`] to get a [`PadBuilder`] and define options.
1824    ///
1825    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
1826    /// automatically generated unique name.
1827    ///
1828    /// # Panics
1829    ///
1830    /// Panics if the `name_template` is a wildcard-name.
1831    // rustdoc-stripper-ignore-next-stop
1832    /// Creates a new pad with the given name from the given static template.
1833    /// If name is [`None`], a guaranteed unique name (across all pads)
1834    /// will be assigned.
1835    /// This function makes a copy of the name so you can safely free the name.
1836    /// ## `templ`
1837    /// the [`StaticPadTemplate`][crate::StaticPadTemplate] to use
1838    /// ## `name`
1839    /// the name of the pad
1840    ///
1841    /// # Returns
1842    ///
1843    /// a new [`Pad`][crate::Pad].
1844    #[doc(alias = "gst_pad_new_from_static_template")]
1845    pub fn from_static_template(templ: &StaticPadTemplate) -> Self {
1846        skip_assert_initialized!();
1847        Self::builder_from_static_template(templ).build()
1848    }
1849
1850    // rustdoc-stripper-ignore-next
1851    /// Creates a new [`PadBuilder`] from the [`StaticPadTemplate`](crate::StaticPadTemplate).
1852    ///
1853    /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`,
1854    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
1855    /// the `Pad` will automatically be named after the `name_template`.
1856    ///
1857    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
1858    /// automatically generated unique name.
1859    #[doc(alias = "gst_pad_new_from_static_template")]
1860    pub fn builder_from_static_template(templ: &StaticPadTemplate) -> PadBuilder<Self> {
1861        skip_assert_initialized!();
1862        PadBuilder::from_static_template(templ)
1863    }
1864
1865    // rustdoc-stripper-ignore-next
1866    /// Creates a new [`Pad`] from the [`PadTemplate`](crate::PadTemplate).
1867    ///
1868    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
1869    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
1870    /// the `Pad` will automatically be named after the `name_template`.
1871    ///
1872    /// Use [`Pad::builder_from_template()`] to get a [`PadBuilder`] and define options.
1873    ///
1874    /// # Panics
1875    ///
1876    /// Panics if the `name_template` is a wildcard-name.
1877    // rustdoc-stripper-ignore-next-stop
1878    /// Creates a new pad with the given name from the given template.
1879    /// If name is [`None`], a guaranteed unique name (across all pads)
1880    /// will be assigned.
1881    /// This function makes a copy of the name so you can safely free the name.
1882    /// ## `templ`
1883    /// the pad template to use
1884    /// ## `name`
1885    /// the name of the pad
1886    ///
1887    /// # Returns
1888    ///
1889    /// a new [`Pad`][crate::Pad].
1890    #[doc(alias = "gst_pad_new_from_template")]
1891    pub fn from_template(templ: &crate::PadTemplate) -> Self {
1892        skip_assert_initialized!();
1893        Self::builder_from_template(templ).build()
1894    }
1895
1896    // rustdoc-stripper-ignore-next
1897    /// Creates a new [`PadBuilder`] from the [`PadTemplate`](crate::PadTemplate).
1898    ///
1899    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
1900    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
1901    /// the `Pad` will automatically be named after the `name_template`.
1902    ///
1903    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
1904    /// automatically generated unique name.
1905    #[doc(alias = "gst_pad_new_from_template")]
1906    pub fn builder_from_template(templ: &crate::PadTemplate) -> PadBuilder<Self> {
1907        skip_assert_initialized!();
1908        PadBuilder::from_template(templ)
1909    }
1910
1911    #[doc(alias = "gst_pad_query_default")]
1912    pub fn query_default<O: IsA<Pad>>(
1913        pad: &O,
1914        parent: Option<&impl IsA<crate::Object>>,
1915        query: &mut QueryRef,
1916    ) -> bool {
1917        skip_assert_initialized!();
1918        unsafe {
1919            from_glib(ffi::gst_pad_query_default(
1920                pad.as_ref().to_glib_none().0,
1921                parent.map(|p| p.as_ref()).to_glib_none().0,
1922                query.as_mut_ptr(),
1923            ))
1924        }
1925    }
1926
1927    #[doc(alias = "gst_pad_event_default")]
1928    pub fn event_default<O: IsA<Pad>>(
1929        pad: &O,
1930        parent: Option<&impl IsA<crate::Object>>,
1931        event: impl Into<Event>,
1932    ) -> bool {
1933        skip_assert_initialized!();
1934        unsafe {
1935            from_glib(ffi::gst_pad_event_default(
1936                pad.as_ref().to_glib_none().0,
1937                parent.map(|p| p.as_ref()).to_glib_none().0,
1938                event.into().into_glib_ptr(),
1939            ))
1940        }
1941    }
1942
1943    #[doc(alias = "gst_pad_iterate_internal_links_default")]
1944    pub fn iterate_internal_links_default<O: IsA<Pad>>(
1945        pad: &O,
1946        parent: Option<&impl IsA<crate::Object>>,
1947    ) -> crate::Iterator<Pad> {
1948        skip_assert_initialized!();
1949        unsafe {
1950            from_glib_full(ffi::gst_pad_iterate_internal_links_default(
1951                pad.as_ref().to_glib_none().0,
1952                parent.map(|p| p.as_ref()).to_glib_none().0,
1953            ))
1954        }
1955    }
1956}
1957
1958pub(crate) enum PadBuilderName {
1959    Undefined,
1960    KeepGenerated,
1961    UserDefined(String),
1962    CandidateForWildcardTemplate(String),
1963}
1964
1965#[must_use = "The builder must be built to be used"]
1966pub struct PadBuilder<T> {
1967    pub(crate) pad: T,
1968    pub(crate) name: PadBuilderName,
1969}
1970
1971impl<T: IsA<Pad> + IsA<glib::Object> + glib::object::IsClass> PadBuilder<T> {
1972    // rustdoc-stripper-ignore-next
1973    /// Creates a `PadBuilder` with the specified [`PadDirection`](crate::PadDirection).
1974    pub fn new(direction: crate::PadDirection) -> Self {
1975        assert_initialized_main_thread!();
1976
1977        let pad = glib::Object::builder::<T>()
1978            .property("direction", direction)
1979            .build();
1980
1981        // Ghost pads are a bit special
1982        if let Some(pad) = pad.dynamic_cast_ref::<crate::GhostPad>() {
1983            unsafe {
1984                let res = ffi::gst_ghost_pad_construct(pad.to_glib_none().0);
1985                // This can't really fail...
1986                debug_assert_ne!(res, glib::ffi::GFALSE, "Failed to construct ghost pad");
1987            }
1988        }
1989
1990        PadBuilder {
1991            pad,
1992            name: PadBuilderName::Undefined,
1993        }
1994    }
1995
1996    // rustdoc-stripper-ignore-next
1997    /// Creates a `PadBuilder` from the specified [`StaticPadTemplate`](crate::StaticPadTemplate).
1998    ///
1999    /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`,
2000    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
2001    /// the `Pad` will automatically be named after the `name_template`.
2002    ///
2003    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
2004    /// automatically generated unique name.
2005    pub fn from_static_template(templ: &StaticPadTemplate) -> Self {
2006        skip_assert_initialized!();
2007
2008        let templ = templ.get();
2009        Self::from_template(&templ)
2010    }
2011
2012    // rustdoc-stripper-ignore-next
2013    /// Creates a `PadBuilder` from the specified [`PadTemplate`](crate::PadTemplate).
2014    ///
2015    /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`,
2016    /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`,
2017    /// the `Pad` will automatically be named after the `name_template`.
2018    ///
2019    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
2020    /// automatically generated unique name.
2021    pub fn from_template(templ: &crate::PadTemplate) -> Self {
2022        assert_initialized_main_thread!();
2023
2024        let mut type_ = T::static_type();
2025        let gtype = templ.gtype();
2026
2027        if gtype == glib::Type::UNIT {
2028            // Nothing to be done, we can create any kind of pad
2029        } else if gtype.is_a(type_) {
2030            // We were asked to create a parent type of the template type, e.g. a gst::Pad for
2031            // a template that wants a gst_base::AggregatorPad. Not a problem: update the type
2032            type_ = gtype;
2033        } else {
2034            // Otherwise the requested type must be a subclass of the template pad type
2035            assert!(type_.is_a(gtype));
2036        }
2037
2038        let mut properties = [
2039            ("direction", templ.direction().into()),
2040            ("template", templ.into()),
2041        ];
2042
2043        let pad =
2044            unsafe { glib::Object::with_mut_values(type_, &mut properties).unsafe_cast::<T>() };
2045
2046        // Ghost pads are a bit special
2047        if let Some(pad) = pad.dynamic_cast_ref::<crate::GhostPad>() {
2048            unsafe {
2049                let res = ffi::gst_ghost_pad_construct(pad.to_glib_none().0);
2050                // This can't really fail...
2051                debug_assert_ne!(res, glib::ffi::GFALSE, "Failed to construct ghost pad");
2052            }
2053        }
2054
2055        PadBuilder {
2056            pad,
2057            name: PadBuilderName::Undefined,
2058        }
2059    }
2060
2061    // rustdoc-stripper-ignore-next
2062    /// Uses the `gst::Object` generated unique name.
2063    pub fn generated_name(mut self) -> Self {
2064        self.name = PadBuilderName::KeepGenerated;
2065        self
2066    }
2067
2068    // rustdoc-stripper-ignore-next
2069    /// Sets the name of the Pad.
2070    pub fn name(mut self, name: impl Into<String>) -> Self {
2071        self.name = PadBuilderName::UserDefined(name.into());
2072
2073        self
2074    }
2075
2076    // rustdoc-stripper-ignore-next
2077    /// Optionally sets the name of the Pad.
2078    ///
2079    /// This method is convenient when the `name` is provided as an `Option`.
2080    /// If the `name` is `None`, this has no effect.
2081    #[deprecated = "use `name_if_some()` instead"]
2082    pub fn maybe_name<N: Into<String>>(self, name: Option<N>) -> Self {
2083        if let Some(name) = name {
2084            self.name(name)
2085        } else {
2086            self
2087        }
2088    }
2089
2090    // rustdoc-stripper-ignore-next
2091    /// Optionally sets the name of the Pad.
2092    ///
2093    /// This method is convenient when the `name` is provided as an `Option`.
2094    /// If the `name` is `None`, this has no effect.
2095    pub fn name_if_some<N: Into<String>>(self, name: Option<N>) -> Self {
2096        if let Some(name) = name {
2097            self.name(name)
2098        } else {
2099            self
2100        }
2101    }
2102
2103    #[doc(alias = "gst_pad_set_activate_function")]
2104    pub fn activate_function<F>(self, func: F) -> Self
2105    where
2106        F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
2107    {
2108        unsafe {
2109            self.pad.set_activate_function(func);
2110        }
2111
2112        self
2113    }
2114
2115    #[doc(alias = "gst_pad_set_activate_function")]
2116    pub fn activate_function_if_some<F>(self, func: Option<F>) -> Self
2117    where
2118        F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
2119    {
2120        if let Some(func) = func {
2121            self.activate_function(func)
2122        } else {
2123            self
2124        }
2125    }
2126
2127    #[doc(alias = "gst_pad_set_activatemode_function")]
2128    pub fn activatemode_function<F>(self, func: F) -> Self
2129    where
2130        F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
2131            + Send
2132            + Sync
2133            + 'static,
2134    {
2135        unsafe {
2136            self.pad.set_activatemode_function(func);
2137        }
2138
2139        self
2140    }
2141
2142    #[doc(alias = "gst_pad_set_activatemode_function")]
2143    pub fn activatemode_function_if_some<F>(self, func: Option<F>) -> Self
2144    where
2145        F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
2146            + Send
2147            + Sync
2148            + 'static,
2149    {
2150        if let Some(func) = func {
2151            self.activatemode_function(func)
2152        } else {
2153            self
2154        }
2155    }
2156
2157    #[doc(alias = "gst_pad_set_chain_function")]
2158    pub fn chain_function<F>(self, func: F) -> Self
2159    where
2160        F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
2161            + Send
2162            + Sync
2163            + 'static,
2164    {
2165        unsafe {
2166            self.pad.set_chain_function(func);
2167        }
2168
2169        self
2170    }
2171
2172    #[doc(alias = "gst_pad_set_chain_function")]
2173    pub fn chain_function_if_some<F>(self, func: Option<F>) -> Self
2174    where
2175        F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
2176            + Send
2177            + Sync
2178            + 'static,
2179    {
2180        if let Some(func) = func {
2181            self.chain_function(func)
2182        } else {
2183            self
2184        }
2185    }
2186
2187    #[doc(alias = "gst_pad_set_chain_list_function")]
2188    pub fn chain_list_function<F>(self, func: F) -> Self
2189    where
2190        F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
2191            + Send
2192            + Sync
2193            + 'static,
2194    {
2195        unsafe {
2196            self.pad.set_chain_list_function(func);
2197        }
2198
2199        self
2200    }
2201
2202    #[doc(alias = "gst_pad_set_chain_list_function")]
2203    pub fn chain_list_function_if_some<F>(self, func: Option<F>) -> Self
2204    where
2205        F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
2206            + Send
2207            + Sync
2208            + 'static,
2209    {
2210        if let Some(func) = func {
2211            self.chain_list_function(func)
2212        } else {
2213            self
2214        }
2215    }
2216
2217    #[doc(alias = "gst_pad_set_event_function")]
2218    pub fn event_function<F>(self, func: F) -> Self
2219    where
2220        F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
2221    {
2222        unsafe {
2223            self.pad.set_event_function(func);
2224        }
2225
2226        self
2227    }
2228
2229    #[doc(alias = "gst_pad_set_event_function")]
2230    pub fn event_function_if_some<F>(self, func: Option<F>) -> Self
2231    where
2232        F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
2233    {
2234        if let Some(func) = func {
2235            self.event_function(func)
2236        } else {
2237            self
2238        }
2239    }
2240
2241    #[doc(alias = "gst_pad_set_event_full_function")]
2242    pub fn event_full_function<F>(self, func: F) -> Self
2243    where
2244        F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
2245            + Send
2246            + Sync
2247            + 'static,
2248    {
2249        unsafe {
2250            self.pad.set_event_full_function(func);
2251        }
2252
2253        self
2254    }
2255
2256    #[doc(alias = "gst_pad_set_event_full_function")]
2257    pub fn event_full_function_if_some<F>(self, func: Option<F>) -> Self
2258    where
2259        F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
2260            + Send
2261            + Sync
2262            + 'static,
2263    {
2264        if let Some(func) = func {
2265            self.event_full_function(func)
2266        } else {
2267            self
2268        }
2269    }
2270
2271    #[doc(alias = "gst_pad_set_getrange_function")]
2272    pub fn getrange_function<F>(self, func: F) -> Self
2273    where
2274        F: Fn(
2275                &T,
2276                Option<&crate::Object>,
2277                u64,
2278                Option<&mut crate::BufferRef>,
2279                u32,
2280            ) -> Result<PadGetRangeSuccess, crate::FlowError>
2281            + Send
2282            + Sync
2283            + 'static,
2284    {
2285        unsafe {
2286            self.pad.set_getrange_function(func);
2287        }
2288
2289        self
2290    }
2291
2292    #[doc(alias = "gst_pad_set_getrange_function")]
2293    pub fn getrange_function_if_some<F>(self, func: Option<F>) -> Self
2294    where
2295        F: Fn(
2296                &T,
2297                Option<&crate::Object>,
2298                u64,
2299                Option<&mut crate::BufferRef>,
2300                u32,
2301            ) -> Result<PadGetRangeSuccess, crate::FlowError>
2302            + Send
2303            + Sync
2304            + 'static,
2305    {
2306        if let Some(func) = func {
2307            self.getrange_function(func)
2308        } else {
2309            self
2310        }
2311    }
2312
2313    #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
2314    pub fn iterate_internal_links_function<F>(self, func: F) -> Self
2315    where
2316        F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
2317    {
2318        unsafe {
2319            self.pad.set_iterate_internal_links_function(func);
2320        }
2321
2322        self
2323    }
2324
2325    #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
2326    pub fn iterate_internal_links_function_if_some<F>(self, func: Option<F>) -> Self
2327    where
2328        F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
2329    {
2330        if let Some(func) = func {
2331            self.iterate_internal_links_function(func)
2332        } else {
2333            self
2334        }
2335    }
2336
2337    #[doc(alias = "gst_pad_set_link_function")]
2338    pub fn link_function<F>(self, func: F) -> Self
2339    where
2340        F: Fn(
2341                &T,
2342                Option<&crate::Object>,
2343                &Pad,
2344            ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
2345            + Send
2346            + Sync
2347            + 'static,
2348    {
2349        unsafe {
2350            self.pad.set_link_function(func);
2351        }
2352
2353        self
2354    }
2355
2356    #[doc(alias = "gst_pad_set_link_function")]
2357    pub fn link_function_if_some<F>(self, func: Option<F>) -> Self
2358    where
2359        F: Fn(
2360                &T,
2361                Option<&crate::Object>,
2362                &Pad,
2363            ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
2364            + Send
2365            + Sync
2366            + 'static,
2367    {
2368        if let Some(func) = func {
2369            self.link_function(func)
2370        } else {
2371            self
2372        }
2373    }
2374
2375    #[doc(alias = "gst_pad_set_query_function")]
2376    pub fn query_function<F>(self, func: F) -> Self
2377    where
2378        F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
2379    {
2380        unsafe {
2381            self.pad.set_query_function(func);
2382        }
2383
2384        self
2385    }
2386
2387    #[doc(alias = "gst_pad_set_query_function")]
2388    pub fn query_function_if_some<F>(self, func: Option<F>) -> Self
2389    where
2390        F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
2391    {
2392        if let Some(func) = func {
2393            self.query_function(func)
2394        } else {
2395            self
2396        }
2397    }
2398
2399    #[doc(alias = "gst_pad_set_unlink_function")]
2400    pub fn unlink_function<F>(self, func: F) -> Self
2401    where
2402        F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
2403    {
2404        unsafe {
2405            self.pad.set_unlink_function(func);
2406        }
2407
2408        self
2409    }
2410
2411    #[doc(alias = "gst_pad_set_unlink_function")]
2412    pub fn unlink_function_if_some<F>(self, func: Option<F>) -> Self
2413    where
2414        F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
2415    {
2416        if let Some(func) = func {
2417            self.unlink_function(func)
2418        } else {
2419            self
2420        }
2421    }
2422
2423    pub fn flags(self, flags: PadFlags) -> Self {
2424        self.pad.set_pad_flags(flags);
2425
2426        self
2427    }
2428
2429    pub fn flags_if_some(self, flags: Option<PadFlags>) -> Self {
2430        if let Some(flags) = flags {
2431            self.flags(flags)
2432        } else {
2433            self
2434        }
2435    }
2436
2437    // rustdoc-stripper-ignore-next
2438    /// Builds the [`Pad`].
2439    ///
2440    /// # Panics
2441    ///
2442    /// Panics if the [`Pad`] was built from a [`PadTemplate`](crate::PadTemplate)
2443    /// with a wildcard-name `name_template` (i.e. containing `%u`, `%s` or `%d`)
2444    /// and no specific `name` was provided using [`PadBuilder::name`]
2445    /// or [`PadBuilder::name_if_some`], or for [`GhostPad`s](crate::GhostPad),
2446    /// by defining a `target`.
2447    ///
2448    /// Use [`generated_name()`](crate::PadBuilder::generated_name`) to keep the `gst::Object`
2449    /// automatically generated unique name.
2450    #[must_use = "Building the pad without using it has no effect"]
2451    #[track_caller]
2452    pub fn build(self) -> T {
2453        let Self { pad, name } = self;
2454
2455        let templ = pad.pad_template();
2456
2457        use PadBuilderName::*;
2458        match (name, templ) {
2459            (KeepGenerated, _) => (),
2460            (Undefined, None) => (),
2461            (Undefined, Some(templ)) => {
2462                if templ.name().find('%').is_some() {
2463                    panic!(concat!(
2464                        "Attempt to build a Pad from a wildcard-name template",
2465                        " or with a target Pad with an incompatible name.",
2466                        " Make sure to define a specific name using PadBuilder",
2467                        " or opt-in to keep the automatically generated name.",
2468                    ));
2469                } else {
2470                    pad.set_property("name", templ.name());
2471                }
2472            }
2473            (UserDefined(name), _) | (CandidateForWildcardTemplate(name), None) => {
2474                pad.set_property("name", name);
2475            }
2476            (CandidateForWildcardTemplate(name), Some(templ)) => {
2477                if templ.name().find('%').is_none() {
2478                    // Not a widlcard template
2479                    pad.set_property("name", templ.name());
2480                } else {
2481                    let mut can_assign_name = true;
2482
2483                    if templ.presence() == crate::PadPresence::Request {
2484                        // Check if the name is compatible with the name template.
2485                        use crate::CAT_RUST;
2486
2487                        let mut name_parts = name.split('_');
2488                        for templ_part in templ.name_template().split('_') {
2489                            let Some(name_part) = name_parts.next() else {
2490                                crate::debug!(
2491                                CAT_RUST,
2492                                "Not using Pad name '{name}': not enough parts compared to template '{}'",
2493                                templ.name_template(),
2494                            );
2495                                can_assign_name = false;
2496                                break;
2497                            };
2498
2499                            if let Some(conv_spec_start) = templ_part.find('%') {
2500                                if conv_spec_start > 0
2501                                    && !name_part.starts_with(&templ_part[..conv_spec_start])
2502                                {
2503                                    crate::debug!(
2504                                    CAT_RUST,
2505                                    "Not using Pad name '{name}': mismatch template '{}' prefix",
2506                                    templ.name_template(),
2507                                );
2508                                    can_assign_name = false;
2509                                    break;
2510                                }
2511
2512                                let conv_spec_pos = conv_spec_start + 1;
2513                                match templ_part.get(conv_spec_pos..=conv_spec_pos) {
2514                                    Some("s") => {
2515                                        // *There can be only one* %s
2516                                        break;
2517                                    }
2518                                    Some("u") => {
2519                                        if name_part
2520                                            .get(conv_spec_start..)
2521                                            .map_or(true, |s| s.parse::<u32>().is_err())
2522                                        {
2523                                            crate::debug!(
2524                                            CAT_RUST,
2525                                            "Not using Pad name '{name}': can't parse '%u' from '{name_part}' (template '{}')",
2526                                            templ.name_template(),
2527                                        );
2528
2529                                            can_assign_name = false;
2530                                            break;
2531                                        }
2532                                    }
2533                                    Some("d") => {
2534                                        if name_part
2535                                            .get(conv_spec_start..)
2536                                            .map_or(true, |s| s.parse::<i32>().is_err())
2537                                        {
2538                                            crate::debug!(
2539                                            CAT_RUST,
2540                                            "Not using target Pad name '{name}': can't parse '%i' from '{name_part}' (template '{}')",
2541                                            templ.name_template(),
2542                                        );
2543
2544                                            can_assign_name = false;
2545                                            break;
2546                                        }
2547                                    }
2548                                    other => {
2549                                        unreachable!("Unexpected conversion specifier {other:?}")
2550                                    }
2551                                }
2552                            } else if name_part != templ_part {
2553                                can_assign_name = false;
2554                            }
2555                        }
2556                    }
2557
2558                    if can_assign_name {
2559                        pad.set_property("name", name);
2560                    } else {
2561                        panic!(concat!(
2562                            "Attempt to build a Pad from a wildcard-name template",
2563                            " with a target Pad with an incompatible name.",
2564                            " Make sure to define a specific name using PadBuilder",
2565                            " or opt-in to keep the automatically generated name.",
2566                        ));
2567                    }
2568                }
2569            }
2570        }
2571
2572        pad
2573    }
2574}
2575
2576#[cfg(test)]
2577mod tests {
2578    use std::sync::{atomic::AtomicUsize, mpsc::channel, Arc, Mutex};
2579
2580    use super::*;
2581
2582    #[test]
2583    fn test_event_chain_functions() {
2584        crate::init().unwrap();
2585
2586        let events = Arc::new(Mutex::new(Vec::new()));
2587        let events_clone = events.clone();
2588        let buffers = Arc::new(Mutex::new(Vec::new()));
2589        let buffers_clone = buffers.clone();
2590        let pad = crate::Pad::builder(crate::PadDirection::Sink)
2591            .name("sink")
2592            .event_function(move |_, _, event| {
2593                let mut events = events_clone.lock().unwrap();
2594                events.push(event);
2595
2596                true
2597            })
2598            .chain_function(move |_, _, buffer| {
2599                let mut buffers = buffers_clone.lock().unwrap();
2600                buffers.push(buffer);
2601
2602                Ok(FlowSuccess::Ok)
2603            })
2604            .build();
2605
2606        pad.set_active(true).unwrap();
2607
2608        assert!(pad.send_event(crate::event::StreamStart::new("test")));
2609        let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2610        assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2611
2612        assert_eq!(pad.chain(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2613
2614        let events = events.lock().unwrap();
2615        let buffers = buffers.lock().unwrap();
2616        assert_eq!(events.len(), 2);
2617        assert_eq!(buffers.len(), 1);
2618
2619        match events[0].view() {
2620            crate::EventView::StreamStart(..) => (),
2621            _ => unreachable!(),
2622        }
2623
2624        match events[1].view() {
2625            crate::EventView::Segment(..) => (),
2626            _ => unreachable!(),
2627        }
2628    }
2629
2630    #[test]
2631    fn test_getrange_function() {
2632        crate::init().unwrap();
2633
2634        let pad = crate::Pad::builder(crate::PadDirection::Src)
2635            .name("src")
2636            .activate_function(|pad, _parent| {
2637                pad.activate_mode(crate::PadMode::Pull, true)
2638                    .map_err(|err| err.into())
2639            })
2640            .getrange_function(|_pad, _parent, offset, _buffer, size| {
2641                assert_eq!(offset, 0);
2642                assert_eq!(size, 5);
2643                let buffer = crate::Buffer::from_slice(b"abcde");
2644                Ok(PadGetRangeSuccess::NewBuffer(buffer))
2645            })
2646            .build();
2647        pad.set_active(true).unwrap();
2648
2649        let buffer = pad.range(0, 5).unwrap();
2650        let map = buffer.map_readable().unwrap();
2651        assert_eq!(&*map, b"abcde");
2652
2653        let mut buffer = crate::Buffer::with_size(5).unwrap();
2654        pad.range_fill(0, buffer.get_mut().unwrap(), 5).unwrap();
2655        let map = buffer.map_readable().unwrap();
2656        assert_eq!(&*map, b"abcde");
2657
2658        pad.set_active(false).unwrap();
2659        drop(pad);
2660
2661        let pad = crate::Pad::builder(crate::PadDirection::Src)
2662            .name("src")
2663            .activate_function(|pad, _parent| {
2664                pad.activate_mode(crate::PadMode::Pull, true)
2665                    .map_err(|err| err.into())
2666            })
2667            .getrange_function(|_pad, _parent, offset, buffer, size| {
2668                assert_eq!(offset, 0);
2669                assert_eq!(size, 5);
2670                if let Some(buffer) = buffer {
2671                    buffer.copy_from_slice(0, b"fghij").unwrap();
2672                    Ok(PadGetRangeSuccess::FilledBuffer)
2673                } else {
2674                    let buffer = crate::Buffer::from_slice(b"abcde");
2675                    Ok(PadGetRangeSuccess::NewBuffer(buffer))
2676                }
2677            })
2678            .build();
2679        pad.set_active(true).unwrap();
2680
2681        let buffer = pad.range(0, 5).unwrap();
2682        let map = buffer.map_readable().unwrap();
2683        assert_eq!(&*map, b"abcde");
2684
2685        let mut buffer = crate::Buffer::with_size(5).unwrap();
2686        pad.range_fill(0, buffer.get_mut().unwrap(), 5).unwrap();
2687        let map = buffer.map_readable().unwrap();
2688        assert_eq!(&*map, b"fghij");
2689    }
2690
2691    #[test]
2692    fn test_task() {
2693        crate::init().unwrap();
2694
2695        let pad = crate::Pad::builder(crate::PadDirection::Sink)
2696            .name("sink")
2697            .build();
2698        let (sender, receiver) = channel();
2699
2700        let mut i = 0;
2701        let pad_clone = pad.clone();
2702        pad.start_task(move || {
2703            i += 1;
2704            if i == 3 {
2705                sender.send(i).unwrap();
2706                pad_clone.pause_task().unwrap();
2707            }
2708        })
2709        .unwrap();
2710
2711        assert_eq!(receiver.recv().unwrap(), 3);
2712    }
2713
2714    #[test]
2715    fn test_remove_probe_from_probe() {
2716        crate::init().unwrap();
2717
2718        let src_pad = crate::Pad::builder(crate::PadDirection::Src)
2719            .name("src")
2720            .build();
2721        let sink_pad = crate::Pad::builder(crate::PadDirection::Sink)
2722            .name("sink")
2723            .chain_function(|_pad, _parent, _buffer| Ok(crate::FlowSuccess::Ok))
2724            .build();
2725
2726        src_pad.link(&sink_pad).unwrap();
2727
2728        let counter = Arc::new(AtomicUsize::new(0));
2729        let counter_clone = counter.clone();
2730        src_pad.add_probe(crate::PadProbeType::BUFFER, move |pad, info| {
2731            if let Some(PadProbeData::Buffer(_)) = info.data {
2732                counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
2733                pad.remove_probe(info.id.take().expect("no pad probe id"));
2734            } else {
2735                unreachable!();
2736            }
2737            crate::PadProbeReturn::Handled
2738        });
2739
2740        sink_pad.set_active(true).unwrap();
2741        src_pad.set_active(true).unwrap();
2742
2743        assert!(src_pad.push_event(crate::event::StreamStart::new("test")));
2744        let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2745        assert!(src_pad.push_event(crate::event::Segment::new(segment.as_ref())));
2746
2747        assert_eq!(src_pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2748        assert_eq!(src_pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2749
2750        assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
2751    }
2752
2753    fn do_probe_with_return(probe_return: crate::PadProbeReturn) {
2754        skip_assert_initialized!();
2755        crate::init().unwrap();
2756
2757        let (major, minor, micro, _) = crate::version();
2758        let pad = crate::Pad::builder(crate::PadDirection::Src)
2759            .name("src")
2760            .build();
2761        let events = Arc::new(Mutex::new(Vec::new()));
2762        let buffers = Arc::new(Mutex::new(Vec::new()));
2763
2764        let flow_override = if (major, minor, micro) >= (1, 16, 1) {
2765            Err(FlowError::Eos)
2766        } else {
2767            // Broken on 1.16.0
2768            // https://gitlab.freedesktop.org/gstreamer/gstreamer/merge_requests/151
2769            Ok(FlowSuccess::Ok)
2770        };
2771
2772        {
2773            let events = events.clone();
2774            pad.add_probe(crate::PadProbeType::EVENT_DOWNSTREAM, move |_, info| {
2775                if let Some(PadProbeData::Event(event)) = &info.data {
2776                    let mut events = events.lock().unwrap();
2777                    events.push(event.clone());
2778                } else {
2779                    unreachable!();
2780                }
2781                crate::PadProbeReturn::Ok
2782            });
2783        }
2784
2785        {
2786            let events = events.clone();
2787            pad.add_probe(crate::PadProbeType::EVENT_UPSTREAM, move |_, info| {
2788                if let Some(event) = info.take_event() {
2789                    let mut events = events.lock().unwrap();
2790                    events.push(event);
2791                } else {
2792                    unreachable!();
2793                }
2794                probe_return
2795            });
2796        }
2797
2798        {
2799            let buffers = buffers.clone();
2800            pad.add_probe(crate::PadProbeType::BUFFER, move |_, info| {
2801                if let Some(buffer) = info.take_buffer() {
2802                    let mut buffers = buffers.lock().unwrap();
2803                    info.flow_res = if buffers.is_empty() {
2804                        Ok(FlowSuccess::Ok)
2805                    } else {
2806                        flow_override
2807                    };
2808                    buffers.push(buffer);
2809                } else {
2810                    unreachable!();
2811                }
2812                probe_return
2813            });
2814        }
2815
2816        pad.set_active(true).unwrap();
2817
2818        assert!(
2819            pad.send_event(crate::event::Latency::new(crate::ClockTime::from_nseconds(
2820                10
2821            )))
2822        );
2823        assert!(pad.push_event(crate::event::StreamStart::new("test")));
2824        let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2825        assert!(pad.push_event(crate::event::Segment::new(segment.as_ref())));
2826
2827        assert_eq!(pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2828        assert_eq!(
2829            pad.push(crate::Buffer::new()),
2830            // On Drop, we will get an Ok, not whatever value we returned
2831            if probe_return == crate::PadProbeReturn::Drop {
2832                Ok(FlowSuccess::Ok)
2833            } else {
2834                flow_override
2835            }
2836        );
2837
2838        let events = events.lock().unwrap();
2839        let buffers = buffers.lock().unwrap();
2840        assert_eq!(events.len(), 3);
2841        assert_eq!(buffers.len(), 2);
2842
2843        assert_eq!(events[0].type_(), crate::EventType::Latency);
2844        assert_eq!(events[1].type_(), crate::EventType::StreamStart);
2845        assert_eq!(events[2].type_(), crate::EventType::Segment);
2846
2847        assert!(
2848            buffers.iter().all(|b| b.is_writable()),
2849            "A buffer ref leaked!"
2850        );
2851
2852        drop(pad); // Need to drop the pad first to unref sticky events
2853        assert!(
2854            events.iter().all(|e| e.is_writable()),
2855            "An event ref leaked!"
2856        );
2857    }
2858
2859    #[test]
2860    fn test_probe() {
2861        crate::init().unwrap();
2862        do_probe_with_return(crate::PadProbeReturn::Handled);
2863    }
2864
2865    #[test]
2866    fn test_probe_drop() {
2867        crate::init().unwrap();
2868        do_probe_with_return(crate::PadProbeReturn::Drop);
2869    }
2870
2871    #[test]
2872    fn test_sticky_events() {
2873        crate::init().unwrap();
2874
2875        let pad = crate::Pad::builder(crate::PadDirection::Sink)
2876            .name("sink")
2877            .build();
2878        pad.set_active(true).unwrap();
2879
2880        // Send some sticky events
2881        assert!(pad.send_event(crate::event::StreamStart::new("test")));
2882
2883        let caps = crate::Caps::builder("some/x-caps").build();
2884        assert!(pad.send_event(crate::event::Caps::new(&caps)));
2885
2886        let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2887        assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2888
2889        let stream_start = pad.sticky_event::<crate::event::StreamStart>(0).unwrap();
2890        assert_eq!(stream_start.stream_id(), "test");
2891
2892        let caps2 = pad.sticky_event::<crate::event::Caps>(0).unwrap();
2893        assert_eq!(&*caps, caps2.caps());
2894
2895        let segment = pad.sticky_event::<crate::event::Segment>(0).unwrap();
2896        assert_eq!(segment.segment().format(), crate::Format::Time);
2897    }
2898
2899    #[test]
2900    fn test_sticky_events_foreach() {
2901        crate::init().unwrap();
2902
2903        let pad = crate::Pad::builder(crate::PadDirection::Sink)
2904            .name("sink")
2905            .build();
2906        pad.set_active(true).unwrap();
2907
2908        // Send some sticky events
2909        assert!(pad.send_event(crate::event::StreamStart::new("test")));
2910
2911        let caps = crate::Caps::builder("some/x-caps").build();
2912        assert!(pad.send_event(crate::event::Caps::new(&caps)));
2913
2914        let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2915        assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2916
2917        let mut sticky_events = Vec::new();
2918        pad.sticky_events_foreach(|event| {
2919            sticky_events.push(event.clone());
2920            ControlFlow::Continue(EventForeachAction::Keep)
2921        });
2922        assert_eq!(sticky_events.len(), 3);
2923
2924        // Test early exit from foreach loop
2925        let mut sticky_events2 = Vec::new();
2926        pad.sticky_events_foreach(|event| {
2927            sticky_events2.push(event.clone());
2928            if event.type_() == crate::EventType::Caps {
2929                ControlFlow::Break(EventForeachAction::Keep)
2930            } else {
2931                ControlFlow::Continue(EventForeachAction::Keep)
2932            }
2933        });
2934        assert_eq!(sticky_events2.len(), 2);
2935
2936        let mut sticky_events3 = Vec::new();
2937        pad.sticky_events_foreach(|event| {
2938            sticky_events3.push(event.clone());
2939            ControlFlow::Continue(EventForeachAction::Keep)
2940        });
2941        assert_eq!(sticky_events3.len(), 3);
2942
2943        for (e1, e2) in sticky_events.iter().zip(sticky_events3.iter()) {
2944            assert_eq!(e1.as_ref() as *const _, e2.as_ref() as *const _);
2945        }
2946
2947        // Replace segment event
2948        pad.sticky_events_foreach(|event| {
2949            let action = if event.type_() == crate::EventType::Segment {
2950                let byte_segment = crate::FormattedSegment::<crate::format::Bytes>::new();
2951                EventForeachAction::Replace(crate::event::Segment::new(&byte_segment))
2952            } else {
2953                EventForeachAction::Keep
2954            };
2955            ControlFlow::Continue(action)
2956        });
2957
2958        // Check that segment event is different now
2959        let mut sticky_events4 = Vec::new();
2960        pad.sticky_events_foreach(|event| {
2961            sticky_events4.push(event.clone());
2962            ControlFlow::Continue(EventForeachAction::Keep)
2963        });
2964        assert_eq!(sticky_events4.len(), 3);
2965        assert_eq!(
2966            sticky_events[0].as_ref() as *const _,
2967            sticky_events4[0].as_ref() as *const _
2968        );
2969        assert_eq!(
2970            sticky_events[1].as_ref() as *const _,
2971            sticky_events4[1].as_ref() as *const _
2972        );
2973        assert_ne!(
2974            sticky_events[2].as_ref() as *const _,
2975            sticky_events4[2].as_ref() as *const _
2976        );
2977
2978        // Drop caps event
2979        pad.sticky_events_foreach(|event| {
2980            let action = if event.type_() == crate::EventType::Caps {
2981                EventForeachAction::Remove
2982            } else {
2983                EventForeachAction::Keep
2984            };
2985            ControlFlow::Continue(action)
2986        });
2987
2988        // Check that caps event actually got removed
2989        let mut sticky_events5 = Vec::new();
2990        pad.sticky_events_foreach(|event| {
2991            sticky_events5.push(event.clone());
2992            ControlFlow::Continue(EventForeachAction::Keep)
2993        });
2994        assert_eq!(sticky_events5.len(), 2);
2995        assert_eq!(
2996            sticky_events4[0].as_ref() as *const _,
2997            sticky_events5[0].as_ref() as *const _
2998        );
2999        assert_eq!(
3000            sticky_events4[2].as_ref() as *const _,
3001            sticky_events5[1].as_ref() as *const _
3002        );
3003    }
3004
3005    #[test]
3006    #[allow(deprecated)] // maybe_name() is deprecated
3007    fn naming() {
3008        crate::init().unwrap();
3009
3010        let pad = crate::Pad::builder(crate::PadDirection::Sink).build();
3011        assert!(pad.name().starts_with("pad"));
3012
3013        let pad = crate::Pad::builder(crate::PadDirection::Src).build();
3014        assert!(pad.name().starts_with("pad"));
3015
3016        let pad = crate::Pad::builder(crate::PadDirection::Unknown).build();
3017        assert!(pad.name().starts_with("pad"));
3018
3019        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3020            .generated_name()
3021            .build();
3022        assert!(pad.name().starts_with("pad"));
3023
3024        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3025            .maybe_name(None::<&str>)
3026            .build();
3027        assert!(pad.name().starts_with("pad"));
3028
3029        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3030            .name_if_some(None::<&str>)
3031            .build();
3032        assert!(pad.name().starts_with("pad"));
3033
3034        let pad = crate::Pad::builder(crate::PadDirection::Sink)
3035            .name("sink_0")
3036            .build();
3037        assert_eq!(pad.name(), "sink_0");
3038
3039        let pad = crate::Pad::builder(crate::PadDirection::Src)
3040            .name("src_0")
3041            .build();
3042        assert_eq!(pad.name(), "src_0");
3043
3044        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3045            .name("test")
3046            .build();
3047        assert_eq!(pad.name(), "test");
3048
3049        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3050            .maybe_name(Some("test"))
3051            .build();
3052        assert_eq!(pad.name(), "test");
3053
3054        let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3055            .name_if_some(Some("test"))
3056            .build();
3057        assert_eq!(pad.name(), "test");
3058
3059        let caps = crate::Caps::new_any();
3060        let templ = crate::PadTemplate::new(
3061            "sink",
3062            crate::PadDirection::Sink,
3063            crate::PadPresence::Always,
3064            &caps,
3065        )
3066        .unwrap();
3067
3068        let pad = Pad::from_template(&templ);
3069        assert!(pad.name().starts_with("sink"));
3070
3071        let pad = Pad::builder_from_template(&templ)
3072            .name("audio_sink")
3073            .build();
3074        assert!(pad.name().starts_with("audio_sink"));
3075
3076        let pad = Pad::builder_from_template(&templ).generated_name().build();
3077        assert!(pad.name().starts_with("pad"));
3078
3079        let templ = crate::PadTemplate::new(
3080            "audio_%u",
3081            crate::PadDirection::Sink,
3082            crate::PadPresence::Request,
3083            &caps,
3084        )
3085        .unwrap();
3086
3087        let pad = Pad::builder_from_template(&templ).name("audio_0").build();
3088        assert!(pad.name().starts_with("audio_0"));
3089
3090        let pad = Pad::builder_from_template(&templ).generated_name().build();
3091        assert!(pad.name().starts_with("pad"));
3092    }
3093
3094    #[test]
3095    #[should_panic]
3096    fn missing_name() {
3097        crate::init().unwrap();
3098
3099        let caps = crate::Caps::new_any();
3100        let templ = crate::PadTemplate::new(
3101            "audio_%u",
3102            crate::PadDirection::Sink,
3103            crate::PadPresence::Request,
3104            &caps,
3105        )
3106        .unwrap();
3107
3108        // Panic: attempt to build from a wildcard-named template
3109        //        without providing a name.
3110        let _pad = Pad::from_template(&templ);
3111    }
3112}