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