1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use glib::translate::*; |
4 | use gst_base::{prelude::*, subclass::prelude::*}; |
5 | |
6 | use crate::{ffi, AudioFilter, AudioInfo}; |
7 | |
8 | pub trait AudioFilterImpl: AudioFilterImplExt + BaseTransformImpl { |
9 | fn allowed_caps() -> &'static gst::Caps { |
10 | Self::parent_allowed_caps() |
11 | } |
12 | |
13 | fn setup(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> { |
14 | self.parent_setup(info) |
15 | } |
16 | } |
17 | |
18 | mod sealed { |
19 | pub trait Sealed {} |
20 | impl<T: super::AudioFilterImplExt> Sealed for T {} |
21 | } |
22 | |
23 | pub trait AudioFilterImplExt: sealed::Sealed + ObjectSubclass { |
24 | fn parent_setup(&self, info: &AudioInfo) -> Result<(), gst::LoggableError> { |
25 | unsafe { |
26 | let data = Self::type_data(); |
27 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioFilterClass; |
28 | (*parent_class) |
29 | .setup |
30 | .map(|f| { |
31 | gst::result_from_gboolean!( |
32 | f( |
33 | self.obj().unsafe_cast_ref::<AudioFilter>().to_glib_none().0, |
34 | info.to_glib_none().0, |
35 | ), |
36 | gst::CAT_RUST, |
37 | "Parent function `setup` failed" |
38 | ) |
39 | }) |
40 | .unwrap_or(Ok(())) |
41 | } |
42 | } |
43 | |
44 | fn parent_allowed_caps() -> &'static gst::Caps { |
45 | unsafe { |
46 | let data = Self::type_data(); |
47 | let parent_class = data.as_ref().parent_class() as *mut gst::ffi::GstElementClass; |
48 | |
49 | let templ = gst::ffi::gst_element_class_get_pad_template( |
50 | parent_class, |
51 | glib::gstr!("sink" ).to_glib_none().0, |
52 | ); |
53 | |
54 | if templ.is_null() { |
55 | static ANY_AUDIO_CAPS: std::sync::OnceLock<gst::Caps> = std::sync::OnceLock::new(); |
56 | |
57 | return ANY_AUDIO_CAPS.get_or_init(|| crate::AudioCapsBuilder::new().build()); |
58 | } |
59 | |
60 | &*(&(*templ).caps as *const *mut gst::ffi::GstCaps as *const gst::Caps) |
61 | } |
62 | } |
63 | } |
64 | |
65 | impl<T: AudioFilterImpl> AudioFilterImplExt for T {} |
66 | |
67 | unsafe impl<T: AudioFilterImpl> IsSubclassable<T> for AudioFilter { |
68 | fn class_init(klass: &mut glib::Class<Self>) { |
69 | Self::parent_class_init::<T>(class:klass); |
70 | |
71 | let klass: &mut GstAudioFilterClass = klass.as_mut(); |
72 | klass.setup = Some(audio_filter_setup::<T>); |
73 | |
74 | unsafe { |
75 | ffi::gst_audio_filter_class_add_pad_templates( |
76 | &mut *klass, |
77 | T::allowed_caps().to_glib_none().0, |
78 | ); |
79 | } |
80 | } |
81 | } |
82 | |
83 | unsafe extern "C" fn audio_filter_setup<T: AudioFilterImpl>( |
84 | ptr: *mut ffi::GstAudioFilter, |
85 | info: *const ffi::GstAudioInfo, |
86 | ) -> glib::ffi::gboolean { |
87 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
88 | let imp: &T = instance.imp(); |
89 | |
90 | gstbool::panic_to_error!(imp, false, { |
91 | match imp.setup(&from_glib_none(info)) { |
92 | Ok(()) => true, |
93 | Err(err) => { |
94 | err.log_with_imp(imp); |
95 | false |
96 | } |
97 | } |
98 | }) |
99 | .into_glib() |
100 | } |
101 | |