gstreamer_audio/subclass/
audio_sink.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, translate::*};
4use gst::LoggableError;
5use gst_base::subclass::prelude::*;
6
7use super::prelude::*;
8use crate::{ffi, AudioRingBufferSpec, AudioSink};
9
10pub trait AudioSinkImpl: AudioSinkImplExt + AudioBaseSinkImpl {
11    /// Close the device.
12    fn close(&self) -> Result<(), LoggableError> {
13        self.parent_close()
14    }
15
16    /// Return how many frames are still in the device. Participates in
17    ///  computing the time for audio clocks and drives the synchronisation.
18    fn delay(&self) -> u32 {
19        self.parent_delay()
20    }
21
22    /// Open the device. No configuration needs to be done at this point.
23    ///  This function is also used to check if the device is available.
24    fn open(&self) -> Result<(), LoggableError> {
25        self.parent_open()
26    }
27
28    /// Prepare the device to operate with the specified parameters.
29    fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
30        AudioSinkImplExt::parent_prepare(self, spec)
31    }
32
33    /// Undo operations done in prepare.
34    fn unprepare(&self) -> Result<(), LoggableError> {
35        self.parent_unprepare()
36    }
37
38    /// Write samples to the device.
39    fn write(&self, audio_data: &[u8]) -> Result<i32, LoggableError> {
40        self.parent_write(audio_data)
41    }
42
43    /// Returns as quickly as possible from a write and flush any pending
44    ///  samples from the device.
45    ///  This vmethod is deprecated. Please provide pause and stop instead.
46    fn reset(&self) {
47        self.parent_reset()
48    }
49}
50
51mod sealed {
52    pub trait Sealed {}
53    impl<T: super::AudioSinkImplExt> Sealed for T {}
54}
55
56pub trait AudioSinkImplExt: sealed::Sealed + ObjectSubclass {
57    fn parent_close(&self) -> Result<(), LoggableError> {
58        unsafe {
59            let data = Self::type_data();
60            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
61            let f = match (*parent_class).close {
62                None => return Ok(()),
63                Some(f) => f,
64            };
65            gst::result_from_gboolean!(
66                f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
67                gst::CAT_RUST,
68                "Failed to close element using the parent function"
69            )
70        }
71    }
72
73    fn parent_delay(&self) -> u32 {
74        unsafe {
75            let data = Self::type_data();
76            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
77            let f = match (*parent_class).delay {
78                Some(f) => f,
79                None => return 0,
80            };
81            f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
82        }
83    }
84
85    fn parent_open(&self) -> Result<(), LoggableError> {
86        unsafe {
87            let data = Self::type_data();
88            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
89            let f = match (*parent_class).open {
90                Some(f) => f,
91                None => return Ok(()),
92            };
93            gst::result_from_gboolean!(
94                f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
95                gst::CAT_RUST,
96                "Failed to open element using the parent function"
97            )
98        }
99    }
100
101    fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
102        unsafe {
103            let data = Self::type_data();
104            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
105            let f = match (*parent_class).prepare {
106                Some(f) => f,
107                None => return Ok(()),
108            };
109            gst::result_from_gboolean!(
110                f(
111                    self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
112                    &mut spec.0
113                ),
114                gst::CAT_RUST,
115                "Failed to prepare element using the parent function"
116            )
117        }
118    }
119
120    fn parent_unprepare(&self) -> Result<(), LoggableError> {
121        unsafe {
122            let data = Self::type_data();
123            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
124            let f = match (*parent_class).unprepare {
125                Some(f) => f,
126                None => {
127                    return Err(gst::loggable_error!(
128                        gst::CAT_RUST,
129                        "Unprepare is not implemented!"
130                    ))
131                }
132            };
133            gst::result_from_gboolean!(
134                f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0),
135                gst::CAT_RUST,
136                "Failed to unprepare element using the parent function"
137            )
138        }
139    }
140
141    fn parent_write(&self, buffer: &[u8]) -> Result<i32, LoggableError> {
142        unsafe {
143            let data = Self::type_data();
144            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
145            let f = match (*parent_class).write {
146                Some(f) => f,
147                None => return Ok(-1),
148            };
149            let buffer_ptr = buffer.as_ptr() as glib::ffi::gpointer;
150            let ret = f(
151                self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0,
152                buffer_ptr,
153                buffer.len() as u32,
154            );
155            if ret > 0 {
156                Ok(ret)
157            } else {
158                Err(gst::loggable_error!(
159                    gst::CAT_RUST,
160                    "Failed to write using the parent function"
161                ))
162            }
163        }
164    }
165
166    fn parent_reset(&self) {
167        unsafe {
168            let data = Self::type_data();
169            let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass;
170            if let Some(f) = (*parent_class).reset {
171                f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0)
172            }
173        }
174    }
175}
176
177impl<T: AudioSinkImpl> AudioSinkImplExt for T {}
178
179unsafe impl<T: AudioSinkImpl> IsSubclassable<T> for AudioSink {
180    fn class_init(klass: &mut glib::Class<Self>) {
181        Self::parent_class_init::<T>(klass);
182        let klass = klass.as_mut();
183        klass.close = Some(audiosink_close::<T>);
184        klass.delay = Some(audiosink_delay::<T>);
185        klass.open = Some(audiosink_open::<T>);
186        klass.prepare = Some(audiosink_prepare::<T>);
187        klass.unprepare = Some(audiosink_unprepare::<T>);
188        klass.write = Some(audiosink_write::<T>);
189        klass.reset = Some(audiosink_reset::<T>);
190    }
191}
192
193unsafe extern "C" fn audiosink_close<T: AudioSinkImpl>(
194    ptr: *mut ffi::GstAudioSink,
195) -> glib::ffi::gboolean {
196    let instance = &*(ptr as *mut T::Instance);
197    let imp = instance.imp();
198
199    gst::panic_to_error!(imp, false, {
200        match imp.close() {
201            Ok(()) => true,
202            Err(err) => {
203                err.log_with_imp(imp);
204                false
205            }
206        }
207    })
208    .into_glib()
209}
210
211unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 {
212    let instance = &*(ptr as *mut T::Instance);
213    let imp = instance.imp();
214
215    gst::panic_to_error!(imp, 0, { imp.delay() })
216}
217
218unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>(
219    ptr: *mut ffi::GstAudioSink,
220) -> glib::ffi::gboolean {
221    let instance = &*(ptr as *mut T::Instance);
222    let imp = instance.imp();
223
224    gst::panic_to_error!(imp, false, {
225        match imp.open() {
226            Ok(()) => true,
227            Err(err) => {
228                err.log_with_imp(imp);
229                false
230            }
231        }
232    })
233    .into_glib()
234}
235
236unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>(
237    ptr: *mut ffi::GstAudioSink,
238    spec: *mut ffi::GstAudioRingBufferSpec,
239) -> glib::ffi::gboolean {
240    let instance = &*(ptr as *mut T::Instance);
241    let imp = instance.imp();
242
243    let spec = &mut *(spec as *mut AudioRingBufferSpec);
244
245    gst::panic_to_error!(imp, false, {
246        match AudioSinkImpl::prepare(imp, spec) {
247            Ok(()) => true,
248            Err(err) => {
249                err.log_with_imp(imp);
250                false
251            }
252        }
253    })
254    .into_glib()
255}
256
257unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>(
258    ptr: *mut ffi::GstAudioSink,
259) -> glib::ffi::gboolean {
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
275unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>(
276    ptr: *mut ffi::GstAudioSink,
277    data: glib::ffi::gpointer,
278    length: u32,
279) -> i32 {
280    let instance = &*(ptr as *mut T::Instance);
281    let imp = instance.imp();
282    let data_slice = if length == 0 {
283        &[]
284    } else {
285        std::slice::from_raw_parts(data as *const u8, length as usize)
286    };
287
288    gst::panic_to_error!(imp, -1, { imp.write(data_slice).unwrap_or(-1) })
289}
290
291unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) {
292    let instance = &*(ptr as *mut T::Instance);
293    let imp = instance.imp();
294
295    gst::panic_to_error!(imp, (), {
296        imp.reset();
297    });
298}