1 // Copyright (C) 2017,2018 Sebastian Dröge <sebastian@centricular.com>
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 use glib_sys;
10 use gst_sys;
11
12 use glib::translate::*;
13
14 use super::prelude::*;
15 use glib::subclass::prelude::*;
16
17 use Bin;
18 use BinClass;
19 use Element;
20 use LoggableError;
21 use Message;
22
23 pub trait BinImpl: BinImplExt + ElementImpl + Send + Sync + 'static {
add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>24 fn add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError> {
25 self.parent_add_element(bin, element)
26 }
27
remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>28 fn remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError> {
29 self.parent_remove_element(bin, element)
30 }
31
handle_message(&self, bin: &Bin, message: Message)32 fn handle_message(&self, bin: &Bin, message: Message) {
33 self.parent_handle_message(bin, message)
34 }
35 }
36
37 pub trait BinImplExt {
parent_add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>38 fn parent_add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>;
39
parent_remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>40 fn parent_remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>;
41
parent_handle_message(&self, bin: &Bin, message: Message)42 fn parent_handle_message(&self, bin: &Bin, message: Message);
43 }
44
45 impl<T: BinImpl + ObjectImpl> BinImplExt for T {
parent_add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>46 fn parent_add_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError> {
47 unsafe {
48 let data = self.get_type_data();
49 let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstBinClass;
50 let f = (*parent_class).add_element.ok_or_else(|| {
51 gst_loggable_error!(::CAT_RUST, "Parent function `add_element` is not defined")
52 })?;
53 gst_result_from_gboolean!(
54 f(bin.to_glib_none().0, element.to_glib_none().0),
55 ::CAT_RUST,
56 "Failed to add the element using the parent function"
57 )
58 }
59 }
60
parent_remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError>61 fn parent_remove_element(&self, bin: &Bin, element: &Element) -> Result<(), LoggableError> {
62 unsafe {
63 let data = self.get_type_data();
64 let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstBinClass;
65 let f = (*parent_class).remove_element.ok_or_else(|| {
66 gst_loggable_error!(
67 ::CAT_RUST,
68 "Parent function `remove_element` is not defined"
69 )
70 })?;
71 gst_result_from_gboolean!(
72 f(bin.to_glib_none().0, element.to_glib_none().0),
73 ::CAT_RUST,
74 "Failed to remove the element using the parent function"
75 )
76 }
77 }
78
parent_handle_message(&self, bin: &Bin, message: Message)79 fn parent_handle_message(&self, bin: &Bin, message: Message) {
80 unsafe {
81 let data = self.get_type_data();
82 let parent_class = data.as_ref().get_parent_class() as *mut gst_sys::GstBinClass;
83 if let Some(ref f) = (*parent_class).handle_message {
84 f(bin.to_glib_none().0, message.into_ptr());
85 }
86 }
87 }
88 }
89
90 unsafe impl<T: ObjectSubclass + BinImpl> IsSubclassable<T> for BinClass
91 where
92 <T as ObjectSubclass>::Instance: PanicPoison,
93 {
override_vfuncs(&mut self)94 fn override_vfuncs(&mut self) {
95 <::ElementClass as IsSubclassable<T>>::override_vfuncs(self);
96 unsafe {
97 let klass = &mut *(self as *mut Self as *mut gst_sys::GstBinClass);
98 klass.add_element = Some(bin_add_element::<T>);
99 klass.remove_element = Some(bin_remove_element::<T>);
100 klass.handle_message = Some(bin_handle_message::<T>);
101 }
102 }
103 }
104
bin_add_element<T: ObjectSubclass>( ptr: *mut gst_sys::GstBin, element: *mut gst_sys::GstElement, ) -> glib_sys::gboolean where T: BinImpl, T::Instance: PanicPoison,105 unsafe extern "C" fn bin_add_element<T: ObjectSubclass>(
106 ptr: *mut gst_sys::GstBin,
107 element: *mut gst_sys::GstElement,
108 ) -> glib_sys::gboolean
109 where
110 T: BinImpl,
111 T::Instance: PanicPoison,
112 {
113 let instance = &*(ptr as *mut T::Instance);
114 let imp = instance.get_impl();
115 let wrap: Bin = from_glib_borrow(ptr);
116
117 gst_panic_to_error!(&wrap, &instance.panicked(), false, {
118 match imp.add_element(&wrap, &from_glib_none(element)) {
119 Ok(()) => true,
120 Err(err) => {
121 err.log_with_object(&wrap);
122 false
123 }
124 }
125 })
126 .to_glib()
127 }
128
bin_remove_element<T: ObjectSubclass>( ptr: *mut gst_sys::GstBin, element: *mut gst_sys::GstElement, ) -> glib_sys::gboolean where T: BinImpl, T::Instance: PanicPoison,129 unsafe extern "C" fn bin_remove_element<T: ObjectSubclass>(
130 ptr: *mut gst_sys::GstBin,
131 element: *mut gst_sys::GstElement,
132 ) -> glib_sys::gboolean
133 where
134 T: BinImpl,
135 T::Instance: PanicPoison,
136 {
137 let instance = &*(ptr as *mut T::Instance);
138 let imp = instance.get_impl();
139 let wrap: Bin = from_glib_borrow(ptr);
140
141 // If we get a floating reference passed simply return FALSE here. It can't be
142 // stored inside this bin, and if we continued to use it we would take ownership
143 // of this floating reference.
144 if gobject_sys::g_object_is_floating(element as *mut gobject_sys::GObject) != glib_sys::GFALSE {
145 return glib_sys::GFALSE;
146 }
147
148 gst_panic_to_error!(&wrap, &instance.panicked(), false, {
149 match imp.remove_element(&wrap, &from_glib_none(element)) {
150 Ok(()) => true,
151 Err(err) => {
152 err.log_with_object(&wrap);
153 false
154 }
155 }
156 })
157 .to_glib()
158 }
159
bin_handle_message<T: ObjectSubclass>( ptr: *mut gst_sys::GstBin, message: *mut gst_sys::GstMessage, ) where T: BinImpl, T::Instance: PanicPoison,160 unsafe extern "C" fn bin_handle_message<T: ObjectSubclass>(
161 ptr: *mut gst_sys::GstBin,
162 message: *mut gst_sys::GstMessage,
163 ) where
164 T: BinImpl,
165 T::Instance: PanicPoison,
166 {
167 let instance = &*(ptr as *mut T::Instance);
168 let imp = instance.get_impl();
169 let wrap: Bin = from_glib_borrow(ptr);
170
171 gst_panic_to_error!(&wrap, &instance.panicked(), (), {
172 imp.handle_message(&wrap, from_glib_full(message))
173 });
174 }
175