gstreamer_pbutils/subclass/
audio_visualizer.rs1use glib::{prelude::*, translate::*};
4use gst::{CAT_RUST, LoggableError, result_from_gboolean, subclass::prelude::*};
5
6use crate::{AudioVisualizer, ffi};
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 unsafe {
129 let instance = &*(ptr as *mut T::Instance);
130 let imp = instance.imp();
131
132 gst::panic_to_error!(imp, false, {
133 let instance = imp.obj();
134 let instance = instance.unsafe_cast_ref::<AudioVisualizer>();
135 let token = AudioVisualizerSetupToken(instance);
136
137 match imp.setup(&token) {
138 Ok(()) => true,
139 Err(err) => {
140 err.log_with_imp(imp);
141 false
142 }
143 }
144 })
145 .into_glib()
146 }
147}
148
149unsafe extern "C" fn audio_visualizer_render<T: AudioVisualizerImpl>(
150 ptr: *mut ffi::GstAudioVisualizer,
151 audio_buffer: *mut gst::ffi::GstBuffer,
152 video_frame: *mut gst_video::ffi::GstVideoFrame,
153) -> gst::ffi::GstFlowReturn {
154 unsafe {
155 let instance = &*(ptr as *mut T::Instance);
156 let imp = instance.imp();
157 let buffer = gst::BufferRef::from_ptr(audio_buffer);
158
159 gst::panic_to_error!(imp, false, {
160 match imp.render(
161 buffer,
162 &mut gst_video::VideoFrameRef::from_glib_borrow_mut(video_frame),
163 ) {
164 Ok(()) => true,
165 Err(err) => {
166 err.log_with_imp(imp);
167 false
168 }
169 }
170 })
171 .into_glib()
172 }
173}
174
175unsafe extern "C" fn audio_visualizer_decide_allocation<T: AudioVisualizerImpl>(
176 ptr: *mut ffi::GstAudioVisualizer,
177 query: *mut gst::ffi::GstQuery,
178) -> gst::ffi::GstFlowReturn {
179 unsafe {
180 let instance = &*(ptr as *mut T::Instance);
181 let imp = instance.imp();
182 let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
183 gst::QueryViewMut::Allocation(allocation) => allocation,
184 _ => unreachable!(),
185 };
186
187 gst::panic_to_error!(imp, false, {
188 match imp.decide_allocation(query) {
189 Ok(()) => true,
190 Err(err) => {
191 err.log_with_imp(imp);
192 false
193 }
194 }
195 })
196 .into_glib()
197 }
198}