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