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