gstreamer/
element.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, pin::Pin};
4
5use glib::translate::*;
6use itertools::Itertools;
7
8use crate::{
9    ffi,
10    format::{
11        CompatibleFormattedValue, FormattedValue, SpecificFormattedValueFullRange,
12        SpecificFormattedValueIntrinsic,
13    },
14    prelude::*,
15    ClockTime, Element, ElementFlags, Event, Format, GenericFormattedValue, Pad, PadTemplate,
16    Plugin, QueryRef, Rank, State,
17};
18
19impl Element {
20    #[doc(alias = "gst_element_link_many")]
21    pub fn link_many(
22        elements: impl IntoIterator<Item = impl AsRef<Element> + Clone>,
23    ) -> Result<(), glib::BoolError> {
24        skip_assert_initialized!();
25        for (src, dest) in elements.into_iter().tuple_windows() {
26            unsafe {
27                glib::result_from_gboolean!(
28                    ffi::gst_element_link(
29                        src.as_ref().to_glib_none().0,
30                        dest.as_ref().to_glib_none().0,
31                    ),
32                    "Failed to link elements '{}' and '{}'",
33                    src.as_ref().name(),
34                    dest.as_ref().name(),
35                )?;
36            }
37        }
38
39        Ok(())
40    }
41
42    #[doc(alias = "gst_element_unlink_many")]
43    pub fn unlink_many(elements: impl IntoIterator<Item = impl AsRef<Element> + Clone>) {
44        skip_assert_initialized!();
45        for (src, dest) in elements.into_iter().tuple_windows() {
46            unsafe {
47                ffi::gst_element_unlink(
48                    src.as_ref().to_glib_none().0,
49                    dest.as_ref().to_glib_none().0,
50                );
51            }
52        }
53    }
54
55    /// Create a new elementfactory capable of instantiating objects of the
56    /// `type_` and add the factory to `plugin`.
57    /// ## `plugin`
58    /// [`Plugin`][crate::Plugin] to register the element with, or [`None`] for
59    ///  a static element.
60    /// ## `name`
61    /// name of elements of this type
62    /// ## `rank`
63    /// rank of element (higher rank means more importance when autoplugging)
64    /// ## `type_`
65    /// GType of element to register
66    ///
67    /// # Returns
68    ///
69    /// [`true`], if the registering succeeded, [`false`] on error
70    #[doc(alias = "gst_element_register")]
71    pub fn register(
72        plugin: Option<&Plugin>,
73        name: &str,
74        rank: Rank,
75        type_: glib::types::Type,
76    ) -> Result<(), glib::error::BoolError> {
77        skip_assert_initialized!();
78        unsafe {
79            glib::result_from_gboolean!(
80                ffi::gst_element_register(
81                    plugin.to_glib_none().0,
82                    name.to_glib_none().0,
83                    rank.into_glib() as u32,
84                    type_.into_glib()
85                ),
86                "Failed to register element factory"
87            )
88        }
89    }
90}
91
92#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
93pub enum ElementMessageType {
94    Error,
95    Warning,
96    Info,
97}
98
99#[derive(Debug, PartialEq, Eq)]
100pub struct NotifyWatchId(NonZeroU64);
101
102impl IntoGlib for NotifyWatchId {
103    type GlibType = libc::c_ulong;
104
105    #[inline]
106    fn into_glib(self) -> libc::c_ulong {
107        self.0.get() as libc::c_ulong
108    }
109}
110
111impl FromGlib<libc::c_ulong> for NotifyWatchId {
112    #[inline]
113    unsafe fn from_glib(val: libc::c_ulong) -> NotifyWatchId {
114        skip_assert_initialized!();
115        debug_assert_ne!(val, 0);
116        NotifyWatchId(NonZeroU64::new_unchecked(val as _))
117    }
118}
119
120mod sealed {
121    pub trait Sealed {}
122    impl<T: super::IsA<super::Element>> Sealed for T {}
123}
124
125pub trait ElementExtManual: sealed::Sealed + IsA<Element> + 'static {
126    #[doc(alias = "get_element_class")]
127    #[inline]
128    fn element_class(&self) -> &glib::Class<Element> {
129        unsafe { self.unsafe_cast_ref::<Element>().class() }
130    }
131
132    #[doc(alias = "get_current_state")]
133    fn current_state(&self) -> State {
134        self.state(Some(ClockTime::ZERO)).1
135    }
136
137    #[doc(alias = "get_pending_state")]
138    fn pending_state(&self) -> State {
139        self.state(Some(ClockTime::ZERO)).2
140    }
141
142    /// Performs a query on the given element.
143    ///
144    /// For elements that don't implement a query handler, this function
145    /// forwards the query to a random srcpad or to the peer of a
146    /// random linked sinkpad of this element.
147    ///
148    /// Please note that some queries might need a running pipeline to work.
149    /// ## `query`
150    /// the [`Query`][crate::Query].
151    ///
152    /// # Returns
153    ///
154    /// [`true`] if the query could be performed.
155    ///
156    /// MT safe.
157    #[doc(alias = "gst_element_query")]
158    fn query(&self, query: &mut QueryRef) -> bool {
159        unsafe {
160            from_glib(ffi::gst_element_query(
161                self.as_ref().to_glib_none().0,
162                query.as_mut_ptr(),
163            ))
164        }
165    }
166
167    /// Sends an event to an element. If the element doesn't implement an
168    /// event handler, the event will be pushed on a random linked sink pad for
169    /// downstream events or a random linked source pad for upstream events.
170    ///
171    /// This function takes ownership of the provided event so you should
172    /// `gst_event_ref()` it if you want to reuse the event after this call.
173    ///
174    /// MT safe.
175    /// ## `event`
176    /// the [`Event`][crate::Event] to send to the element.
177    ///
178    /// # Returns
179    ///
180    /// [`true`] if the event was handled. Events that trigger a preroll (such
181    /// as flushing seeks and steps) will emit `GST_MESSAGE_ASYNC_DONE`.
182    #[doc(alias = "gst_element_send_event")]
183    fn send_event(&self, event: impl Into<Event>) -> bool {
184        unsafe {
185            from_glib(ffi::gst_element_send_event(
186                self.as_ref().to_glib_none().0,
187                event.into().into_glib_ptr(),
188            ))
189        }
190    }
191
192    /// Get metadata with `key` in `klass`.
193    /// ## `key`
194    /// the key to get
195    ///
196    /// # Returns
197    ///
198    /// the metadata for `key`.
199    #[doc(alias = "get_metadata")]
200    #[doc(alias = "gst_element_class_get_metadata")]
201    fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
202        self.element_class().metadata(key)
203    }
204
205    /// Retrieves a padtemplate from `self` with the given name.
206    /// ## `name`
207    /// the name of the [`PadTemplate`][crate::PadTemplate] to get.
208    ///
209    /// # Returns
210    ///
211    /// the [`PadTemplate`][crate::PadTemplate] with the
212    ///  given name, or [`None`] if none was found. No unreferencing is
213    ///  necessary.
214    #[doc(alias = "get_pad_template")]
215    #[doc(alias = "gst_element_class_get_pad_template")]
216    fn pad_template(&self, name: &str) -> Option<PadTemplate> {
217        self.element_class().pad_template(name)
218    }
219
220    /// Retrieves a list of the pad templates associated with `self`. The
221    /// list must not be modified by the calling code.
222    ///
223    /// # Returns
224    ///
225    /// the `GList` of
226    ///  pad templates.
227    #[doc(alias = "get_pad_template_list")]
228    #[doc(alias = "gst_element_class_get_pad_template_list")]
229    fn pad_template_list(&self) -> glib::List<PadTemplate> {
230        self.element_class().pad_template_list()
231    }
232
233    /// Post an error, warning or info message on the bus from inside an element.
234    ///
235    /// `type_` must be of `GST_MESSAGE_ERROR`, `GST_MESSAGE_WARNING` or
236    /// `GST_MESSAGE_INFO`.
237    ///
238    /// MT safe.
239    /// ## `type_`
240    /// the `GstMessageType`
241    /// ## `domain`
242    /// the GStreamer GError domain this message belongs to
243    /// ## `code`
244    /// the GError code belonging to the domain
245    /// ## `text`
246    /// an allocated text string to be used
247    ///  as a replacement for the default message connected to code,
248    ///  or [`None`]
249    /// ## `debug`
250    /// an allocated debug message to be
251    ///  used as a replacement for the default debugging information,
252    ///  or [`None`]
253    /// ## `file`
254    /// the source code file where the error was generated
255    /// ## `function`
256    /// the source code function where the error was generated
257    /// ## `line`
258    /// the source code line where the error was generated
259    #[allow(clippy::too_many_arguments)]
260    #[doc(alias = "gst_element_message_full")]
261    fn message_full<T: crate::MessageErrorDomain>(
262        &self,
263        type_: ElementMessageType,
264        code: T,
265        message: Option<&str>,
266        debug: Option<&str>,
267        file: &str,
268        function: &str,
269        line: u32,
270    ) {
271        unsafe {
272            let type_ = match type_ {
273                ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
274                ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
275                ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
276            };
277
278            ffi::gst_element_message_full(
279                self.as_ref().to_glib_none().0,
280                type_,
281                T::domain().into_glib(),
282                code.code(),
283                message.to_glib_full(),
284                debug.to_glib_full(),
285                file.to_glib_none().0,
286                function.to_glib_none().0,
287                line as i32,
288            );
289        }
290    }
291
292    fn set_element_flags(&self, flags: ElementFlags) {
293        unsafe {
294            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
295            let _guard = self.as_ref().object_lock();
296            (*ptr).flags |= flags.into_glib();
297        }
298    }
299
300    fn unset_element_flags(&self, flags: ElementFlags) {
301        unsafe {
302            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
303            let _guard = self.as_ref().object_lock();
304            (*ptr).flags &= !flags.into_glib();
305        }
306    }
307
308    #[doc(alias = "get_element_flags")]
309    fn element_flags(&self) -> ElementFlags {
310        unsafe {
311            let ptr: *mut ffi::GstObject = self.as_ptr() as *mut _;
312            let _guard = self.as_ref().object_lock();
313            from_glib((*ptr).flags)
314        }
315    }
316
317    /// Post an error, warning or info message on the bus from inside an element.
318    ///
319    /// `type_` must be of `GST_MESSAGE_ERROR`, `GST_MESSAGE_WARNING` or
320    /// `GST_MESSAGE_INFO`.
321    /// ## `type_`
322    /// the `GstMessageType`
323    /// ## `domain`
324    /// the GStreamer GError domain this message belongs to
325    /// ## `code`
326    /// the GError code belonging to the domain
327    /// ## `text`
328    /// an allocated text string to be used
329    ///  as a replacement for the default message connected to code,
330    ///  or [`None`]
331    /// ## `debug`
332    /// an allocated debug message to be
333    ///  used as a replacement for the default debugging information,
334    ///  or [`None`]
335    /// ## `file`
336    /// the source code file where the error was generated
337    /// ## `function`
338    /// the source code function where the error was generated
339    /// ## `line`
340    /// the source code line where the error was generated
341    /// ## `structure`
342    /// optional details structure
343    #[allow(clippy::too_many_arguments)]
344    #[doc(alias = "gst_element_message_full_with_details")]
345    fn message_full_with_details<T: crate::MessageErrorDomain>(
346        &self,
347        type_: ElementMessageType,
348        code: T,
349        message: Option<&str>,
350        debug: Option<&str>,
351        file: &str,
352        function: &str,
353        line: u32,
354        structure: crate::Structure,
355    ) {
356        unsafe {
357            let type_ = match type_ {
358                ElementMessageType::Error => ffi::GST_MESSAGE_ERROR,
359                ElementMessageType::Warning => ffi::GST_MESSAGE_WARNING,
360                ElementMessageType::Info => ffi::GST_MESSAGE_INFO,
361            };
362
363            ffi::gst_element_message_full_with_details(
364                self.as_ref().to_glib_none().0,
365                type_,
366                T::domain().into_glib(),
367                code.code(),
368                message.to_glib_full(),
369                debug.to_glib_full(),
370                file.to_glib_none().0,
371                function.to_glib_none().0,
372                line as i32,
373                structure.into_glib_ptr(),
374            );
375        }
376    }
377
378    fn post_error_message(&self, msg: crate::ErrorMessage) {
379        let crate::ErrorMessage {
380            error_domain,
381            error_code,
382            ref message,
383            ref debug,
384            filename,
385            function,
386            line,
387        } = msg;
388
389        unsafe {
390            ffi::gst_element_message_full(
391                self.as_ref().to_glib_none().0,
392                ffi::GST_MESSAGE_ERROR,
393                error_domain.into_glib(),
394                error_code,
395                message.to_glib_full(),
396                debug.to_glib_full(),
397                filename.to_glib_none().0,
398                function.to_glib_none().0,
399                line as i32,
400            );
401        }
402    }
403
404    /// Retrieves an iterator of `self`'s pads. The iterator should
405    /// be freed after usage. Also more specialized iterators exists such as
406    /// [`iterate_src_pads()`][Self::iterate_src_pads()] or [`iterate_sink_pads()`][Self::iterate_sink_pads()].
407    ///
408    /// The order of pads returned by the iterator will be the order in which
409    /// the pads were added to the element.
410    ///
411    /// # Returns
412    ///
413    /// the `GstIterator` of [`Pad`][crate::Pad].
414    ///
415    /// MT safe.
416    #[doc(alias = "gst_element_iterate_pads")]
417    fn iterate_pads(&self) -> crate::Iterator<Pad> {
418        unsafe {
419            from_glib_full(ffi::gst_element_iterate_pads(
420                self.as_ref().to_glib_none().0,
421            ))
422        }
423    }
424
425    /// Retrieves an iterator of `self`'s sink pads.
426    ///
427    /// The order of pads returned by the iterator will be the order in which
428    /// the pads were added to the element.
429    ///
430    /// # Returns
431    ///
432    /// the `GstIterator` of [`Pad`][crate::Pad].
433    ///
434    /// MT safe.
435    #[doc(alias = "gst_element_iterate_sink_pads")]
436    fn iterate_sink_pads(&self) -> crate::Iterator<Pad> {
437        unsafe {
438            from_glib_full(ffi::gst_element_iterate_sink_pads(
439                self.as_ref().to_glib_none().0,
440            ))
441        }
442    }
443
444    /// Retrieves an iterator of `self`'s source pads.
445    ///
446    /// The order of pads returned by the iterator will be the order in which
447    /// the pads were added to the element.
448    ///
449    /// # Returns
450    ///
451    /// the `GstIterator` of [`Pad`][crate::Pad].
452    ///
453    /// MT safe.
454    #[doc(alias = "gst_element_iterate_src_pads")]
455    fn iterate_src_pads(&self) -> crate::Iterator<Pad> {
456        unsafe {
457            from_glib_full(ffi::gst_element_iterate_src_pads(
458                self.as_ref().to_glib_none().0,
459            ))
460        }
461    }
462
463    #[doc(alias = "get_pads")]
464    #[doc(alias = "gst_element_foreach_pad")]
465    fn pads(&self) -> Vec<Pad> {
466        unsafe {
467            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
468            let _guard = self.as_ref().object_lock();
469            FromGlibPtrContainer::from_glib_none(elt.pads)
470        }
471    }
472
473    #[doc(alias = "get_sink_pads")]
474    #[doc(alias = "gst_element_foreach_sink_pad")]
475    fn sink_pads(&self) -> Vec<Pad> {
476        unsafe {
477            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
478            let _guard = self.as_ref().object_lock();
479            FromGlibPtrContainer::from_glib_none(elt.sinkpads)
480        }
481    }
482
483    #[doc(alias = "get_src_pads")]
484    #[doc(alias = "gst_element_foreach_src_pad")]
485    fn src_pads(&self) -> Vec<Pad> {
486        unsafe {
487            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
488            let _guard = self.as_ref().object_lock();
489            FromGlibPtrContainer::from_glib_none(elt.srcpads)
490        }
491    }
492
493    fn num_pads(&self) -> u16 {
494        unsafe {
495            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
496            let _guard = self.as_ref().object_lock();
497            elt.numpads
498        }
499    }
500
501    fn num_sink_pads(&self) -> u16 {
502        unsafe {
503            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
504            let _guard = self.as_ref().object_lock();
505            elt.numsinkpads
506        }
507    }
508
509    fn num_src_pads(&self) -> u16 {
510        unsafe {
511            let elt: &ffi::GstElement = &*(self.as_ptr() as *const _);
512            let _guard = self.as_ref().object_lock();
513            elt.numsrcpads
514        }
515    }
516
517    /// ## `property_name`
518    /// name of property to watch for changes, or
519    ///  NULL to watch all properties
520    /// ## `include_value`
521    /// whether to include the new property value in the message
522    ///
523    /// # Returns
524    ///
525    /// a watch id, which can be used in connection with
526    ///  [`remove_property_notify_watch()`][Self::remove_property_notify_watch()] to remove the watch again.
527    #[doc(alias = "gst_element_add_property_deep_notify_watch")]
528    fn add_property_deep_notify_watch(
529        &self,
530        property_name: Option<&str>,
531        include_value: bool,
532    ) -> NotifyWatchId {
533        let property_name = property_name.to_glib_none();
534        unsafe {
535            from_glib(ffi::gst_element_add_property_deep_notify_watch(
536                self.as_ref().to_glib_none().0,
537                property_name.0,
538                include_value.into_glib(),
539            ))
540        }
541    }
542
543    /// ## `property_name`
544    /// name of property to watch for changes, or
545    ///  NULL to watch all properties
546    /// ## `include_value`
547    /// whether to include the new property value in the message
548    ///
549    /// # Returns
550    ///
551    /// a watch id, which can be used in connection with
552    ///  [`remove_property_notify_watch()`][Self::remove_property_notify_watch()] to remove the watch again.
553    #[doc(alias = "gst_element_add_property_notify_watch")]
554    fn add_property_notify_watch(
555        &self,
556        property_name: Option<&str>,
557        include_value: bool,
558    ) -> NotifyWatchId {
559        let property_name = property_name.to_glib_none();
560        unsafe {
561            from_glib(ffi::gst_element_add_property_notify_watch(
562                self.as_ref().to_glib_none().0,
563                property_name.0,
564                include_value.into_glib(),
565            ))
566        }
567    }
568
569    /// ## `watch_id`
570    /// watch id to remove
571    #[doc(alias = "gst_element_remove_property_notify_watch")]
572    fn remove_property_notify_watch(&self, watch_id: NotifyWatchId) {
573        unsafe {
574            ffi::gst_element_remove_property_notify_watch(
575                self.as_ref().to_glib_none().0,
576                watch_id.into_glib(),
577            );
578        }
579    }
580
581    /// Queries an element to convert `src_val` in `src_format` to `dest_format`.
582    /// ## `src_format`
583    /// a [`Format`][crate::Format] to convert from.
584    /// ## `src_val`
585    /// a value to convert.
586    /// ## `dest_format`
587    /// the [`Format`][crate::Format] to convert to.
588    ///
589    /// # Returns
590    ///
591    /// [`true`] if the query could be performed.
592    ///
593    /// ## `dest_val`
594    /// a pointer to the result.
595    #[doc(alias = "gst_element_query_convert")]
596    fn query_convert<U: SpecificFormattedValueFullRange>(
597        &self,
598        src_val: impl FormattedValue,
599    ) -> Option<U> {
600        unsafe {
601            let mut dest_val = mem::MaybeUninit::uninit();
602            let ret = from_glib(ffi::gst_element_query_convert(
603                self.as_ref().to_glib_none().0,
604                src_val.format().into_glib(),
605                src_val.into_raw_value(),
606                U::default_format().into_glib(),
607                dest_val.as_mut_ptr(),
608            ));
609            if ret {
610                Some(U::from_raw(U::default_format(), dest_val.assume_init()))
611            } else {
612                None
613            }
614        }
615    }
616
617    #[doc(alias = "gst_element_query_convert")]
618    fn query_convert_generic(
619        &self,
620        src_val: impl FormattedValue,
621        dest_format: Format,
622    ) -> Option<GenericFormattedValue> {
623        unsafe {
624            let mut dest_val = mem::MaybeUninit::uninit();
625            let ret = from_glib(ffi::gst_element_query_convert(
626                self.as_ref().to_glib_none().0,
627                src_val.format().into_glib(),
628                src_val.into_raw_value(),
629                dest_format.into_glib(),
630                dest_val.as_mut_ptr(),
631            ));
632            if ret {
633                Some(GenericFormattedValue::new(
634                    dest_format,
635                    dest_val.assume_init(),
636                ))
637            } else {
638                None
639            }
640        }
641    }
642
643    /// Queries an element (usually top-level pipeline or playbin element) for the
644    /// total stream duration in nanoseconds. This query will only work once the
645    /// pipeline is prerolled (i.e. reached PAUSED or PLAYING state). The application
646    /// will receive an ASYNC_DONE message on the pipeline bus when that is the case.
647    ///
648    /// If the duration changes for some reason, you will get a DURATION_CHANGED
649    /// message on the pipeline bus, in which case you should re-query the duration
650    /// using this function.
651    /// ## `format`
652    /// the [`Format`][crate::Format] requested
653    ///
654    /// # Returns
655    ///
656    /// [`true`] if the query could be performed.
657    ///
658    /// ## `duration`
659    /// A location in which to store the total duration, or [`None`].
660    #[doc(alias = "gst_element_query_duration")]
661    fn query_duration<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
662        unsafe {
663            let mut duration = mem::MaybeUninit::uninit();
664            let ret = from_glib(ffi::gst_element_query_duration(
665                self.as_ref().to_glib_none().0,
666                T::default_format().into_glib(),
667                duration.as_mut_ptr(),
668            ));
669            if ret {
670                try_from_glib(duration.assume_init()).ok()
671            } else {
672                None
673            }
674        }
675    }
676
677    #[doc(alias = "gst_element_query_duration")]
678    fn query_duration_generic(&self, format: Format) -> Option<GenericFormattedValue> {
679        unsafe {
680            let mut duration = mem::MaybeUninit::uninit();
681            let ret = from_glib(ffi::gst_element_query_duration(
682                self.as_ref().to_glib_none().0,
683                format.into_glib(),
684                duration.as_mut_ptr(),
685            ));
686            if ret {
687                Some(GenericFormattedValue::new(format, duration.assume_init()))
688            } else {
689                None
690            }
691        }
692    }
693
694    /// Queries an element (usually top-level pipeline or playbin element) for the
695    /// stream position in nanoseconds. This will be a value between 0 and the
696    /// stream duration (if the stream duration is known). This query will usually
697    /// only work once the pipeline is prerolled (i.e. reached PAUSED or PLAYING
698    /// state). The application will receive an ASYNC_DONE message on the pipeline
699    /// bus when that is the case.
700    ///
701    /// If one repeatedly calls this function one can also create a query and reuse
702    /// it in [`query()`][Self::query()].
703    /// ## `format`
704    /// the [`Format`][crate::Format] requested
705    ///
706    /// # Returns
707    ///
708    /// [`true`] if the query could be performed.
709    ///
710    /// ## `cur`
711    /// a location in which to store the current
712    ///  position, or [`None`].
713    #[doc(alias = "gst_element_query_position")]
714    fn query_position<T: SpecificFormattedValueIntrinsic>(&self) -> Option<T> {
715        unsafe {
716            let mut cur = mem::MaybeUninit::uninit();
717            let ret = from_glib(ffi::gst_element_query_position(
718                self.as_ref().to_glib_none().0,
719                T::default_format().into_glib(),
720                cur.as_mut_ptr(),
721            ));
722            if ret {
723                try_from_glib(cur.assume_init()).ok()
724            } else {
725                None
726            }
727        }
728    }
729
730    #[doc(alias = "gst_element_query_position")]
731    fn query_position_generic(&self, format: Format) -> Option<GenericFormattedValue> {
732        unsafe {
733            let mut cur = mem::MaybeUninit::uninit();
734            let ret = from_glib(ffi::gst_element_query_position(
735                self.as_ref().to_glib_none().0,
736                format.into_glib(),
737                cur.as_mut_ptr(),
738            ));
739            if ret {
740                Some(GenericFormattedValue::new(format, cur.assume_init()))
741            } else {
742                None
743            }
744        }
745    }
746
747    /// Sends a seek event to an element. See `gst_event_new_seek()` for the details of
748    /// the parameters. The seek event is sent to the element using
749    /// [`send_event()`][Self::send_event()].
750    ///
751    /// MT safe.
752    /// ## `rate`
753    /// The new playback rate
754    /// ## `format`
755    /// The format of the seek values
756    /// ## `flags`
757    /// The optional seek flags.
758    /// ## `start_type`
759    /// The type and flags for the new start position
760    /// ## `start`
761    /// The value of the new start position
762    /// ## `stop_type`
763    /// The type and flags for the new stop position
764    /// ## `stop`
765    /// The value of the new stop position
766    ///
767    /// # Returns
768    ///
769    /// [`true`] if the event was handled. Flushing seeks will trigger a
770    /// preroll, which will emit `GST_MESSAGE_ASYNC_DONE`.
771    #[doc(alias = "gst_element_seek")]
772    fn seek<V: FormattedValue>(
773        &self,
774        rate: f64,
775        flags: crate::SeekFlags,
776        start_type: crate::SeekType,
777        start: V,
778        stop_type: crate::SeekType,
779        stop: impl CompatibleFormattedValue<V>,
780    ) -> Result<(), glib::error::BoolError> {
781        let stop = stop.try_into_checked(start).unwrap();
782
783        unsafe {
784            glib::result_from_gboolean!(
785                ffi::gst_element_seek(
786                    self.as_ref().to_glib_none().0,
787                    rate,
788                    start.format().into_glib(),
789                    flags.into_glib(),
790                    start_type.into_glib(),
791                    start.into_raw_value(),
792                    stop_type.into_glib(),
793                    stop.into_raw_value(),
794                ),
795                "Failed to seek",
796            )
797        }
798    }
799
800    /// Simple API to perform a seek on the given element, meaning it just seeks
801    /// to the given position relative to the start of the stream. For more complex
802    /// operations like segment seeks (e.g. for looping) or changing the playback
803    /// rate or seeking relative to the last configured playback segment you should
804    /// use [`seek()`][Self::seek()].
805    ///
806    /// In a completely prerolled PAUSED or PLAYING pipeline, seeking is always
807    /// guaranteed to return [`true`] on a seekable media type or [`false`] when the media
808    /// type is certainly not seekable (such as a live stream).
809    ///
810    /// Some elements allow for seeking in the READY state, in this
811    /// case they will store the seek event and execute it when they are put to
812    /// PAUSED. If the element supports seek in READY, it will always return [`true`] when
813    /// it receives the event in the READY state.
814    /// ## `format`
815    /// a [`Format`][crate::Format] to execute the seek in, such as [`Format::Time`][crate::Format::Time]
816    /// ## `seek_flags`
817    /// seek options; playback applications will usually want to use
818    ///  GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here
819    /// ## `seek_pos`
820    /// position to seek to (relative to the start); if you are doing
821    ///  a seek in [`Format::Time`][crate::Format::Time] this value is in nanoseconds -
822    ///  multiply with `GST_SECOND` to convert seconds to nanoseconds or
823    ///  with `GST_MSECOND` to convert milliseconds to nanoseconds.
824    ///
825    /// # Returns
826    ///
827    /// [`true`] if the seek operation succeeded. Flushing seeks will trigger a
828    /// preroll, which will emit `GST_MESSAGE_ASYNC_DONE`.
829    #[doc(alias = "gst_element_seek_simple")]
830    fn seek_simple(
831        &self,
832        seek_flags: crate::SeekFlags,
833        seek_pos: impl FormattedValue,
834    ) -> Result<(), glib::error::BoolError> {
835        unsafe {
836            glib::result_from_gboolean!(
837                ffi::gst_element_seek_simple(
838                    self.as_ref().to_glib_none().0,
839                    seek_pos.format().into_glib(),
840                    seek_flags.into_glib(),
841                    seek_pos.into_raw_value(),
842                ),
843                "Failed to seek",
844            )
845        }
846    }
847
848    /// Calls `func` from another thread and passes `user_data` to it. This is to be
849    /// used for cases when a state change has to be performed from a streaming
850    /// thread, directly via [`ElementExt::set_state()`][crate::prelude::ElementExt::set_state()] or indirectly e.g. via SEEK
851    /// events.
852    ///
853    /// Calling those functions directly from the streaming thread will cause
854    /// deadlocks in many situations, as they might involve waiting for the
855    /// streaming thread to shut down from this very streaming thread.
856    ///
857    /// MT safe.
858    /// ## `func`
859    /// Function to call asynchronously from another thread
860    /// ## `destroy_notify`
861    /// GDestroyNotify for `user_data`
862    #[doc(alias = "gst_element_call_async")]
863    fn call_async<F>(&self, func: F)
864    where
865        F: FnOnce(&Self) + Send + 'static,
866    {
867        let user_data: Box<Option<F>> = Box::new(Some(func));
868
869        unsafe extern "C" fn trampoline<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
870            element: *mut ffi::GstElement,
871            user_data: glib::ffi::gpointer,
872        ) {
873            let user_data: &mut Option<F> = &mut *(user_data as *mut _);
874            let callback = user_data.take().unwrap();
875
876            callback(Element::from_glib_borrow(element).unsafe_cast_ref());
877        }
878
879        unsafe extern "C" fn free_user_data<O: IsA<Element>, F: FnOnce(&O) + Send + 'static>(
880            user_data: glib::ffi::gpointer,
881        ) {
882            let _: Box<Option<F>> = Box::from_raw(user_data as *mut _);
883        }
884
885        unsafe {
886            ffi::gst_element_call_async(
887                self.as_ref().to_glib_none().0,
888                Some(trampoline::<Self, F>),
889                Box::into_raw(user_data) as *mut _,
890                Some(free_user_data::<Self, F>),
891            );
892        }
893    }
894
895    fn call_async_future<F, T>(&self, func: F) -> Pin<Box<dyn Future<Output = T> + Send + 'static>>
896    where
897        F: FnOnce(&Self) -> T + Send + 'static,
898        T: Send + 'static,
899    {
900        use futures_channel::oneshot;
901
902        let (sender, receiver) = oneshot::channel();
903
904        self.call_async(move |element| {
905            let _ = sender.send(func(element));
906        });
907
908        Box::pin(async move { receiver.await.expect("sender dropped") })
909    }
910
911    /// Returns the running time of the element. The running time is the
912    /// element's clock time minus its base time. Will return GST_CLOCK_TIME_NONE
913    /// if the element has no clock, or if its base time has not been set.
914    ///
915    /// # Returns
916    ///
917    /// the running time of the element, or GST_CLOCK_TIME_NONE if the
918    /// element has no clock or its base time has not been set.
919    #[doc(alias = "get_current_running_time")]
920    #[doc(alias = "gst_element_get_current_running_time")]
921    fn current_running_time(&self) -> Option<crate::ClockTime> {
922        let base_time = self.base_time();
923        let clock_time = self.current_clock_time();
924
925        clock_time
926            .zip(base_time)
927            .and_then(|(ct, bt)| ct.checked_sub(bt))
928    }
929
930    /// Returns the current clock time of the element, as in, the time of the
931    /// element's clock, or GST_CLOCK_TIME_NONE if there is no clock.
932    ///
933    /// # Returns
934    ///
935    /// the clock time of the element, or GST_CLOCK_TIME_NONE if there is
936    /// no clock.
937    #[doc(alias = "get_current_clock_time")]
938    #[doc(alias = "gst_element_get_current_clock_time")]
939    fn current_clock_time(&self) -> Option<crate::ClockTime> {
940        if let Some(clock) = self.clock() {
941            clock.time()
942        } else {
943            crate::ClockTime::NONE
944        }
945    }
946
947    /// The name of this function is confusing to people learning GStreamer.
948    /// [`request_pad_simple()`][Self::request_pad_simple()] aims at making it more explicit it is
949    /// a simplified [`ElementExt::request_pad()`][crate::prelude::ElementExt::request_pad()].
950    ///
951    /// # Deprecated since 1.20
952    ///
953    /// Prefer using [`request_pad_simple()`][Self::request_pad_simple()] which
954    /// provides the exact same functionality.
955    /// ## `name`
956    /// the name of the request [`Pad`][crate::Pad] to retrieve.
957    ///
958    /// # Returns
959    ///
960    /// requested [`Pad`][crate::Pad] if found,
961    ///  otherwise [`None`]. Release after usage.
962    #[doc(alias = "gst_element_get_request_pad")]
963    #[doc(alias = "get_request_pad")]
964    #[doc(alias = "gst_element_request_pad_simple")]
965    fn request_pad_simple(&self, name: &str) -> Option<Pad> {
966        unsafe {
967            #[cfg(feature = "v1_20")]
968            {
969                from_glib_full(ffi::gst_element_request_pad_simple(
970                    self.as_ref().to_glib_none().0,
971                    name.to_glib_none().0,
972                ))
973            }
974            #[cfg(not(feature = "v1_20"))]
975            {
976                from_glib_full(ffi::gst_element_get_request_pad(
977                    self.as_ref().to_glib_none().0,
978                    name.to_glib_none().0,
979                ))
980            }
981        }
982    }
983
984    /// Links `self` to `dest`. The link must be from source to
985    /// destination; the other direction will not be tried. The function looks for
986    /// existing pads that aren't linked yet. It will request new pads if necessary.
987    /// Such pads need to be released manually when unlinking.
988    /// If multiple links are possible, only one is established.
989    ///
990    /// Make sure you have added your elements to a bin or pipeline with
991    /// [`GstBinExt::add()`][crate::prelude::GstBinExt::add()] before trying to link them.
992    /// ## `dest`
993    /// the [`Element`][crate::Element] containing the destination pad.
994    ///
995    /// # Returns
996    ///
997    /// [`true`] if the elements could be linked, [`false`] otherwise.
998    #[doc(alias = "gst_element_link")]
999    fn link(&self, dest: &impl IsA<Element>) -> Result<(), glib::error::BoolError> {
1000        unsafe {
1001            glib::result_from_gboolean!(
1002                ffi::gst_element_link(
1003                    self.as_ref().to_glib_none().0,
1004                    dest.as_ref().to_glib_none().0
1005                ),
1006                "Failed to link elements '{}' and '{}'",
1007                self.as_ref().name(),
1008                dest.as_ref().name(),
1009            )
1010        }
1011    }
1012
1013    /// Links `self` to `dest` using the given caps as filtercaps.
1014    /// The link must be from source to
1015    /// destination; the other direction will not be tried. The function looks for
1016    /// existing pads that aren't linked yet. It will request new pads if necessary.
1017    /// If multiple links are possible, only one is established.
1018    ///
1019    /// Make sure you have added your elements to a bin or pipeline with
1020    /// [`GstBinExt::add()`][crate::prelude::GstBinExt::add()] before trying to link them.
1021    /// ## `dest`
1022    /// the [`Element`][crate::Element] containing the destination pad.
1023    /// ## `filter`
1024    /// the [`Caps`][crate::Caps] to filter the link,
1025    ///  or [`None`] for no filter.
1026    ///
1027    /// # Returns
1028    ///
1029    /// [`true`] if the pads could be linked, [`false`] otherwise.
1030    #[doc(alias = "gst_element_link_filtered")]
1031    fn link_filtered(
1032        &self,
1033        dest: &impl IsA<Element>,
1034        filter: &crate::Caps,
1035    ) -> Result<(), glib::error::BoolError> {
1036        unsafe {
1037            glib::result_from_gboolean!(
1038                ffi::gst_element_link_filtered(
1039                    self.as_ref().to_glib_none().0,
1040                    dest.as_ref().to_glib_none().0,
1041                    filter.to_glib_none().0
1042                ),
1043                "Failed to link elements '{}' and '{}' with filter '{:?}'",
1044                self.as_ref().name(),
1045                dest.as_ref().name(),
1046                filter,
1047            )
1048        }
1049    }
1050
1051    /// Links the two named pads of the source and destination elements.
1052    /// Side effect is that if one of the pads has no parent, it becomes a
1053    /// child of the parent of the other element. If they have different
1054    /// parents, the link fails.
1055    /// ## `srcpadname`
1056    /// the name of the [`Pad`][crate::Pad] in source element
1057    ///  or [`None`] for any pad.
1058    /// ## `dest`
1059    /// the [`Element`][crate::Element] containing the destination pad.
1060    /// ## `destpadname`
1061    /// the name of the [`Pad`][crate::Pad] in destination element,
1062    /// or [`None`] for any pad.
1063    ///
1064    /// # Returns
1065    ///
1066    /// [`true`] if the pads could be linked, [`false`] otherwise.
1067    #[doc(alias = "gst_element_link_pads")]
1068    fn link_pads(
1069        &self,
1070        srcpadname: Option<&str>,
1071        dest: &impl IsA<Element>,
1072        destpadname: Option<&str>,
1073    ) -> Result<(), glib::error::BoolError> {
1074        unsafe {
1075            glib::result_from_gboolean!(
1076                ffi::gst_element_link_pads(
1077                    self.as_ref().to_glib_none().0,
1078                    srcpadname.to_glib_none().0,
1079                    dest.as_ref().to_glib_none().0,
1080                    destpadname.to_glib_none().0
1081                ),
1082                "Failed to link pads '{}' and '{}'",
1083                if let Some(srcpadname) = srcpadname {
1084                    format!("{}:{}", self.as_ref().name(), srcpadname)
1085                } else {
1086                    format!("{}:*", self.as_ref().name())
1087                },
1088                if let Some(destpadname) = destpadname {
1089                    format!("{}:{}", dest.as_ref().name(), destpadname)
1090                } else {
1091                    format!("{}:*", dest.as_ref().name())
1092                },
1093            )
1094        }
1095    }
1096
1097    /// Links the two named pads of the source and destination elements. Side effect
1098    /// is that if one of the pads has no parent, it becomes a child of the parent of
1099    /// the other element. If they have different parents, the link fails. If `caps`
1100    /// is not [`None`], makes sure that the caps of the link is a subset of `caps`.
1101    /// ## `srcpadname`
1102    /// the name of the [`Pad`][crate::Pad] in source element
1103    ///  or [`None`] for any pad.
1104    /// ## `dest`
1105    /// the [`Element`][crate::Element] containing the destination pad.
1106    /// ## `destpadname`
1107    /// the name of the [`Pad`][crate::Pad] in destination element
1108    ///  or [`None`] for any pad.
1109    /// ## `filter`
1110    /// the [`Caps`][crate::Caps] to filter the link,
1111    ///  or [`None`] for no filter.
1112    ///
1113    /// # Returns
1114    ///
1115    /// [`true`] if the pads could be linked, [`false`] otherwise.
1116    #[doc(alias = "gst_element_link_pads_filtered")]
1117    fn link_pads_filtered(
1118        &self,
1119        srcpadname: Option<&str>,
1120        dest: &impl IsA<Element>,
1121        destpadname: Option<&str>,
1122        filter: &crate::Caps,
1123    ) -> Result<(), glib::error::BoolError> {
1124        unsafe {
1125            glib::result_from_gboolean!(
1126                ffi::gst_element_link_pads_filtered(
1127                    self.as_ref().to_glib_none().0,
1128                    srcpadname.to_glib_none().0,
1129                    dest.as_ref().to_glib_none().0,
1130                    destpadname.to_glib_none().0,
1131                    filter.to_glib_none().0
1132                ),
1133                "Failed to link pads '{}' and '{}' with filter '{:?}'",
1134                if let Some(srcpadname) = srcpadname {
1135                    format!("{}:{}", self.as_ref().name(), srcpadname)
1136                } else {
1137                    format!("{}:*", self.as_ref().name())
1138                },
1139                if let Some(destpadname) = destpadname {
1140                    format!("{}:{}", dest.as_ref().name(), destpadname)
1141                } else {
1142                    format!("{}:*", dest.as_ref().name())
1143                },
1144                filter,
1145            )
1146        }
1147    }
1148
1149    /// Links the two named pads of the source and destination elements.
1150    /// Side effect is that if one of the pads has no parent, it becomes a
1151    /// child of the parent of the other element. If they have different
1152    /// parents, the link fails.
1153    ///
1154    /// Calling [`link_pads_full()`][Self::link_pads_full()] with `flags` == [`PadLinkCheck::DEFAULT`][crate::PadLinkCheck::DEFAULT]
1155    /// is the same as calling [`link_pads()`][Self::link_pads()] and the recommended way of
1156    /// linking pads with safety checks applied.
1157    ///
1158    /// This is a convenience function for [`PadExt::link_full()`][crate::prelude::PadExt::link_full()].
1159    /// ## `srcpadname`
1160    /// the name of the [`Pad`][crate::Pad] in source element
1161    ///  or [`None`] for any pad.
1162    /// ## `dest`
1163    /// the [`Element`][crate::Element] containing the destination pad.
1164    /// ## `destpadname`
1165    /// the name of the [`Pad`][crate::Pad] in destination element,
1166    /// or [`None`] for any pad.
1167    /// ## `flags`
1168    /// the [`PadLinkCheck`][crate::PadLinkCheck] to be performed when linking pads.
1169    ///
1170    /// # Returns
1171    ///
1172    /// [`true`] if the pads could be linked, [`false`] otherwise.
1173    #[doc(alias = "gst_element_link_pads_full")]
1174    fn link_pads_full(
1175        &self,
1176        srcpadname: Option<&str>,
1177        dest: &impl IsA<Element>,
1178        destpadname: Option<&str>,
1179        flags: crate::PadLinkCheck,
1180    ) -> Result<(), glib::error::BoolError> {
1181        unsafe {
1182            glib::result_from_gboolean!(
1183                ffi::gst_element_link_pads_full(
1184                    self.as_ref().to_glib_none().0,
1185                    srcpadname.to_glib_none().0,
1186                    dest.as_ref().to_glib_none().0,
1187                    destpadname.to_glib_none().0,
1188                    flags.into_glib()
1189                ),
1190                "Failed to link pads '{}' and '{}' with flags '{:?}'",
1191                if let Some(srcpadname) = srcpadname {
1192                    format!("{}:{}", self.as_ref().name(), srcpadname)
1193                } else {
1194                    format!("{}:*", self.as_ref().name())
1195                },
1196                if let Some(destpadname) = destpadname {
1197                    format!("{}:{}", dest.as_ref().name(), destpadname)
1198                } else {
1199                    format!("{}:*", dest.as_ref().name())
1200                },
1201                flags,
1202            )
1203        }
1204    }
1205}
1206
1207impl<O: IsA<Element>> ElementExtManual for O {}
1208
1209pub unsafe trait ElementClassExt {
1210    /// Get metadata with `key` in `self`.
1211    /// ## `key`
1212    /// the key to get
1213    ///
1214    /// # Returns
1215    ///
1216    /// the metadata for `key`.
1217    #[doc(alias = "get_metadata")]
1218    #[doc(alias = "gst_element_class_get_metadata")]
1219    fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
1220        unsafe {
1221            let klass = self as *const _ as *const ffi::GstElementClass;
1222
1223            let ptr = ffi::gst_element_class_get_metadata(klass as *mut _, key.to_glib_none().0);
1224
1225            if ptr.is_null() {
1226                None
1227            } else {
1228                Some(CStr::from_ptr(ptr).to_str().unwrap())
1229            }
1230        }
1231    }
1232
1233    /// Retrieves a padtemplate from `self` with the given name.
1234    /// > If you use this function in the GInstanceInitFunc of an object class
1235    /// > that has subclasses, make sure to pass the g_class parameter of the
1236    /// > GInstanceInitFunc here.
1237    /// ## `name`
1238    /// the name of the [`PadTemplate`][crate::PadTemplate] to get.
1239    ///
1240    /// # Returns
1241    ///
1242    /// the [`PadTemplate`][crate::PadTemplate] with the
1243    ///  given name, or [`None`] if none was found. No unreferencing is
1244    ///  necessary.
1245    #[doc(alias = "get_pad_template")]
1246    #[doc(alias = "gst_element_class_get_pad_template")]
1247    fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1248        unsafe {
1249            let klass = self as *const _ as *const ffi::GstElementClass;
1250
1251            from_glib_none(ffi::gst_element_class_get_pad_template(
1252                klass as *mut _,
1253                name.to_glib_none().0,
1254            ))
1255        }
1256    }
1257
1258    /// Retrieves a list of the pad templates associated with `self`. The
1259    /// list must not be modified by the calling code.
1260    /// > If you use this function in the GInstanceInitFunc of an object class
1261    /// > that has subclasses, make sure to pass the g_class parameter of the
1262    /// > GInstanceInitFunc here.
1263    ///
1264    /// # Returns
1265    ///
1266    /// the `GList` of
1267    ///  pad templates.
1268    #[doc(alias = "get_pad_template_list")]
1269    #[doc(alias = "gst_element_class_get_pad_template_list")]
1270    fn pad_template_list(&self) -> glib::List<PadTemplate> {
1271        unsafe {
1272            let klass = self as *const _ as *const ffi::GstElementClass;
1273
1274            glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1275                klass as *mut _,
1276            ))
1277        }
1278    }
1279}
1280
1281unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1282
1283/// Name and contact details of the author(s). Use \n to separate
1284/// multiple author details.
1285/// E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
1286#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1287pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1288    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1289/// Sentence describing the purpose of the element.
1290/// E.g: "Write stream to a file"
1291#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1292pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1293    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1294/// Set uri pointing to user documentation. Applications can use this to show
1295/// help for e.g. effects to users.
1296#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1297pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1298    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1299/// Elements that bridge to certain other products can include an icon of that
1300/// used product. Application can show the icon in menus/selectors to help
1301/// identifying specific elements.
1302#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1303pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1304    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1305/// String describing the type of element, as an unordered list
1306/// separated with slashes ('/'). See draft-klass.txt of the design docs
1307/// for more details and common types. E.g: "Sink/File"
1308#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1309pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1310    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1311/// The long English name of the element. E.g. "File Sink"
1312#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1313pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1314    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1315
1316#[doc(alias = "GST_ELEMENT_ERROR")]
1317#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1318#[macro_export]
1319macro_rules! element_error(
1320    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1321        use $crate::prelude::ElementExtManual;
1322        $obj.message_full(
1323            $crate::ElementMessageType::Error,
1324            $err,
1325            Some(&format!($($msg)*)),
1326            Some(&format!($($debug)*)),
1327            file!(),
1328            $crate::glib::function_name!(),
1329            line!(),
1330        );
1331    }};
1332    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1333        use $crate::prelude::ElementExtManual;
1334        $obj.message_full(
1335            $crate::ElementMessageType::Error,
1336            $err,
1337            Some(&format!($($msg)*)),
1338            None,
1339            file!(),
1340            $crate::glib::function_name!(),
1341            line!(),
1342        );
1343    }};
1344    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1345        use $crate::prelude::ElementExtManual;
1346        $obj.message_full(
1347            $crate::ElementMessageType::Error,
1348            $err,
1349            None,
1350            Some(&format!($($debug)*)),
1351            file!(),
1352            $crate::glib::function_name!(),
1353            line!(),
1354        );
1355    }};
1356
1357    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1358        use $crate::prelude::ElementExtManual;
1359        $obj.message_full_with_details(
1360            $crate::ElementMessageType::Error,
1361            $err,
1362            Some(&format!($($msg)*)),
1363            Some(&format!($($debug)*)),
1364            file!(),
1365            $crate::glib::function_name!(),
1366            line!(),
1367            $details,
1368        );
1369    }};
1370    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1371        use $crate::prelude::ElementExtManual;
1372        $obj.message_full_with_details(
1373            $crate::ElementMessageType::Error,
1374            $err,
1375            Some(&format!($($msg)*)),
1376            None,
1377            file!(),
1378            $crate::glib::function_name!(),
1379            line!(),
1380            $details,
1381        );
1382    }};
1383    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1384        use $crate::prelude::ElementExtManual;
1385        $obj.message_full_with_details(
1386            $crate::ElementMessageType::Error,
1387            $err,
1388            None,
1389            Some(&format!($($debug)*)),
1390            file!(),
1391            $crate::glib::function_name!(),
1392            line!(),
1393            $details,
1394        );
1395    }};
1396);
1397
1398#[doc(alias = "GST_ELEMENT_WARNING")]
1399#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1400#[macro_export]
1401macro_rules! element_warning(
1402    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1403        use $crate::prelude::ElementExtManual;
1404        $obj.message_full(
1405            $crate::ElementMessageType::Warning,
1406            $err,
1407            Some(&format!($($msg)*)),
1408            Some(&format!($($debug)*)),
1409            file!(),
1410            $crate::glib::function_name!(),
1411            line!(),
1412        );
1413    }};
1414    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1415        use $crate::prelude::ElementExtManual;
1416        $obj.message_full(
1417            $crate::ElementMessageType::Warning,
1418            $err,
1419            Some(&format!($($msg)*)),
1420            None,
1421            file!(),
1422            $crate::glib::function_name!(),
1423            line!(),
1424        );
1425    }};
1426    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1427        use $crate::prelude::ElementExtManual;
1428        $obj.message_full(
1429            $crate::ElementMessageType::Warning,
1430            $err,
1431            None,
1432            Some(&format!($($debug)*)),
1433            file!(),
1434            $crate::glib::function_name!(),
1435            line!(),
1436        );
1437    }};
1438
1439    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1440        use $crate::prelude::ElementExtManual;
1441        $obj.message_full_with_details(
1442            $crate::ElementMessageType::Warning,
1443            $err,
1444            Some(&format!($($msg)*)),
1445            Some(&format!($($debug)*)),
1446            file!(),
1447            $crate::glib::function_name!(),
1448            line!(),
1449            $details,
1450        );
1451    }};
1452    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1453        use $crate::prelude::ElementExtManual;
1454        $obj.message_full_with_details(
1455            $crate::ElementMessageType::Warning,
1456            $err,
1457            Some(&format!($($msg)*)),
1458            None,
1459            file!(),
1460            $crate::glib::function_name!(),
1461            line!(),
1462            $details,
1463        );
1464    }};
1465    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1466        use $crate::prelude::ElementExtManual;
1467        $obj.message_full_with_details(
1468            $crate::ElementMessageType::Warning,
1469            $err,
1470            None,
1471            Some(&format!($($debug)*)),
1472            file!(),
1473            $crate::glib::function_name!(),
1474            line!(),
1475            $details,
1476        );
1477    }};
1478);
1479
1480#[doc(alias = "GST_ELEMENT_INFO")]
1481#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1482#[macro_export]
1483macro_rules! element_info(
1484    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1485        use $crate::prelude::ElementExtManual;
1486        $obj.message_full(
1487            $crate::ElementMessageType::Info,
1488            $err,
1489            Some(&format!($($msg)*)),
1490            Some(&format!($($debug)*)),
1491            file!(),
1492            $crate::glib::function_name!(),
1493            line!(),
1494        );
1495    }};
1496    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1497        use $crate::prelude::ElementExtManual;
1498        $obj.message_full(
1499            $crate::ElementMessageType::Info,
1500            $err,
1501            Some(&format!($($msg)*)),
1502            None,
1503            file!(),
1504            $crate::glib::function_name!(),
1505            line!(),
1506        );
1507    }};
1508    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1509        use $crate::prelude::ElementExtManual;
1510        $obj.message_full(
1511            $crate::ElementMessageType::Info,
1512            $err,
1513            None,
1514            Some(&format!($($debug)*)),
1515            file!(),
1516            $crate::glib::function_name!(),
1517            line!(),
1518        );
1519    }};
1520
1521    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1522        use $crate::prelude::ElementExtManual;
1523        $obj.message_full_with_details(
1524            $crate::ElementMessageType::Info,
1525            $err,
1526            Some(&format!($($msg)*)),
1527            Some(&format!($($debug)*)),
1528            file!(),
1529            $crate::glib::function_name!(),
1530            line!(),
1531            $details,
1532        );
1533    }};
1534    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1535        use $crate::prelude::ElementExtManual;
1536        $obj.message_full_with_details(
1537            $crate::ElementMessageType::Info,
1538            $err,
1539            Some(&format!($($msg)*)),
1540            None,
1541            file!(),
1542            $crate::glib::function_name!(),
1543            line!(),
1544            $details,
1545        );
1546    }};
1547    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1548        use $crate::prelude::ElementExtManual;
1549        $obj.message_full_with_details(
1550            $crate::ElementMessageType::Info,
1551            $err,
1552            None,
1553            Some(&format!($($debug)*)),
1554            file!(),
1555            $crate::glib::function_name!(),
1556            line!(),
1557            $details,
1558        );
1559    }};
1560);
1561
1562#[doc(alias = "GST_ELEMENT_ERROR")]
1563#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1564#[macro_export]
1565macro_rules! element_imp_error(
1566    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1567        let obj = $imp.obj();
1568        $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1569    }};
1570    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1571        let obj = $imp.obj();
1572        $crate::element_error!(obj, $err, ($($msg)*));
1573    }};
1574    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1575        let obj = $imp.obj();
1576        $crate::element_error!(obj, $err, [$($debug)*]);
1577    }};
1578
1579    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1580        let obj = $imp.obj();
1581        $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1582    }};
1583    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1584        let obj = $imp.obj();
1585        $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1586    }};
1587    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1588        let obj = $imp.obj();
1589        $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1590    }};
1591);
1592
1593#[doc(alias = "GST_ELEMENT_WARNING")]
1594#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1595#[macro_export]
1596macro_rules! element_imp_warning(
1597    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1598        let obj = $imp.obj();
1599        $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1600    }};
1601    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1602        let obj = $imp.obj();
1603        $crate::element_warning!(obj, $err, ($($msg)*));
1604    }};
1605    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1606        let obj = $imp.obj();
1607        $crate::element_warning!(obj, $err, [$($debug)*]);
1608    }};
1609
1610    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1611        let obj = $imp.obj();
1612        $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1613    }};
1614    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1615        let obj = $imp.obj();
1616        $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1617    }};
1618    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1619        let obj = $imp.obj();
1620        $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1621    }};
1622);
1623
1624#[doc(alias = "GST_ELEMENT_INFO")]
1625#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1626#[macro_export]
1627macro_rules! element_imp_info(
1628    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1629        let obj = $imp.obj();
1630        $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1631    }};
1632    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1633        let obj = $imp.obj();
1634        $crate::element_info!(obj, $err, ($($msg)*));
1635    }};
1636    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1637        let obj = $imp.obj();
1638        $crate::element_info!(obj, $err, [$($debug)*]);
1639    }};
1640
1641    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1642        let obj = $imp.obj();
1643        $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1644    }};
1645    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1646        let obj = $imp.obj();
1647        $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1648    }};
1649    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1650        let obj = $imp.obj();
1651        $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1652    }};
1653);
1654
1655#[cfg(test)]
1656mod tests {
1657    use std::sync::mpsc::channel;
1658
1659    use glib::GString;
1660
1661    use super::*;
1662
1663    #[test]
1664    fn test_get_pads() {
1665        crate::init().unwrap();
1666
1667        let identity = crate::ElementFactory::make("identity").build().unwrap();
1668
1669        let mut pad_names = identity
1670            .pads()
1671            .iter()
1672            .map(|p| p.name())
1673            .collect::<Vec<GString>>();
1674        pad_names.sort();
1675        assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1676
1677        let mut pad_names = identity
1678            .sink_pads()
1679            .iter()
1680            .map(|p| p.name())
1681            .collect::<Vec<GString>>();
1682        pad_names.sort();
1683        assert_eq!(pad_names, vec![String::from("sink")]);
1684
1685        let mut pad_names = identity
1686            .src_pads()
1687            .iter()
1688            .map(|p| p.name())
1689            .collect::<Vec<GString>>();
1690        pad_names.sort();
1691        assert_eq!(pad_names, vec![String::from("src")]);
1692    }
1693
1694    #[test]
1695    fn test_foreach_pad() {
1696        crate::init().unwrap();
1697
1698        let identity = crate::ElementFactory::make("identity").build().unwrap();
1699
1700        let mut pad_names = Vec::new();
1701        identity.foreach_pad(|_element, pad| {
1702            pad_names.push(pad.name());
1703
1704            true
1705        });
1706        pad_names.sort();
1707        assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1708    }
1709
1710    #[test]
1711    fn test_call_async() {
1712        crate::init().unwrap();
1713
1714        let identity = crate::ElementFactory::make("identity").build().unwrap();
1715        let (sender, receiver) = channel();
1716
1717        identity.call_async(move |_| {
1718            sender.send(()).unwrap();
1719        });
1720
1721        assert_eq!(receiver.recv(), Ok(()));
1722    }
1723
1724    #[test]
1725    fn test_element_error() {
1726        crate::init().unwrap();
1727
1728        let identity = crate::ElementFactory::make("identity").build().unwrap();
1729
1730        crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1731        crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1732        crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1733
1734        // We define a new variable for each call so there would be a compiler warning if the
1735        // string formatting did not actually use it.
1736        let x = 123i32;
1737        crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1738        let x = 123i32;
1739        crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1740        let x = 123i32;
1741        crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1742    }
1743}