gstreamer_editing_services/auto/clip.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
6#[cfg(feature = "v1_18")]
7#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
8use crate::FrameNumber;
9use crate::{
10 ffi, Asset, BaseEffect, Container, Extractable, Layer, MetaContainer, TimelineElement, Track,
11 TrackElement, TrackType,
12};
13use glib::{
14 prelude::*,
15 signal::{connect_raw, SignalHandlerId},
16 translate::*,
17};
18use std::boxed::Box as Box_;
19
20glib::wrapper! {
21 /// [`Clip`][crate::Clip]-s are the core objects of a [`Layer`][crate::Layer]. Each clip may exist in
22 /// a single layer but may control several [`TrackElement`][crate::TrackElement]-s that span
23 /// several [`Track`][crate::Track]-s. A clip will ensure that all its children share the
24 /// same [`start`][struct@crate::TimelineElement#start] and [`duration`][struct@crate::TimelineElement#duration] in
25 /// their tracks, which will match the [`start`][struct@crate::TimelineElement#start] and
26 /// [`duration`][struct@crate::TimelineElement#duration] of the clip itself. Therefore, changing
27 /// the timing of the clip will change the timing of the children, and a
28 /// change in the timing of a child will change the timing of the clip and
29 /// subsequently all its siblings. As such, a clip can be treated as a
30 /// singular object in its layer.
31 ///
32 /// For most uses of a [`Timeline`][crate::Timeline], it is often sufficient to only
33 /// interact with [`Clip`][crate::Clip]-s directly, which will take care of creating and
34 /// organising the elements of the timeline's tracks.
35 ///
36 /// ## Core Children
37 ///
38 /// In more detail, clips will usually have some *core* [`TrackElement`][crate::TrackElement]
39 /// children, which are created by the clip when it is added to a layer in
40 /// a timeline. The type and form of these core children will depend on the
41 /// clip's subclass. You can use [`TrackElementExt::is_core()`][crate::prelude::TrackElementExt::is_core()] to determine
42 /// whether a track element is considered such a core track element. Note,
43 /// if a core track element is part of a clip, it will always be treated as
44 /// a core *child* of the clip. You can connect to the
45 /// [`child-added`][struct@crate::Container#child-added] signal to be notified of their creation.
46 ///
47 /// When a child is added to a clip, the timeline will select its tracks
48 /// using [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object]. Note that it may be the
49 /// case that the child will still have no set [`track`][struct@crate::TrackElement#track]
50 /// after this process. For example, if the timeline does not have a track
51 /// of the corresponding [`track-type`][struct@crate::Track#track-type]. A clip can safely contain
52 /// such children, which may have their track set later, although they will
53 /// play no functioning role in the timeline in the meantime.
54 ///
55 /// If a clip may create track elements with various
56 /// [`track-type`][struct@crate::TrackElement#track-type](s), such as a [`UriClip`][crate::UriClip], but you only
57 /// want it to create a subset of these types, you should set the
58 /// [`supported-formats`][struct@crate::Clip#supported-formats] of the clip to the subset of types. This
59 /// should be done *before* adding the clip to a layer.
60 ///
61 /// If a clip will produce several core elements of the same
62 /// [`track-type`][struct@crate::TrackElement#track-type], you should connect to the timeline's
63 /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] signal to coordinate which
64 /// tracks each element should land in. Note, no two core children within a
65 /// clip can share the same [`Track`][crate::Track], so you should not select the same
66 /// track for two separate core children. Provided you stick to this rule,
67 /// it is still safe to select several tracks for the same core child, the
68 /// core child will be copied into the additional tracks. You can manually
69 /// add the child to more tracks later using [`ClipExt::add_child_to_track()`][crate::prelude::ClipExt::add_child_to_track()].
70 /// If you do not wish to use a core child, you can always select no track.
71 ///
72 /// The [`in-point`][struct@crate::TimelineElement#in-point] of the clip will control the
73 /// [`in-point`][struct@crate::TimelineElement#in-point] of its core children to be the same
74 /// value if their [`has-internal-source`][struct@crate::TrackElement#has-internal-source] is set to [`true`].
75 ///
76 /// The [`max-duration`][struct@crate::TimelineElement#max-duration] of the clip is the minimum
77 /// [`max-duration`][struct@crate::TimelineElement#max-duration] of its core children. If you set its
78 /// value to anything other than its current value, this will also set the
79 /// [`max-duration`][struct@crate::TimelineElement#max-duration] of all its core children to the same
80 /// value if their [`has-internal-source`][struct@crate::TrackElement#has-internal-source] is set to [`true`].
81 /// As a special case, whilst a clip does not yet have any core children,
82 /// its [`max-duration`][struct@crate::TimelineElement#max-duration] may be set to indicate what its
83 /// value will be once they are created.
84 ///
85 /// ## Effects
86 ///
87 /// Some subclasses ([`SourceClip`][crate::SourceClip] and [`BaseEffectClip`][crate::BaseEffectClip]) may also allow
88 /// their objects to have additional non-core [`BaseEffect`][crate::BaseEffect]-s elements as
89 /// children. These are additional effects that are applied to the output
90 /// data of the core elements. They can be added to the clip using
91 /// [`ClipExt::add_top_effect()`][crate::prelude::ClipExt::add_top_effect()], which will take care of adding the effect to
92 /// the timeline's tracks. The new effect will be placed between the clip's
93 /// core track elements and its other effects. As such, the newly added
94 /// effect will be applied to any source data **before** the other existing
95 /// effects. You can change the ordering of effects using
96 /// [`ClipExt::set_top_effect_index()`][crate::prelude::ClipExt::set_top_effect_index()].
97 ///
98 /// Tracks are selected for top effects in the same way as core children.
99 /// If you add a top effect to a clip before it is part of a timeline, and
100 /// later add the clip to a timeline, the track selection for the top
101 /// effects will occur just after the track selection for the core
102 /// children. If you add a top effect to a clip that is already part of a
103 /// timeline, the track selection will occur immediately. Since a top
104 /// effect must be applied on top of a core child, if you use
105 /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object], you should ensure that the
106 /// added effects are destined for a [`Track`][crate::Track] that already contains a core
107 /// child.
108 ///
109 /// In addition, if the core child in the track is not
110 /// [`active`][struct@crate::TrackElement#active], then neither can any of its effects be
111 /// [`active`][struct@crate::TrackElement#active]. Therefore, if a core child is made in-active,
112 /// all of the additional effects in the same track will also become
113 /// in-active. Similarly, if an effect is set to be active, then the core
114 /// child will also become active, but other effects will be left alone.
115 /// Finally, if an active effect is added to the track of an in-active core
116 /// child, it will become in-active as well. Note, in contrast, setting a
117 /// core child to be active, or an effect to be in-active will *not* change
118 /// the other children in the same track.
119 ///
120 /// ### Time Effects
121 ///
122 /// Some effects also change the timing of their data (see [`BaseEffect`][crate::BaseEffect]
123 /// for what counts as a time effect). Note that a [`BaseEffectClip`][crate::BaseEffectClip] will
124 /// refuse time effects, but a [`Source`][crate::Source] will allow them.
125 ///
126 /// When added to a clip, time effects may adjust the timing of other
127 /// children in the same track. Similarly, when changing the order of
128 /// effects, making them (in)-active, setting their time property values
129 /// or removing time effects. These can cause the [`duration-limit`][struct@crate::Clip#duration-limit]
130 /// to change in value. However, if such an operation would ever cause the
131 /// [`duration`][struct@crate::TimelineElement#duration] to shrink such that a clip's [`Source`][crate::Source] is
132 /// totally overlapped in the timeline, the operation would be prevented.
133 /// Note that the same can happen when adding non-time effects with a
134 /// finite [`max-duration`][struct@crate::TimelineElement#max-duration].
135 ///
136 /// Therefore, when working with time effects, you should -- more so than
137 /// usual -- not assume that setting the properties of the clip's children
138 /// will succeed. In particular, you should use
139 /// [`TimelineElementExt::set_child_property_full()`][crate::prelude::TimelineElementExt::set_child_property_full()] when setting the time
140 /// properties.
141 ///
142 /// If you wish to preserve the *internal* duration of a source in a clip
143 /// during these time effect operations, you can do something like the
144 /// following.
145 ///
146 /// **⚠️ The following code is in c ⚠️**
147 ///
148 /// ```c
149 /// void
150 /// do_time_effect_change (GESClip * clip)
151 /// {
152 /// GList *tmp, *children;
153 /// GESTrackElement *source;
154 /// GstClockTime source_outpoint;
155 /// GstClockTime new_end;
156 /// GError *error = NULL;
157 ///
158 /// // choose some active source in a track to preserve the internal
159 /// // duration of
160 /// source = ges_clip_get_track_element (clip, NULL, GES_TYPE_SOURCE);
161 ///
162 /// // note its current internal end time
163 /// source_outpoint = ges_clip_get_internal_time_from_timeline_time (
164 /// clip, source, GES_TIMELINE_ELEMENT_END (clip), NULL);
165 ///
166 /// // handle invalid out-point
167 ///
168 /// // stop the children's control sources from clamping when their
169 /// // out-point changes with a change in the time effects
170 /// children = ges_container_get_children (GES_CONTAINER (clip), FALSE);
171 ///
172 /// for (tmp = children; tmp; tmp = tmp->next)
173 /// ges_track_element_set_auto_clamp_control_sources (tmp->data, FALSE);
174 ///
175 /// // add time effect, or set their children properties, or move them around
176 /// ...
177 /// // user can make sure that if a time effect changes one source, we should
178 /// // also change the time effect for another source. E.g. if
179 /// // "GstVideorate::rate" is set to 2.0, we also set "GstPitch::rate" to
180 /// // 2.0
181 ///
182 /// // Note the duration of the clip may have already changed if the
183 /// // duration-limit of the clip dropped below its current value
184 ///
185 /// new_end = ges_clip_get_timeline_time_from_internal_time (
186 /// clip, source, source_outpoint, &error);
187 /// // handle error
188 ///
189 /// if (!ges_timeline_elemnet_edit_full (GES_TIMELINE_ELEMENT (clip),
190 /// -1, GES_EDIT_MODE_TRIM, GES_EDGE_END, new_end, &error))
191 /// // handle error
192 ///
193 /// for (tmp = children; tmp; tmp = tmp->next)
194 /// ges_track_element_set_auto_clamp_control_sources (tmp->data, TRUE);
195 ///
196 /// g_list_free_full (children, gst_object_unref);
197 /// gst_object_unref (source);
198 /// }
199 /// ```
200 ///
201 /// This is an Abstract Base Class, you cannot instantiate it.
202 ///
203 /// ## Properties
204 ///
205 ///
206 /// #### `duration-limit`
207 /// The maximum [`duration`][struct@crate::TimelineElement#duration] that can be *currently* set
208 /// for the clip, taking into account the [`in-point`][struct@crate::TimelineElement#in-point],
209 /// [`max-duration`][struct@crate::TimelineElement#max-duration], [`active`][struct@crate::TrackElement#active], and
210 /// [`track`][struct@crate::TrackElement#track] properties of its children, as well as any
211 /// time effects. If there is no limit, this will be set to
212 /// `GST_CLOCK_TIME_NONE`.
213 ///
214 /// Note that whilst a clip has no children in any tracks, the limit will
215 /// be unknown, and similarly set to `GST_CLOCK_TIME_NONE`.
216 ///
217 /// If the duration-limit would ever go below the current
218 /// [`duration`][struct@crate::TimelineElement#duration] of the clip due to a change in the above
219 /// variables, its [`duration`][struct@crate::TimelineElement#duration] will be set to the new
220 /// limit.
221 ///
222 /// Readable
223 ///
224 ///
225 /// #### `layer`
226 /// The layer this clip lies in.
227 ///
228 /// If you want to connect to this property's [`notify`][struct@crate::glib::Object#notify] signal,
229 /// you should connect to it with `g_signal_connect_after()` since the
230 /// signal emission may be stopped internally.
231 ///
232 /// Readable
233 ///
234 ///
235 /// #### `supported-formats`
236 /// The [`TrackType`][crate::TrackType]-s that the clip supports, which it can create
237 /// [`TrackElement`][crate::TrackElement]-s for. Note that this can be a combination of
238 /// [`TrackType`][crate::TrackType] flags to indicate support for several
239 /// [`track-type`][struct@crate::TrackElement#track-type] elements.
240 ///
241 /// Readable | Writeable | Construct
242 /// <details><summary><h4>Container</h4></summary>
243 ///
244 ///
245 /// #### `height`
246 /// The span of the container's children's [`priority`][struct@crate::TimelineElement#priority]
247 /// values, which is the number of integers that lie between (inclusive)
248 /// the minimum and maximum priorities found amongst the container's
249 /// children (maximum - minimum + 1).
250 ///
251 /// Readable
252 /// </details>
253 /// <details><summary><h4>TimelineElement</h4></summary>
254 ///
255 ///
256 /// #### `duration`
257 /// The duration that the element is in effect for in the timeline (a
258 /// time difference in nanoseconds using the time coordinates of the
259 /// timeline). For example, for a source element, this would determine
260 /// for how long it should output its internal content for. For an
261 /// operation element, this would determine for how long its effect
262 /// should be applied to any source content.
263 ///
264 /// Readable | Writeable
265 ///
266 ///
267 /// #### `in-point`
268 /// The initial offset to use internally when outputting content (in
269 /// nanoseconds, but in the time coordinates of the internal content).
270 ///
271 /// For example, for a [`VideoUriSource`][crate::VideoUriSource] that references some media
272 /// file, the "internal content" is the media file data, and the
273 /// in-point would correspond to some timestamp in the media file.
274 /// When playing the timeline, and when the element is first reached at
275 /// timeline-time [`start`][struct@crate::TimelineElement#start], it will begin outputting the
276 /// data from the timestamp in-point **onwards**, until it reaches the
277 /// end of its [`duration`][struct@crate::TimelineElement#duration] in the timeline.
278 ///
279 /// For elements that have no internal content, this should be kept
280 /// as 0.
281 ///
282 /// Readable | Writeable
283 ///
284 ///
285 /// #### `max-duration`
286 /// The full duration of internal content that is available (a time
287 /// difference in nanoseconds using the time coordinates of the internal
288 /// content).
289 ///
290 /// This will act as a cap on the [`in-point`][struct@crate::TimelineElement#in-point] of the
291 /// element (which is in the same time coordinates), and will sometimes
292 /// be used to limit the [`duration`][struct@crate::TimelineElement#duration] of the element in
293 /// the timeline.
294 ///
295 /// For example, for a [`VideoUriSource`][crate::VideoUriSource] that references some media
296 /// file, this would be the length of the media file.
297 ///
298 /// For elements that have no internal content, or whose content is
299 /// indefinite, this should be kept as `GST_CLOCK_TIME_NONE`.
300 ///
301 /// Readable | Writeable | Construct
302 ///
303 ///
304 /// #### `name`
305 /// The name of the element. This should be unique within its timeline.
306 ///
307 /// Readable | Writeable | Construct
308 ///
309 ///
310 /// #### `parent`
311 /// The parent container of the element.
312 ///
313 /// Readable | Writeable
314 ///
315 ///
316 /// #### `priority`
317 /// The priority of the element.
318 ///
319 /// Readable | Writeable
320 ///
321 ///
322 /// #### `serialize`
323 /// Whether the element should be serialized.
324 ///
325 /// Readable | Writeable
326 ///
327 ///
328 /// #### `start`
329 /// The starting position of the element in the timeline (in nanoseconds
330 /// and in the time coordinates of the timeline). For example, for a
331 /// source element, this would determine the time at which it should
332 /// start outputting its internal content. For an operation element, this
333 /// would determine the time at which it should start applying its effect
334 /// to any source content.
335 ///
336 /// Readable | Writeable
337 ///
338 ///
339 /// #### `timeline`
340 /// The timeline that the element lies within.
341 ///
342 /// Readable | Writeable
343 /// </details>
344 ///
345 /// # Implements
346 ///
347 /// [`ClipExt`][trait@crate::prelude::ClipExt], [`GESContainerExt`][trait@crate::prelude::GESContainerExt], [`TimelineElementExt`][trait@crate::prelude::TimelineElementExt], [`trait@glib::ObjectExt`], [`ExtractableExt`][trait@crate::prelude::ExtractableExt], [`MetaContainerExt`][trait@crate::prelude::MetaContainerExt], [`TimelineElementExtManual`][trait@crate::prelude::TimelineElementExtManual]
348 #[doc(alias = "GESClip")]
349 pub struct Clip(Object<ffi::GESClip, ffi::GESClipClass>) @extends Container, TimelineElement, @implements Extractable, MetaContainer;
350
351 match fn {
352 type_ => || ffi::ges_clip_get_type(),
353 }
354}
355
356impl Clip {
357 pub const NONE: Option<&'static Clip> = None;
358}
359
360/// Trait containing all [`struct@Clip`] methods.
361///
362/// # Implementors
363///
364/// [`Clip`][struct@crate::Clip], [`OperationClip`][struct@crate::OperationClip], [`SourceClip`][struct@crate::SourceClip]
365pub trait ClipExt: IsA<Clip> + 'static {
366 /// Extracts a [`TrackElement`][crate::TrackElement] from an asset and adds it to the clip.
367 /// This can be used to add effects that derive from the asset to the
368 /// clip, but this method is not intended to be used to create the core
369 /// elements of the clip.
370 /// ## `asset`
371 /// An asset with `GES_TYPE_TRACK_ELEMENT` as its
372 /// [`extractable-type`][struct@crate::Asset#extractable-type]
373 ///
374 /// # Returns
375 ///
376 /// The newly created element, or
377 /// [`None`] if an error occurred.
378 #[doc(alias = "ges_clip_add_asset")]
379 fn add_asset(&self, asset: &impl IsA<Asset>) -> Result<TrackElement, glib::BoolError> {
380 unsafe {
381 Option::<_>::from_glib_none(ffi::ges_clip_add_asset(
382 self.as_ref().to_glib_none().0,
383 asset.as_ref().to_glib_none().0,
384 ))
385 .ok_or_else(|| glib::bool_error!("Failed to add asset"))
386 }
387 }
388
389 /// Adds the track element child of the clip to a specific track.
390 ///
391 /// If the given child is already in another track, this will create a copy
392 /// of the child, add it to the clip, and add this copy to the track.
393 ///
394 /// You should only call this whilst a clip is part of a [`Timeline`][crate::Timeline], and
395 /// for tracks that are in the same timeline.
396 ///
397 /// This method is an alternative to using the
398 /// [`select-tracks-for-object`][struct@crate::Timeline#select-tracks-for-object] signal, but can be used to
399 /// complement it when, say, you wish to copy a clip's children from one
400 /// track into a new one.
401 ///
402 /// When the child is a core child, it must be added to a track that does
403 /// not already contain another core child of the same clip. If it is not a
404 /// core child (an additional effect), then it must be added to a track
405 /// that already contains one of the core children of the same clip.
406 ///
407 /// This method can also fail if the adding the track element to the track
408 /// would break a configuration rule of the corresponding [`Timeline`][crate::Timeline],
409 /// such as causing three sources to overlap at a single time, or causing
410 /// a source to completely overlap another in the same track.
411 /// ## `child`
412 /// A child of `self`
413 /// ## `track`
414 /// The track to add `child` to
415 ///
416 /// # Returns
417 ///
418 /// The element that was added to `track`, either
419 /// `child` or a copy of child, or [`None`] if the element could not be added.
420 #[cfg(feature = "v1_18")]
421 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
422 #[doc(alias = "ges_clip_add_child_to_track")]
423 fn add_child_to_track(
424 &self,
425 child: &impl IsA<TrackElement>,
426 track: &impl IsA<Track>,
427 ) -> Result<TrackElement, glib::Error> {
428 unsafe {
429 let mut error = std::ptr::null_mut();
430 let ret = ffi::ges_clip_add_child_to_track(
431 self.as_ref().to_glib_none().0,
432 child.as_ref().to_glib_none().0,
433 track.as_ref().to_glib_none().0,
434 &mut error,
435 );
436 if error.is_null() {
437 Ok(from_glib_none(ret))
438 } else {
439 Err(from_glib_full(error))
440 }
441 }
442 }
443
444 /// Add a top effect to a clip at the given index.
445 ///
446 /// Unlike using [`GESContainerExt::add()`][crate::prelude::GESContainerExt::add()], this allows you to set the index
447 /// in advance. It will also check that no error occurred during the track
448 /// selection for the effect.
449 ///
450 /// Note, only subclasses of `GESClipClass` that have
451 /// `GES_CLIP_CLASS_CAN_ADD_EFFECTS` set to [`true`] (such as [`SourceClip`][crate::SourceClip]
452 /// and [`BaseEffectClip`][crate::BaseEffectClip]) can have additional top effects added.
453 ///
454 /// Note, if the effect is a time effect, this may be refused if the clip
455 /// would not be able to adapt itself once the effect is added.
456 /// ## `effect`
457 /// A top effect to add
458 /// ## `index`
459 /// The index to add `effect` at, or -1 to add at the highest,
460 /// see `ges_clip_get_top_effect_index` for more information
461 ///
462 /// # Returns
463 ///
464 /// [`true`] if `effect` was successfully added to `self` at `index`.
465 #[cfg(feature = "v1_18")]
466 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
467 #[doc(alias = "ges_clip_add_top_effect")]
468 fn add_top_effect(&self, effect: &impl IsA<BaseEffect>, index: i32) -> Result<(), glib::Error> {
469 unsafe {
470 let mut error = std::ptr::null_mut();
471 let is_ok = ffi::ges_clip_add_top_effect(
472 self.as_ref().to_glib_none().0,
473 effect.as_ref().to_glib_none().0,
474 index,
475 &mut error,
476 );
477 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
478 if error.is_null() {
479 Ok(())
480 } else {
481 Err(from_glib_full(error))
482 }
483 }
484 }
485
486 /// Finds an element controlled by the clip. If `track` is given,
487 /// then only the track elements in `track` are searched for. If `type_` is
488 /// given, then this function searches for a track element of the given
489 /// `type_`.
490 ///
491 /// Note, if multiple track elements in the clip match the given criteria,
492 /// this will return the element amongst them with the highest
493 /// [`priority`][struct@crate::TimelineElement#priority] (numerically, the smallest). See
494 /// [`find_track_elements()`][Self::find_track_elements()] if you wish to find all such elements.
495 /// ## `track`
496 /// The track to search in, or [`None`] to search in
497 /// all tracks
498 /// ## `type_`
499 /// The type of track element to search for, or `G_TYPE_NONE` to
500 /// match any type
501 ///
502 /// # Returns
503 ///
504 /// The element controlled by
505 /// `self`, in `track`, and of the given `type_`, or [`None`] if no such element
506 /// could be found.
507 #[doc(alias = "ges_clip_find_track_element")]
508 fn find_track_element(
509 &self,
510 track: Option<&impl IsA<Track>>,
511 type_: glib::types::Type,
512 ) -> Option<TrackElement> {
513 unsafe {
514 from_glib_full(ffi::ges_clip_find_track_element(
515 self.as_ref().to_glib_none().0,
516 track.map(|p| p.as_ref()).to_glib_none().0,
517 type_.into_glib(),
518 ))
519 }
520 }
521
522 /// Finds the [`TrackElement`][crate::TrackElement]-s controlled by the clip that match the
523 /// given criteria. If `track` is given as [`None`] and `track_type` is given as
524 /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], then the search will match all elements in any
525 /// track, including those with no track, and of any
526 /// [`track-type`][struct@crate::TrackElement#track-type]. Otherwise, if `track` is not [`None`], but
527 /// `track_type` is [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], then only the track elements in
528 /// `track` are searched for. Otherwise, if `track_type` is not
529 /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN], but `track` is [`None`], then only the track
530 /// elements whose [`track-type`][struct@crate::TrackElement#track-type] matches `track_type` are
531 /// searched for. Otherwise, when both are given, the track elements that
532 /// match **either** criteria are searched for. Therefore, if you wish to
533 /// only find elements in a specific track, you should give the track as
534 /// `track`, but you should not give the track's [`track-type`][struct@crate::Track#track-type] as
535 /// `track_type` because this would also select elements from other tracks
536 /// of the same type.
537 ///
538 /// You may also give `type_` to _further_ restrict the search to track
539 /// elements of the given `type_`.
540 /// ## `track`
541 /// The track to search in, or [`None`] to search in
542 /// all tracks
543 /// ## `track_type`
544 /// The track-type of the track element to search for, or
545 /// [`TrackType::UNKNOWN`][crate::TrackType::UNKNOWN] to match any track type
546 /// ## `type_`
547 /// The type of track element to search for, or `G_TYPE_NONE` to
548 /// match any type
549 ///
550 /// # Returns
551 ///
552 /// A list of all
553 /// the [`TrackElement`][crate::TrackElement]-s controlled by `self`, in `track` or of the given
554 /// `track_type`, and of the given `type_`.
555 #[doc(alias = "ges_clip_find_track_elements")]
556 fn find_track_elements(
557 &self,
558 track: Option<&impl IsA<Track>>,
559 track_type: TrackType,
560 type_: glib::types::Type,
561 ) -> Vec<TrackElement> {
562 unsafe {
563 FromGlibPtrContainer::from_glib_full(ffi::ges_clip_find_track_elements(
564 self.as_ref().to_glib_none().0,
565 track.map(|p| p.as_ref()).to_glib_none().0,
566 track_type.into_glib(),
567 type_.into_glib(),
568 ))
569 }
570 }
571
572 /// Gets the [`duration-limit`][struct@crate::Clip#duration-limit] of the clip.
573 ///
574 /// # Returns
575 ///
576 /// The duration-limit of `self`.
577 #[cfg(feature = "v1_18")]
578 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
579 #[doc(alias = "ges_clip_get_duration_limit")]
580 #[doc(alias = "get_duration_limit")]
581 #[doc(alias = "duration-limit")]
582 fn duration_limit(&self) -> gst::ClockTime {
583 unsafe {
584 try_from_glib(ffi::ges_clip_get_duration_limit(
585 self.as_ref().to_glib_none().0,
586 ))
587 .expect("mandatory glib value is None")
588 }
589 }
590
591 /// Convert the timeline time to an internal source time of the child.
592 /// This will take any time effects placed on the clip into account (see
593 /// [`BaseEffect`][crate::BaseEffect] for what time effects are supported, and how to
594 /// declare them in GES).
595 ///
596 /// When `timeline_time` is above the [`start`][struct@crate::TimelineElement#start] of `self`,
597 /// this will return the internal time at which the content that appears at
598 /// `timeline_time` in the output of the timeline is created in `child`. For
599 /// example, if `timeline_time` corresponds to the current seek position,
600 /// this would let you know which part of a media file is being read.
601 ///
602 /// This will be done assuming the clip has an indefinite end, so the
603 /// internal time may be beyond the current out-point of the child, or even
604 /// its [`max-duration`][struct@crate::TimelineElement#max-duration].
605 ///
606 /// If, instead, `timeline_time` is below the current
607 /// [`start`][struct@crate::TimelineElement#start] of `self`, this will return what you would
608 /// need to set the [`in-point`][struct@crate::TimelineElement#in-point] of `child` to if you set
609 /// the [`start`][struct@crate::TimelineElement#start] of `self` to `timeline_time` and wanted
610 /// to keep the content of `child` currently found at the current
611 /// [`start`][struct@crate::TimelineElement#start] of `self` at the same timeline position. If
612 /// this would be negative, the conversion fails. This is useful for
613 /// determining what [`in-point`][struct@crate::TimelineElement#in-point] would result from a
614 /// [`EditMode::Trim`][crate::EditMode::Trim] to `timeline_time`.
615 ///
616 /// Note that whilst a clip has no time effects, this second return is
617 /// equivalent to finding the internal time at which the content that
618 /// appears at `timeline_time` in the timeline can be found in `child` if it
619 /// had indefinite extent in both directions. However, with non-linear time
620 /// effects this second return will be more distinct.
621 ///
622 /// In either case, the returned time would be appropriate to use for the
623 /// [`in-point`][struct@crate::TimelineElement#in-point] or [`max-duration`][struct@crate::TimelineElement#max-duration] of the
624 /// child.
625 ///
626 /// See [`timeline_time_from_internal_time()`][Self::timeline_time_from_internal_time()], which performs the
627 /// reverse.
628 /// ## `child`
629 /// An [`active`][struct@crate::TrackElement#active] child of `self` with a
630 /// [`track`][struct@crate::TrackElement#track]
631 /// ## `timeline_time`
632 /// A time in the timeline time coordinates
633 ///
634 /// # Returns
635 ///
636 /// The time in the internal coordinates of `child` corresponding
637 /// to `timeline_time`, or `GST_CLOCK_TIME_NONE` if the conversion could not
638 /// be performed.
639 #[cfg(feature = "v1_18")]
640 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
641 #[doc(alias = "ges_clip_get_internal_time_from_timeline_time")]
642 #[doc(alias = "get_internal_time_from_timeline_time")]
643 fn internal_time_from_timeline_time(
644 &self,
645 child: &impl IsA<TrackElement>,
646 timeline_time: impl Into<Option<gst::ClockTime>>,
647 ) -> Result<Option<gst::ClockTime>, glib::Error> {
648 unsafe {
649 let mut error = std::ptr::null_mut();
650 let ret = ffi::ges_clip_get_internal_time_from_timeline_time(
651 self.as_ref().to_glib_none().0,
652 child.as_ref().to_glib_none().0,
653 timeline_time.into().into_glib(),
654 &mut error,
655 );
656 if error.is_null() {
657 Ok(from_glib(ret))
658 } else {
659 Err(from_glib_full(error))
660 }
661 }
662 }
663
664 /// Gets the [`layer`][struct@crate::Clip#layer] of the clip.
665 ///
666 /// # Returns
667 ///
668 /// The layer `self` is in, or [`None`] if
669 /// `self` is not in any layer.
670 #[doc(alias = "ges_clip_get_layer")]
671 #[doc(alias = "get_layer")]
672 fn layer(&self) -> Option<Layer> {
673 unsafe { from_glib_full(ffi::ges_clip_get_layer(self.as_ref().to_glib_none().0)) }
674 }
675
676 /// Gets the [`supported-formats`][struct@crate::Clip#supported-formats] of the clip.
677 ///
678 /// # Returns
679 ///
680 /// The [`TrackType`][crate::TrackType]-s supported by `self`.
681 #[doc(alias = "ges_clip_get_supported_formats")]
682 #[doc(alias = "get_supported_formats")]
683 #[doc(alias = "supported-formats")]
684 fn supported_formats(&self) -> TrackType {
685 unsafe {
686 from_glib(ffi::ges_clip_get_supported_formats(
687 self.as_ref().to_glib_none().0,
688 ))
689 }
690 }
691
692 /// Convert the internal source time from the child to a timeline time.
693 /// This will take any time effects placed on the clip into account (see
694 /// [`BaseEffect`][crate::BaseEffect] for what time effects are supported, and how to
695 /// declare them in GES).
696 ///
697 /// When `internal_time` is above the [`in-point`][struct@crate::TimelineElement#in-point] of
698 /// `child`, this will return the timeline time at which the internal
699 /// content found at `internal_time` appears in the output of the timeline's
700 /// track. For example, this would let you know where in the timeline a
701 /// particular scene in a media file would appear.
702 ///
703 /// This will be done assuming the clip has an indefinite end, so the
704 /// timeline time may be beyond the end of the clip, or even breaking its
705 /// [`duration-limit`][struct@crate::Clip#duration-limit].
706 ///
707 /// If, instead, `internal_time` is below the current
708 /// [`in-point`][struct@crate::TimelineElement#in-point] of `child`, this will return what you would
709 /// need to set the [`start`][struct@crate::TimelineElement#start] of `self` to if you set the
710 /// [`in-point`][struct@crate::TimelineElement#in-point] of `child` to `internal_time` and wanted to
711 /// keep the content of `child` currently found at the current
712 /// [`start`][struct@crate::TimelineElement#start] of `self` at the same timeline position. If
713 /// this would be negative, the conversion fails. This is useful for
714 /// determining what position to use in a [`EditMode::Trim`][crate::EditMode::Trim] if you wish
715 /// to trim to a specific point in the internal content, such as a
716 /// particular scene in a media file.
717 ///
718 /// Note that whilst a clip has no time effects, this second return is
719 /// equivalent to finding the timeline time at which the content of `child`
720 /// at `internal_time` would be found in the timeline if it had indefinite
721 /// extent in both directions. However, with non-linear time effects this
722 /// second return will be more distinct.
723 ///
724 /// In either case, the returned time would be appropriate to use in
725 /// [`TimelineElementExt::edit()`][crate::prelude::TimelineElementExt::edit()] for [`EditMode::Trim`][crate::EditMode::Trim], and similar, if
726 /// you wish to use a particular internal point as a reference. For
727 /// example, you could choose to end a clip at a certain internal
728 /// 'out-point', similar to the [`in-point`][struct@crate::TimelineElement#in-point], by
729 /// translating the desired end time into the timeline coordinates, and
730 /// using this position to trim the end of a clip.
731 ///
732 /// See [`internal_time_from_timeline_time()`][Self::internal_time_from_timeline_time()], which performs the
733 /// reverse, or [`timeline_time_from_source_frame()`][Self::timeline_time_from_source_frame()] which does
734 /// the same conversion, but using frame numbers.
735 /// ## `child`
736 /// An [`active`][struct@crate::TrackElement#active] child of `self` with a
737 /// [`track`][struct@crate::TrackElement#track]
738 /// ## `internal_time`
739 /// A time in the internal time coordinates of `child`
740 ///
741 /// # Returns
742 ///
743 /// The time in the timeline coordinates corresponding to
744 /// `internal_time`, or `GST_CLOCK_TIME_NONE` if the conversion could not be
745 /// performed.
746 #[cfg(feature = "v1_18")]
747 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
748 #[doc(alias = "ges_clip_get_timeline_time_from_internal_time")]
749 #[doc(alias = "get_timeline_time_from_internal_time")]
750 fn timeline_time_from_internal_time(
751 &self,
752 child: &impl IsA<TrackElement>,
753 internal_time: impl Into<Option<gst::ClockTime>>,
754 ) -> Result<Option<gst::ClockTime>, glib::Error> {
755 unsafe {
756 let mut error = std::ptr::null_mut();
757 let ret = ffi::ges_clip_get_timeline_time_from_internal_time(
758 self.as_ref().to_glib_none().0,
759 child.as_ref().to_glib_none().0,
760 internal_time.into().into_glib(),
761 &mut error,
762 );
763 if error.is_null() {
764 Ok(from_glib(ret))
765 } else {
766 Err(from_glib_full(error))
767 }
768 }
769 }
770
771 /// Convert the source frame number to a timeline time. This acts the same
772 /// as [`timeline_time_from_internal_time()`][Self::timeline_time_from_internal_time()] using the core
773 /// children of the clip and using the frame number to specify the internal
774 /// position, rather than a timestamp.
775 ///
776 /// The returned timeline time can be used to seek or edit to a specific
777 /// frame.
778 ///
779 /// Note that you can get the frame timestamp of a particular clip asset
780 /// with [`ClipAssetExt::frame_time()`][crate::prelude::ClipAssetExt::frame_time()].
781 /// ## `frame_number`
782 /// The frame number to get the corresponding timestamp of
783 /// in the timeline coordinates
784 ///
785 /// # Returns
786 ///
787 /// The timestamp corresponding to `frame_number` in the core
788 /// children of `self`, in the timeline coordinates, or `GST_CLOCK_TIME_NONE`
789 /// if the conversion could not be performed.
790 #[cfg(feature = "v1_18")]
791 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
792 #[doc(alias = "ges_clip_get_timeline_time_from_source_frame")]
793 #[doc(alias = "get_timeline_time_from_source_frame")]
794 fn timeline_time_from_source_frame(
795 &self,
796 frame_number: FrameNumber,
797 ) -> Result<Option<gst::ClockTime>, glib::Error> {
798 unsafe {
799 let mut error = std::ptr::null_mut();
800 let ret = ffi::ges_clip_get_timeline_time_from_source_frame(
801 self.as_ref().to_glib_none().0,
802 frame_number,
803 &mut error,
804 );
805 if error.is_null() {
806 Ok(from_glib(ret))
807 } else {
808 Err(from_glib_full(error))
809 }
810 }
811 }
812
813 /// Gets the internal index of an effect in the clip. The index of effects
814 /// in a clip will run from 0 to n-1, where n is the total number of
815 /// effects. If two effects share the same [`track`][struct@crate::TrackElement#track], the
816 /// effect with the numerically lower index will be applied to the source
817 /// data **after** the other effect, i.e. output data will always flow from
818 /// a higher index effect to a lower index effect.
819 /// ## `effect`
820 /// The effect we want to get the index of
821 ///
822 /// # Returns
823 ///
824 /// The index of `effect` in `self`, or -1 if something went wrong.
825 #[doc(alias = "ges_clip_get_top_effect_index")]
826 #[doc(alias = "get_top_effect_index")]
827 fn top_effect_index(&self, effect: &impl IsA<BaseEffect>) -> i32 {
828 unsafe {
829 ffi::ges_clip_get_top_effect_index(
830 self.as_ref().to_glib_none().0,
831 effect.as_ref().to_glib_none().0,
832 )
833 }
834 }
835
836 #[doc(alias = "ges_clip_get_top_effect_position")]
837 #[doc(alias = "get_top_effect_position")]
838 fn top_effect_position(&self, effect: &impl IsA<BaseEffect>) -> i32 {
839 unsafe {
840 ffi::ges_clip_get_top_effect_position(
841 self.as_ref().to_glib_none().0,
842 effect.as_ref().to_glib_none().0,
843 )
844 }
845 }
846
847 /// Gets the [`BaseEffect`][crate::BaseEffect]-s that have been added to the clip. The
848 /// returned list is ordered by their internal index in the clip. See
849 /// [`top_effect_index()`][Self::top_effect_index()].
850 ///
851 /// # Returns
852 ///
853 /// A list of all
854 /// [`BaseEffect`][crate::BaseEffect]-s that have been added to `self`.
855 #[doc(alias = "ges_clip_get_top_effects")]
856 #[doc(alias = "get_top_effects")]
857 fn top_effects(&self) -> Vec<TrackElement> {
858 unsafe {
859 FromGlibPtrContainer::from_glib_full(ffi::ges_clip_get_top_effects(
860 self.as_ref().to_glib_none().0,
861 ))
862 }
863 }
864
865 /// See [`move_to_layer_full()`][Self::move_to_layer_full()], which also gives an error.
866 /// ## `layer`
867 /// The new layer
868 ///
869 /// # Returns
870 ///
871 /// [`true`] if `self` was successfully moved to `layer`.
872 #[doc(alias = "ges_clip_move_to_layer")]
873 fn move_to_layer(&self, layer: &impl IsA<Layer>) -> Result<(), glib::error::BoolError> {
874 unsafe {
875 glib::result_from_gboolean!(
876 ffi::ges_clip_move_to_layer(
877 self.as_ref().to_glib_none().0,
878 layer.as_ref().to_glib_none().0
879 ),
880 "Failed to move clip to specified layer"
881 )
882 }
883 }
884
885 /// Moves a clip to a new layer. If the clip already exists in a layer, it
886 /// is first removed from its current layer before being added to the new
887 /// layer.
888 /// ## `layer`
889 /// The new layer
890 ///
891 /// # Returns
892 ///
893 /// [`true`] if `self` was successfully moved to `layer`.
894 #[cfg(feature = "v1_18")]
895 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
896 #[doc(alias = "ges_clip_move_to_layer_full")]
897 fn move_to_layer_full(&self, layer: &impl IsA<Layer>) -> Result<(), glib::Error> {
898 unsafe {
899 let mut error = std::ptr::null_mut();
900 let is_ok = ffi::ges_clip_move_to_layer_full(
901 self.as_ref().to_glib_none().0,
902 layer.as_ref().to_glib_none().0,
903 &mut error,
904 );
905 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
906 if error.is_null() {
907 Ok(())
908 } else {
909 Err(from_glib_full(error))
910 }
911 }
912 }
913
914 /// Remove a top effect from the clip.
915 ///
916 /// Note, if the effect is a time effect, this may be refused if the clip
917 /// would not be able to adapt itself once the effect is removed.
918 /// ## `effect`
919 /// The top effect to remove
920 ///
921 /// # Returns
922 ///
923 /// [`true`] if `effect` was successfully added to `self` at `index`.
924 #[cfg(feature = "v1_18")]
925 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
926 #[doc(alias = "ges_clip_remove_top_effect")]
927 fn remove_top_effect(&self, effect: &impl IsA<BaseEffect>) -> Result<(), glib::Error> {
928 unsafe {
929 let mut error = std::ptr::null_mut();
930 let is_ok = ffi::ges_clip_remove_top_effect(
931 self.as_ref().to_glib_none().0,
932 effect.as_ref().to_glib_none().0,
933 &mut error,
934 );
935 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
936 if error.is_null() {
937 Ok(())
938 } else {
939 Err(from_glib_full(error))
940 }
941 }
942 }
943
944 /// Sets the [`supported-formats`][struct@crate::Clip#supported-formats] of the clip. This should normally
945 /// only be called by subclasses, which should be responsible for updating
946 /// its value, rather than the user.
947 /// ## `supportedformats`
948 /// The [`TrackType`][crate::TrackType]-s supported by `self`
949 #[doc(alias = "ges_clip_set_supported_formats")]
950 #[doc(alias = "supported-formats")]
951 fn set_supported_formats(&self, supportedformats: TrackType) {
952 unsafe {
953 ffi::ges_clip_set_supported_formats(
954 self.as_ref().to_glib_none().0,
955 supportedformats.into_glib(),
956 );
957 }
958 }
959
960 /// See [`set_top_effect_index_full()`][Self::set_top_effect_index_full()], which also gives an error.
961 /// ## `effect`
962 /// An effect within `self` to move
963 /// ## `newindex`
964 /// The index for `effect` in `self`
965 ///
966 /// # Returns
967 ///
968 /// [`true`] if `effect` was successfully moved to `newindex`.
969 #[doc(alias = "ges_clip_set_top_effect_index")]
970 fn set_top_effect_index(
971 &self,
972 effect: &impl IsA<BaseEffect>,
973 newindex: u32,
974 ) -> Result<(), glib::error::BoolError> {
975 unsafe {
976 glib::result_from_gboolean!(
977 ffi::ges_clip_set_top_effect_index(
978 self.as_ref().to_glib_none().0,
979 effect.as_ref().to_glib_none().0,
980 newindex
981 ),
982 "Failed to move effect"
983 )
984 }
985 }
986
987 /// Set the index of an effect within the clip. See
988 /// [`top_effect_index()`][Self::top_effect_index()]. The new index must be an existing
989 /// index of the clip. The effect is moved to the new index, and the other
990 /// effects may be shifted in index accordingly to otherwise maintain the
991 /// ordering.
992 /// ## `effect`
993 /// An effect within `self` to move
994 /// ## `newindex`
995 /// The index for `effect` in `self`
996 ///
997 /// # Returns
998 ///
999 /// [`true`] if `effect` was successfully moved to `newindex`.
1000 #[cfg(feature = "v1_18")]
1001 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1002 #[doc(alias = "ges_clip_set_top_effect_index_full")]
1003 fn set_top_effect_index_full(
1004 &self,
1005 effect: &impl IsA<BaseEffect>,
1006 newindex: u32,
1007 ) -> Result<(), glib::Error> {
1008 unsafe {
1009 let mut error = std::ptr::null_mut();
1010 let is_ok = ffi::ges_clip_set_top_effect_index_full(
1011 self.as_ref().to_glib_none().0,
1012 effect.as_ref().to_glib_none().0,
1013 newindex,
1014 &mut error,
1015 );
1016 debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
1017 if error.is_null() {
1018 Ok(())
1019 } else {
1020 Err(from_glib_full(error))
1021 }
1022 }
1023 }
1024
1025 #[doc(alias = "ges_clip_set_top_effect_priority")]
1026 fn set_top_effect_priority(
1027 &self,
1028 effect: &impl IsA<BaseEffect>,
1029 newpriority: u32,
1030 ) -> Result<(), glib::error::BoolError> {
1031 unsafe {
1032 glib::result_from_gboolean!(
1033 ffi::ges_clip_set_top_effect_priority(
1034 self.as_ref().to_glib_none().0,
1035 effect.as_ref().to_glib_none().0,
1036 newpriority
1037 ),
1038 "Failed to the set top effect priority"
1039 )
1040 }
1041 }
1042
1043 /// See [`split_full()`][Self::split_full()], which also gives an error.
1044 /// ## `position`
1045 /// The timeline position at which to perform the split
1046 ///
1047 /// # Returns
1048 ///
1049 /// The newly created clip resulting
1050 /// from the splitting `self`, or [`None`] if `self` can't be split.
1051 #[doc(alias = "ges_clip_split")]
1052 fn split(&self, position: u64) -> Result<Clip, glib::BoolError> {
1053 unsafe {
1054 Option::<_>::from_glib_none(ffi::ges_clip_split(
1055 self.as_ref().to_glib_none().0,
1056 position,
1057 ))
1058 .ok_or_else(|| glib::bool_error!("Failed to split clip"))
1059 }
1060 }
1061
1062 /// Splits a clip at the given timeline position into two clips. The clip
1063 /// must already have a [`layer`][struct@crate::Clip#layer].
1064 ///
1065 /// The original clip's [`duration`][struct@crate::TimelineElement#duration] is reduced such that
1066 /// its end point matches the split position. Then a new clip is created in
1067 /// the same layer, whose [`start`][struct@crate::TimelineElement#start] matches the split
1068 /// position and [`duration`][struct@crate::TimelineElement#duration] will be set such that its end
1069 /// point matches the old end point of the original clip. Thus, the two
1070 /// clips together will occupy the same positions in the timeline as the
1071 /// original clip did.
1072 ///
1073 /// The children of the new clip will be new copies of the original clip's
1074 /// children, so it will share the same sources and use the same
1075 /// operations.
1076 ///
1077 /// The new clip will also have its [`in-point`][struct@crate::TimelineElement#in-point] set so
1078 /// that any internal data will appear in the timeline at the same time.
1079 /// Thus, when the timeline is played, the playback of data should
1080 /// appear the same. This may be complicated by any additional
1081 /// [`Effect`][crate::Effect]-s that have been placed on the original clip that depend on
1082 /// the playback time or change the data consumption rate of sources. This
1083 /// method will attempt to translate these effects such that the playback
1084 /// appears the same. In such complex situations, you may get a better
1085 /// result if you place the clip in a separate sub [`Project`][crate::Project], which only
1086 /// contains this clip (and its effects), and in the original layer
1087 /// create two neighbouring [`UriClip`][crate::UriClip]-s that reference this sub-project,
1088 /// but at a different [`in-point`][struct@crate::TimelineElement#in-point].
1089 /// ## `position`
1090 /// The timeline position at which to perform the split, between
1091 /// the start and end of the clip
1092 ///
1093 /// # Returns
1094 ///
1095 /// The newly created clip resulting
1096 /// from the splitting `self`, or [`None`] if `self` can't be split.
1097 #[cfg(feature = "v1_18")]
1098 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1099 #[doc(alias = "ges_clip_split_full")]
1100 fn split_full(&self, position: u64) -> Result<Option<Clip>, glib::Error> {
1101 unsafe {
1102 let mut error = std::ptr::null_mut();
1103 let ret =
1104 ffi::ges_clip_split_full(self.as_ref().to_glib_none().0, position, &mut error);
1105 if error.is_null() {
1106 Ok(from_glib_none(ret))
1107 } else {
1108 Err(from_glib_full(error))
1109 }
1110 }
1111 }
1112
1113 #[cfg(feature = "v1_18")]
1114 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1115 #[doc(alias = "duration-limit")]
1116 fn connect_duration_limit_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1117 unsafe extern "C" fn notify_duration_limit_trampoline<P: IsA<Clip>, F: Fn(&P) + 'static>(
1118 this: *mut ffi::GESClip,
1119 _param_spec: glib::ffi::gpointer,
1120 f: glib::ffi::gpointer,
1121 ) {
1122 let f: &F = &*(f as *const F);
1123 f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1124 }
1125 unsafe {
1126 let f: Box_<F> = Box_::new(f);
1127 connect_raw(
1128 self.as_ptr() as *mut _,
1129 c"notify::duration-limit".as_ptr() as *const _,
1130 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1131 notify_duration_limit_trampoline::<Self, F> as *const (),
1132 )),
1133 Box_::into_raw(f),
1134 )
1135 }
1136 }
1137
1138 #[doc(alias = "layer")]
1139 fn connect_layer_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1140 unsafe extern "C" fn notify_layer_trampoline<P: IsA<Clip>, F: Fn(&P) + 'static>(
1141 this: *mut ffi::GESClip,
1142 _param_spec: glib::ffi::gpointer,
1143 f: glib::ffi::gpointer,
1144 ) {
1145 let f: &F = &*(f as *const F);
1146 f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1147 }
1148 unsafe {
1149 let f: Box_<F> = Box_::new(f);
1150 connect_raw(
1151 self.as_ptr() as *mut _,
1152 c"notify::layer".as_ptr() as *const _,
1153 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1154 notify_layer_trampoline::<Self, F> as *const (),
1155 )),
1156 Box_::into_raw(f),
1157 )
1158 }
1159 }
1160
1161 #[doc(alias = "supported-formats")]
1162 fn connect_supported_formats_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
1163 unsafe extern "C" fn notify_supported_formats_trampoline<
1164 P: IsA<Clip>,
1165 F: Fn(&P) + 'static,
1166 >(
1167 this: *mut ffi::GESClip,
1168 _param_spec: glib::ffi::gpointer,
1169 f: glib::ffi::gpointer,
1170 ) {
1171 let f: &F = &*(f as *const F);
1172 f(Clip::from_glib_borrow(this).unsafe_cast_ref())
1173 }
1174 unsafe {
1175 let f: Box_<F> = Box_::new(f);
1176 connect_raw(
1177 self.as_ptr() as *mut _,
1178 c"notify::supported-formats".as_ptr() as *const _,
1179 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
1180 notify_supported_formats_trampoline::<Self, F> as *const (),
1181 )),
1182 Box_::into_raw(f),
1183 )
1184 }
1185 }
1186}
1187
1188impl<O: IsA<Clip>> ClipExt for O {}