1use std::{ffi::CStr, mem, num::NonZeroU64, ops::ControlFlow};
4#[cfg(not(feature = "v1_28"))]
5use std::{future::Future, pin::Pin};
6
7use glib::translate::*;
8use itertools::Itertools;
9
10use crate::{
11 ClockTime, Element, ElementFlags, Event, Format, GenericFormattedValue, Pad, PadTemplate,
12 Plugin, QueryRef, Rank, State, ffi,
13 format::{
14 CompatibleFormattedValue, FormattedValue, SpecificFormattedValueFullRange,
15 SpecificFormattedValueIntrinsic,
16 },
17 prelude::*,
18};
19
20impl Element {
21 #[doc(alias = "gst_element_link_many")]
22 pub fn link_many<E: AsRef<Element> + Clone>(
23 elements: impl IntoIterator<Item = E>,
24 ) -> Result<(), glib::BoolError> {
25 skip_assert_initialized!();
26 for (src, dest) in elements.into_iter().tuple_windows() {
27 unsafe {
28 glib::result_from_gboolean!(
29 ffi::gst_element_link(
30 src.as_ref().to_glib_none().0,
31 dest.as_ref().to_glib_none().0,
32 ),
33 "Failed to link elements '{}' and '{}'",
34 src.as_ref().name(),
35 dest.as_ref().name(),
36 )?;
37 }
38 }
39
40 Ok(())
41 }
42
43 #[doc(alias = "gst_element_unlink_many")]
44 pub fn unlink_many<E: AsRef<Element> + Clone>(elements: impl IntoIterator<Item = E>) {
45 skip_assert_initialized!();
46 for (src, dest) in elements.into_iter().tuple_windows() {
47 unsafe {
48 ffi::gst_element_unlink(
49 src.as_ref().to_glib_none().0,
50 dest.as_ref().to_glib_none().0,
51 );
52 }
53 }
54 }
55
56 #[doc(alias = "gst_element_register")]
72 pub fn register(
73 plugin: Option<&Plugin>,
74 name: &str,
75 rank: Rank,
76 type_: glib::types::Type,
77 ) -> Result<(), glib::error::BoolError> {
78 skip_assert_initialized!();
79 unsafe {
80 glib::result_from_gboolean!(
81 ffi::gst_element_register(
82 plugin.to_glib_none().0,
83 name.to_glib_none().0,
84 rank.into_glib() as u32,
85 type_.into_glib()
86 ),
87 "Failed to register element factory"
88 )
89 }
90 }
91}
92
93#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
94pub enum ElementMessageType {
95 Error,
96 Warning,
97 Info,
98}
99
100#[derive(Debug, PartialEq, Eq)]
101pub struct NotifyWatchId(NonZeroU64);
102
103impl IntoGlib for NotifyWatchId {
104 type GlibType = libc::c_ulong;
105
106 #[inline]
107 fn into_glib(self) -> libc::c_ulong {
108 self.0.get() as libc::c_ulong
109 }
110}
111
112impl FromGlib<libc::c_ulong> for NotifyWatchId {
113 #[inline]
114 unsafe fn from_glib(val: libc::c_ulong) -> NotifyWatchId {
115 unsafe {
116 skip_assert_initialized!();
117 debug_assert_ne!(val, 0);
118 NotifyWatchId(NonZeroU64::new_unchecked(val as _))
119 }
120 }
121}
122
123pub trait ElementExtManual: IsA<Element> + 'static {
124 #[doc(alias = "get_element_class")]
125 #[inline]
126 fn element_class(&self) -> &glib::Class<Element> {
127 unsafe { self.unsafe_cast_ref::<Element>().class() }
128 }
129
130 #[doc(alias = "get_current_state")]
131 fn current_state(&self) -> State {
132 self.state(Some(ClockTime::ZERO)).1
133 }
134
135 #[doc(alias = "get_pending_state")]
136 fn pending_state(&self) -> State {
137 self.state(Some(ClockTime::ZERO)).2
138 }
139
140 #[doc(alias = "gst_element_query")]
156 fn query(&self, query: &mut QueryRef) -> bool {
157 unsafe {
158 from_glib(ffi::gst_element_query(
159 self.as_ref().to_glib_none().0,
160 query.as_mut_ptr(),
161 ))
162 }
163 }
164
165 #[doc(alias = "gst_element_send_event")]
181 fn send_event(&self, event: impl Into<Event>) -> bool {
182 unsafe {
183 from_glib(ffi::gst_element_send_event(
184 self.as_ref().to_glib_none().0,
185 event.into().into_glib_ptr(),
186 ))
187 }
188 }
189
190 #[doc(alias = "get_metadata")]
198 #[doc(alias = "gst_element_class_get_metadata")]
199 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
200 self.element_class().metadata(key)
201 }
202
203 #[doc(alias = "get_pad_template")]
213 #[doc(alias = "gst_element_class_get_pad_template")]
214 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
215 self.element_class().pad_template(name)
216 }
217
218 #[doc(alias = "get_pad_template_list")]
226 #[doc(alias = "gst_element_class_get_pad_template_list")]
227 fn pad_template_list(&self) -> glib::List<PadTemplate> {
228 self.element_class().pad_template_list()
229 }
230
231 #[allow(clippy::too_many_arguments)]
258 #[doc(alias = "gst_element_message_full")]
259 fn message_full<T: crate::MessageErrorDomain>(
260 &self,
261 type_: ElementMessageType,
262 code: T,
263 message: Option<&str>,
264 debug: Option<&str>,
265 file: &str,
266 function: &str,
267 line: u32,
268 ) {
269 unsafe {
270 let type_ = match type_ {
271 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
272 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
273 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
274 };
275
276 ffi::gst_element_message_full(
277 self.as_ref().to_glib_none().0,
278 type_,
279 T::domain().into_glib(),
280 code.code(),
281 message.to_glib_full(),
282 debug.to_glib_full(),
283 file.to_glib_none().0,
284 function.to_glib_none().0,
285 line as i32,
286 );
287 }
288 }
289
290 fn set_element_flags(&self, flags: ElementFlags) {
291 unsafe {
292 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
293 let _guard = self.as_ref().object_lock();
294 (*ptr).flags |= flags.into_glib();
295 }
296 }
297
298 fn unset_element_flags(&self, flags: ElementFlags) {
299 unsafe {
300 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
301 let _guard = self.as_ref().object_lock();
302 (*ptr).flags &= !flags.into_glib();
303 }
304 }
305
306 #[doc(alias = "get_element_flags")]
307 fn element_flags(&self) -> ElementFlags {
308 unsafe {
309 let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
310 let _guard = self.as_ref().object_lock();
311 from_glib((*ptr).flags)
312 }
313 }
314
315 #[allow(clippy::too_many_arguments)]
342 #[doc(alias = "gst_element_message_full_with_details")]
343 fn message_full_with_details<T: crate::MessageErrorDomain>(
344 &self,
345 type_: ElementMessageType,
346 code: T,
347 message: Option<&str>,
348 debug: Option<&str>,
349 file: &str,
350 function: &str,
351 line: u32,
352 structure: crate::Structure,
353 ) {
354 unsafe {
355 let type_ = match type_ {
356 ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
357 ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
358 ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
359 };
360
361 ffi::gst_element_message_full_with_details(
362 self.as_ref().to_glib_none().0,
363 type_,
364 T::domain().into_glib(),
365 code.code(),
366 message.to_glib_full(),
367 debug.to_glib_full(),
368 file.to_glib_none().0,
369 function.to_glib_none().0,
370 line as i32,
371 structure.into_glib_ptr(),
372 );
373 }
374 }
375
376 fn post_error_message(&self, msg: crate::ErrorMessage) {
377 let crate::ErrorMessage {
378 error_domain,
379 error_code,
380 ref message,
381 ref debug,
382 filename,
383 function,
384 line,
385 } = msg;
386
387 unsafe {
388 ffi::gst_element_message_full(
389 self.as_ref().to_glib_none().0,
390 ffi::GST_MESSAGE_ERROR,
391 error_domain.into_glib(),
392 error_code,
393 message.to_glib_full(),
394 debug.to_glib_full(),
395 filename.to_glib_none().0,
396 function.to_glib_none().0,
397 line as i32,
398 );
399 }
400 }
401
402 #[doc(alias = "gst_element_iterate_pads")]
415 fn iterate_pads(&self) -> crate::Iterator<Pad> {
416 unsafe {
417 from_glib_full(ffi::gst_element_iterate_pads(
418 self.as_ref().to_glib_none().0,
419 ))
420 }
421 }
422
423 #[doc(alias = "gst_element_iterate_sink_pads")]
434 fn iterate_sink_pads(&self) -> crate::Iterator<Pad> {
435 unsafe {
436 from_glib_full(ffi::gst_element_iterate_sink_pads(
437 self.as_ref().to_glib_none().0,
438 ))
439 }
440 }
441
442 #[doc(alias = "gst_element_iterate_src_pads")]
453 fn iterate_src_pads(&self) -> crate::Iterator<Pad> {
454 unsafe {
455 from_glib_full(ffi::gst_element_iterate_src_pads(
456 self.as_ref().to_glib_none().0,
457 ))
458 }
459 }
460
461 #[doc(alias = "get_pads")]
462 #[doc(alias = "gst_element_foreach_pad")]
463 fn pads(&self) -> Vec<Pad> {
464 unsafe {
465 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
466 let _guard = self.as_ref().object_lock();
467 FromGlibPtrContainer::from_glib_none(elt.pads)
468 }
469 }
470
471 #[doc(alias = "get_sink_pads")]
472 #[doc(alias = "gst_element_foreach_sink_pad")]
473 fn sink_pads(&self) -> Vec<Pad> {
474 unsafe {
475 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
476 let _guard = self.as_ref().object_lock();
477 FromGlibPtrContainer::from_glib_none(elt.sinkpads)
478 }
479 }
480
481 #[doc(alias = "get_src_pads")]
482 #[doc(alias = "gst_element_foreach_src_pad")]
483 fn src_pads(&self) -> Vec<Pad> {
484 unsafe {
485 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
486 let _guard = self.as_ref().object_lock();
487 FromGlibPtrContainer::from_glib_none(elt.srcpads)
488 }
489 }
490
491 #[doc(alias = "gst_element_foreach_pad")]
505 fn foreach_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
506 unsafe extern "C" fn trampoline<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(
507 element: *mut ffi::GstElement,
508 pad: *mut ffi::GstPad,
509 user_data: glib::ffi::gpointer,
510 ) -> glib::ffi::gboolean {
511 unsafe {
512 let element = from_glib_borrow(element);
513 let pad = from_glib_borrow(pad);
514 let callback = user_data as *mut F;
515 (*callback)(&element, &pad).is_continue().into_glib()
516 }
517 }
518
519 unsafe {
520 let mut func = func;
521 let func_ptr: &mut F = &mut func;
522
523 let _ = ffi::gst_element_foreach_pad(
524 self.as_ptr() as *mut _,
525 Some(trampoline::<F>),
526 func_ptr as *mut _ as *mut _,
527 );
528 }
529 }
530
531 #[doc(alias = "gst_element_foreach_sink_pad")]
545 fn foreach_sink_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
546 unsafe extern "C" fn trampoline<P: FnMut(&Element, &Pad) -> ControlFlow<()>>(
547 element: *mut ffi::GstElement,
548 pad: *mut ffi::GstPad,
549 user_data: glib::ffi::gpointer,
550 ) -> glib::ffi::gboolean {
551 unsafe {
552 let element = from_glib_borrow(element);
553 let pad = from_glib_borrow(pad);
554 let callback = user_data as *mut P;
555 (*callback)(&element, &pad).is_continue().into_glib()
556 }
557 }
558
559 unsafe {
560 let mut func = func;
561 let func_ptr: &mut F = &mut func;
562
563 let _ = ffi::gst_element_foreach_sink_pad(
564 self.as_ptr() as *mut _,
565 Some(trampoline::<F>),
566 func_ptr as *mut _ as *mut _,
567 );
568 }
569 }
570
571 #[doc(alias = "gst_element_foreach_src_pad")]
585 fn foreach_src_pad<F: FnMut(&Element, &Pad) -> ControlFlow<()>>(&self, func: F) {
586 unsafe extern "C" fn trampoline<P: FnMut(&Element, &Pad) -> ControlFlow<()>>(
587 element: *mut ffi::GstElement,
588 pad: *mut ffi::GstPad,
589 user_data: glib::ffi::gpointer,
590 ) -> glib::ffi::gboolean {
591 unsafe {
592 let element = from_glib_borrow(element);
593 let pad = from_glib_borrow(pad);
594 let callback = user_data as *mut P;
595 (*callback)(&element, &pad).is_continue().into_glib()
596 }
597 }
598
599 unsafe {
600 let mut func = func;
601 let func_ptr: &mut F = &mut func;
602
603 let _ = ffi::gst_element_foreach_src_pad(
604 self.as_ptr() as *mut _,
605 Some(trampoline::<F>),
606 func_ptr as *mut _ as *mut _,
607 );
608 }
609 }
610
611 fn num_pads(&self) -> u16 {
612 unsafe {
613 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
614 let _guard = self.as_ref().object_lock();
615 elt.numpads
616 }
617 }
618
619 fn num_sink_pads(&self) -> u16 {
620 unsafe {
621 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
622 let _guard = self.as_ref().object_lock();
623 elt.numsinkpads
624 }
625 }
626
627 fn num_src_pads(&self) -> u16 {
628 unsafe {
629 let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
630 let _guard = self.as_ref().object_lock();
631 elt.numsrcpads
632 }
633 }
634
635 #[doc(alias = "gst_element_add_property_deep_notify_watch")]
646 fn add_property_deep_notify_watch(
647 &self,
648 property_name: Option<&str>,
649 include_value: bool,
650 ) -> NotifyWatchId {
651 let property_name = property_name.to_glib_none();
652 unsafe {
653 from_glib(ffi::gst_element_add_property_deep_notify_watch(
654 self.as_ref().to_glib_none().0,
655 property_name.0,
656 include_value.into_glib(),
657 ))
658 }
659 }
660
661 #[doc(alias = "gst_element_add_property_notify_watch")]
672 fn add_property_notify_watch(
673 &self,
674 property_name: Option<&str>,
675 include_value: bool,
676 ) -> NotifyWatchId {
677 let property_name = property_name.to_glib_none();
678 unsafe {
679 from_glib(ffi::gst_element_add_property_notify_watch(
680 self.as_ref().to_glib_none().0,
681 property_name.0,
682 include_value.into_glib(),
683 ))
684 }
685 }
686
687 #[doc(alias = "gst_element_remove_property_notify_watch")]
690 fn remove_property_notify_watch(&self, watch_id: NotifyWatchId) {
691 unsafe {
692 ffi::gst_element_remove_property_notify_watch(
693 self.as_ref().to_glib_none().0,
694 watch_id.into_glib(),
695 );
696 }
697 }
698
699 #[doc(alias = "gst_element_query_convert")]
714 fn query_convert<U: SpecificFormattedValueFullRange>(
715 &self,
716 src_val: impl FormattedValue,
717 ) -> Option<U> {
718 unsafe {
719 let mut dest_val = mem::MaybeUninit::uninit();
720 let ret = from_glib(ffi::gst_element_query_convert(
721 self.as_ref().to_glib_none().0,
722 src_val.format().into_glib(),
723 src_val.into_raw_value(),
724 U::default_format().into_glib(),
725 dest_val.as_mut_ptr(),
726 ));
727 if ret {
728 Some(U::from_raw(U::default_format(), dest_val.assume_init()))
729 } else {
730 None
731 }
732 }
733 }
734
735 #[doc(alias = "gst_element_query_convert")]
736 fn query_convert_generic(
737 &self,
738 src_val: impl FormattedValue,
739 dest_format: Format,
740 ) -> Option<GenericFormattedValue> {
741 unsafe {
742 let mut dest_val = mem::MaybeUninit::uninit();
743 let ret = from_glib(ffi::gst_element_query_convert(
744 self.as_ref().to_glib_none().0,
745 src_val.format().into_glib(),
746 src_val.into_raw_value(),
747 dest_format.into_glib(),
748 dest_val.as_mut_ptr(),
749 ));
750 if ret {
751 Some(GenericFormattedValue::new(
752 dest_format,
753 dest_val.assume_init(),
754 ))
755 } else {
756 None
757 }
758 }
759 }
760
761 #[doc(alias = "gst_element_query_duration")]
779 fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
780 unsafe {
781 let mut duration = mem::MaybeUninit::uninit();
782 let ret = from_glib(ffi::gst_element_query_duration(
783 self.as_ref().to_glib_none().0,
784 T::default_format().into_glib(),
785 duration.as_mut_ptr(),
786 ));
787 if ret {
788 try_from_glib(duration.assume_init()).ok()
789 } else {
790 None
791 }
792 }
793 }
794
795 #[doc(alias = "gst_element_query_duration")]
796 fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
797 unsafe {
798 let mut duration = mem::MaybeUninit::uninit();
799 let ret = from_glib(ffi::gst_element_query_duration(
800 self.as_ref().to_glib_none().0,
801 format.into_glib(),
802 duration.as_mut_ptr(),
803 ));
804 if ret {
805 Some(GenericFormattedValue::new(format, duration.assume_init()))
806 } else {
807 None
808 }
809 }
810 }
811
812 #[doc(alias = "gst_element_query_position")]
832 fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
833 unsafe {
834 let mut cur = mem::MaybeUninit::uninit();
835 let ret = from_glib(ffi::gst_element_query_position(
836 self.as_ref().to_glib_none().0,
837 T::default_format().into_glib(),
838 cur.as_mut_ptr(),
839 ));
840 if ret {
841 try_from_glib(cur.assume_init()).ok()
842 } else {
843 None
844 }
845 }
846 }
847
848 #[doc(alias = "gst_element_query_position")]
849 fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
850 unsafe {
851 let mut cur = mem::MaybeUninit::uninit();
852 let ret = from_glib(ffi::gst_element_query_position(
853 self.as_ref().to_glib_none().0,
854 format.into_glib(),
855 cur.as_mut_ptr(),
856 ));
857 if ret {
858 Some(GenericFormattedValue::new(format, cur.assume_init()))
859 } else {
860 None
861 }
862 }
863 }
864
865 #[doc(alias = "gst_element_seek")]
890 fn seek<V: FormattedValue>(
891 &self,
892 rate: f64,
893 flags: crate::SeekFlags,
894 start_type: crate::SeekType,
895 start: V,
896 stop_type: crate::SeekType,
897 stop: impl CompatibleFormattedValue<V>,
898 ) -> Result<(), glib::error::BoolError> {
899 let stop = stop.try_into_checked(start).unwrap();
900
901 unsafe {
902 glib::result_from_gboolean!(
903 ffi::gst_element_seek(
904 self.as_ref().to_glib_none().0,
905 rate,
906 start.format().into_glib(),
907 flags.into_glib(),
908 start_type.into_glib(),
909 start.into_raw_value(),
910 stop_type.into_glib(),
911 stop.into_raw_value(),
912 ),
913 "Failed to seek",
914 )
915 }
916 }
917
918 #[doc(alias = "gst_element_seek_simple")]
948 fn seek_simple(
949 &self,
950 seek_flags: crate::SeekFlags,
951 seek_pos: impl FormattedValue,
952 ) -> Result<(), glib::error::BoolError> {
953 unsafe {
954 glib::result_from_gboolean!(
955 ffi::gst_element_seek_simple(
956 self.as_ref().to_glib_none().0,
957 seek_pos.format().into_glib(),
958 seek_flags.into_glib(),
959 seek_pos.into_raw_value(),
960 ),
961 "Failed to seek",
962 )
963 }
964 }
965
966 #[cfg(not(feature = "v1_28"))]
985 #[doc(alias = "gst_element_call_async")]
986 fn call_async<F>(&self, func: F)
987 where
988 F: FnOnce(&Self) + Send + 'static,
989 {
990 let user_data: Box<Option<F>> = Box::new(Some(func));
991
992 unsafe extern "C" fn trampoline<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
993 element: *mut ffi::GstElement,
994 user_data: glib::ffi::gpointer,
995 ) {
996 unsafe {
997 let user_data: &mut Option<F> = &mut *(user_data as *mut _);
998 let callback = user_data.take().unwrap();
999
1000 callback(Element::from_glib_borrow(element).unsafe_cast_ref());
1001 }
1002 }
1003
1004 unsafe extern "C" fn free_user_data<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
1005 user_data: glib::ffi::gpointer,
1006 ) {
1007 unsafe {
1008 let _: Box<Option<F>> = Box::from_raw(user_data as *mut _);
1009 }
1010 }
1011
1012 unsafe {
1013 ffi::gst_element_call_async(
1014 self.as_ref().to_glib_none().0,
1015 Some(trampoline::<Self, F>),
1016 Box::into_raw(user_data) as *mut _,
1017 Some(free_user_data::<Self, F>),
1018 );
1019 }
1020 }
1021
1022 #[cfg(not(feature = "v1_28"))]
1023 fn call_async_future<F, T>(&self, func: F) -> Pin<Box<dyn Future<Output = T> + Send + 'static>>
1024 where
1025 F: FnOnce(&Self) -> T + Send + 'static,
1026 T: Send + 'static,
1027 {
1028 use futures_channel::oneshot;
1029
1030 let (sender, receiver) = oneshot::channel();
1031
1032 self.call_async(move |element| {
1033 let _ = sender.send(func(element));
1034 });
1035
1036 Box::pin(async move { receiver.await.expect("sender dropped") })
1037 }
1038
1039 #[doc(alias = "get_current_running_time")]
1048 #[doc(alias = "gst_element_get_current_running_time")]
1049 fn current_running_time(&self) -> Option<crate::ClockTime> {
1050 let base_time = self.base_time();
1051 let clock_time = self.current_clock_time();
1052
1053 clock_time
1054 .zip(base_time)
1055 .and_then(|(ct, bt)| ct.checked_sub(bt))
1056 }
1057
1058 #[doc(alias = "get_current_clock_time")]
1066 #[doc(alias = "gst_element_get_current_clock_time")]
1067 fn current_clock_time(&self) -> Option<crate::ClockTime> {
1068 self.clock().as_ref().map(crate::Clock::time)
1069 }
1070
1071 #[doc(alias = "gst_element_get_request_pad")]
1087 #[doc(alias = "get_request_pad")]
1088 #[doc(alias = "gst_element_request_pad_simple")]
1089 fn request_pad_simple(&self, name: &str) -> Option<Pad> {
1090 unsafe {
1091 #[cfg(feature = "v1_20")]
1092 {
1093 from_glib_full(ffi::gst_element_request_pad_simple(
1094 self.as_ref().to_glib_none().0,
1095 name.to_glib_none().0,
1096 ))
1097 }
1098 #[cfg(not(feature = "v1_20"))]
1099 {
1100 from_glib_full(ffi::gst_element_get_request_pad(
1101 self.as_ref().to_glib_none().0,
1102 name.to_glib_none().0,
1103 ))
1104 }
1105 }
1106 }
1107
1108 #[doc(alias = "gst_element_link")]
1123 fn link(&self, dest: &impl IsA<Element>) -> Result<(), glib::error::BoolError> {
1124 unsafe {
1125 glib::result_from_gboolean!(
1126 ffi::gst_element_link(
1127 self.as_ref().to_glib_none().0,
1128 dest.as_ref().to_glib_none().0
1129 ),
1130 "Failed to link elements '{}' and '{}'",
1131 self.as_ref().name(),
1132 dest.as_ref().name(),
1133 )
1134 }
1135 }
1136
1137 #[doc(alias = "gst_element_link_filtered")]
1155 fn link_filtered(
1156 &self,
1157 dest: &impl IsA<Element>,
1158 filter: &crate::Caps,
1159 ) -> Result<(), glib::error::BoolError> {
1160 unsafe {
1161 glib::result_from_gboolean!(
1162 ffi::gst_element_link_filtered(
1163 self.as_ref().to_glib_none().0,
1164 dest.as_ref().to_glib_none().0,
1165 filter.to_glib_none().0
1166 ),
1167 "Failed to link elements '{}' and '{}' with filter '{:?}'",
1168 self.as_ref().name(),
1169 dest.as_ref().name(),
1170 filter,
1171 )
1172 }
1173 }
1174
1175 #[doc(alias = "gst_element_link_pads")]
1192 fn link_pads(
1193 &self,
1194 srcpadname: Option<&str>,
1195 dest: &impl IsA<Element>,
1196 destpadname: Option<&str>,
1197 ) -> Result<(), glib::error::BoolError> {
1198 unsafe {
1199 glib::result_from_gboolean!(
1200 ffi::gst_element_link_pads(
1201 self.as_ref().to_glib_none().0,
1202 srcpadname.to_glib_none().0,
1203 dest.as_ref().to_glib_none().0,
1204 destpadname.to_glib_none().0
1205 ),
1206 "Failed to link pads '{}' and '{}'",
1207 if let Some(srcpadname) = srcpadname {
1208 format!("{}:{}", self.as_ref().name(), srcpadname)
1209 } else {
1210 format!("{}:*", self.as_ref().name())
1211 },
1212 if let Some(destpadname) = destpadname {
1213 format!("{}:{}", dest.as_ref().name(), destpadname)
1214 } else {
1215 format!("{}:*", dest.as_ref().name())
1216 },
1217 )
1218 }
1219 }
1220
1221 #[doc(alias = "gst_element_link_pads_filtered")]
1241 fn link_pads_filtered(
1242 &self,
1243 srcpadname: Option<&str>,
1244 dest: &impl IsA<Element>,
1245 destpadname: Option<&str>,
1246 filter: &crate::Caps,
1247 ) -> Result<(), glib::error::BoolError> {
1248 unsafe {
1249 glib::result_from_gboolean!(
1250 ffi::gst_element_link_pads_filtered(
1251 self.as_ref().to_glib_none().0,
1252 srcpadname.to_glib_none().0,
1253 dest.as_ref().to_glib_none().0,
1254 destpadname.to_glib_none().0,
1255 filter.to_glib_none().0
1256 ),
1257 "Failed to link pads '{}' and '{}' with filter '{:?}'",
1258 if let Some(srcpadname) = srcpadname {
1259 format!("{}:{}", self.as_ref().name(), srcpadname)
1260 } else {
1261 format!("{}:*", self.as_ref().name())
1262 },
1263 if let Some(destpadname) = destpadname {
1264 format!("{}:{}", dest.as_ref().name(), destpadname)
1265 } else {
1266 format!("{}:*", dest.as_ref().name())
1267 },
1268 filter,
1269 )
1270 }
1271 }
1272
1273 #[doc(alias = "gst_element_link_pads_full")]
1298 fn link_pads_full(
1299 &self,
1300 srcpadname: Option<&str>,
1301 dest: &impl IsA<Element>,
1302 destpadname: Option<&str>,
1303 flags: crate::PadLinkCheck,
1304 ) -> Result<(), glib::error::BoolError> {
1305 unsafe {
1306 glib::result_from_gboolean!(
1307 ffi::gst_element_link_pads_full(
1308 self.as_ref().to_glib_none().0,
1309 srcpadname.to_glib_none().0,
1310 dest.as_ref().to_glib_none().0,
1311 destpadname.to_glib_none().0,
1312 flags.into_glib()
1313 ),
1314 "Failed to link pads '{}' and '{}' with flags '{:?}'",
1315 if let Some(srcpadname) = srcpadname {
1316 format!("{}:{}", self.as_ref().name(), srcpadname)
1317 } else {
1318 format!("{}:*", self.as_ref().name())
1319 },
1320 if let Some(destpadname) = destpadname {
1321 format!("{}:{}", dest.as_ref().name(), destpadname)
1322 } else {
1323 format!("{}:*", dest.as_ref().name())
1324 },
1325 flags,
1326 )
1327 }
1328 }
1329}
1330
1331impl<O: IsA<Element>> ElementExtManual for O {}
1332
1333pub unsafe trait ElementClassExt {
1334 #[doc(alias = "get_metadata")]
1342 #[doc(alias = "gst_element_class_get_metadata")]
1343 fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
1344 unsafe {
1345 let klass = self as *const _ as *const ffi::GstElementClass;
1346
1347 let ptr = ffi::gst_element_class_get_metadata(klass as *mut _, key.to_glib_none().0);
1348
1349 if ptr.is_null() {
1350 None
1351 } else {
1352 Some(CStr::from_ptr(ptr).to_str().unwrap())
1353 }
1354 }
1355 }
1356
1357 #[doc(alias = "get_pad_template")]
1370 #[doc(alias = "gst_element_class_get_pad_template")]
1371 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1372 unsafe {
1373 let klass = self as *const _ as *const ffi::GstElementClass;
1374
1375 from_glib_none(ffi::gst_element_class_get_pad_template(
1376 klass as *mut _,
1377 name.to_glib_none().0,
1378 ))
1379 }
1380 }
1381
1382 #[doc(alias = "get_pad_template_list")]
1393 #[doc(alias = "gst_element_class_get_pad_template_list")]
1394 fn pad_template_list(&self) -> glib::List<PadTemplate> {
1395 unsafe {
1396 let klass = self as *const _ as *const ffi::GstElementClass;
1397
1398 glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1399 klass as *mut _,
1400 ))
1401 }
1402 }
1403}
1404
1405unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1406
1407#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1411pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1412 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1413#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1416pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1417 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1418#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1421pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1422 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1423#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1427pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1428 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1429#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1433pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1434 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1435#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1437pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1438 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1439
1440#[doc(alias = "GST_ELEMENT_ERROR")]
1441#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1442#[macro_export]
1443macro_rules! element_error(
1444 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1445 use $crate::prelude::ElementExtManual;
1446 $obj.message_full(
1447 $crate::ElementMessageType::Error,
1448 $err,
1449 Some(&format!($($msg)*)),
1450 Some(&format!($($debug)*)),
1451 file!(),
1452 $crate::glib::function_name!(),
1453 line!(),
1454 );
1455 }};
1456 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1457 use $crate::prelude::ElementExtManual;
1458 $obj.message_full(
1459 $crate::ElementMessageType::Error,
1460 $err,
1461 Some(&format!($($msg)*)),
1462 None,
1463 file!(),
1464 $crate::glib::function_name!(),
1465 line!(),
1466 );
1467 }};
1468 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1469 use $crate::prelude::ElementExtManual;
1470 $obj.message_full(
1471 $crate::ElementMessageType::Error,
1472 $err,
1473 None,
1474 Some(&format!($($debug)*)),
1475 file!(),
1476 $crate::glib::function_name!(),
1477 line!(),
1478 );
1479 }};
1480
1481 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1482 use $crate::prelude::ElementExtManual;
1483 $obj.message_full_with_details(
1484 $crate::ElementMessageType::Error,
1485 $err,
1486 Some(&format!($($msg)*)),
1487 Some(&format!($($debug)*)),
1488 file!(),
1489 $crate::glib::function_name!(),
1490 line!(),
1491 $details,
1492 );
1493 }};
1494 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1495 use $crate::prelude::ElementExtManual;
1496 $obj.message_full_with_details(
1497 $crate::ElementMessageType::Error,
1498 $err,
1499 Some(&format!($($msg)*)),
1500 None,
1501 file!(),
1502 $crate::glib::function_name!(),
1503 line!(),
1504 $details,
1505 );
1506 }};
1507 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1508 use $crate::prelude::ElementExtManual;
1509 $obj.message_full_with_details(
1510 $crate::ElementMessageType::Error,
1511 $err,
1512 None,
1513 Some(&format!($($debug)*)),
1514 file!(),
1515 $crate::glib::function_name!(),
1516 line!(),
1517 $details,
1518 );
1519 }};
1520);
1521
1522#[doc(alias = "GST_ELEMENT_WARNING")]
1523#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1524#[macro_export]
1525macro_rules! element_warning(
1526 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1527 use $crate::prelude::ElementExtManual;
1528 $obj.message_full(
1529 $crate::ElementMessageType::Warning,
1530 $err,
1531 Some(&format!($($msg)*)),
1532 Some(&format!($($debug)*)),
1533 file!(),
1534 $crate::glib::function_name!(),
1535 line!(),
1536 );
1537 }};
1538 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1539 use $crate::prelude::ElementExtManual;
1540 $obj.message_full(
1541 $crate::ElementMessageType::Warning,
1542 $err,
1543 Some(&format!($($msg)*)),
1544 None,
1545 file!(),
1546 $crate::glib::function_name!(),
1547 line!(),
1548 );
1549 }};
1550 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1551 use $crate::prelude::ElementExtManual;
1552 $obj.message_full(
1553 $crate::ElementMessageType::Warning,
1554 $err,
1555 None,
1556 Some(&format!($($debug)*)),
1557 file!(),
1558 $crate::glib::function_name!(),
1559 line!(),
1560 );
1561 }};
1562
1563 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1564 use $crate::prelude::ElementExtManual;
1565 $obj.message_full_with_details(
1566 $crate::ElementMessageType::Warning,
1567 $err,
1568 Some(&format!($($msg)*)),
1569 Some(&format!($($debug)*)),
1570 file!(),
1571 $crate::glib::function_name!(),
1572 line!(),
1573 $details,
1574 );
1575 }};
1576 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1577 use $crate::prelude::ElementExtManual;
1578 $obj.message_full_with_details(
1579 $crate::ElementMessageType::Warning,
1580 $err,
1581 Some(&format!($($msg)*)),
1582 None,
1583 file!(),
1584 $crate::glib::function_name!(),
1585 line!(),
1586 $details,
1587 );
1588 }};
1589 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1590 use $crate::prelude::ElementExtManual;
1591 $obj.message_full_with_details(
1592 $crate::ElementMessageType::Warning,
1593 $err,
1594 None,
1595 Some(&format!($($debug)*)),
1596 file!(),
1597 $crate::glib::function_name!(),
1598 line!(),
1599 $details,
1600 );
1601 }};
1602);
1603
1604#[doc(alias = "GST_ELEMENT_INFO")]
1605#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1606#[macro_export]
1607macro_rules! element_info(
1608 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1609 use $crate::prelude::ElementExtManual;
1610 $obj.message_full(
1611 $crate::ElementMessageType::Info,
1612 $err,
1613 Some(&format!($($msg)*)),
1614 Some(&format!($($debug)*)),
1615 file!(),
1616 $crate::glib::function_name!(),
1617 line!(),
1618 );
1619 }};
1620 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1621 use $crate::prelude::ElementExtManual;
1622 $obj.message_full(
1623 $crate::ElementMessageType::Info,
1624 $err,
1625 Some(&format!($($msg)*)),
1626 None,
1627 file!(),
1628 $crate::glib::function_name!(),
1629 line!(),
1630 );
1631 }};
1632 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1633 use $crate::prelude::ElementExtManual;
1634 $obj.message_full(
1635 $crate::ElementMessageType::Info,
1636 $err,
1637 None,
1638 Some(&format!($($debug)*)),
1639 file!(),
1640 $crate::glib::function_name!(),
1641 line!(),
1642 );
1643 }};
1644
1645 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1646 use $crate::prelude::ElementExtManual;
1647 $obj.message_full_with_details(
1648 $crate::ElementMessageType::Info,
1649 $err,
1650 Some(&format!($($msg)*)),
1651 Some(&format!($($debug)*)),
1652 file!(),
1653 $crate::glib::function_name!(),
1654 line!(),
1655 $details,
1656 );
1657 }};
1658 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1659 use $crate::prelude::ElementExtManual;
1660 $obj.message_full_with_details(
1661 $crate::ElementMessageType::Info,
1662 $err,
1663 Some(&format!($($msg)*)),
1664 None,
1665 file!(),
1666 $crate::glib::function_name!(),
1667 line!(),
1668 $details,
1669 );
1670 }};
1671 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1672 use $crate::prelude::ElementExtManual;
1673 $obj.message_full_with_details(
1674 $crate::ElementMessageType::Info,
1675 $err,
1676 None,
1677 Some(&format!($($debug)*)),
1678 file!(),
1679 $crate::glib::function_name!(),
1680 line!(),
1681 $details,
1682 );
1683 }};
1684);
1685
1686#[doc(alias = "GST_ELEMENT_ERROR")]
1687#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1688#[macro_export]
1689macro_rules! element_imp_error(
1690 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1691 let obj = $imp.obj();
1692 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1693 }};
1694 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1695 let obj = $imp.obj();
1696 $crate::element_error!(obj, $err, ($($msg)*));
1697 }};
1698 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1699 let obj = $imp.obj();
1700 $crate::element_error!(obj, $err, [$($debug)*]);
1701 }};
1702
1703 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1704 let obj = $imp.obj();
1705 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1706 }};
1707 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1708 let obj = $imp.obj();
1709 $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1710 }};
1711 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1712 let obj = $imp.obj();
1713 $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1714 }};
1715);
1716
1717#[doc(alias = "GST_ELEMENT_WARNING")]
1718#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1719#[macro_export]
1720macro_rules! element_imp_warning(
1721 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1722 let obj = $imp.obj();
1723 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1724 }};
1725 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1726 let obj = $imp.obj();
1727 $crate::element_warning!(obj, $err, ($($msg)*));
1728 }};
1729 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1730 let obj = $imp.obj();
1731 $crate::element_warning!(obj, $err, [$($debug)*]);
1732 }};
1733
1734 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1735 let obj = $imp.obj();
1736 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1737 }};
1738 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1739 let obj = $imp.obj();
1740 $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1741 }};
1742 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1743 let obj = $imp.obj();
1744 $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1745 }};
1746);
1747
1748#[doc(alias = "GST_ELEMENT_INFO")]
1749#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1750#[macro_export]
1751macro_rules! element_imp_info(
1752 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1753 let obj = $imp.obj();
1754 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1755 }};
1756 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1757 let obj = $imp.obj();
1758 $crate::element_info!(obj, $err, ($($msg)*));
1759 }};
1760 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1761 let obj = $imp.obj();
1762 $crate::element_info!(obj, $err, [$($debug)*]);
1763 }};
1764
1765 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1766 let obj = $imp.obj();
1767 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1768 }};
1769 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1770 let obj = $imp.obj();
1771 $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1772 }};
1773 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1774 let obj = $imp.obj();
1775 $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1776 }};
1777);
1778
1779#[cfg(test)]
1780mod tests {
1781 use std::sync::mpsc::channel;
1782
1783 use glib::GString;
1784
1785 use super::*;
1786
1787 #[test]
1788 fn test_get_pads() {
1789 crate::init().unwrap();
1790
1791 let identity = crate::ElementFactory::make("identity").build().unwrap();
1792
1793 let mut pad_names = identity
1794 .pads()
1795 .iter()
1796 .map(|p| p.name())
1797 .collect::<Vec<GString>>();
1798 pad_names.sort();
1799 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1800
1801 let mut pad_names = identity
1802 .sink_pads()
1803 .iter()
1804 .map(|p| p.name())
1805 .collect::<Vec<GString>>();
1806 pad_names.sort();
1807 assert_eq!(pad_names, vec![String::from("sink")]);
1808
1809 let mut pad_names = identity
1810 .src_pads()
1811 .iter()
1812 .map(|p| p.name())
1813 .collect::<Vec<GString>>();
1814 pad_names.sort();
1815 assert_eq!(pad_names, vec![String::from("src")]);
1816 }
1817
1818 #[test]
1819 fn test_foreach_pad() {
1820 crate::init().unwrap();
1821
1822 let identity = crate::ElementFactory::make("identity").build().unwrap();
1823
1824 let mut pad_names = Vec::new();
1825 identity.foreach_pad(|_element, pad| {
1826 pad_names.push(pad.name());
1827
1828 ControlFlow::Continue(())
1829 });
1830 pad_names.sort();
1831 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1832
1833 pad_names.clear();
1834 identity.foreach_sink_pad(|_element, pad| {
1835 pad_names.push(pad.name());
1836
1837 ControlFlow::Continue(())
1838 });
1839 assert_eq!(pad_names, vec![String::from("sink")]);
1840
1841 pad_names.clear();
1842 identity.foreach_src_pad(|_element, pad| {
1843 pad_names.push(pad.name());
1844
1845 ControlFlow::Continue(())
1846 });
1847 assert_eq!(pad_names, vec![String::from("src")]);
1848 }
1849
1850 #[test]
1851 fn test_call_async() {
1852 crate::init().unwrap();
1853
1854 let identity = crate::ElementFactory::make("identity").build().unwrap();
1855 let (sender, receiver) = channel();
1856
1857 identity.call_async(move |_| {
1858 sender.send(()).unwrap();
1859 });
1860
1861 assert_eq!(receiver.recv(), Ok(()));
1862 }
1863
1864 #[test]
1865 fn test_element_error() {
1866 crate::init().unwrap();
1867
1868 let identity = crate::ElementFactory::make("identity").build().unwrap();
1869
1870 crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1871 crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1872 crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1873
1874 let x = 123i32;
1877 crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1878 let x = 123i32;
1879 crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1880 let x = 123i32;
1881 crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1882 }
1883}