Skip to main content

gstreamer_editing_services/auto/
timeline.rs

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