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