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