Skip to main content

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