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