1use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, 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(
22 elements: impl IntoIterator<Item = impl AsRef<Element> + Clone>,
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(elements: impl IntoIterator<Item = impl AsRef<Element> + Clone>) {
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
120mod sealed {
121 pub trait Sealed {}
122 impl<T: super::IsA<super::Element>> Sealed for T {}
123}
124
125pub trait ElementExtManual: sealed::Sealed + IsA<Element> + 'static {
126 #[doc(alias = "get_element_class")]
127 #[inline]
128 fn element_class(&self) -> &glib::Class<Element> {
129 unsafe { self.unsafe_cast_ref::<Element>().class() }
130 }
131
132 #[doc(alias = "get_current_state")]
133 fn current_state(&self) -> State {
134 self.state(Some(ClockTime::ZERO)).1
135 }
136
137 #[doc(alias = "get_pending_state")]
138 fn pending_state(&self) -> State {
139 self.state(Some(ClockTime::ZERO)).2
140 }
141
142 #[doc(alias = "gst_element_query")]
158 fn query(&self, query: &mut QueryRef) -> bool {
159 unsafe {
160 from_glib(ffi::gst_element_query(
161 self.as_ref().to_glib_none().0,
162 query.as_mut_ptr(),
163 ))
164 }
165 }
166
167 #[doc(alias = "gst_element_send_event")]
183 fn send_event(&self, event: impl Into<Event>) -> bool {
184 unsafe {
185 from_glib(ffi::gst_element_send_event(
186 self.as_ref().to_glib_none().0,
187 event.into().into_glib_ptr(),
188 ))
189 }
190 }
191
192 #[doc(alias = "get_metadata")]
200 #[doc(alias = "gst_element_class_get_metadata")]
201 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
202 self.element_class().metadata(key)
203 }
204
205 #[doc(alias = "get_pad_template")]
215 #[doc(alias = "gst_element_class_get_pad_template")]
216 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
217 self.element_class().pad_template(name)
218 }
219
220 #[doc(alias = "get_pad_template_list")]
228 #[doc(alias = "gst_element_class_get_pad_template_list")]
229 fn pad_template_list(&self) -> glib::List<PadTemplate> {
230 self.element_class().pad_template_list()
231 }
232
233 #[allow(clippy::too_many_arguments)]
260 #[doc(alias = "gst_element_message_full")]
261 fn message_full<T: crate::MessageErrorDomain>(
262 &self,
263 type_: ElementMessageType,
264 code: T,
265 message: Option<&str>,
266 debug: Option<&str>,
267 file: &str,
268 function: &str,
269 line: u32,
270 ) {
271 unsafe {
272 let type_ = match type_ {
273 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
274 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
275 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
276 };
277
278 ffi::gst_element_message_full(
279 self.as_ref().to_glib_none().0,
280 type_,
281 T::domain().into_glib(),
282 code.code(),
283 message.to_glib_full(),
284 debug.to_glib_full(),
285 file.to_glib_none().0,
286 function.to_glib_none().0,
287 line as i32,
288 );
289 }
290 }
291
292 fn set_element_flags(&self, flags: ElementFlags) {
293 unsafe {
294 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
295 let _guard = self.as_ref().object_lock();
296 (*ptr).flags |= flags.into_glib();
297 }
298 }
299
300 fn unset_element_flags(&self, flags: ElementFlags) {
301 unsafe {
302 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
303 let _guard = self.as_ref().object_lock();
304 (*ptr).flags &= !flags.into_glib();
305 }
306 }
307
308 #[doc(alias = "get_element_flags")]
309 fn element_flags(&self) -> ElementFlags {
310 unsafe {
311 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
312 let _guard = self.as_ref().object_lock();
313 from_glib((*ptr).flags)
314 }
315 }
316
317 #[allow(clippy::too_many_arguments)]
344 #[doc(alias = "gst_element_message_full_with_details")]
345 fn message_full_with_details<T: crate::MessageErrorDomain>(
346 &self,
347 type_: ElementMessageType,
348 code: T,
349 message: Option<&str>,
350 debug: Option<&str>,
351 file: &str,
352 function: &str,
353 line: u32,
354 structure: crate::Structure,
355 ) {
356 unsafe {
357 let type_ = match type_ {
358 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
359 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
360 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
361 };
362
363 ffi::gst_element_message_full_with_details(
364 self.as_ref().to_glib_none().0,
365 type_,
366 T::domain().into_glib(),
367 code.code(),
368 message.to_glib_full(),
369 debug.to_glib_full(),
370 file.to_glib_none().0,
371 function.to_glib_none().0,
372 line as i32,
373 structure.into_glib_ptr(),
374 );
375 }
376 }
377
378 fn post_error_message(&self, msg: crate::ErrorMessage) {
379 let crate::ErrorMessage {
380 error_domain,
381 error_code,
382 ref message,
383 ref debug,
384 filename,
385 function,
386 line,
387 } = msg;
388
389 unsafe {
390 ffi::gst_element_message_full(
391 self.as_ref().to_glib_none().0,
392 ffi::GST_MESSAGE_ERROR,
393 error_domain.into_glib(),
394 error_code,
395 message.to_glib_full(),
396 debug.to_glib_full(),
397 filename.to_glib_none().0,
398 function.to_glib_none().0,
399 line as i32,
400 );
401 }
402 }
403
404 #[doc(alias = "gst_element_iterate_pads")]
417 fn iterate_pads(&self) -> crate::Iterator<Pad> {
418 unsafe {
419 from_glib_full(ffi::gst_element_iterate_pads(
420 self.as_ref().to_glib_none().0,
421 ))
422 }
423 }
424
425 #[doc(alias = "gst_element_iterate_sink_pads")]
436 fn iterate_sink_pads(&self) -> crate::Iterator<Pad> {
437 unsafe {
438 from_glib_full(ffi::gst_element_iterate_sink_pads(
439 self.as_ref().to_glib_none().0,
440 ))
441 }
442 }
443
444 #[doc(alias = "gst_element_iterate_src_pads")]
455 fn iterate_src_pads(&self) -> crate::Iterator<Pad> {
456 unsafe {
457 from_glib_full(ffi::gst_element_iterate_src_pads(
458 self.as_ref().to_glib_none().0,
459 ))
460 }
461 }
462
463 #[doc(alias = "get_pads")]
464 #[doc(alias = "gst_element_foreach_pad")]
465 fn pads(&self) -> Vec<Pad> {
466 unsafe {
467 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
468 let _guard = self.as_ref().object_lock();
469 FromGlibPtrContainer::from_glib_none(elt.pads)
470 }
471 }
472
473 #[doc(alias = "get_sink_pads")]
474 #[doc(alias = "gst_element_foreach_sink_pad")]
475 fn sink_pads(&self) -> Vec<Pad> {
476 unsafe {
477 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
478 let _guard = self.as_ref().object_lock();
479 FromGlibPtrContainer::from_glib_none(elt.sinkpads)
480 }
481 }
482
483 #[doc(alias = "get_src_pads")]
484 #[doc(alias = "gst_element_foreach_src_pad")]
485 fn src_pads(&self) -> Vec<Pad> {
486 unsafe {
487 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
488 let _guard = self.as_ref().object_lock();
489 FromGlibPtrContainer::from_glib_none(elt.srcpads)
490 }
491 }
492
493 fn num_pads(&self) -> u16 {
494 unsafe {
495 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
496 let _guard = self.as_ref().object_lock();
497 elt.numpads
498 }
499 }
500
501 fn num_sink_pads(&self) -> u16 {
502 unsafe {
503 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
504 let _guard = self.as_ref().object_lock();
505 elt.numsinkpads
506 }
507 }
508
509 fn num_src_pads(&self) -> u16 {
510 unsafe {
511 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
512 let _guard = self.as_ref().object_lock();
513 elt.numsrcpads
514 }
515 }
516
517 #[doc(alias = "gst_element_add_property_deep_notify_watch")]
528 fn add_property_deep_notify_watch(
529 &self,
530 property_name: Option<&str>,
531 include_value: bool,
532 ) -> NotifyWatchId {
533 let property_name = property_name.to_glib_none();
534 unsafe {
535 from_glib(ffi::gst_element_add_property_deep_notify_watch(
536 self.as_ref().to_glib_none().0,
537 property_name.0,
538 include_value.into_glib(),
539 ))
540 }
541 }
542
543 #[doc(alias = "gst_element_add_property_notify_watch")]
554 fn add_property_notify_watch(
555 &self,
556 property_name: Option<&str>,
557 include_value: bool,
558 ) -> NotifyWatchId {
559 let property_name = property_name.to_glib_none();
560 unsafe {
561 from_glib(ffi::gst_element_add_property_notify_watch(
562 self.as_ref().to_glib_none().0,
563 property_name.0,
564 include_value.into_glib(),
565 ))
566 }
567 }
568
569 #[doc(alias = "gst_element_remove_property_notify_watch")]
572 fn remove_property_notify_watch(&self, watch_id: NotifyWatchId) {
573 unsafe {
574 ffi::gst_element_remove_property_notify_watch(
575 self.as_ref().to_glib_none().0,
576 watch_id.into_glib(),
577 );
578 }
579 }
580
581 #[doc(alias = "gst_element_query_convert")]
596 fn query_convert<U: SpecificFormattedValueFullRange>(
597 &self,
598 src_val: impl FormattedValue,
599 ) -> Option<U> {
600 unsafe {
601 let mut dest_val = mem::MaybeUninit::uninit();
602 let ret = from_glib(ffi::gst_element_query_convert(
603 self.as_ref().to_glib_none().0,
604 src_val.format().into_glib(),
605 src_val.into_raw_value(),
606 U::default_format().into_glib(),
607 dest_val.as_mut_ptr(),
608 ));
609 if ret {
610 Some(U::from_raw(U::default_format(), dest_val.assume_init()))
611 } else {
612 None
613 }
614 }
615 }
616
617 #[doc(alias = "gst_element_query_convert")]
618 fn query_convert_generic(
619 &self,
620 src_val: impl FormattedValue,
621 dest_format: Format,
622 ) -> Option<GenericFormattedValue> {
623 unsafe {
624 let mut dest_val = mem::MaybeUninit::uninit();
625 let ret = from_glib(ffi::gst_element_query_convert(
626 self.as_ref().to_glib_none().0,
627 src_val.format().into_glib(),
628 src_val.into_raw_value(),
629 dest_format.into_glib(),
630 dest_val.as_mut_ptr(),
631 ));
632 if ret {
633 Some(GenericFormattedValue::new(
634 dest_format,
635 dest_val.assume_init(),
636 ))
637 } else {
638 None
639 }
640 }
641 }
642
643 #[doc(alias = "gst_element_query_duration")]
661 fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
662 unsafe {
663 let mut duration = mem::MaybeUninit::uninit();
664 let ret = from_glib(ffi::gst_element_query_duration(
665 self.as_ref().to_glib_none().0,
666 T::default_format().into_glib(),
667 duration.as_mut_ptr(),
668 ));
669 if ret {
670 try_from_glib(duration.assume_init()).ok()
671 } else {
672 None
673 }
674 }
675 }
676
677 #[doc(alias = "gst_element_query_duration")]
678 fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
679 unsafe {
680 let mut duration = mem::MaybeUninit::uninit();
681 let ret = from_glib(ffi::gst_element_query_duration(
682 self.as_ref().to_glib_none().0,
683 format.into_glib(),
684 duration.as_mut_ptr(),
685 ));
686 if ret {
687 Some(GenericFormattedValue::new(format, duration.assume_init()))
688 } else {
689 None
690 }
691 }
692 }
693
694 #[doc(alias = "gst_element_query_position")]
714 fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
715 unsafe {
716 let mut cur = mem::MaybeUninit::uninit();
717 let ret = from_glib(ffi::gst_element_query_position(
718 self.as_ref().to_glib_none().0,
719 T::default_format().into_glib(),
720 cur.as_mut_ptr(),
721 ));
722 if ret {
723 try_from_glib(cur.assume_init()).ok()
724 } else {
725 None
726 }
727 }
728 }
729
730 #[doc(alias = "gst_element_query_position")]
731 fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
732 unsafe {
733 let mut cur = mem::MaybeUninit::uninit();
734 let ret = from_glib(ffi::gst_element_query_position(
735 self.as_ref().to_glib_none().0,
736 format.into_glib(),
737 cur.as_mut_ptr(),
738 ));
739 if ret {
740 Some(GenericFormattedValue::new(format, cur.assume_init()))
741 } else {
742 None
743 }
744 }
745 }
746
747 #[doc(alias = "gst_element_seek")]
772 fn seek<V: FormattedValue>(
773 &self,
774 rate: f64,
775 flags: crate::SeekFlags,
776 start_type: crate::SeekType,
777 start: V,
778 stop_type: crate::SeekType,
779 stop: impl CompatibleFormattedValue<V>,
780 ) -> Result<(), glib::error::BoolError> {
781 let stop = stop.try_into_checked(start).unwrap();
782
783 unsafe {
784 glib::result_from_gboolean!(
785 ffi::gst_element_seek(
786 self.as_ref().to_glib_none().0,
787 rate,
788 start.format().into_glib(),
789 flags.into_glib(),
790 start_type.into_glib(),
791 start.into_raw_value(),
792 stop_type.into_glib(),
793 stop.into_raw_value(),
794 ),
795 "Failed to seek",
796 )
797 }
798 }
799
800 #[doc(alias = "gst_element_seek_simple")]
830 fn seek_simple(
831 &self,
832 seek_flags: crate::SeekFlags,
833 seek_pos: impl FormattedValue,
834 ) -> Result<(), glib::error::BoolError> {
835 unsafe {
836 glib::result_from_gboolean!(
837 ffi::gst_element_seek_simple(
838 self.as_ref().to_glib_none().0,
839 seek_pos.format().into_glib(),
840 seek_flags.into_glib(),
841 seek_pos.into_raw_value(),
842 ),
843 "Failed to seek",
844 )
845 }
846 }
847
848 #[doc(alias = "gst_element_call_async")]
863 fn call_async<F>(&self, func: F)
864 where
865 F: FnOnce(&Self) + Send + 'static,
866 {
867 let user_data: Box<Option<F>> = Box::new(Some(func));
868
869 unsafe extern "C" fn trampoline<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
870 element: *mut ffi::GstElement,
871 user_data: glib::ffi::gpointer,
872 ) {
873 let user_data: &mut Option<F> = &mut *(user_data as *mut _);
874 let callback = user_data.take().unwrap();
875
876 callback(Element::from_glib_borrow(element).unsafe_cast_ref());
877 }
878
879 unsafe extern "C" fn free_user_data<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
880 user_data: glib::ffi::gpointer,
881 ) {
882 let _: Box<Option<F>> = Box::from_raw(user_data as *mut _);
883 }
884
885 unsafe {
886 ffi::gst_element_call_async(
887 self.as_ref().to_glib_none().0,
888 Some(trampoline::<Self, F>),
889 Box::into_raw(user_data) as *mut _,
890 Some(free_user_data::<Self, F>),
891 );
892 }
893 }
894
895 fn call_async_future<F, T>(&self, func: F) -> Pin<Box<dyn Future<Output = T> + Send + 'static>>
896 where
897 F: FnOnce(&Self) -> T + Send + 'static,
898 T: Send + 'static,
899 {
900 use futures_channel::oneshot;
901
902 let (sender, receiver) = oneshot::channel();
903
904 self.call_async(move |element| {
905 let _ = sender.send(func(element));
906 });
907
908 Box::pin(async move { receiver.await.expect("sender dropped") })
909 }
910
911 #[doc(alias = "get_current_running_time")]
920 #[doc(alias = "gst_element_get_current_running_time")]
921 fn current_running_time(&self) -> Option<crate::ClockTime> {
922 let base_time = self.base_time();
923 let clock_time = self.current_clock_time();
924
925 clock_time
926 .zip(base_time)
927 .and_then(|(ct, bt)| ct.checked_sub(bt))
928 }
929
930 #[doc(alias = "get_current_clock_time")]
938 #[doc(alias = "gst_element_get_current_clock_time")]
939 fn current_clock_time(&self) -> Option<crate::ClockTime> {
940 if let Some(clock) = self.clock() {
941 clock.time()
942 } else {
943 crate::ClockTime::NONE
944 }
945 }
946
947 #[doc(alias = "gst_element_get_request_pad")]
963 #[doc(alias = "get_request_pad")]
964 #[doc(alias = "gst_element_request_pad_simple")]
965 fn request_pad_simple(&self, name: &str) -> Option<Pad> {
966 unsafe {
967 #[cfg(feature = "v1_20")]
968 {
969 from_glib_full(ffi::gst_element_request_pad_simple(
970 self.as_ref().to_glib_none().0,
971 name.to_glib_none().0,
972 ))
973 }
974 #[cfg(not(feature = "v1_20"))]
975 {
976 from_glib_full(ffi::gst_element_get_request_pad(
977 self.as_ref().to_glib_none().0,
978 name.to_glib_none().0,
979 ))
980 }
981 }
982 }
983
984 #[doc(alias = "gst_element_link")]
999 fn link(&self, dest: &impl IsA<Element>) -> Result<(), glib::error::BoolError> {
1000 unsafe {
1001 glib::result_from_gboolean!(
1002 ffi::gst_element_link(
1003 self.as_ref().to_glib_none().0,
1004 dest.as_ref().to_glib_none().0
1005 ),
1006 "Failed to link elements '{}' and '{}'",
1007 self.as_ref().name(),
1008 dest.as_ref().name(),
1009 )
1010 }
1011 }
1012
1013 #[doc(alias = "gst_element_link_filtered")]
1031 fn link_filtered(
1032 &self,
1033 dest: &impl IsA<Element>,
1034 filter: &crate::Caps,
1035 ) -> Result<(), glib::error::BoolError> {
1036 unsafe {
1037 glib::result_from_gboolean!(
1038 ffi::gst_element_link_filtered(
1039 self.as_ref().to_glib_none().0,
1040 dest.as_ref().to_glib_none().0,
1041 filter.to_glib_none().0
1042 ),
1043 "Failed to link elements '{}' and '{}' with filter '{:?}'",
1044 self.as_ref().name(),
1045 dest.as_ref().name(),
1046 filter,
1047 )
1048 }
1049 }
1050
1051 #[doc(alias = "gst_element_link_pads")]
1068 fn link_pads(
1069 &self,
1070 srcpadname: Option<&str>,
1071 dest: &impl IsA<Element>,
1072 destpadname: Option<&str>,
1073 ) -> Result<(), glib::error::BoolError> {
1074 unsafe {
1075 glib::result_from_gboolean!(
1076 ffi::gst_element_link_pads(
1077 self.as_ref().to_glib_none().0,
1078 srcpadname.to_glib_none().0,
1079 dest.as_ref().to_glib_none().0,
1080 destpadname.to_glib_none().0
1081 ),
1082 "Failed to link pads '{}' and '{}'",
1083 if let Some(srcpadname) = srcpadname {
1084 format!("{}:{}", self.as_ref().name(), srcpadname)
1085 } else {
1086 format!("{}:*", self.as_ref().name())
1087 },
1088 if let Some(destpadname) = destpadname {
1089 format!("{}:{}", dest.as_ref().name(), destpadname)
1090 } else {
1091 format!("{}:*", dest.as_ref().name())
1092 },
1093 )
1094 }
1095 }
1096
1097 #[doc(alias = "gst_element_link_pads_filtered")]
1117 fn link_pads_filtered(
1118 &self,
1119 srcpadname: Option<&str>,
1120 dest: &impl IsA<Element>,
1121 destpadname: Option<&str>,
1122 filter: &crate::Caps,
1123 ) -> Result<(), glib::error::BoolError> {
1124 unsafe {
1125 glib::result_from_gboolean!(
1126 ffi::gst_element_link_pads_filtered(
1127 self.as_ref().to_glib_none().0,
1128 srcpadname.to_glib_none().0,
1129 dest.as_ref().to_glib_none().0,
1130 destpadname.to_glib_none().0,
1131 filter.to_glib_none().0
1132 ),
1133 "Failed to link pads '{}' and '{}' with filter '{:?}'",
1134 if let Some(srcpadname) = srcpadname {
1135 format!("{}:{}", self.as_ref().name(), srcpadname)
1136 } else {
1137 format!("{}:*", self.as_ref().name())
1138 },
1139 if let Some(destpadname) = destpadname {
1140 format!("{}:{}", dest.as_ref().name(), destpadname)
1141 } else {
1142 format!("{}:*", dest.as_ref().name())
1143 },
1144 filter,
1145 )
1146 }
1147 }
1148
1149 #[doc(alias = "gst_element_link_pads_full")]
1174 fn link_pads_full(
1175 &self,
1176 srcpadname: Option<&str>,
1177 dest: &impl IsA<Element>,
1178 destpadname: Option<&str>,
1179 flags: crate::PadLinkCheck,
1180 ) -> Result<(), glib::error::BoolError> {
1181 unsafe {
1182 glib::result_from_gboolean!(
1183 ffi::gst_element_link_pads_full(
1184 self.as_ref().to_glib_none().0,
1185 srcpadname.to_glib_none().0,
1186 dest.as_ref().to_glib_none().0,
1187 destpadname.to_glib_none().0,
1188 flags.into_glib()
1189 ),
1190 "Failed to link pads '{}' and '{}' with flags '{:?}'",
1191 if let Some(srcpadname) = srcpadname {
1192 format!("{}:{}", self.as_ref().name(), srcpadname)
1193 } else {
1194 format!("{}:*", self.as_ref().name())
1195 },
1196 if let Some(destpadname) = destpadname {
1197 format!("{}:{}", dest.as_ref().name(), destpadname)
1198 } else {
1199 format!("{}:*", dest.as_ref().name())
1200 },
1201 flags,
1202 )
1203 }
1204 }
1205}
1206
1207impl<O: IsA<Element>> ElementExtManual for O {}
1208
1209pub unsafe trait ElementClassExt {
1210 #[doc(alias = "get_metadata")]
1218 #[doc(alias = "gst_element_class_get_metadata")]
1219 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
1220 unsafe {
1221 let klass = self as *const _ as *const ffi::GstElementClass;
1222
1223 let ptr = ffi::gst_element_class_get_metadata(klass as *mut _, key.to_glib_none().0);
1224
1225 if ptr.is_null() {
1226 None
1227 } else {
1228 Some(CStr::from_ptr(ptr).to_str().unwrap())
1229 }
1230 }
1231 }
1232
1233 #[doc(alias = "get_pad_template")]
1246 #[doc(alias = "gst_element_class_get_pad_template")]
1247 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1248 unsafe {
1249 let klass = self as *const _ as *const ffi::GstElementClass;
1250
1251 from_glib_none(ffi::gst_element_class_get_pad_template(
1252 klass as *mut _,
1253 name.to_glib_none().0,
1254 ))
1255 }
1256 }
1257
1258 #[doc(alias = "get_pad_template_list")]
1269 #[doc(alias = "gst_element_class_get_pad_template_list")]
1270 fn pad_template_list(&self) -> glib::List<PadTemplate> {
1271 unsafe {
1272 let klass = self as *const _ as *const ffi::GstElementClass;
1273
1274 glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1275 klass as *mut _,
1276 ))
1277 }
1278 }
1279}
1280
1281unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1282
1283#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1287pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1288 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1289#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1292pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1293 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1294#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1297pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1298 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1299#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1303pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1304 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1305#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1309pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1310 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1311#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1313pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1314 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1315
1316#[doc(alias = "GST_ELEMENT_ERROR")]
1317#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1318#[macro_export]
1319macro_rules! element_error(
1320 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1321 use $crate::prelude::ElementExtManual;
1322 $obj.message_full(
1323 $crate::ElementMessageType::Error,
1324 $err,
1325 Some(&format!($($msg)*)),
1326 Some(&format!($($debug)*)),
1327 file!(),
1328 $crate::glib::function_name!(),
1329 line!(),
1330 );
1331 }};
1332 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1333 use $crate::prelude::ElementExtManual;
1334 $obj.message_full(
1335 $crate::ElementMessageType::Error,
1336 $err,
1337 Some(&format!($($msg)*)),
1338 None,
1339 file!(),
1340 $crate::glib::function_name!(),
1341 line!(),
1342 );
1343 }};
1344 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1345 use $crate::prelude::ElementExtManual;
1346 $obj.message_full(
1347 $crate::ElementMessageType::Error,
1348 $err,
1349 None,
1350 Some(&format!($($debug)*)),
1351 file!(),
1352 $crate::glib::function_name!(),
1353 line!(),
1354 );
1355 }};
1356
1357 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1358 use $crate::prelude::ElementExtManual;
1359 $obj.message_full_with_details(
1360 $crate::ElementMessageType::Error,
1361 $err,
1362 Some(&format!($($msg)*)),
1363 Some(&format!($($debug)*)),
1364 file!(),
1365 $crate::glib::function_name!(),
1366 line!(),
1367 $details,
1368 );
1369 }};
1370 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1371 use $crate::prelude::ElementExtManual;
1372 $obj.message_full_with_details(
1373 $crate::ElementMessageType::Error,
1374 $err,
1375 Some(&format!($($msg)*)),
1376 None,
1377 file!(),
1378 $crate::glib::function_name!(),
1379 line!(),
1380 $details,
1381 );
1382 }};
1383 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1384 use $crate::prelude::ElementExtManual;
1385 $obj.message_full_with_details(
1386 $crate::ElementMessageType::Error,
1387 $err,
1388 None,
1389 Some(&format!($($debug)*)),
1390 file!(),
1391 $crate::glib::function_name!(),
1392 line!(),
1393 $details,
1394 );
1395 }};
1396);
1397
1398#[doc(alias = "GST_ELEMENT_WARNING")]
1399#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1400#[macro_export]
1401macro_rules! element_warning(
1402 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1403 use $crate::prelude::ElementExtManual;
1404 $obj.message_full(
1405 $crate::ElementMessageType::Warning,
1406 $err,
1407 Some(&format!($($msg)*)),
1408 Some(&format!($($debug)*)),
1409 file!(),
1410 $crate::glib::function_name!(),
1411 line!(),
1412 );
1413 }};
1414 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1415 use $crate::prelude::ElementExtManual;
1416 $obj.message_full(
1417 $crate::ElementMessageType::Warning,
1418 $err,
1419 Some(&format!($($msg)*)),
1420 None,
1421 file!(),
1422 $crate::glib::function_name!(),
1423 line!(),
1424 );
1425 }};
1426 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1427 use $crate::prelude::ElementExtManual;
1428 $obj.message_full(
1429 $crate::ElementMessageType::Warning,
1430 $err,
1431 None,
1432 Some(&format!($($debug)*)),
1433 file!(),
1434 $crate::glib::function_name!(),
1435 line!(),
1436 );
1437 }};
1438
1439 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1440 use $crate::prelude::ElementExtManual;
1441 $obj.message_full_with_details(
1442 $crate::ElementMessageType::Warning,
1443 $err,
1444 Some(&format!($($msg)*)),
1445 Some(&format!($($debug)*)),
1446 file!(),
1447 $crate::glib::function_name!(),
1448 line!(),
1449 $details,
1450 );
1451 }};
1452 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1453 use $crate::prelude::ElementExtManual;
1454 $obj.message_full_with_details(
1455 $crate::ElementMessageType::Warning,
1456 $err,
1457 Some(&format!($($msg)*)),
1458 None,
1459 file!(),
1460 $crate::glib::function_name!(),
1461 line!(),
1462 $details,
1463 );
1464 }};
1465 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1466 use $crate::prelude::ElementExtManual;
1467 $obj.message_full_with_details(
1468 $crate::ElementMessageType::Warning,
1469 $err,
1470 None,
1471 Some(&format!($($debug)*)),
1472 file!(),
1473 $crate::glib::function_name!(),
1474 line!(),
1475 $details,
1476 );
1477 }};
1478);
1479
1480#[doc(alias = "GST_ELEMENT_INFO")]
1481#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1482#[macro_export]
1483macro_rules! element_info(
1484 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1485 use $crate::prelude::ElementExtManual;
1486 $obj.message_full(
1487 $crate::ElementMessageType::Info,
1488 $err,
1489 Some(&format!($($msg)*)),
1490 Some(&format!($($debug)*)),
1491 file!(),
1492 $crate::glib::function_name!(),
1493 line!(),
1494 );
1495 }};
1496 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1497 use $crate::prelude::ElementExtManual;
1498 $obj.message_full(
1499 $crate::ElementMessageType::Info,
1500 $err,
1501 Some(&format!($($msg)*)),
1502 None,
1503 file!(),
1504 $crate::glib::function_name!(),
1505 line!(),
1506 );
1507 }};
1508 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1509 use $crate::prelude::ElementExtManual;
1510 $obj.message_full(
1511 $crate::ElementMessageType::Info,
1512 $err,
1513 None,
1514 Some(&format!($($debug)*)),
1515 file!(),
1516 $crate::glib::function_name!(),
1517 line!(),
1518 );
1519 }};
1520
1521 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1522 use $crate::prelude::ElementExtManual;
1523 $obj.message_full_with_details(
1524 $crate::ElementMessageType::Info,
1525 $err,
1526 Some(&format!($($msg)*)),
1527 Some(&format!($($debug)*)),
1528 file!(),
1529 $crate::glib::function_name!(),
1530 line!(),
1531 $details,
1532 );
1533 }};
1534 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1535 use $crate::prelude::ElementExtManual;
1536 $obj.message_full_with_details(
1537 $crate::ElementMessageType::Info,
1538 $err,
1539 Some(&format!($($msg)*)),
1540 None,
1541 file!(),
1542 $crate::glib::function_name!(),
1543 line!(),
1544 $details,
1545 );
1546 }};
1547 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1548 use $crate::prelude::ElementExtManual;
1549 $obj.message_full_with_details(
1550 $crate::ElementMessageType::Info,
1551 $err,
1552 None,
1553 Some(&format!($($debug)*)),
1554 file!(),
1555 $crate::glib::function_name!(),
1556 line!(),
1557 $details,
1558 );
1559 }};
1560);
1561
1562#[doc(alias = "GST_ELEMENT_ERROR")]
1563#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1564#[macro_export]
1565macro_rules! element_imp_error(
1566 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1567 let obj = $imp.obj();
1568 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1569 }};
1570 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1571 let obj = $imp.obj();
1572 $crate::element_error!(obj, $err, ($($msg)*));
1573 }};
1574 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1575 let obj = $imp.obj();
1576 $crate::element_error!(obj, $err, [$($debug)*]);
1577 }};
1578
1579 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1580 let obj = $imp.obj();
1581 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1582 }};
1583 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1584 let obj = $imp.obj();
1585 $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1586 }};
1587 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1588 let obj = $imp.obj();
1589 $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1590 }};
1591);
1592
1593#[doc(alias = "GST_ELEMENT_WARNING")]
1594#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1595#[macro_export]
1596macro_rules! element_imp_warning(
1597 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1598 let obj = $imp.obj();
1599 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1600 }};
1601 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1602 let obj = $imp.obj();
1603 $crate::element_warning!(obj, $err, ($($msg)*));
1604 }};
1605 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1606 let obj = $imp.obj();
1607 $crate::element_warning!(obj, $err, [$($debug)*]);
1608 }};
1609
1610 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1611 let obj = $imp.obj();
1612 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1613 }};
1614 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1615 let obj = $imp.obj();
1616 $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1617 }};
1618 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1619 let obj = $imp.obj();
1620 $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1621 }};
1622);
1623
1624#[doc(alias = "GST_ELEMENT_INFO")]
1625#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1626#[macro_export]
1627macro_rules! element_imp_info(
1628 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1629 let obj = $imp.obj();
1630 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1631 }};
1632 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1633 let obj = $imp.obj();
1634 $crate::element_info!(obj, $err, ($($msg)*));
1635 }};
1636 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1637 let obj = $imp.obj();
1638 $crate::element_info!(obj, $err, [$($debug)*]);
1639 }};
1640
1641 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1642 let obj = $imp.obj();
1643 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1644 }};
1645 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1646 let obj = $imp.obj();
1647 $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1648 }};
1649 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1650 let obj = $imp.obj();
1651 $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1652 }};
1653);
1654
1655#[cfg(test)]
1656mod tests {
1657 use std::sync::mpsc::channel;
1658
1659 use glib::GString;
1660
1661 use super::*;
1662
1663 #[test]
1664 fn test_get_pads() {
1665 crate::init().unwrap();
1666
1667 let identity = crate::ElementFactory::make("identity").build().unwrap();
1668
1669 let mut pad_names = identity
1670 .pads()
1671 .iter()
1672 .map(|p| p.name())
1673 .collect::<Vec<GString>>();
1674 pad_names.sort();
1675 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1676
1677 let mut pad_names = identity
1678 .sink_pads()
1679 .iter()
1680 .map(|p| p.name())
1681 .collect::<Vec<GString>>();
1682 pad_names.sort();
1683 assert_eq!(pad_names, vec![String::from("sink")]);
1684
1685 let mut pad_names = identity
1686 .src_pads()
1687 .iter()
1688 .map(|p| p.name())
1689 .collect::<Vec<GString>>();
1690 pad_names.sort();
1691 assert_eq!(pad_names, vec![String::from("src")]);
1692 }
1693
1694 #[test]
1695 fn test_foreach_pad() {
1696 crate::init().unwrap();
1697
1698 let identity = crate::ElementFactory::make("identity").build().unwrap();
1699
1700 let mut pad_names = Vec::new();
1701 identity.foreach_pad(|_element, pad| {
1702 pad_names.push(pad.name());
1703
1704 true
1705 });
1706 pad_names.sort();
1707 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1708 }
1709
1710 #[test]
1711 fn test_call_async() {
1712 crate::init().unwrap();
1713
1714 let identity = crate::ElementFactory::make("identity").build().unwrap();
1715 let (sender, receiver) = channel();
1716
1717 identity.call_async(move |_| {
1718 sender.send(()).unwrap();
1719 });
1720
1721 assert_eq!(receiver.recv(), Ok(()));
1722 }
1723
1724 #[test]
1725 fn test_element_error() {
1726 crate::init().unwrap();
1727
1728 let identity = crate::ElementFactory::make("identity").build().unwrap();
1729
1730 crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1731 crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1732 crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1733
1734 let x = 123i32;
1737 crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1738 let x = 123i32;
1739 crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1740 let x = 123i32;
1741 crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1742 }
1743}