Skip to main content

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