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