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    /// # Returns
808    ///
809    /// The list of
810    /// groups that contain clips present in `self`'s layers.
811    /// Must not be changed.
812    #[doc(alias = "ges_timeline_get_groups")]
813    #[doc(alias = "get_groups")]
814    fn groups(&self) -> Vec<Group> {
815        unsafe {
816            FromGlibPtrContainer::from_glib_none(ffi::ges_timeline_get_groups(
817                self.as_ref().to_glib_none().0,
818            ))
819        }
820    }
821
822    /// Retrieve the layer whose index in the timeline matches the given
823    /// priority.
824    /// ## `priority`
825    /// The priority/index of the layer to find
826    ///
827    /// # Returns
828    ///
829    /// The layer with the given
830    /// `priority`, or [`None`] if none was found.
831    ///
832    /// Since 1.6
833    #[doc(alias = "ges_timeline_get_layer")]
834    #[doc(alias = "get_layer")]
835    fn layer(&self, priority: u32) -> Option<Layer> {
836        unsafe {
837            from_glib_full(ffi::ges_timeline_get_layer(
838                self.as_ref().to_glib_none().0,
839                priority,
840            ))
841        }
842    }
843
844    /// Get the list of [`Layer`][crate::Layer]-s present in the timeline.
845    ///
846    /// # Returns
847    ///
848    /// The list of
849    /// layers present in `self` sorted by priority.
850    #[doc(alias = "ges_timeline_get_layers")]
851    #[doc(alias = "get_layers")]
852    fn layers(&self) -> Vec<Layer> {
853        unsafe {
854            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_layers(
855                self.as_ref().to_glib_none().0,
856            ))
857        }
858    }
859
860    /// Search for the [`gst::Pad`][crate::gst::Pad] corresponding to the given timeline's track.
861    /// You can link to this pad to receive the output data of the given track.
862    /// ## `track`
863    /// A track
864    ///
865    /// # Returns
866    ///
867    /// The pad corresponding to `track`,
868    /// or [`None`] if there is an error.
869    #[doc(alias = "ges_timeline_get_pad_for_track")]
870    #[doc(alias = "get_pad_for_track")]
871    fn pad_for_track(&self, track: &impl IsA<Track>) -> Option<gst::Pad> {
872        unsafe {
873            from_glib_none(ffi::ges_timeline_get_pad_for_track(
874                self.as_ref().to_glib_none().0,
875                track.as_ref().to_glib_none().0,
876            ))
877        }
878    }
879
880    /// Gets the [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline.
881    ///
882    /// # Returns
883    ///
884    /// The snapping distance (in nanoseconds) of `self`.
885    #[doc(alias = "ges_timeline_get_snapping_distance")]
886    #[doc(alias = "get_snapping_distance")]
887    #[doc(alias = "snapping-distance")]
888    fn snapping_distance(&self) -> Option<gst::ClockTime> {
889        unsafe {
890            from_glib(ffi::ges_timeline_get_snapping_distance(
891                self.as_ref().to_glib_none().0,
892            ))
893        }
894    }
895
896    /// Search for the [`Track`][crate::Track] corresponding to the given timeline's pad.
897    /// ## `pad`
898    /// A pad
899    ///
900    /// # Returns
901    ///
902    /// The track corresponding to `pad`,
903    /// or [`None`] if there is an error.
904    #[doc(alias = "ges_timeline_get_track_for_pad")]
905    #[doc(alias = "get_track_for_pad")]
906    fn track_for_pad(&self, pad: &impl IsA<gst::Pad>) -> Option<Track> {
907        unsafe {
908            from_glib_none(ffi::ges_timeline_get_track_for_pad(
909                self.as_ref().to_glib_none().0,
910                pad.as_ref().to_glib_none().0,
911            ))
912        }
913    }
914
915    /// Get the list of [`Track`][crate::Track]-s used by the timeline.
916    ///
917    /// # Returns
918    ///
919    /// The list of tracks
920    /// used by `self`.
921    #[doc(alias = "ges_timeline_get_tracks")]
922    #[doc(alias = "get_tracks")]
923    fn tracks(&self) -> Vec<Track> {
924        unsafe {
925            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_tracks(
926                self.as_ref().to_glib_none().0,
927            ))
928        }
929    }
930
931    /// Check whether the timeline is empty or not.
932    ///
933    /// # Returns
934    ///
935    /// [`true`] if `self` is empty.
936    #[doc(alias = "ges_timeline_is_empty")]
937    fn is_empty(&self) -> bool {
938        unsafe { from_glib(ffi::ges_timeline_is_empty(self.as_ref().to_glib_none().0)) }
939    }
940
941    /// Loads the contents of URI into the timeline.
942    /// ## `uri`
943    /// The URI to load from
944    ///
945    /// # Returns
946    ///
947    /// [`true`] if the timeline was loaded successfully from `uri`.
948    #[doc(alias = "ges_timeline_load_from_uri")]
949    fn load_from_uri(&self, uri: &str) -> Result<(), glib::Error> {
950        unsafe {
951            let mut error = std::ptr::null_mut();
952            let is_ok = ffi::ges_timeline_load_from_uri(
953                self.as_ref().to_glib_none().0,
954                uri.to_glib_none().0,
955                &mut error,
956            );
957            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
958            if error.is_null() {
959                Ok(())
960            } else {
961                Err(from_glib_full(error))
962            }
963        }
964    }
965
966    /// Moves a layer within the timeline to the index given by
967    /// `new_layer_priority`.
968    /// An index of 0 corresponds to the layer with the highest priority in a
969    /// timeline. If `new_layer_priority` is greater than the number of layers
970    /// present in the timeline, it will become the lowest priority layer.
971    /// ## `layer`
972    /// A layer within `self`, whose priority should be changed
973    /// ## `new_layer_priority`
974    /// The new index for `layer`
975    #[cfg(feature = "v1_16")]
976    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
977    #[doc(alias = "ges_timeline_move_layer")]
978    fn move_layer(
979        &self,
980        layer: &impl IsA<Layer>,
981        new_layer_priority: u32,
982    ) -> Result<(), glib::error::BoolError> {
983        unsafe {
984            glib::result_from_gboolean!(
985                ffi::ges_timeline_move_layer(
986                    self.as_ref().to_glib_none().0,
987                    layer.as_ref().to_glib_none().0,
988                    new_layer_priority
989                ),
990                "Failed to move layer"
991            )
992        }
993    }
994
995    /// Paste an element inside the timeline. `element` **must** be the return of
996    /// `ges_timeline_element_copy()` with `deep=TRUE`,
997    /// and it should not be changed before pasting. `element` itself is not
998    /// placed in the timeline, instead a new element is created, alike to the
999    /// originally copied element. Note that the originally copied element must
1000    /// also lie within `self`, at both the point of copying and pasting.
1001    ///
1002    /// Pasting may fail if it would place the timeline in an unsupported
1003    /// configuration.
1004    ///
1005    /// After calling this function `element` should not be used. In particular,
1006    /// `element` can **not** be pasted again. Instead, you can copy the
1007    /// returned element and paste that copy (although, this is only possible
1008    /// if the paste was successful).
1009    ///
1010    /// See also [`TimelineElementExt::paste()`][crate::prelude::TimelineElementExt::paste()].
1011    /// ## `element`
1012    /// The element to paste
1013    /// ## `position`
1014    /// The position in the timeline `element` should be pasted to,
1015    /// i.e. the [`start`][struct@crate::TimelineElement#start] value for the pasted element.
1016    /// ## `layer_priority`
1017    /// The layer into which the element should be pasted.
1018    /// -1 means paste to the same layer from which `element` has been copied from
1019    ///
1020    /// # Returns
1021    ///
1022    /// The newly created element, or
1023    /// [`None`] if pasting fails.
1024    #[doc(alias = "ges_timeline_paste_element")]
1025    fn paste_element(
1026        &self,
1027        element: &impl IsA<TimelineElement>,
1028        position: gst::ClockTime,
1029        layer_priority: i32,
1030    ) -> Option<TimelineElement> {
1031        unsafe {
1032            from_glib_full(ffi::ges_timeline_paste_element(
1033                self.as_ref().to_glib_none().0,
1034                element.as_ref().to_glib_none().0,
1035                position.into_glib(),
1036                layer_priority,
1037            ))
1038        }
1039    }
1040
1041    /// Removes a layer from the timeline.
1042    /// ## `layer`
1043    /// The layer to remove
1044    ///
1045    /// # Returns
1046    ///
1047    /// [`true`] if `layer` was properly removed.
1048    #[doc(alias = "ges_timeline_remove_layer")]
1049    fn remove_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
1050        unsafe {
1051            glib::result_from_gboolean!(
1052                ffi::ges_timeline_remove_layer(
1053                    self.as_ref().to_glib_none().0,
1054                    layer.as_ref().to_glib_none().0
1055                ),
1056                "Failed to remove layer"
1057            )
1058        }
1059    }
1060
1061    /// Remove a track from the timeline.
1062    /// ## `track`
1063    /// The track to remove
1064    ///
1065    /// # Returns
1066    ///
1067    /// [`true`] if `track` was properly removed.
1068    #[doc(alias = "ges_timeline_remove_track")]
1069    fn remove_track(&self, track: &impl IsA<Track>) -> Result<(), glib::error::BoolError> {
1070        unsafe {
1071            glib::result_from_gboolean!(
1072                ffi::ges_timeline_remove_track(
1073                    self.as_ref().to_glib_none().0,
1074                    track.as_ref().to_glib_none().0
1075                ),
1076                "Failed to remove track"
1077            )
1078        }
1079    }
1080
1081    /// Saves the timeline to the given location. If `formatter_asset` is [`None`],
1082    /// the method will attempt to save in the same format the timeline was
1083    /// loaded from, before defaulting to the formatter with highest rank.
1084    /// ## `uri`
1085    /// The location to save to
1086    /// ## `formatter_asset`
1087    /// The formatter asset to use, or [`None`]
1088    /// ## `overwrite`
1089    /// [`true`] to overwrite file if it exists
1090    ///
1091    /// # Returns
1092    ///
1093    /// [`true`] if `self` was successfully saved to `uri`.
1094    #[doc(alias = "ges_timeline_save_to_uri")]
1095    fn save_to_uri(
1096        &self,
1097        uri: &str,
1098        formatter_asset: Option<&impl IsA<Asset>>,
1099        overwrite: bool,
1100    ) -> Result<(), glib::Error> {
1101        unsafe {
1102            let mut error = std::ptr::null_mut();
1103            let is_ok = ffi::ges_timeline_save_to_uri(
1104                self.as_ref().to_glib_none().0,
1105                uri.to_glib_none().0,
1106                formatter_asset.map(|p| p.as_ref()).to_glib_none().0,
1107                overwrite.into_glib(),
1108                &mut error,
1109            );
1110            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1111            if error.is_null() {
1112                Ok(())
1113            } else {
1114                Err(from_glib_full(error))
1115            }
1116        }
1117    }
1118
1119    /// Sets [`auto-transition`][struct@crate::Timeline#auto-transition] for the timeline. This will also set
1120    /// the corresponding [`auto-transition`][struct@crate::Layer#auto-transition] for all of the timeline's
1121    /// layers to the same value. See [`LayerExt::set_auto_transition()`][crate::prelude::LayerExt::set_auto_transition()] if you
1122    /// wish to set the layer's [`auto-transition`][struct@crate::Layer#auto-transition] individually.
1123    /// ## `auto_transition`
1124    /// Whether transitions should be automatically added
1125    /// to `self`'s layers
1126    #[doc(alias = "ges_timeline_set_auto_transition")]
1127    #[doc(alias = "auto-transition")]
1128    fn set_auto_transition(&self, auto_transition: bool) {
1129        unsafe {
1130            ffi::ges_timeline_set_auto_transition(
1131                self.as_ref().to_glib_none().0,
1132                auto_transition.into_glib(),
1133            );
1134        }
1135    }
1136
1137    /// Sets [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline. This new value
1138    /// will only effect future snappings and will not be used to snap the
1139    /// current element positions within the timeline.
1140    /// ## `snapping_distance`
1141    /// The snapping distance to use (in nanoseconds)
1142    #[doc(alias = "ges_timeline_set_snapping_distance")]
1143    #[doc(alias = "snapping-distance")]
1144    fn set_snapping_distance(&self, snapping_distance: gst::ClockTime) {
1145        unsafe {
1146            ffi::ges_timeline_set_snapping_distance(
1147                self.as_ref().to_glib_none().0,
1148                snapping_distance.into_glib(),
1149            );
1150        }
1151    }
1152
1153    /// Thaw the timeline so that comiting becomes possible
1154    /// again and any call to ``commit()`` that happened during the rendering is
1155    /// actually taken into account.
1156    #[cfg(feature = "v1_20")]
1157    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1158    #[doc(alias = "ges_timeline_thaw_commit")]
1159    fn thaw_commit(&self) {
1160        unsafe {
1161            ffi::ges_timeline_thaw_commit(self.as_ref().to_glib_none().0);
1162        }
1163    }
1164
1165    /// This signal will be emitted once the changes initiated by
1166    /// [`commit()`][Self::commit()] have been executed in the backend. Use
1167    /// [`commit_sync()`][Self::commit_sync()] if you do not want to have to connect
1168    /// to this signal.
1169    #[doc(alias = "commited")]
1170    fn connect_commited<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1171        unsafe extern "C" fn commited_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1172            this: *mut ffi::GESTimeline,
1173            f: glib::ffi::gpointer,
1174        ) {
1175            unsafe {
1176                let f: &F = &*(f as *const F);
1177                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1178            }
1179        }
1180        unsafe {
1181            let f: Box_<F> = Box_::new(f);
1182            connect_raw(
1183                self.as_ptr() as *mut _,
1184                c"commited".as_ptr(),
1185                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1186                    commited_trampoline::<Self, F> as *const (),
1187                )),
1188                Box_::into_raw(f),
1189            )
1190        }
1191    }
1192
1193    /// Will be emitted after the group is added to to the timeline. This can
1194    /// happen when grouping with `ges_container_group`, or by adding
1195    /// containers to a newly created group.
1196    ///
1197    /// Note that this should not be emitted whilst a timeline is being
1198    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1199    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which groups
1200    /// were created for the timeline.
1201    /// ## `group`
1202    /// The group that was added to `timeline`
1203    #[doc(alias = "group-added")]
1204    fn connect_group_added<F: Fn(&Self, &Group) + 'static>(&self, f: F) -> SignalHandlerId {
1205        unsafe extern "C" fn group_added_trampoline<
1206            P: IsA<Timeline>,
1207            F: Fn(&P, &Group) + 'static,
1208        >(
1209            this: *mut ffi::GESTimeline,
1210            group: *mut ffi::GESGroup,
1211            f: glib::ffi::gpointer,
1212        ) {
1213            unsafe {
1214                let f: &F = &*(f as *const F);
1215                f(
1216                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1217                    &from_glib_borrow(group),
1218                )
1219            }
1220        }
1221        unsafe {
1222            let f: Box_<F> = Box_::new(f);
1223            connect_raw(
1224                self.as_ptr() as *mut _,
1225                c"group-added".as_ptr(),
1226                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1227                    group_added_trampoline::<Self, F> as *const (),
1228                )),
1229                Box_::into_raw(f),
1230            )
1231        }
1232    }
1233
1234    //#[doc(alias = "group-removed")]
1235    //fn connect_group_removed<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1236    //    Empty ctype children: *.PtrArray TypeId { ns_id: 1, id: 54 }
1237    //}
1238
1239    /// Will be emitted after the layer is added to the timeline.
1240    ///
1241    /// Note that this should not be emitted whilst a timeline is being
1242    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1243    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1244    /// layers were created for the timeline.
1245    /// ## `layer`
1246    /// The layer that was added to `timeline`
1247    #[doc(alias = "layer-added")]
1248    fn connect_layer_added<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1249        unsafe extern "C" fn layer_added_trampoline<
1250            P: IsA<Timeline>,
1251            F: Fn(&P, &Layer) + 'static,
1252        >(
1253            this: *mut ffi::GESTimeline,
1254            layer: *mut ffi::GESLayer,
1255            f: glib::ffi::gpointer,
1256        ) {
1257            unsafe {
1258                let f: &F = &*(f as *const F);
1259                f(
1260                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1261                    &from_glib_borrow(layer),
1262                )
1263            }
1264        }
1265        unsafe {
1266            let f: Box_<F> = Box_::new(f);
1267            connect_raw(
1268                self.as_ptr() as *mut _,
1269                c"layer-added".as_ptr(),
1270                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1271                    layer_added_trampoline::<Self, F> as *const (),
1272                )),
1273                Box_::into_raw(f),
1274            )
1275        }
1276    }
1277
1278    /// Will be emitted after the layer is removed from the timeline.
1279    /// ## `layer`
1280    /// The layer that was removed from `timeline`
1281    #[doc(alias = "layer-removed")]
1282    fn connect_layer_removed<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1283        unsafe extern "C" fn layer_removed_trampoline<
1284            P: IsA<Timeline>,
1285            F: Fn(&P, &Layer) + 'static,
1286        >(
1287            this: *mut ffi::GESTimeline,
1288            layer: *mut ffi::GESLayer,
1289            f: glib::ffi::gpointer,
1290        ) {
1291            unsafe {
1292                let f: &F = &*(f as *const F);
1293                f(
1294                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1295                    &from_glib_borrow(layer),
1296                )
1297            }
1298        }
1299        unsafe {
1300            let f: Box_<F> = Box_::new(f);
1301            connect_raw(
1302                self.as_ptr() as *mut _,
1303                c"layer-removed".as_ptr(),
1304                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1305                    layer_removed_trampoline::<Self, F> as *const (),
1306                )),
1307                Box_::into_raw(f),
1308            )
1309        }
1310    }
1311
1312    /// Simplified version of [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] which only
1313    /// allows `track_element` to be added to a single [`Track`][crate::Track].
1314    /// ## `clip`
1315    /// The clip that `track_element` is being added to
1316    /// ## `track_element`
1317    /// The element being added
1318    ///
1319    /// # Returns
1320    ///
1321    /// A track to put `track_element` into, or [`None`] if
1322    /// it should be discarded.
1323    #[cfg(feature = "v1_18")]
1324    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1325    #[doc(alias = "select-element-track")]
1326    fn connect_select_element_track<
1327        F: Fn(&Self, &Clip, &TrackElement) -> Option<Track> + 'static,
1328    >(
1329        &self,
1330        f: F,
1331    ) -> SignalHandlerId {
1332        unsafe extern "C" fn select_element_track_trampoline<
1333            P: IsA<Timeline>,
1334            F: Fn(&P, &Clip, &TrackElement) -> Option<Track> + 'static,
1335        >(
1336            this: *mut ffi::GESTimeline,
1337            clip: *mut ffi::GESClip,
1338            track_element: *mut ffi::GESTrackElement,
1339            f: glib::ffi::gpointer,
1340        ) -> *mut ffi::GESTrack {
1341            unsafe {
1342                let f: &F = &*(f as *const F);
1343                f(
1344                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1345                    &from_glib_borrow(clip),
1346                    &from_glib_borrow(track_element),
1347                )
1348                .to_glib_full()
1349            }
1350        }
1351        unsafe {
1352            let f: Box_<F> = Box_::new(f);
1353            connect_raw(
1354                self.as_ptr() as *mut _,
1355                c"select-element-track".as_ptr(),
1356                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1357                    select_element_track_trampoline::<Self, F> as *const (),
1358                )),
1359                Box_::into_raw(f),
1360            )
1361        }
1362    }
1363
1364    //#[doc(alias = "select-tracks-for-object")]
1365    //fn connect_select_tracks_for_object<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1366    //    Empty ctype return value *.PtrArray TypeId { ns_id: 1, id: 17 }
1367    //}
1368
1369    /// Will be emitted whenever a snapping event ends. After a snap event
1370    /// has started (see [`snapping-started`][struct@crate::Timeline#snapping-started]), it can later end
1371    /// because either another timeline edit has occurred (which may or may
1372    /// not have created a new snapping event), or because the timeline has
1373    /// been committed.
1374    /// ## `obj1`
1375    /// The first element that was snapping
1376    /// ## `obj2`
1377    /// The second element that was snapping
1378    /// ## `position`
1379    /// The position where the two objects were to be snapped to
1380    #[doc(alias = "snapping-ended")]
1381    fn connect_snapping_ended<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1382        &self,
1383        f: F,
1384    ) -> SignalHandlerId {
1385        unsafe extern "C" fn snapping_ended_trampoline<
1386            P: IsA<Timeline>,
1387            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1388        >(
1389            this: *mut ffi::GESTimeline,
1390            obj1: *mut ffi::GESTrackElement,
1391            obj2: *mut ffi::GESTrackElement,
1392            position: u64,
1393            f: glib::ffi::gpointer,
1394        ) {
1395            unsafe {
1396                let f: &F = &*(f as *const F);
1397                f(
1398                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1399                    &from_glib_borrow(obj1),
1400                    &from_glib_borrow(obj2),
1401                    position,
1402                )
1403            }
1404        }
1405        unsafe {
1406            let f: Box_<F> = Box_::new(f);
1407            connect_raw(
1408                self.as_ptr() as *mut _,
1409                c"snapping-ended".as_ptr(),
1410                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1411                    snapping_ended_trampoline::<Self, F> as *const (),
1412                )),
1413                Box_::into_raw(f),
1414            )
1415        }
1416    }
1417
1418    /// Will be emitted whenever an element's movement invokes a snapping
1419    /// event during an edit (usually of one of its ancestors) because its
1420    /// start or end point lies within the [`snapping-distance`][struct@crate::Timeline#snapping-distance] of
1421    /// another element's start or end point.
1422    ///
1423    /// See [`EditMode`][crate::EditMode] to see what can snap during an edit.
1424    ///
1425    /// Note that only up to one snapping-started signal will be emitted per
1426    /// element edit within a timeline.
1427    /// ## `obj1`
1428    /// The first element that is snapping
1429    /// ## `obj2`
1430    /// The second element that is snapping
1431    /// ## `position`
1432    /// The position where the two objects will snap to
1433    #[doc(alias = "snapping-started")]
1434    fn connect_snapping_started<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1435        &self,
1436        f: F,
1437    ) -> SignalHandlerId {
1438        unsafe extern "C" fn snapping_started_trampoline<
1439            P: IsA<Timeline>,
1440            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1441        >(
1442            this: *mut ffi::GESTimeline,
1443            obj1: *mut ffi::GESTrackElement,
1444            obj2: *mut ffi::GESTrackElement,
1445            position: u64,
1446            f: glib::ffi::gpointer,
1447        ) {
1448            unsafe {
1449                let f: &F = &*(f as *const F);
1450                f(
1451                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1452                    &from_glib_borrow(obj1),
1453                    &from_glib_borrow(obj2),
1454                    position,
1455                )
1456            }
1457        }
1458        unsafe {
1459            let f: Box_<F> = Box_::new(f);
1460            connect_raw(
1461                self.as_ptr() as *mut _,
1462                c"snapping-started".as_ptr(),
1463                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1464                    snapping_started_trampoline::<Self, F> as *const (),
1465                )),
1466                Box_::into_raw(f),
1467            )
1468        }
1469    }
1470
1471    /// Will be emitted after the track is added to the timeline.
1472    ///
1473    /// Note that this should not be emitted whilst a timeline is being
1474    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1475    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1476    /// tracks were created for the timeline.
1477    /// ## `track`
1478    /// The track that was added to `timeline`
1479    #[doc(alias = "track-added")]
1480    fn connect_track_added<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1481        unsafe extern "C" fn track_added_trampoline<
1482            P: IsA<Timeline>,
1483            F: Fn(&P, &Track) + 'static,
1484        >(
1485            this: *mut ffi::GESTimeline,
1486            track: *mut ffi::GESTrack,
1487            f: glib::ffi::gpointer,
1488        ) {
1489            unsafe {
1490                let f: &F = &*(f as *const F);
1491                f(
1492                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1493                    &from_glib_borrow(track),
1494                )
1495            }
1496        }
1497        unsafe {
1498            let f: Box_<F> = Box_::new(f);
1499            connect_raw(
1500                self.as_ptr() as *mut _,
1501                c"track-added".as_ptr(),
1502                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1503                    track_added_trampoline::<Self, F> as *const (),
1504                )),
1505                Box_::into_raw(f),
1506            )
1507        }
1508    }
1509
1510    /// Will be emitted after the track is removed from the timeline.
1511    /// ## `track`
1512    /// The track that was removed from `timeline`
1513    #[doc(alias = "track-removed")]
1514    fn connect_track_removed<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1515        unsafe extern "C" fn track_removed_trampoline<
1516            P: IsA<Timeline>,
1517            F: Fn(&P, &Track) + 'static,
1518        >(
1519            this: *mut ffi::GESTimeline,
1520            track: *mut ffi::GESTrack,
1521            f: glib::ffi::gpointer,
1522        ) {
1523            unsafe {
1524                let f: &F = &*(f as *const F);
1525                f(
1526                    Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1527                    &from_glib_borrow(track),
1528                )
1529            }
1530        }
1531        unsafe {
1532            let f: Box_<F> = Box_::new(f);
1533            connect_raw(
1534                self.as_ptr() as *mut _,
1535                c"track-removed".as_ptr(),
1536                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1537                    track_removed_trampoline::<Self, F> as *const (),
1538                )),
1539                Box_::into_raw(f),
1540            )
1541        }
1542    }
1543
1544    #[doc(alias = "auto-transition")]
1545    fn connect_auto_transition_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1546        unsafe extern "C" fn notify_auto_transition_trampoline<
1547            P: IsA<Timeline>,
1548            F: Fn(&P) + 'static,
1549        >(
1550            this: *mut ffi::GESTimeline,
1551            _param_spec: glib::ffi::gpointer,
1552            f: glib::ffi::gpointer,
1553        ) {
1554            unsafe {
1555                let f: &F = &*(f as *const F);
1556                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1557            }
1558        }
1559        unsafe {
1560            let f: Box_<F> = Box_::new(f);
1561            connect_raw(
1562                self.as_ptr() as *mut _,
1563                c"notify::auto-transition".as_ptr(),
1564                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1565                    notify_auto_transition_trampoline::<Self, F> as *const (),
1566                )),
1567                Box_::into_raw(f),
1568            )
1569        }
1570    }
1571
1572    #[doc(alias = "duration")]
1573    fn connect_duration_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1574        unsafe extern "C" fn notify_duration_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1575            this: *mut ffi::GESTimeline,
1576            _param_spec: glib::ffi::gpointer,
1577            f: glib::ffi::gpointer,
1578        ) {
1579            unsafe {
1580                let f: &F = &*(f as *const F);
1581                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1582            }
1583        }
1584        unsafe {
1585            let f: Box_<F> = Box_::new(f);
1586            connect_raw(
1587                self.as_ptr() as *mut _,
1588                c"notify::duration".as_ptr(),
1589                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1590                    notify_duration_trampoline::<Self, F> as *const (),
1591                )),
1592                Box_::into_raw(f),
1593            )
1594        }
1595    }
1596
1597    #[doc(alias = "snapping-distance")]
1598    fn connect_snapping_distance_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1599        unsafe extern "C" fn notify_snapping_distance_trampoline<
1600            P: IsA<Timeline>,
1601            F: Fn(&P) + 'static,
1602        >(
1603            this: *mut ffi::GESTimeline,
1604            _param_spec: glib::ffi::gpointer,
1605            f: glib::ffi::gpointer,
1606        ) {
1607            unsafe {
1608                let f: &F = &*(f as *const F);
1609                f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1610            }
1611        }
1612        unsafe {
1613            let f: Box_<F> = Box_::new(f);
1614            connect_raw(
1615                self.as_ptr() as *mut _,
1616                c"notify::snapping-distance".as_ptr(),
1617                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1618                    notify_snapping_distance_trampoline::<Self, F> as *const (),
1619                )),
1620                Box_::into_raw(f),
1621            )
1622        }
1623    }
1624}
1625
1626impl<O: IsA<Timeline>> TimelineExt for O {}