gstreamer_audio/subclass/
audio_sink.rs1use glib::{prelude::*, translate::*};
4use gst::LoggableError;
5use gst_base::subclass::prelude::*;
6
7use super::prelude::*;
8use crate::{AudioRingBufferSpec, AudioSink, ffi};
9
10pub trait AudioSinkImpl: AudioBaseSinkImpl + ObjectSubclass<Type: IsA<AudioSink>> {
11 fn close(&self) -> Result<(), LoggableError> {
13 self.parent_close()
14 }
15
16 fn delay(&self) -> u32 {
19 self.parent_delay()
20 }
21
22 fn open(&self) -> Result<(), LoggableError> {
25 self.parent_open()
26 }
27
28 fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
30 AudioSinkImplExt::parent_prepare(self, spec)
31 }
32
33 fn unprepare(&self) -> Result<(), LoggableError> {
35 self.parent_unprepare()
36 }
37
38 fn write(&self, audio_data: &[u8]) -> Result<i32, LoggableError> {
40 self.parent_write(audio_data)
41 }
42
43 fn reset(&self) {
47 self.parent_reset()
48 }
49}
50
51pub trait AudioSinkImplExt: AudioSinkImpl {
52 fn parent_close(&self) -> Result<(), LoggableError> {
53 unsafe {
54 let data = Self::type_data();
55 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
56 let f = match (*parent_class).close {
57 None => return Ok(()),
58 Some(f) => f,
59 };
60 gst::result_from_gboolean!(
61 f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
62 gst::CAT_RUST,
63 "Failed to close element using the parent function"
64 )
65 }
66 }
67
68 fn parent_delay(&self) -> u32 {
69 unsafe {
70 let data = Self::type_data();
71 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
72 let f = match (*parent_class).delay {
73 Some(f) => f,
74 None => return 0,
75 };
76 f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
77 }
78 }
79
80 fn parent_open(&self) -> Result<(), LoggableError> {
81 unsafe {
82 let data = Self::type_data();
83 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
84 let f = match (*parent_class).open {
85 Some(f) => f,
86 None => return Ok(()),
87 };
88 gst::result_from_gboolean!(
89 f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
90 gst::CAT_RUST,
91 "Failed to open element using the parent function"
92 )
93 }
94 }
95
96 fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
97 unsafe {
98 let data = Self::type_data();
99 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
100 let f = match (*parent_class).prepare {
101 Some(f) => f,
102 None => return Ok(()),
103 };
104 gst::result_from_gboolean!(
105 f(
106 self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
107 &mut spec.0
108 ),
109 gst::CAT_RUST,
110 "Failed to prepare element using the parent function"
111 )
112 }
113 }
114
115 fn parent_unprepare(&self) -> Result<(), LoggableError> {
116 unsafe {
117 let data = Self::type_data();
118 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
119 let f = match (*parent_class).unprepare {
120 Some(f) => f,
121 None => {
122 return Err(gst::loggable_error!(
123 gst::CAT_RUST,
124 "Unprepare is not implemented!"
125 ));
126 }
127 };
128 gst::result_from_gboolean!(
129 f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
130 gst::CAT_RUST,
131 "Failed to unprepare element using the parent function"
132 )
133 }
134 }
135
136 fn parent_write(&self, buffer: &[u8]) -> Result<i32, LoggableError> {
137 unsafe {
138 let data = Self::type_data();
139 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
140 let f = match (*parent_class).write {
141 Some(f) => f,
142 None => return Ok(-1),
143 };
144 let buffer_ptr = buffer.as_ptr() as glib::ffi::gpointer;
145 let ret = f(
146 self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
147 buffer_ptr,
148 buffer.len() as u32,
149 );
150 if ret > 0 {
151 Ok(ret)
152 } else {
153 Err(gst::loggable_error!(
154 gst::CAT_RUST,
155 "Failed to write using the parent function"
156 ))
157 }
158 }
159 }
160
161 fn parent_reset(&self) {
162 unsafe {
163 let data = Self::type_data();
164 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
165 if let Some(f) = (*parent_class).reset {
166 f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
167 }
168 }
169 }
170}
171
172impl<T: AudioSinkImpl> AudioSinkImplExt for T {}
173
174unsafe impl<T: AudioSinkImpl> IsSubclassable<T> for AudioSink {
175 fn class_init(klass: &mut glib::Class<Self>) {
176 Self::parent_class_init::<T>(klass);
177 let klass = klass.as_mut();
178 klass.close = Some(audiosink_close::<T>);
179 klass.delay = Some(audiosink_delay::<T>);
180 klass.open = Some(audiosink_open::<T>);
181 klass.prepare = Some(audiosink_prepare::<T>);
182 klass.unprepare = Some(audiosink_unprepare::<T>);
183 klass.write = Some(audiosink_write::<T>);
184 klass.reset = Some(audiosink_reset::<T>);
185 }
186}
187
188unsafe extern "C" fn audiosink_close<T: AudioSinkImpl>(
189 ptr: *mut ffi::GstAudioSink,
190) -> glib::ffi::gboolean {
191 unsafe {
192 let instance = &*(ptr as *mut T::Instance);
193 let imp = instance.imp();
194
195 gst::panic_to_error!(imp, false, {
196 match imp.close() {
197 Ok(()) => true,
198 Err(err) => {
199 err.log_with_imp(imp);
200 false
201 }
202 }
203 })
204 .into_glib()
205 }
206}
207
208unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 {
209 unsafe {
210 let instance = &*(ptr as *mut T::Instance);
211 let imp = instance.imp();
212
213 gst::panic_to_error!(imp, 0, { imp.delay() })
214 }
215}
216
217unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>(
218 ptr: *mut ffi::GstAudioSink,
219) -> glib::ffi::gboolean {
220 unsafe {
221 let instance = &*(ptr as *mut T::Instance);
222 let imp = instance.imp();
223
224 gst::panic_to_error!(imp, false, {
225 match imp.open() {
226 Ok(()) => true,
227 Err(err) => {
228 err.log_with_imp(imp);
229 false
230 }
231 }
232 })
233 .into_glib()
234 }
235}
236
237unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>(
238 ptr: *mut ffi::GstAudioSink,
239 spec: *mut ffi::GstAudioRingBufferSpec,
240) -> glib::ffi::gboolean {
241 unsafe {
242 let instance = &*(ptr as *mut T::Instance);
243 let imp = instance.imp();
244
245 let spec = &mut *(spec as *mut AudioRingBufferSpec);
246
247 gst::panic_to_error!(imp, false, {
248 match AudioSinkImpl::prepare(imp, spec) {
249 Ok(()) => true,
250 Err(err) => {
251 err.log_with_imp(imp);
252 false
253 }
254 }
255 })
256 .into_glib()
257 }
258}
259
260unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>(
261 ptr: *mut ffi::GstAudioSink,
262) -> glib::ffi::gboolean {
263 unsafe {
264 let instance = &*(ptr as *mut T::Instance);
265 let imp = instance.imp();
266
267 gst::panic_to_error!(imp, false, {
268 match imp.unprepare() {
269 Ok(()) => true,
270 Err(err) => {
271 err.log_with_imp(imp);
272 false
273 }
274 }
275 })
276 .into_glib()
277 }
278}
279
280unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>(
281 ptr: *mut ffi::GstAudioSink,
282 data: glib::ffi::gpointer,
283 length: u32,
284) -> i32 {
285 unsafe {
286 let instance = &*(ptr as *mut T::Instance);
287 let imp = instance.imp();
288 let data_slice = if length == 0 {
289 &[]
290 } else {
291 std::slice::from_raw_parts(data as *const u8, length as usize)
292 };
293
294 gst::panic_to_error!(imp, -1, { imp.write(data_slice).unwrap_or(-1) })
295 }
296}
297
298unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) {
299 unsafe {
300 let instance = &*(ptr as *mut T::Instance);
301 let imp = instance.imp();
302
303 gst::panic_to_error!(imp, (), {
304 imp.reset();
305 });
306 }
307}