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")]
1367 #[doc(alias = "gst_element_class_get_pad_template")]
1368 fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1369 unsafe {
1370 let klass = self as *const _ as *const ffi::GstElementClass;
1371
1372 from_glib_none(ffi::gst_element_class_get_pad_template(
1373 klass as *mut _,
1374 name.to_glib_none().0,
1375 ))
1376 }
1377 }
1378
1379 #[doc(alias = "get_pad_template_list")]
1386 #[doc(alias = "gst_element_class_get_pad_template_list")]
1387 fn pad_template_list(&self) -> glib::List<PadTemplate> {
1388 unsafe {
1389 let klass = self as *const _ as *const ffi::GstElementClass;
1390
1391 glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1392 klass as *mut _,
1393 ))
1394 }
1395 }
1396}
1397
1398unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1399
1400#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1402pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1403 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1404#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1407pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1408 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1409#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1412pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1413 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1414#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1418pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1419 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1420#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1424pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1425 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1426#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1428pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1429 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1430
1431#[doc(alias = "GST_ELEMENT_ERROR")]
1432#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1433#[macro_export]
1434macro_rules! element_error(
1435 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1436 use $crate::prelude::ElementExtManual;
1437 $obj.message_full(
1438 $crate::ElementMessageType::Error,
1439 $err,
1440 Some(&format!($($msg)*)),
1441 Some(&format!($($debug)*)),
1442 file!(),
1443 $crate::glib::function_name!(),
1444 line!(),
1445 );
1446 }};
1447 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1448 use $crate::prelude::ElementExtManual;
1449 $obj.message_full(
1450 $crate::ElementMessageType::Error,
1451 $err,
1452 Some(&format!($($msg)*)),
1453 None,
1454 file!(),
1455 $crate::glib::function_name!(),
1456 line!(),
1457 );
1458 }};
1459 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1460 use $crate::prelude::ElementExtManual;
1461 $obj.message_full(
1462 $crate::ElementMessageType::Error,
1463 $err,
1464 None,
1465 Some(&format!($($debug)*)),
1466 file!(),
1467 $crate::glib::function_name!(),
1468 line!(),
1469 );
1470 }};
1471
1472 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1473 use $crate::prelude::ElementExtManual;
1474 $obj.message_full_with_details(
1475 $crate::ElementMessageType::Error,
1476 $err,
1477 Some(&format!($($msg)*)),
1478 Some(&format!($($debug)*)),
1479 file!(),
1480 $crate::glib::function_name!(),
1481 line!(),
1482 $details,
1483 );
1484 }};
1485 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1486 use $crate::prelude::ElementExtManual;
1487 $obj.message_full_with_details(
1488 $crate::ElementMessageType::Error,
1489 $err,
1490 Some(&format!($($msg)*)),
1491 None,
1492 file!(),
1493 $crate::glib::function_name!(),
1494 line!(),
1495 $details,
1496 );
1497 }};
1498 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1499 use $crate::prelude::ElementExtManual;
1500 $obj.message_full_with_details(
1501 $crate::ElementMessageType::Error,
1502 $err,
1503 None,
1504 Some(&format!($($debug)*)),
1505 file!(),
1506 $crate::glib::function_name!(),
1507 line!(),
1508 $details,
1509 );
1510 }};
1511);
1512
1513#[doc(alias = "GST_ELEMENT_WARNING")]
1514#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1515#[macro_export]
1516macro_rules! element_warning(
1517 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1518 use $crate::prelude::ElementExtManual;
1519 $obj.message_full(
1520 $crate::ElementMessageType::Warning,
1521 $err,
1522 Some(&format!($($msg)*)),
1523 Some(&format!($($debug)*)),
1524 file!(),
1525 $crate::glib::function_name!(),
1526 line!(),
1527 );
1528 }};
1529 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1530 use $crate::prelude::ElementExtManual;
1531 $obj.message_full(
1532 $crate::ElementMessageType::Warning,
1533 $err,
1534 Some(&format!($($msg)*)),
1535 None,
1536 file!(),
1537 $crate::glib::function_name!(),
1538 line!(),
1539 );
1540 }};
1541 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1542 use $crate::prelude::ElementExtManual;
1543 $obj.message_full(
1544 $crate::ElementMessageType::Warning,
1545 $err,
1546 None,
1547 Some(&format!($($debug)*)),
1548 file!(),
1549 $crate::glib::function_name!(),
1550 line!(),
1551 );
1552 }};
1553
1554 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1555 use $crate::prelude::ElementExtManual;
1556 $obj.message_full_with_details(
1557 $crate::ElementMessageType::Warning,
1558 $err,
1559 Some(&format!($($msg)*)),
1560 Some(&format!($($debug)*)),
1561 file!(),
1562 $crate::glib::function_name!(),
1563 line!(),
1564 $details,
1565 );
1566 }};
1567 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1568 use $crate::prelude::ElementExtManual;
1569 $obj.message_full_with_details(
1570 $crate::ElementMessageType::Warning,
1571 $err,
1572 Some(&format!($($msg)*)),
1573 None,
1574 file!(),
1575 $crate::glib::function_name!(),
1576 line!(),
1577 $details,
1578 );
1579 }};
1580 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1581 use $crate::prelude::ElementExtManual;
1582 $obj.message_full_with_details(
1583 $crate::ElementMessageType::Warning,
1584 $err,
1585 None,
1586 Some(&format!($($debug)*)),
1587 file!(),
1588 $crate::glib::function_name!(),
1589 line!(),
1590 $details,
1591 );
1592 }};
1593);
1594
1595#[doc(alias = "GST_ELEMENT_INFO")]
1596#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1597#[macro_export]
1598macro_rules! element_info(
1599 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1600 use $crate::prelude::ElementExtManual;
1601 $obj.message_full(
1602 $crate::ElementMessageType::Info,
1603 $err,
1604 Some(&format!($($msg)*)),
1605 Some(&format!($($debug)*)),
1606 file!(),
1607 $crate::glib::function_name!(),
1608 line!(),
1609 );
1610 }};
1611 ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1612 use $crate::prelude::ElementExtManual;
1613 $obj.message_full(
1614 $crate::ElementMessageType::Info,
1615 $err,
1616 Some(&format!($($msg)*)),
1617 None,
1618 file!(),
1619 $crate::glib::function_name!(),
1620 line!(),
1621 );
1622 }};
1623 ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1624 use $crate::prelude::ElementExtManual;
1625 $obj.message_full(
1626 $crate::ElementMessageType::Info,
1627 $err,
1628 None,
1629 Some(&format!($($debug)*)),
1630 file!(),
1631 $crate::glib::function_name!(),
1632 line!(),
1633 );
1634 }};
1635
1636 ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1637 use $crate::prelude::ElementExtManual;
1638 $obj.message_full_with_details(
1639 $crate::ElementMessageType::Info,
1640 $err,
1641 Some(&format!($($msg)*)),
1642 Some(&format!($($debug)*)),
1643 file!(),
1644 $crate::glib::function_name!(),
1645 line!(),
1646 $details,
1647 );
1648 }};
1649 ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1650 use $crate::prelude::ElementExtManual;
1651 $obj.message_full_with_details(
1652 $crate::ElementMessageType::Info,
1653 $err,
1654 Some(&format!($($msg)*)),
1655 None,
1656 file!(),
1657 $crate::glib::function_name!(),
1658 line!(),
1659 $details,
1660 );
1661 }};
1662 ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1663 use $crate::prelude::ElementExtManual;
1664 $obj.message_full_with_details(
1665 $crate::ElementMessageType::Info,
1666 $err,
1667 None,
1668 Some(&format!($($debug)*)),
1669 file!(),
1670 $crate::glib::function_name!(),
1671 line!(),
1672 $details,
1673 );
1674 }};
1675);
1676
1677#[doc(alias = "GST_ELEMENT_ERROR")]
1678#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1679#[macro_export]
1680macro_rules! element_imp_error(
1681 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1682 let obj = $imp.obj();
1683 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1684 }};
1685 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1686 let obj = $imp.obj();
1687 $crate::element_error!(obj, $err, ($($msg)*));
1688 }};
1689 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1690 let obj = $imp.obj();
1691 $crate::element_error!(obj, $err, [$($debug)*]);
1692 }};
1693
1694 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1695 let obj = $imp.obj();
1696 $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1697 }};
1698 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1699 let obj = $imp.obj();
1700 $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1701 }};
1702 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1703 let obj = $imp.obj();
1704 $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1705 }};
1706);
1707
1708#[doc(alias = "GST_ELEMENT_WARNING")]
1709#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1710#[macro_export]
1711macro_rules! element_imp_warning(
1712 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1713 let obj = $imp.obj();
1714 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1715 }};
1716 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1717 let obj = $imp.obj();
1718 $crate::element_warning!(obj, $err, ($($msg)*));
1719 }};
1720 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1721 let obj = $imp.obj();
1722 $crate::element_warning!(obj, $err, [$($debug)*]);
1723 }};
1724
1725 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1726 let obj = $imp.obj();
1727 $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1728 }};
1729 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1730 let obj = $imp.obj();
1731 $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1732 }};
1733 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1734 let obj = $imp.obj();
1735 $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1736 }};
1737);
1738
1739#[doc(alias = "GST_ELEMENT_INFO")]
1740#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1741#[macro_export]
1742macro_rules! element_imp_info(
1743 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1744 let obj = $imp.obj();
1745 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1746 }};
1747 ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1748 let obj = $imp.obj();
1749 $crate::element_info!(obj, $err, ($($msg)*));
1750 }};
1751 ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1752 let obj = $imp.obj();
1753 $crate::element_info!(obj, $err, [$($debug)*]);
1754 }};
1755
1756 ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1757 let obj = $imp.obj();
1758 $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1759 }};
1760 ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1761 let obj = $imp.obj();
1762 $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1763 }};
1764 ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1765 let obj = $imp.obj();
1766 $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1767 }};
1768);
1769
1770#[cfg(test)]
1771mod tests {
1772 use std::sync::mpsc::channel;
1773
1774 use glib::GString;
1775
1776 use super::*;
1777
1778 #[test]
1779 fn test_get_pads() {
1780 crate::init().unwrap();
1781
1782 let identity = crate::ElementFactory::make("identity").build().unwrap();
1783
1784 let mut pad_names = identity
1785 .pads()
1786 .iter()
1787 .map(|p| p.name())
1788 .collect::<Vec<GString>>();
1789 pad_names.sort();
1790 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1791
1792 let mut pad_names = identity
1793 .sink_pads()
1794 .iter()
1795 .map(|p| p.name())
1796 .collect::<Vec<GString>>();
1797 pad_names.sort();
1798 assert_eq!(pad_names, vec![String::from("sink")]);
1799
1800 let mut pad_names = identity
1801 .src_pads()
1802 .iter()
1803 .map(|p| p.name())
1804 .collect::<Vec<GString>>();
1805 pad_names.sort();
1806 assert_eq!(pad_names, vec![String::from("src")]);
1807 }
1808
1809 #[test]
1810 fn test_foreach_pad() {
1811 crate::init().unwrap();
1812
1813 let identity = crate::ElementFactory::make("identity").build().unwrap();
1814
1815 let mut pad_names = Vec::new();
1816 identity.foreach_pad(|_element, pad| {
1817 pad_names.push(pad.name());
1818
1819 ControlFlow::Continue(())
1820 });
1821 pad_names.sort();
1822 assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1823
1824 pad_names.clear();
1825 identity.foreach_sink_pad(|_element, pad| {
1826 pad_names.push(pad.name());
1827
1828 ControlFlow::Continue(())
1829 });
1830 assert_eq!(pad_names, vec![String::from("sink")]);
1831
1832 pad_names.clear();
1833 identity.foreach_src_pad(|_element, pad| {
1834 pad_names.push(pad.name());
1835
1836 ControlFlow::Continue(())
1837 });
1838 assert_eq!(pad_names, vec![String::from("src")]);
1839 }
1840
1841 #[test]
1842 fn test_call_async() {
1843 crate::init().unwrap();
1844
1845 let identity = crate::ElementFactory::make("identity").build().unwrap();
1846 let (sender, receiver) = channel();
1847
1848 identity.call_async(move |_| {
1849 sender.send(()).unwrap();
1850 });
1851
1852 assert_eq!(receiver.recv(), Ok(()));
1853 }
1854
1855 #[test]
1856 fn test_element_error() {
1857 crate::init().unwrap();
1858
1859 let identity = crate::ElementFactory::make("identity").build().unwrap();
1860
1861 crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1862 crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1863 crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1864
1865 let x = 123i32;
1868 crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1869 let x = 123i32;
1870 crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1871 let x = 123i32;
1872 crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1873 }
1874}