gstreamer_pbutils/subclass/
audio_visualizer.rs
1use 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}