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    ffi, Asset, Extractable, Group, Layer, MetaContainer, TimelineElement, Track, TrackElement,
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::{connect_raw, SignalHandlerId},
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
519mod sealed {
520    pub trait Sealed {}
521    impl<T: super::IsA<super::Timeline>> Sealed for T {}
522}
523
524/// Trait containing all [`struct@Timeline`] methods.
525///
526/// # Implementors
527///
528/// [`Timeline`][struct@crate::Timeline]
529pub trait TimelineExt: IsA<Timeline> + sealed::Sealed + 'static {
530    /// Add a layer to the timeline.
531    ///
532    /// If the layer contains [`Clip`][crate::Clip]-s, then this may trigger the creation of
533    /// their core track element children for the timeline's tracks, and the
534    /// placement of the clip's children in the tracks of the timeline using
535    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Some errors may occur if this
536    /// would break one of the configuration rules of the timeline in one of
537    /// its tracks. In such cases, some track elements would fail to be added
538    /// to their tracks, but this method would still return [`true`]. As such, it
539    /// is advised that you only add clips to layers that already part of a
540    /// timeline. In such situations, [`LayerExt::add_clip()`][crate::prelude::LayerExt::add_clip()] is able to fail if
541    /// adding the clip would cause such an error.
542    ///
543    /// # Deprecated since 1.18
544    ///
545    /// This method requires you to ensure the layer's
546    /// [`priority`][struct@crate::Layer#priority] will be unique to the timeline. Use
547    /// [`append_layer()`][Self::append_layer()] and [`move_layer()`][Self::move_layer()] instead.
548    /// ## `layer`
549    /// The layer to add
550    ///
551    /// # Returns
552    ///
553    /// [`true`] if `layer` was properly added.
554    #[cfg_attr(feature = "v1_18", deprecated = "Since 1.18")]
555    #[allow(deprecated)]
556    #[doc(alias = "ges_timeline_add_layer")]
557    fn add_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
558        unsafe {
559            glib::result_from_gboolean!(
560                ffi::ges_timeline_add_layer(
561                    self.as_ref().to_glib_none().0,
562                    layer.as_ref().to_glib_none().0
563                ),
564                "Failed to add layer"
565            )
566        }
567    }
568
569    /// Add a track to the timeline.
570    ///
571    /// If the timeline already contains clips, then this may trigger the
572    /// creation of their core track element children for the track, and the
573    /// placement of the clip's children in the track of the timeline using
574    /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Some errors may occur if this
575    /// would break one of the configuration rules for the timeline in the
576    /// track. In such cases, some track elements would fail to be added to the
577    /// track, but this method would still return [`true`]. As such, it is advised
578    /// that you avoid adding tracks to timelines that already contain clips.
579    /// ## `track`
580    /// The track to add
581    ///
582    /// # Returns
583    ///
584    /// [`true`] if `track` was properly added.
585    #[doc(alias = "ges_timeline_add_track")]
586    fn add_track(&self, track: &impl IsA<Track>) -> Result<(), glib::error::BoolError> {
587        unsafe {
588            glib::result_from_gboolean!(
589                ffi::ges_timeline_add_track(
590                    self.as_ref().to_glib_none().0,
591                    track.as_ref().to_glib_none().0
592                ),
593                "Failed to add track"
594            )
595        }
596    }
597
598    /// Append a newly created layer to the timeline. The layer will
599    /// be added at the lowest [`priority`][struct@crate::Layer#priority] (numerically, the highest).
600    ///
601    /// # Returns
602    ///
603    /// The newly created layer.
604    #[doc(alias = "ges_timeline_append_layer")]
605    fn append_layer(&self) -> Layer {
606        unsafe {
607            from_glib_none(ffi::ges_timeline_append_layer(
608                self.as_ref().to_glib_none().0,
609            ))
610        }
611    }
612
613    /// Commit all the pending changes of the clips contained in the
614    /// timeline.
615    ///
616    /// When changes happen in a timeline, they are not immediately executed
617    /// internally, in a way that effects the output data of the timeline. You
618    /// should call this method when you are done with a set of changes and you
619    /// want them to be executed.
620    ///
621    /// Any pending changes will be executed in the backend. The
622    /// [`commited`][struct@crate::Timeline#commited] signal will be emitted once this has completed.
623    /// You should not try to change the state of the timeline, seek it or add
624    /// tracks to it before receiving this signal. You can use
625    /// [`commit_sync()`][Self::commit_sync()] if you do not want to perform other tasks in
626    /// the mean time.
627    ///
628    /// Note that all the pending changes will automatically be executed when
629    /// the timeline goes from [`gst::State::Ready`][crate::gst::State::Ready] to [`gst::State::Paused`][crate::gst::State::Paused], which is
630    /// usually triggered by a corresponding state changes in a containing
631    /// [`Pipeline`][crate::Pipeline].
632    ///
633    /// # Returns
634    ///
635    /// [`true`] if pending changes were committed, or [`false`] if nothing
636    /// needed to be committed.
637    #[doc(alias = "ges_timeline_commit")]
638    fn commit(&self) -> bool {
639        unsafe { from_glib(ffi::ges_timeline_commit(self.as_ref().to_glib_none().0)) }
640    }
641
642    /// Commit all the pending changes of the clips contained in the
643    /// timeline and wait for the changes to complete.
644    ///
645    /// See [`commit()`][Self::commit()].
646    ///
647    /// # Returns
648    ///
649    /// [`true`] if pending changes were committed, or [`false`] if nothing
650    /// needed to be committed.
651    #[doc(alias = "ges_timeline_commit_sync")]
652    fn commit_sync(&self) -> bool {
653        unsafe {
654            from_glib(ffi::ges_timeline_commit_sync(
655                self.as_ref().to_glib_none().0,
656            ))
657        }
658    }
659
660    /// WARNING: When using that mode, GES won't guarantee the coherence of the
661    /// timeline. You need to ensure that the rules described in the [Overlaps and
662    /// auto transitions](`overlaps`-and-autotransitions) section are respected any time
663    /// the timeline is [commited](ges_timeline_commit) (otherwise playback will most
664    /// probably fail in different ways).
665    ///
666    /// When disabling editing APIs, GES won't be able to enforce the rules that
667    /// makes the timeline overall state to be valid but some feature won't be
668    /// usable:
669    ///  * [`snapping-distance`][struct@crate::Timeline#snapping-distance]
670    ///  * [`auto-transition`][struct@crate::Timeline#auto-transition]
671    /// ## `disable_edit_apis`
672    /// [`true`] to disable all the edit APIs so the user is in full
673    /// control of ensuring timeline state validity [`false`] otherwise.
674    #[cfg(feature = "v1_22")]
675    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
676    #[doc(alias = "ges_timeline_disable_edit_apis")]
677    fn disable_edit_apis(&self, disable_edit_apis: bool) {
678        unsafe {
679            ffi::ges_timeline_disable_edit_apis(
680                self.as_ref().to_glib_none().0,
681                disable_edit_apis.into_glib(),
682            );
683        }
684    }
685
686    /// Freezes the timeline from being committed. This is usually needed while the
687    /// timeline is being rendered to ensure that not change to the timeline are
688    /// taken into account during that moment. Once the rendering is done, you
689    /// should call `ges_timeline_thaw_commit` so that committing becomes possible
690    /// again and any call to ``commit()`` that happened during the rendering is
691    /// actually taken into account.
692    #[cfg(feature = "v1_20")]
693    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
694    #[doc(alias = "ges_timeline_freeze_commit")]
695    fn freeze_commit(&self) {
696        unsafe {
697            ffi::ges_timeline_freeze_commit(self.as_ref().to_glib_none().0);
698        }
699    }
700
701    /// Gets [`auto-transition`][struct@crate::Timeline#auto-transition] for the timeline.
702    ///
703    /// # Returns
704    ///
705    /// The auto-transition of `self_`.
706    #[doc(alias = "ges_timeline_get_auto_transition")]
707    #[doc(alias = "get_auto_transition")]
708    #[doc(alias = "auto-transition")]
709    fn is_auto_transition(&self) -> bool {
710        unsafe {
711            from_glib(ffi::ges_timeline_get_auto_transition(
712                self.as_ref().to_glib_none().0,
713            ))
714        }
715    }
716
717    /// Get the current [`duration`][struct@crate::Timeline#duration] of the timeline
718    ///
719    /// # Returns
720    ///
721    /// The current duration of `self`.
722    #[doc(alias = "ges_timeline_get_duration")]
723    #[doc(alias = "get_duration")]
724    fn duration(&self) -> gst::ClockTime {
725        unsafe {
726            try_from_glib(ffi::ges_timeline_get_duration(
727                self.as_ref().to_glib_none().0,
728            ))
729            .expect("mandatory glib value is None")
730        }
731    }
732
733    ///
734    /// # Returns
735    ///
736    /// [`true`] if edit APIs are disabled, [`false`] otherwise.
737    #[cfg(feature = "v1_22")]
738    #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
739    #[doc(alias = "ges_timeline_get_edit_apis_disabled")]
740    #[doc(alias = "get_edit_apis_disabled")]
741    fn is_edit_apis_disabled(&self) -> bool {
742        unsafe {
743            from_glib(ffi::ges_timeline_get_edit_apis_disabled(
744                self.as_ref().to_glib_none().0,
745            ))
746        }
747    }
748
749    /// Gets the element contained in the timeline with the given name.
750    /// ## `name`
751    /// The name of the element to find
752    ///
753    /// # Returns
754    ///
755    /// The timeline element in `self`
756    /// with the given `name`, or [`None`] if it was not found.
757    #[doc(alias = "ges_timeline_get_element")]
758    #[doc(alias = "get_element")]
759    fn element(&self, name: &str) -> Option<TimelineElement> {
760        unsafe {
761            from_glib_full(ffi::ges_timeline_get_element(
762                self.as_ref().to_glib_none().0,
763                name.to_glib_none().0,
764            ))
765        }
766    }
767
768    /// This method allows you to convert a timeline `GstClockTime` into its
769    /// corresponding `GESFrameNumber` in the timeline's output.
770    /// ## `timestamp`
771    /// The timestamp to get the corresponding frame number of
772    ///
773    /// # Returns
774    ///
775    /// The frame number `timestamp` corresponds to.
776    #[cfg(feature = "v1_18")]
777    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
778    #[doc(alias = "ges_timeline_get_frame_at")]
779    #[doc(alias = "get_frame_at")]
780    fn frame_at(&self, timestamp: gst::ClockTime) -> FrameNumber {
781        unsafe {
782            ffi::ges_timeline_get_frame_at(self.as_ref().to_glib_none().0, timestamp.into_glib())
783        }
784    }
785
786    /// This method allows you to convert a timeline output frame number into a
787    /// timeline `GstClockTime`. For example, this time could be used to seek to a
788    /// particular frame in the timeline's output, or as the edit position for
789    /// an element within the timeline.
790    /// ## `frame_number`
791    /// The frame number to get the corresponding timestamp of in the
792    ///  timeline coordinates
793    ///
794    /// # Returns
795    ///
796    /// The timestamp corresponding to `frame_number` in the output of `self`.
797    #[cfg(feature = "v1_18")]
798    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
799    #[doc(alias = "ges_timeline_get_frame_time")]
800    #[doc(alias = "get_frame_time")]
801    fn frame_time(&self, frame_number: FrameNumber) -> Option<gst::ClockTime> {
802        unsafe {
803            from_glib(ffi::ges_timeline_get_frame_time(
804                self.as_ref().to_glib_none().0,
805                frame_number,
806            ))
807        }
808    }
809
810    /// Get the list of [`Group`][crate::Group]-s present in the timeline.
811    ///
812    /// # Returns
813    ///
814    /// The list of
815    /// groups that contain clips present in `self`'s layers.
816    /// Must not be changed.
817    #[doc(alias = "ges_timeline_get_groups")]
818    #[doc(alias = "get_groups")]
819    fn groups(&self) -> Vec<Group> {
820        unsafe {
821            FromGlibPtrContainer::from_glib_none(ffi::ges_timeline_get_groups(
822                self.as_ref().to_glib_none().0,
823            ))
824        }
825    }
826
827    /// Retrieve the layer whose index in the timeline matches the given
828    /// priority.
829    /// ## `priority`
830    /// The priority/index of the layer to find
831    ///
832    /// # Returns
833    ///
834    /// The layer with the given
835    /// `priority`, or [`None`] if none was found.
836    ///
837    /// Since 1.6
838    #[doc(alias = "ges_timeline_get_layer")]
839    #[doc(alias = "get_layer")]
840    fn layer(&self, priority: u32) -> Option<Layer> {
841        unsafe {
842            from_glib_full(ffi::ges_timeline_get_layer(
843                self.as_ref().to_glib_none().0,
844                priority,
845            ))
846        }
847    }
848
849    /// Get the list of [`Layer`][crate::Layer]-s present in the timeline.
850    ///
851    /// # Returns
852    ///
853    /// The list of
854    /// layers present in `self` sorted by priority.
855    #[doc(alias = "ges_timeline_get_layers")]
856    #[doc(alias = "get_layers")]
857    fn layers(&self) -> Vec<Layer> {
858        unsafe {
859            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_layers(
860                self.as_ref().to_glib_none().0,
861            ))
862        }
863    }
864
865    /// Search for the [`gst::Pad`][crate::gst::Pad] corresponding to the given timeline's track.
866    /// You can link to this pad to receive the output data of the given track.
867    /// ## `track`
868    /// A track
869    ///
870    /// # Returns
871    ///
872    /// The pad corresponding to `track`,
873    /// or [`None`] if there is an error.
874    #[doc(alias = "ges_timeline_get_pad_for_track")]
875    #[doc(alias = "get_pad_for_track")]
876    fn pad_for_track(&self, track: &impl IsA<Track>) -> Option<gst::Pad> {
877        unsafe {
878            from_glib_none(ffi::ges_timeline_get_pad_for_track(
879                self.as_ref().to_glib_none().0,
880                track.as_ref().to_glib_none().0,
881            ))
882        }
883    }
884
885    /// Gets the [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline.
886    ///
887    /// # Returns
888    ///
889    /// The snapping distance (in nanoseconds) of `self`.
890    #[doc(alias = "ges_timeline_get_snapping_distance")]
891    #[doc(alias = "get_snapping_distance")]
892    #[doc(alias = "snapping-distance")]
893    fn snapping_distance(&self) -> Option<gst::ClockTime> {
894        unsafe {
895            from_glib(ffi::ges_timeline_get_snapping_distance(
896                self.as_ref().to_glib_none().0,
897            ))
898        }
899    }
900
901    /// Search for the [`Track`][crate::Track] corresponding to the given timeline's pad.
902    /// ## `pad`
903    /// A pad
904    ///
905    /// # Returns
906    ///
907    /// The track corresponding to `pad`,
908    /// or [`None`] if there is an error.
909    #[doc(alias = "ges_timeline_get_track_for_pad")]
910    #[doc(alias = "get_track_for_pad")]
911    fn track_for_pad(&self, pad: &impl IsA<gst::Pad>) -> Option<Track> {
912        unsafe {
913            from_glib_none(ffi::ges_timeline_get_track_for_pad(
914                self.as_ref().to_glib_none().0,
915                pad.as_ref().to_glib_none().0,
916            ))
917        }
918    }
919
920    /// Get the list of [`Track`][crate::Track]-s used by the timeline.
921    ///
922    /// # Returns
923    ///
924    /// The list of tracks
925    /// used by `self`.
926    #[doc(alias = "ges_timeline_get_tracks")]
927    #[doc(alias = "get_tracks")]
928    fn tracks(&self) -> Vec<Track> {
929        unsafe {
930            FromGlibPtrContainer::from_glib_full(ffi::ges_timeline_get_tracks(
931                self.as_ref().to_glib_none().0,
932            ))
933        }
934    }
935
936    /// Check whether the timeline is empty or not.
937    ///
938    /// # Returns
939    ///
940    /// [`true`] if `self` is empty.
941    #[doc(alias = "ges_timeline_is_empty")]
942    fn is_empty(&self) -> bool {
943        unsafe { from_glib(ffi::ges_timeline_is_empty(self.as_ref().to_glib_none().0)) }
944    }
945
946    /// Loads the contents of URI into the timeline.
947    /// ## `uri`
948    /// The URI to load from
949    ///
950    /// # Returns
951    ///
952    /// [`true`] if the timeline was loaded successfully from `uri`.
953    #[doc(alias = "ges_timeline_load_from_uri")]
954    fn load_from_uri(&self, uri: &str) -> Result<(), glib::Error> {
955        unsafe {
956            let mut error = std::ptr::null_mut();
957            let is_ok = ffi::ges_timeline_load_from_uri(
958                self.as_ref().to_glib_none().0,
959                uri.to_glib_none().0,
960                &mut error,
961            );
962            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
963            if error.is_null() {
964                Ok(())
965            } else {
966                Err(from_glib_full(error))
967            }
968        }
969    }
970
971    /// Moves a layer within the timeline to the index given by
972    /// `new_layer_priority`.
973    /// An index of 0 corresponds to the layer with the highest priority in a
974    /// timeline. If `new_layer_priority` is greater than the number of layers
975    /// present in the timeline, it will become the lowest priority layer.
976    /// ## `layer`
977    /// A layer within `self`, whose priority should be changed
978    /// ## `new_layer_priority`
979    /// The new index for `layer`
980    #[cfg(feature = "v1_16")]
981    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
982    #[doc(alias = "ges_timeline_move_layer")]
983    fn move_layer(
984        &self,
985        layer: &impl IsA<Layer>,
986        new_layer_priority: u32,
987    ) -> Result<(), glib::error::BoolError> {
988        unsafe {
989            glib::result_from_gboolean!(
990                ffi::ges_timeline_move_layer(
991                    self.as_ref().to_glib_none().0,
992                    layer.as_ref().to_glib_none().0,
993                    new_layer_priority
994                ),
995                "Failed to move layer"
996            )
997        }
998    }
999
1000    /// Paste an element inside the timeline. `element` **must** be the return of
1001    /// `ges_timeline_element_copy()` with `deep=TRUE`,
1002    /// and it should not be changed before pasting. `element` itself is not
1003    /// placed in the timeline, instead a new element is created, alike to the
1004    /// originally copied element. Note that the originally copied element must
1005    /// also lie within `self`, at both the point of copying and pasting.
1006    ///
1007    /// Pasting may fail if it would place the timeline in an unsupported
1008    /// configuration.
1009    ///
1010    /// After calling this function `element` should not be used. In particular,
1011    /// `element` can **not** be pasted again. Instead, you can copy the
1012    /// returned element and paste that copy (although, this is only possible
1013    /// if the paste was successful).
1014    ///
1015    /// See also [`TimelineElementExt::paste()`][crate::prelude::TimelineElementExt::paste()].
1016    /// ## `element`
1017    /// The element to paste
1018    /// ## `position`
1019    /// The position in the timeline `element` should be pasted to,
1020    /// i.e. the [`start`][struct@crate::TimelineElement#start] value for the pasted element.
1021    /// ## `layer_priority`
1022    /// The layer into which the element should be pasted.
1023    /// -1 means paste to the same layer from which `element` has been copied from
1024    ///
1025    /// # Returns
1026    ///
1027    /// The newly created element, or
1028    /// [`None`] if pasting fails.
1029    #[doc(alias = "ges_timeline_paste_element")]
1030    fn paste_element(
1031        &self,
1032        element: &impl IsA<TimelineElement>,
1033        position: gst::ClockTime,
1034        layer_priority: i32,
1035    ) -> Option<TimelineElement> {
1036        unsafe {
1037            from_glib_full(ffi::ges_timeline_paste_element(
1038                self.as_ref().to_glib_none().0,
1039                element.as_ref().to_glib_none().0,
1040                position.into_glib(),
1041                layer_priority,
1042            ))
1043        }
1044    }
1045
1046    /// Removes a layer from the timeline.
1047    /// ## `layer`
1048    /// The layer to remove
1049    ///
1050    /// # Returns
1051    ///
1052    /// [`true`] if `layer` was properly removed.
1053    #[doc(alias = "ges_timeline_remove_layer")]
1054    fn remove_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
1055        unsafe {
1056            glib::result_from_gboolean!(
1057                ffi::ges_timeline_remove_layer(
1058                    self.as_ref().to_glib_none().0,
1059                    layer.as_ref().to_glib_none().0
1060                ),
1061                "Failed to remove layer"
1062            )
1063        }
1064    }
1065
1066    /// Remove a track from the timeline.
1067    /// ## `track`
1068    /// The track to remove
1069    ///
1070    /// # Returns
1071    ///
1072    /// [`true`] if `track` was properly removed.
1073    #[doc(alias = "ges_timeline_remove_track")]
1074    fn remove_track(&self, track: &impl IsA<Track>) -> Result<(), glib::error::BoolError> {
1075        unsafe {
1076            glib::result_from_gboolean!(
1077                ffi::ges_timeline_remove_track(
1078                    self.as_ref().to_glib_none().0,
1079                    track.as_ref().to_glib_none().0
1080                ),
1081                "Failed to remove track"
1082            )
1083        }
1084    }
1085
1086    /// Saves the timeline to the given location. If `formatter_asset` is [`None`],
1087    /// the method will attempt to save in the same format the timeline was
1088    /// loaded from, before defaulting to the formatter with highest rank.
1089    /// ## `uri`
1090    /// The location to save to
1091    /// ## `formatter_asset`
1092    /// The formatter asset to use, or [`None`]
1093    /// ## `overwrite`
1094    /// [`true`] to overwrite file if it exists
1095    ///
1096    /// # Returns
1097    ///
1098    /// [`true`] if `self` was successfully saved to `uri`.
1099    #[doc(alias = "ges_timeline_save_to_uri")]
1100    fn save_to_uri(
1101        &self,
1102        uri: &str,
1103        formatter_asset: Option<&impl IsA<Asset>>,
1104        overwrite: bool,
1105    ) -> Result<(), glib::Error> {
1106        unsafe {
1107            let mut error = std::ptr::null_mut();
1108            let is_ok = ffi::ges_timeline_save_to_uri(
1109                self.as_ref().to_glib_none().0,
1110                uri.to_glib_none().0,
1111                formatter_asset.map(|p| p.as_ref()).to_glib_none().0,
1112                overwrite.into_glib(),
1113                &mut error,
1114            );
1115            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1116            if error.is_null() {
1117                Ok(())
1118            } else {
1119                Err(from_glib_full(error))
1120            }
1121        }
1122    }
1123
1124    /// Sets [`auto-transition`][struct@crate::Timeline#auto-transition] for the timeline. This will also set
1125    /// the corresponding [`auto-transition`][struct@crate::Layer#auto-transition] for all of the timeline's
1126    /// layers to the same value. See [`LayerExt::set_auto_transition()`][crate::prelude::LayerExt::set_auto_transition()] if you
1127    /// wish to set the layer's [`auto-transition`][struct@crate::Layer#auto-transition] individually.
1128    /// ## `auto_transition`
1129    /// Whether transitions should be automatically added
1130    /// to `self`'s layers
1131    #[doc(alias = "ges_timeline_set_auto_transition")]
1132    #[doc(alias = "auto-transition")]
1133    fn set_auto_transition(&self, auto_transition: bool) {
1134        unsafe {
1135            ffi::ges_timeline_set_auto_transition(
1136                self.as_ref().to_glib_none().0,
1137                auto_transition.into_glib(),
1138            );
1139        }
1140    }
1141
1142    /// Sets [`snapping-distance`][struct@crate::Timeline#snapping-distance] for the timeline. This new value
1143    /// will only effect future snappings and will not be used to snap the
1144    /// current element positions within the timeline.
1145    /// ## `snapping_distance`
1146    /// The snapping distance to use (in nanoseconds)
1147    #[doc(alias = "ges_timeline_set_snapping_distance")]
1148    #[doc(alias = "snapping-distance")]
1149    fn set_snapping_distance(&self, snapping_distance: gst::ClockTime) {
1150        unsafe {
1151            ffi::ges_timeline_set_snapping_distance(
1152                self.as_ref().to_glib_none().0,
1153                snapping_distance.into_glib(),
1154            );
1155        }
1156    }
1157
1158    /// Thaw the timeline so that comiting becomes possible
1159    /// again and any call to ``commit()`` that happened during the rendering is
1160    /// actually taken into account.
1161    #[cfg(feature = "v1_20")]
1162    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1163    #[doc(alias = "ges_timeline_thaw_commit")]
1164    fn thaw_commit(&self) {
1165        unsafe {
1166            ffi::ges_timeline_thaw_commit(self.as_ref().to_glib_none().0);
1167        }
1168    }
1169
1170    /// This signal will be emitted once the changes initiated by
1171    /// [`commit()`][Self::commit()] have been executed in the backend. Use
1172    /// [`commit_sync()`][Self::commit_sync()] if you do not want to have to connect
1173    /// to this signal.
1174    #[doc(alias = "commited")]
1175    fn connect_commited<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1176        unsafe extern "C" fn commited_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1177            this: *mut ffi::GESTimeline,
1178            f: glib::ffi::gpointer,
1179        ) {
1180            let f: &F = &*(f as *const F);
1181            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1182        }
1183        unsafe {
1184            let f: Box_<F> = Box_::new(f);
1185            connect_raw(
1186                self.as_ptr() as *mut _,
1187                b"commited\0".as_ptr() as *const _,
1188                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1189                    commited_trampoline::<Self, F> as *const (),
1190                )),
1191                Box_::into_raw(f),
1192            )
1193        }
1194    }
1195
1196    /// Will be emitted after the group is added to to the timeline. This can
1197    /// happen when grouping with `ges_container_group`, or by adding
1198    /// containers to a newly created group.
1199    ///
1200    /// Note that this should not be emitted whilst a timeline is being
1201    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1202    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which groups
1203    /// were created for the timeline.
1204    /// ## `group`
1205    /// The group that was added to `timeline`
1206    #[doc(alias = "group-added")]
1207    fn connect_group_added<F: Fn(&Self, &Group) + 'static>(&self, f: F) -> SignalHandlerId {
1208        unsafe extern "C" fn group_added_trampoline<
1209            P: IsA<Timeline>,
1210            F: Fn(&P, &Group) + 'static,
1211        >(
1212            this: *mut ffi::GESTimeline,
1213            group: *mut ffi::GESGroup,
1214            f: glib::ffi::gpointer,
1215        ) {
1216            let f: &F = &*(f as *const F);
1217            f(
1218                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1219                &from_glib_borrow(group),
1220            )
1221        }
1222        unsafe {
1223            let f: Box_<F> = Box_::new(f);
1224            connect_raw(
1225                self.as_ptr() as *mut _,
1226                b"group-added\0".as_ptr() as *const _,
1227                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1228                    group_added_trampoline::<Self, F> as *const (),
1229                )),
1230                Box_::into_raw(f),
1231            )
1232        }
1233    }
1234
1235    //#[doc(alias = "group-removed")]
1236    //fn connect_group_removed<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1237    //    Empty ctype children: *.PtrArray TypeId { ns_id: 1, id: 54 }
1238    //}
1239
1240    /// Will be emitted after the layer is added to the timeline.
1241    ///
1242    /// Note that this should not be emitted whilst a timeline is being
1243    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1244    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1245    /// layers were created for the timeline.
1246    /// ## `layer`
1247    /// The layer that was added to `timeline`
1248    #[doc(alias = "layer-added")]
1249    fn connect_layer_added<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1250        unsafe extern "C" fn layer_added_trampoline<
1251            P: IsA<Timeline>,
1252            F: Fn(&P, &Layer) + 'static,
1253        >(
1254            this: *mut ffi::GESTimeline,
1255            layer: *mut ffi::GESLayer,
1256            f: glib::ffi::gpointer,
1257        ) {
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        unsafe {
1265            let f: Box_<F> = Box_::new(f);
1266            connect_raw(
1267                self.as_ptr() as *mut _,
1268                b"layer-added\0".as_ptr() as *const _,
1269                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1270                    layer_added_trampoline::<Self, F> as *const (),
1271                )),
1272                Box_::into_raw(f),
1273            )
1274        }
1275    }
1276
1277    /// Will be emitted after the layer is removed from the timeline.
1278    /// ## `layer`
1279    /// The layer that was removed from `timeline`
1280    #[doc(alias = "layer-removed")]
1281    fn connect_layer_removed<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1282        unsafe extern "C" fn layer_removed_trampoline<
1283            P: IsA<Timeline>,
1284            F: Fn(&P, &Layer) + 'static,
1285        >(
1286            this: *mut ffi::GESTimeline,
1287            layer: *mut ffi::GESLayer,
1288            f: glib::ffi::gpointer,
1289        ) {
1290            let f: &F = &*(f as *const F);
1291            f(
1292                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1293                &from_glib_borrow(layer),
1294            )
1295        }
1296        unsafe {
1297            let f: Box_<F> = Box_::new(f);
1298            connect_raw(
1299                self.as_ptr() as *mut _,
1300                b"layer-removed\0".as_ptr() as *const _,
1301                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1302                    layer_removed_trampoline::<Self, F> as *const (),
1303                )),
1304                Box_::into_raw(f),
1305            )
1306        }
1307    }
1308
1309    /// Simplified version of [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] which only
1310    /// allows `track_element` to be added to a single [`Track`][crate::Track].
1311    /// ## `clip`
1312    /// The clip that `track_element` is being added to
1313    /// ## `track_element`
1314    /// The element being added
1315    ///
1316    /// # Returns
1317    ///
1318    /// A track to put `track_element` into, or [`None`] if
1319    /// it should be discarded.
1320    #[cfg(feature = "v1_18")]
1321    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1322    #[doc(alias = "select-element-track")]
1323    fn connect_select_element_track<
1324        F: Fn(&Self, &Clip, &TrackElement) -> Option<Track> + 'static,
1325    >(
1326        &self,
1327        f: F,
1328    ) -> SignalHandlerId {
1329        unsafe extern "C" fn select_element_track_trampoline<
1330            P: IsA<Timeline>,
1331            F: Fn(&P, &Clip, &TrackElement) -> Option<Track> + 'static,
1332        >(
1333            this: *mut ffi::GESTimeline,
1334            clip: *mut ffi::GESClip,
1335            track_element: *mut ffi::GESTrackElement,
1336            f: glib::ffi::gpointer,
1337        ) -> *mut ffi::GESTrack {
1338            let f: &F = &*(f as *const F);
1339            f(
1340                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1341                &from_glib_borrow(clip),
1342                &from_glib_borrow(track_element),
1343            )
1344            .to_glib_full()
1345        }
1346        unsafe {
1347            let f: Box_<F> = Box_::new(f);
1348            connect_raw(
1349                self.as_ptr() as *mut _,
1350                b"select-element-track\0".as_ptr() as *const _,
1351                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1352                    select_element_track_trampoline::<Self, F> as *const (),
1353                )),
1354                Box_::into_raw(f),
1355            )
1356        }
1357    }
1358
1359    //#[doc(alias = "select-tracks-for-object")]
1360    //fn connect_select_tracks_for_object<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1361    //    Empty ctype return value *.PtrArray TypeId { ns_id: 1, id: 17 }
1362    //}
1363
1364    /// Will be emitted whenever a snapping event ends. After a snap event
1365    /// has started (see [`snapping-started`][struct@crate::Timeline#snapping-started]), it can later end
1366    /// because either another timeline edit has occurred (which may or may
1367    /// not have created a new snapping event), or because the timeline has
1368    /// been committed.
1369    /// ## `obj1`
1370    /// The first element that was snapping
1371    /// ## `obj2`
1372    /// The second element that was snapping
1373    /// ## `position`
1374    /// The position where the two objects were to be snapped to
1375    #[doc(alias = "snapping-ended")]
1376    fn connect_snapping_ended<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1377        &self,
1378        f: F,
1379    ) -> SignalHandlerId {
1380        unsafe extern "C" fn snapping_ended_trampoline<
1381            P: IsA<Timeline>,
1382            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1383        >(
1384            this: *mut ffi::GESTimeline,
1385            obj1: *mut ffi::GESTrackElement,
1386            obj2: *mut ffi::GESTrackElement,
1387            position: u64,
1388            f: glib::ffi::gpointer,
1389        ) {
1390            let f: &F = &*(f as *const F);
1391            f(
1392                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1393                &from_glib_borrow(obj1),
1394                &from_glib_borrow(obj2),
1395                position,
1396            )
1397        }
1398        unsafe {
1399            let f: Box_<F> = Box_::new(f);
1400            connect_raw(
1401                self.as_ptr() as *mut _,
1402                b"snapping-ended\0".as_ptr() as *const _,
1403                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1404                    snapping_ended_trampoline::<Self, F> as *const (),
1405                )),
1406                Box_::into_raw(f),
1407            )
1408        }
1409    }
1410
1411    /// Will be emitted whenever an element's movement invokes a snapping
1412    /// event during an edit (usually of one of its ancestors) because its
1413    /// start or end point lies within the [`snapping-distance`][struct@crate::Timeline#snapping-distance] of
1414    /// another element's start or end point.
1415    ///
1416    /// See [`EditMode`][crate::EditMode] to see what can snap during an edit.
1417    ///
1418    /// Note that only up to one snapping-started signal will be emitted per
1419    /// element edit within a timeline.
1420    /// ## `obj1`
1421    /// The first element that is snapping
1422    /// ## `obj2`
1423    /// The second element that is snapping
1424    /// ## `position`
1425    /// The position where the two objects will snap to
1426    #[doc(alias = "snapping-started")]
1427    fn connect_snapping_started<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1428        &self,
1429        f: F,
1430    ) -> SignalHandlerId {
1431        unsafe extern "C" fn snapping_started_trampoline<
1432            P: IsA<Timeline>,
1433            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1434        >(
1435            this: *mut ffi::GESTimeline,
1436            obj1: *mut ffi::GESTrackElement,
1437            obj2: *mut ffi::GESTrackElement,
1438            position: u64,
1439            f: glib::ffi::gpointer,
1440        ) {
1441            let f: &F = &*(f as *const F);
1442            f(
1443                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1444                &from_glib_borrow(obj1),
1445                &from_glib_borrow(obj2),
1446                position,
1447            )
1448        }
1449        unsafe {
1450            let f: Box_<F> = Box_::new(f);
1451            connect_raw(
1452                self.as_ptr() as *mut _,
1453                b"snapping-started\0".as_ptr() as *const _,
1454                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1455                    snapping_started_trampoline::<Self, F> as *const (),
1456                )),
1457                Box_::into_raw(f),
1458            )
1459        }
1460    }
1461
1462    /// Will be emitted after the track is added to the timeline.
1463    ///
1464    /// Note that this should not be emitted whilst a timeline is being
1465    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1466    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1467    /// tracks were created for the timeline.
1468    /// ## `track`
1469    /// The track that was added to `timeline`
1470    #[doc(alias = "track-added")]
1471    fn connect_track_added<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1472        unsafe extern "C" fn track_added_trampoline<
1473            P: IsA<Timeline>,
1474            F: Fn(&P, &Track) + 'static,
1475        >(
1476            this: *mut ffi::GESTimeline,
1477            track: *mut ffi::GESTrack,
1478            f: glib::ffi::gpointer,
1479        ) {
1480            let f: &F = &*(f as *const F);
1481            f(
1482                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1483                &from_glib_borrow(track),
1484            )
1485        }
1486        unsafe {
1487            let f: Box_<F> = Box_::new(f);
1488            connect_raw(
1489                self.as_ptr() as *mut _,
1490                b"track-added\0".as_ptr() as *const _,
1491                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1492                    track_added_trampoline::<Self, F> as *const (),
1493                )),
1494                Box_::into_raw(f),
1495            )
1496        }
1497    }
1498
1499    /// Will be emitted after the track is removed from the timeline.
1500    /// ## `track`
1501    /// The track that was removed from `timeline`
1502    #[doc(alias = "track-removed")]
1503    fn connect_track_removed<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1504        unsafe extern "C" fn track_removed_trampoline<
1505            P: IsA<Timeline>,
1506            F: Fn(&P, &Track) + 'static,
1507        >(
1508            this: *mut ffi::GESTimeline,
1509            track: *mut ffi::GESTrack,
1510            f: glib::ffi::gpointer,
1511        ) {
1512            let f: &F = &*(f as *const F);
1513            f(
1514                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1515                &from_glib_borrow(track),
1516            )
1517        }
1518        unsafe {
1519            let f: Box_<F> = Box_::new(f);
1520            connect_raw(
1521                self.as_ptr() as *mut _,
1522                b"track-removed\0".as_ptr() as *const _,
1523                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1524                    track_removed_trampoline::<Self, F> as *const (),
1525                )),
1526                Box_::into_raw(f),
1527            )
1528        }
1529    }
1530
1531    #[doc(alias = "auto-transition")]
1532    fn connect_auto_transition_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1533        unsafe extern "C" fn notify_auto_transition_trampoline<
1534            P: IsA<Timeline>,
1535            F: Fn(&P) + 'static,
1536        >(
1537            this: *mut ffi::GESTimeline,
1538            _param_spec: glib::ffi::gpointer,
1539            f: glib::ffi::gpointer,
1540        ) {
1541            let f: &F = &*(f as *const F);
1542            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1543        }
1544        unsafe {
1545            let f: Box_<F> = Box_::new(f);
1546            connect_raw(
1547                self.as_ptr() as *mut _,
1548                b"notify::auto-transition\0".as_ptr() as *const _,
1549                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1550                    notify_auto_transition_trampoline::<Self, F> as *const (),
1551                )),
1552                Box_::into_raw(f),
1553            )
1554        }
1555    }
1556
1557    #[doc(alias = "duration")]
1558    fn connect_duration_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1559        unsafe extern "C" fn notify_duration_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1560            this: *mut ffi::GESTimeline,
1561            _param_spec: glib::ffi::gpointer,
1562            f: glib::ffi::gpointer,
1563        ) {
1564            let f: &F = &*(f as *const F);
1565            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1566        }
1567        unsafe {
1568            let f: Box_<F> = Box_::new(f);
1569            connect_raw(
1570                self.as_ptr() as *mut _,
1571                b"notify::duration\0".as_ptr() as *const _,
1572                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1573                    notify_duration_trampoline::<Self, F> as *const (),
1574                )),
1575                Box_::into_raw(f),
1576            )
1577        }
1578    }
1579
1580    #[doc(alias = "snapping-distance")]
1581    fn connect_snapping_distance_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1582        unsafe extern "C" fn notify_snapping_distance_trampoline<
1583            P: IsA<Timeline>,
1584            F: Fn(&P) + 'static,
1585        >(
1586            this: *mut ffi::GESTimeline,
1587            _param_spec: glib::ffi::gpointer,
1588            f: glib::ffi::gpointer,
1589        ) {
1590            let f: &F = &*(f as *const F);
1591            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1592        }
1593        unsafe {
1594            let f: Box_<F> = Box_::new(f);
1595            connect_raw(
1596                self.as_ptr() as *mut _,
1597                b"notify::snapping-distance\0".as_ptr() as *const _,
1598                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1599                    notify_snapping_distance_trampoline::<Self, F> as *const (),
1600                )),
1601                Box_::into_raw(f),
1602            )
1603        }
1604    }
1605}
1606
1607impl<O: IsA<Timeline>> TimelineExt for O {}