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