gstreamer_audio/subclass/
audio_sink.rs1use glib::{prelude::*, translate::*};
4use gst::LoggableError;
5use gst_base::subclass::prelude::*;
6
7use super::prelude::*;
8use crate::{ffi, AudioRingBufferSpec, AudioSink};
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 let instance = &*(ptr as *mut T::Instance);
181 let imp = instance.imp();
182
183 gst::panic_to_error!(imp, false, {
184 match imp.close() {
185 Ok(()) => true,
186 Err(err) => {
187 err.log_with_imp(imp);
188 false
189 }
190 }
191 })
192 .into_glib()
193}
194
195unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 {
196 let instance = &*(ptr as *mut T::Instance);
197 let imp = instance.imp();
198
199 gst::panic_to_error!(imp, 0, { imp.delay() })
200}
201
202unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>(
203 ptr: *mut ffi::GstAudioSink,
204) -> glib::ffi::gboolean {
205 let instance = &*(ptr as *mut T::Instance);
206 let imp = instance.imp();
207
208 gst::panic_to_error!(imp, false, {
209 match imp.open() {
210 Ok(()) => true,
211 Err(err) => {
212 err.log_with_imp(imp);
213 false
214 }
215 }
216 })
217 .into_glib()
218}
219
220unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>(
221 ptr: *mut ffi::GstAudioSink,
222 spec: *mut ffi::GstAudioRingBufferSpec,
223) -> glib::ffi::gboolean {
224 let instance = &*(ptr as *mut T::Instance);
225 let imp = instance.imp();
226
227 let spec = &mut *(spec as *mut AudioRingBufferSpec);
228
229 gst::panic_to_error!(imp, false, {
230 match AudioSinkImpl::prepare(imp, spec) {
231 Ok(()) => true,
232 Err(err) => {
233 err.log_with_imp(imp);
234 false
235 }
236 }
237 })
238 .into_glib()
239}
240
241unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>(
242 ptr: *mut ffi::GstAudioSink,
243) -> glib::ffi::gboolean {
244 let instance = &*(ptr as *mut T::Instance);
245 let imp = instance.imp();
246
247 gst::panic_to_error!(imp, false, {
248 match imp.unprepare() {
249 Ok(()) => true,
250 Err(err) => {
251 err.log_with_imp(imp);
252 false
253 }
254 }
255 })
256 .into_glib()
257}
258
259unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>(
260 ptr: *mut ffi::GstAudioSink,
261 data: glib::ffi::gpointer,
262 length: u32,
263) -> i32 {
264 let instance = &*(ptr as *mut T::Instance);
265 let imp = instance.imp();
266 let data_slice = if length == 0 {
267 &[]
268 } else {
269 std::slice::from_raw_parts(data as *const u8, length as usize)
270 };
271
272 gst::panic_to_error!(imp, -1, { imp.write(data_slice).unwrap_or(-1) })
273}
274
275unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) {
276 let instance = &*(ptr as *mut T::Instance);
277 let imp = instance.imp();
278
279 gst::panic_to_error!(imp, (), {
280 imp.reset();
281 });
282}