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: 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 let instance = &*(ptr as *mut T::Instance);
192 let imp = instance.imp();
193
194 gst::panic_to_error!(imp, false, {
195 match imp.close() {
196 Ok(()) => true,
197 Err(err) => {
198 err.log_with_imp(imp);
199 false
200 }
201 }
202 })
203 .into_glib()
204}
205
206unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 {
207 let instance = &*(ptr as *mut T::Instance);
208 let imp = instance.imp();
209
210 gst::panic_to_error!(imp, 0, { imp.delay() })
211}
212
213unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>(
214 ptr: *mut ffi::GstAudioSink,
215) -> glib::ffi::gboolean {
216 let instance = &*(ptr as *mut T::Instance);
217 let imp = instance.imp();
218
219 gst::panic_to_error!(imp, false, {
220 match imp.open() {
221 Ok(()) => true,
222 Err(err) => {
223 err.log_with_imp(imp);
224 false
225 }
226 }
227 })
228 .into_glib()
229}
230
231unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>(
232 ptr: *mut ffi::GstAudioSink,
233 spec: *mut ffi::GstAudioRingBufferSpec,
234) -> glib::ffi::gboolean {
235 let instance = &*(ptr as *mut T::Instance);
236 let imp = instance.imp();
237
238 let spec = &mut *(spec as *mut AudioRingBufferSpec);
239
240 gst::panic_to_error!(imp, false, {
241 match AudioSinkImpl::prepare(imp, spec) {
242 Ok(()) => true,
243 Err(err) => {
244 err.log_with_imp(imp);
245 false
246 }
247 }
248 })
249 .into_glib()
250}
251
252unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>(
253 ptr: *mut ffi::GstAudioSink,
254) -> glib::ffi::gboolean {
255 let instance = &*(ptr as *mut T::Instance);
256 let imp = instance.imp();
257
258 gst::panic_to_error!(imp, false, {
259 match imp.unprepare() {
260 Ok(()) => true,
261 Err(err) => {
262 err.log_with_imp(imp);
263 false
264 }
265 }
266 })
267 .into_glib()
268}
269
270unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>(
271 ptr: *mut ffi::GstAudioSink,
272 data: glib::ffi::gpointer,
273 length: u32,
274) -> i32 {
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
286unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) {
287 let instance = &*(ptr as *mut T::Instance);
288 let imp = instance.imp();
289
290 gst::panic_to_error!(imp, (), {
291 imp.reset();
292 });
293}