gstreamer_audio/subclass/
audio_src.rs

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::{ffi, AudioRingBufferSpec, AudioSrc};
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    let instance = &*(ptr as *mut T::Instance);
188    let imp = instance.imp();
189
190    gst::panic_to_error!(imp, false, {
191        match imp.close() {
192            Ok(()) => true,
193            Err(err) => {
194                err.log_with_imp(imp);
195                false
196            }
197        }
198    })
199    .into_glib()
200}
201
202unsafe extern "C" fn audiosrc_delay<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) -> u32 {
203    let instance = &*(ptr as *mut T::Instance);
204    let imp = instance.imp();
205
206    gst::panic_to_error!(imp, 0, { imp.delay() })
207}
208
209unsafe extern "C" fn audiosrc_open<T: AudioSrcImpl>(
210    ptr: *mut ffi::GstAudioSrc,
211) -> glib::ffi::gboolean {
212    let instance = &*(ptr as *mut T::Instance);
213    let imp = instance.imp();
214
215    gst::panic_to_error!(imp, false, {
216        match imp.open() {
217            Ok(()) => true,
218            Err(err) => {
219                err.log_with_imp(imp);
220                false
221            }
222        }
223    })
224    .into_glib()
225}
226
227unsafe extern "C" fn audiosrc_prepare<T: AudioSrcImpl>(
228    ptr: *mut ffi::GstAudioSrc,
229    spec: *mut ffi::GstAudioRingBufferSpec,
230) -> glib::ffi::gboolean {
231    let instance = &*(ptr as *mut T::Instance);
232    let imp = instance.imp();
233
234    let spec = &mut *(spec as *mut AudioRingBufferSpec);
235
236    gst::panic_to_error!(imp, false, {
237        match AudioSrcImpl::prepare(imp, spec) {
238            Ok(()) => true,
239            Err(err) => {
240                err.log_with_imp(imp);
241                false
242            }
243        }
244    })
245    .into_glib()
246}
247
248unsafe extern "C" fn audiosrc_unprepare<T: AudioSrcImpl>(
249    ptr: *mut ffi::GstAudioSrc,
250) -> glib::ffi::gboolean {
251    let instance = &*(ptr as *mut T::Instance);
252    let imp = instance.imp();
253
254    gst::panic_to_error!(imp, false, {
255        match imp.unprepare() {
256            Ok(()) => true,
257            Err(err) => {
258                err.log_with_imp(imp);
259                false
260            }
261        }
262    })
263    .into_glib()
264}
265
266unsafe extern "C" fn audiosrc_read<T: AudioSrcImpl>(
267    ptr: *mut ffi::GstAudioSrc,
268    data: glib::ffi::gpointer,
269    length: u32,
270    timestamp: *mut gst::ffi::GstClockTime,
271) -> u32 {
272    let instance = &*(ptr as *mut T::Instance);
273    let imp = instance.imp();
274    let data_slice = if length == 0 {
275        &mut []
276    } else {
277        std::slice::from_raw_parts_mut(data as *mut u8, length as usize)
278    };
279
280    gst::panic_to_error!(imp, 0, {
281        let (res, timestamp_res) = imp.read(data_slice).unwrap_or((0, gst::ClockTime::NONE));
282        *timestamp = timestamp_res.into_glib();
283
284        res
285    })
286}
287
288unsafe extern "C" fn audiosrc_reset<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) {
289    let instance = &*(ptr as *mut T::Instance);
290    let imp = instance.imp();
291
292    gst::panic_to_error!(imp, (), {
293        imp.reset();
294    });
295}