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