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: 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>(klass);
178        let klass = 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 = &*(ptr as *mut T::Instance);
193    let imp = instance.imp();
194
195    gst::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 = &*(ptr as *mut T::Instance);
209    let imp = 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 = &*(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
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 = &*(ptr as *mut T::Instance);
237    let imp = instance.imp();
238
239    let spec = &mut *(spec as *mut AudioRingBufferSpec);
240
241    gst::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 = &*(ptr as *mut T::Instance);
257    let imp = instance.imp();
258
259    gst::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 = &*(ptr as *mut T::Instance);
278    let imp = instance.imp();
279    let data_slice = if length == 0 {
280        &mut []
281    } else {
282        std::slice::from_raw_parts_mut(data as *mut u8, 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 = &*(ptr as *mut T::Instance);
295    let imp = instance.imp();
296
297    gst::panic_to_error!(imp, (), {
298        imp.reset();
299    });
300}