gtk4/subclass/
media_stream.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! Traits intended for subclassing [`MediaStream`].
5
6use gdk::Paintable;
7use glib::translate::*;
8
9use crate::{ffi, prelude::*, subclass::prelude::*, MediaStream};
10
11pub trait MediaStreamImpl:
12    ObjectImpl + ObjectSubclass<Type: IsA<MediaStream> + IsA<Paintable>>
13{
14    /// Pauses playback of the stream.
15    ///
16    /// If the stream is not playing, do nothing.
17    fn pause(&self) {
18        self.parent_pause()
19    }
20
21    fn play(&self) -> bool {
22        self.parent_play()
23    }
24
25    /// Called by users to attach the media stream to a [`gdk::Surface`][crate::gdk::Surface] they manage.
26    ///
27    /// The stream can then access the resources of @surface for its
28    /// rendering purposes. In particular, media streams might want to
29    /// create a [`gdk::GLContext`][crate::gdk::GLContext] or sync to the [`gdk::FrameClock`][crate::gdk::FrameClock].
30    ///
31    /// Whoever calls this function is responsible for calling
32    /// [`MediaStreamExt::unrealize()`][crate::prelude::MediaStreamExt::unrealize()] before either the stream
33    /// or @surface get destroyed.
34    ///
35    /// Multiple calls to this function may happen from different
36    /// users of the video, even with the same @surface. Each of these
37    /// calls must be followed by its own call to
38    /// [`MediaStreamExt::unrealize()`][crate::prelude::MediaStreamExt::unrealize()].
39    ///
40    /// It is not required to call this function to make a media stream work.
41    /// ## `surface`
42    /// a [`gdk::Surface`][crate::gdk::Surface]
43    fn realize(&self, surface: gdk::Surface) {
44        self.parent_realize(surface)
45    }
46
47    /// Start a seek operation on @self to @timestamp.
48    ///
49    /// If @timestamp is out of range, it will be clamped.
50    ///
51    /// Seek operations may not finish instantly. While a
52    /// seek operation is in process, the [`seeking`][struct@crate::MediaStream#seeking]
53    /// property will be set.
54    ///
55    /// When calling gtk_media_stream_seek() during an
56    /// ongoing seek operation, the new seek will override
57    /// any pending seek.
58    /// ## `timestamp`
59    /// timestamp to seek to.
60    fn seek(&self, timestamp: i64) {
61        self.parent_seek(timestamp)
62    }
63
64    /// Undoes a previous call to gtk_media_stream_realize().
65    ///
66    /// This causes the stream to release all resources it had
67    /// allocated from @surface.
68    /// ## `surface`
69    /// the [`gdk::Surface`][crate::gdk::Surface] the stream was realized with
70    fn unrealize(&self, surface: gdk::Surface) {
71        self.parent_unrealize(surface)
72    }
73
74    fn update_audio(&self, muted: bool, volume: f64) {
75        self.parent_update_audio(muted, volume)
76    }
77}
78
79pub trait MediaStreamImplExt: MediaStreamImpl {
80    fn parent_pause(&self) {
81        unsafe {
82            let data = Self::type_data();
83            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
84            let f = (*parent_class)
85                .pause
86                .expect("No parent class impl for \"pause\"");
87            f(self.obj().unsafe_cast_ref::<MediaStream>().to_glib_none().0)
88        }
89    }
90
91    // Returns true if successfully started playing
92    fn parent_play(&self) -> bool {
93        unsafe {
94            let data = Self::type_data();
95            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
96            if let Some(f) = (*parent_class).play {
97                return from_glib(f(self
98                    .obj()
99                    .unsafe_cast_ref::<MediaStream>()
100                    .to_glib_none()
101                    .0));
102            }
103            false
104        }
105    }
106
107    fn parent_realize(&self, surface: gdk::Surface) {
108        unsafe {
109            let data = Self::type_data();
110            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
111            let f = (*parent_class)
112                .realize
113                .expect("No parent class impl for \"realize\"");
114            f(
115                self.obj().unsafe_cast_ref::<MediaStream>().to_glib_none().0,
116                surface.to_glib_none().0,
117            )
118        }
119    }
120
121    fn parent_seek(&self, timestamp: i64) {
122        unsafe {
123            let data = Self::type_data();
124            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
125            let f = (*parent_class)
126                .seek
127                .expect("No parent class impl for \"realize\"");
128            f(
129                self.obj().unsafe_cast_ref::<MediaStream>().to_glib_none().0,
130                timestamp,
131            )
132        }
133    }
134
135    fn parent_unrealize(&self, surface: gdk::Surface) {
136        unsafe {
137            let data = Self::type_data();
138            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
139            let f = (*parent_class)
140                .unrealize
141                .expect("No parent class impl for \"unrealize\"");
142            f(
143                self.obj().unsafe_cast_ref::<MediaStream>().to_glib_none().0,
144                surface.to_glib_none().0,
145            )
146        }
147    }
148
149    fn parent_update_audio(&self, muted: bool, volume: f64) {
150        unsafe {
151            let data = Self::type_data();
152            let parent_class = data.as_ref().parent_class() as *mut ffi::GtkMediaStreamClass;
153            let f = (*parent_class)
154                .update_audio
155                .expect("No parent class impl for \"update_audio\"");
156            f(
157                self.obj().unsafe_cast_ref::<MediaStream>().to_glib_none().0,
158                muted.into_glib(),
159                volume,
160            )
161        }
162    }
163}
164
165impl<T: MediaStreamImpl> MediaStreamImplExt for T {}
166
167unsafe impl<T: MediaStreamImpl> IsSubclassable<T> for MediaStream {
168    fn class_init(class: &mut glib::Class<Self>) {
169        Self::parent_class_init::<T>(class);
170
171        assert_initialized_main_thread!();
172
173        let klass = class.as_mut();
174        klass.pause = Some(media_stream_pause::<T>);
175        klass.play = Some(media_stream_play::<T>);
176        klass.realize = Some(media_stream_realize::<T>);
177        klass.seek = Some(media_stream_seek::<T>);
178        klass.unrealize = Some(media_stream_unrealize::<T>);
179        klass.update_audio = Some(media_stream_update_audio::<T>);
180    }
181}
182
183unsafe extern "C" fn media_stream_pause<T: MediaStreamImpl>(ptr: *mut ffi::GtkMediaStream) {
184    let instance = &*(ptr as *mut T::Instance);
185    let imp = instance.imp();
186
187    imp.pause()
188}
189
190unsafe extern "C" fn media_stream_play<T: MediaStreamImpl>(
191    ptr: *mut ffi::GtkMediaStream,
192) -> glib::ffi::gboolean {
193    let instance = &*(ptr as *mut T::Instance);
194    let imp = instance.imp();
195
196    imp.play().into_glib()
197}
198
199unsafe extern "C" fn media_stream_realize<T: MediaStreamImpl>(
200    ptr: *mut ffi::GtkMediaStream,
201    surface: *mut gdk::ffi::GdkSurface,
202) {
203    let instance = &*(ptr as *mut T::Instance);
204    let imp = instance.imp();
205
206    imp.realize(from_glib_none(surface))
207}
208
209unsafe extern "C" fn media_stream_seek<T: MediaStreamImpl>(
210    ptr: *mut ffi::GtkMediaStream,
211    timestamp: i64,
212) {
213    let instance = &*(ptr as *mut T::Instance);
214    let imp = instance.imp();
215
216    imp.seek(timestamp)
217}
218
219unsafe extern "C" fn media_stream_unrealize<T: MediaStreamImpl>(
220    ptr: *mut ffi::GtkMediaStream,
221    surface: *mut gdk::ffi::GdkSurface,
222) {
223    let instance = &*(ptr as *mut T::Instance);
224    let imp = instance.imp();
225
226    imp.unrealize(from_glib_none(surface))
227}
228
229unsafe extern "C" fn media_stream_update_audio<T: MediaStreamImpl>(
230    ptr: *mut ffi::GtkMediaStream,
231    muted: glib::ffi::gboolean,
232    volume: f64,
233) {
234    let instance = &*(ptr as *mut T::Instance);
235    let imp = instance.imp();
236
237    imp.update_audio(from_glib(muted), volume)
238}