1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use glib::{once_cell::sync::Lazy, translate::*}; |
4 | use gst_base::{prelude::*, subclass::prelude::*}; |
5 | |
6 | use crate::{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: Lazy<gst::Caps> = |
56 | Lazy::new(|| crate::AudioCapsBuilder::new().build()); |
57 | |
58 | return &ANY_AUDIO_CAPS; |
59 | } |
60 | |
61 | &*(&(*templ).caps as *const *mut gst::ffi::GstCaps as *const gst::Caps) |
62 | } |
63 | } |
64 | } |
65 | |
66 | impl<T: AudioFilterImpl> AudioFilterImplExt for T {} |
67 | |
68 | unsafe impl<T: AudioFilterImpl> IsSubclassable<T> for AudioFilter { |
69 | fn class_init(klass: &mut glib::Class<Self>) { |
70 | Self::parent_class_init::<T>(class:klass); |
71 | |
72 | let klass: &mut GstAudioFilterClass = klass.as_mut(); |
73 | klass.setup = Some(audio_filter_setup::<T>); |
74 | |
75 | unsafe { |
76 | ffi::gst_audio_filter_class_add_pad_templates( |
77 | &mut *klass, |
78 | T::allowed_caps().to_glib_none().0, |
79 | ); |
80 | } |
81 | } |
82 | } |
83 | |
84 | unsafe extern "C" fn audio_filter_setup<T: AudioFilterImpl>( |
85 | ptr: *mut ffi::GstAudioFilter, |
86 | info: *const ffi::GstAudioInfo, |
87 | ) -> glib::ffi::gboolean { |
88 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
89 | let imp: &T = instance.imp(); |
90 | |
91 | gstbool::panic_to_error!(imp, false, { |
92 | match imp.setup(&from_glib_none(info)) { |
93 | Ok(()) => true, |
94 | Err(err) => { |
95 | err.log_with_imp(imp); |
96 | false |
97 | } |
98 | } |
99 | }) |
100 | .into_glib() |
101 | } |
102 | |