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