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
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            let f: &F = &*(f as *const F);
1176            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1177        }
1178        unsafe {
1179            let f: Box_<F> = Box_::new(f);
1180            connect_raw(
1181                self.as_ptr() as *mut _,
1182                c"commited".as_ptr() as *const _,
1183                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1184                    commited_trampoline::<Self, F> as *const (),
1185                )),
1186                Box_::into_raw(f),
1187            )
1188        }
1189    }
1190
1191    /// Will be emitted after the group is added to to the timeline. This can
1192    /// happen when grouping with `ges_container_group`, or by adding
1193    /// containers to a newly created group.
1194    ///
1195    /// Note that this should not be emitted whilst a timeline is being
1196    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1197    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which groups
1198    /// were created for the timeline.
1199    /// ## `group`
1200    /// The group that was added to `timeline`
1201    #[doc(alias = "group-added")]
1202    fn connect_group_added<F: Fn(&Self, &Group) + 'static>(&self, f: F) -> SignalHandlerId {
1203        unsafe extern "C" fn group_added_trampoline<
1204            P: IsA<Timeline>,
1205            F: Fn(&P, &Group) + 'static,
1206        >(
1207            this: *mut ffi::GESTimeline,
1208            group: *mut ffi::GESGroup,
1209            f: glib::ffi::gpointer,
1210        ) {
1211            let f: &F = &*(f as *const F);
1212            f(
1213                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1214                &from_glib_borrow(group),
1215            )
1216        }
1217        unsafe {
1218            let f: Box_<F> = Box_::new(f);
1219            connect_raw(
1220                self.as_ptr() as *mut _,
1221                c"group-added".as_ptr() as *const _,
1222                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1223                    group_added_trampoline::<Self, F> as *const (),
1224                )),
1225                Box_::into_raw(f),
1226            )
1227        }
1228    }
1229
1230    //#[doc(alias = "group-removed")]
1231    //fn connect_group_removed<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1232    //    Empty ctype children: *.PtrArray TypeId { ns_id: 1, id: 54 }
1233    //}
1234
1235    /// Will be emitted after the layer is added to the timeline.
1236    ///
1237    /// Note that this should not be emitted whilst a timeline is being
1238    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1239    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1240    /// layers were created for the timeline.
1241    /// ## `layer`
1242    /// The layer that was added to `timeline`
1243    #[doc(alias = "layer-added")]
1244    fn connect_layer_added<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1245        unsafe extern "C" fn layer_added_trampoline<
1246            P: IsA<Timeline>,
1247            F: Fn(&P, &Layer) + 'static,
1248        >(
1249            this: *mut ffi::GESTimeline,
1250            layer: *mut ffi::GESLayer,
1251            f: glib::ffi::gpointer,
1252        ) {
1253            let f: &F = &*(f as *const F);
1254            f(
1255                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1256                &from_glib_borrow(layer),
1257            )
1258        }
1259        unsafe {
1260            let f: Box_<F> = Box_::new(f);
1261            connect_raw(
1262                self.as_ptr() as *mut _,
1263                c"layer-added".as_ptr() as *const _,
1264                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1265                    layer_added_trampoline::<Self, F> as *const (),
1266                )),
1267                Box_::into_raw(f),
1268            )
1269        }
1270    }
1271
1272    /// Will be emitted after the layer is removed from the timeline.
1273    /// ## `layer`
1274    /// The layer that was removed from `timeline`
1275    #[doc(alias = "layer-removed")]
1276    fn connect_layer_removed<F: Fn(&Self, &Layer) + 'static>(&self, f: F) -> SignalHandlerId {
1277        unsafe extern "C" fn layer_removed_trampoline<
1278            P: IsA<Timeline>,
1279            F: Fn(&P, &Layer) + 'static,
1280        >(
1281            this: *mut ffi::GESTimeline,
1282            layer: *mut ffi::GESLayer,
1283            f: glib::ffi::gpointer,
1284        ) {
1285            let f: &F = &*(f as *const F);
1286            f(
1287                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1288                &from_glib_borrow(layer),
1289            )
1290        }
1291        unsafe {
1292            let f: Box_<F> = Box_::new(f);
1293            connect_raw(
1294                self.as_ptr() as *mut _,
1295                c"layer-removed".as_ptr() as *const _,
1296                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1297                    layer_removed_trampoline::<Self, F> as *const (),
1298                )),
1299                Box_::into_raw(f),
1300            )
1301        }
1302    }
1303
1304    /// Simplified version of [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] which only
1305    /// allows `track_element` to be added to a single [`Track`][crate::Track].
1306    /// ## `clip`
1307    /// The clip that `track_element` is being added to
1308    /// ## `track_element`
1309    /// The element being added
1310    ///
1311    /// # Returns
1312    ///
1313    /// A track to put `track_element` into, or [`None`] if
1314    /// it should be discarded.
1315    #[cfg(feature = "v1_18")]
1316    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1317    #[doc(alias = "select-element-track")]
1318    fn connect_select_element_track<
1319        F: Fn(&Self, &Clip, &TrackElement) -> Option<Track> + 'static,
1320    >(
1321        &self,
1322        f: F,
1323    ) -> SignalHandlerId {
1324        unsafe extern "C" fn select_element_track_trampoline<
1325            P: IsA<Timeline>,
1326            F: Fn(&P, &Clip, &TrackElement) -> Option<Track> + 'static,
1327        >(
1328            this: *mut ffi::GESTimeline,
1329            clip: *mut ffi::GESClip,
1330            track_element: *mut ffi::GESTrackElement,
1331            f: glib::ffi::gpointer,
1332        ) -> *mut ffi::GESTrack {
1333            let f: &F = &*(f as *const F);
1334            f(
1335                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1336                &from_glib_borrow(clip),
1337                &from_glib_borrow(track_element),
1338            )
1339            .to_glib_full()
1340        }
1341        unsafe {
1342            let f: Box_<F> = Box_::new(f);
1343            connect_raw(
1344                self.as_ptr() as *mut _,
1345                c"select-element-track".as_ptr() as *const _,
1346                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1347                    select_element_track_trampoline::<Self, F> as *const (),
1348                )),
1349                Box_::into_raw(f),
1350            )
1351        }
1352    }
1353
1354    //#[doc(alias = "select-tracks-for-object")]
1355    //fn connect_select_tracks_for_object<Unsupported or ignored types>(&self, f: F) -> SignalHandlerId {
1356    //    Empty ctype return value *.PtrArray TypeId { ns_id: 1, id: 17 }
1357    //}
1358
1359    /// Will be emitted whenever a snapping event ends. After a snap event
1360    /// has started (see [`snapping-started`][struct@crate::Timeline#snapping-started]), it can later end
1361    /// because either another timeline edit has occurred (which may or may
1362    /// not have created a new snapping event), or because the timeline has
1363    /// been committed.
1364    /// ## `obj1`
1365    /// The first element that was snapping
1366    /// ## `obj2`
1367    /// The second element that was snapping
1368    /// ## `position`
1369    /// The position where the two objects were to be snapped to
1370    #[doc(alias = "snapping-ended")]
1371    fn connect_snapping_ended<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1372        &self,
1373        f: F,
1374    ) -> SignalHandlerId {
1375        unsafe extern "C" fn snapping_ended_trampoline<
1376            P: IsA<Timeline>,
1377            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1378        >(
1379            this: *mut ffi::GESTimeline,
1380            obj1: *mut ffi::GESTrackElement,
1381            obj2: *mut ffi::GESTrackElement,
1382            position: u64,
1383            f: glib::ffi::gpointer,
1384        ) {
1385            let f: &F = &*(f as *const F);
1386            f(
1387                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1388                &from_glib_borrow(obj1),
1389                &from_glib_borrow(obj2),
1390                position,
1391            )
1392        }
1393        unsafe {
1394            let f: Box_<F> = Box_::new(f);
1395            connect_raw(
1396                self.as_ptr() as *mut _,
1397                c"snapping-ended".as_ptr() as *const _,
1398                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1399                    snapping_ended_trampoline::<Self, F> as *const (),
1400                )),
1401                Box_::into_raw(f),
1402            )
1403        }
1404    }
1405
1406    /// Will be emitted whenever an element's movement invokes a snapping
1407    /// event during an edit (usually of one of its ancestors) because its
1408    /// start or end point lies within the [`snapping-distance`][struct@crate::Timeline#snapping-distance] of
1409    /// another element's start or end point.
1410    ///
1411    /// See [`EditMode`][crate::EditMode] to see what can snap during an edit.
1412    ///
1413    /// Note that only up to one snapping-started signal will be emitted per
1414    /// element edit within a timeline.
1415    /// ## `obj1`
1416    /// The first element that is snapping
1417    /// ## `obj2`
1418    /// The second element that is snapping
1419    /// ## `position`
1420    /// The position where the two objects will snap to
1421    #[doc(alias = "snapping-started")]
1422    fn connect_snapping_started<F: Fn(&Self, &TrackElement, &TrackElement, u64) + 'static>(
1423        &self,
1424        f: F,
1425    ) -> SignalHandlerId {
1426        unsafe extern "C" fn snapping_started_trampoline<
1427            P: IsA<Timeline>,
1428            F: Fn(&P, &TrackElement, &TrackElement, u64) + 'static,
1429        >(
1430            this: *mut ffi::GESTimeline,
1431            obj1: *mut ffi::GESTrackElement,
1432            obj2: *mut ffi::GESTrackElement,
1433            position: u64,
1434            f: glib::ffi::gpointer,
1435        ) {
1436            let f: &F = &*(f as *const F);
1437            f(
1438                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1439                &from_glib_borrow(obj1),
1440                &from_glib_borrow(obj2),
1441                position,
1442            )
1443        }
1444        unsafe {
1445            let f: Box_<F> = Box_::new(f);
1446            connect_raw(
1447                self.as_ptr() as *mut _,
1448                c"snapping-started".as_ptr() as *const _,
1449                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1450                    snapping_started_trampoline::<Self, F> as *const (),
1451                )),
1452                Box_::into_raw(f),
1453            )
1454        }
1455    }
1456
1457    /// Will be emitted after the track is added to the timeline.
1458    ///
1459    /// Note that this should not be emitted whilst a timeline is being
1460    /// loaded from its [`Project`][crate::Project] asset. You should connect to the
1461    /// project's [`loaded`][struct@crate::Project#loaded] signal if you want to know which
1462    /// tracks were created for the timeline.
1463    /// ## `track`
1464    /// The track that was added to `timeline`
1465    #[doc(alias = "track-added")]
1466    fn connect_track_added<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1467        unsafe extern "C" fn track_added_trampoline<
1468            P: IsA<Timeline>,
1469            F: Fn(&P, &Track) + 'static,
1470        >(
1471            this: *mut ffi::GESTimeline,
1472            track: *mut ffi::GESTrack,
1473            f: glib::ffi::gpointer,
1474        ) {
1475            let f: &F = &*(f as *const F);
1476            f(
1477                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1478                &from_glib_borrow(track),
1479            )
1480        }
1481        unsafe {
1482            let f: Box_<F> = Box_::new(f);
1483            connect_raw(
1484                self.as_ptr() as *mut _,
1485                c"track-added".as_ptr() as *const _,
1486                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1487                    track_added_trampoline::<Self, F> as *const (),
1488                )),
1489                Box_::into_raw(f),
1490            )
1491        }
1492    }
1493
1494    /// Will be emitted after the track is removed from the timeline.
1495    /// ## `track`
1496    /// The track that was removed from `timeline`
1497    #[doc(alias = "track-removed")]
1498    fn connect_track_removed<F: Fn(&Self, &Track) + 'static>(&self, f: F) -> SignalHandlerId {
1499        unsafe extern "C" fn track_removed_trampoline<
1500            P: IsA<Timeline>,
1501            F: Fn(&P, &Track) + 'static,
1502        >(
1503            this: *mut ffi::GESTimeline,
1504            track: *mut ffi::GESTrack,
1505            f: glib::ffi::gpointer,
1506        ) {
1507            let f: &F = &*(f as *const F);
1508            f(
1509                Timeline::from_glib_borrow(this).unsafe_cast_ref(),
1510                &from_glib_borrow(track),
1511            )
1512        }
1513        unsafe {
1514            let f: Box_<F> = Box_::new(f);
1515            connect_raw(
1516                self.as_ptr() as *mut _,
1517                c"track-removed".as_ptr() as *const _,
1518                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1519                    track_removed_trampoline::<Self, F> as *const (),
1520                )),
1521                Box_::into_raw(f),
1522            )
1523        }
1524    }
1525
1526    #[doc(alias = "auto-transition")]
1527    fn connect_auto_transition_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1528        unsafe extern "C" fn notify_auto_transition_trampoline<
1529            P: IsA<Timeline>,
1530            F: Fn(&P) + 'static,
1531        >(
1532            this: *mut ffi::GESTimeline,
1533            _param_spec: glib::ffi::gpointer,
1534            f: glib::ffi::gpointer,
1535        ) {
1536            let f: &F = &*(f as *const F);
1537            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1538        }
1539        unsafe {
1540            let f: Box_<F> = Box_::new(f);
1541            connect_raw(
1542                self.as_ptr() as *mut _,
1543                c"notify::auto-transition".as_ptr() as *const _,
1544                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1545                    notify_auto_transition_trampoline::<Self, F> as *const (),
1546                )),
1547                Box_::into_raw(f),
1548            )
1549        }
1550    }
1551
1552    #[doc(alias = "duration")]
1553    fn connect_duration_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1554        unsafe extern "C" fn notify_duration_trampoline<P: IsA<Timeline>, F: Fn(&P) + 'static>(
1555            this: *mut ffi::GESTimeline,
1556            _param_spec: glib::ffi::gpointer,
1557            f: glib::ffi::gpointer,
1558        ) {
1559            let f: &F = &*(f as *const F);
1560            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1561        }
1562        unsafe {
1563            let f: Box_<F> = Box_::new(f);
1564            connect_raw(
1565                self.as_ptr() as *mut _,
1566                c"notify::duration".as_ptr() as *const _,
1567                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1568                    notify_duration_trampoline::<Self, F> as *const (),
1569                )),
1570                Box_::into_raw(f),
1571            )
1572        }
1573    }
1574
1575    #[doc(alias = "snapping-distance")]
1576    fn connect_snapping_distance_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1577        unsafe extern "C" fn notify_snapping_distance_trampoline<
1578            P: IsA<Timeline>,
1579            F: Fn(&P) + 'static,
1580        >(
1581            this: *mut ffi::GESTimeline,
1582            _param_spec: glib::ffi::gpointer,
1583            f: glib::ffi::gpointer,
1584        ) {
1585            let f: &F = &*(f as *const F);
1586            f(Timeline::from_glib_borrow(this).unsafe_cast_ref())
1587        }
1588        unsafe {
1589            let f: Box_<F> = Box_::new(f);
1590            connect_raw(
1591                self.as_ptr() as *mut _,
1592                c"notify::snapping-distance".as_ptr() as *const _,
1593                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1594                    notify_snapping_distance_trampoline::<Self, F> as *const (),
1595                )),
1596                Box_::into_raw(f),
1597            )
1598        }
1599    }
1600}
1601
1602impl<O: IsA<Timeline>> TimelineExt for O {}