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        if let Some(clock) = self.clock() {
1050            clock.time()
1051        } else {
1052            crate::ClockTime::NONE
1053        }
1054    }
1055
1056    /// The name of this function is confusing to people learning GStreamer.
1057    /// [`request_pad_simple()`][Self::request_pad_simple()] aims at making it more explicit it is
1058    /// a simplified [`ElementExt::request_pad()`][crate::prelude::ElementExt::request_pad()].
1059    ///
1060    /// # Deprecated since 1.20
1061    ///
1062    /// Prefer using [`request_pad_simple()`][Self::request_pad_simple()] which
1063    /// provides the exact same functionality.
1064    /// ## `name`
1065    /// the name of the request [`Pad`][crate::Pad] to retrieve.
1066    ///
1067    /// # Returns
1068    ///
1069    /// requested [`Pad`][crate::Pad] if found,
1070    ///  otherwise [`None`]. Release after usage.
1071    #[doc(alias = "gst_element_get_request_pad")]
1072    #[doc(alias = "get_request_pad")]
1073    #[doc(alias = "gst_element_request_pad_simple")]
1074    fn request_pad_simple(&self, name: &str) -> Option<Pad> {
1075        unsafe {
1076            #[cfg(feature = "v1_20")]
1077            {
1078                from_glib_full(ffi::gst_element_request_pad_simple(
1079                    self.as_ref().to_glib_none().0,
1080                    name.to_glib_none().0,
1081                ))
1082            }
1083            #[cfg(not(feature = "v1_20"))]
1084            {
1085                from_glib_full(ffi::gst_element_get_request_pad(
1086                    self.as_ref().to_glib_none().0,
1087                    name.to_glib_none().0,
1088                ))
1089            }
1090        }
1091    }
1092
1093    /// Links `self` to `dest`. The link must be from source to
1094    /// destination; the other direction will not be tried. The function looks for
1095    /// existing pads that aren't linked yet. It will request new pads if necessary.
1096    /// Such pads need to be released manually when unlinking.
1097    /// If multiple links are possible, only one is established.
1098    ///
1099    /// Make sure you have added your elements to a bin or pipeline with
1100    /// [`GstBinExt::add()`][crate::prelude::GstBinExt::add()] before trying to link them.
1101    /// ## `dest`
1102    /// the [`Element`][crate::Element] containing the destination pad.
1103    ///
1104    /// # Returns
1105    ///
1106    /// [`true`] if the elements could be linked, [`false`] otherwise.
1107    #[doc(alias = "gst_element_link")]
1108    fn link(&self, dest: &impl IsA<Element>) -> Result<(), glib::error::BoolError> {
1109        unsafe {
1110            glib::result_from_gboolean!(
1111                ffi::gst_element_link(
1112                    self.as_ref().to_glib_none().0,
1113                    dest.as_ref().to_glib_none().0
1114                ),
1115                "Failed to link elements '{}' and '{}'",
1116                self.as_ref().name(),
1117                dest.as_ref().name(),
1118            )
1119        }
1120    }
1121
1122    /// Links `self` to `dest` using the given caps as filtercaps.
1123    /// The link must be from source to
1124    /// destination; the other direction will not be tried. The function looks for
1125    /// existing pads that aren't linked yet. It will request new pads if necessary.
1126    /// If multiple links are possible, only one is established.
1127    ///
1128    /// Make sure you have added your elements to a bin or pipeline with
1129    /// [`GstBinExt::add()`][crate::prelude::GstBinExt::add()] before trying to link them.
1130    /// ## `dest`
1131    /// the [`Element`][crate::Element] containing the destination pad.
1132    /// ## `filter`
1133    /// the [`Caps`][crate::Caps] to filter the link,
1134    ///  or [`None`] for no filter.
1135    ///
1136    /// # Returns
1137    ///
1138    /// [`true`] if the pads could be linked, [`false`] otherwise.
1139    #[doc(alias = "gst_element_link_filtered")]
1140    fn link_filtered(
1141        &self,
1142        dest: &impl IsA<Element>,
1143        filter: &crate::Caps,
1144    ) -> Result<(), glib::error::BoolError> {
1145        unsafe {
1146            glib::result_from_gboolean!(
1147                ffi::gst_element_link_filtered(
1148                    self.as_ref().to_glib_none().0,
1149                    dest.as_ref().to_glib_none().0,
1150                    filter.to_glib_none().0
1151                ),
1152                "Failed to link elements '{}' and '{}' with filter '{:?}'",
1153                self.as_ref().name(),
1154                dest.as_ref().name(),
1155                filter,
1156            )
1157        }
1158    }
1159
1160    /// Links the two named pads of the source and destination elements.
1161    /// Side effect is that if one of the pads has no parent, it becomes a
1162    /// child of the parent of the other element. If they have different
1163    /// parents, the link fails.
1164    /// ## `srcpadname`
1165    /// the name of the [`Pad`][crate::Pad] in source element
1166    ///  or [`None`] for any pad.
1167    /// ## `dest`
1168    /// the [`Element`][crate::Element] containing the destination pad.
1169    /// ## `destpadname`
1170    /// the name of the [`Pad`][crate::Pad] in destination element,
1171    /// or [`None`] for any pad.
1172    ///
1173    /// # Returns
1174    ///
1175    /// [`true`] if the pads could be linked, [`false`] otherwise.
1176    #[doc(alias = "gst_element_link_pads")]
1177    fn link_pads(
1178        &self,
1179        srcpadname: Option<&str>,
1180        dest: &impl IsA<Element>,
1181        destpadname: Option<&str>,
1182    ) -> Result<(), glib::error::BoolError> {
1183        unsafe {
1184            glib::result_from_gboolean!(
1185                ffi::gst_element_link_pads(
1186                    self.as_ref().to_glib_none().0,
1187                    srcpadname.to_glib_none().0,
1188                    dest.as_ref().to_glib_none().0,
1189                    destpadname.to_glib_none().0
1190                ),
1191                "Failed to link pads '{}' and '{}'",
1192                if let Some(srcpadname) = srcpadname {
1193                    format!("{}:{}", self.as_ref().name(), srcpadname)
1194                } else {
1195                    format!("{}:*", self.as_ref().name())
1196                },
1197                if let Some(destpadname) = destpadname {
1198                    format!("{}:{}", dest.as_ref().name(), destpadname)
1199                } else {
1200                    format!("{}:*", dest.as_ref().name())
1201                },
1202            )
1203        }
1204    }
1205
1206    /// Links the two named pads of the source and destination elements. Side effect
1207    /// is that if one of the pads has no parent, it becomes a child of the parent of
1208    /// the other element. If they have different parents, the link fails. If `caps`
1209    /// is not [`None`], makes sure that the caps of the link is a subset of `caps`.
1210    /// ## `srcpadname`
1211    /// the name of the [`Pad`][crate::Pad] in source element
1212    ///  or [`None`] for any pad.
1213    /// ## `dest`
1214    /// the [`Element`][crate::Element] containing the destination pad.
1215    /// ## `destpadname`
1216    /// the name of the [`Pad`][crate::Pad] in destination element
1217    ///  or [`None`] for any pad.
1218    /// ## `filter`
1219    /// the [`Caps`][crate::Caps] to filter the link,
1220    ///  or [`None`] for no filter.
1221    ///
1222    /// # Returns
1223    ///
1224    /// [`true`] if the pads could be linked, [`false`] otherwise.
1225    #[doc(alias = "gst_element_link_pads_filtered")]
1226    fn link_pads_filtered(
1227        &self,
1228        srcpadname: Option<&str>,
1229        dest: &impl IsA<Element>,
1230        destpadname: Option<&str>,
1231        filter: &crate::Caps,
1232    ) -> Result<(), glib::error::BoolError> {
1233        unsafe {
1234            glib::result_from_gboolean!(
1235                ffi::gst_element_link_pads_filtered(
1236                    self.as_ref().to_glib_none().0,
1237                    srcpadname.to_glib_none().0,
1238                    dest.as_ref().to_glib_none().0,
1239                    destpadname.to_glib_none().0,
1240                    filter.to_glib_none().0
1241                ),
1242                "Failed to link pads '{}' and '{}' with filter '{:?}'",
1243                if let Some(srcpadname) = srcpadname {
1244                    format!("{}:{}", self.as_ref().name(), srcpadname)
1245                } else {
1246                    format!("{}:*", self.as_ref().name())
1247                },
1248                if let Some(destpadname) = destpadname {
1249                    format!("{}:{}", dest.as_ref().name(), destpadname)
1250                } else {
1251                    format!("{}:*", dest.as_ref().name())
1252                },
1253                filter,
1254            )
1255        }
1256    }
1257
1258    /// Links the two named pads of the source and destination elements.
1259    /// Side effect is that if one of the pads has no parent, it becomes a
1260    /// child of the parent of the other element. If they have different
1261    /// parents, the link fails.
1262    ///
1263    /// Calling [`link_pads_full()`][Self::link_pads_full()] with `flags` == [`PadLinkCheck::DEFAULT`][crate::PadLinkCheck::DEFAULT]
1264    /// is the same as calling [`link_pads()`][Self::link_pads()] and the recommended way of
1265    /// linking pads with safety checks applied.
1266    ///
1267    /// This is a convenience function for [`PadExt::link_full()`][crate::prelude::PadExt::link_full()].
1268    /// ## `srcpadname`
1269    /// the name of the [`Pad`][crate::Pad] in source element
1270    ///  or [`None`] for any pad.
1271    /// ## `dest`
1272    /// the [`Element`][crate::Element] containing the destination pad.
1273    /// ## `destpadname`
1274    /// the name of the [`Pad`][crate::Pad] in destination element,
1275    /// or [`None`] for any pad.
1276    /// ## `flags`
1277    /// the [`PadLinkCheck`][crate::PadLinkCheck] to be performed when linking pads.
1278    ///
1279    /// # Returns
1280    ///
1281    /// [`true`] if the pads could be linked, [`false`] otherwise.
1282    #[doc(alias = "gst_element_link_pads_full")]
1283    fn link_pads_full(
1284        &self,
1285        srcpadname: Option<&str>,
1286        dest: &impl IsA<Element>,
1287        destpadname: Option<&str>,
1288        flags: crate::PadLinkCheck,
1289    ) -> Result<(), glib::error::BoolError> {
1290        unsafe {
1291            glib::result_from_gboolean!(
1292                ffi::gst_element_link_pads_full(
1293                    self.as_ref().to_glib_none().0,
1294                    srcpadname.to_glib_none().0,
1295                    dest.as_ref().to_glib_none().0,
1296                    destpadname.to_glib_none().0,
1297                    flags.into_glib()
1298                ),
1299                "Failed to link pads '{}' and '{}' with flags '{:?}'",
1300                if let Some(srcpadname) = srcpadname {
1301                    format!("{}:{}", self.as_ref().name(), srcpadname)
1302                } else {
1303                    format!("{}:*", self.as_ref().name())
1304                },
1305                if let Some(destpadname) = destpadname {
1306                    format!("{}:{}", dest.as_ref().name(), destpadname)
1307                } else {
1308                    format!("{}:*", dest.as_ref().name())
1309                },
1310                flags,
1311            )
1312        }
1313    }
1314}
1315
1316impl<O: IsA<Element>> ElementExtManual for O {}
1317
1318pub unsafe trait ElementClassExt {
1319    /// Get metadata with `key` in `self`.
1320    /// ## `key`
1321    /// the key to get
1322    ///
1323    /// # Returns
1324    ///
1325    /// the metadata for `key`.
1326    #[doc(alias = "get_metadata")]
1327    #[doc(alias = "gst_element_class_get_metadata")]
1328    fn metadata<'a>(&self, key: &str) -> Option<&'a str> {
1329        unsafe {
1330            let klass = self as *const _ as *const ffi::GstElementClass;
1331
1332            let ptr = ffi::gst_element_class_get_metadata(klass as *mut _, key.to_glib_none().0);
1333
1334            if ptr.is_null() {
1335                None
1336            } else {
1337                Some(CStr::from_ptr(ptr).to_str().unwrap())
1338            }
1339        }
1340    }
1341
1342    /// Retrieves a padtemplate from `self` with the given name.
1343    /// > If you use this function in the GInstanceInitFunc of an object class
1344    /// > that has subclasses, make sure to pass the g_class parameter of the
1345    /// > GInstanceInitFunc here.
1346    /// ## `name`
1347    /// the name of the [`PadTemplate`][crate::PadTemplate] to get.
1348    ///
1349    /// # Returns
1350    ///
1351    /// the [`PadTemplate`][crate::PadTemplate] with the
1352    ///  given name, or [`None`] if none was found. No unreferencing is
1353    ///  necessary.
1354    #[doc(alias = "get_pad_template")]
1355    #[doc(alias = "gst_element_class_get_pad_template")]
1356    fn pad_template(&self, name: &str) -> Option<PadTemplate> {
1357        unsafe {
1358            let klass = self as *const _ as *const ffi::GstElementClass;
1359
1360            from_glib_none(ffi::gst_element_class_get_pad_template(
1361                klass as *mut _,
1362                name.to_glib_none().0,
1363            ))
1364        }
1365    }
1366
1367    /// Retrieves a list of the pad templates associated with `self`. The
1368    /// list must not be modified by the calling code.
1369    /// > If you use this function in the GInstanceInitFunc of an object class
1370    /// > that has subclasses, make sure to pass the g_class parameter of the
1371    /// > GInstanceInitFunc here.
1372    ///
1373    /// # Returns
1374    ///
1375    /// the `GList` of
1376    ///  pad templates.
1377    #[doc(alias = "get_pad_template_list")]
1378    #[doc(alias = "gst_element_class_get_pad_template_list")]
1379    fn pad_template_list(&self) -> glib::List<PadTemplate> {
1380        unsafe {
1381            let klass = self as *const _ as *const ffi::GstElementClass;
1382
1383            glib::List::from_glib_none(ffi::gst_element_class_get_pad_template_list(
1384                klass as *mut _,
1385            ))
1386        }
1387    }
1388}
1389
1390unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
1391
1392/// Name and contact details of the author(s). Use \n to separate
1393/// multiple author details.
1394/// E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
1395#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
1396pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
1397    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
1398/// Sentence describing the purpose of the element.
1399/// E.g: "Write stream to a file"
1400#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
1401pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
1402    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
1403/// Set uri pointing to user documentation. Applications can use this to show
1404/// help for e.g. effects to users.
1405#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
1406pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
1407    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
1408/// Elements that bridge to certain other products can include an icon of that
1409/// used product. Application can show the icon in menus/selectors to help
1410/// identifying specific elements.
1411#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
1412pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
1413    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
1414/// String describing the type of element, as an unordered list
1415/// separated with slashes ('/'). See draft-klass.txt of the design docs
1416/// for more details and common types. E.g: "Sink/File"
1417#[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
1418pub static ELEMENT_METADATA_KLASS: &glib::GStr =
1419    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
1420/// The long English name of the element. E.g. "File Sink"
1421#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
1422pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
1423    unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
1424
1425#[doc(alias = "GST_ELEMENT_ERROR")]
1426#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1427#[macro_export]
1428macro_rules! element_error(
1429    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1430        use $crate::prelude::ElementExtManual;
1431        $obj.message_full(
1432            $crate::ElementMessageType::Error,
1433            $err,
1434            Some(&format!($($msg)*)),
1435            Some(&format!($($debug)*)),
1436            file!(),
1437            $crate::glib::function_name!(),
1438            line!(),
1439        );
1440    }};
1441    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1442        use $crate::prelude::ElementExtManual;
1443        $obj.message_full(
1444            $crate::ElementMessageType::Error,
1445            $err,
1446            Some(&format!($($msg)*)),
1447            None,
1448            file!(),
1449            $crate::glib::function_name!(),
1450            line!(),
1451        );
1452    }};
1453    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1454        use $crate::prelude::ElementExtManual;
1455        $obj.message_full(
1456            $crate::ElementMessageType::Error,
1457            $err,
1458            None,
1459            Some(&format!($($debug)*)),
1460            file!(),
1461            $crate::glib::function_name!(),
1462            line!(),
1463        );
1464    }};
1465
1466    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1467        use $crate::prelude::ElementExtManual;
1468        $obj.message_full_with_details(
1469            $crate::ElementMessageType::Error,
1470            $err,
1471            Some(&format!($($msg)*)),
1472            Some(&format!($($debug)*)),
1473            file!(),
1474            $crate::glib::function_name!(),
1475            line!(),
1476            $details,
1477        );
1478    }};
1479    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1480        use $crate::prelude::ElementExtManual;
1481        $obj.message_full_with_details(
1482            $crate::ElementMessageType::Error,
1483            $err,
1484            Some(&format!($($msg)*)),
1485            None,
1486            file!(),
1487            $crate::glib::function_name!(),
1488            line!(),
1489            $details,
1490        );
1491    }};
1492    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1493        use $crate::prelude::ElementExtManual;
1494        $obj.message_full_with_details(
1495            $crate::ElementMessageType::Error,
1496            $err,
1497            None,
1498            Some(&format!($($debug)*)),
1499            file!(),
1500            $crate::glib::function_name!(),
1501            line!(),
1502            $details,
1503        );
1504    }};
1505);
1506
1507#[doc(alias = "GST_ELEMENT_WARNING")]
1508#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1509#[macro_export]
1510macro_rules! element_warning(
1511    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1512        use $crate::prelude::ElementExtManual;
1513        $obj.message_full(
1514            $crate::ElementMessageType::Warning,
1515            $err,
1516            Some(&format!($($msg)*)),
1517            Some(&format!($($debug)*)),
1518            file!(),
1519            $crate::glib::function_name!(),
1520            line!(),
1521        );
1522    }};
1523    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1524        use $crate::prelude::ElementExtManual;
1525        $obj.message_full(
1526            $crate::ElementMessageType::Warning,
1527            $err,
1528            Some(&format!($($msg)*)),
1529            None,
1530            file!(),
1531            $crate::glib::function_name!(),
1532            line!(),
1533        );
1534    }};
1535    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1536        use $crate::prelude::ElementExtManual;
1537        $obj.message_full(
1538            $crate::ElementMessageType::Warning,
1539            $err,
1540            None,
1541            Some(&format!($($debug)*)),
1542            file!(),
1543            $crate::glib::function_name!(),
1544            line!(),
1545        );
1546    }};
1547
1548    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1549        use $crate::prelude::ElementExtManual;
1550        $obj.message_full_with_details(
1551            $crate::ElementMessageType::Warning,
1552            $err,
1553            Some(&format!($($msg)*)),
1554            Some(&format!($($debug)*)),
1555            file!(),
1556            $crate::glib::function_name!(),
1557            line!(),
1558            $details,
1559        );
1560    }};
1561    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1562        use $crate::prelude::ElementExtManual;
1563        $obj.message_full_with_details(
1564            $crate::ElementMessageType::Warning,
1565            $err,
1566            Some(&format!($($msg)*)),
1567            None,
1568            file!(),
1569            $crate::glib::function_name!(),
1570            line!(),
1571            $details,
1572        );
1573    }};
1574    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1575        use $crate::prelude::ElementExtManual;
1576        $obj.message_full_with_details(
1577            $crate::ElementMessageType::Warning,
1578            $err,
1579            None,
1580            Some(&format!($($debug)*)),
1581            file!(),
1582            $crate::glib::function_name!(),
1583            line!(),
1584            $details,
1585        );
1586    }};
1587);
1588
1589#[doc(alias = "GST_ELEMENT_INFO")]
1590#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1591#[macro_export]
1592macro_rules! element_info(
1593    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1594        use $crate::prelude::ElementExtManual;
1595        $obj.message_full(
1596            $crate::ElementMessageType::Info,
1597            $err,
1598            Some(&format!($($msg)*)),
1599            Some(&format!($($debug)*)),
1600            file!(),
1601            $crate::glib::function_name!(),
1602            line!(),
1603        );
1604    }};
1605    ($obj:expr, $err:expr, ($($msg:tt)*)) => { {
1606        use $crate::prelude::ElementExtManual;
1607        $obj.message_full(
1608            $crate::ElementMessageType::Info,
1609            $err,
1610            Some(&format!($($msg)*)),
1611            None,
1612            file!(),
1613            $crate::glib::function_name!(),
1614            line!(),
1615        );
1616    }};
1617    ($obj:expr, $err:expr, [$($debug:tt)*]) => { {
1618        use $crate::prelude::ElementExtManual;
1619        $obj.message_full(
1620            $crate::ElementMessageType::Info,
1621            $err,
1622            None,
1623            Some(&format!($($debug)*)),
1624            file!(),
1625            $crate::glib::function_name!(),
1626            line!(),
1627        );
1628    }};
1629
1630    ($obj:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1631        use $crate::prelude::ElementExtManual;
1632        $obj.message_full_with_details(
1633            $crate::ElementMessageType::Info,
1634            $err,
1635            Some(&format!($($msg)*)),
1636            Some(&format!($($debug)*)),
1637            file!(),
1638            $crate::glib::function_name!(),
1639            line!(),
1640            $details,
1641        );
1642    }};
1643    ($obj:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1644        use $crate::prelude::ElementExtManual;
1645        $obj.message_full_with_details(
1646            $crate::ElementMessageType::Info,
1647            $err,
1648            Some(&format!($($msg)*)),
1649            None,
1650            file!(),
1651            $crate::glib::function_name!(),
1652            line!(),
1653            $details,
1654        );
1655    }};
1656    ($obj:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1657        use $crate::prelude::ElementExtManual;
1658        $obj.message_full_with_details(
1659            $crate::ElementMessageType::Info,
1660            $err,
1661            None,
1662            Some(&format!($($debug)*)),
1663            file!(),
1664            $crate::glib::function_name!(),
1665            line!(),
1666            $details,
1667        );
1668    }};
1669);
1670
1671#[doc(alias = "GST_ELEMENT_ERROR")]
1672#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]
1673#[macro_export]
1674macro_rules! element_imp_error(
1675    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1676        let obj = $imp.obj();
1677        $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*]);
1678    }};
1679    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1680        let obj = $imp.obj();
1681        $crate::element_error!(obj, $err, ($($msg)*));
1682    }};
1683    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1684        let obj = $imp.obj();
1685        $crate::element_error!(obj, $err, [$($debug)*]);
1686    }};
1687
1688    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1689        let obj = $imp.obj();
1690        $crate::element_error!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1691    }};
1692    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1693        let obj = $imp.obj();
1694        $crate::element_error!(obj, $err, ($($msg)*), details: $details);
1695    }};
1696    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1697        let obj = $imp.obj();
1698        $crate::element_error!(obj, $err, [$($debug)*], details: $details);
1699    }};
1700);
1701
1702#[doc(alias = "GST_ELEMENT_WARNING")]
1703#[doc(alias = "GST_ELEMENT_WARNING_WITH_DETAILS")]
1704#[macro_export]
1705macro_rules! element_imp_warning(
1706    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1707        let obj = $imp.obj();
1708        $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*]);
1709    }};
1710    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1711        let obj = $imp.obj();
1712        $crate::element_warning!(obj, $err, ($($msg)*));
1713    }};
1714    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1715        let obj = $imp.obj();
1716        $crate::element_warning!(obj, $err, [$($debug)*]);
1717    }};
1718
1719    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1720        let obj = $imp.obj();
1721        $crate::element_warning!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1722    }};
1723    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1724        let obj = $imp.obj();
1725        $crate::element_warning!(obj, $err, ($($msg)*), details: $details);
1726    }};
1727    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1728        let obj = $imp.obj();
1729        $crate::element_warning!(obj, $err, [$($debug)*], details: $details);
1730    }};
1731);
1732
1733#[doc(alias = "GST_ELEMENT_INFO")]
1734#[doc(alias = "GST_ELEMENT_INFO_WITH_DETAILS")]
1735#[macro_export]
1736macro_rules! element_imp_info(
1737    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*]) => { {
1738        let obj = $imp.obj();
1739        $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*]);
1740    }};
1741    ($imp:expr, $err:expr, ($($msg:tt)*)) => { {
1742        let obj = $imp.obj();
1743        $crate::element_info!(obj, $err, ($($msg)*));
1744    }};
1745    ($imp:expr, $err:expr, [$($debug:tt)*]) => { {
1746        let obj = $imp.obj();
1747        $crate::element_info!(obj, $err, [$($debug)*]);
1748    }};
1749
1750    ($imp:expr, $err:expr, ($($msg:tt)*), [$($debug:tt)*], details: $details:expr) => { {
1751        let obj = $imp.obj();
1752        $crate::element_info!(obj, $err, ($($msg)*), [$($debug)*], details: $details);
1753    }};
1754    ($imp:expr, $err:expr, ($($msg:tt)*), details: $details:expr) => { {
1755        let obj = $imp.obj();
1756        $crate::element_info!(obj, $err, ($($msg)*), details: $details);
1757    }};
1758    ($imp:expr, $err:expr, [$($debug:tt)*], details: $details:expr) => { {
1759        let obj = $imp.obj();
1760        $crate::element_info!(obj, $err, [$($debug)*], details: $details);
1761    }};
1762);
1763
1764#[cfg(test)]
1765mod tests {
1766    use std::sync::mpsc::channel;
1767
1768    use glib::GString;
1769
1770    use super::*;
1771
1772    #[test]
1773    fn test_get_pads() {
1774        crate::init().unwrap();
1775
1776        let identity = crate::ElementFactory::make("identity").build().unwrap();
1777
1778        let mut pad_names = identity
1779            .pads()
1780            .iter()
1781            .map(|p| p.name())
1782            .collect::<Vec<GString>>();
1783        pad_names.sort();
1784        assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1785
1786        let mut pad_names = identity
1787            .sink_pads()
1788            .iter()
1789            .map(|p| p.name())
1790            .collect::<Vec<GString>>();
1791        pad_names.sort();
1792        assert_eq!(pad_names, vec![String::from("sink")]);
1793
1794        let mut pad_names = identity
1795            .src_pads()
1796            .iter()
1797            .map(|p| p.name())
1798            .collect::<Vec<GString>>();
1799        pad_names.sort();
1800        assert_eq!(pad_names, vec![String::from("src")]);
1801    }
1802
1803    #[test]
1804    fn test_foreach_pad() {
1805        crate::init().unwrap();
1806
1807        let identity = crate::ElementFactory::make("identity").build().unwrap();
1808
1809        let mut pad_names = Vec::new();
1810        identity.foreach_pad(|_element, pad| {
1811            pad_names.push(pad.name());
1812
1813            ControlFlow::Continue(())
1814        });
1815        pad_names.sort();
1816        assert_eq!(pad_names, vec![String::from("sink"), String::from("src")]);
1817
1818        pad_names.clear();
1819        identity.foreach_sink_pad(|_element, pad| {
1820            pad_names.push(pad.name());
1821
1822            ControlFlow::Continue(())
1823        });
1824        assert_eq!(pad_names, vec![String::from("sink")]);
1825
1826        pad_names.clear();
1827        identity.foreach_src_pad(|_element, pad| {
1828            pad_names.push(pad.name());
1829
1830            ControlFlow::Continue(())
1831        });
1832        assert_eq!(pad_names, vec![String::from("src")]);
1833    }
1834
1835    #[test]
1836    fn test_call_async() {
1837        crate::init().unwrap();
1838
1839        let identity = crate::ElementFactory::make("identity").build().unwrap();
1840        let (sender, receiver) = channel();
1841
1842        identity.call_async(move |_| {
1843            sender.send(()).unwrap();
1844        });
1845
1846        assert_eq!(receiver.recv(), Ok(()));
1847    }
1848
1849    #[test]
1850    fn test_element_error() {
1851        crate::init().unwrap();
1852
1853        let identity = crate::ElementFactory::make("identity").build().unwrap();
1854
1855        crate::element_error!(identity, crate::CoreError::Failed, ("msg"), ["debug"]);
1856        crate::element_error!(identity, crate::CoreError::Failed, ["debug"]);
1857        crate::element_error!(identity, crate::CoreError::Failed, ("msg"));
1858
1859        // We define a new variable for each call so there would be a compiler warning if the
1860        // string formatting did not actually use it.
1861        let x = 123i32;
1862        crate::element_error!(identity, crate::CoreError::Failed, ("msg {x}"), ["debug"]);
1863        let x = 123i32;
1864        crate::element_error!(identity, crate::CoreError::Failed, ["debug {x}"]);
1865        let x = 123i32;
1866        crate::element_error!(identity, crate::CoreError::Failed, ("msg {}", x));
1867    }
1868}