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: AudioVisualizerImplExt + ElementImpl {
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
31mod sealed {
32 pub trait Sealed {}
33 impl<T: super::AudioVisualizerImplExt> Sealed for T {}
34}
35
36pub trait AudioVisualizerImplExt: sealed::Sealed + ObjectSubclass {
37 fn parent_setup(&self, token: &AudioVisualizerSetupToken) -> Result<(), LoggableError> {
38 assert_eq!(
39 self.obj().as_ptr() as *mut ffi::GstAudioVisualizer,
40 token.0.as_ptr()
41 );
42
43 unsafe {
44 let data = Self::type_data();
45 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
46 (*parent_class)
47 .setup
48 .map(|f| {
49 result_from_gboolean!(
50 f(self
51 .obj()
52 .unsafe_cast_ref::<AudioVisualizer>()
53 .to_glib_none()
54 .0,),
55 CAT_RUST,
56 "Parent function `setup` failed",
57 )
58 })
59 .unwrap_or(Ok(()))
60 }
61 }
62
63 fn parent_render(
64 &self,
65 audio_buffer: &gst::BufferRef,
66 video_frame: &mut gst_video::VideoFrameRef<&mut gst::BufferRef>,
67 ) -> Result<(), LoggableError> {
68 unsafe {
69 let data = Self::type_data();
70 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
71 (*parent_class)
72 .render
73 .map(|f| {
74 result_from_gboolean!(
75 f(
76 self.obj()
77 .unsafe_cast_ref::<AudioVisualizer>()
78 .to_glib_none()
79 .0,
80 audio_buffer.as_mut_ptr(),
81 video_frame.as_mut_ptr(),
82 ),
83 CAT_RUST,
84 "Parent function `render` failed",
85 )
86 })
87 .unwrap_or(Ok(()))
88 }
89 }
90
91 fn parent_decide_allocation(
92 &self,
93 query: &mut gst::query::Allocation,
94 ) -> Result<(), gst::LoggableError> {
95 unsafe {
96 let data = Self::type_data();
97 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioVisualizerClass;
98 (*parent_class)
99 .decide_allocation
100 .map(|f| {
101 gst::result_from_gboolean!(
102 f(
103 self.obj()
104 .unsafe_cast_ref::<AudioVisualizer>()
105 .to_glib_none()
106 .0,
107 query.as_mut_ptr(),
108 ),
109 gst::CAT_RUST,
110 "Parent function `decide_allocation` failed",
111 )
112 })
113 .unwrap_or(Ok(()))
114 }
115 }
116}
117
118impl<T: AudioVisualizerImpl> AudioVisualizerImplExt for T {}
119
120unsafe impl<T: AudioVisualizerImpl> IsSubclassable<T> for AudioVisualizer {
121 fn class_init(klass: &mut glib::Class<Self>) {
122 Self::parent_class_init::<T>(klass);
123 let klass = klass.as_mut();
124 klass.setup = Some(audio_visualizer_setup::<T>);
125 klass.render = Some(audio_visualizer_render::<T>);
126 klass.decide_allocation = Some(audio_visualizer_decide_allocation::<T>);
127 }
128}
129
130unsafe extern "C" fn audio_visualizer_setup<T: AudioVisualizerImpl>(
131 ptr: *mut ffi::GstAudioVisualizer,
132) -> gst::ffi::GstFlowReturn {
133 let instance = &*(ptr as *mut T::Instance);
134 let imp = instance.imp();
135
136 gst::panic_to_error!(imp, false, {
137 let instance = imp.obj();
138 let instance = instance.unsafe_cast_ref::<AudioVisualizer>();
139 let token = AudioVisualizerSetupToken(instance);
140
141 match imp.setup(&token) {
142 Ok(()) => true,
143 Err(err) => {
144 err.log_with_imp(imp);
145 false
146 }
147 }
148 })
149 .into_glib()
150}
151
152unsafe extern "C" fn audio_visualizer_render<T: AudioVisualizerImpl>(
153 ptr: *mut ffi::GstAudioVisualizer,
154 audio_buffer: *mut gst::ffi::GstBuffer,
155 video_frame: *mut gst_video::ffi::GstVideoFrame,
156) -> gst::ffi::GstFlowReturn {
157 let instance = &*(ptr as *mut T::Instance);
158 let imp = instance.imp();
159 let buffer = gst::BufferRef::from_ptr(audio_buffer);
160
161 gst::panic_to_error!(imp, false, {
162 match imp.render(
163 buffer,
164 &mut gst_video::VideoFrameRef::from_glib_borrow_mut(video_frame),
165 ) {
166 Ok(()) => true,
167 Err(err) => {
168 err.log_with_imp(imp);
169 false
170 }
171 }
172 })
173 .into_glib()
174}
175
176unsafe extern "C" fn audio_visualizer_decide_allocation<T: AudioVisualizerImpl>(
177 ptr: *mut ffi::GstAudioVisualizer,
178 query: *mut gst::ffi::GstQuery,
179) -> gst::ffi::GstFlowReturn {
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}