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