Skip to main content

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::{UriClipAsset, ffi};
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            unsafe {
71                let mut error = std::ptr::null_mut();
72                let ret = {
73                    #[cfg(feature = "v1_16")]
74                    {
75                        ffi::ges_uri_clip_asset_finish(res, &mut error)
76                    }
77                    #[cfg(not(feature = "v1_16"))]
78                    {
79                        ffi::ges_asset_request_finish(res, &mut error) as *mut ffi::GESUriClipAsset
80                    }
81                };
82                let result = if error.is_null() {
83                    Ok(from_glib_full(ret))
84                } else {
85                    Err(from_glib_full(error))
86                };
87                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
88                    Box_::from_raw(user_data as *mut _);
89                let callback: P = callback.into_inner();
90                callback(result);
91            }
92        }
93        let callback = new_trampoline::<P>;
94        unsafe {
95            ffi::ges_uri_clip_asset_new(
96                uri.to_glib_none().0,
97                cancellable.map(|p| p.as_ref()).to_glib_none().0,
98                Some(callback),
99                Box_::into_raw(user_data) as *mut _,
100            );
101        }
102    }
103
104    pub fn new_future(
105        uri: &str,
106    ) -> Pin<Box_<dyn std::future::Future<Output = Result<UriClipAsset, glib::Error>> + 'static>>
107    {
108        skip_assert_initialized!();
109        let uri = String::from(uri);
110        Box_::pin(gio::GioFuture::new(&(), move |_obj, cancellable, send| {
111            Self::new(&uri, Some(cancellable), move |res| {
112                send.resolve(res);
113            });
114        }))
115    }
116}