1use std::{
4 mem,
5 num::NonZeroU64,
6 ops::ControlFlow,
7 panic::{self, AssertUnwindSafe},
8 ptr,
9};
10
11use glib::{ffi::gpointer, prelude::*, translate::*};
12
13use crate::{
14 ffi,
15 format::{FormattedValue, SpecificFormattedValueFullRange, SpecificFormattedValueIntrinsic},
16 prelude::*,
17 Buffer, BufferList, Event, FlowError, FlowReturn, FlowSuccess, Format, GenericFormattedValue,
18 LoggableError, Pad, PadFlags, PadProbeReturn, PadProbeType, Query, QueryRef, StaticPadTemplate,
19};
20
21#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct PadProbeId(NonZeroU64);
23
24impl IntoGlib for PadProbeId {
25 type GlibType = libc::c_ulong;
26
27 #[inline]
28 fn into_glib(self) -> libc::c_ulong {
29 self.0.get() as libc::c_ulong
30 }
31}
32
33impl FromGlib<libc::c_ulong> for PadProbeId {
34 #[inline]
35 unsafe fn from_glib(val: libc::c_ulong) -> PadProbeId {
36 skip_assert_initialized!();
37 debug_assert_ne!(val, 0);
38 PadProbeId(NonZeroU64::new_unchecked(val as _))
39 }
40}
41
42impl PadProbeId {
43 #[inline]
44 pub fn as_raw(&self) -> libc::c_ulong {
45 self.0.get() as libc::c_ulong
46 }
47}
48
49#[doc(alias = "GstPadProbeInfo")]
50#[derive(Debug)]
51pub struct PadProbeInfo<'a> {
52 pub mask: PadProbeType,
53 pub id: Option<PadProbeId>,
54 pub offset: u64,
55 pub size: u32,
56 pub data: Option<PadProbeData<'a>>,
57 pub flow_res: Result<FlowSuccess, FlowError>,
58}
59
60impl PadProbeInfo<'_> {
61 pub fn buffer(&self) -> Option<&Buffer> {
62 match self.data {
63 Some(PadProbeData::Buffer(ref buffer)) => Some(buffer),
64 _ => None,
65 }
66 }
67
68 pub fn buffer_mut(&mut self) -> Option<&mut Buffer> {
69 match self.data {
70 Some(PadProbeData::Buffer(ref mut buffer)) => Some(buffer),
71 _ => None,
72 }
73 }
74
75 pub fn buffer_list(&self) -> Option<&BufferList> {
76 match self.data {
77 Some(PadProbeData::BufferList(ref buffer_list)) => Some(buffer_list),
78 _ => None,
79 }
80 }
81
82 pub fn buffer_list_mut(&mut self) -> Option<&mut BufferList> {
83 match self.data {
84 Some(PadProbeData::BufferList(ref mut buffer_list)) => Some(buffer_list),
85 _ => None,
86 }
87 }
88
89 pub fn query(&self) -> Option<&QueryRef> {
90 match self.data {
91 Some(PadProbeData::Query(ref query)) => Some(*query),
92 _ => None,
93 }
94 }
95
96 pub fn query_mut(&mut self) -> Option<&mut QueryRef> {
97 match self.data {
98 Some(PadProbeData::Query(ref mut query)) => Some(*query),
99 _ => None,
100 }
101 }
102
103 pub fn event(&self) -> Option<&Event> {
104 match self.data {
105 Some(PadProbeData::Event(ref event)) => Some(event),
106 _ => None,
107 }
108 }
109
110 pub fn event_mut(&mut self) -> Option<&mut Event> {
111 match self.data {
112 Some(PadProbeData::Event(ref mut event)) => Some(event),
113 _ => None,
114 }
115 }
116
117 pub fn take_buffer(&mut self) -> Option<Buffer> {
121 if matches!(self.data, Some(PadProbeData::Buffer(..))) {
122 match self.data.take() {
123 Some(PadProbeData::Buffer(b)) => Some(b),
124 _ => unreachable!(),
125 }
126 } else {
127 None
128 }
129 }
130
131 pub fn take_buffer_list(&mut self) -> Option<BufferList> {
135 if matches!(self.data, Some(PadProbeData::BufferList(..))) {
136 match self.data.take() {
137 Some(PadProbeData::BufferList(b)) => Some(b),
138 _ => unreachable!(),
139 }
140 } else {
141 None
142 }
143 }
144 pub fn take_event(&mut self) -> Option<Event> {
148 if matches!(self.data, Some(PadProbeData::Event(..))) {
149 match self.data.take() {
150 Some(PadProbeData::Event(e)) => Some(e),
151 _ => unreachable!(),
152 }
153 } else {
154 None
155 }
156 }
157}
158
159#[derive(Debug)]
160pub enum PadProbeData<'a> {
161 Buffer(Buffer),
162 BufferList(BufferList),
163 Query(&'a mut QueryRef),
164 Event(Event),
165 #[doc(hidden)]
166 __Unknown(*mut ffi::GstMiniObject),
167}
168
169unsafe impl Send for PadProbeData<'_> {}
170unsafe impl Sync for PadProbeData<'_> {}
171
172#[derive(Debug)]
173#[must_use = "if unused the StreamLock will immediately unlock"]
174pub struct StreamLock<'a>(&'a Pad);
175impl Drop for StreamLock<'_> {
176 #[inline]
177 fn drop(&mut self) {
178 unsafe {
179 let pad: *mut ffi::GstPad = self.0.to_glib_none().0;
180 glib::ffi::g_rec_mutex_unlock(&mut (*pad).stream_rec_lock);
181 }
182 }
183}
184
185#[derive(Debug)]
186pub enum PadGetRangeSuccess {
187 FilledBuffer,
188 NewBuffer(crate::Buffer),
189}
190
191#[derive(Debug)]
192pub enum EventForeachAction {
193 Keep,
194 Remove,
195 Replace(Event),
196}
197
198mod sealed {
199 pub trait Sealed {}
200 impl<T: super::IsA<super::Pad>> Sealed for T {}
201}
202
203pub trait PadExtManual: sealed::Sealed + IsA<Pad> + 'static {
204 #[doc(alias = "gst_pad_add_probe")]
230 fn add_probe<F>(&self, mask: PadProbeType, func: F) -> Option<PadProbeId>
231 where
232 F: Fn(&Self, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
233 {
234 unsafe {
235 let func_box: Box<F> = Box::new(func);
236 let id = ffi::gst_pad_add_probe(
237 self.as_ref().to_glib_none().0,
238 mask.into_glib(),
239 Some(trampoline_pad_probe::<Self, F>),
240 Box::into_raw(func_box) as gpointer,
241 Some(destroy_closure::<F>),
242 );
243
244 if id == 0 {
245 None
246 } else {
247 Some(from_glib(id))
248 }
249 }
250 }
251
252 #[doc(alias = "gst_pad_remove_probe")]
258 fn remove_probe(&self, id: PadProbeId) {
259 unsafe {
260 ffi::gst_pad_remove_probe(self.as_ref().to_glib_none().0, id.into_glib());
261 }
262 }
263
264 #[doc(alias = "gst_pad_pull_range")]
304 fn pull_range(&self, offset: u64, size: u32) -> Result<Buffer, FlowError> {
305 unsafe {
306 let mut buffer = ptr::null_mut();
307 FlowSuccess::try_from_glib(ffi::gst_pad_pull_range(
308 self.as_ref().to_glib_none().0,
309 offset,
310 size,
311 &mut buffer,
312 ))
313 .map(|_| from_glib_full(buffer))
314 }
315 }
316
317 fn pull_range_fill(
318 &self,
319 offset: u64,
320 buffer: &mut crate::BufferRef,
321 size: u32,
322 ) -> Result<(), FlowError> {
323 assert!(buffer.size() >= size as usize);
324
325 unsafe {
326 let mut buffer_ref = buffer.as_mut_ptr();
327 FlowSuccess::try_from_glib(ffi::gst_pad_pull_range(
328 self.as_ref().to_glib_none().0,
329 offset,
330 size,
331 &mut buffer_ref,
332 ))
333 .and_then(|_| {
334 if buffer.as_mut_ptr() != buffer_ref {
335 ffi::gst_mini_object_unref(buffer_ref as *mut _);
336 Err(crate::FlowError::Error)
337 } else {
338 Ok(())
339 }
340 })
341 }
342 }
343
344 #[doc(alias = "get_range")]
385 #[doc(alias = "gst_pad_get_range")]
386 fn range(&self, offset: u64, size: u32) -> Result<Buffer, FlowError> {
387 unsafe {
388 let mut buffer = ptr::null_mut();
389 FlowSuccess::try_from_glib(ffi::gst_pad_get_range(
390 self.as_ref().to_glib_none().0,
391 offset,
392 size,
393 &mut buffer,
394 ))
395 .map(|_| from_glib_full(buffer))
396 }
397 }
398
399 #[doc(alias = "get_range_fill")]
400 fn range_fill(
401 &self,
402 offset: u64,
403 buffer: &mut crate::BufferRef,
404 size: u32,
405 ) -> Result<(), FlowError> {
406 assert!(buffer.size() >= size as usize);
407
408 unsafe {
409 let mut buffer_ref = buffer.as_mut_ptr();
410 FlowSuccess::try_from_glib(ffi::gst_pad_get_range(
411 self.as_ref().to_glib_none().0,
412 offset,
413 size,
414 &mut buffer_ref,
415 ))
416 .and_then(|_| {
417 if buffer.as_mut_ptr() != buffer_ref {
418 ffi::gst_mini_object_unref(buffer_ref as *mut _);
419 Err(crate::FlowError::Error)
420 } else {
421 Ok(())
422 }
423 })
424 }
425 }
426
427 #[doc(alias = "gst_pad_peer_query")]
439 fn peer_query(&self, query: &mut QueryRef) -> bool {
440 unsafe {
441 from_glib(ffi::gst_pad_peer_query(
442 self.as_ref().to_glib_none().0,
443 query.as_mut_ptr(),
444 ))
445 }
446 }
447
448 #[doc(alias = "gst_pad_query")]
465 fn query(&self, query: &mut QueryRef) -> bool {
466 unsafe {
467 from_glib(ffi::gst_pad_query(
468 self.as_ref().to_glib_none().0,
469 query.as_mut_ptr(),
470 ))
471 }
472 }
473
474 #[doc(alias = "gst_pad_proxy_query_caps")]
487 fn proxy_query_caps(&self, query: &mut QueryRef) -> bool {
488 unsafe {
489 from_glib(ffi::gst_pad_proxy_query_caps(
490 self.as_ref().to_glib_none().0,
491 query.as_mut_ptr(),
492 ))
493 }
494 }
495
496 #[doc(alias = "gst_pad_proxy_query_accept_caps")]
509 fn proxy_query_accept_caps(&self, query: &mut QueryRef) -> bool {
510 unsafe {
511 from_glib(ffi::gst_pad_proxy_query_accept_caps(
512 self.as_ref().to_glib_none().0,
513 query.as_mut_ptr(),
514 ))
515 }
516 }
517
518 #[doc(alias = "gst_pad_push_event")]
533 fn push_event(&self, event: impl Into<Event>) -> bool {
534 unsafe {
535 from_glib(ffi::gst_pad_push_event(
536 self.as_ref().to_glib_none().0,
537 event.into().into_glib_ptr(),
538 ))
539 }
540 }
541
542 #[doc(alias = "gst_pad_send_event")]
569 fn send_event(&self, event: impl Into<Event>) -> bool {
570 unsafe {
571 from_glib(ffi::gst_pad_send_event(
572 self.as_ref().to_glib_none().0,
573 event.into().into_glib_ptr(),
574 ))
575 }
576 }
577
578 #[doc(alias = "gst_pad_iterate_internal_links")]
579 fn iterate_internal_links(&self) -> crate::Iterator<Pad> {
580 unsafe {
581 from_glib_full(ffi::gst_pad_iterate_internal_links(
582 self.as_ref().to_glib_none().0,
583 ))
584 }
585 }
586
587 fn stream_lock(&self) -> StreamLock {
588 unsafe {
589 let ptr: &mut ffi::GstPad = &mut *(self.as_ptr() as *mut _);
590 glib::ffi::g_rec_mutex_lock(&mut ptr.stream_rec_lock);
591 StreamLock(self.upcast_ref())
592 }
593 }
594
595 #[doc(alias = "gst_pad_set_activate_function")]
596 #[doc(alias = "gst_pad_set_activate_function_full")]
597 unsafe fn set_activate_function<F>(&self, func: F)
598 where
599 F: Fn(&Self, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
600 {
601 let func_box: Box<F> = Box::new(func);
602 ffi::gst_pad_set_activate_function_full(
603 self.as_ref().to_glib_none().0,
604 Some(trampoline_activate_function::<Self, F>),
605 Box::into_raw(func_box) as gpointer,
606 Some(destroy_closure::<F>),
607 );
608 }
609
610 #[doc(alias = "gst_pad_set_activatemode_function")]
611 #[doc(alias = "gst_pad_set_activatemode_function_full")]
612 unsafe fn set_activatemode_function<F>(&self, func: F)
613 where
614 F: Fn(&Self, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
615 + Send
616 + Sync
617 + 'static,
618 {
619 let func_box: Box<F> = Box::new(func);
620 ffi::gst_pad_set_activatemode_function_full(
621 self.as_ref().to_glib_none().0,
622 Some(trampoline_activatemode_function::<Self, F>),
623 Box::into_raw(func_box) as gpointer,
624 Some(destroy_closure::<F>),
625 );
626 }
627
628 #[doc(alias = "gst_pad_set_chain_function")]
629 #[doc(alias = "gst_pad_set_chain_function_full")]
630 unsafe fn set_chain_function<F>(&self, func: F)
631 where
632 F: Fn(&Self, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
633 + Send
634 + Sync
635 + 'static,
636 {
637 let func_box: Box<F> = Box::new(func);
638 ffi::gst_pad_set_chain_function_full(
639 self.as_ref().to_glib_none().0,
640 Some(trampoline_chain_function::<Self, F>),
641 Box::into_raw(func_box) as gpointer,
642 Some(destroy_closure::<F>),
643 );
644 }
645
646 #[doc(alias = "gst_pad_set_chain_list_function")]
647 #[doc(alias = "gst_pad_set_chain_list_function_full")]
648 unsafe fn set_chain_list_function<F>(&self, func: F)
649 where
650 F: Fn(&Self, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
651 + Send
652 + Sync
653 + 'static,
654 {
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 #[doc(alias = "gst_pad_set_event_function")]
665 #[doc(alias = "gst_pad_set_event_function_full")]
666 unsafe fn set_event_function<F>(&self, func: F)
667 where
668 F: Fn(&Self, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
669 {
670 let func_box: Box<F> = Box::new(func);
671 ffi::gst_pad_set_event_function_full(
672 self.as_ref().to_glib_none().0,
673 Some(trampoline_event_function::<Self, F>),
674 Box::into_raw(func_box) as gpointer,
675 Some(destroy_closure::<F>),
676 );
677 }
678
679 #[doc(alias = "gst_pad_set_event_full_function")]
680 #[doc(alias = "gst_pad_set_event_full_function_full")]
681 unsafe fn set_event_full_function<F>(&self, func: F)
682 where
683 F: Fn(&Self, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
684 + Send
685 + Sync
686 + 'static,
687 {
688 let func_box: Box<F> = Box::new(func);
689 ffi::gst_pad_set_event_full_function_full(
690 self.as_ref().to_glib_none().0,
691 Some(trampoline_event_full_function::<Self, F>),
692 Box::into_raw(func_box) as gpointer,
693 Some(destroy_closure::<F>),
694 );
695 }
696
697 #[doc(alias = "gst_pad_set_getrange_function")]
698 #[doc(alias = "gst_pad_set_getrange_function_full")]
699 unsafe fn set_getrange_function<F>(&self, func: F)
700 where
701 F: Fn(
702 &Self,
703 Option<&crate::Object>,
704 u64,
705 Option<&mut crate::BufferRef>,
706 u32,
707 ) -> Result<PadGetRangeSuccess, crate::FlowError>
708 + Send
709 + Sync
710 + 'static,
711 {
712 let func_box: Box<F> = Box::new(func);
713 ffi::gst_pad_set_getrange_function_full(
714 self.as_ref().to_glib_none().0,
715 Some(trampoline_getrange_function::<Self, F>),
716 Box::into_raw(func_box) as gpointer,
717 Some(destroy_closure::<F>),
718 );
719 }
720
721 #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
722 #[doc(alias = "gst_pad_set_iterate_internal_links_function_full")]
723 unsafe fn set_iterate_internal_links_function<F>(&self, func: F)
724 where
725 F: Fn(&Self, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
726 {
727 let func_box: Box<F> = Box::new(func);
728 ffi::gst_pad_set_iterate_internal_links_function_full(
729 self.as_ref().to_glib_none().0,
730 Some(trampoline_iterate_internal_links_function::<Self, F>),
731 Box::into_raw(func_box) as gpointer,
732 Some(destroy_closure::<F>),
733 );
734 }
735
736 #[doc(alias = "gst_pad_set_link_function")]
737 #[doc(alias = "gst_pad_set_link_function_full")]
738 unsafe fn set_link_function<F>(&self, func: F)
739 where
740 F: Fn(
741 &Self,
742 Option<&crate::Object>,
743 &Pad,
744 ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
745 + Send
746 + Sync
747 + 'static,
748 {
749 let func_box: Box<F> = Box::new(func);
750 ffi::gst_pad_set_link_function_full(
751 self.as_ref().to_glib_none().0,
752 Some(trampoline_link_function::<Self, F>),
753 Box::into_raw(func_box) as gpointer,
754 Some(destroy_closure::<F>),
755 );
756 }
757
758 #[doc(alias = "gst_pad_set_query_function")]
759 #[doc(alias = "gst_pad_set_query_function_full")]
760 unsafe fn set_query_function<F>(&self, func: F)
761 where
762 F: Fn(&Self, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
763 {
764 let func_box: Box<F> = Box::new(func);
765 ffi::gst_pad_set_query_function_full(
766 self.as_ref().to_glib_none().0,
767 Some(trampoline_query_function::<Self, F>),
768 Box::into_raw(func_box) as gpointer,
769 Some(destroy_closure::<F>),
770 );
771 }
772
773 #[doc(alias = "gst_pad_set_unlink_function")]
774 #[doc(alias = "gst_pad_set_unlink_function_full")]
775 unsafe fn set_unlink_function<F>(&self, func: F)
776 where
777 F: Fn(&Self, Option<&crate::Object>) + Send + Sync + 'static,
778 {
779 let func_box: Box<F> = Box::new(func);
780 ffi::gst_pad_set_unlink_function_full(
781 self.as_ref().to_glib_none().0,
782 Some(trampoline_unlink_function::<Self, F>),
783 Box::into_raw(func_box) as gpointer,
784 Some(destroy_closure::<F>),
785 );
786 }
787
788 #[doc(alias = "gst_pad_start_task")]
801 fn start_task<F: FnMut() + Send + 'static>(&self, func: F) -> Result<(), glib::BoolError> {
802 unsafe extern "C" fn trampoline_pad_task<F: FnMut() + Send + 'static>(func: gpointer) {
803 let (func, pad) = &mut *(func as *mut (F, *mut ffi::GstPad));
804 let pad = Pad::from_glib_borrow(*pad);
805 let result = panic::catch_unwind(AssertUnwindSafe(func));
806
807 if let Err(err) = result {
808 let element = match pad.parent_element() {
809 Some(element) => element,
810 None => panic::resume_unwind(err),
811 };
812
813 if pad.pause_task().is_err() {
814 crate::error!(crate::CAT_RUST, "could not stop pad task on panic");
815 }
816
817 crate::subclass::post_panic_error_message(&element, pad.upcast_ref(), Some(err));
818 }
819 }
820
821 fn into_raw_pad_task<F: FnMut() + Send + 'static>(
822 func: F,
823 pad: *mut ffi::GstPad,
824 ) -> gpointer {
825 #[allow(clippy::type_complexity)]
826 let func: Box<(F, *mut ffi::GstPad)> = Box::new((func, pad));
827 Box::into_raw(func) as gpointer
828 }
829
830 unsafe extern "C" fn destroy_closure_pad_task<F>(ptr: gpointer) {
831 let _ = Box::<(F, *mut ffi::GstPad)>::from_raw(ptr as *mut _);
832 }
833
834 unsafe {
835 glib::result_from_gboolean!(
836 ffi::gst_pad_start_task(
837 self.as_ref().to_glib_none().0,
838 Some(trampoline_pad_task::<F>),
839 into_raw_pad_task(func, self.upcast_ref().as_ptr()),
840 Some(destroy_closure_pad_task::<F>),
841 ),
842 "Failed to start pad task",
843 )
844 }
845 }
846 #[doc(alias = "gst_pad_peer_query_convert")]
862 fn peer_query_convert<U: SpecificFormattedValueFullRange>(
863 &self,
864 src_val: impl FormattedValue,
865 ) -> Option<U> {
866 unsafe {
867 let mut dest_val = mem::MaybeUninit::uninit();
868 let ret = from_glib(ffi::gst_pad_peer_query_convert(
869 self.as_ref().to_glib_none().0,
870 src_val.format().into_glib(),
871 src_val.into_raw_value(),
872 U::default_format().into_glib(),
873 dest_val.as_mut_ptr(),
874 ));
875 if ret {
876 Some(U::from_raw(U::default_format(), dest_val.assume_init()))
877 } else {
878 None
879 }
880 }
881 }
882
883 #[doc(alias = "gst_pad_peer_query_convert")]
884 fn peer_query_convert_generic(
885 &self,
886 src_val: impl FormattedValue,
887 dest_format: Format,
888 ) -> Option<GenericFormattedValue> {
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 dest_format.into_glib(),
896 dest_val.as_mut_ptr(),
897 ));
898 if ret {
899 Some(GenericFormattedValue::new(
900 dest_format,
901 dest_val.assume_init(),
902 ))
903 } else {
904 None
905 }
906 }
907 }
908
909 #[doc(alias = "gst_pad_peer_query_duration")]
921 fn peer_query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
922 unsafe {
923 let mut duration = mem::MaybeUninit::uninit();
924 let ret = from_glib(ffi::gst_pad_peer_query_duration(
925 self.as_ref().to_glib_none().0,
926 T::default_format().into_glib(),
927 duration.as_mut_ptr(),
928 ));
929 if ret {
930 try_from_glib(duration.assume_init()).ok()
931 } else {
932 None
933 }
934 }
935 }
936
937 #[doc(alias = "gst_pad_peer_query_duration")]
938 fn peer_query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
939 unsafe {
940 let mut duration = mem::MaybeUninit::uninit();
941 let ret = from_glib(ffi::gst_pad_peer_query_duration(
942 self.as_ref().to_glib_none().0,
943 format.into_glib(),
944 duration.as_mut_ptr(),
945 ));
946 if ret {
947 Some(GenericFormattedValue::new(format, duration.assume_init()))
948 } else {
949 None
950 }
951 }
952 }
953
954 #[doc(alias = "gst_pad_peer_query_position")]
966 fn peer_query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
967 unsafe {
968 let mut cur = mem::MaybeUninit::uninit();
969 let ret = from_glib(ffi::gst_pad_peer_query_position(
970 self.as_ref().to_glib_none().0,
971 T::default_format().into_glib(),
972 cur.as_mut_ptr(),
973 ));
974 if ret {
975 try_from_glib(cur.assume_init()).ok()
976 } else {
977 None
978 }
979 }
980 }
981
982 #[doc(alias = "gst_pad_peer_query_position")]
983 fn peer_query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
984 unsafe {
985 let mut cur = mem::MaybeUninit::uninit();
986 let ret = from_glib(ffi::gst_pad_peer_query_position(
987 self.as_ref().to_glib_none().0,
988 format.into_glib(),
989 cur.as_mut_ptr(),
990 ));
991 if ret {
992 Some(GenericFormattedValue::new(format, cur.assume_init()))
993 } else {
994 None
995 }
996 }
997 }
998
999 #[doc(alias = "gst_pad_query_convert")]
1014 fn query_convert<U: SpecificFormattedValueFullRange>(
1015 &self,
1016 src_val: impl FormattedValue,
1017 ) -> Option<U> {
1018 unsafe {
1019 let mut dest_val = mem::MaybeUninit::uninit();
1020 let ret = from_glib(ffi::gst_pad_query_convert(
1021 self.as_ref().to_glib_none().0,
1022 src_val.format().into_glib(),
1023 src_val.into_raw_value(),
1024 U::default_format().into_glib(),
1025 dest_val.as_mut_ptr(),
1026 ));
1027 if ret {
1028 Some(U::from_raw(U::default_format(), dest_val.assume_init()))
1029 } else {
1030 None
1031 }
1032 }
1033 }
1034
1035 #[doc(alias = "gst_pad_query_convert")]
1036 fn query_convert_generic(
1037 &self,
1038 src_val: impl FormattedValue,
1039 dest_format: Format,
1040 ) -> Option<GenericFormattedValue> {
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 dest_format.into_glib(),
1048 dest_val.as_mut_ptr(),
1049 ));
1050 if ret {
1051 Some(GenericFormattedValue::new(
1052 dest_format,
1053 dest_val.assume_init(),
1054 ))
1055 } else {
1056 None
1057 }
1058 }
1059 }
1060
1061 #[doc(alias = "gst_pad_query_duration")]
1073 fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
1074 unsafe {
1075 let mut duration = mem::MaybeUninit::uninit();
1076 let ret = from_glib(ffi::gst_pad_query_duration(
1077 self.as_ref().to_glib_none().0,
1078 T::default_format().into_glib(),
1079 duration.as_mut_ptr(),
1080 ));
1081 if ret {
1082 try_from_glib(duration.assume_init()).ok()
1083 } else {
1084 None
1085 }
1086 }
1087 }
1088
1089 #[doc(alias = "gst_pad_query_duration")]
1090 fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
1091 unsafe {
1092 let mut duration = mem::MaybeUninit::uninit();
1093 let ret = from_glib(ffi::gst_pad_query_duration(
1094 self.as_ref().to_glib_none().0,
1095 format.into_glib(),
1096 duration.as_mut_ptr(),
1097 ));
1098 if ret {
1099 Some(GenericFormattedValue::new(format, duration.assume_init()))
1100 } else {
1101 None
1102 }
1103 }
1104 }
1105
1106 #[doc(alias = "gst_pad_query_position")]
1117 fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
1118 unsafe {
1119 let mut cur = mem::MaybeUninit::uninit();
1120 let ret = from_glib(ffi::gst_pad_query_position(
1121 self.as_ref().to_glib_none().0,
1122 T::default_format().into_glib(),
1123 cur.as_mut_ptr(),
1124 ));
1125 if ret {
1126 try_from_glib(cur.assume_init()).ok()
1127 } else {
1128 None
1129 }
1130 }
1131 }
1132
1133 #[doc(alias = "gst_pad_query_position")]
1134 fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
1135 unsafe {
1136 let mut cur = mem::MaybeUninit::uninit();
1137 let ret = from_glib(ffi::gst_pad_query_position(
1138 self.as_ref().to_glib_none().0,
1139 format.into_glib(),
1140 cur.as_mut_ptr(),
1141 ));
1142 if ret {
1143 Some(GenericFormattedValue::new(format, cur.assume_init()))
1144 } else {
1145 None
1146 }
1147 }
1148 }
1149
1150 #[doc(alias = "get_mode")]
1151 #[doc(alias = "GST_PAD_MODE")]
1152 fn mode(&self) -> crate::PadMode {
1153 unsafe {
1154 let ptr: &ffi::GstPad = &*(self.as_ptr() as *const _);
1155 from_glib(ptr.mode)
1156 }
1157 }
1158
1159 #[doc(alias = "gst_pad_sticky_events_foreach")]
1165 fn sticky_events_foreach<
1166 F: FnMut(&Event) -> ControlFlow<EventForeachAction, EventForeachAction>,
1167 >(
1168 &self,
1169 func: F,
1170 ) {
1171 unsafe extern "C" fn trampoline<
1172 F: FnMut(&Event) -> ControlFlow<EventForeachAction, EventForeachAction>,
1173 >(
1174 _pad: *mut ffi::GstPad,
1175 event: *mut *mut ffi::GstEvent,
1176 user_data: glib::ffi::gpointer,
1177 ) -> glib::ffi::gboolean {
1178 let func = user_data as *mut F;
1179 let res = (*func)(&from_glib_borrow(*event));
1180
1181 let (do_continue, ev_action) = match res {
1182 ControlFlow::Continue(ev_action) => (glib::ffi::GTRUE, ev_action),
1183 ControlFlow::Break(ev_action) => (glib::ffi::GFALSE, ev_action),
1184 };
1185
1186 use EventForeachAction::*;
1187
1188 match ev_action {
1189 Keep => (), Remove => {
1191 ffi::gst_mini_object_unref(*event as *mut _);
1192 *event = ptr::null_mut();
1193 }
1194 Replace(ev) => {
1195 ffi::gst_mini_object_unref(*event as *mut _);
1196 *event = ev.into_glib_ptr();
1197 }
1198 }
1199
1200 do_continue
1201 }
1202
1203 unsafe {
1204 let mut func = func;
1205 let func_ptr = &mut func as *mut F as glib::ffi::gpointer;
1206
1207 ffi::gst_pad_sticky_events_foreach(
1208 self.as_ref().to_glib_none().0,
1209 Some(trampoline::<F>),
1210 func_ptr,
1211 );
1212 }
1213 }
1214
1215 #[doc(alias = "gst_pad_get_sticky_event")]
1228 #[doc(alias = "get_sticky_event")]
1229 fn sticky_event<T: crate::event::StickyEventType>(&self, idx: u32) -> Option<T::Owned> {
1230 unsafe {
1231 let ptr = ffi::gst_pad_get_sticky_event(
1232 self.as_ref().to_glib_none().0,
1233 T::TYPE.into_glib(),
1234 idx,
1235 );
1236
1237 if ptr.is_null() {
1238 None
1239 } else {
1240 Some(T::from_event(from_glib_full(ptr)))
1241 }
1242 }
1243 }
1244
1245 fn set_pad_flags(&self, flags: PadFlags) {
1246 unsafe {
1247 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1248 let _guard = self.as_ref().object_lock();
1249 (*ptr).flags |= flags.into_glib();
1250 }
1251 }
1252
1253 fn unset_pad_flags(&self, flags: PadFlags) {
1254 unsafe {
1255 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1256 let _guard = self.as_ref().object_lock();
1257 (*ptr).flags &= !flags.into_glib();
1258 }
1259 }
1260
1261 #[doc(alias = "get_pad_flags")]
1262 fn pad_flags(&self) -> PadFlags {
1263 unsafe {
1264 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
1265 let _guard = self.as_ref().object_lock();
1266 from_glib((*ptr).flags)
1267 }
1268 }
1269}
1270
1271impl<O: IsA<Pad>> PadExtManual for O {}
1272
1273unsafe fn create_probe_info<'a>(
1274 info: *mut ffi::GstPadProbeInfo,
1275) -> (PadProbeInfo<'a>, Option<glib::Type>) {
1276 let mut data_type = None;
1277 let flow_res = try_from_glib((*info).ABI.abi.flow_ret);
1278 let info = PadProbeInfo {
1279 mask: from_glib((*info).type_),
1280 id: Some(PadProbeId(NonZeroU64::new_unchecked((*info).id as _))),
1281 offset: (*info).offset,
1282 size: (*info).size,
1283 data: if (*info).data.is_null() {
1284 None
1285 } else {
1286 let data = (*info).data as *mut ffi::GstMiniObject;
1287 (*info).data = ptr::null_mut();
1288 if (*data).type_ == Buffer::static_type().into_glib() {
1289 data_type = Some(Buffer::static_type());
1290 Some(PadProbeData::Buffer(from_glib_full(
1291 data as *const ffi::GstBuffer,
1292 )))
1293 } else if (*data).type_ == BufferList::static_type().into_glib() {
1294 data_type = Some(BufferList::static_type());
1295 Some(PadProbeData::BufferList(from_glib_full(
1296 data as *const ffi::GstBufferList,
1297 )))
1298 } else if (*data).type_ == Query::static_type().into_glib() {
1299 data_type = Some(Query::static_type());
1300 Some(PadProbeData::Query(QueryRef::from_mut_ptr(
1301 data as *mut ffi::GstQuery,
1302 )))
1303 } else if (*data).type_ == Event::static_type().into_glib() {
1304 data_type = Some(Event::static_type());
1305 Some(PadProbeData::Event(from_glib_full(
1306 data as *const ffi::GstEvent,
1307 )))
1308 } else {
1309 Some(PadProbeData::__Unknown(data))
1310 }
1311 },
1312 flow_res,
1313 };
1314 (info, data_type)
1315}
1316
1317unsafe fn update_probe_info(
1318 ret: PadProbeReturn,
1319 probe_info: PadProbeInfo,
1320 data_type: Option<glib::Type>,
1321 info: *mut ffi::GstPadProbeInfo,
1322) {
1323 if ret == PadProbeReturn::Handled {
1324 match probe_info.data {
1329 Some(PadProbeData::Query(query)) => {
1330 assert_eq!(data_type, Some(Query::static_type()));
1331 (*info).data = query.as_mut_ptr() as *mut libc::c_void;
1332 }
1333 Some(PadProbeData::Buffer(_)) => {
1334 assert_eq!(data_type, Some(Buffer::static_type()));
1335 }
1337 Some(PadProbeData::BufferList(_)) => {
1338 assert_eq!(data_type, Some(BufferList::static_type()));
1339 }
1341 Some(PadProbeData::Event(_)) => {
1342 assert_eq!(data_type, Some(Event::static_type()));
1343 }
1345 None if data_type == Some(Buffer::static_type())
1346 || data_type == Some(BufferList::static_type())
1347 || data_type == Some(Event::static_type()) =>
1348 {
1349 (*info).data = ptr::null_mut();
1351 }
1352 other => panic!("Bad data for {data_type:?} pad probe returning Handled: {other:?}"),
1353 }
1354 } else if ret == PadProbeReturn::Drop {
1355 match probe_info.data {
1357 None if data_type == Some(Buffer::static_type())
1358 || data_type == Some(BufferList::static_type())
1359 || data_type == Some(Event::static_type()) =>
1360 {
1361 (*info).data = ptr::null_mut();
1362 }
1363 _ => {
1364 }
1366 }
1367 } else {
1368 match probe_info.data {
1369 Some(PadProbeData::Buffer(buffer)) => {
1370 assert_eq!(data_type, Some(Buffer::static_type()));
1371 (*info).data = buffer.into_glib_ptr() as *mut libc::c_void;
1372 }
1373 Some(PadProbeData::BufferList(bufferlist)) => {
1374 assert_eq!(data_type, Some(BufferList::static_type()));
1375 (*info).data = bufferlist.into_glib_ptr() as *mut libc::c_void;
1376 }
1377 Some(PadProbeData::Event(event)) => {
1378 assert_eq!(data_type, Some(Event::static_type()));
1379 (*info).data = event.into_glib_ptr() as *mut libc::c_void;
1380 }
1381 Some(PadProbeData::Query(query)) => {
1382 assert_eq!(data_type, Some(Query::static_type()));
1383 (*info).data = query.as_mut_ptr() as *mut libc::c_void;
1384 }
1385 Some(PadProbeData::__Unknown(ptr)) => {
1386 assert_eq!(data_type, None);
1387 (*info).data = ptr as *mut libc::c_void;
1388 }
1389 None => {
1390 assert_eq!(data_type, None);
1391 }
1392 }
1393 }
1394
1395 let flow_ret: FlowReturn = probe_info.flow_res.into();
1396 (*info).ABI.abi.flow_ret = flow_ret.into_glib();
1397}
1398
1399unsafe extern "C" fn trampoline_pad_probe<
1400 T,
1401 F: Fn(&T, &mut PadProbeInfo) -> PadProbeReturn + Send + Sync + 'static,
1402>(
1403 pad: *mut ffi::GstPad,
1404 info: *mut ffi::GstPadProbeInfo,
1405 func: gpointer,
1406) -> ffi::GstPadProbeReturn
1407where
1408 T: IsA<Pad>,
1409{
1410 let func: &F = &*(func as *const F);
1411
1412 let (mut probe_info, data_type) = create_probe_info(info);
1413
1414 let ret = func(
1415 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1416 &mut probe_info,
1417 );
1418
1419 update_probe_info(ret, probe_info, data_type, info);
1420
1421 ret.into_glib()
1422}
1423
1424unsafe extern "C" fn trampoline_activate_function<
1425 T,
1426 F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
1427>(
1428 pad: *mut ffi::GstPad,
1429 parent: *mut ffi::GstObject,
1430) -> glib::ffi::gboolean
1431where
1432 T: IsA<Pad>,
1433{
1434 let func: &F = &*((*pad).activatedata as *const F);
1435
1436 match func(
1437 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1438 Option::<crate::Object>::from_glib_borrow(parent)
1439 .as_ref()
1440 .as_ref(),
1441 ) {
1442 Ok(()) => true,
1443 Err(err) => {
1444 err.log_with_object(&*Pad::from_glib_borrow(pad));
1445 false
1446 }
1447 }
1448 .into_glib()
1449}
1450
1451unsafe extern "C" fn trampoline_activatemode_function<
1452 T,
1453 F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
1454 + Send
1455 + Sync
1456 + 'static,
1457>(
1458 pad: *mut ffi::GstPad,
1459 parent: *mut ffi::GstObject,
1460 mode: ffi::GstPadMode,
1461 active: glib::ffi::gboolean,
1462) -> glib::ffi::gboolean
1463where
1464 T: IsA<Pad>,
1465{
1466 let func: &F = &*((*pad).activatemodedata as *const F);
1467
1468 match func(
1469 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1470 Option::<crate::Object>::from_glib_borrow(parent)
1471 .as_ref()
1472 .as_ref(),
1473 from_glib(mode),
1474 from_glib(active),
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
1485unsafe extern "C" fn trampoline_chain_function<
1486 T,
1487 F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
1488 + Send
1489 + Sync
1490 + 'static,
1491>(
1492 pad: *mut ffi::GstPad,
1493 parent: *mut ffi::GstObject,
1494 buffer: *mut ffi::GstBuffer,
1495) -> ffi::GstFlowReturn
1496where
1497 T: IsA<Pad>,
1498{
1499 let func: &F = &*((*pad).chaindata as *const F);
1500
1501 let res: FlowReturn = func(
1502 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1503 Option::<crate::Object>::from_glib_borrow(parent)
1504 .as_ref()
1505 .as_ref(),
1506 from_glib_full(buffer),
1507 )
1508 .into();
1509 res.into_glib()
1510}
1511
1512unsafe extern "C" fn trampoline_chain_list_function<
1513 T,
1514 F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
1515 + Send
1516 + Sync
1517 + 'static,
1518>(
1519 pad: *mut ffi::GstPad,
1520 parent: *mut ffi::GstObject,
1521 list: *mut ffi::GstBufferList,
1522) -> ffi::GstFlowReturn
1523where
1524 T: IsA<Pad>,
1525{
1526 let func: &F = &*((*pad).chainlistdata as *const F);
1527
1528 let res: FlowReturn = func(
1529 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1530 Option::<crate::Object>::from_glib_borrow(parent)
1531 .as_ref()
1532 .as_ref(),
1533 from_glib_full(list),
1534 )
1535 .into();
1536 res.into_glib()
1537}
1538
1539unsafe extern "C" fn trampoline_event_function<
1540 T,
1541 F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
1542>(
1543 pad: *mut ffi::GstPad,
1544 parent: *mut ffi::GstObject,
1545 event: *mut ffi::GstEvent,
1546) -> glib::ffi::gboolean
1547where
1548 T: IsA<Pad>,
1549{
1550 let func: &F = &*((*pad).eventdata as *const F);
1551
1552 func(
1553 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1554 Option::<crate::Object>::from_glib_borrow(parent)
1555 .as_ref()
1556 .as_ref(),
1557 from_glib_full(event),
1558 )
1559 .into_glib()
1560}
1561
1562unsafe extern "C" fn trampoline_event_full_function<
1563 T,
1564 F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
1565 + Send
1566 + Sync
1567 + 'static,
1568>(
1569 pad: *mut ffi::GstPad,
1570 parent: *mut ffi::GstObject,
1571 event: *mut ffi::GstEvent,
1572) -> ffi::GstFlowReturn
1573where
1574 T: IsA<Pad>,
1575{
1576 let func: &F = &*((*pad).eventdata as *const F);
1577
1578 let res: FlowReturn = func(
1579 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1580 Option::<crate::Object>::from_glib_borrow(parent)
1581 .as_ref()
1582 .as_ref(),
1583 from_glib_full(event),
1584 )
1585 .into();
1586 res.into_glib()
1587}
1588
1589#[allow(clippy::needless_option_as_deref)]
1590unsafe extern "C" fn trampoline_getrange_function<
1591 T,
1592 F: Fn(
1593 &T,
1594 Option<&crate::Object>,
1595 u64,
1596 Option<&mut crate::BufferRef>,
1597 u32,
1598 ) -> Result<PadGetRangeSuccess, crate::FlowError>
1599 + Send
1600 + Sync
1601 + 'static,
1602>(
1603 pad: *mut ffi::GstPad,
1604 parent: *mut ffi::GstObject,
1605 offset: u64,
1606 length: u32,
1607 buffer: *mut *mut ffi::GstBuffer,
1608) -> ffi::GstFlowReturn
1609where
1610 T: IsA<Pad>,
1611{
1612 let func: &F = &*((*pad).getrangedata as *const F);
1613
1614 debug_assert!(!buffer.is_null());
1615
1616 let pad = Pad::from_glib_borrow(pad);
1617 let pad = pad.unsafe_cast_ref();
1618 let mut passed_buffer = if (*buffer).is_null() {
1619 None
1620 } else {
1621 Some(crate::BufferRef::from_mut_ptr(*buffer))
1622 };
1623
1624 match func(
1625 pad,
1626 Option::<crate::Object>::from_glib_borrow(parent)
1627 .as_ref()
1628 .as_ref(),
1629 offset,
1630 passed_buffer.as_deref_mut(),
1631 length,
1632 ) {
1633 Ok(PadGetRangeSuccess::NewBuffer(new_buffer)) => {
1634 if let Some(passed_buffer) = passed_buffer {
1635 crate::debug!(
1636 crate::CAT_PERFORMANCE,
1637 obj = pad.unsafe_cast_ref::<glib::Object>(),
1638 "Returned new buffer from getrange function, copying into passed buffer"
1639 );
1640
1641 let mut map = match passed_buffer.map_writable() {
1642 Ok(map) => map,
1643 Err(_) => {
1644 crate::error!(
1645 crate::CAT_RUST,
1646 obj = pad.unsafe_cast_ref::<glib::Object>(),
1647 "Failed to map passed buffer writable"
1648 );
1649 return ffi::GST_FLOW_ERROR;
1650 }
1651 };
1652
1653 let copied_size = new_buffer.copy_to_slice(0, &mut map);
1654 drop(map);
1655
1656 if let Err(copied_size) = copied_size {
1657 passed_buffer.set_size(copied_size);
1658 }
1659
1660 match new_buffer.copy_into(passed_buffer, crate::BUFFER_COPY_METADATA, ..) {
1661 Ok(_) => FlowReturn::Ok.into_glib(),
1662 Err(_) => {
1663 crate::error!(
1664 crate::CAT_RUST,
1665 obj = pad.unsafe_cast_ref::<glib::Object>(),
1666 "Failed to copy buffer metadata"
1667 );
1668
1669 FlowReturn::Error.into_glib()
1670 }
1671 }
1672 } else {
1673 *buffer = new_buffer.into_glib_ptr();
1674 FlowReturn::Ok.into_glib()
1675 }
1676 }
1677 Ok(PadGetRangeSuccess::FilledBuffer) => {
1678 assert!(passed_buffer.is_some());
1679 FlowReturn::Ok.into_glib()
1680 }
1681 Err(ret) => FlowReturn::from_error(ret).into_glib(),
1682 }
1683}
1684
1685unsafe extern "C" fn trampoline_iterate_internal_links_function<
1686 T,
1687 F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
1688>(
1689 pad: *mut ffi::GstPad,
1690 parent: *mut ffi::GstObject,
1691) -> *mut ffi::GstIterator
1692where
1693 T: IsA<Pad>,
1694{
1695 let func: &F = &*((*pad).iterintlinkdata as *const F);
1696
1697 let ret = func(
1699 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1700 Option::<crate::Object>::from_glib_borrow(parent)
1701 .as_ref()
1702 .as_ref(),
1703 );
1704
1705 ret.into_glib_ptr()
1706}
1707
1708unsafe extern "C" fn trampoline_link_function<
1709 T,
1710 F: Fn(
1711 &T,
1712 Option<&crate::Object>,
1713 &crate::Pad,
1714 ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
1715 + Send
1716 + Sync
1717 + 'static,
1718>(
1719 pad: *mut ffi::GstPad,
1720 parent: *mut ffi::GstObject,
1721 peer: *mut ffi::GstPad,
1722) -> ffi::GstPadLinkReturn
1723where
1724 T: IsA<Pad>,
1725{
1726 let func: &F = &*((*pad).linkdata as *const F);
1727
1728 let res: crate::PadLinkReturn = func(
1729 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1730 Option::<crate::Object>::from_glib_borrow(parent)
1731 .as_ref()
1732 .as_ref(),
1733 &from_glib_borrow(peer),
1734 )
1735 .into();
1736 res.into_glib()
1737}
1738
1739unsafe extern "C" fn trampoline_query_function<
1740 T,
1741 F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
1742>(
1743 pad: *mut ffi::GstPad,
1744 parent: *mut ffi::GstObject,
1745 query: *mut ffi::GstQuery,
1746) -> glib::ffi::gboolean
1747where
1748 T: IsA<Pad>,
1749{
1750 let func: &F = &*((*pad).querydata as *const F);
1751
1752 func(
1753 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1754 Option::<crate::Object>::from_glib_borrow(parent)
1755 .as_ref()
1756 .as_ref(),
1757 crate::QueryRef::from_mut_ptr(query),
1758 )
1759 .into_glib()
1760}
1761
1762unsafe extern "C" fn trampoline_unlink_function<
1763 T,
1764 F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
1765>(
1766 pad: *mut ffi::GstPad,
1767 parent: *mut ffi::GstObject,
1768) where
1769 T: IsA<Pad>,
1770{
1771 let func: &F = &*((*pad).unlinkdata as *const F);
1772
1773 func(
1774 Pad::from_glib_borrow(pad).unsafe_cast_ref(),
1775 Option::<crate::Object>::from_glib_borrow(parent)
1776 .as_ref()
1777 .as_ref(),
1778 )
1779}
1780
1781unsafe extern "C" fn destroy_closure<F>(ptr: gpointer) {
1782 let _ = Box::<F>::from_raw(ptr as *mut _);
1783}
1784
1785impl Pad {
1786 #[doc(alias = "gst_pad_new")]
1808 pub fn new(direction: crate::PadDirection) -> Self {
1809 skip_assert_initialized!();
1810 Self::builder(direction).build()
1811 }
1812
1813 #[doc(alias = "gst_pad_new")]
1816 pub fn builder(direction: crate::PadDirection) -> PadBuilder<Self> {
1817 skip_assert_initialized!();
1818 PadBuilder::new(direction)
1819 }
1820
1821 #[doc(alias = "gst_pad_new_from_static_template")]
1850 pub fn from_static_template(templ: &StaticPadTemplate) -> Self {
1851 skip_assert_initialized!();
1852 Self::builder_from_static_template(templ).build()
1853 }
1854
1855 #[doc(alias = "gst_pad_new_from_static_template")]
1865 pub fn builder_from_static_template(templ: &StaticPadTemplate) -> PadBuilder<Self> {
1866 skip_assert_initialized!();
1867 PadBuilder::from_static_template(templ)
1868 }
1869
1870 #[doc(alias = "gst_pad_new_from_template")]
1896 pub fn from_template(templ: &crate::PadTemplate) -> Self {
1897 skip_assert_initialized!();
1898 Self::builder_from_template(templ).build()
1899 }
1900
1901 #[doc(alias = "gst_pad_new_from_template")]
1911 pub fn builder_from_template(templ: &crate::PadTemplate) -> PadBuilder<Self> {
1912 skip_assert_initialized!();
1913 PadBuilder::from_template(templ)
1914 }
1915
1916 #[doc(alias = "gst_pad_query_default")]
1917 pub fn query_default<O: IsA<Pad>>(
1918 pad: &O,
1919 parent: Option<&impl IsA<crate::Object>>,
1920 query: &mut QueryRef,
1921 ) -> bool {
1922 skip_assert_initialized!();
1923 unsafe {
1924 from_glib(ffi::gst_pad_query_default(
1925 pad.as_ref().to_glib_none().0,
1926 parent.map(|p| p.as_ref()).to_glib_none().0,
1927 query.as_mut_ptr(),
1928 ))
1929 }
1930 }
1931
1932 #[doc(alias = "gst_pad_event_default")]
1933 pub fn event_default<O: IsA<Pad>>(
1934 pad: &O,
1935 parent: Option<&impl IsA<crate::Object>>,
1936 event: impl Into<Event>,
1937 ) -> bool {
1938 skip_assert_initialized!();
1939 unsafe {
1940 from_glib(ffi::gst_pad_event_default(
1941 pad.as_ref().to_glib_none().0,
1942 parent.map(|p| p.as_ref()).to_glib_none().0,
1943 event.into().into_glib_ptr(),
1944 ))
1945 }
1946 }
1947
1948 #[doc(alias = "gst_pad_iterate_internal_links_default")]
1949 pub fn iterate_internal_links_default<O: IsA<Pad>>(
1950 pad: &O,
1951 parent: Option<&impl IsA<crate::Object>>,
1952 ) -> crate::Iterator<Pad> {
1953 skip_assert_initialized!();
1954 unsafe {
1955 from_glib_full(ffi::gst_pad_iterate_internal_links_default(
1956 pad.as_ref().to_glib_none().0,
1957 parent.map(|p| p.as_ref()).to_glib_none().0,
1958 ))
1959 }
1960 }
1961}
1962
1963pub(crate) enum PadBuilderName {
1964 Undefined,
1965 KeepGenerated,
1966 UserDefined(String),
1967 CandidateForWildcardTemplate(String),
1968}
1969
1970#[must_use = "The builder must be built to be used"]
1971pub struct PadBuilder<T> {
1972 pub(crate) pad: T,
1973 pub(crate) name: PadBuilderName,
1974}
1975
1976impl<T: IsA<Pad> + IsA<glib::Object> + glib::object::IsClass> PadBuilder<T> {
1977 pub fn new(direction: crate::PadDirection) -> Self {
1980 assert_initialized_main_thread!();
1981
1982 let pad = glib::Object::builder::<T>()
1983 .property("direction", direction)
1984 .build();
1985
1986 if let Some(pad) = pad.dynamic_cast_ref::<crate::GhostPad>() {
1988 unsafe {
1989 let res = ffi::gst_ghost_pad_construct(pad.to_glib_none().0);
1990 debug_assert_ne!(res, glib::ffi::GFALSE, "Failed to construct ghost pad");
1992 }
1993 }
1994
1995 PadBuilder {
1996 pad,
1997 name: PadBuilderName::Undefined,
1998 }
1999 }
2000
2001 pub fn from_static_template(templ: &StaticPadTemplate) -> Self {
2011 skip_assert_initialized!();
2012
2013 let templ = templ.get();
2014 Self::from_template(&templ)
2015 }
2016
2017 pub fn from_template(templ: &crate::PadTemplate) -> Self {
2027 assert_initialized_main_thread!();
2028
2029 let mut type_ = T::static_type();
2030 let gtype = templ.gtype();
2031
2032 if gtype == glib::Type::UNIT {
2033 } else if gtype.is_a(type_) {
2035 type_ = gtype;
2038 } else {
2039 assert!(type_.is_a(gtype));
2041 }
2042
2043 let mut properties = [
2044 ("direction", templ.direction().into()),
2045 ("template", templ.into()),
2046 ];
2047
2048 let pad =
2049 unsafe { glib::Object::with_mut_values(type_, &mut properties).unsafe_cast::<T>() };
2050
2051 if let Some(pad) = pad.dynamic_cast_ref::<crate::GhostPad>() {
2053 unsafe {
2054 let res = ffi::gst_ghost_pad_construct(pad.to_glib_none().0);
2055 debug_assert_ne!(res, glib::ffi::GFALSE, "Failed to construct ghost pad");
2057 }
2058 }
2059
2060 PadBuilder {
2061 pad,
2062 name: PadBuilderName::Undefined,
2063 }
2064 }
2065
2066 pub fn generated_name(mut self) -> Self {
2069 self.name = PadBuilderName::KeepGenerated;
2070 self
2071 }
2072
2073 pub fn name(mut self, name: impl Into<String>) -> Self {
2076 self.name = PadBuilderName::UserDefined(name.into());
2077
2078 self
2079 }
2080
2081 #[deprecated = "use `name_if_some()` instead"]
2087 pub fn maybe_name<N: Into<String>>(self, name: Option<N>) -> Self {
2088 if let Some(name) = name {
2089 self.name(name)
2090 } else {
2091 self
2092 }
2093 }
2094
2095 pub fn name_if_some<N: Into<String>>(self, name: Option<N>) -> Self {
2101 if let Some(name) = name {
2102 self.name(name)
2103 } else {
2104 self
2105 }
2106 }
2107
2108 #[doc(alias = "gst_pad_set_activate_function")]
2109 pub fn activate_function<F>(self, func: F) -> Self
2110 where
2111 F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
2112 {
2113 unsafe {
2114 self.pad.set_activate_function(func);
2115 }
2116
2117 self
2118 }
2119
2120 #[doc(alias = "gst_pad_set_activate_function")]
2121 pub fn activate_function_if_some<F>(self, func: Option<F>) -> Self
2122 where
2123 F: Fn(&T, Option<&crate::Object>) -> Result<(), LoggableError> + Send + Sync + 'static,
2124 {
2125 if let Some(func) = func {
2126 self.activate_function(func)
2127 } else {
2128 self
2129 }
2130 }
2131
2132 #[doc(alias = "gst_pad_set_activatemode_function")]
2133 pub fn activatemode_function<F>(self, func: F) -> Self
2134 where
2135 F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
2136 + Send
2137 + Sync
2138 + 'static,
2139 {
2140 unsafe {
2141 self.pad.set_activatemode_function(func);
2142 }
2143
2144 self
2145 }
2146
2147 #[doc(alias = "gst_pad_set_activatemode_function")]
2148 pub fn activatemode_function_if_some<F>(self, func: Option<F>) -> Self
2149 where
2150 F: Fn(&T, Option<&crate::Object>, crate::PadMode, bool) -> Result<(), LoggableError>
2151 + Send
2152 + Sync
2153 + 'static,
2154 {
2155 if let Some(func) = func {
2156 self.activatemode_function(func)
2157 } else {
2158 self
2159 }
2160 }
2161
2162 #[doc(alias = "gst_pad_set_chain_function")]
2163 pub fn chain_function<F>(self, func: F) -> Self
2164 where
2165 F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
2166 + Send
2167 + Sync
2168 + 'static,
2169 {
2170 unsafe {
2171 self.pad.set_chain_function(func);
2172 }
2173
2174 self
2175 }
2176
2177 #[doc(alias = "gst_pad_set_chain_function")]
2178 pub fn chain_function_if_some<F>(self, func: Option<F>) -> Self
2179 where
2180 F: Fn(&T, Option<&crate::Object>, crate::Buffer) -> Result<FlowSuccess, FlowError>
2181 + Send
2182 + Sync
2183 + 'static,
2184 {
2185 if let Some(func) = func {
2186 self.chain_function(func)
2187 } else {
2188 self
2189 }
2190 }
2191
2192 #[doc(alias = "gst_pad_set_chain_list_function")]
2193 pub fn chain_list_function<F>(self, func: F) -> Self
2194 where
2195 F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
2196 + Send
2197 + Sync
2198 + 'static,
2199 {
2200 unsafe {
2201 self.pad.set_chain_list_function(func);
2202 }
2203
2204 self
2205 }
2206
2207 #[doc(alias = "gst_pad_set_chain_list_function")]
2208 pub fn chain_list_function_if_some<F>(self, func: Option<F>) -> Self
2209 where
2210 F: Fn(&T, Option<&crate::Object>, crate::BufferList) -> Result<FlowSuccess, FlowError>
2211 + Send
2212 + Sync
2213 + 'static,
2214 {
2215 if let Some(func) = func {
2216 self.chain_list_function(func)
2217 } else {
2218 self
2219 }
2220 }
2221
2222 #[doc(alias = "gst_pad_set_event_function")]
2223 pub fn event_function<F>(self, func: F) -> Self
2224 where
2225 F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
2226 {
2227 unsafe {
2228 self.pad.set_event_function(func);
2229 }
2230
2231 self
2232 }
2233
2234 #[doc(alias = "gst_pad_set_event_function")]
2235 pub fn event_function_if_some<F>(self, func: Option<F>) -> Self
2236 where
2237 F: Fn(&T, Option<&crate::Object>, crate::Event) -> bool + Send + Sync + 'static,
2238 {
2239 if let Some(func) = func {
2240 self.event_function(func)
2241 } else {
2242 self
2243 }
2244 }
2245
2246 #[doc(alias = "gst_pad_set_event_full_function")]
2247 pub fn event_full_function<F>(self, func: F) -> Self
2248 where
2249 F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
2250 + Send
2251 + Sync
2252 + 'static,
2253 {
2254 unsafe {
2255 self.pad.set_event_full_function(func);
2256 }
2257
2258 self
2259 }
2260
2261 #[doc(alias = "gst_pad_set_event_full_function")]
2262 pub fn event_full_function_if_some<F>(self, func: Option<F>) -> Self
2263 where
2264 F: Fn(&T, Option<&crate::Object>, crate::Event) -> Result<FlowSuccess, FlowError>
2265 + Send
2266 + Sync
2267 + 'static,
2268 {
2269 if let Some(func) = func {
2270 self.event_full_function(func)
2271 } else {
2272 self
2273 }
2274 }
2275
2276 #[doc(alias = "gst_pad_set_getrange_function")]
2277 pub fn getrange_function<F>(self, func: F) -> Self
2278 where
2279 F: Fn(
2280 &T,
2281 Option<&crate::Object>,
2282 u64,
2283 Option<&mut crate::BufferRef>,
2284 u32,
2285 ) -> Result<PadGetRangeSuccess, crate::FlowError>
2286 + Send
2287 + Sync
2288 + 'static,
2289 {
2290 unsafe {
2291 self.pad.set_getrange_function(func);
2292 }
2293
2294 self
2295 }
2296
2297 #[doc(alias = "gst_pad_set_getrange_function")]
2298 pub fn getrange_function_if_some<F>(self, func: Option<F>) -> Self
2299 where
2300 F: Fn(
2301 &T,
2302 Option<&crate::Object>,
2303 u64,
2304 Option<&mut crate::BufferRef>,
2305 u32,
2306 ) -> Result<PadGetRangeSuccess, crate::FlowError>
2307 + Send
2308 + Sync
2309 + 'static,
2310 {
2311 if let Some(func) = func {
2312 self.getrange_function(func)
2313 } else {
2314 self
2315 }
2316 }
2317
2318 #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
2319 pub fn iterate_internal_links_function<F>(self, func: F) -> Self
2320 where
2321 F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
2322 {
2323 unsafe {
2324 self.pad.set_iterate_internal_links_function(func);
2325 }
2326
2327 self
2328 }
2329
2330 #[doc(alias = "gst_pad_set_iterate_internal_links_function")]
2331 pub fn iterate_internal_links_function_if_some<F>(self, func: Option<F>) -> Self
2332 where
2333 F: Fn(&T, Option<&crate::Object>) -> crate::Iterator<Pad> + Send + Sync + 'static,
2334 {
2335 if let Some(func) = func {
2336 self.iterate_internal_links_function(func)
2337 } else {
2338 self
2339 }
2340 }
2341
2342 #[doc(alias = "gst_pad_set_link_function")]
2343 pub fn link_function<F>(self, func: F) -> Self
2344 where
2345 F: Fn(
2346 &T,
2347 Option<&crate::Object>,
2348 &Pad,
2349 ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
2350 + Send
2351 + Sync
2352 + 'static,
2353 {
2354 unsafe {
2355 self.pad.set_link_function(func);
2356 }
2357
2358 self
2359 }
2360
2361 #[doc(alias = "gst_pad_set_link_function")]
2362 pub fn link_function_if_some<F>(self, func: Option<F>) -> Self
2363 where
2364 F: Fn(
2365 &T,
2366 Option<&crate::Object>,
2367 &Pad,
2368 ) -> Result<crate::PadLinkSuccess, crate::PadLinkError>
2369 + Send
2370 + Sync
2371 + 'static,
2372 {
2373 if let Some(func) = func {
2374 self.link_function(func)
2375 } else {
2376 self
2377 }
2378 }
2379
2380 #[doc(alias = "gst_pad_set_query_function")]
2381 pub fn query_function<F>(self, func: F) -> Self
2382 where
2383 F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
2384 {
2385 unsafe {
2386 self.pad.set_query_function(func);
2387 }
2388
2389 self
2390 }
2391
2392 #[doc(alias = "gst_pad_set_query_function")]
2393 pub fn query_function_if_some<F>(self, func: Option<F>) -> Self
2394 where
2395 F: Fn(&T, Option<&crate::Object>, &mut crate::QueryRef) -> bool + Send + Sync + 'static,
2396 {
2397 if let Some(func) = func {
2398 self.query_function(func)
2399 } else {
2400 self
2401 }
2402 }
2403
2404 #[doc(alias = "gst_pad_set_unlink_function")]
2405 pub fn unlink_function<F>(self, func: F) -> Self
2406 where
2407 F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
2408 {
2409 unsafe {
2410 self.pad.set_unlink_function(func);
2411 }
2412
2413 self
2414 }
2415
2416 #[doc(alias = "gst_pad_set_unlink_function")]
2417 pub fn unlink_function_if_some<F>(self, func: Option<F>) -> Self
2418 where
2419 F: Fn(&T, Option<&crate::Object>) + Send + Sync + 'static,
2420 {
2421 if let Some(func) = func {
2422 self.unlink_function(func)
2423 } else {
2424 self
2425 }
2426 }
2427
2428 pub fn flags(self, flags: PadFlags) -> Self {
2429 self.pad.set_pad_flags(flags);
2430
2431 self
2432 }
2433
2434 pub fn flags_if_some(self, flags: Option<PadFlags>) -> Self {
2435 if let Some(flags) = flags {
2436 self.flags(flags)
2437 } else {
2438 self
2439 }
2440 }
2441
2442 #[must_use = "Building the pad without using it has no effect"]
2456 #[track_caller]
2457 pub fn build(self) -> T {
2458 let Self { pad, name } = self;
2459
2460 let templ = pad.pad_template();
2461
2462 use PadBuilderName::*;
2463 match (name, templ) {
2464 (KeepGenerated, _) => (),
2465 (Undefined, None) => (),
2466 (Undefined, Some(templ)) => {
2467 if templ.name().find('%').is_some() {
2468 panic!(concat!(
2469 "Attempt to build a Pad from a wildcard-name template",
2470 " or with a target Pad with an incompatible name.",
2471 " Make sure to define a specific name using PadBuilder",
2472 " or opt-in to keep the automatically generated name.",
2473 ));
2474 } else {
2475 pad.set_property("name", templ.name());
2476 }
2477 }
2478 (UserDefined(name), _) | (CandidateForWildcardTemplate(name), None) => {
2479 pad.set_property("name", name);
2480 }
2481 (CandidateForWildcardTemplate(name), Some(templ)) => {
2482 if templ.name().find('%').is_none() {
2483 pad.set_property("name", templ.name());
2485 } else {
2486 let mut can_assign_name = true;
2487
2488 if templ.presence() == crate::PadPresence::Request {
2489 use crate::CAT_RUST;
2491
2492 let mut name_parts = name.split('_');
2493 for templ_part in templ.name_template().split('_') {
2494 let Some(name_part) = name_parts.next() else {
2495 crate::debug!(
2496 CAT_RUST,
2497 "Not using Pad name '{name}': not enough parts compared to template '{}'",
2498 templ.name_template(),
2499 );
2500 can_assign_name = false;
2501 break;
2502 };
2503
2504 if let Some(conv_spec_start) = templ_part.find('%') {
2505 if conv_spec_start > 0
2506 && !name_part.starts_with(&templ_part[..conv_spec_start])
2507 {
2508 crate::debug!(
2509 CAT_RUST,
2510 "Not using Pad name '{name}': mismatch template '{}' prefix",
2511 templ.name_template(),
2512 );
2513 can_assign_name = false;
2514 break;
2515 }
2516
2517 let conv_spec_pos = conv_spec_start + 1;
2518 match templ_part.get(conv_spec_pos..=conv_spec_pos) {
2519 Some("s") => {
2520 break;
2522 }
2523 Some("u") => {
2524 if name_part
2525 .get(conv_spec_start..)
2526 .map_or(true, |s| s.parse::<u32>().is_err())
2527 {
2528 crate::debug!(
2529 CAT_RUST,
2530 "Not using Pad name '{name}': can't parse '%u' from '{name_part}' (template '{}')",
2531 templ.name_template(),
2532 );
2533
2534 can_assign_name = false;
2535 break;
2536 }
2537 }
2538 Some("d") => {
2539 if name_part
2540 .get(conv_spec_start..)
2541 .map_or(true, |s| s.parse::<i32>().is_err())
2542 {
2543 crate::debug!(
2544 CAT_RUST,
2545 "Not using target Pad name '{name}': can't parse '%i' from '{name_part}' (template '{}')",
2546 templ.name_template(),
2547 );
2548
2549 can_assign_name = false;
2550 break;
2551 }
2552 }
2553 other => {
2554 unreachable!("Unexpected conversion specifier {other:?}")
2555 }
2556 }
2557 } else if name_part != templ_part {
2558 can_assign_name = false;
2559 }
2560 }
2561 }
2562
2563 if can_assign_name {
2564 pad.set_property("name", name);
2565 } else {
2566 panic!(concat!(
2567 "Attempt to build a Pad from a wildcard-name template",
2568 " with a target Pad with an incompatible name.",
2569 " Make sure to define a specific name using PadBuilder",
2570 " or opt-in to keep the automatically generated name.",
2571 ));
2572 }
2573 }
2574 }
2575 }
2576
2577 pad
2578 }
2579}
2580
2581#[cfg(test)]
2582mod tests {
2583 use std::sync::{atomic::AtomicUsize, mpsc::channel, Arc, Mutex};
2584
2585 use super::*;
2586
2587 #[test]
2588 fn test_event_chain_functions() {
2589 crate::init().unwrap();
2590
2591 let events = Arc::new(Mutex::new(Vec::new()));
2592 let events_clone = events.clone();
2593 let buffers = Arc::new(Mutex::new(Vec::new()));
2594 let buffers_clone = buffers.clone();
2595 let pad = crate::Pad::builder(crate::PadDirection::Sink)
2596 .name("sink")
2597 .event_function(move |_, _, event| {
2598 let mut events = events_clone.lock().unwrap();
2599 events.push(event);
2600
2601 true
2602 })
2603 .chain_function(move |_, _, buffer| {
2604 let mut buffers = buffers_clone.lock().unwrap();
2605 buffers.push(buffer);
2606
2607 Ok(FlowSuccess::Ok)
2608 })
2609 .build();
2610
2611 pad.set_active(true).unwrap();
2612
2613 assert!(pad.send_event(crate::event::StreamStart::new("test")));
2614 let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2615 assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2616
2617 assert_eq!(pad.chain(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2618
2619 let events = events.lock().unwrap();
2620 let buffers = buffers.lock().unwrap();
2621 assert_eq!(events.len(), 2);
2622 assert_eq!(buffers.len(), 1);
2623
2624 match events[0].view() {
2625 crate::EventView::StreamStart(..) => (),
2626 _ => unreachable!(),
2627 }
2628
2629 match events[1].view() {
2630 crate::EventView::Segment(..) => (),
2631 _ => unreachable!(),
2632 }
2633 }
2634
2635 #[test]
2636 fn test_getrange_function() {
2637 crate::init().unwrap();
2638
2639 let pad = crate::Pad::builder(crate::PadDirection::Src)
2640 .name("src")
2641 .activate_function(|pad, _parent| {
2642 pad.activate_mode(crate::PadMode::Pull, true)
2643 .map_err(|err| err.into())
2644 })
2645 .getrange_function(|_pad, _parent, offset, _buffer, size| {
2646 assert_eq!(offset, 0);
2647 assert_eq!(size, 5);
2648 let buffer = crate::Buffer::from_slice(b"abcde");
2649 Ok(PadGetRangeSuccess::NewBuffer(buffer))
2650 })
2651 .build();
2652 pad.set_active(true).unwrap();
2653
2654 let buffer = pad.range(0, 5).unwrap();
2655 let map = buffer.map_readable().unwrap();
2656 assert_eq!(&*map, b"abcde");
2657
2658 let mut buffer = crate::Buffer::with_size(5).unwrap();
2659 pad.range_fill(0, buffer.get_mut().unwrap(), 5).unwrap();
2660 let map = buffer.map_readable().unwrap();
2661 assert_eq!(&*map, b"abcde");
2662
2663 pad.set_active(false).unwrap();
2664 drop(pad);
2665
2666 let pad = crate::Pad::builder(crate::PadDirection::Src)
2667 .name("src")
2668 .activate_function(|pad, _parent| {
2669 pad.activate_mode(crate::PadMode::Pull, true)
2670 .map_err(|err| err.into())
2671 })
2672 .getrange_function(|_pad, _parent, offset, buffer, size| {
2673 assert_eq!(offset, 0);
2674 assert_eq!(size, 5);
2675 if let Some(buffer) = buffer {
2676 buffer.copy_from_slice(0, b"fghij").unwrap();
2677 Ok(PadGetRangeSuccess::FilledBuffer)
2678 } else {
2679 let buffer = crate::Buffer::from_slice(b"abcde");
2680 Ok(PadGetRangeSuccess::NewBuffer(buffer))
2681 }
2682 })
2683 .build();
2684 pad.set_active(true).unwrap();
2685
2686 let buffer = pad.range(0, 5).unwrap();
2687 let map = buffer.map_readable().unwrap();
2688 assert_eq!(&*map, b"abcde");
2689
2690 let mut buffer = crate::Buffer::with_size(5).unwrap();
2691 pad.range_fill(0, buffer.get_mut().unwrap(), 5).unwrap();
2692 let map = buffer.map_readable().unwrap();
2693 assert_eq!(&*map, b"fghij");
2694 }
2695
2696 #[test]
2697 fn test_task() {
2698 crate::init().unwrap();
2699
2700 let pad = crate::Pad::builder(crate::PadDirection::Sink)
2701 .name("sink")
2702 .build();
2703 let (sender, receiver) = channel();
2704
2705 let mut i = 0;
2706 let pad_clone = pad.clone();
2707 pad.start_task(move || {
2708 i += 1;
2709 if i == 3 {
2710 sender.send(i).unwrap();
2711 pad_clone.pause_task().unwrap();
2712 }
2713 })
2714 .unwrap();
2715
2716 assert_eq!(receiver.recv().unwrap(), 3);
2717 }
2718
2719 #[test]
2720 fn test_remove_probe_from_probe() {
2721 crate::init().unwrap();
2722
2723 let src_pad = crate::Pad::builder(crate::PadDirection::Src)
2724 .name("src")
2725 .build();
2726 let sink_pad = crate::Pad::builder(crate::PadDirection::Sink)
2727 .name("sink")
2728 .chain_function(|_pad, _parent, _buffer| Ok(crate::FlowSuccess::Ok))
2729 .build();
2730
2731 src_pad.link(&sink_pad).unwrap();
2732
2733 let counter = Arc::new(AtomicUsize::new(0));
2734 let counter_clone = counter.clone();
2735 src_pad.add_probe(crate::PadProbeType::BUFFER, move |pad, info| {
2736 if let Some(PadProbeData::Buffer(_)) = info.data {
2737 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
2738 pad.remove_probe(info.id.take().expect("no pad probe id"));
2739 } else {
2740 unreachable!();
2741 }
2742 crate::PadProbeReturn::Handled
2743 });
2744
2745 sink_pad.set_active(true).unwrap();
2746 src_pad.set_active(true).unwrap();
2747
2748 assert!(src_pad.push_event(crate::event::StreamStart::new("test")));
2749 let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2750 assert!(src_pad.push_event(crate::event::Segment::new(segment.as_ref())));
2751
2752 assert_eq!(src_pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2753 assert_eq!(src_pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2754
2755 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
2756 }
2757
2758 fn do_probe_with_return(probe_return: crate::PadProbeReturn) {
2759 skip_assert_initialized!();
2760 crate::init().unwrap();
2761
2762 let (major, minor, micro, _) = crate::version();
2763 let pad = crate::Pad::builder(crate::PadDirection::Src)
2764 .name("src")
2765 .build();
2766 let events = Arc::new(Mutex::new(Vec::new()));
2767 let buffers = Arc::new(Mutex::new(Vec::new()));
2768
2769 let flow_override = if (major, minor, micro) >= (1, 16, 1) {
2770 Err(FlowError::Eos)
2771 } else {
2772 Ok(FlowSuccess::Ok)
2775 };
2776
2777 {
2778 let events = events.clone();
2779 pad.add_probe(crate::PadProbeType::EVENT_DOWNSTREAM, move |_, info| {
2780 if let Some(PadProbeData::Event(event)) = &info.data {
2781 let mut events = events.lock().unwrap();
2782 events.push(event.clone());
2783 } else {
2784 unreachable!();
2785 }
2786 crate::PadProbeReturn::Ok
2787 });
2788 }
2789
2790 {
2791 let events = events.clone();
2792 pad.add_probe(crate::PadProbeType::EVENT_UPSTREAM, move |_, info| {
2793 if let Some(event) = info.take_event() {
2794 let mut events = events.lock().unwrap();
2795 events.push(event);
2796 } else {
2797 unreachable!();
2798 }
2799 probe_return
2800 });
2801 }
2802
2803 {
2804 let buffers = buffers.clone();
2805 pad.add_probe(crate::PadProbeType::BUFFER, move |_, info| {
2806 if let Some(buffer) = info.take_buffer() {
2807 let mut buffers = buffers.lock().unwrap();
2808 info.flow_res = if buffers.is_empty() {
2809 Ok(FlowSuccess::Ok)
2810 } else {
2811 flow_override
2812 };
2813 buffers.push(buffer);
2814 } else {
2815 unreachable!();
2816 }
2817 probe_return
2818 });
2819 }
2820
2821 pad.set_active(true).unwrap();
2822
2823 assert!(
2824 pad.send_event(crate::event::Latency::new(crate::ClockTime::from_nseconds(
2825 10
2826 )))
2827 );
2828 assert!(pad.push_event(crate::event::StreamStart::new("test")));
2829 let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2830 assert!(pad.push_event(crate::event::Segment::new(segment.as_ref())));
2831
2832 assert_eq!(pad.push(crate::Buffer::new()), Ok(FlowSuccess::Ok));
2833 assert_eq!(
2834 pad.push(crate::Buffer::new()),
2835 if probe_return == crate::PadProbeReturn::Drop {
2837 Ok(FlowSuccess::Ok)
2838 } else {
2839 flow_override
2840 }
2841 );
2842
2843 let events = events.lock().unwrap();
2844 let buffers = buffers.lock().unwrap();
2845 assert_eq!(events.len(), 3);
2846 assert_eq!(buffers.len(), 2);
2847
2848 assert_eq!(events[0].type_(), crate::EventType::Latency);
2849 assert_eq!(events[1].type_(), crate::EventType::StreamStart);
2850 assert_eq!(events[2].type_(), crate::EventType::Segment);
2851
2852 assert!(
2853 buffers.iter().all(|b| b.is_writable()),
2854 "A buffer ref leaked!"
2855 );
2856
2857 drop(pad); assert!(
2859 events.iter().all(|e| e.is_writable()),
2860 "An event ref leaked!"
2861 );
2862 }
2863
2864 #[test]
2865 fn test_probe() {
2866 crate::init().unwrap();
2867 do_probe_with_return(crate::PadProbeReturn::Handled);
2868 }
2869
2870 #[test]
2871 fn test_probe_drop() {
2872 crate::init().unwrap();
2873 do_probe_with_return(crate::PadProbeReturn::Drop);
2874 }
2875
2876 #[test]
2877 fn test_sticky_events() {
2878 crate::init().unwrap();
2879
2880 let pad = crate::Pad::builder(crate::PadDirection::Sink)
2881 .name("sink")
2882 .build();
2883 pad.set_active(true).unwrap();
2884
2885 assert!(pad.send_event(crate::event::StreamStart::new("test")));
2887
2888 let caps = crate::Caps::builder("some/x-caps").build();
2889 assert!(pad.send_event(crate::event::Caps::new(&caps)));
2890
2891 let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2892 assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2893
2894 let stream_start = pad.sticky_event::<crate::event::StreamStart>(0).unwrap();
2895 assert_eq!(stream_start.stream_id(), "test");
2896
2897 let caps2 = pad.sticky_event::<crate::event::Caps>(0).unwrap();
2898 assert_eq!(&*caps, caps2.caps());
2899
2900 let segment = pad.sticky_event::<crate::event::Segment>(0).unwrap();
2901 assert_eq!(segment.segment().format(), crate::Format::Time);
2902 }
2903
2904 #[test]
2905 fn test_sticky_events_foreach() {
2906 crate::init().unwrap();
2907
2908 let pad = crate::Pad::builder(crate::PadDirection::Sink)
2909 .name("sink")
2910 .build();
2911 pad.set_active(true).unwrap();
2912
2913 assert!(pad.send_event(crate::event::StreamStart::new("test")));
2915
2916 let caps = crate::Caps::builder("some/x-caps").build();
2917 assert!(pad.send_event(crate::event::Caps::new(&caps)));
2918
2919 let segment = crate::FormattedSegment::<crate::ClockTime>::new();
2920 assert!(pad.send_event(crate::event::Segment::new(segment.as_ref())));
2921
2922 let mut sticky_events = Vec::new();
2923 pad.sticky_events_foreach(|event| {
2924 sticky_events.push(event.clone());
2925 ControlFlow::Continue(EventForeachAction::Keep)
2926 });
2927 assert_eq!(sticky_events.len(), 3);
2928
2929 let mut sticky_events2 = Vec::new();
2931 pad.sticky_events_foreach(|event| {
2932 sticky_events2.push(event.clone());
2933 if event.type_() == crate::EventType::Caps {
2934 ControlFlow::Break(EventForeachAction::Keep)
2935 } else {
2936 ControlFlow::Continue(EventForeachAction::Keep)
2937 }
2938 });
2939 assert_eq!(sticky_events2.len(), 2);
2940
2941 let mut sticky_events3 = Vec::new();
2942 pad.sticky_events_foreach(|event| {
2943 sticky_events3.push(event.clone());
2944 ControlFlow::Continue(EventForeachAction::Keep)
2945 });
2946 assert_eq!(sticky_events3.len(), 3);
2947
2948 for (e1, e2) in sticky_events.iter().zip(sticky_events3.iter()) {
2949 assert_eq!(e1.as_ref() as *const _, e2.as_ref() as *const _);
2950 }
2951
2952 pad.sticky_events_foreach(|event| {
2954 let action = if event.type_() == crate::EventType::Segment {
2955 let byte_segment = crate::FormattedSegment::<crate::format::Bytes>::new();
2956 EventForeachAction::Replace(crate::event::Segment::new(&byte_segment))
2957 } else {
2958 EventForeachAction::Keep
2959 };
2960 ControlFlow::Continue(action)
2961 });
2962
2963 let mut sticky_events4 = Vec::new();
2965 pad.sticky_events_foreach(|event| {
2966 sticky_events4.push(event.clone());
2967 ControlFlow::Continue(EventForeachAction::Keep)
2968 });
2969 assert_eq!(sticky_events4.len(), 3);
2970 assert_eq!(
2971 sticky_events[0].as_ref() as *const _,
2972 sticky_events4[0].as_ref() as *const _
2973 );
2974 assert_eq!(
2975 sticky_events[1].as_ref() as *const _,
2976 sticky_events4[1].as_ref() as *const _
2977 );
2978 assert_ne!(
2979 sticky_events[2].as_ref() as *const _,
2980 sticky_events4[2].as_ref() as *const _
2981 );
2982
2983 pad.sticky_events_foreach(|event| {
2985 let action = if event.type_() == crate::EventType::Caps {
2986 EventForeachAction::Remove
2987 } else {
2988 EventForeachAction::Keep
2989 };
2990 ControlFlow::Continue(action)
2991 });
2992
2993 let mut sticky_events5 = Vec::new();
2995 pad.sticky_events_foreach(|event| {
2996 sticky_events5.push(event.clone());
2997 ControlFlow::Continue(EventForeachAction::Keep)
2998 });
2999 assert_eq!(sticky_events5.len(), 2);
3000 assert_eq!(
3001 sticky_events4[0].as_ref() as *const _,
3002 sticky_events5[0].as_ref() as *const _
3003 );
3004 assert_eq!(
3005 sticky_events4[2].as_ref() as *const _,
3006 sticky_events5[1].as_ref() as *const _
3007 );
3008 }
3009
3010 #[test]
3011 #[allow(deprecated)] fn naming() {
3013 crate::init().unwrap();
3014
3015 let pad = crate::Pad::builder(crate::PadDirection::Sink).build();
3016 assert!(pad.name().starts_with("pad"));
3017
3018 let pad = crate::Pad::builder(crate::PadDirection::Src).build();
3019 assert!(pad.name().starts_with("pad"));
3020
3021 let pad = crate::Pad::builder(crate::PadDirection::Unknown).build();
3022 assert!(pad.name().starts_with("pad"));
3023
3024 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3025 .generated_name()
3026 .build();
3027 assert!(pad.name().starts_with("pad"));
3028
3029 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3030 .maybe_name(None::<&str>)
3031 .build();
3032 assert!(pad.name().starts_with("pad"));
3033
3034 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3035 .name_if_some(None::<&str>)
3036 .build();
3037 assert!(pad.name().starts_with("pad"));
3038
3039 let pad = crate::Pad::builder(crate::PadDirection::Sink)
3040 .name("sink_0")
3041 .build();
3042 assert_eq!(pad.name(), "sink_0");
3043
3044 let pad = crate::Pad::builder(crate::PadDirection::Src)
3045 .name("src_0")
3046 .build();
3047 assert_eq!(pad.name(), "src_0");
3048
3049 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3050 .name("test")
3051 .build();
3052 assert_eq!(pad.name(), "test");
3053
3054 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3055 .maybe_name(Some("test"))
3056 .build();
3057 assert_eq!(pad.name(), "test");
3058
3059 let pad = crate::Pad::builder(crate::PadDirection::Unknown)
3060 .name_if_some(Some("test"))
3061 .build();
3062 assert_eq!(pad.name(), "test");
3063
3064 let caps = crate::Caps::new_any();
3065 let templ = crate::PadTemplate::new(
3066 "sink",
3067 crate::PadDirection::Sink,
3068 crate::PadPresence::Always,
3069 &caps,
3070 )
3071 .unwrap();
3072
3073 let pad = Pad::from_template(&templ);
3074 assert!(pad.name().starts_with("sink"));
3075
3076 let pad = Pad::builder_from_template(&templ)
3077 .name("audio_sink")
3078 .build();
3079 assert!(pad.name().starts_with("audio_sink"));
3080
3081 let pad = Pad::builder_from_template(&templ).generated_name().build();
3082 assert!(pad.name().starts_with("pad"));
3083
3084 let templ = crate::PadTemplate::new(
3085 "audio_%u",
3086 crate::PadDirection::Sink,
3087 crate::PadPresence::Request,
3088 &caps,
3089 )
3090 .unwrap();
3091
3092 let pad = Pad::builder_from_template(&templ).name("audio_0").build();
3093 assert!(pad.name().starts_with("audio_0"));
3094
3095 let pad = Pad::builder_from_template(&templ).generated_name().build();
3096 assert!(pad.name().starts_with("pad"));
3097 }
3098
3099 #[test]
3100 #[should_panic]
3101 fn missing_name() {
3102 crate::init().unwrap();
3103
3104 let caps = crate::Caps::new_any();
3105 let templ = crate::PadTemplate::new(
3106 "audio_%u",
3107 crate::PadDirection::Sink,
3108 crate::PadPresence::Request,
3109 &caps,
3110 )
3111 .unwrap();
3112
3113 let _pad = Pad::from_template(&templ);
3116 }
3117}