Skip to main content

gstreamer_editing_services/auto/
timeline.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
7use crate::{
8    Asset, Extractable, Group, Layer, MetaContainer, TimelineElement, Track, TrackElement, ffi,
9};
10#[cfg(feature = "v1_18")]
11#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
12use crate::{Clip, FrameNumber};
13use glib::{
14    object::ObjectType as _,
15    prelude::*,
16    signal::{SignalHandlerId, connect_raw},
17    translate::*,
18};
19use std::boxed::Box as Box_;
20
21glib::wrapper! {
22    /// [`Timeline`][crate::Timeline] is the central object for any multimedia timeline.
23    ///
24    /// A timeline is composed of a set of [`Track`][crate::Track]-s and a set of
25    /// [`Layer`][crate::Layer]-s, which are added to the timeline using
26    /// [`TimelineExt::add_track()`][crate::prelude::TimelineExt::add_track()] and [`TimelineExt::append_layer()`][crate::prelude::TimelineExt::append_layer()], respectively.
27    ///
28    /// The contained tracks define the supported types of the timeline
29    /// and provide the media output. Essentially, each track provides an
30    /// additional source [`gst::Pad`][crate::gst::Pad].
31    ///
32    /// Most usage of a timeline will likely only need a single [`AudioTrack`][crate::AudioTrack]
33    /// and/or a single [`VideoTrack`][crate::VideoTrack]. You can create such a timeline with
34    /// [`new_audio_video()`][Self::new_audio_video()]. After this, you are unlikely to need to
35    /// work with the tracks directly.
36    ///
37    /// A timeline's layers contain [`Clip`][crate::Clip]-s, which in turn control the
38    /// creation of [`TrackElement`][crate::TrackElement]-s, which are added to the timeline's
39    /// tracks. See [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] if you wish to have
40    /// more control over which track a clip's elements are added to.
41    ///
42    /// The layers are ordered, with higher priority layers having their
43    /// content prioritised in the tracks. This ordering can be changed using
44    /// [`TimelineExt::move_layer()`][crate::prelude::TimelineExt::move_layer()].
45    ///
46    /// ## Editing
47    ///
48    /// See [`TimelineElement`][crate::TimelineElement] for the various ways the elements of a timeline
49    /// can be edited.
50    ///
51    /// If you change the timing or ordering of a timeline's
52    /// [`TimelineElement`][crate::TimelineElement]-s, then these changes will not actually be taken
53    /// into account in the output of the timeline's tracks until the
54    /// [`TimelineExt::commit()`][crate::prelude::TimelineExt::commit()] method is called. This allows you to move its
55    /// elements around, say, in response to an end user's mouse dragging, with
56    /// little expense before finalising their effect on the produced data.
57    ///
58    /// ## Overlaps and Auto-Transitions
59    ///
60    /// There are certain restrictions placed on how [`Source`][crate::Source]-s may overlap
61    /// in a [`Track`][crate::Track] that belongs to a timeline. These will be enforced by
62    /// GES, so the user will not need to keep track of them, but they should
63    /// be aware that certain edits will be refused as a result if the overlap
64    /// rules would be broken.
65    ///
66    /// Consider two [`Source`][crate::Source]-s, `A` and `B`, with start times `startA` and
67    /// `startB`, and end times `endA` and `endB`, respectively. The start
68    /// time refers to their [`start`][struct@crate::TimelineElement#start], and the end time is
69    /// their [`start`][struct@crate::TimelineElement#start] + [`duration`][struct@crate::TimelineElement#duration]. These
70    /// two sources *overlap* if:
71    ///
72    /// + they share the same [`track`][struct@crate::TrackElement#track] (non [`None`]), which belongs
73    ///  to the timeline;
74    /// + they share the same `GES_TIMELINE_ELEMENT_LAYER_PRIORITY`; and
75    /// + `startA < endB` and `startB < endA `.
76    ///
77    /// Note that when `startA = endB` or `startB = endA` then the two sources
78    /// will *touch* at their edges, but are not considered overlapping.
79    ///
80    /// If, in addition, `startA < startB < endA`, then we can say that the
81    /// end of `A` overlaps the start of `B`.
82    ///
83    /// If, instead, `startA <= startB` and `endA >= endB`, then we can say
84    /// that `A` fully overlaps `B`.
85    ///
86    /// The overlap rules for a timeline are that:
87    ///
88    /// 1. One source cannot fully overlap another source.
89    /// 2. A source can only overlap the end of up to one other source at its
90    ///  start.
91    /// 3. A source can only overlap the start of up to one other source at its
92    ///  end.
93    ///
94    /// The last two rules combined essentially mean that at any given timeline
95    /// position, only up to two [`Source`][crate::Source]-s may overlap at that position. So
96    /// triple or more overlaps are not allowed.
97    ///
98    /// If you switch on [`auto-transition`][struct@crate::Timeline#auto-transition], then at any moment when
99    /// the end of one source (the first source) overlaps the start of another
100    /// (the second source), a [`TransitionClip`][crate::TransitionClip] will be automatically created
101    /// for the pair in the same layer and it will cover their overlap. If the
102    /// two elements are edited in a way such that the end of the first source
103    /// no longer overlaps the start of the second, the transition will be
104    /// automatically removed from the timeline. However, if the two sources
105    /// still overlap at the same edges after the edit, then the same
106    /// transition object will be kept, but with its timing and layer adjusted
107    /// accordingly.
108    ///
109    /// NOTE: if you know what you are doing and want to be in full control of the
110    /// timeline layout, you can disable the edit APIs with
111    /// `ges_timeline_disable_edit_apis`.
112    ///
113    /// ## Saving
114    ///
115    /// To save/load a timeline, you can use the [`TimelineExt::load_from_uri()`][crate::prelude::TimelineExt::load_from_uri()]
116    /// and [`TimelineExt::save_to_uri()`][crate::prelude::TimelineExt::save_to_uri()] methods that use the default format.
117    ///
118    /// ## Playing
119    ///
120    /// A timeline is a [`gst::Bin`][crate::gst::Bin] with a source [`gst::Pad`][crate::gst::Pad] for each of its
121    /// tracks, which you can fetch with [`TimelineExt::pad_for_track()`][crate::prelude::TimelineExt::pad_for_track()]. You
122    /// will likely want to link these to some compatible sink [`gst::Element`][crate::gst::Element]-s to
123    /// be able to play or capture the content of the timeline.
124    ///
125    /// You can use a [`Pipeline`][crate::Pipeline] to easily preview/play the timeline's
126    /// content, or render it to a file.
127    ///
128    /// ## Properties
129    ///
130    ///
131    /// #### `auto-transition`
132    ///  Whether to automatically create a transition whenever two
133    /// [`Source`][crate::Source]-s overlap in a track of the timeline. See
134    /// [`auto-transition`][struct@crate::Layer#auto-transition] if you want this to only happen in some
135    /// layers.
136    ///
137    /// Readable | Writeable
138    ///
139    ///
140    /// #### `duration`
141    ///  The current duration (in nanoseconds) of the timeline. A timeline
142    /// 'starts' at time 0, so this is the maximum end time of all of its
143    /// [`TimelineElement`][crate::TimelineElement]-s.
144    ///
145    /// Readable
146    ///
147    ///
148    /// #### `snapping-distance`
149    ///  The distance (in nanoseconds) at which a [`TimelineElement`][crate::TimelineElement] being
150    /// moved within the timeline should snap one of its [`Source`][crate::Source]-s with
151    /// another [`Source`][crate::Source]-s edge. See [`EditMode`][crate::EditMode] for which edges can
152    /// snap during an edit. 0 means no snapping.
153    ///
154    /// Readable | Writeable
155    /// <details><summary><h4>Bin</h4></summary>
156    ///
157    ///
158    /// #### `async-handling`
159    ///  If set to [`true`], the bin will handle asynchronous state changes.
160    /// This should be used only if the bin subclass is modifying the state
161    /// of its children on its own.
162    ///
163    /// Readable | Writeable
164    ///
165    ///
166    /// #### `message-forward`
167    ///  Forward all children messages, even those that would normally be filtered by
168    /// the bin. This can be interesting when one wants to be notified of the EOS
169    /// state of individual elements, for example.
170    ///
171    /// The messages are converted to an ELEMENT message with the bin as the
172    /// source. The structure of the message is named `GstBinForwarded` and contains
173    /// a field named `message` that contains the original forwarded `GstMessage`.
174    ///
175    /// Readable | Writeable
176    /// </details>
177    /// <details><summary><h4>Object</h4></summary>
178    ///
179    ///
180    /// #### `name`
181    ///  Readable | Writeable | Construct
182    ///
183    ///
184    /// #### `parent`
185    ///  The parent of the object. Please note, that when changing the 'parent'
186    /// property, we don't emit [`notify`][struct@crate::glib::Object#notify] and [`deep-notify`][struct@crate::gst::Object#deep-notify]
187    /// signals due to locking issues. In some cases one can use
188    /// [`element-added`][struct@crate::gst::Bin#element-added] or [`element-removed`][struct@crate::gst::Bin#element-removed] signals on the parent to
189    /// achieve a similar effect.
190    ///
191    /// Readable | Writeable
192    /// </details>
193    ///
194    /// ## Signals
195    ///
196    ///
197    /// #### `commited`
198    ///  This signal will be emitted once the changes initiated by
199    /// [`TimelineExt::commit()`][crate::prelude::TimelineExt::commit()] have been executed in the backend. Use
200    /// [`TimelineExt::commit_sync()`][crate::prelude::TimelineExt::commit_sync()] if you do not want to have to connect
201    /// to this signal.
202    ///
203    ///
204    ///
205    ///
206    /// #### `group-added`
207    ///  Will be emitted after the group is added to to the timeline. This can
208    /// happen when grouping with `ges_container_group`, or by adding
209    /// containers to a newly created group.
210    ///
211    /// Note that this should not be emitted whilst a timeline is being
212    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
213    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which groups
214    /// were created for the timeline.
215    ///
216    ///
217    ///
218    ///
219    /// #### `group-removed`
220    ///  Will be emitted after the group is removed from the timeline through
221    /// `ges_container_ungroup`. Note that `group` will no longer contain its
222    /// former children, these are held in `children`.
223    ///
224    /// Note that if a group is emptied, then it will no longer belong to the
225    /// timeline, but this signal will **not** be emitted in such a case.
226    ///
227    ///
228    ///
229    ///
230    /// #### `layer-added`
231    ///  Will be emitted after the layer is added to the timeline.
232    ///
233    /// Note that this should not be emitted whilst a timeline is being
234    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
235    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
236    /// layers were created for the timeline.
237    ///
238    ///
239    ///
240    ///
241    /// #### `layer-removed`
242    ///  Will be emitted after the layer is removed from the timeline.
243    ///
244    ///
245    ///
246    ///
247    /// #### `select-element-track`
248    ///  Simplified version of [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] which only
249    /// allows `track_element` to be added to a single [`Track`][crate::Track].
250    ///
251    ///
252    ///
253    ///
254    /// #### `select-tracks-for-object`
255    ///  This will be emitted whenever the timeline needs to determine which
256    /// tracks a clip's children should be added to. The track element will
257    /// be added to each of the tracks given in the return. If a track
258    /// element is selected to go into multiple tracks, it will be copied
259    /// into the additional tracks, under the same clip. Note that the copy
260    /// will *not* keep its properties or state in sync with the original.
261    ///
262    /// Connect to this signal once if you wish to control which element
263    /// should be added to which track. Doing so will overwrite the default
264    /// behaviour, which adds `track_element` to all tracks whose
265    /// [`track-type`][struct@crate::Track#track-type] includes the `track_element`'s
266    /// [`track-type`][struct@crate::TrackElement#track-type].
267    ///
268    /// Note that under the default track selection, if a clip would produce
269    /// multiple core children of the same [`TrackType`][crate::TrackType], it will choose
270    /// one of the core children arbitrarily to place in the corresponding
271    /// tracks, with a warning for the other core children that are not
272    /// placed in the track. For example, this would happen for a [`UriClip`][crate::UriClip]
273    /// that points to a file that contains multiple audio streams. If you
274    /// wish to choose the stream, you could connect to this signal, and use,
275    /// say, [`UriSourceAssetExt::stream_info()`][crate::prelude::UriSourceAssetExt::stream_info()] to choose which core
276    /// source to add.
277    ///
278    /// When a clip is first added to a timeline, its core elements will
279    /// be created for the current tracks in the timeline if they have not
280    /// already been created. Then this will be emitted for each of these
281    /// core children to select which tracks, if any, they should be added
282    /// to. It will then be called for any non-core children in the clip.
283    ///
284    /// In addition, if a new track element is ever added to a clip in a
285    /// timeline (and it is not already part of a track) this will be emitted
286    /// to select which tracks the element should be added to.
287    ///
288    /// Finally, as a special case, if a track is added to the timeline
289    /// *after* it already contains clips, then it will request the creation
290    /// of the clips' core elements of the corresponding type, if they have
291    /// not already been created, and this signal will be emitted for each of
292    /// these newly created elements. In addition, this will also be released
293    /// for all other track elements in the timeline's clips that have not
294    /// yet been assigned a track. However, in this final case, the timeline
295    /// will only check whether the newly added track appears in the track
296    /// list. If it does appear, the track element will be added to the newly
297    /// added track. All other tracks in the returned track list are ignored.
298    ///
299    /// In this latter case, track elements that are already part of a track
300    /// will not be asked if they want to be copied into the new track. If
301    /// you wish to do this, you can use [`ClipExt::add_child_to_track()`][crate::prelude::ClipExt::add_child_to_track()].
302    ///
303    /// Note that the returned `GPtrArray` should own a new reference to each
304    /// of its contained [`Track`][crate::Track]. The timeline will set the `GDestroyNotify`
305    /// free function on the `GPtrArray` to dereference the elements.
306    ///
307    ///
308    ///
309    ///
310    /// #### `snapping-ended`
311    ///  Will be emitted whenever a snapping event ends. After a snap event
312    /// has started (see [`snapping-started`][struct@crate::Timeline#snapping-started]), it can later end
313    /// because either another timeline edit has occurred (which may or may
314    /// not have created a new snapping event), or because the timeline has
315    /// been committed.
316    ///
317    ///
318    ///
319    ///
320    /// #### `snapping-started`
321    ///  Will be emitted whenever an element's movement invokes a snapping
322    /// event during an edit (usually of one of its ancestors) because its
323    /// start or end point lies within the [`snapping-distance`][struct@crate::Timeline#snapping-distance] of
324    /// another element's start or end point.
325    ///
326    /// See [`EditMode`][crate::EditMode] to see what can snap during an edit.
327    ///
328    /// Note that only up to one snapping-started signal will be emitted per
329    /// element edit within a timeline.
330    ///
331    ///
332    ///
333    ///
334    /// #### `track-added`
335    ///  Will be emitted after the track is added to the timeline.
336    ///
337    /// Note that this should not be emitted whilst a timeline is being
338    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
339    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
340    /// tracks were created for the timeline.
341    ///
342    ///
343    ///
344    ///
345    /// #### `track-removed`
346    ///  Will be emitted after the track is removed from the timeline.
347    ///
348    ///
349    /// <details><summary><h4>Bin</h4></summary>
350    ///
351    ///
352    /// #### `deep-element-added`
353    ///  Will be emitted after the element was added to `sub_bin`.
354    ///
355    ///
356    ///
357    ///
358    /// #### `deep-element-removed`
359    ///  Will be emitted after the element was removed from `sub_bin`.
360    ///
361    ///
362    ///
363    ///
364    /// #### `do-latency`
365    ///  Will be emitted when the bin needs to perform latency calculations. This
366    /// signal is only emitted for toplevel bins or when [`async-handling`][struct@crate::gst::Bin#async-handling] is
367    /// enabled.
368    ///
369    /// Only one signal handler is invoked. If no signals are connected, the
370    /// default handler is invoked, which will query and distribute the lowest
371    /// possible latency to all sinks.
372    ///
373    /// Connect to this signal if the default latency calculations are not
374    /// sufficient, like when you need different latencies for different sinks in
375    /// the same pipeline.
376    ///
377    ///
378    ///
379    ///
380    /// #### `element-added`
381    ///  Will be emitted after the element was added to the bin.
382    ///
383    ///
384    ///
385    ///
386    /// #### `element-removed`
387    ///  Will be emitted after the element was removed from the bin.
388    ///
389    ///
390    /// </details>
391    /// <details><summary><h4>Element</h4></summary>
392    ///
393    ///
394    /// #### `no-more-pads`
395    ///  This signals that the element will not generate more dynamic pads.
396    /// Note that this signal will usually be emitted from the context of
397    /// the streaming thread.
398    ///
399    ///
400    ///
401    ///
402    /// #### `pad-added`
403    ///  a new [`gst::Pad`][crate::gst::Pad] has been added to the element. Note that this signal will
404    /// usually be emitted from the context of the streaming thread. Also keep in
405    /// mind that if you add new elements to the pipeline in the signal handler
406    /// you will need to set them to the desired target state with
407    /// [`ElementExtManual::set_state()`][crate::gst::prelude::ElementExtManual::set_state()] or [`ElementExtManual::sync_state_with_parent()`][crate::gst::prelude::ElementExtManual::sync_state_with_parent()].
408    ///
409    ///
410    ///
411    ///
412    /// #### `pad-removed`
413    ///  a [`gst::Pad`][crate::gst::Pad] has been removed from the element
414    ///
415    ///
416    /// </details>
417    /// <details><summary><h4>Object</h4></summary>
418    ///
419    ///
420    /// #### `deep-notify`
421    ///  The deep notify signal is used to be notified of property changes. It is
422    /// typically attached to the toplevel bin to receive notifications from all
423    /// the elements contained in that bin.
424    ///
425    /// Detailed
426    /// </details>
427    /// <details><summary><h4>ChildProxy</h4></summary>
428    ///
429    ///
430    /// #### `child-added`
431    ///  Will be emitted after the `object` was added to the `child_proxy`.
432    ///
433    ///
434    ///
435    ///
436    /// #### `child-removed`
437    ///  Will be emitted after the `object` was removed from the `child_proxy`.
438    ///
439    ///
440    /// </details>
441    /// <details><summary><h4>MetaContainer</h4></summary>
442    ///
443    ///
444    /// #### `notify-meta`
445    ///  This is emitted for a meta container whenever the metadata under one
446    /// of its fields changes, is set for the first time, or is removed. In
447    /// the latter case, `value` will be [`None`].
448    ///
449    /// Detailed
450    /// </details>
451    ///
452    /// # Implements
453    ///
454    /// [`TimelineExt`][trait@crate::prelude::TimelineExt], [`trait@gst::prelude::BinExt`], [`trait@gst::prelude::ElementExt`], [`trait@gst::prelude::GstObjectExt`], [`trait@glib::ObjectExt`], [`trait@gst::prelude::ChildProxyExt`], [`ExtractableExt`][trait@crate::prelude::ExtractableExt], [`MetaContainerExt`][trait@crate::prelude::MetaContainerExt]
455    #[doc(alias = "GESTimeline")]
456    pub struct Timeline(Object<ffi::GESTimeline, ffi::GESTimelineClass>) @extends gst::Bin, gst::Element, gst::Object, @implements gst::ChildProxy, Extractable, MetaContainer;
457
458    match fn {
459        type_ => || ffi::ges_timeline_get_type(),
460    }
461}
462
463impl Timeline {
464    pub const NONE: Option<&'static Timeline> = None;
465
466    /// Creates a new empty timeline.
467    ///
468    /// # Returns
469    ///
470    /// The new timeline.
471    #[doc(alias = "ges_timeline_new")]
472    pub fn new() -> Timeline {
473        assert_initialized_main_thread!();
474        unsafe { from_glib_none(ffi::ges_timeline_new()) }
475    }
476
477    /// Creates a new timeline containing a single [`AudioTrack`][crate::AudioTrack] and a
478    /// single [`VideoTrack`][crate::VideoTrack].
479    ///
480    /// # Returns
481    ///
482    /// The new timeline.
483    #[doc(alias = "ges_timeline_new_audio_video")]
484    pub fn new_audio_video() -> Timeline {
485        assert_initialized_main_thread!();
486        unsafe { from_glib_none(ffi::ges_timeline_new_audio_video()) }
487    }
488
489    /// Creates a timeline from the given URI.
490    /// ## `uri`
491    /// The URI to load from
492    ///
493    /// # Returns
494    ///
495    /// A new timeline if the uri was loaded
496    /// successfully, or [`None`] if the uri could not be loaded.
497    #[doc(alias = "ges_timeline_new_from_uri")]
498    #[doc(alias = "new_from_uri")]
499    pub fn from_uri(uri: &str) -> Result<Timeline, glib::Error> {
500        assert_initialized_main_thread!();
501        unsafe {
502            let mut error = std::ptr::null_mut();
503            let ret = ffi::ges_timeline_new_from_uri(uri.to_glib_none().0, &mut error);
504            if error.is_null() {
505                Ok(from_glib_none(ret))
506            } else {
507                Err(from_glib_full(error))
508            }
509        }
510    }
511}
512
513impl Default for Timeline {
514    fn default() -> Self {
515        Self::new()
516    }
517}
518
519/// Trait containing all [`struct@Timeline`] methods.
520///
521/// # Implementors
522///
523/// [`Timeline`][struct@crate::Timeline]
524pub trait TimelineExt: IsA<Timeline> + 'static {
525    /// Add a layer to the timeline.
526    ///
527    /// If the layer contains [`Clip`][crate::Clip]-s, then this may trigger the creation of
528    /// their core track element children for the timeline's tracks, and the
529    /// placement of the clip's children in the tracks of the timeline using
530    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Some errors may occur if this
531    /// would break one of the configuration rules of the timeline in one of
532    /// its tracks. In such cases, some track elements would fail to be added
533    /// to their tracks, but this method would still return [`true`]. As such, it
534    /// is advised that you only add clips to layers that already part of a
535    /// timeline. In such situations, [`LayerExt::add_clip()`][crate::prelude::LayerExt::add_clip()] is able to fail if
536    /// adding the clip would cause such an error.
537    ///
538    /// # Deprecated since 1.18
539    ///
540    /// This method requires you to ensure the layer's
541    /// [`priority`][struct@crate::Layer#priority] will be unique to the timeline. Use
542    /// [`append_layer()`][Self::append_layer()] and [`move_layer()`][Self::move_layer()] instead.
543    /// ## `layer`
544    /// The layer to add
545    ///
546    /// # Returns
547    ///
548    /// [`true`] if `layer` was properly added.
549    #[cfg_attr(feature = "v1_18", deprecated = "Since 1.18")]
550    #[allow(deprecated)]
551    #[doc(alias = "ges_timeline_add_layer")]
552    fn add_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
553        unsafe {
554            glib::result_from_gboolean!(
555                ffi::ges_timeline_add_layer(
556                    self.as_ref().to_glib_none().0,
557                    layer.as_ref().to_glib_none().0
558                ),
559                "Failed to add layer"
560            )
561        }
562    }
563
564    /// Add a track to the timeline.
565    ///
566    /// If the timeline already contains clips, then this may trigger the
567    /// creation of their core track element children for the track, and the
568    /// placement of the clip's children in the track of the timeline using
569    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Some errors may occur if this
570    /// would break one of the configuration rules for the timeline in the
571    /// track. In such cases, some track elements would fail to be added to the
572    /// track, but this method would still return [`true`]. As such, it is advised
573    /// that you avoid adding tracks to timelines that already contain clips.
574    /// ## `track`
575    /// The track to add
576    ///
577    /// # Returns
578    ///
579    /// [`true`] if `track` was properly added.
580    #[doc(alias = "ges_timeline_add_track")]
581    fn add_track(&self, track: &impl IsA<Track>) -> Result<(), glib::error::BoolError> {
582        unsafe {
583            glib::result_from_gboolean!(
584                ffi::ges_timeline_add_track(
585                    self.as_ref().to_glib_none().0,
586                    track.as_ref().to_glib_none().0
587                ),
588                "Failed to add track"
589            )
590        }
591    }
592
593    /// Append a newly created layer to the timeline. The layer will
594    /// be added at the lowest [`priority`][struct@crate::Layer#priority] (numerically, the highest).
595    ///
596    /// # Returns
597    ///
598    /// The newly created layer.
599    #[doc(alias = "ges_timeline_append_layer")]
600    fn append_layer(&self) -> Layer {
601        unsafe {
602            from_glib_none(ffi::ges_timeline_append_layer(
603                self.as_ref().to_glib_none().0,
604            ))
605        }
606    }
607
608    /// Commit all the pending changes of the clips contained in the
609    /// timeline.
610    ///
611    /// When changes happen in a timeline, they are not immediately executed
612    /// internally, in a way that effects the output data of the timeline. You
613    /// should call this method when you are done with a set of changes and you
614    /// want them to be executed.
615    ///
616    /// Any pending changes will be executed in the backend. The
617    /// [`commited`][struct@crate::Timeline#commited] signal will be emitted once this has completed.
618    /// You should not try to change the state of the timeline, seek it or add
619    /// tracks to it before receiving this signal. You can use
620    /// [`commit_sync()`][Self::commit_sync()] if you do not want to perform other tasks in
621    /// the mean time.
622    ///
623    /// Note that all the pending changes will automatically be executed when
624    /// the timeline goes from [`gst::State::Ready`][crate::gst::State::Ready] to [`gst::State::Paused`][crate::gst::State::Paused], which is
625    /// usually triggered by a corresponding state changes in a containing
626    /// [`Pipeline`][crate::Pipeline].
627    ///
628    /// # Returns
629    ///
630    /// [`true`] if pending changes were committed, or [`false`] if nothing
631    /// needed to be committed.
632    #[doc(alias = "ges_timeline_commit")]
633    fn commit(&self) -> bool {
634        unsafe { from_glib(ffi::ges_timeline_commit(self.as_ref().to_glib_none().0)) }
635    }
636
637    /// Commit all the pending changes of the clips contained in the
638    /// timeline and wait for the changes to complete.
639    ///
640    /// See [`commit()`][Self::commit()].
641    ///
642    /// # Returns
643    ///
644    /// [`true`] if pending changes were committed, or [`false`] if nothing
645    /// needed to be committed.
646    #[doc(alias = "ges_timeline_commit_sync")]
647    fn commit_sync(&self) -> bool {
648        unsafe {
649            from_glib(ffi::ges_timeline_commit_sync(
650                self.as_ref().to_glib_none().0,
651            ))
652        }
653    }
654
655    /// WARNING: When using that mode, GES won't guarantee the coherence of the
656    /// timeline. You need to ensure that the rules described in the [Overlaps and
657    /// auto transitions](`overlaps`-and-autotransitions) section are respected any time
658    /// the timeline is [commited](ges_timeline_commit) (otherwise playback will most
659    /// probably fail in different ways).
660    ///
661    /// When disabling editing APIs, GES won't be able to enforce the rules that
662    /// makes the timeline overall state to be valid but some feature won't be
663    /// usable:
664    ///  * [`snapping-distance`][struct@crate::Timeline#snapping-distance]
665    ///  * [`auto-transition`][struct@crate::Timeline#auto-transition]
666    /// ## `disable_edit_apis`
667    /// [`true`] to disable all the edit APIs so the user is in full
668    /// control of ensuring timeline state validity [`false`] otherwise.
669    #[cfg(feature = "v1_22")]
670    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
671    #[doc(alias = "ges_timeline_disable_edit_apis")]
672    fn disable_edit_apis(&self, disable_edit_apis: bool) {
673        unsafe {
674            ffi::ges_timeline_disable_edit_apis(
675                self.as_ref().to_glib_none().0,
676                disable_edit_apis.into_glib(),
677            );
678        }
679    }
680
681    /// Freezes the timeline from being committed. This is usually needed while the
682    /// timeline is being rendered to ensure that not change to the timeline are
683    /// taken into account during that moment. Once the rendering is done, you
684    /// should call `ges_timeline_thaw_commit` so that committing becomes possible
685    /// again and any call to ``commit()`` that happened during the rendering is
686    /// actually taken into account.
687    #[cfg(feature = "v1_20")]
688    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
689    #[doc(alias = "ges_timeline_freeze_commit")]
690    fn freeze_commit(&self) {
691        unsafe {
692            ffi::ges_timeline_freeze_commit(self.as_ref().to_glib_none().0);
693        }
694    }
695
696    /// Gets [`auto-transition`][struct@crate::Timeline#auto-transition] for the timeline.
697    ///
698    /// # Returns
699    ///
700    /// The auto-transition of `self_`.
701    #[doc(alias = "ges_timeline_get_auto_transition")]
702    #[doc(alias = "get_auto_transition")]
703    #[doc(alias = "auto-transition")]
704    fn is_auto_transition(&self) -> bool {
705        unsafe {
706            from_glib(ffi::ges_timeline_get_auto_transition(
707                self.as_ref().to_glib_none().0,
708            ))
709        }
710    }
711
712    /// Get the current [`duration`][struct@crate::Timeline#duration] of the timeline
713    ///
714    /// # Returns
715    ///
716    /// The current duration of `self`.
717    #[doc(alias = "ges_timeline_get_duration")]
718    #[doc(alias = "get_duration")]
719    fn duration(&self) -> gst::ClockTime {
720        unsafe {
721            try_from_glib(ffi::ges_timeline_get_duration(
722                self.as_ref().to_glib_none().0,
723            ))
724            .expect("mandatory glib value is None")
725        }
726    }
727
728    ///
729    /// # Returns
730    ///
731    /// [`true`] if edit APIs are disabled, [`false`] otherwise.
732    #[cfg(feature = "v1_22")]
733    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
734    #[doc(alias = "ges_timeline_get_edit_apis_disabled")]
735    #[doc(alias = "get_edit_apis_disabled")]
736    fn is_edit_apis_disabled(&self) -> bool {
737        unsafe {
738            from_glib(ffi::ges_timeline_get_edit_apis_disabled(
739                self.as_ref().to_glib_none().0,
740            ))
741        }
742    }
743
744    /// Gets the element contained in the timeline with the given name.
745    /// ## `name`
746    /// The name of the element to find
747    ///
748    /// # Returns
749    ///
750    /// The timeline element in `self`
751    /// with the given `name`, or [`None`] if it was not found.
752    #[doc(alias = "ges_timeline_get_element")]
753    #[doc(alias = "get_element")]
754    fn element(&self, name: &str) -> Option<TimelineElement> {
755        unsafe {
756            from_glib_full(ffi::ges_timeline_get_element(
757                self.as_ref().to_glib_none().0,
758                name.to_glib_none().0,
759            ))
760        }
761    }
762
763    /// This method allows you to convert a timeline `GstClockTime` into its
764    /// corresponding `GESFrameNumber` in the timeline's output.
765    /// ## `timestamp`
766    /// The timestamp to get the corresponding frame number of
767    ///
768    /// # Returns
769    ///
770    /// The frame number `timestamp` corresponds to.
771    #[cfg(feature = "v1_18")]
772    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
773    #[doc(alias = "ges_timeline_get_frame_at")]
774    #[doc(alias = "get_frame_at")]
775    fn frame_at(&self, timestamp: gst::ClockTime) -> FrameNumber {
776        unsafe {
777            ffi::ges_timeline_get_frame_at(self.as_ref().to_glib_none().0, timestamp.into_glib())
778        }
779    }
780
781    /// This method allows you to convert a timeline output frame number into a
782    /// timeline `GstClockTime`. For example, this time could be used to seek to a
783    /// particular frame in the timeline's output, or as the edit position for
784    /// an element within the timeline.
785    /// ## `frame_number`
786    /// The frame number to get the corresponding timestamp of in the
787    ///  timeline coordinates
788    ///
789    /// # Returns
790    ///
791    /// The timestamp corresponding to `frame_number` in the output of `self`.
792    #[cfg(feature = "v1_18")]
793    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
794    #[doc(alias = "ges_timeline_get_frame_time")]
795    #[doc(alias = "get_frame_time")]
796    fn frame_time(&self, frame_number: FrameNumber) -> Option<gst::ClockTime> {
797        unsafe {
798            from_glib(ffi::ges_timeline_get_frame_time(
799                self.as_ref().to_glib_none().0,
800                frame_number,
801            ))
802        }
803    }
804
805    /// Get the list of [`Group`][crate::Group]-s present in the timeline.
806    ///
807    /// # Deprecated since 1.30
808    ///
809    /// Use [`groups_full()`][Self::groups_full()] instead for MT-safety.
810    ///
811    /// # Returns
812    ///
813    /// The list of
814    /// groups that contain clips present in `self`'s layers.
815    /// Must not be changed.
816    #[cfg_attr(feature = "v1_30", deprecated = "Since 1.30")]
817    #[allow(deprecated)]
818    #[doc(alias = "ges_timeline_get_groups")]
819    #[doc(alias = "get_groups")]
820    fn groups(&self) -> Vec<Group> {
821        unsafe {
822            FromGlibPtrContainer::from_glib_none(ffi::ges_timeline_get_groups(
823                self.as_ref().to_glib_none().0,
824            ))
825        }
826    }
827
828    /// Get the list of [`Group`][crate::Group]-s present in the timeline.
829    ///
830    /// # Returns
831    ///
832    /// The list of
833    /// groups that contain clips present in `self`'s layers.
834    #[cfg(feature = "v1_30")]
835    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
836    #[doc(alias = "ges_timeline_get_groups_full")]
837    #[doc(alias = "get_groups_full")]
838    fn groups_full(&self) -> Vec<Group> {
839        unsafe {
840            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_groups_full(
841                self.as_ref().to_glib_none().0,
842            ))
843        }
844    }
845
846    /// Retrieve the layer whose index in the timeline matches the given
847    /// priority.
848    /// ## `priority`
849    /// The priority/index of the layer to find
850    ///
851    /// # Returns
852    ///
853    /// The layer with the given
854    /// `priority`, or [`None`] if none was found.
855    ///
856    /// Since 1.6
857    #[doc(alias = "ges_timeline_get_layer")]
858    #[doc(alias = "get_layer")]
859    fn layer(&self, priority: u32) -> Option<Layer> {
860        unsafe {
861            from_glib_full(ffi::ges_timeline_get_layer(
862                self.as_ref().to_glib_none().0,
863                priority,
864            ))
865        }
866    }
867
868    /// Get the list of [`Layer`][crate::Layer]-s present in the timeline.
869    ///
870    /// # Returns
871    ///
872    /// The list of
873    /// layers present in `self` sorted by priority.
874    #[doc(alias = "ges_timeline_get_layers")]
875    #[doc(alias = "get_layers")]
876    fn layers(&self) -> Vec<Layer> {
877        unsafe {
878            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_layers(
879                self.as_ref().to_glib_none().0,
880            ))
881        }
882    }
883
884    /// Search for the [`gst::Pad`][crate::gst::Pad] corresponding to the given timeline's track.
885    /// You can link to this pad to receive the output data of the given track.
886    /// ## `track`
887    /// A track
888    ///
889    /// # Returns
890    ///
891    /// The pad corresponding to `track`,
892    /// or [`None`] if there is an error.
893    #[doc(alias = "ges_timeline_get_pad_for_track")]
894    #[doc(alias = "get_pad_for_track")]
895    fn pad_for_track(&self, track: &impl IsA<Track>) -> Option<gst::Pad> {
896        unsafe {
897            from_glib_none(ffi::ges_timeline_get_pad_for_track(
898                self.as_ref().to_glib_none().0,
899                track.as_ref().to_glib_none().0,
900            ))
901        }
902    }
903
904    /// Gets the [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline.
905    ///
906    /// # Returns
907    ///
908    /// The snapping distance (in nanoseconds) of `self`.
909    #[doc(alias = "ges_timeline_get_snapping_distance")]
910    #[doc(alias = "get_snapping_distance")]
911    #[doc(alias = "snapping-distance")]
912    fn snapping_distance(&self) -> Option<gst::ClockTime> {
913        unsafe {
914            from_glib(ffi::ges_timeline_get_snapping_distance(
915                self.as_ref().to_glib_none().0,
916            ))
917        }
918    }
919
920    /// Search for the [`Track`][crate::Track] corresponding to the given timeline's pad.
921    ///
922    /// # Deprecated since 1.30
923    ///
924    /// Use [`track_for_pad_full()`][Self::track_for_pad_full()] instead for MT-safety.
925    /// ## `pad`
926    /// A pad
927    ///
928    /// # Returns
929    ///
930    /// The track corresponding to `pad`,
931    /// or [`None`] if there is an error.
932    #[cfg_attr(feature = "v1_30", deprecated = "Since 1.30")]
933    #[allow(deprecated)]
934    #[doc(alias = "ges_timeline_get_track_for_pad")]
935    #[doc(alias = "get_track_for_pad")]
936    fn track_for_pad(&self, pad: &impl IsA<gst::Pad>) -> Option<Track> {
937        unsafe {
938            from_glib_none(ffi::ges_timeline_get_track_for_pad(
939                self.as_ref().to_glib_none().0,
940                pad.as_ref().to_glib_none().0,
941            ))
942        }
943    }
944
945    /// Search for the [`Track`][crate::Track] corresponding to the given timeline's pad.
946    /// ## `pad`
947    /// A pad
948    ///
949    /// # Returns
950    ///
951    /// The track corresponding to `pad`,
952    /// or [`None`] if there is an error.
953    #[cfg(feature = "v1_30")]
954    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
955    #[doc(alias = "ges_timeline_get_track_for_pad_full")]
956    #[doc(alias = "get_track_for_pad_full")]
957    fn track_for_pad_full(&self, pad: &impl IsA<gst::Pad>) -> Option<Track> {
958        unsafe {
959            from_glib_full(ffi::ges_timeline_get_track_for_pad_full(
960                self.as_ref().to_glib_none().0,
961                pad.as_ref().to_glib_none().0,
962            ))
963        }
964    }
965
966    /// Get the list of [`Track`][crate::Track]-s used by the timeline.
967    ///
968    /// # Returns
969    ///
970    /// The list of tracks
971    /// used by `self`.
972    #[doc(alias = "ges_timeline_get_tracks")]
973    #[doc(alias = "get_tracks")]
974    fn tracks(&self) -> Vec<Track> {
975        unsafe {
976            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_tracks(
977                self.as_ref().to_glib_none().0,
978            ))
979        }
980    }
981
982    /// Check whether the timeline is empty or not.
983    ///
984    /// # Returns
985    ///
986    /// [`true`] if `self` is empty.
987    #[doc(alias = "ges_timeline_is_empty")]
988    fn is_empty(&self) -> bool {
989        unsafe { from_glib(ffi::ges_timeline_is_empty(self.as_ref().to_glib_none().0)) }
990    }
991
992    /// Loads the contents of URI into the timeline.
993    /// ## `uri`
994    /// The URI to load from
995    ///
996    /// # Returns
997    ///
998    /// [`true`] if the timeline was loaded successfully from `uri`.
999    #[doc(alias = "ges_timeline_load_from_uri")]
1000    fn load_from_uri(&self, uri: &str) -> Result<(), glib::Error> {
1001        unsafe {
1002            let mut error = std::ptr::null_mut();
1003            let is_ok = ffi::ges_timeline_load_from_uri(
1004                self.as_ref().to_glib_none().0,
1005                uri.to_glib_none().0,
1006                &mut error,
1007            );
1008            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1009            if error.is_null() {
1010                Ok(())
1011            } else {
1012                Err(from_glib_full(error))
1013            }
1014        }
1015    }
1016
1017    /// Moves a layer within the timeline to the index given by
1018    /// `new_layer_priority`.
1019    /// An index of 0 corresponds to the layer with the highest priority in a
1020    /// timeline. If `new_layer_priority` is greater than the number of layers
1021    /// present in the timeline, it will become the lowest priority layer.
1022    /// ## `layer`
1023    /// A layer within `self`, whose priority should be changed
1024    /// ## `new_layer_priority`
1025    /// The new index for `layer`
1026    #[cfg(feature = "v1_16")]
1027    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
1028    #[doc(alias = "ges_timeline_move_layer")]
1029    fn move_layer(
1030        &self,
1031        layer: &impl IsA<Layer>,
1032        new_layer_priority: u32,
1033    ) -> Result<(), glib::error::BoolError> {
1034        unsafe {
1035            glib::result_from_gboolean!(
1036                ffi::ges_timeline_move_layer(
1037                    self.as_ref().to_glib_none().0,
1038                    layer.as_ref().to_glib_none().0,
1039                    new_layer_priority
1040                ),
1041                "Failed to move layer"
1042            )
1043        }
1044    }
1045
1046    /// Paste an element inside the timeline. `element` **must** be the return of
1047    /// `ges_timeline_element_copy()` with `deep=TRUE`,
1048    /// and it should not be changed before pasting. `element` itself is not
1049    /// placed in the timeline, instead a new element is created, alike to the
1050    /// originally copied element. Note that the originally copied element must
1051    /// also lie within `self`, at both the point of copying and pasting.
1052    ///
1053    /// Pasting may fail if it would place the timeline in an unsupported
1054    /// configuration.
1055    ///
1056    /// After calling this function `element` should not be used. In particular,
1057    /// `element` can **not** be pasted again. Instead, you can copy the
1058    /// returned element and paste that copy (although, this is only possible
1059    /// if the paste was successful).
1060    ///
1061    /// See also [`TimelineElementExt::paste()`][crate::prelude::TimelineElementExt::paste()].
1062    /// ## `element`
1063    /// The element to paste
1064    /// ## `position`
1065    /// The position in the timeline `element` should be pasted to,
1066    /// i.e. the [`start`][struct@crate::TimelineElement#start] value for the pasted element.
1067    /// ## `layer_priority`
1068    /// The layer into which the element should be pasted.
1069    /// -1 means paste to the same layer from which `element` has been copied from
1070    ///
1071    /// # Returns
1072    ///
1073    /// The newly created element, or
1074    /// [`None`] if pasting fails.
1075    #[doc(alias = "ges_timeline_paste_element")]
1076    fn paste_element(
1077        &self,
1078        element: &impl IsA<TimelineElement>,
1079        position: gst::ClockTime,
1080        layer_priority: i32,
1081    ) -> Option<TimelineElement> {
1082        unsafe {
1083            from_glib_full(ffi::ges_timeline_paste_element(
1084                self.as_ref().to_glib_none().0,
1085                element.as_ref().to_glib_none().0,
1086                position.into_glib(),
1087                layer_priority,
1088            ))
1089        }
1090    }
1091
1092    /// Removes a layer from the timeline.
1093    /// ## `layer`
1094    /// The layer to remove
1095    ///
1096    /// # Returns
1097    ///
1098    /// [`true`] if `layer` was properly removed.
1099    #[doc(alias = "ges_timeline_remove_layer")]
1100    fn remove_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
1101        unsafe {
1102            glib::result_from_gboolean!(
1103                ffi::ges_timeline_remove_layer(
1104                    self.as_ref().to_glib_none().0,
1105                    layer.as_ref().to_glib_none().0
1106                ),
1107                "Failed to remove layer"
1108            )
1109        }
1110    }
1111
1112    /// Remove a track from the timeline.
1113    /// ## `track`
1114    /// The track to remove
1115    ///
1116    /// # Returns
1117    ///
1118    /// [`true`] if `track` was properly removed.
1119    #[doc(alias = "ges_timeline_remove_track")]
1120    fn remove_track(&self, track: &impl IsA<Track>) -> Result<(), glib::error::BoolError> {
1121        unsafe {
1122            glib::result_from_gboolean!(
1123                ffi::ges_timeline_remove_track(
1124                    self.as_ref().to_glib_none().0,
1125                    track.as_ref().to_glib_none().0
1126                ),
1127                "Failed to remove track"
1128            )
1129        }
1130    }
1131
1132    /// Saves the timeline to the given location. If `formatter_asset` is [`None`],
1133    /// the method will attempt to save in the same format the timeline was
1134    /// loaded from, before defaulting to the formatter with highest rank.
1135    /// ## `uri`
1136    /// The location to save to
1137    /// ## `formatter_asset`
1138    /// The formatter asset to use, or [`None`]
1139    /// ## `overwrite`
1140    /// [`true`] to overwrite file if it exists
1141    ///
1142    /// # Returns
1143    ///
1144    /// [`true`] if `self` was successfully saved to `uri`.
1145    #[doc(alias = "ges_timeline_save_to_uri")]
1146    fn save_to_uri(
1147        &self,
1148        uri: &str,
1149        formatter_asset: Option<&impl IsA<Asset>>,
1150        overwrite: bool,
1151    ) -> Result<(), glib::Error> {
1152        unsafe {
1153            let mut error = std::ptr::null_mut();
1154            let is_ok = ffi::ges_timeline_save_to_uri(
1155                self.as_ref().to_glib_none().0,
1156                uri.to_glib_none().0,
1157                formatter_asset.map(|p| p.as_ref()).to_glib_none().0,
1158                overwrite.into_glib(),
1159                &mut error,
1160            );
1161            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1162            if error.is_null() {
1163                Ok(())
1164            } else {
1165                Err(from_glib_full(error))
1166            }
1167        }
1168    }
1169
1170    /// Sets [`auto-transition`][struct@crate::Timeline#auto-transition] for the timeline. This will also set
1171    /// the corresponding [`auto-transition`][struct@crate::Layer#auto-transition] for all of the timeline's
1172    /// layers to the same value. See [`LayerExt::set_auto_transition()`][crate::prelude::LayerExt::set_auto_transition()] if you
1173    /// wish to set the layer's [`auto-transition`][struct@crate::Layer#auto-transition] individually.
1174    /// ## `auto_transition`
1175    /// Whether transitions should be automatically added
1176    /// to `self`'s layers
1177    #[doc(alias = "ges_timeline_set_auto_transition")]
1178    #[doc(alias = "auto-transition")]
1179    fn set_auto_transition(&self, auto_transition: bool) {
1180        unsafe {
1181            ffi::ges_timeline_set_auto_transition(
1182                self.as_ref().to_glib_none().0,
1183                auto_transition.into_glib(),
1184            );
1185        }
1186    }
1187
1188    /// Sets [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline. This new value
1189    /// will only effect future snappings and will not be used to snap the
1190    /// current element positions within the timeline.
1191    /// ## `snapping_distance`
1192    /// The snapping distance to use (in nanoseconds)
1193    #[doc(alias = "ges_timeline_set_snapping_distance")]
1194    #[doc(alias = "snapping-distance")]
1195    fn set_snapping_distance(&self, snapping_distance: gst::ClockTime) {
1196        unsafe {
1197            ffi::ges_timeline_set_snapping_distance(
1198                self.as_ref().to_glib_none().0,
1199                snapping_distance.into_glib(),
1200            );
1201        }
1202    }
1203
1204    /// Thaw the timeline so that comiting becomes possible
1205    /// again and any call to ``commit()`` that happened during the rendering is
1206    /// actually taken into account.
1207    #[cfg(feature = "v1_20")]
1208    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1209    #[doc(alias = "ges_timeline_thaw_commit")]
1210    fn thaw_commit(&self) {
1211        unsafe {
1212            ffi::ges_timeline_thaw_commit(self.as_ref().to_glib_none().0);
1213        }
1214    }
1215
1216    /// This signal will be emitted once the changes initiated by
1217    /// [`commit()`][Self::commit()] have been executed in the backend. Use
1218    /// [`commit_sync()`][Self::commit_sync()] if you do not want to have to connect
1219    /// to this signal.
1220    #[doc(alias = "commited")]
1221    fn connect_commited<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1222        unsafe extern "C" fn commited_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1223            this: *mut ffi::GESTimeline,
1224            f: glib::ffi::gpointer,
1225        ) {
1226            unsafe {
1227                let f: &F = &*(f as *const F);
1228                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1229            }
1230        }
1231        unsafe {
1232            let f: Box_<F> = Box_::new(f);
1233            connect_raw(
1234                self.as_ptr() as *mut _,
1235                c"commited".as_ptr(),
1236                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1237                    commited_trampoline::<Self, F> as *const (),
1238                )),
1239                Box_::into_raw(f),
1240            )
1241        }
1242    }
1243
1244    /// Will be emitted after the group is added to to the timeline. This can
1245    /// happen when grouping with `ges_container_group`, or by adding
1246    /// containers to a newly created group.
1247    ///
1248    /// Note that this should not be emitted whilst a timeline is being
1249    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1250    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which groups
1251    /// were created for the timeline.
1252    /// ## `group`
1253    /// The group that was added to `timeline`
1254    #[doc(alias = "group-added")]
1255    fn connect_group_added<F: Fn(&Self, &Group) + 'static>(&self, f: F) -> SignalHandlerId {
1256        unsafe extern "C" fn group_added_trampoline<
1257            P: IsA<Timeline>,
1258            F: Fn(&P, &Group) + 'static,
1259        >(
1260            this: *mut ffi::GESTimeline,
1261            group: *mut ffi::GESGroup,
1262            f: glib::ffi::gpointer,
1263        ) {
1264            unsafe {
1265                let f: &F = &*(f as *const F);
1266                f(
1267                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1268                    &from_glib_borrow(group),
1269                )
1270            }
1271        }
1272        unsafe {
1273            let f: Box_<F> = Box_::new(f);
1274            connect_raw(
1275                self.as_ptr() as *mut _,
1276                c"group-added".as_ptr(),
1277                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1278                    group_added_trampoline::<Self, F> as *const (),
1279                )),
1280                Box_::into_raw(f),
1281            )
1282        }
1283    }
1284
1285    //#[doc(alias = "group-removed")]
1286    //fn connect_group_removed<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1287    //    Empty ctype children: *.PtrArray TypeId { ns_id: 1, id: 54 }
1288    //}
1289
1290    /// Will be emitted after the layer is added to the timeline.
1291    ///
1292    /// Note that this should not be emitted whilst a timeline is being
1293    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1294    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1295    /// layers were created for the timeline.
1296    /// ## `layer`
1297    /// The layer that was added to `timeline`
1298    #[doc(alias = "layer-added")]
1299    fn connect_layer_added<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1300        unsafe extern "C" fn layer_added_trampoline<
1301            P: IsA<Timeline>,
1302            F: Fn(&P, &Layer) + 'static,
1303        >(
1304            this: *mut ffi::GESTimeline,
1305            layer: *mut ffi::GESLayer,
1306            f: glib::ffi::gpointer,
1307        ) {
1308            unsafe {
1309                let f: &F = &*(f as *const F);
1310                f(
1311                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1312                    &from_glib_borrow(layer),
1313                )
1314            }
1315        }
1316        unsafe {
1317            let f: Box_<F> = Box_::new(f);
1318            connect_raw(
1319                self.as_ptr() as *mut _,
1320                c"layer-added".as_ptr(),
1321                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1322                    layer_added_trampoline::<Self, F> as *const (),
1323                )),
1324                Box_::into_raw(f),
1325            )
1326        }
1327    }
1328
1329    /// Will be emitted after the layer is removed from the timeline.
1330    /// ## `layer`
1331    /// The layer that was removed from `timeline`
1332    #[doc(alias = "layer-removed")]
1333    fn connect_layer_removed<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1334        unsafe extern "C" fn layer_removed_trampoline<
1335            P: IsA<Timeline>,
1336            F: Fn(&P, &Layer) + 'static,
1337        >(
1338            this: *mut ffi::GESTimeline,
1339            layer: *mut ffi::GESLayer,
1340            f: glib::ffi::gpointer,
1341        ) {
1342            unsafe {
1343                let f: &F = &*(f as *const F);
1344                f(
1345                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1346                    &from_glib_borrow(layer),
1347                )
1348            }
1349        }
1350        unsafe {
1351            let f: Box_<F> = Box_::new(f);
1352            connect_raw(
1353                self.as_ptr() as *mut _,
1354                c"layer-removed".as_ptr(),
1355                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1356                    layer_removed_trampoline::<Self, F> as *const (),
1357                )),
1358                Box_::into_raw(f),
1359            )
1360        }
1361    }
1362
1363    /// Simplified version of [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] which only
1364    /// allows `track_element` to be added to a single [`Track`][crate::Track].
1365    /// ## `clip`
1366    /// The clip that `track_element` is being added to
1367    /// ## `track_element`
1368    /// The element being added
1369    ///
1370    /// # Returns
1371    ///
1372    /// A track to put `track_element` into, or [`None`] if
1373    /// it should be discarded.
1374    #[cfg(feature = "v1_18")]
1375    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1376    #[doc(alias = "select-element-track")]
1377    fn connect_select_element_track<
1378        F: Fn(&Self, &Clip, &TrackElement) -> Option<Track> + 'static,
1379    >(
1380        &self,
1381        f: F,
1382    ) -> SignalHandlerId {
1383        unsafe extern "C" fn select_element_track_trampoline<
1384            P: IsA<Timeline>,
1385            F: Fn(&P, &Clip, &TrackElement) -> Option<Track> + 'static,
1386        >(
1387            this: *mut ffi::GESTimeline,
1388            clip: *mut ffi::GESClip,
1389            track_element: *mut ffi::GESTrackElement,
1390            f: glib::ffi::gpointer,
1391        ) -> *mut ffi::GESTrack {
1392            unsafe {
1393                let f: &F = &*(f as *const F);
1394                f(
1395                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1396                    &from_glib_borrow(clip),
1397                    &from_glib_borrow(track_element),
1398                )
1399                .to_glib_full()
1400            }
1401        }
1402        unsafe {
1403            let f: Box_<F> = Box_::new(f);
1404            connect_raw(
1405                self.as_ptr() as *mut _,
1406                c"select-element-track".as_ptr(),
1407                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1408                    select_element_track_trampoline::<Self, F> as *const (),
1409                )),
1410                Box_::into_raw(f),
1411            )
1412        }
1413    }
1414
1415    //#[doc(alias = "select-tracks-for-object")]
1416    //fn connect_select_tracks_for_object<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1417    //    Empty ctype return value *.PtrArray TypeId { ns_id: 1, id: 17 }
1418    //}
1419
1420    /// Will be emitted whenever a snapping event ends. After a snap event
1421    /// has started (see [`snapping-started`][struct@crate::Timeline#snapping-started]), it can later end
1422    /// because either another timeline edit has occurred (which may or may
1423    /// not have created a new snapping event), or because the timeline has
1424    /// been committed.
1425    /// ## `obj1`
1426    /// The first element that was snapping
1427    /// ## `obj2`
1428    /// The second element that was snapping
1429    /// ## `position`
1430    /// The position where the two objects were to be snapped to
1431    #[doc(alias = "snapping-ended")]
1432    fn connect_snapping_ended<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1433        &self,
1434        f: F,
1435    ) -> SignalHandlerId {
1436        unsafe extern "C" fn snapping_ended_trampoline<
1437            P: IsA<Timeline>,
1438            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1439        >(
1440            this: *mut ffi::GESTimeline,
1441            obj1: *mut ffi::GESTrackElement,
1442            obj2: *mut ffi::GESTrackElement,
1443            position: u64,
1444            f: glib::ffi::gpointer,
1445        ) {
1446            unsafe {
1447                let f: &F = &*(f as *const F);
1448                f(
1449                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1450                    &from_glib_borrow(obj1),
1451                    &from_glib_borrow(obj2),
1452                    position,
1453                )
1454            }
1455        }
1456        unsafe {
1457            let f: Box_<F> = Box_::new(f);
1458            connect_raw(
1459                self.as_ptr() as *mut _,
1460                c"snapping-ended".as_ptr(),
1461                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1462                    snapping_ended_trampoline::<Self, F> as *const (),
1463                )),
1464                Box_::into_raw(f),
1465            )
1466        }
1467    }
1468
1469    /// Will be emitted whenever an element's movement invokes a snapping
1470    /// event during an edit (usually of one of its ancestors) because its
1471    /// start or end point lies within the [`snapping-distance`][struct@crate::Timeline#snapping-distance] of
1472    /// another element's start or end point.
1473    ///
1474    /// See [`EditMode`][crate::EditMode] to see what can snap during an edit.
1475    ///
1476    /// Note that only up to one snapping-started signal will be emitted per
1477    /// element edit within a timeline.
1478    /// ## `obj1`
1479    /// The first element that is snapping
1480    /// ## `obj2`
1481    /// The second element that is snapping
1482    /// ## `position`
1483    /// The position where the two objects will snap to
1484    #[doc(alias = "snapping-started")]
1485    fn connect_snapping_started<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1486        &self,
1487        f: F,
1488    ) -> SignalHandlerId {
1489        unsafe extern "C" fn snapping_started_trampoline<
1490            P: IsA<Timeline>,
1491            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1492        >(
1493            this: *mut ffi::GESTimeline,
1494            obj1: *mut ffi::GESTrackElement,
1495            obj2: *mut ffi::GESTrackElement,
1496            position: u64,
1497            f: glib::ffi::gpointer,
1498        ) {
1499            unsafe {
1500                let f: &F = &*(f as *const F);
1501                f(
1502                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1503                    &from_glib_borrow(obj1),
1504                    &from_glib_borrow(obj2),
1505                    position,
1506                )
1507            }
1508        }
1509        unsafe {
1510            let f: Box_<F> = Box_::new(f);
1511            connect_raw(
1512                self.as_ptr() as *mut _,
1513                c"snapping-started".as_ptr(),
1514                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1515                    snapping_started_trampoline::<Self, F> as *const (),
1516                )),
1517                Box_::into_raw(f),
1518            )
1519        }
1520    }
1521
1522    /// Will be emitted after the track is added to the timeline.
1523    ///
1524    /// Note that this should not be emitted whilst a timeline is being
1525    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1526    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1527    /// tracks were created for the timeline.
1528    /// ## `track`
1529    /// The track that was added to `timeline`
1530    #[doc(alias = "track-added")]
1531    fn connect_track_added<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1532        unsafe extern "C" fn track_added_trampoline<
1533            P: IsA<Timeline>,
1534            F: Fn(&P, &Track) + 'static,
1535        >(
1536            this: *mut ffi::GESTimeline,
1537            track: *mut ffi::GESTrack,
1538            f: glib::ffi::gpointer,
1539        ) {
1540            unsafe {
1541                let f: &F = &*(f as *const F);
1542                f(
1543                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1544                    &from_glib_borrow(track),
1545                )
1546            }
1547        }
1548        unsafe {
1549            let f: Box_<F> = Box_::new(f);
1550            connect_raw(
1551                self.as_ptr() as *mut _,
1552                c"track-added".as_ptr(),
1553                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1554                    track_added_trampoline::<Self, F> as *const (),
1555                )),
1556                Box_::into_raw(f),
1557            )
1558        }
1559    }
1560
1561    /// Will be emitted after the track is removed from the timeline.
1562    /// ## `track`
1563    /// The track that was removed from `timeline`
1564    #[doc(alias = "track-removed")]
1565    fn connect_track_removed<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1566        unsafe extern "C" fn track_removed_trampoline<
1567            P: IsA<Timeline>,
1568            F: Fn(&P, &Track) + 'static,
1569        >(
1570            this: *mut ffi::GESTimeline,
1571            track: *mut ffi::GESTrack,
1572            f: glib::ffi::gpointer,
1573        ) {
1574            unsafe {
1575                let f: &F = &*(f as *const F);
1576                f(
1577                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1578                    &from_glib_borrow(track),
1579                )
1580            }
1581        }
1582        unsafe {
1583            let f: Box_<F> = Box_::new(f);
1584            connect_raw(
1585                self.as_ptr() as *mut _,
1586                c"track-removed".as_ptr(),
1587                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1588                    track_removed_trampoline::<Self, F> as *const (),
1589                )),
1590                Box_::into_raw(f),
1591            )
1592        }
1593    }
1594
1595    #[doc(alias = "auto-transition")]
1596    fn connect_auto_transition_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1597        unsafe extern "C" fn notify_auto_transition_trampoline<
1598            P: IsA<Timeline>,
1599            F: Fn(&P) + 'static,
1600        >(
1601            this: *mut ffi::GESTimeline,
1602            _param_spec: glib::ffi::gpointer,
1603            f: glib::ffi::gpointer,
1604        ) {
1605            unsafe {
1606                let f: &F = &*(f as *const F);
1607                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1608            }
1609        }
1610        unsafe {
1611            let f: Box_<F> = Box_::new(f);
1612            connect_raw(
1613                self.as_ptr() as *mut _,
1614                c"notify::auto-transition".as_ptr(),
1615                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1616                    notify_auto_transition_trampoline::<Self, F> as *const (),
1617                )),
1618                Box_::into_raw(f),
1619            )
1620        }
1621    }
1622
1623    #[doc(alias = "duration")]
1624    fn connect_duration_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1625        unsafe extern "C" fn notify_duration_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1626            this: *mut ffi::GESTimeline,
1627            _param_spec: glib::ffi::gpointer,
1628            f: glib::ffi::gpointer,
1629        ) {
1630            unsafe {
1631                let f: &F = &*(f as *const F);
1632                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1633            }
1634        }
1635        unsafe {
1636            let f: Box_<F> = Box_::new(f);
1637            connect_raw(
1638                self.as_ptr() as *mut _,
1639                c"notify::duration".as_ptr(),
1640                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1641                    notify_duration_trampoline::<Self, F> as *const (),
1642                )),
1643                Box_::into_raw(f),
1644            )
1645        }
1646    }
1647
1648    #[doc(alias = "snapping-distance")]
1649    fn connect_snapping_distance_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1650        unsafe extern "C" fn notify_snapping_distance_trampoline<
1651            P: IsA<Timeline>,
1652            F: Fn(&P) + 'static,
1653        >(
1654            this: *mut ffi::GESTimeline,
1655            _param_spec: glib::ffi::gpointer,
1656            f: glib::ffi::gpointer,
1657        ) {
1658            unsafe {
1659                let f: &F = &*(f as *const F);
1660                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1661            }
1662        }
1663        unsafe {
1664            let f: Box_<F> = Box_::new(f);
1665            connect_raw(
1666                self.as_ptr() as *mut _,
1667                c"notify::snapping-distance".as_ptr(),
1668                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1669                    notify_snapping_distance_trampoline::<Self, F> as *const (),
1670                )),
1671                Box_::into_raw(f),
1672            )
1673        }
1674    }
1675}
1676
1677impl<O: IsA<Timeline>> TimelineExt for O {}