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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 => (), 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 #[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 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 }
1365 Some(PadProbeData::BufferList(_)) => {
1366 assert_eq!(data_type, Some(BufferList::static_type()));
1367 }
1369 Some(PadProbeData::Event(_)) => {
1370 assert_eq!(data_type, Some(Event::static_type()));
1371 }
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 (*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 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 }
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 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 #[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 #[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 #[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 #[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 #[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 #[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 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 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 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 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 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 } else if gtype.is_a(type_) {
2092 type_ = gtype;
2095 } else {
2096 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 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 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 pub fn generated_name(mut self) -> Self {
2126 self.name = PadBuilderName::KeepGenerated;
2127 self
2128 }
2129
2130 pub fn name(mut self, name: impl Into<String>) -> Self {
2133 self.name = PadBuilderName::UserDefined(name.into());
2134
2135 self
2136 }
2137
2138 #[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 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 #[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 pad.set_property("name", templ.name());
2542 } else {
2543 let mut can_assign_name = true;
2544
2545 if templ.presence() == crate::PadPresence::Request {
2546 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 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 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 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); 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 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 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 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 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 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 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 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)] 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 let _pad = Pad::from_template(&templ);
3179 }
3180}