1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::mem;
4
5use glib::{prelude::*, translate::*};
6use gst::LoggableError;
7use gst_base::subclass::prelude::*;
8
9use super::prelude::*;
10use crate::{AudioRingBufferSpec, AudioSrc};
11
12pub trait AudioSrcImpl: AudioSrcImplExt + AudioBaseSrcImpl {
13 fn close(&self) -> Result<(), LoggableError> {
14 self.parent_close()
15 }
16
17 fn delay(&self) -> u32 {
18 self.parent_delay()
19 }
20
21 fn open(&self) -> Result<(), LoggableError> {
22 self.parent_open()
23 }
24
25 fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
26 AudioSrcImplExt::parent_prepare(self, spec)
27 }
28
29 fn unprepare(&self) -> Result<(), LoggableError> {
30 self.parent_unprepare()
31 }
32
33 fn read(&self, audio_data: &mut [u8]) -> Result<(u32, Option<gst::ClockTime>), LoggableError> {
34 self.parent_read(audio_data)
35 }
36
37 fn reset(&self) {
38 self.parent_reset()
39 }
40}
41
42mod sealed {
43 pub trait Sealed {}
44 impl<T: super::AudioSrcImplExt> Sealed for T {}
45}
46
47pub trait AudioSrcImplExt: sealed::Sealed + ObjectSubclass {
48 fn parent_close(&self) -> Result<(), LoggableError> {
49 unsafe {
50 let data = Self::type_data();
51 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
52 let f = match (*parent_class).close {
53 None => return Ok(()),
54 Some(f) => f,
55 };
56 gst::result_from_gboolean!(
57 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
58 gst::CAT_RUST,
59 "Failed to close element using the parent function"
60 )
61 }
62 }
63
64 fn parent_delay(&self) -> u32 {
65 unsafe {
66 let data = Self::type_data();
67 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
68 let f = match (*parent_class).delay {
69 Some(f) => f,
70 None => return 0,
71 };
72 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0)
73 }
74 }
75
76 fn parent_open(&self) -> Result<(), LoggableError> {
77 unsafe {
78 let data = Self::type_data();
79 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
80 let f = match (*parent_class).open {
81 Some(f) => f,
82 None => return Ok(()),
83 };
84 gst::result_from_gboolean!(
85 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
86 gst::CAT_RUST,
87 "Failed to open element using the parent function"
88 )
89 }
90 }
91
92 fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
93 unsafe {
94 let data = Self::type_data();
95 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
96 let f = match (*parent_class).prepare {
97 Some(f) => f,
98 None => return Ok(()),
99 };
100 gst::result_from_gboolean!(
101 f(
102 self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0,
103 &mut spec.0
104 ),
105 gst::CAT_RUST,
106 "Failed to prepare element using the parent function"
107 )
108 }
109 }
110
111 fn parent_unprepare(&self) -> Result<(), LoggableError> {
112 unsafe {
113 let data = Self::type_data();
114 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
115 let f = match (*parent_class).unprepare {
116 Some(f) => f,
117 None => {
118 return Err(gst::loggable_error!(
119 gst::CAT_RUST,
120 "Unprepare is not implemented!"
121 ))
122 }
123 };
124 gst::result_from_gboolean!(
125 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
126 gst::CAT_RUST,
127 "Failed to unprepare element using the parent function"
128 )
129 }
130 }
131
132 fn parent_read(
133 &self,
134 buffer: &mut [u8],
135 ) -> Result<(u32, Option<gst::ClockTime>), LoggableError> {
136 unsafe {
137 let data = Self::type_data();
138 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
139 let f = match (*parent_class).read {
140 Some(f) => f,
141 None => return Ok((0, gst::ClockTime::NONE)),
142 };
143 let buffer_ptr = buffer.as_mut_ptr() as *mut _;
144 let mut timestamp = mem::MaybeUninit::uninit();
145 let ret = f(
146 self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0,
147 buffer_ptr,
148 buffer.len() as u32,
149 timestamp.as_mut_ptr(),
150 );
151 if ret > 0 {
152 Ok((ret, from_glib(timestamp.assume_init())))
153 } else {
154 Err(gst::loggable_error!(
155 gst::CAT_RUST,
156 "Failed to read using the parent function"
157 ))
158 }
159 }
160 }
161
162 fn parent_reset(&self) {
163 unsafe {
164 let data = Self::type_data();
165 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
166 if let Some(f) = (*parent_class).reset {
167 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0)
168 }
169 }
170 }
171}
172
173impl<T: AudioSrcImpl> AudioSrcImplExt for T {}
174
175unsafe impl<T: AudioSrcImpl> IsSubclassable<T> for AudioSrc {
176 fn class_init(klass: &mut glib::Class<Self>) {
177 Self::parent_class_init::<T>(class:klass);
178 let klass: &mut GstAudioSrcClass = klass.as_mut();
179 klass.close = Some(audiosrc_close::<T>);
180 klass.delay = Some(audiosrc_delay::<T>);
181 klass.open = Some(audiosrc_open::<T>);
182 klass.prepare = Some(audiosrc_prepare::<T>);
183 klass.unprepare = Some(audiosrc_unprepare::<T>);
184 klass.read = Some(audiosrc_read::<T>);
185 klass.reset = Some(audiosrc_reset::<T>);
186 }
187}
188
189unsafe extern "C" fn audiosrc_close<T: AudioSrcImpl>(
190 ptr: *mut ffi::GstAudioSrc,
191) -> glib::ffi::gboolean {
192 let instance: &::Instance = &*(ptr as *mut T::Instance);
193 let imp: &T = instance.imp();
194
195 gstbool::panic_to_error!(imp, false, {
196 match imp.close() {
197 Ok(()) => true,
198 Err(err) => {
199 err.log_with_imp(imp);
200 false
201 }
202 }
203 })
204 .into_glib()
205}
206
207unsafe extern "C" fn audiosrc_delay<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) -> u32 {
208 let instance: &::Instance = &*(ptr as *mut T::Instance);
209 let imp: &T = instance.imp();
210
211 gst::panic_to_error!(imp, 0, { imp.delay() })
212}
213
214unsafe extern "C" fn audiosrc_open<T: AudioSrcImpl>(
215 ptr: *mut ffi::GstAudioSrc,
216) -> glib::ffi::gboolean {
217 let instance: &::Instance = &*(ptr as *mut T::Instance);
218 let imp: &T = instance.imp();
219
220 gstbool::panic_to_error!(imp, false, {
221 match imp.open() {
222 Ok(()) => true,
223 Err(err) => {
224 err.log_with_imp(imp);
225 false
226 }
227 }
228 })
229 .into_glib()
230}
231
232unsafe extern "C" fn audiosrc_prepare<T: AudioSrcImpl>(
233 ptr: *mut ffi::GstAudioSrc,
234 spec: *mut ffi::GstAudioRingBufferSpec,
235) -> glib::ffi::gboolean {
236 let instance: &::Instance = &*(ptr as *mut T::Instance);
237 let imp: &T = instance.imp();
238
239 let spec: &mut AudioRingBufferSpec = &mut *(spec as *mut AudioRingBufferSpec);
240
241 gstbool::panic_to_error!(imp, false, {
242 match AudioSrcImpl::prepare(imp, spec) {
243 Ok(()) => true,
244 Err(err) => {
245 err.log_with_imp(imp);
246 false
247 }
248 }
249 })
250 .into_glib()
251}
252
253unsafe extern "C" fn audiosrc_unprepare<T: AudioSrcImpl>(
254 ptr: *mut ffi::GstAudioSrc,
255) -> glib::ffi::gboolean {
256 let instance: &::Instance = &*(ptr as *mut T::Instance);
257 let imp: &T = instance.imp();
258
259 gstbool::panic_to_error!(imp, false, {
260 match imp.unprepare() {
261 Ok(()) => true,
262 Err(err) => {
263 err.log_with_imp(imp);
264 false
265 }
266 }
267 })
268 .into_glib()
269}
270
271unsafe extern "C" fn audiosrc_read<T: AudioSrcImpl>(
272 ptr: *mut ffi::GstAudioSrc,
273 data: glib::ffi::gpointer,
274 length: u32,
275 timestamp: *mut gst::ffi::GstClockTime,
276) -> u32 {
277 let instance: &::Instance = &*(ptr as *mut T::Instance);
278 let imp: &T = instance.imp();
279 let data_slice: &mut [u8] = if length == 0 {
280 &mut []
281 } else {
282 std::slice::from_raw_parts_mut(data as *mut u8, len:length as usize)
283 };
284
285 gst::panic_to_error!(imp, 0, {
286 let (res, timestamp_res) = imp.read(data_slice).unwrap_or((0, gst::ClockTime::NONE));
287 *timestamp = timestamp_res.into_glib();
288
289 res
290 })
291}
292
293unsafe extern "C" fn audiosrc_reset<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) {
294 let instance: &::Instance = &*(ptr as *mut T::Instance);
295 let imp: &T = instance.imp();
296
297 gst::panic_to_error!(imp, (), {
298 imp.reset();
299 });
300}
301