gstreamer_pbutils/subclass/
audio_visualizer.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, translate::*};
4use gst::{result_from_gboolean, subclass::prelude::*, LoggableError, CAT_RUST};
5
6use crate::{ffi, AudioVisualizer};
7
8pub struct AudioVisualizerSetupToken<'a>(pub(crate) &'a AudioVisualizer);
9
10pub trait AudioVisualizerImpl: ElementImpl + ObjectSubclass<Type: IsA<AudioVisualizer>> {
11    fn setup(&self, token: &AudioVisualizerSetupToken) -> Result<(), LoggableError> {
12        self.parent_setup(token)
13    }
14
15    fn render(
16        &self,
17        audio_buffer: &gst::BufferRef,
18        video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
19    ) -> Result<(), LoggableError> {
20        self.parent_render(audio_buffer, video_frame)
21    }
22
23    fn decide_allocation(
24        &self,
25        query: &mut gst::query::Allocation,
26    ) -> Result<(), gst::LoggableError> {
27        self.parent_decide_allocation(query)
28    }
29}
30
31pub trait AudioVisualizerImplExt: AudioVisualizerImpl {
32    fn parent_setup(&self, token: &AudioVisualizerSetupToken) -> Result<(), LoggableError> {
33        assert_eq!(
34            self.obj().as_ptr() as *mut ffi::GstAudioVisualizer,
35            token.0.as_ptr()
36        );
37
38        unsafe {
39            let data = Self::type_data();
40            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
41            (*parent_class)
42                .setup
43                .map(|f| {
44                    result_from_gboolean!(
45                        f(self
46                            .obj()
47                            .unsafe_cast_ref::<AudioVisualizer>()
48                            .to_glib_none()
49                            .0,),
50                        CAT_RUST,
51                        "Parent function `setup` failed",
52                    )
53                })
54                .unwrap_or(Ok(()))
55        }
56    }
57
58    fn parent_render(
59        &self,
60        audio_buffer: &gst::BufferRef,
61        video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
62    ) -> Result<(), LoggableError> {
63        unsafe {
64            let data = Self::type_data();
65            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
66            (*parent_class)
67                .render
68                .map(|f| {
69                    result_from_gboolean!(
70                        f(
71                            self.obj()
72                                .unsafe_cast_ref::<AudioVisualizer>()
73                                .to_glib_none()
74                                .0,
75                            audio_buffer.as_mut_ptr(),
76                            video_frame.as_mut_ptr(),
77                        ),
78                        CAT_RUST,
79                        "Parent function `render` failed",
80                    )
81                })
82                .unwrap_or(Ok(()))
83        }
84    }
85
86    fn parent_decide_allocation(
87        &self,
88        query: &mut gst::query::Allocation,
89    ) -> Result<(), gst::LoggableError> {
90        unsafe {
91            let data = Self::type_data();
92            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
93            (*parent_class)
94                .decide_allocation
95                .map(|f| {
96                    gst::result_from_gboolean!(
97                        f(
98                            self.obj()
99                                .unsafe_cast_ref::<AudioVisualizer>()
100                                .to_glib_none()
101                                .0,
102                            query.as_mut_ptr(),
103                        ),
104                        gst::CAT_RUST,
105                        "Parent function `decide_allocation` failed",
106                    )
107                })
108                .unwrap_or(Ok(()))
109        }
110    }
111}
112
113impl<T: AudioVisualizerImpl> AudioVisualizerImplExt for T {}
114
115unsafe impl<T: AudioVisualizerImpl> IsSubclassable<T> for AudioVisualizer {
116    fn class_init(klass: &mut glib::Class<Self>) {
117        Self::parent_class_init::<T>(klass);
118        let klass = klass.as_mut();
119        klass.setup = Some(audio_visualizer_setup::<T>);
120        klass.render = Some(audio_visualizer_render::<T>);
121        klass.decide_allocation = Some(audio_visualizer_decide_allocation::<T>);
122    }
123}
124
125unsafe extern "C" fn audio_visualizer_setup<T: AudioVisualizerImpl>(
126    ptr: *mut ffi::GstAudioVisualizer,
127) -> gst::ffi::GstFlowReturn {
128    let instance = &*(ptr as *mut T::Instance);
129    let imp = instance.imp();
130
131    gst::panic_to_error!(imp, false, {
132        let instance = imp.obj();
133        let instance = instance.unsafe_cast_ref::<AudioVisualizer>();
134        let token = AudioVisualizerSetupToken(instance);
135
136        match imp.setup(&token) {
137            Ok(()) => true,
138            Err(err) => {
139                err.log_with_imp(imp);
140                false
141            }
142        }
143    })
144    .into_glib()
145}
146
147unsafe extern "C" fn audio_visualizer_render<T: AudioVisualizerImpl>(
148    ptr: *mut ffi::GstAudioVisualizer,
149    audio_buffer: *mut gst::ffi::GstBuffer,
150    video_frame: *mut gst_video::ffi::GstVideoFrame,
151) -> gst::ffi::GstFlowReturn {
152    let instance = &*(ptr as *mut T::Instance);
153    let imp = instance.imp();
154    let buffer = gst::BufferRef::from_ptr(audio_buffer);
155
156    gst::panic_to_error!(imp, false, {
157        match imp.render(
158            buffer,
159            &mut gst_video::VideoFrameRef::from_glib_borrow_mut(video_frame),
160        ) {
161            Ok(()) => true,
162            Err(err) => {
163                err.log_with_imp(imp);
164                false
165            }
166        }
167    })
168    .into_glib()
169}
170
171unsafe extern "C" fn audio_visualizer_decide_allocation<T: AudioVisualizerImpl>(
172    ptr: *mut ffi::GstAudioVisualizer,
173    query: *mut gst::ffi::GstQuery,
174) -> gst::ffi::GstFlowReturn {
175    let instance = &*(ptr as *mut T::Instance);
176    let imp = instance.imp();
177    let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
178        gst::QueryViewMut::Allocation(allocation) => allocation,
179        _ => unreachable!(),
180    };
181
182    gst::panic_to_error!(imp, false, {
183        match imp.decide_allocation(query) {
184            Ok(()) => true,
185            Err(err) => {
186                err.log_with_imp(imp);
187                false
188            }
189        }
190    })
191    .into_glib()
192}