1use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, ops::ControlFlow, pin::Pin};
4
5use glib::translate::*;
6use itertools::Itertools;
7
8use crate::{
9 ffi,
10 format::{
11 CompatibleFormattedValue, FormattedValue, SpecificFormattedValueFullRange,
12 SpecificFormattedValueIntrinsic,
13 },
14 prelude::*,
15 ClockTime, Element, ElementFlags, Event, Format, GenericFormattedValue, Pad, PadTemplate,
16 Plugin, QueryRef, Rank, State,
17};
18
19impl Element {
20 #[doc(alias = "gst_element_link_many")]
21 pub fn link_many<E: AsRef<Element> + Clone>(
22 elements: impl IntoIterator<Item = E>,
23 ) -> Result<(), glib::BoolError> {
24 skip_assert_initialized!();
25 for (src, dest) in elements.into_iter().tuple_windows() {
26 unsafe {
27 glib::result_from_gboolean!(
28 ffi::gst_element_link(
29 src.as_ref().to_glib_none().0,
30 dest.as_ref().to_glib_none().0,
31 ),
32 "Failed to link elements '{}' and '{}'",
33 src.as_ref().name(),
34 dest.as_ref().name(),
35 )?;
36 }
37 }
38
39 Ok(())
40 }
41
42 #[doc(alias = "gst_element_unlink_many")]
43 pub fn unlink_many<E: AsRef<Element> + Clone>(elements: impl IntoIterator<Item = E>) {
44 skip_assert_initialized!();
45 for (src, dest) in elements.into_iter().tuple_windows() {
46 unsafe {
47 ffi::gst_element_unlink(
48 src.as_ref().to_glib_none().0,
49 dest.as_ref().to_glib_none().0,
50 );
51 }
52 }
53 }
54
55 #[doc(alias = "gst_element_register")]
71 pub fn register(
72 plugin: Option<&Plugin>,
73 name: &str,
74 rank: Rank,
75 type_: glib::types::Type,
76 ) -> Result<(), glib::error::BoolError> {
77 skip_assert_initialized!();
78 unsafe {
79 glib::result_from_gboolean!(
80 ffi::gst_element_register(
81 plugin.to_glib_none().0,
82 name.to_glib_none().0,
83 rank.into_glib() as u32,
84 type_.into_glib()
85 ),
86 "Failed to register element factory"
87 )
88 }
89 }
90}
91
92#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
93pub enum ElementMessageType {
94 Error,
95 Warning,
96 Info,
97}
98
99#[derive(Debug, PartialEq, Eq)]
100pub struct NotifyWatchId(NonZeroU64);
101
102impl IntoGlib for NotifyWatchId {
103 type GlibType = libc::c_ulong;
104
105 #[inline]
106 fn into_glib(self) -> libc::c_ulong {
107 self.0.get() as libc::c_ulong
108 }
109}
110
111impl FromGlib<libc::c_ulong> for NotifyWatchId {
112 #[inline]
113 unsafe fn from_glib(val: libc::c_ulong) -> NotifyWatchId {
114 skip_assert_initialized!();
115 debug_assert_ne!(val, 0);
116 NotifyWatchId(NonZeroU64::new_unchecked(val as _))
117 }
118}
119
120pub trait ElementExtManual: IsA<Element> + 'static {
121 #[doc(alias = "get_element_class")]
122 #[inline]
123 fn element_class(&self) -> &glib::Class<Element> {
124 unsafe { self.unsafe_cast_ref::<Element>().class() }
125 }
126
127 #[doc(alias = "get_current_state")]
128 fn current_state(&self) -> State {
129 self.state(Some(ClockTime::ZERO)).1
130 }
131
132 #[doc(alias = "get_pending_state")]
133 fn pending_state(&self) -> State {
134 self.state(Some(ClockTime::ZERO)).2
135 }
136
137 #[doc(alias = "gst_element_query")]
153 fn query(&self, query: &mut QueryRef) -> bool {
154 unsafe {
155 from_glib(ffi::gst_element_query(
156 self.as_ref().to_glib_none().0,
157 query.as_mut_ptr(),
158 ))
159 }
160 }
161
162 #[doc(alias = "gst_element_send_event")]
178 fn send_event(&self, event: impl Into<Event>) -> bool {
179 unsafe {
180 from_glib(ffi::gst_element_send_event(
181 self.as_ref().to_glib_none().0,
182 event.into().into_glib_ptr(),
183 ))
184 }
185 }
186
187 #[doc(alias = "get_metadata")]
195 #[doc(alias = "gst_element_class_get_metadata")]
196 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
197 self.element_class().metadata(key)
198 }
199
200 #[doc(alias = "get_pad_template")]
210 #[doc(alias = "gst_element_class_get_pad_template")]
211 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
212 self.element_class().pad_template(name)
213 }
214
215 #[doc(alias = "get_pad_template_list")]
223 #[doc(alias = "gst_element_class_get_pad_template_list")]
224 fn pad_template_list(&self) -> glib::List<PadTemplate> {
225 self.element_class().pad_template_list()
226 }
227
228 #[allow(clippy::too_many_arguments)]
255 #[doc(alias = "gst_element_message_full")]
256 fn message_full<T: crate::MessageErrorDomain>(
257 &self,
258 type_: ElementMessageType,
259 code: T,
260 message: Option<&str>,
261 debug: Option<&str>,
262 file: &str,
263 function: &str,
264 line: u32,
265 ) {
266 unsafe {
267 let type_ = match type_ {
268 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
269 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
270 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
271 };
272
273 ffi::gst_element_message_full(
274 self.as_ref().to_glib_none().0,
275 type_,
276 T::domain().into_glib(),
277 code.code(),
278 message.to_glib_full(),
279 debug.to_glib_full(),
280 file.to_glib_none().0,
281 function.to_glib_none().0,
282 line as i32,
283 );
284 }
285 }
286
287 fn set_element_flags(&self, flags: ElementFlags) {
288 unsafe {
289 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
290 let _guard = self.as_ref().object_lock();
291 (*ptr).flags |= flags.into_glib();
292 }
293 }
294
295 fn unset_element_flags(&self, flags: ElementFlags) {
296 unsafe {
297 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
298 let _guard = self.as_ref().object_lock();
299 (*ptr).flags &= !flags.into_glib();
300 }
301 }
302
303 #[doc(alias = "get_element_flags")]
304 fn element_flags(&self) -> ElementFlags {
305 unsafe {
306 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
307 let _guard = self.as_ref().object_lock();
308 from_glib((*ptr).flags)
309 }
310 }
311
312 #[allow(clippy::too_many_arguments)]
339 #[doc(alias = "gst_element_message_full_with_details")]
340 fn message_full_with_details<T: crate::MessageErrorDomain>(
341 &self,
342 type_: ElementMessageType,
343 code: T,
344 message: Option<&str>,
345 debug: Option<&str>,
346 file: &str,
347 function: &str,
348 line: u32,
349 structure: crate::Structure,
350 ) {
351 unsafe {
352 let type_ = match type_ {
353 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
354 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
355 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
356 };
357
358 ffi::gst_element_message_full_with_details(
359 self.as_ref().to_glib_none().0,
360 type_,
361 T::domain().into_glib(),
362 code.code(),
363 message.to_glib_full(),
364 debug.to_glib_full(),
365 file.to_glib_none().0,
366 function.to_glib_none().0,
367 line as i32,
368 structure.into_glib_ptr(),
369 );
370 }
371 }
372
373 fn post_error_message(&self, msg: crate::ErrorMessage) {
374 let crate::ErrorMessage {
375 error_domain,
376 error_code,
377 ref message,
378 ref debug,
379 filename,
380 function,
381 line,
382 } = msg;
383
384 unsafe {
385 ffi::gst_element_message_full(
386 self.as_ref().to_glib_none().0,
387 ffi::GST_MESSAGE_ERROR,
388 error_domain.into_glib(),
389 error_code,
390 message.to_glib_full(),
391 debug.to_glib_full(),
392 filename.to_glib_none().0,
393 function.to_glib_none().0,
394 line as i32,
395 );
396 }
397 }
398
399 #[doc(alias = "gst_element_iterate_pads")]
412 fn iterate_pads(&self) -> crate::Iterator<Pad> {
413 unsafe {
414 from_glib_full(ffi::gst_element_iterate_pads(
415 self.as_ref().to_glib_none().0,
416 ))
417 }
418 }
419
420 #[doc(alias = "gst_element_iterate_sink_pads")]
431 fn iterate_sink_pads(&self) -> crate::Iterator<Pad> {
432 unsafe {
433 from_glib_full(ffi::gst_element_iterate_sink_pads(
434 self.as_ref().to_glib_none().0,
435 ))
436 }
437 }
438
439 #[doc(alias = "gst_element_iterate_src_pads")]
450 fn iterate_src_pads(&self) -> crate::Iterator<Pad> {
451 unsafe {
452 from_glib_full(ffi::gst_element_iterate_src_pads(
453 self.as_ref().to_glib_none().0,
454 ))
455 }
456 }
457
458 #[doc(alias = "get_pads")]
459 #[doc(alias = "gst_element_foreach_pad")]
460 fn pads(&self) -> Vec<Pad> {
461 unsafe {
462 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
463 let _guard = self.as_ref().object_lock();
464 FromGlibPtrContainer::from_glib_none(elt.pads)
465 }
466 }
467
468 #[doc(alias = "get_sink_pads")]
469 #[doc(alias = "gst_element_foreach_sink_pad")]
470 fn sink_pads(&self) -> Vec<Pad> {
471 unsafe {
472 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
473 let _guard = self.as_ref().object_lock();
474 FromGlibPtrContainer::from_glib_none(elt.sinkpads)
475 }
476 }
477
478 #[doc(alias = "get_src_pads")]
479 #[doc(alias = "gst_element_foreach_src_pad")]
480 fn src_pads(&self) -> Vec<Pad> {
481 unsafe {
482 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
483 let _guard = self.as_ref().object_lock();
484 FromGlibPtrContainer::from_glib_none(elt.srcpads)
485 }
486 }
487
488 #[doc(alias = "gst_element_foreach_pad")]
502 fn foreach_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
503 unsafe extern "C" fn trampoline<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(
504 element: *mut ffi::GstElement,
505 pad: *mut ffi::GstPad,
506 user_data: glib::ffi::gpointer,
507 ) -> glib::ffi::gboolean {
508 let element = from_glib_borrow(element);
509 let pad = from_glib_borrow(pad);
510 let callback = user_data as *mut F;
511 (*callback)(&element, &pad).is_continue().into_glib()
512 }
513
514 unsafe {
515 let mut func = func;
516 let func_ptr: &mut F = &mut func;
517
518 let _ = ffi::gst_element_foreach_pad(
519 self.as_ptr() as *mut _,
520 Some(trampoline::<F>),
521 func_ptr as *mut _ as *mut _,
522 );
523 }
524 }
525
526 #[doc(alias = "gst_element_foreach_sink_pad")]
540 fn foreach_sink_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
541 unsafe extern "C" fn trampoline<P: FnMut(&Element, &Pad) -> ControlFlow<()>>(
542 element: *mut ffi::GstElement,
543 pad: *mut ffi::GstPad,
544 user_data: glib::ffi::gpointer,
545 ) -> glib::ffi::gboolean {
546 let element = from_glib_borrow(element);
547 let pad = from_glib_borrow(pad);
548 let callback = user_data as *mut P;
549 (*callback)(&element, &pad).is_continue().into_glib()
550 }
551
552 unsafe {
553 let mut func = func;
554 let func_ptr: &mut F = &mut func;
555
556 let _ = ffi::gst_element_foreach_sink_pad(
557 self.as_ptr() as *mut _,
558 Some(trampoline::<F>),
559 func_ptr as *mut _ as *mut _,
560 );
561 }
562 }
563
564 #[doc(alias = "gst_element_foreach_src_pad")]
578 fn foreach_src_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
579 unsafe extern "C" fn trampoline<P: FnMut(&Element, &Pad) -> ControlFlow<()>>(
580 element: *mut ffi::GstElement,
581 pad: *mut ffi::GstPad,
582 user_data: glib::ffi::gpointer,
583 ) -> glib::ffi::gboolean {
584 let element = from_glib_borrow(element);
585 let pad = from_glib_borrow(pad);
586 let callback = user_data as *mut P;
587 (*callback)(&element, &pad).is_continue().into_glib()
588 }
589
590 unsafe {
591 let mut func = func;
592 let func_ptr: &mut F = &mut func;
593
594 let _ = ffi::gst_element_foreach_src_pad(
595 self.as_ptr() as *mut _,
596 Some(trampoline::<F>),
597 func_ptr as *mut _ as *mut _,
598 );
599 }
600 }
601
602 fn num_pads(&self) -> u16 {
603 unsafe {
604 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
605 let _guard = self.as_ref().object_lock();
606 elt.numpads
607 }
608 }
609
610 fn num_sink_pads(&self) -> u16 {
611 unsafe {
612 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
613 let _guard = self.as_ref().object_lock();
614 elt.numsinkpads
615 }
616 }
617
618 fn num_src_pads(&self) -> u16 {
619 unsafe {
620 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
621 let _guard = self.as_ref().object_lock();
622 elt.numsrcpads
623 }
624 }
625
626 #[doc(alias = "gst_element_add_property_deep_notify_watch")]
637 fn add_property_deep_notify_watch(
638 &self,
639 property_name: Option<&str>,
640 include_value: bool,
641 ) -> NotifyWatchId {
642 let property_name = property_name.to_glib_none();
643 unsafe {
644 from_glib(ffi::gst_element_add_property_deep_notify_watch(
645 self.as_ref().to_glib_none().0,
646 property_name.0,
647 include_value.into_glib(),
648 ))
649 }
650 }
651
652 #[doc(alias = "gst_element_add_property_notify_watch")]
663 fn add_property_notify_watch(
664 &self,
665 property_name: Option<&str>,
666 include_value: bool,
667 ) -> NotifyWatchId {
668 let property_name = property_name.to_glib_none();
669 unsafe {
670 from_glib(ffi::gst_element_add_property_notify_watch(
671 self.as_ref().to_glib_none().0,
672 property_name.0,
673 include_value.into_glib(),
674 ))
675 }
676 }
677
678 #[doc(alias = "gst_element_remove_property_notify_watch")]
681 fn remove_property_notify_watch(&self, watch_id: NotifyWatchId) {
682 unsafe {
683 ffi::gst_element_remove_property_notify_watch(
684 self.as_ref().to_glib_none().0,
685 watch_id.into_glib(),
686 );
687 }
688 }
689
690 #[doc(alias = "gst_element_query_convert")]
705 fn query_convert<U: SpecificFormattedValueFullRange>(
706 &self,
707 src_val: impl FormattedValue,
708 ) -> Option<U> {
709 unsafe {
710 let mut dest_val = mem::MaybeUninit::uninit();
711 let ret = from_glib(ffi::gst_element_query_convert(
712 self.as_ref().to_glib_none().0,
713 src_val.format().into_glib(),
714 src_val.into_raw_value(),
715 U::default_format().into_glib(),
716 dest_val.as_mut_ptr(),
717 ));
718 if ret {
719 Some(U::from_raw(U::default_format(), dest_val.assume_init()))
720 } else {
721 None
722 }
723 }
724 }
725
726 #[doc(alias = "gst_element_query_convert")]
727 fn query_convert_generic(
728 &self,
729 src_val: impl FormattedValue,
730 dest_format: Format,
731 ) -> Option<GenericFormattedValue> {
732 unsafe {
733 let mut dest_val = mem::MaybeUninit::uninit();
734 let ret = from_glib(ffi::gst_element_query_convert(
735 self.as_ref().to_glib_none().0,
736 src_val.format().into_glib(),
737 src_val.into_raw_value(),
738 dest_format.into_glib(),
739 dest_val.as_mut_ptr(),
740 ));
741 if ret {
742 Some(GenericFormattedValue::new(
743 dest_format,
744 dest_val.assume_init(),
745 ))
746 } else {
747 None
748 }
749 }
750 }
751
752 #[doc(alias = "gst_element_query_duration")]
770 fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
771 unsafe {
772 let mut duration = mem::MaybeUninit::uninit();
773 let ret = from_glib(ffi::gst_element_query_duration(
774 self.as_ref().to_glib_none().0,
775 T::default_format().into_glib(),
776 duration.as_mut_ptr(),
777 ));
778 if ret {
779 try_from_glib(duration.assume_init()).ok()
780 } else {
781 None
782 }
783 }
784 }
785
786 #[doc(alias = "gst_element_query_duration")]
787 fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
788 unsafe {
789 let mut duration = mem::MaybeUninit::uninit();
790 let ret = from_glib(ffi::gst_element_query_duration(
791 self.as_ref().to_glib_none().0,
792 format.into_glib(),
793 duration.as_mut_ptr(),
794 ));
795 if ret {
796 Some(GenericFormattedValue::new(format, duration.assume_init()))
797 } else {
798 None
799 }
800 }
801 }
802
803 #[doc(alias = "gst_element_query_position")]
823 fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
824 unsafe {
825 let mut cur = mem::MaybeUninit::uninit();
826 let ret = from_glib(ffi::gst_element_query_position(
827 self.as_ref().to_glib_none().0,
828 T::default_format().into_glib(),
829 cur.as_mut_ptr(),
830 ));
831 if ret {
832 try_from_glib(cur.assume_init()).ok()
833 } else {
834 None
835 }
836 }
837 }
838
839 #[doc(alias = "gst_element_query_position")]
840 fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
841 unsafe {
842 let mut cur = mem::MaybeUninit::uninit();
843 let ret = from_glib(ffi::gst_element_query_position(
844 self.as_ref().to_glib_none().0,
845 format.into_glib(),
846 cur.as_mut_ptr(),
847 ));
848 if ret {
849 Some(GenericFormattedValue::new(format, cur.assume_init()))
850 } else {
851 None
852 }
853 }
854 }
855
856 #[doc(alias = "gst_element_seek")]
881 fn seek<V: FormattedValue>(
882 &self,
883 rate: f64,
884 flags: crate::SeekFlags,
885 start_type: crate::SeekType,
886 start: V,
887 stop_type: crate::SeekType,
888 stop: impl CompatibleFormattedValue<V>,
889 ) -> Result<(), glib::error::BoolError> {
890 let stop = stop.try_into_checked(start).unwrap();
891
892 unsafe {
893 glib::result_from_gboolean!(
894 ffi::gst_element_seek(
895 self.as_ref().to_glib_none().0,
896 rate,
897 start.format().into_glib(),
898 flags.into_glib(),
899 start_type.into_glib(),
900 start.into_raw_value(),
901 stop_type.into_glib(),
902 stop.into_raw_value(),
903 ),
904 "Failed to seek",
905 )
906 }
907 }
908
909 #[doc(alias = "gst_element_seek_simple")]
939 fn seek_simple(
940 &self,
941 seek_flags: crate::SeekFlags,
942 seek_pos: impl FormattedValue,
943 ) -> Result<(), glib::error::BoolError> {
944 unsafe {
945 glib::result_from_gboolean!(
946 ffi::gst_element_seek_simple(
947 self.as_ref().to_glib_none().0,
948 seek_pos.format().into_glib(),
949 seek_flags.into_glib(),
950 seek_pos.into_raw_value(),
951 ),
952 "Failed to seek",
953 )
954 }
955 }
956
957 #[doc(alias = "gst_element_call_async")]
972 fn call_async<F>(&self, func: F)
973 where
974 F: FnOnce(&Self) + Send + 'static,
975 {
976 let user_data: Box<Option<F>> = Box::new(Some(func));
977
978 unsafe extern "C" fn trampoline<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
979 element: *mut ffi::GstElement,
980 user_data: glib::ffi::gpointer,
981 ) {
982 let user_data: &mut Option<F> = &mut *(user_data as *mut _);
983 let callback = user_data.take().unwrap();
984
985 callback(Element::from_glib_borrow(element).unsafe_cast_ref());
986 }
987
988 unsafe extern "C" fn free_user_data<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
989 user_data: glib::ffi::gpointer,
990 ) {
991 let _: Box<Option<F>> = Box::from_raw(user_data as *mut _);
992 }
993
994 unsafe {
995 ffi::gst_element_call_async(
996 self.as_ref().to_glib_none().0,
997 Some(trampoline::<Self, F>),
998 Box::into_raw(user_data) as *mut _,
999 Some(free_user_data::<Self, F>),
1000 );
1001 }
1002 }
1003
1004 fn call_async_future<F, T>(&self, func: F) -> Pin<Box<dyn Future<Output = T> + Send + 'static>>
1005 where
1006 F: FnOnce(&Self) -> T + Send + 'static,
1007 T: Send + 'static,
1008 {
1009 use futures_channel::oneshot;
1010
1011 let (sender, receiver) = oneshot::channel();
1012
1013 self.call_async(move |element| {
1014 let _ = sender.send(func(element));
1015 });
1016
1017 Box::pin(async move { receiver.await.expect("sender dropped") })
1018 }
1019
1020 #[doc(alias = "get_current_running_time")]
1029 #[doc(alias = "gst_element_get_current_running_time")]
1030 fn current_running_time(&self) -> Option<crate::ClockTime> {
1031 let base_time = self.base_time();
1032 let clock_time = self.current_clock_time();
1033
1034 clock_time
1035 .zip(base_time)
1036 .and_then(|(ct, bt)| ct.checked_sub(bt))
1037 }
1038
1039 #[doc(alias = "get_current_clock_time")]
1047 #[doc(alias = "gst_element_get_current_clock_time")]
1048 fn current_clock_time(&self) -> Option<crate::ClockTime> {
1049 self.clock().as_ref().map(crate::Clock::time)
1050 }
1051
1052 #[doc(alias = "gst_element_get_request_pad")]
1068 #[doc(alias = "get_request_pad")]
1069 #[doc(alias = "gst_element_request_pad_simple")]
1070 fn request_pad_simple(&self, name: &str) -> Option<Pad> {
1071 unsafe {
1072 #[cfg(feature = "v1_20")]
1073 {
1074 from_glib_full(ffi::gst_element_request_pad_simple(
1075 self.as_ref().to_glib_none().0,
1076 name.to_glib_none().0,
1077 ))
1078 }
1079 #[cfg(not(feature = "v1_20"))]
1080 {
1081 from_glib_full(ffi::gst_element_get_request_pad(
1082 self.as_ref().to_glib_none().0,
1083 name.to_glib_none().0,
1084 ))
1085 }
1086 }
1087 }
1088
1089 #[doc(alias = "gst_element_link")]
1104 fn link(&self, dest: &impl IsA<Element>) -> Result<(), glib::error::BoolError> {
1105 unsafe {
1106 glib::result_from_gboolean!(
1107 ffi::gst_element_link(
1108 self.as_ref().to_glib_none().0,
1109 dest.as_ref().to_glib_none().0
1110 ),
1111 "Failed to link elements '{}' and '{}'",
1112 self.as_ref().name(),
1113 dest.as_ref().name(),
1114 )
1115 }
1116 }
1117
1118 #[doc(alias = "gst_element_link_filtered")]
1136 fn link_filtered(
1137 &self,
1138 dest: &impl IsA<Element>,
1139 filter: &crate::Caps,
1140 ) -> Result<(), glib::error::BoolError> {
1141 unsafe {
1142 glib::result_from_gboolean!(
1143 ffi::gst_element_link_filtered(
1144 self.as_ref().to_glib_none().0,
1145 dest.as_ref().to_glib_none().0,
1146 filter.to_glib_none().0
1147 ),
1148 "Failed to link elements '{}' and '{}' with filter '{:?}'",
1149 self.as_ref().name(),
1150 dest.as_ref().name(),
1151 filter,
1152 )
1153 }
1154 }
1155
1156 #[doc(alias = "gst_element_link_pads")]
1173 fn link_pads(
1174 &self,
1175 srcpadname: Option<&str>,
1176 dest: &impl IsA<Element>,
1177 destpadname: Option<&str>,
1178 ) -> Result<(), glib::error::BoolError> {
1179 unsafe {
1180 glib::result_from_gboolean!(
1181 ffi::gst_element_link_pads(
1182 self.as_ref().to_glib_none().0,
1183 srcpadname.to_glib_none().0,
1184 dest.as_ref().to_glib_none().0,
1185 destpadname.to_glib_none().0
1186 ),
1187 "Failed to link pads '{}' and '{}'",
1188 if let Some(srcpadname) = srcpadname {
1189 format!("{}:{}", self.as_ref().name(), srcpadname)
1190 } else {
1191 format!("{}:*", self.as_ref().name())
1192 },
1193 if let Some(destpadname) = destpadname {
1194 format!("{}:{}", dest.as_ref().name(), destpadname)
1195 } else {
1196 format!("{}:*", dest.as_ref().name())
1197 },
1198 )
1199 }
1200 }
1201
1202 #[doc(alias = "gst_element_link_pads_filtered")]
1222 fn link_pads_filtered(
1223 &self,
1224 srcpadname: Option<&str>,
1225 dest: &impl IsA<Element>,
1226 destpadname: Option<&str>,
1227 filter: &crate::Caps,
1228 ) -> Result<(), glib::error::BoolError> {
1229 unsafe {
1230 glib::result_from_gboolean!(
1231 ffi::gst_element_link_pads_filtered(
1232 self.as_ref().to_glib_none().0,
1233 srcpadname.to_glib_none().0,
1234 dest.as_ref().to_glib_none().0,
1235 destpadname.to_glib_none().0,
1236 filter.to_glib_none().0
1237 ),
1238 "Failed to link pads '{}' and '{}' with filter '{:?}'",
1239 if let Some(srcpadname) = srcpadname {
1240 format!("{}:{}", self.as_ref().name(), srcpadname)
1241 } else {
1242 format!("{}:*", self.as_ref().name())
1243 },
1244 if let Some(destpadname) = destpadname {
1245 format!("{}:{}", dest.as_ref().name(), destpadname)
1246 } else {
1247 format!("{}:*", dest.as_ref().name())
1248 },
1249 filter,
1250 )
1251 }
1252 }
1253
1254 #[doc(alias = "gst_element_link_pads_full")]
1279 fn link_pads_full(
1280 &self,
1281 srcpadname: Option<&str>,
1282 dest: &impl IsA<Element>,
1283 destpadname: Option<&str>,
1284 flags: crate::PadLinkCheck,
1285 ) -> Result<(), glib::error::BoolError> {
1286 unsafe {
1287 glib::result_from_gboolean!(
1288 ffi::gst_element_link_pads_full(
1289 self.as_ref().to_glib_none().0,
1290 srcpadname.to_glib_none().0,
1291 dest.as_ref().to_glib_none().0,
1292 destpadname.to_glib_none().0,
1293 flags.into_glib()
1294 ),
1295 "Failed to link pads '{}' and '{}' with flags '{:?}'",
1296 if let Some(srcpadname) = srcpadname {
1297 format!("{}:{}", self.as_ref().name(), srcpadname)
1298 } else {
1299 format!("{}:*", self.as_ref().name())
1300 },
1301 if let Some(destpadname) = destpadname {
1302 format!("{}:{}", dest.as_ref().name(), destpadname)
1303 } else {
1304 format!("{}:*", dest.as_ref().name())
1305 },
1306 flags,
1307 )
1308 }
1309 }
1310}
1311
1312impl<O: IsA<Element>> ElementExtManual for O {}
1313
1314pub unsafe trait ElementClassExt {
1315 #[doc(alias = "get_metadata")]
1323 #[doc(alias = "gst_element_class_get_metadata")]
1324 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
1325 unsafe {
1326 let klass = self as *const _ as *const ffi::GstElementClass;
1327
1328 let ptr = ffi::gst_element_class_get_metadata(klass as *mut _, key.to_glib_none().0);
1329
1330 if ptr.is_null() {
1331 None
1332 } else {
1333 Some(CStr::from_ptr(ptr).to_str().unwrap())
1334 }
1335 }
1336 }
1337
1338 #[doc(alias = "get_pad_template")]
1351 #[doc(alias = "gst_element_class_get_pad_template")]
1352 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1353 unsafe {
1354 let klass = self as *const _ as *const ffi::GstElementClass;
1355
1356 from_glib_none(ffi::gst_element_class_get_pad_template(
1357 klass as *mut _,
1358 name.to_glib_none().0,
1359 ))
1360 }
1361 }
1362
1363 #[doc(alias = "get_pad_template_list")]
1374 #[doc(alias = "gst_element_class_get_pad_template_list")]
1375 fn pad_template_list(&self) -> glib::List<PadTemplate> {
1376 unsafe {
1377 let klass = self as *const _ as *const ffi::GstElementClass;
1378
1379 glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1380 klass as *mut _,
1381 ))
1382 }
1383 }
1384}
1385
1386unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1387
1388#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1392pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1393 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1394#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1397pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1398 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1399#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1402pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1403 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1404#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1408pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1409 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1410#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1414pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1415 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1416#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1418pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1419 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1420
1421#[doc(alias = "GST_ELEMENT_ERROR")]
1422#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1423#[macro_export]
1424macro_rules! element_error(
1425 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1426 use $crate::prelude::ElementExtManual;
1427 $obj.message_full(
1428 $crate::ElementMessageType::Error,
1429 $err,
1430 Some(&format!($($msg)*)),
1431 Some(&format!($($debug)*)),
1432 file!(),
1433 $crate::glib::function_name!(),
1434 line!(),
1435 );
1436 }};
1437 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1438 use $crate::prelude::ElementExtManual;
1439 $obj.message_full(
1440 $crate::ElementMessageType::Error,
1441 $err,
1442 Some(&format!($($msg)*)),
1443 None,
1444 file!(),
1445 $crate::glib::function_name!(),
1446 line!(),
1447 );
1448 }};
1449 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1450 use $crate::prelude::ElementExtManual;
1451 $obj.message_full(
1452 $crate::ElementMessageType::Error,
1453 $err,
1454 None,
1455 Some(&format!($($debug)*)),
1456 file!(),
1457 $crate::glib::function_name!(),
1458 line!(),
1459 );
1460 }};
1461
1462 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1463 use $crate::prelude::ElementExtManual;
1464 $obj.message_full_with_details(
1465 $crate::ElementMessageType::Error,
1466 $err,
1467 Some(&format!($($msg)*)),
1468 Some(&format!($($debug)*)),
1469 file!(),
1470 $crate::glib::function_name!(),
1471 line!(),
1472 $details,
1473 );
1474 }};
1475 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1476 use $crate::prelude::ElementExtManual;
1477 $obj.message_full_with_details(
1478 $crate::ElementMessageType::Error,
1479 $err,
1480 Some(&format!($($msg)*)),
1481 None,
1482 file!(),
1483 $crate::glib::function_name!(),
1484 line!(),
1485 $details,
1486 );
1487 }};
1488 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1489 use $crate::prelude::ElementExtManual;
1490 $obj.message_full_with_details(
1491 $crate::ElementMessageType::Error,
1492 $err,
1493 None,
1494 Some(&format!($($debug)*)),
1495 file!(),
1496 $crate::glib::function_name!(),
1497 line!(),
1498 $details,
1499 );
1500 }};
1501);
1502
1503#[doc(alias = "GST_ELEMENT_WARNING")]
1504#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1505#[macro_export]
1506macro_rules! element_warning(
1507 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1508 use $crate::prelude::ElementExtManual;
1509 $obj.message_full(
1510 $crate::ElementMessageType::Warning,
1511 $err,
1512 Some(&format!($($msg)*)),
1513 Some(&format!($($debug)*)),
1514 file!(),
1515 $crate::glib::function_name!(),
1516 line!(),
1517 );
1518 }};
1519 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1520 use $crate::prelude::ElementExtManual;
1521 $obj.message_full(
1522 $crate::ElementMessageType::Warning,
1523 $err,
1524 Some(&format!($($msg)*)),
1525 None,
1526 file!(),
1527 $crate::glib::function_name!(),
1528 line!(),
1529 );
1530 }};
1531 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1532 use $crate::prelude::ElementExtManual;
1533 $obj.message_full(
1534 $crate::ElementMessageType::Warning,
1535 $err,
1536 None,
1537 Some(&format!($($debug)*)),
1538 file!(),
1539 $crate::glib::function_name!(),
1540 line!(),
1541 );
1542 }};
1543
1544 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1545 use $crate::prelude::ElementExtManual;
1546 $obj.message_full_with_details(
1547 $crate::ElementMessageType::Warning,
1548 $err,
1549 Some(&format!($($msg)*)),
1550 Some(&format!($($debug)*)),
1551 file!(),
1552 $crate::glib::function_name!(),
1553 line!(),
1554 $details,
1555 );
1556 }};
1557 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1558 use $crate::prelude::ElementExtManual;
1559 $obj.message_full_with_details(
1560 $crate::ElementMessageType::Warning,
1561 $err,
1562 Some(&format!($($msg)*)),
1563 None,
1564 file!(),
1565 $crate::glib::function_name!(),
1566 line!(),
1567 $details,
1568 );
1569 }};
1570 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1571 use $crate::prelude::ElementExtManual;
1572 $obj.message_full_with_details(
1573 $crate::ElementMessageType::Warning,
1574 $err,
1575 None,
1576 Some(&format!($($debug)*)),
1577 file!(),
1578 $crate::glib::function_name!(),
1579 line!(),
1580 $details,
1581 );
1582 }};
1583);
1584
1585#[doc(alias = "GST_ELEMENT_INFO")]
1586#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1587#[macro_export]
1588macro_rules! element_info(
1589 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1590 use $crate::prelude::ElementExtManual;
1591 $obj.message_full(
1592 $crate::ElementMessageType::Info,
1593 $err,
1594 Some(&format!($($msg)*)),
1595 Some(&format!($($debug)*)),
1596 file!(),
1597 $crate::glib::function_name!(),
1598 line!(),
1599 );
1600 }};
1601 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1602 use $crate::prelude::ElementExtManual;
1603 $obj.message_full(
1604 $crate::ElementMessageType::Info,
1605 $err,
1606 Some(&format!($($msg)*)),
1607 None,
1608 file!(),
1609 $crate::glib::function_name!(),
1610 line!(),
1611 );
1612 }};
1613 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1614 use $crate::prelude::ElementExtManual;
1615 $obj.message_full(
1616 $crate::ElementMessageType::Info,
1617 $err,
1618 None,
1619 Some(&format!($($debug)*)),
1620 file!(),
1621 $crate::glib::function_name!(),
1622 line!(),
1623 );
1624 }};
1625
1626 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1627 use $crate::prelude::ElementExtManual;
1628 $obj.message_full_with_details(
1629 $crate::ElementMessageType::Info,
1630 $err,
1631 Some(&format!($($msg)*)),
1632 Some(&format!($($debug)*)),
1633 file!(),
1634 $crate::glib::function_name!(),
1635 line!(),
1636 $details,
1637 );
1638 }};
1639 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1640 use $crate::prelude::ElementExtManual;
1641 $obj.message_full_with_details(
1642 $crate::ElementMessageType::Info,
1643 $err,
1644 Some(&format!($($msg)*)),
1645 None,
1646 file!(),
1647 $crate::glib::function_name!(),
1648 line!(),
1649 $details,
1650 );
1651 }};
1652 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1653 use $crate::prelude::ElementExtManual;
1654 $obj.message_full_with_details(
1655 $crate::ElementMessageType::Info,
1656 $err,
1657 None,
1658 Some(&format!($($debug)*)),
1659 file!(),
1660 $crate::glib::function_name!(),
1661 line!(),
1662 $details,
1663 );
1664 }};
1665);
1666
1667#[doc(alias = "GST_ELEMENT_ERROR")]
1668#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1669#[macro_export]
1670macro_rules! element_imp_error(
1671 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1672 let obj = $imp.obj();
1673 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1674 }};
1675 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1676 let obj = $imp.obj();
1677 $crate::element_error!(obj, $err, ($($msg)*));
1678 }};
1679 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1680 let obj = $imp.obj();
1681 $crate::element_error!(obj, $err, [$($debug)*]);
1682 }};
1683
1684 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1685 let obj = $imp.obj();
1686 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1687 }};
1688 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1689 let obj = $imp.obj();
1690 $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1691 }};
1692 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1693 let obj = $imp.obj();
1694 $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1695 }};
1696);
1697
1698#[doc(alias = "GST_ELEMENT_WARNING")]
1699#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1700#[macro_export]
1701macro_rules! element_imp_warning(
1702 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1703 let obj = $imp.obj();
1704 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1705 }};
1706 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1707 let obj = $imp.obj();
1708 $crate::element_warning!(obj, $err, ($($msg)*));
1709 }};
1710 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1711 let obj = $imp.obj();
1712 $crate::element_warning!(obj, $err, [$($debug)*]);
1713 }};
1714
1715 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1716 let obj = $imp.obj();
1717 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1718 }};
1719 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1720 let obj = $imp.obj();
1721 $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1722 }};
1723 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1724 let obj = $imp.obj();
1725 $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1726 }};
1727);
1728
1729#[doc(alias = "GST_ELEMENT_INFO")]
1730#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1731#[macro_export]
1732macro_rules! element_imp_info(
1733 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1734 let obj = $imp.obj();
1735 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1736 }};
1737 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1738 let obj = $imp.obj();
1739 $crate::element_info!(obj, $err, ($($msg)*));
1740 }};
1741 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1742 let obj = $imp.obj();
1743 $crate::element_info!(obj, $err, [$($debug)*]);
1744 }};
1745
1746 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1747 let obj = $imp.obj();
1748 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1749 }};
1750 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1751 let obj = $imp.obj();
1752 $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1753 }};
1754 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1755 let obj = $imp.obj();
1756 $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1757 }};
1758);
1759
1760#[cfg(test)]
1761mod tests {
1762 use std::sync::mpsc::channel;
1763
1764 use glib::GString;
1765
1766 use super::*;
1767
1768 #[test]
1769 fn test_get_pads() {
1770 crate::init().unwrap();
1771
1772 let identity = crate::ElementFactory::make("identity").build().unwrap();
1773
1774 let mut pad_names = identity
1775 .pads()
1776 .iter()
1777 .map(|p| p.name())
1778 .collect::<Vec<GString>>();
1779 pad_names.sort();
1780 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1781
1782 let mut pad_names = identity
1783 .sink_pads()
1784 .iter()
1785 .map(|p| p.name())
1786 .collect::<Vec<GString>>();
1787 pad_names.sort();
1788 assert_eq!(pad_names, vec![String::from("sink")]);
1789
1790 let mut pad_names = identity
1791 .src_pads()
1792 .iter()
1793 .map(|p| p.name())
1794 .collect::<Vec<GString>>();
1795 pad_names.sort();
1796 assert_eq!(pad_names, vec![String::from("src")]);
1797 }
1798
1799 #[test]
1800 fn test_foreach_pad() {
1801 crate::init().unwrap();
1802
1803 let identity = crate::ElementFactory::make("identity").build().unwrap();
1804
1805 let mut pad_names = Vec::new();
1806 identity.foreach_pad(|_element, pad| {
1807 pad_names.push(pad.name());
1808
1809 ControlFlow::Continue(())
1810 });
1811 pad_names.sort();
1812 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1813
1814 pad_names.clear();
1815 identity.foreach_sink_pad(|_element, pad| {
1816 pad_names.push(pad.name());
1817
1818 ControlFlow::Continue(())
1819 });
1820 assert_eq!(pad_names, vec![String::from("sink")]);
1821
1822 pad_names.clear();
1823 identity.foreach_src_pad(|_element, pad| {
1824 pad_names.push(pad.name());
1825
1826 ControlFlow::Continue(())
1827 });
1828 assert_eq!(pad_names, vec![String::from("src")]);
1829 }
1830
1831 #[test]
1832 fn test_call_async() {
1833 crate::init().unwrap();
1834
1835 let identity = crate::ElementFactory::make("identity").build().unwrap();
1836 let (sender, receiver) = channel();
1837
1838 identity.call_async(move |_| {
1839 sender.send(()).unwrap();
1840 });
1841
1842 assert_eq!(receiver.recv(), Ok(()));
1843 }
1844
1845 #[test]
1846 fn test_element_error() {
1847 crate::init().unwrap();
1848
1849 let identity = crate::ElementFactory::make("identity").build().unwrap();
1850
1851 crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1852 crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1853 crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1854
1855 let x = 123i32;
1858 crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1859 let x = 123i32;
1860 crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1861 let x = 123i32;
1862 crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1863 }
1864}