gstreamer/subclass/
bin.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, subclass::prelude::*, translate::*};
4
5use super::prelude::*;
6use crate::{ffi, Bin, Element, LoggableError, Message};
7
8pub trait BinImpl: BinImplExt + ElementImpl {
9    /// Method to add an element to the bin.
10    /// ## `element`
11    /// the element to be added
12    ///
13    /// # Returns
14    ///
15    /// [`true`] if the `element` was added
16    fn add_element(&self, element: &Element) -> Result<(), LoggableError> {
17        self.parent_add_element(element)
18    }
19
20    /// Method to remove an element from the bin.
21    /// ## `element`
22    /// the element to be removed
23    ///
24    /// # Returns
25    ///
26    /// [`true`] if the `element` was removed
27    fn remove_element(&self, element: &Element) -> Result<(), LoggableError> {
28        self.parent_remove_element(element)
29    }
30
31    fn do_latency(&self) -> Result<(), LoggableError> {
32        self.parent_do_latency()
33    }
34
35    /// Method to handle a message from the children.
36    /// ## `message`
37    /// the message to be handled
38    fn handle_message(&self, message: Message) {
39        self.parent_handle_message(message)
40    }
41}
42
43mod sealed {
44    pub trait Sealed {}
45    impl<T: super::BinImplExt> Sealed for T {}
46}
47
48pub trait BinImplExt: sealed::Sealed + ObjectSubclass {
49    fn parent_add_element(&self, element: &Element) -> Result<(), LoggableError> {
50        unsafe {
51            let data = Self::type_data();
52            let parent_class = data.as_ref().parent_class() as *mut ffi::GstBinClass;
53            let f = (*parent_class).add_element.ok_or_else(|| {
54                loggable_error!(
55                    crate::CAT_RUST,
56                    "Parent function `add_element` is not defined"
57                )
58            })?;
59            result_from_gboolean!(
60                f(
61                    self.obj().unsafe_cast_ref::<crate::Bin>().to_glib_none().0,
62                    element.to_glib_none().0
63                ),
64                crate::CAT_RUST,
65                "Failed to add the element using the parent function"
66            )
67        }
68    }
69
70    fn parent_remove_element(&self, element: &Element) -> Result<(), LoggableError> {
71        unsafe {
72            let data = Self::type_data();
73            let parent_class = data.as_ref().parent_class() as *mut ffi::GstBinClass;
74            let f = (*parent_class).remove_element.ok_or_else(|| {
75                loggable_error!(
76                    crate::CAT_RUST,
77                    "Parent function `remove_element` is not defined"
78                )
79            })?;
80            result_from_gboolean!(
81                f(
82                    self.obj().unsafe_cast_ref::<crate::Bin>().to_glib_none().0,
83                    element.to_glib_none().0
84                ),
85                crate::CAT_RUST,
86                "Failed to remove the element using the parent function"
87            )
88        }
89    }
90
91    fn parent_do_latency(&self) -> Result<(), LoggableError> {
92        unsafe {
93            let data = Self::type_data();
94            let parent_class = data.as_ref().parent_class() as *mut ffi::GstBinClass;
95            let f = (*parent_class).do_latency.ok_or_else(|| {
96                loggable_error!(
97                    crate::CAT_RUST,
98                    "Parent function `do_latency` is not defined"
99                )
100            })?;
101            result_from_gboolean!(
102                f(self.obj().unsafe_cast_ref::<crate::Bin>().to_glib_none().0,),
103                crate::CAT_RUST,
104                "Failed to update latency using the parent function"
105            )
106        }
107    }
108
109    fn parent_handle_message(&self, message: Message) {
110        unsafe {
111            let data = Self::type_data();
112            let parent_class = data.as_ref().parent_class() as *mut ffi::GstBinClass;
113            if let Some(ref f) = (*parent_class).handle_message {
114                f(
115                    self.obj().unsafe_cast_ref::<crate::Bin>().to_glib_none().0,
116                    message.into_glib_ptr(),
117                );
118            }
119        }
120    }
121}
122
123impl<T: BinImpl> BinImplExt for T {}
124
125unsafe impl<T: BinImpl> IsSubclassable<T> for Bin {
126    fn class_init(klass: &mut glib::Class<Self>) {
127        Self::parent_class_init::<T>(klass);
128        let klass = klass.as_mut();
129        klass.add_element = Some(bin_add_element::<T>);
130        klass.remove_element = Some(bin_remove_element::<T>);
131        klass.do_latency = Some(bin_do_latency::<T>);
132        klass.handle_message = Some(bin_handle_message::<T>);
133    }
134}
135
136unsafe extern "C" fn bin_add_element<T: BinImpl>(
137    ptr: *mut ffi::GstBin,
138    element: *mut ffi::GstElement,
139) -> glib::ffi::gboolean {
140    let instance = &*(ptr as *mut T::Instance);
141    let imp = instance.imp();
142
143    panic_to_error!(imp, false, {
144        match imp.add_element(&from_glib_none(element)) {
145            Ok(()) => true,
146            Err(err) => {
147                err.log_with_imp(imp);
148                false
149            }
150        }
151    })
152    .into_glib()
153}
154
155unsafe extern "C" fn bin_remove_element<T: BinImpl>(
156    ptr: *mut ffi::GstBin,
157    element: *mut ffi::GstElement,
158) -> glib::ffi::gboolean {
159    let instance = &*(ptr as *mut T::Instance);
160    let imp = instance.imp();
161
162    // If we get a floating reference passed simply return FALSE here. It can't be
163    // stored inside this bin, and if we continued to use it we would take ownership
164    // of this floating reference.
165    if glib::gobject_ffi::g_object_is_floating(element as *mut glib::gobject_ffi::GObject)
166        != glib::ffi::GFALSE
167    {
168        return glib::ffi::GFALSE;
169    }
170
171    panic_to_error!(imp, false, {
172        match imp.remove_element(&from_glib_none(element)) {
173            Ok(()) => true,
174            Err(err) => {
175                err.log_with_imp(imp);
176                false
177            }
178        }
179    })
180    .into_glib()
181}
182
183unsafe extern "C" fn bin_do_latency<T: BinImpl>(ptr: *mut ffi::GstBin) -> glib::ffi::gboolean {
184    let instance = &*(ptr as *mut T::Instance);
185    let imp = instance.imp();
186
187    panic_to_error!(imp, false, {
188        match imp.do_latency() {
189            Ok(()) => true,
190            Err(err) => {
191                err.log_with_imp(imp);
192                false
193            }
194        }
195    })
196    .into_glib()
197}
198
199unsafe extern "C" fn bin_handle_message<T: BinImpl>(
200    ptr: *mut ffi::GstBin,
201    message: *mut ffi::GstMessage,
202) {
203    let instance = &*(ptr as *mut T::Instance);
204    let imp = instance.imp();
205
206    panic_to_error!(imp, (), { imp.handle_message(from_glib_full(message)) });
207}