gstreamer_editing_services/
uri_clip_asset.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2use crate::{ffi, UriClipAsset};
3use glib::{prelude::*, translate::*};
4use std::{boxed::Box as Box_, pin::Pin};
5
6impl UriClipAsset {
7    /// Creates a [`UriClipAsset`][crate::UriClipAsset] for `uri`
8    ///
9    /// Example of request of a GESUriClipAsset:
10    ///
11    /// ```text
12    /// // The request callback
13    /// static void
14    /// filesource_asset_loaded_cb (GESAsset * source, GAsyncResult * res, gpointer user_data)
15    /// {
16    ///   GError *error = NULL;
17    ///   GESUriClipAsset *filesource_asset;
18    ///
19    ///   filesource_asset = ges_uri_clip_asset_finish (res, &error);
20    ///   if (filesource_asset) {
21    ///    gst_print ("The file: %s is usable as a FileSource, it is%s an image and lasts %" GST_TIME_FORMAT,
22    ///        ges_asset_get_id (GES_ASSET (filesource_asset))
23    ///        ges_uri_clip_asset_is_image (filesource_asset) ? "" : " not",
24    ///        GST_TIME_ARGS (ges_uri_clip_asset_get_duration (filesource_asset));
25    ///   } else {
26    ///    gst_print ("The file: %s is *not* usable as a FileSource because: %s",
27    ///        ges_asset_get_id (source), error->message);
28    ///   }
29    ///
30    ///   gst_object_unref (mfs);
31    /// }
32    ///
33    /// // The request:
34    /// ges_uri_clip_asset_new (uri, (GAsyncReadyCallback) filesource_asset_loaded_cb, user_data);
35    /// ```
36    /// ## `uri`
37    /// The URI of the file for which to create a [`UriClipAsset`][crate::UriClipAsset]
38    /// ## `cancellable`
39    /// optional `GCancellable` object, [`None`] to ignore.
40    /// ## `callback`
41    /// a `GAsyncReadyCallback` to call when the initialization is finished
42    #[doc(alias = "ges_uri_clip_asset_new")]
43    #[allow(clippy::new_ret_no_self)]
44    pub fn new<P: FnOnce(Result<UriClipAsset, glib::Error>) + 'static>(
45        uri: &str,
46        cancellable: Option<&impl IsA<gio::Cancellable>>,
47        callback: P,
48    ) {
49        assert_initialized_main_thread!();
50
51        let main_context = glib::MainContext::ref_thread_default();
52        let is_main_context_owner = main_context.is_owner();
53        let has_acquired_main_context = (!is_main_context_owner)
54            .then(|| main_context.acquire().ok())
55            .flatten();
56        assert!(
57            is_main_context_owner || has_acquired_main_context.is_some(),
58            "Async operations only allowed if the thread is owning the MainContext"
59        );
60
61        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
62            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
63        unsafe extern "C" fn new_trampoline<
64            P: FnOnce(Result<UriClipAsset, glib::Error>) + 'static,
65        >(
66            _source_object: *mut glib::gobject_ffi::GObject,
67            res: *mut gio::ffi::GAsyncResult,
68            user_data: glib::ffi::gpointer,
69        ) {
70            let mut error = std::ptr::null_mut();
71            let ret = {
72                #[cfg(feature = "v1_16")]
73                {
74                    ffi::ges_uri_clip_asset_finish(res, &mut error)
75                }
76                #[cfg(not(feature = "v1_16"))]
77                {
78                    ffi::ges_asset_request_finish(res, &mut error) as *mut ffi::GESUriClipAsset
79                }
80            };
81            let result = if error.is_null() {
82                Ok(from_glib_full(ret))
83            } else {
84                Err(from_glib_full(error))
85            };
86            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
87                Box_::from_raw(user_data as *mut _);
88            let callback: P = callback.into_inner();
89            callback(result);
90        }
91        let callback = new_trampoline::<P>;
92        unsafe {
93            ffi::ges_uri_clip_asset_new(
94                uri.to_glib_none().0,
95                cancellable.map(|p| p.as_ref()).to_glib_none().0,
96                Some(callback),
97                Box_::into_raw(user_data) as *mut _,
98            );
99        }
100    }
101
102    pub fn new_future(
103        uri: &str,
104    ) -> Pin<Box_<dyn std::future::Future<Output = Result<UriClipAsset, glib::Error>> + 'static>>
105    {
106        skip_assert_initialized!();
107        let uri = String::from(uri);
108        Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
109            Self::new(&uri, Some(cancellable), move |res| {
110                send.resolve(res);
111            });
112        }))
113    }
114}