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