1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::mem; |
4 | |
5 | use glib::{prelude::*, translate::*}; |
6 | use gst::LoggableError; |
7 | use gst_base::subclass::prelude::*; |
8 | |
9 | use super::prelude::*; |
10 | use crate::{AudioRingBufferSpec, AudioSrc}; |
11 | |
12 | pub 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 | |
42 | mod sealed { |
43 | pub trait Sealed {} |
44 | impl<T: super::AudioSrcImplExt> Sealed for T {} |
45 | } |
46 | |
47 | pub 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 | |
173 | impl<T: AudioSrcImpl> AudioSrcImplExt for T {} |
174 | |
175 | unsafe 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 | |
189 | unsafe 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 | |
207 | unsafe 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 | |
214 | unsafe 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 | |
232 | unsafe 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 | |
253 | unsafe 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 | |
271 | unsafe 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 | |
293 | unsafe 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 | |