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