gstreamer_player/
player.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{boxed::Box as Box_, mem::transmute};
4
5use glib::{
6    object::ObjectType,
7    signal::{connect_raw, SignalHandlerId},
8    translate::*,
9};
10
11use crate::{ffi, Player};
12
13impl Player {
14    /// Get a copy of the current configuration of the player. This configuration
15    /// can either be modified and used for the [`set_config()`][Self::set_config()] call
16    /// or it must be freed after usage.
17    ///
18    /// # Returns
19    ///
20    /// a copy of the current configuration of `self`. Use
21    /// `gst_structure_free()` after usage or [`set_config()`][Self::set_config()].
22    #[doc(alias = "get_config")]
23    #[doc(alias = "gst_player_get_config")]
24    pub fn config(&self) -> crate::PlayerConfig {
25        unsafe { from_glib_full(ffi::gst_player_get_config(self.to_glib_none().0)) }
26    }
27
28    /// Set the configuration of the player. If the player is already configured, and
29    /// the configuration haven't change, this function will return [`true`]. If the
30    /// player is not in the GST_PLAYER_STATE_STOPPED, this method will return [`false`]
31    /// and active configuration will remain.
32    ///
33    /// `config` is a [`gst::Structure`][crate::gst::Structure] that contains the configuration parameters for
34    /// the player.
35    ///
36    /// This function takes ownership of `config`.
37    /// ## `config`
38    /// a [`gst::Structure`][crate::gst::Structure]
39    ///
40    /// # Returns
41    ///
42    /// [`true`] when the configuration could be set.
43    #[doc(alias = "gst_player_set_config")]
44    pub fn set_config(&self, config: crate::PlayerConfig) -> Result<(), glib::error::BoolError> {
45        unsafe {
46            glib::result_from_gboolean!(
47                ffi::gst_player_set_config(self.to_glib_none().0, config.into_glib_ptr()),
48                "Failed to set config",
49            )
50        }
51    }
52
53    pub fn connect_duration_changed<F: Fn(&Player, Option<gst::ClockTime>) + Send + 'static>(
54        &self,
55        f: F,
56    ) -> SignalHandlerId {
57        #[allow(clippy::cast_ptr_alignment)]
58        unsafe {
59            let f: Box_<F> = Box_::new(f);
60            connect_raw(
61                self.as_ptr() as *mut _,
62                b"duration-changed\0".as_ptr() as *const _,
63                Some(transmute::<*const (), unsafe extern "C" fn()>(
64                    duration_changed_trampoline::<F> as *const (),
65                )),
66                Box_::into_raw(f),
67            )
68        }
69    }
70
71    pub fn connect_position_updated<F: Fn(&Player, Option<gst::ClockTime>) + Send + 'static>(
72        &self,
73        f: F,
74    ) -> SignalHandlerId {
75        #[allow(clippy::cast_ptr_alignment)]
76        unsafe {
77            let f: Box_<F> = Box_::new(f);
78            connect_raw(
79                self.as_ptr() as *mut _,
80                b"position-updated\0".as_ptr() as *const _,
81                Some(transmute::<*const (), unsafe extern "C" fn()>(
82                    position_updated_trampoline::<F> as *const (),
83                )),
84                Box_::into_raw(f),
85            )
86        }
87    }
88
89    pub fn connect_seek_done<F: Fn(&Player, gst::ClockTime) + Send + 'static>(
90        &self,
91        f: F,
92    ) -> SignalHandlerId {
93        #[allow(clippy::cast_ptr_alignment)]
94        unsafe {
95            let f: Box_<F> = Box_::new(f);
96            connect_raw(
97                self.as_ptr() as *mut _,
98                b"seek-done\0".as_ptr() as *const _,
99                Some(transmute::<*const (), unsafe extern "C" fn()>(
100                    seek_done_trampoline::<F> as *const (),
101                )),
102                Box_::into_raw(f),
103            )
104        }
105    }
106
107    /// Get a snapshot of the currently selected video stream, if any. The format can be
108    /// selected with `format` and optional configuration is possible with `config`
109    /// Currently supported settings are:
110    /// - width, height of type G_TYPE_INT
111    /// - pixel-aspect-ratio of type GST_TYPE_FRACTION
112    ///  Except for GST_PLAYER_THUMBNAIL_RAW_NATIVE format, if no config is set, pixel-aspect-ratio would be 1/1
113    /// ## `format`
114    /// output format of the video snapshot
115    /// ## `config`
116    /// Additional configuration
117    ///
118    /// # Returns
119    ///
120    /// Current video snapshot sample or [`None`] on failure
121    #[doc(alias = "gst_player_get_video_snapshot")]
122    #[doc(alias = "get_video_snapshot")]
123    pub fn video_snapshot(
124        &self,
125        format: crate::PlayerSnapshotFormat,
126        config: Option<&gst::StructureRef>,
127    ) -> Option<gst::Sample> {
128        unsafe {
129            from_glib_full(ffi::gst_player_get_video_snapshot(
130                self.to_glib_none().0,
131                format.into_glib(),
132                mut_override(config.map(|c| c.as_ptr()).unwrap_or(std::ptr::null())),
133            ))
134        }
135    }
136}
137
138impl Default for Player {
139    fn default() -> Self {
140        Self::new(
141            None::<crate::PlayerVideoRenderer>,
142            None::<crate::PlayerSignalDispatcher>,
143        )
144    }
145}
146
147unsafe extern "C" fn duration_changed_trampoline<
148    F: Fn(&Player, Option<gst::ClockTime>) + Send + 'static,
149>(
150    this: *mut ffi::GstPlayer,
151    object: u64,
152    f: glib::ffi::gpointer,
153) {
154    let f: &F = &*(f as *const F);
155    f(&from_glib_borrow(this), FromGlib::from_glib(object))
156}
157
158unsafe extern "C" fn position_updated_trampoline<
159    F: Fn(&Player, Option<gst::ClockTime>) + Send + 'static,
160>(
161    this: *mut ffi::GstPlayer,
162    object: u64,
163    f: glib::ffi::gpointer,
164) {
165    let f: &F = &*(f as *const F);
166    f(&from_glib_borrow(this), FromGlib::from_glib(object))
167}
168
169unsafe extern "C" fn seek_done_trampoline<F: Fn(&Player, gst::ClockTime) + Send + 'static>(
170    this: *mut ffi::GstPlayer,
171    object: u64,
172    f: glib::ffi::gpointer,
173) {
174    let f: &F = &*(f as *const F);
175    f(
176        &from_glib_borrow(this),
177        try_from_glib(object).expect("undefined seek position"),
178    )
179}