gstreamer_editing_services/auto/
clip.rs

1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
4// DO NOT EDIT
5
6#[cfg(feature = "v1_18")]
7#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
8use crate::FrameNumber;
9use crate::{
10    ffi, Asset, BaseEffect, Container, Extractable, Layer, MetaContainer, TimelineElement, Track,
11    TrackElement, TrackType,
12};
13use glib::{
14    prelude::*,
15    signal::{connect_raw, SignalHandlerId},
16    translate::*,
17};
18use std::boxed::Box as Box_;
19
20glib::wrapper! {
21    /// [`Clip`][crate::Clip]-s are the core objects of a [`Layer`][crate::Layer]. Each clip may exist in
22    /// a single layer but may control several [`TrackElement`][crate::TrackElement]-s that span
23    /// several [`Track`][crate::Track]-s. A clip will ensure that all its children share the
24    /// same [`start`][struct@crate::TimelineElement#start] and [`duration`][struct@crate::TimelineElement#duration] in
25    /// their tracks, which will match the [`start`][struct@crate::TimelineElement#start] and
26    /// [`duration`][struct@crate::TimelineElement#duration] of the clip itself. Therefore, changing
27    /// the timing of the clip will change the timing of the children, and a
28    /// change in the timing of a child will change the timing of the clip and
29    /// subsequently all its siblings. As such, a clip can be treated as a
30    /// singular object in its layer.
31    ///
32    /// For most uses of a [`Timeline`][crate::Timeline], it is often sufficient to only
33    /// interact with [`Clip`][crate::Clip]-s directly, which will take care of creating and
34    /// organising the elements of the timeline's tracks.
35    ///
36    /// ## Core Children
37    ///
38    /// In more detail, clips will usually have some *core* [`TrackElement`][crate::TrackElement]
39    /// children, which are created by the clip when it is added to a layer in
40    /// a timeline. The type and form of these core children will depend on the
41    /// clip's subclass. You can use [`TrackElementExt::is_core()`][crate::prelude::TrackElementExt::is_core()] to determine
42    /// whether a track element is considered such a core track element. Note,
43    /// if a core track element is part of a clip, it will always be treated as
44    /// a core *child* of the clip. You can connect to the
45    /// [`child-added`][struct@crate::Container#child-added] signal to be notified of their creation.
46    ///
47    /// When a child is added to a clip, the timeline will select its tracks
48    /// using [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Note that it may be the
49    /// case that the child will still have no set [`track`][struct@crate::TrackElement#track]
50    /// after this process. For example, if the timeline does not have a track
51    /// of the corresponding [`track-type`][struct@crate::Track#track-type]. A clip can safely contain
52    /// such children, which may have their track set later, although they will
53    /// play no functioning role in the timeline in the meantime.
54    ///
55    /// If a clip may create track elements with various
56    /// [`track-type`][struct@crate::TrackElement#track-type](s), such as a [`UriClip`][crate::UriClip], but you only
57    /// want it to create a subset of these types, you should set the
58    /// [`supported-formats`][struct@crate::Clip#supported-formats] of the clip to the subset of types. This
59    /// should be done *before* adding the clip to a layer.
60    ///
61    /// If a clip will produce several core elements of the same
62    /// [`track-type`][struct@crate::TrackElement#track-type], you should connect to the timeline's
63    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] signal to coordinate which
64    /// tracks each element should land in. Note, no two core children within a
65    /// clip can share the same [`Track`][crate::Track], so you should not select the same
66    /// track for two separate core children. Provided you stick to this rule,
67    /// it is still safe to select several tracks for the same core child, the
68    /// core child will be copied into the additional tracks. You can manually
69    /// add the child to more tracks later using [`ClipExt::add_child_to_track()`][crate::prelude::ClipExt::add_child_to_track()].
70    /// If you do not wish to use a core child, you can always select no track.
71    ///
72    /// The [`in-point`][struct@crate::TimelineElement#in-point] of the clip will control the
73    /// [`in-point`][struct@crate::TimelineElement#in-point] of its core children to be the same
74    /// value if their [`has-internal-source`][struct@crate::TrackElement#has-internal-source] is set to [`true`].
75    ///
76    /// The [`max-duration`][struct@crate::TimelineElement#max-duration] of the clip is the minimum
77    /// [`max-duration`][struct@crate::TimelineElement#max-duration] of its core children. If you set its
78    /// value to anything other than its current value, this will also set the
79    /// [`max-duration`][struct@crate::TimelineElement#max-duration] of all its core children to the same
80    /// value if their [`has-internal-source`][struct@crate::TrackElement#has-internal-source] is set to [`true`].
81    /// As a special case, whilst a clip does not yet have any core children,
82    /// its [`max-duration`][struct@crate::TimelineElement#max-duration] may be set to indicate what its
83    /// value will be once they are created.
84    ///
85    /// ## Effects
86    ///
87    /// Some subclasses ([`SourceClip`][crate::SourceClip] and [`BaseEffectClip`][crate::BaseEffectClip]) may also allow
88    /// their objects to have additional non-core [`BaseEffect`][crate::BaseEffect]-s elements as
89    /// children. These are additional effects that are applied to the output
90    /// data of the core elements. They can be added to the clip using
91    /// [`ClipExt::add_top_effect()`][crate::prelude::ClipExt::add_top_effect()], which will take care of adding the effect to
92    /// the timeline's tracks. The new effect will be placed between the clip's
93    /// core track elements and its other effects. As such, the newly added
94    /// effect will be applied to any source data **before** the other existing
95    /// effects. You can change the ordering of effects using
96    /// [`ClipExt::set_top_effect_index()`][crate::prelude::ClipExt::set_top_effect_index()].
97    ///
98    /// Tracks are selected for top effects in the same way as core children.
99    /// If you add a top effect to a clip before it is part of a timeline, and
100    /// later add the clip to a timeline, the track selection for the top
101    /// effects will occur just after the track selection for the core
102    /// children. If you add a top effect to a clip that is already part of a
103    /// timeline, the track selection will occur immediately. Since a top
104    /// effect must be applied on top of a core child, if you use
105    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object], you should ensure that the
106    /// added effects are destined for a [`Track`][crate::Track] that already contains a core
107    /// child.
108    ///
109    /// In addition, if the core child in the track is not
110    /// [`active`][struct@crate::TrackElement#active], then neither can any of its effects be
111    /// [`active`][struct@crate::TrackElement#active]. Therefore, if a core child is made in-active,
112    /// all of the additional effects in the same track will also become
113    /// in-active. Similarly, if an effect is set to be active, then the core
114    /// child will also become active, but other effects will be left alone.
115    /// Finally, if an active effect is added to the track of an in-active core
116    /// child, it will become in-active as well. Note, in contrast, setting a
117    /// core child to be active, or an effect to be in-active will *not* change
118    /// the other children in the same track.
119    ///
120    /// ### Time Effects
121    ///
122    /// Some effects also change the timing of their data (see [`BaseEffect`][crate::BaseEffect]
123    /// for what counts as a time effect). Note that a [`BaseEffectClip`][crate::BaseEffectClip] will
124    /// refuse time effects, but a [`Source`][crate::Source] will allow them.
125    ///
126    /// When added to a clip, time effects may adjust the timing of other
127    /// children in the same track. Similarly, when changing the order of
128    /// effects, making them (in)-active, setting their time property values
129    /// or removing time effects. These can cause the [`duration-limit`][struct@crate::Clip#duration-limit]
130    /// to change in value. However, if such an operation would ever cause the
131    /// [`duration`][struct@crate::TimelineElement#duration] to shrink such that a clip's [`Source`][crate::Source] is
132    /// totally overlapped in the timeline, the operation would be prevented.
133    /// Note that the same can happen when adding non-time effects with a
134    /// finite [`max-duration`][struct@crate::TimelineElement#max-duration].
135    ///
136    /// Therefore, when working with time effects, you should -- more so than
137    /// usual -- not assume that setting the properties of the clip's children
138    /// will succeed. In particular, you should use
139    /// [`TimelineElementExt::set_child_property_full()`][crate::prelude::TimelineElementExt::set_child_property_full()] when setting the time
140    /// properties.
141    ///
142    /// If you wish to preserve the *internal* duration of a source in a clip
143    /// during these time effect operations, you can do something like the
144    /// following.
145    ///
146    /// **⚠️ The following code is in c ⚠️**
147    ///
148    /// ```c
149    /// void
150    /// do_time_effect_change (GESClip * clip)
151    /// {
152    ///   GList *tmp, *children;
153    ///   GESTrackElement *source;
154    ///   GstClockTime source_outpoint;
155    ///   GstClockTime new_end;
156    ///   GError *error = NULL;
157    ///
158    ///   // choose some active source in a track to preserve the internal
159    ///   // duration of
160    ///   source = ges_clip_get_track_element (clip, NULL, GES_TYPE_SOURCE);
161    ///
162    ///   // note its current internal end time
163    ///   source_outpoint = ges_clip_get_internal_time_from_timeline_time (
164    ///         clip, source, GES_TIMELINE_ELEMENT_END (clip), NULL);
165    ///
166    ///   // handle invalid out-point
167    ///
168    ///   // stop the children's control sources from clamping when their
169    ///   // out-point changes with a change in the time effects
170    ///   children = ges_container_get_children (GES_CONTAINER (clip), FALSE);
171    ///
172    ///   for (tmp = children; tmp; tmp = tmp->next)
173    ///     ges_track_element_set_auto_clamp_control_sources (tmp->data, FALSE);
174    ///
175    ///   // add time effect, or set their children properties, or move them around
176    ///   ...
177    ///   // user can make sure that if a time effect changes one source, we should
178    ///   // also change the time effect for another source. E.g. if
179    ///   // "GstVideorate::rate" is set to 2.0, we also set "GstPitch::rate" to
180    ///   // 2.0
181    ///
182    ///   // Note the duration of the clip may have already changed if the
183    ///   // duration-limit of the clip dropped below its current value
184    ///
185    ///   new_end = ges_clip_get_timeline_time_from_internal_time (
186    ///         clip, source, source_outpoint, &error);
187    ///   // handle error
188    ///
189    ///   if (!ges_timeline_elemnet_edit_full (GES_TIMELINE_ELEMENT (clip),
190    ///         -1, GES_EDIT_MODE_TRIM, GES_EDGE_END, new_end, &error))
191    ///     // handle error
192    ///
193    ///   for (tmp = children; tmp; tmp = tmp->next)
194    ///     ges_track_element_set_auto_clamp_control_sources (tmp->data, TRUE);
195    ///
196    ///   g_list_free_full (children, gst_object_unref);
197    ///   gst_object_unref (source);
198    /// }
199    /// ```
200    ///
201    /// This is an Abstract Base Class, you cannot instantiate it.
202    ///
203    /// ## Properties
204    ///
205    ///
206    /// #### `duration-limit`
207    ///  The maximum [`duration`][struct@crate::TimelineElement#duration] that can be *currently* set
208    /// for the clip, taking into account the [`in-point`][struct@crate::TimelineElement#in-point],
209    /// [`max-duration`][struct@crate::TimelineElement#max-duration], [`active`][struct@crate::TrackElement#active], and
210    /// [`track`][struct@crate::TrackElement#track] properties of its children, as well as any
211    /// time effects. If there is no limit, this will be set to
212    /// `GST_CLOCK_TIME_NONE`.
213    ///
214    /// Note that whilst a clip has no children in any tracks, the limit will
215    /// be unknown, and similarly set to `GST_CLOCK_TIME_NONE`.
216    ///
217    /// If the duration-limit would ever go below the current
218    /// [`duration`][struct@crate::TimelineElement#duration] of the clip due to a change in the above
219    /// variables, its [`duration`][struct@crate::TimelineElement#duration] will be set to the new
220    /// limit.
221    ///
222    /// Readable
223    ///
224    ///
225    /// #### `layer`
226    ///  The layer this clip lies in.
227    ///
228    /// If you want to connect to this property's [`notify`][struct@crate::glib::Object#notify] signal,
229    /// you should connect to it with `g_signal_connect_after()` since the
230    /// signal emission may be stopped internally.
231    ///
232    /// Readable
233    ///
234    ///
235    /// #### `supported-formats`
236    ///  The [`TrackType`][crate::TrackType]-s that the clip supports, which it can create
237    /// [`TrackElement`][crate::TrackElement]-s for. Note that this can be a combination of
238    /// [`TrackType`][crate::TrackType] flags to indicate support for several
239    /// [`track-type`][struct@crate::TrackElement#track-type] elements.
240    ///
241    /// Readable | Writeable | Construct
242    /// <details><summary><h4>Container</h4></summary>
243    ///
244    ///
245    /// #### `height`
246    ///  The span of the container's children's [`priority`][struct@crate::TimelineElement#priority]
247    /// values, which is the number of integers that lie between (inclusive)
248    /// the minimum and maximum priorities found amongst the container's
249    /// children (maximum - minimum + 1).
250    ///
251    /// Readable
252    /// </details>
253    /// <details><summary><h4>TimelineElement</h4></summary>
254    ///
255    ///
256    /// #### `duration`
257    ///  The duration that the element is in effect for in the timeline (a
258    /// time difference in nanoseconds using the time coordinates of the
259    /// timeline). For example, for a source element, this would determine
260    /// for how long it should output its internal content for. For an
261    /// operation element, this would determine for how long its effect
262    /// should be applied to any source content.
263    ///
264    /// Readable | Writeable
265    ///
266    ///
267    /// #### `in-point`
268    ///  The initial offset to use internally when outputting content (in
269    /// nanoseconds, but in the time coordinates of the internal content).
270    ///
271    /// For example, for a [`VideoUriSource`][crate::VideoUriSource] that references some media
272    /// file, the "internal content" is the media file data, and the
273    /// in-point would correspond to some timestamp in the media file.
274    /// When playing the timeline, and when the element is first reached at
275    /// timeline-time [`start`][struct@crate::TimelineElement#start], it will begin outputting the
276    /// data from the timestamp in-point **onwards**, until it reaches the
277    /// end of its [`duration`][struct@crate::TimelineElement#duration] in the timeline.
278    ///
279    /// For elements that have no internal content, this should be kept
280    /// as 0.
281    ///
282    /// Readable | Writeable
283    ///
284    ///
285    /// #### `max-duration`
286    ///  The full duration of internal content that is available (a time
287    /// difference in nanoseconds using the time coordinates of the internal
288    /// content).
289    ///
290    /// This will act as a cap on the [`in-point`][struct@crate::TimelineElement#in-point] of the
291    /// element (which is in the same time coordinates), and will sometimes
292    /// be used to limit the [`duration`][struct@crate::TimelineElement#duration] of the element in
293    /// the timeline.
294    ///
295    /// For example, for a [`VideoUriSource`][crate::VideoUriSource] that references some media
296    /// file, this would be the length of the media file.
297    ///
298    /// For elements that have no internal content, or whose content is
299    /// indefinite, this should be kept as `GST_CLOCK_TIME_NONE`.
300    ///
301    /// Readable | Writeable | Construct
302    ///
303    ///
304    /// #### `name`
305    ///  The name of the element. This should be unique within its timeline.
306    ///
307    /// Readable | Writeable | Construct
308    ///
309    ///
310    /// #### `parent`
311    ///  The parent container of the element.
312    ///
313    /// Readable | Writeable
314    ///
315    ///
316    /// #### `priority`
317    ///  The priority of the element.
318    ///
319    /// Readable | Writeable
320    ///
321    ///
322    /// #### `serialize`
323    ///  Whether the element should be serialized.
324    ///
325    /// Readable | Writeable
326    ///
327    ///
328    /// #### `start`
329    ///  The starting position of the element in the timeline (in nanoseconds
330    /// and in the time coordinates of the timeline). For example, for a
331    /// source element, this would determine the time at which it should
332    /// start outputting its internal content. For an operation element, this
333    /// would determine the time at which it should start applying its effect
334    /// to any source content.
335    ///
336    /// Readable | Writeable
337    ///
338    ///
339    /// #### `timeline`
340    ///  The timeline that the element lies within.
341    ///
342    /// Readable | Writeable
343    /// </details>
344    ///
345    /// # Implements
346    ///
347    /// [`ClipExt`][trait@crate::prelude::ClipExt], [`GESContainerExt`][trait@crate::prelude::GESContainerExt], [`TimelineElementExt`][trait@crate::prelude::TimelineElementExt], [`trait@glib::ObjectExt`], [`ExtractableExt`][trait@crate::prelude::ExtractableExt], [`MetaContainerExt`][trait@crate::prelude::MetaContainerExt], [`TimelineElementExtManual`][trait@crate::prelude::TimelineElementExtManual]
348    #[doc(alias = "GESClip")]
349    pub struct Clip(Object<ffi::GESClip, ffi::GESClipClass>) @extends Container, TimelineElement, @implements Extractable, MetaContainer;
350
351    match fn {
352        type_ => || ffi::ges_clip_get_type(),
353    }
354}
355
356impl Clip {
357    pub const NONE: Option<&'static Clip> = None;
358}
359
360/// Trait containing all [`struct@Clip`] methods.
361///
362/// # Implementors
363///
364/// [`Clip`][struct@crate::Clip], [`OperationClip`][struct@crate::OperationClip], [`SourceClip`][struct@crate::SourceClip]
365pub trait ClipExt: IsA<Clip> + 'static {
366    /// Extracts a [`TrackElement`][crate::TrackElement] from an asset and adds it to the clip.
367    /// This can be used to add effects that derive from the asset to the
368    /// clip, but this method is not intended to be used to create the core
369    /// elements of the clip.
370    /// ## `asset`
371    /// An asset with `GES_TYPE_TRACK_ELEMENT` as its
372    /// [`extractable-type`][struct@crate::Asset#extractable-type]
373    ///
374    /// # Returns
375    ///
376    /// The newly created element, or
377    /// [`None`] if an error occurred.
378    #[doc(alias = "ges_clip_add_asset")]
379    fn add_asset(&self, asset: &impl IsA<Asset>) -> Result<TrackElement, glib::BoolError> {
380        unsafe {
381            Option::<_>::from_glib_none(ffi::ges_clip_add_asset(
382                self.as_ref().to_glib_none().0,
383                asset.as_ref().to_glib_none().0,
384            ))
385            .ok_or_else(|| glib::bool_error!("Failed to add asset"))
386        }
387    }
388
389    /// Adds the track element child of the clip to a specific track.
390    ///
391    /// If the given child is already in another track, this will create a copy
392    /// of the child, add it to the clip, and add this copy to the track.
393    ///
394    /// You should only call this whilst a clip is part of a [`Timeline`][crate::Timeline], and
395    /// for tracks that are in the same timeline.
396    ///
397    /// This method is an alternative to using the
398    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] signal, but can be used to
399    /// complement it when, say, you wish to copy a clip's children from one
400    /// track into a new one.
401    ///
402    /// When the child is a core child, it must be added to a track that does
403    /// not already contain another core child of the same clip. If it is not a
404    /// core child (an additional effect), then it must be added to a track
405    /// that already contains one of the core children of the same clip.
406    ///
407    /// This method can also fail if the adding the track element to the track
408    /// would break a configuration rule of the corresponding [`Timeline`][crate::Timeline],
409    /// such as causing three sources to overlap at a single time, or causing
410    /// a source to completely overlap another in the same track.
411    /// ## `child`
412    /// A child of `self`
413    /// ## `track`
414    /// The track to add `child` to
415    ///
416    /// # Returns
417    ///
418    /// The element that was added to `track`, either
419    /// `child` or a copy of child, or [`None`] if the element could not be added.
420    #[cfg(feature = "v1_18")]
421    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
422    #[doc(alias = "ges_clip_add_child_to_track")]
423    fn add_child_to_track(
424        &self,
425        child: &impl IsA<TrackElement>,
426        track: &impl IsA<Track>,
427    ) -> Result<TrackElement, glib::Error> {
428        unsafe {
429            let mut error = std::ptr::null_mut();
430            let ret = ffi::ges_clip_add_child_to_track(
431                self.as_ref().to_glib_none().0,
432                child.as_ref().to_glib_none().0,
433                track.as_ref().to_glib_none().0,
434                &mut error,
435            );
436            if error.is_null() {
437                Ok(from_glib_none(ret))
438            } else {
439                Err(from_glib_full(error))
440            }
441        }
442    }
443
444    /// Add a top effect to a clip at the given index.
445    ///
446    /// Unlike using [`GESContainerExt::add()`][crate::prelude::GESContainerExt::add()], this allows you to set the index
447    /// in advance. It will also check that no error occurred during the track
448    /// selection for the effect.
449    ///
450    /// Note, only subclasses of `GESClipClass` that have
451    /// `GES_CLIP_CLASS_CAN_ADD_EFFECTS` set to [`true`] (such as [`SourceClip`][crate::SourceClip]
452    /// and [`BaseEffectClip`][crate::BaseEffectClip]) can have additional top effects added.
453    ///
454    /// Note, if the effect is a time effect, this may be refused if the clip
455    /// would not be able to adapt itself once the effect is added.
456    /// ## `effect`
457    /// A top effect to add
458    /// ## `index`
459    /// The index to add `effect` at, or -1 to add at the highest,
460    ///  see `ges_clip_get_top_effect_index` for more information
461    ///
462    /// # Returns
463    ///
464    /// [`true`] if `effect` was successfully added to `self` at `index`.
465    #[cfg(feature = "v1_18")]
466    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
467    #[doc(alias = "ges_clip_add_top_effect")]
468    fn add_top_effect(&self, effect: &impl IsA<BaseEffect>, index: i32) -> Result<(), glib::Error> {
469        unsafe {
470            let mut error = std::ptr::null_mut();
471            let is_ok = ffi::ges_clip_add_top_effect(
472                self.as_ref().to_glib_none().0,
473                effect.as_ref().to_glib_none().0,
474                index,
475                &mut error,
476            );
477            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
478            if error.is_null() {
479                Ok(())
480            } else {
481                Err(from_glib_full(error))
482            }
483        }
484    }
485
486    /// Finds an element controlled by the clip. If `track` is given,
487    /// then only the track elements in `track` are searched for. If `type_` is
488    /// given, then this function searches for a track element of the given
489    /// `type_`.
490    ///
491    /// Note, if multiple track elements in the clip match the given criteria,
492    /// this will return the element amongst them with the highest
493    /// [`priority`][struct@crate::TimelineElement#priority] (numerically, the smallest). See
494    /// [`find_track_elements()`][Self::find_track_elements()] if you wish to find all such elements.
495    /// ## `track`
496    /// The track to search in, or [`None`] to search in
497    /// all tracks
498    /// ## `type_`
499    /// The type of track element to search for, or `G_TYPE_NONE` to
500    /// match any type
501    ///
502    /// # Returns
503    ///
504    /// The element controlled by
505    /// `self`, in `track`, and of the given `type_`, or [`None`] if no such element
506    /// could be found.
507    #[doc(alias = "ges_clip_find_track_element")]
508    fn find_track_element(
509        &self,
510        track: Option<&impl IsA<Track>>,
511        type_: glib::types::Type,
512    ) -> Option<TrackElement> {
513        unsafe {
514            from_glib_full(ffi::ges_clip_find_track_element(
515                self.as_ref().to_glib_none().0,
516                track.map(|p| p.as_ref()).to_glib_none().0,
517                type_.into_glib(),
518            ))
519        }
520    }
521
522    /// Finds the [`TrackElement`][crate::TrackElement]-s controlled by the clip that match the
523    /// given criteria. If `track` is given as [`None`] and `track_type` is given as
524    /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], then the search will match all elements in any
525    /// track, including those with no track, and of any
526    /// [`track-type`][struct@crate::TrackElement#track-type]. Otherwise, if `track` is not [`None`], but
527    /// `track_type` is [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], then only the track elements in
528    /// `track` are searched for. Otherwise, if `track_type` is not
529    /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], but `track` is [`None`], then only the track
530    /// elements whose [`track-type`][struct@crate::TrackElement#track-type] matches `track_type` are
531    /// searched for. Otherwise, when both are given, the track elements that
532    /// match **either** criteria are searched for. Therefore, if you wish to
533    /// only find elements in a specific track, you should give the track as
534    /// `track`, but you should not give the track's [`track-type`][struct@crate::Track#track-type] as
535    /// `track_type` because this would also select elements from other tracks
536    /// of the same type.
537    ///
538    /// You may also give `type_` to _further_ restrict the search to track
539    /// elements of the given `type_`.
540    /// ## `track`
541    /// The track to search in, or [`None`] to search in
542    /// all tracks
543    /// ## `track_type`
544    /// The track-type of the track element to search for, or
545    /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN] to match any track type
546    /// ## `type_`
547    /// The type of track element to search for, or `G_TYPE_NONE` to
548    /// match any type
549    ///
550    /// # Returns
551    ///
552    /// A list of all
553    /// the [`TrackElement`][crate::TrackElement]-s controlled by `self`, in `track` or of the given
554    /// `track_type`, and of the given `type_`.
555    #[doc(alias = "ges_clip_find_track_elements")]
556    fn find_track_elements(
557        &self,
558        track: Option<&impl IsA<Track>>,
559        track_type: TrackType,
560        type_: glib::types::Type,
561    ) -> Vec<TrackElement> {
562        unsafe {
563            FromGlibPtrContainer::from_glib_full(ffi::ges_clip_find_track_elements(
564                self.as_ref().to_glib_none().0,
565                track.map(|p| p.as_ref()).to_glib_none().0,
566                track_type.into_glib(),
567                type_.into_glib(),
568            ))
569        }
570    }
571
572    /// Gets the [`duration-limit`][struct@crate::Clip#duration-limit] of the clip.
573    ///
574    /// # Returns
575    ///
576    /// The duration-limit of `self`.
577    #[cfg(feature = "v1_18")]
578    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
579    #[doc(alias = "ges_clip_get_duration_limit")]
580    #[doc(alias = "get_duration_limit")]
581    #[doc(alias = "duration-limit")]
582    fn duration_limit(&self) -> gst::ClockTime {
583        unsafe {
584            try_from_glib(ffi::ges_clip_get_duration_limit(
585                self.as_ref().to_glib_none().0,
586            ))
587            .expect("mandatory glib value is None")
588        }
589    }
590
591    /// Convert the timeline time to an internal source time of the child.
592    /// This will take any time effects placed on the clip into account (see
593    /// [`BaseEffect`][crate::BaseEffect] for what time effects are supported, and how to
594    /// declare them in GES).
595    ///
596    /// When `timeline_time` is above the [`start`][struct@crate::TimelineElement#start] of `self`,
597    /// this will return the internal time at which the content that appears at
598    /// `timeline_time` in the output of the timeline is created in `child`. For
599    /// example, if `timeline_time` corresponds to the current seek position,
600    /// this would let you know which part of a media file is being read.
601    ///
602    /// This will be done assuming the clip has an indefinite end, so the
603    /// internal time may be beyond the current out-point of the child, or even
604    /// its [`max-duration`][struct@crate::TimelineElement#max-duration].
605    ///
606    /// If, instead, `timeline_time` is below the current
607    /// [`start`][struct@crate::TimelineElement#start] of `self`, this will return what you would
608    /// need to set the [`in-point`][struct@crate::TimelineElement#in-point] of `child` to if you set
609    /// the [`start`][struct@crate::TimelineElement#start] of `self` to `timeline_time` and wanted
610    /// to keep the content of `child` currently found at the current
611    /// [`start`][struct@crate::TimelineElement#start] of `self` at the same timeline position. If
612    /// this would be negative, the conversion fails. This is useful for
613    /// determining what [`in-point`][struct@crate::TimelineElement#in-point] would result from a
614    /// [`EditMode::Trim`][crate::EditMode::Trim] to `timeline_time`.
615    ///
616    /// Note that whilst a clip has no time effects, this second return is
617    /// equivalent to finding the internal time at which the content that
618    /// appears at `timeline_time` in the timeline can be found in `child` if it
619    /// had indefinite extent in both directions. However, with non-linear time
620    /// effects this second return will be more distinct.
621    ///
622    /// In either case, the returned time would be appropriate to use for the
623    /// [`in-point`][struct@crate::TimelineElement#in-point] or [`max-duration`][struct@crate::TimelineElement#max-duration] of the
624    /// child.
625    ///
626    /// See [`timeline_time_from_internal_time()`][Self::timeline_time_from_internal_time()], which performs the
627    /// reverse.
628    /// ## `child`
629    /// An [`active`][struct@crate::TrackElement#active] child of `self` with a
630    /// [`track`][struct@crate::TrackElement#track]
631    /// ## `timeline_time`
632    /// A time in the timeline time coordinates
633    ///
634    /// # Returns
635    ///
636    /// The time in the internal coordinates of `child` corresponding
637    /// to `timeline_time`, or `GST_CLOCK_TIME_NONE` if the conversion could not
638    /// be performed.
639    #[cfg(feature = "v1_18")]
640    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
641    #[doc(alias = "ges_clip_get_internal_time_from_timeline_time")]
642    #[doc(alias = "get_internal_time_from_timeline_time")]
643    fn internal_time_from_timeline_time(
644        &self,
645        child: &impl IsA<TrackElement>,
646        timeline_time: impl Into<Option<gst::ClockTime>>,
647    ) -> Result<Option<gst::ClockTime>, glib::Error> {
648        unsafe {
649            let mut error = std::ptr::null_mut();
650            let ret = ffi::ges_clip_get_internal_time_from_timeline_time(
651                self.as_ref().to_glib_none().0,
652                child.as_ref().to_glib_none().0,
653                timeline_time.into().into_glib(),
654                &mut error,
655            );
656            if error.is_null() {
657                Ok(from_glib(ret))
658            } else {
659                Err(from_glib_full(error))
660            }
661        }
662    }
663
664    /// Gets the [`layer`][struct@crate::Clip#layer] of the clip.
665    ///
666    /// # Returns
667    ///
668    /// The layer `self` is in, or [`None`] if
669    /// `self` is not in any layer.
670    #[doc(alias = "ges_clip_get_layer")]
671    #[doc(alias = "get_layer")]
672    fn layer(&self) -> Option<Layer> {
673        unsafe { from_glib_full(ffi::ges_clip_get_layer(self.as_ref().to_glib_none().0)) }
674    }
675
676    /// Gets the [`supported-formats`][struct@crate::Clip#supported-formats] of the clip.
677    ///
678    /// # Returns
679    ///
680    /// The [`TrackType`][crate::TrackType]-s supported by `self`.
681    #[doc(alias = "ges_clip_get_supported_formats")]
682    #[doc(alias = "get_supported_formats")]
683    #[doc(alias = "supported-formats")]
684    fn supported_formats(&self) -> TrackType {
685        unsafe {
686            from_glib(ffi::ges_clip_get_supported_formats(
687                self.as_ref().to_glib_none().0,
688            ))
689        }
690    }
691
692    /// Convert the internal source time from the child to a timeline time.
693    /// This will take any time effects placed on the clip into account (see
694    /// [`BaseEffect`][crate::BaseEffect] for what time effects are supported, and how to
695    /// declare them in GES).
696    ///
697    /// When `internal_time` is above the [`in-point`][struct@crate::TimelineElement#in-point] of
698    /// `child`, this will return the timeline time at which the internal
699    /// content found at `internal_time` appears in the output of the timeline's
700    /// track. For example, this would let you know where in the timeline a
701    /// particular scene in a media file would appear.
702    ///
703    /// This will be done assuming the clip has an indefinite end, so the
704    /// timeline time may be beyond the end of the clip, or even breaking its
705    /// [`duration-limit`][struct@crate::Clip#duration-limit].
706    ///
707    /// If, instead, `internal_time` is below the current
708    /// [`in-point`][struct@crate::TimelineElement#in-point] of `child`, this will return what you would
709    /// need to set the [`start`][struct@crate::TimelineElement#start] of `self` to if you set the
710    /// [`in-point`][struct@crate::TimelineElement#in-point] of `child` to `internal_time` and wanted to
711    /// keep the content of `child` currently found at the current
712    /// [`start`][struct@crate::TimelineElement#start] of `self` at the same timeline position. If
713    /// this would be negative, the conversion fails. This is useful for
714    /// determining what position to use in a [`EditMode::Trim`][crate::EditMode::Trim] if you wish
715    /// to trim to a specific point in the internal content, such as a
716    /// particular scene in a media file.
717    ///
718    /// Note that whilst a clip has no time effects, this second return is
719    /// equivalent to finding the timeline time at which the content of `child`
720    /// at `internal_time` would be found in the timeline if it had indefinite
721    /// extent in both directions. However, with non-linear time effects this
722    /// second return will be more distinct.
723    ///
724    /// In either case, the returned time would be appropriate to use in
725    /// [`TimelineElementExt::edit()`][crate::prelude::TimelineElementExt::edit()] for [`EditMode::Trim`][crate::EditMode::Trim], and similar, if
726    /// you wish to use a particular internal point as a reference. For
727    /// example, you could choose to end a clip at a certain internal
728    /// 'out-point', similar to the [`in-point`][struct@crate::TimelineElement#in-point], by
729    /// translating the desired end time into the timeline coordinates, and
730    /// using this position to trim the end of a clip.
731    ///
732    /// See [`internal_time_from_timeline_time()`][Self::internal_time_from_timeline_time()], which performs the
733    /// reverse, or [`timeline_time_from_source_frame()`][Self::timeline_time_from_source_frame()] which does
734    /// the same conversion, but using frame numbers.
735    /// ## `child`
736    /// An [`active`][struct@crate::TrackElement#active] child of `self` with a
737    /// [`track`][struct@crate::TrackElement#track]
738    /// ## `internal_time`
739    /// A time in the internal time coordinates of `child`
740    ///
741    /// # Returns
742    ///
743    /// The time in the timeline coordinates corresponding to
744    /// `internal_time`, or `GST_CLOCK_TIME_NONE` if the conversion could not be
745    /// performed.
746    #[cfg(feature = "v1_18")]
747    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
748    #[doc(alias = "ges_clip_get_timeline_time_from_internal_time")]
749    #[doc(alias = "get_timeline_time_from_internal_time")]
750    fn timeline_time_from_internal_time(
751        &self,
752        child: &impl IsA<TrackElement>,
753        internal_time: impl Into<Option<gst::ClockTime>>,
754    ) -> Result<Option<gst::ClockTime>, glib::Error> {
755        unsafe {
756            let mut error = std::ptr::null_mut();
757            let ret = ffi::ges_clip_get_timeline_time_from_internal_time(
758                self.as_ref().to_glib_none().0,
759                child.as_ref().to_glib_none().0,
760                internal_time.into().into_glib(),
761                &mut error,
762            );
763            if error.is_null() {
764                Ok(from_glib(ret))
765            } else {
766                Err(from_glib_full(error))
767            }
768        }
769    }
770
771    /// Convert the source frame number to a timeline time. This acts the same
772    /// as [`timeline_time_from_internal_time()`][Self::timeline_time_from_internal_time()] using the core
773    /// children of the clip and using the frame number to specify the internal
774    /// position, rather than a timestamp.
775    ///
776    /// The returned timeline time can be used to seek or edit to a specific
777    /// frame.
778    ///
779    /// Note that you can get the frame timestamp of a particular clip asset
780    /// with [`ClipAssetExt::frame_time()`][crate::prelude::ClipAssetExt::frame_time()].
781    /// ## `frame_number`
782    /// The frame number to get the corresponding timestamp of
783    /// in the timeline coordinates
784    ///
785    /// # Returns
786    ///
787    /// The timestamp corresponding to `frame_number` in the core
788    /// children of `self`, in the timeline coordinates, or `GST_CLOCK_TIME_NONE`
789    /// if the conversion could not be performed.
790    #[cfg(feature = "v1_18")]
791    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
792    #[doc(alias = "ges_clip_get_timeline_time_from_source_frame")]
793    #[doc(alias = "get_timeline_time_from_source_frame")]
794    fn timeline_time_from_source_frame(
795        &self,
796        frame_number: FrameNumber,
797    ) -> Result<Option<gst::ClockTime>, glib::Error> {
798        unsafe {
799            let mut error = std::ptr::null_mut();
800            let ret = ffi::ges_clip_get_timeline_time_from_source_frame(
801                self.as_ref().to_glib_none().0,
802                frame_number,
803                &mut error,
804            );
805            if error.is_null() {
806                Ok(from_glib(ret))
807            } else {
808                Err(from_glib_full(error))
809            }
810        }
811    }
812
813    /// Gets the internal index of an effect in the clip. The index of effects
814    /// in a clip will run from 0 to n-1, where n is the total number of
815    /// effects. If two effects share the same [`track`][struct@crate::TrackElement#track], the
816    /// effect with the numerically lower index will be applied to the source
817    /// data **after** the other effect, i.e. output data will always flow from
818    /// a higher index effect to a lower index effect.
819    /// ## `effect`
820    /// The effect we want to get the index of
821    ///
822    /// # Returns
823    ///
824    /// The index of `effect` in `self`, or -1 if something went wrong.
825    #[doc(alias = "ges_clip_get_top_effect_index")]
826    #[doc(alias = "get_top_effect_index")]
827    fn top_effect_index(&self, effect: &impl IsA<BaseEffect>) -> i32 {
828        unsafe {
829            ffi::ges_clip_get_top_effect_index(
830                self.as_ref().to_glib_none().0,
831                effect.as_ref().to_glib_none().0,
832            )
833        }
834    }
835
836    #[doc(alias = "ges_clip_get_top_effect_position")]
837    #[doc(alias = "get_top_effect_position")]
838    fn top_effect_position(&self, effect: &impl IsA<BaseEffect>) -> i32 {
839        unsafe {
840            ffi::ges_clip_get_top_effect_position(
841                self.as_ref().to_glib_none().0,
842                effect.as_ref().to_glib_none().0,
843            )
844        }
845    }
846
847    /// Gets the [`BaseEffect`][crate::BaseEffect]-s that have been added to the clip. The
848    /// returned list is ordered by their internal index in the clip. See
849    /// [`top_effect_index()`][Self::top_effect_index()].
850    ///
851    /// # Returns
852    ///
853    /// A list of all
854    /// [`BaseEffect`][crate::BaseEffect]-s that have been added to `self`.
855    #[doc(alias = "ges_clip_get_top_effects")]
856    #[doc(alias = "get_top_effects")]
857    fn top_effects(&self) -> Vec<TrackElement> {
858        unsafe {
859            FromGlibPtrContainer::from_glib_full(ffi::ges_clip_get_top_effects(
860                self.as_ref().to_glib_none().0,
861            ))
862        }
863    }
864
865    /// See [`move_to_layer_full()`][Self::move_to_layer_full()], which also gives an error.
866    /// ## `layer`
867    /// The new layer
868    ///
869    /// # Returns
870    ///
871    /// [`true`] if `self` was successfully moved to `layer`.
872    #[doc(alias = "ges_clip_move_to_layer")]
873    fn move_to_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
874        unsafe {
875            glib::result_from_gboolean!(
876                ffi::ges_clip_move_to_layer(
877                    self.as_ref().to_glib_none().0,
878                    layer.as_ref().to_glib_none().0
879                ),
880                "Failed to move clip to specified layer"
881            )
882        }
883    }
884
885    /// Moves a clip to a new layer. If the clip already exists in a layer, it
886    /// is first removed from its current layer before being added to the new
887    /// layer.
888    /// ## `layer`
889    /// The new layer
890    ///
891    /// # Returns
892    ///
893    /// [`true`] if `self` was successfully moved to `layer`.
894    #[cfg(feature = "v1_18")]
895    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
896    #[doc(alias = "ges_clip_move_to_layer_full")]
897    fn move_to_layer_full(&self, layer: &impl IsA<Layer>) -> Result<(), glib::Error> {
898        unsafe {
899            let mut error = std::ptr::null_mut();
900            let is_ok = ffi::ges_clip_move_to_layer_full(
901                self.as_ref().to_glib_none().0,
902                layer.as_ref().to_glib_none().0,
903                &mut error,
904            );
905            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
906            if error.is_null() {
907                Ok(())
908            } else {
909                Err(from_glib_full(error))
910            }
911        }
912    }
913
914    /// Remove a top effect from the clip.
915    ///
916    /// Note, if the effect is a time effect, this may be refused if the clip
917    /// would not be able to adapt itself once the effect is removed.
918    /// ## `effect`
919    /// The top effect to remove
920    ///
921    /// # Returns
922    ///
923    /// [`true`] if `effect` was successfully added to `self` at `index`.
924    #[cfg(feature = "v1_18")]
925    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
926    #[doc(alias = "ges_clip_remove_top_effect")]
927    fn remove_top_effect(&self, effect: &impl IsA<BaseEffect>) -> Result<(), glib::Error> {
928        unsafe {
929            let mut error = std::ptr::null_mut();
930            let is_ok = ffi::ges_clip_remove_top_effect(
931                self.as_ref().to_glib_none().0,
932                effect.as_ref().to_glib_none().0,
933                &mut error,
934            );
935            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
936            if error.is_null() {
937                Ok(())
938            } else {
939                Err(from_glib_full(error))
940            }
941        }
942    }
943
944    /// Sets the [`supported-formats`][struct@crate::Clip#supported-formats] of the clip. This should normally
945    /// only be called by subclasses, which should be responsible for updating
946    /// its value, rather than the user.
947    /// ## `supportedformats`
948    /// The [`TrackType`][crate::TrackType]-s supported by `self`
949    #[doc(alias = "ges_clip_set_supported_formats")]
950    #[doc(alias = "supported-formats")]
951    fn set_supported_formats(&self, supportedformats: TrackType) {
952        unsafe {
953            ffi::ges_clip_set_supported_formats(
954                self.as_ref().to_glib_none().0,
955                supportedformats.into_glib(),
956            );
957        }
958    }
959
960    /// See [`set_top_effect_index_full()`][Self::set_top_effect_index_full()], which also gives an error.
961    /// ## `effect`
962    /// An effect within `self` to move
963    /// ## `newindex`
964    /// The index for `effect` in `self`
965    ///
966    /// # Returns
967    ///
968    /// [`true`] if `effect` was successfully moved to `newindex`.
969    #[doc(alias = "ges_clip_set_top_effect_index")]
970    fn set_top_effect_index(
971        &self,
972        effect: &impl IsA<BaseEffect>,
973        newindex: u32,
974    ) -> Result<(), glib::error::BoolError> {
975        unsafe {
976            glib::result_from_gboolean!(
977                ffi::ges_clip_set_top_effect_index(
978                    self.as_ref().to_glib_none().0,
979                    effect.as_ref().to_glib_none().0,
980                    newindex
981                ),
982                "Failed to move effect"
983            )
984        }
985    }
986
987    /// Set the index of an effect within the clip. See
988    /// [`top_effect_index()`][Self::top_effect_index()]. The new index must be an existing
989    /// index of the clip. The effect is moved to the new index, and the other
990    /// effects may be shifted in index accordingly to otherwise maintain the
991    /// ordering.
992    /// ## `effect`
993    /// An effect within `self` to move
994    /// ## `newindex`
995    /// The index for `effect` in `self`
996    ///
997    /// # Returns
998    ///
999    /// [`true`] if `effect` was successfully moved to `newindex`.
1000    #[cfg(feature = "v1_18")]
1001    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1002    #[doc(alias = "ges_clip_set_top_effect_index_full")]
1003    fn set_top_effect_index_full(
1004        &self,
1005        effect: &impl IsA<BaseEffect>,
1006        newindex: u32,
1007    ) -> Result<(), glib::Error> {
1008        unsafe {
1009            let mut error = std::ptr::null_mut();
1010            let is_ok = ffi::ges_clip_set_top_effect_index_full(
1011                self.as_ref().to_glib_none().0,
1012                effect.as_ref().to_glib_none().0,
1013                newindex,
1014                &mut error,
1015            );
1016            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1017            if error.is_null() {
1018                Ok(())
1019            } else {
1020                Err(from_glib_full(error))
1021            }
1022        }
1023    }
1024
1025    #[doc(alias = "ges_clip_set_top_effect_priority")]
1026    fn set_top_effect_priority(
1027        &self,
1028        effect: &impl IsA<BaseEffect>,
1029        newpriority: u32,
1030    ) -> Result<(), glib::error::BoolError> {
1031        unsafe {
1032            glib::result_from_gboolean!(
1033                ffi::ges_clip_set_top_effect_priority(
1034                    self.as_ref().to_glib_none().0,
1035                    effect.as_ref().to_glib_none().0,
1036                    newpriority
1037                ),
1038                "Failed to the set top effect priority"
1039            )
1040        }
1041    }
1042
1043    /// See [`split_full()`][Self::split_full()], which also gives an error.
1044    /// ## `position`
1045    /// The timeline position at which to perform the split
1046    ///
1047    /// # Returns
1048    ///
1049    /// The newly created clip resulting
1050    /// from the splitting `self`, or [`None`] if `self` can't be split.
1051    #[doc(alias = "ges_clip_split")]
1052    fn split(&self, position: u64) -> Result<Clip, glib::BoolError> {
1053        unsafe {
1054            Option::<_>::from_glib_none(ffi::ges_clip_split(
1055                self.as_ref().to_glib_none().0,
1056                position,
1057            ))
1058            .ok_or_else(|| glib::bool_error!("Failed to split clip"))
1059        }
1060    }
1061
1062    /// Splits a clip at the given timeline position into two clips. The clip
1063    /// must already have a [`layer`][struct@crate::Clip#layer].
1064    ///
1065    /// The original clip's [`duration`][struct@crate::TimelineElement#duration] is reduced such that
1066    /// its end point matches the split position. Then a new clip is created in
1067    /// the same layer, whose [`start`][struct@crate::TimelineElement#start] matches the split
1068    /// position and [`duration`][struct@crate::TimelineElement#duration] will be set such that its end
1069    /// point matches the old end point of the original clip. Thus, the two
1070    /// clips together will occupy the same positions in the timeline as the
1071    /// original clip did.
1072    ///
1073    /// The children of the new clip will be new copies of the original clip's
1074    /// children, so it will share the same sources and use the same
1075    /// operations.
1076    ///
1077    /// The new clip will also have its [`in-point`][struct@crate::TimelineElement#in-point] set so
1078    /// that any internal data will appear in the timeline at the same time.
1079    /// Thus, when the timeline is played, the playback of data should
1080    /// appear the same. This may be complicated by any additional
1081    /// [`Effect`][crate::Effect]-s that have been placed on the original clip that depend on
1082    /// the playback time or change the data consumption rate of sources. This
1083    /// method will attempt to translate these effects such that the playback
1084    /// appears the same. In such complex situations, you may get a better
1085    /// result if you place the clip in a separate sub [`Project`][crate::Project], which only
1086    /// contains this clip (and its effects), and in the original layer
1087    /// create two neighbouring [`UriClip`][crate::UriClip]-s that reference this sub-project,
1088    /// but at a different [`in-point`][struct@crate::TimelineElement#in-point].
1089    /// ## `position`
1090    /// The timeline position at which to perform the split, between
1091    /// the start and end of the clip
1092    ///
1093    /// # Returns
1094    ///
1095    /// The newly created clip resulting
1096    /// from the splitting `self`, or [`None`] if `self` can't be split.
1097    #[cfg(feature = "v1_18")]
1098    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1099    #[doc(alias = "ges_clip_split_full")]
1100    fn split_full(&self, position: u64) -> Result<Option<Clip>, glib::Error> {
1101        unsafe {
1102            let mut error = std::ptr::null_mut();
1103            let ret =
1104                ffi::ges_clip_split_full(self.as_ref().to_glib_none().0, position, &mut error);
1105            if error.is_null() {
1106                Ok(from_glib_none(ret))
1107            } else {
1108                Err(from_glib_full(error))
1109            }
1110        }
1111    }
1112
1113    #[cfg(feature = "v1_18")]
1114    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1115    #[doc(alias = "duration-limit")]
1116    fn connect_duration_limit_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1117        unsafe extern "C" fn notify_duration_limit_trampoline<P: IsA<Clip>, F: Fn(&P) + 'static>(
1118            this: *mut ffi::GESClip,
1119            _param_spec: glib::ffi::gpointer,
1120            f: glib::ffi::gpointer,
1121        ) {
1122            let f: &F = &*(f as *const F);
1123            f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1124        }
1125        unsafe {
1126            let f: Box_<F> = Box_::new(f);
1127            connect_raw(
1128                self.as_ptr() as *mut _,
1129                c"notify::duration-limit".as_ptr() as *const _,
1130                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1131                    notify_duration_limit_trampoline::<Self, F> as *const (),
1132                )),
1133                Box_::into_raw(f),
1134            )
1135        }
1136    }
1137
1138    #[doc(alias = "layer")]
1139    fn connect_layer_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1140        unsafe extern "C" fn notify_layer_trampoline<P: IsA<Clip>, F: Fn(&P) + 'static>(
1141            this: *mut ffi::GESClip,
1142            _param_spec: glib::ffi::gpointer,
1143            f: glib::ffi::gpointer,
1144        ) {
1145            let f: &F = &*(f as *const F);
1146            f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1147        }
1148        unsafe {
1149            let f: Box_<F> = Box_::new(f);
1150            connect_raw(
1151                self.as_ptr() as *mut _,
1152                c"notify::layer".as_ptr() as *const _,
1153                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1154                    notify_layer_trampoline::<Self, F> as *const (),
1155                )),
1156                Box_::into_raw(f),
1157            )
1158        }
1159    }
1160
1161    #[doc(alias = "supported-formats")]
1162    fn connect_supported_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1163        unsafe extern "C" fn notify_supported_formats_trampoline<
1164            P: IsA<Clip>,
1165            F: Fn(&P) + 'static,
1166        >(
1167            this: *mut ffi::GESClip,
1168            _param_spec: glib::ffi::gpointer,
1169            f: glib::ffi::gpointer,
1170        ) {
1171            let f: &F = &*(f as *const F);
1172            f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1173        }
1174        unsafe {
1175            let f: Box_<F> = Box_::new(f);
1176            connect_raw(
1177                self.as_ptr() as *mut _,
1178                c"notify::supported-formats".as_ptr() as *const _,
1179                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1180                    notify_supported_formats_trampoline::<Self, F> as *const (),
1181                )),
1182                Box_::into_raw(f),
1183            )
1184        }
1185    }
1186}
1187
1188impl<O: IsA<Clip>> ClipExt for O {}