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