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