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