Skip to main content

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