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