1use std::mem;
10use std::ptr;
11
12use glib_ffi;
13use gobject_ffi;
14use gst_ffi;
15
16use glib;
17use glib::translate::*;
18use gst;
19use gst::prelude::*;
20
21use gobject_subclass::anyimpl::*;
22use gobject_subclass::object::*;
23
24use element::*;
25use object::*;
26
27pub trait BinImpl<T: BinBase>:
28 AnyImpl + ObjectImpl<T> + ElementImpl<T> + Send + Sync + 'static
29where
30 T::InstanceStructType: PanicPoison,
31{
32 fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
33 bin.parent_add_element(element)
34 }
35
36 fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
37 bin.parent_remove_element(element)
38 }
39
40 fn handle_message(&self, bin: &T, message: gst::Message) {
41 bin.parent_handle_message(message)
42 }
43}
44
45any_impl!(BinBase, BinImpl, PanicPoison);
46
47pub unsafe trait BinBase: IsA<gst::Element> + IsA<gst::Bin> + ObjectType {
48 fn parent_add_element(&self, element: &gst::Element) -> bool {
49 unsafe {
50 let klass = self.get_class();
51 let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
52 (*parent_klass)
53 .add_element
54 .map(|f| from_glib(f(self.to_glib_none().0, element.to_glib_none().0)))
55 .unwrap_or(false)
56 }
57 }
58
59 fn parent_remove_element(&self, element: &gst::Element) -> bool {
60 unsafe {
61 let klass = self.get_class();
62 let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
63 (*parent_klass)
64 .remove_element
65 .map(|f| from_glib(f(self.to_glib_none().0, element.to_glib_none().0)))
66 .unwrap_or(false)
67 }
68 }
69
70 fn parent_handle_message(&self, message: gst::Message) {
71 unsafe {
72 let klass = self.get_class();
73 let parent_klass = (*klass).get_parent_class() as *const gst_ffi::GstBinClass;
74 (*parent_klass)
75 .handle_message
76 .map(move |f| f(self.to_glib_none().0, message.into_ptr()));
77 }
78 }
79}
80
81pub unsafe trait BinClassExt<T: BinBase>
82where
83 T::ImplType: BinImpl<T>,
84 T::InstanceStructType: PanicPoison,
85{
86 fn override_vfuncs(&mut self, _: &ClassInitToken) {
87 unsafe {
88 let klass = &mut *(self as *const Self as *mut gst_ffi::GstBinClass);
89 klass.add_element = Some(bin_add_element::<T>);
90 klass.remove_element = Some(bin_remove_element::<T>);
91 klass.handle_message = Some(bin_handle_message::<T>);
92 }
93 }
94}
95
96glib_wrapper! {
97 pub struct Bin(Object<ElementInstanceStruct<Bin>>):
98 [gst::Bin => gst_ffi::GstBin,
99 gst::Element => gst_ffi::GstElement,
100 gst::Object => gst_ffi::GstObject,
101 gst::ChildProxy => gst_ffi::GstChildProxy];
102
103 match fn {
104 get_type => || get_type::<Bin>(),
105 }
106}
107
108unsafe impl<T: IsA<gst::Element> + IsA<gst::Bin> + ObjectType> BinBase for T {}
109pub type BinClass = ClassStruct<Bin>;
110
111unsafe impl BinClassExt<Bin> for BinClass {}
113unsafe impl ElementClassExt<Bin> for BinClass {}
114unsafe impl ObjectClassExt<Bin> for BinClass {}
115
116unsafe impl Send for Bin {}
117unsafe impl Sync for Bin {}
118
119#[macro_export]
120macro_rules! box_bin_impl(
121 ($name:ident) => {
122 box_element_impl!($name);
123
124 impl<T: BinBase> BinImpl<T> for Box<$name<T>>
125 where
126 T::InstanceStructType: PanicPoison
127 {
128 fn add_element(&self, bin: &T, element: &gst::Element) -> bool {
129 let imp: &$name<T> = self.as_ref();
130 imp.add_element(bin, element)
131 }
132
133 fn remove_element(&self, bin: &T, element: &gst::Element) -> bool {
134 let imp: &$name<T> = self.as_ref();
135 imp.remove_element(bin, element)
136 }
137
138 fn handle_message(&self, bin: &T, message: gst::Message) {
139 let imp: &$name<T> = self.as_ref();
140 imp.handle_message(bin, message)
141 }
142 }
143 };
144);
145box_bin_impl!(BinImpl);
146
147impl ObjectType for Bin {
148 const NAME: &'static str = "RsBin";
149 type ParentType = gst::Bin;
150 type ImplType = Box<BinImpl<Self>>;
151 type InstanceStructType = ElementInstanceStruct<Self>;
152
153 fn class_init(token: &ClassInitToken, klass: &mut BinClass) {
154 ObjectClassExt::override_vfuncs(klass, token);
155 ElementClassExt::override_vfuncs(klass, token);
156 BinClassExt::override_vfuncs(klass, token);
157 }
158
159 object_type_fns!();
160}
161
162unsafe extern "C" fn bin_add_element<T: BinBase>(
163 ptr: *mut gst_ffi::GstBin,
164 element: *mut gst_ffi::GstElement,
165) -> glib_ffi::gboolean
166where
167 T::ImplType: BinImpl<T>,
168 T::InstanceStructType: PanicPoison,
169{
170 floating_reference_guard!(ptr);
171 let bin = &*(ptr as *mut T::InstanceStructType);
172 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
173 let imp = bin.get_impl();
174
175 panic_to_error!(&wrap, &bin.panicked(), false, {
176 imp.add_element(&wrap, &from_glib_borrow(element))
177 })
178 .to_glib()
179}
180
181unsafe extern "C" fn bin_remove_element<T: BinBase>(
182 ptr: *mut gst_ffi::GstBin,
183 element: *mut gst_ffi::GstElement,
184) -> glib_ffi::gboolean
185where
186 T::ImplType: BinImpl<T>,
187 T::InstanceStructType: PanicPoison,
188{
189 floating_reference_guard!(ptr);
190 let bin = &*(ptr as *mut T::InstanceStructType);
191 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
192 let imp = bin.get_impl();
193
194 panic_to_error!(&wrap, &bin.panicked(), false, {
195 imp.remove_element(&wrap, &from_glib_borrow(element))
196 })
197 .to_glib()
198}
199
200unsafe extern "C" fn bin_handle_message<T: BinBase>(
201 ptr: *mut gst_ffi::GstBin,
202 message: *mut gst_ffi::GstMessage,
203) where
204 T::ImplType: BinImpl<T>,
205 T::InstanceStructType: PanicPoison,
206{
207 floating_reference_guard!(ptr);
208 let bin = &*(ptr as *mut T::InstanceStructType);
209 let wrap: T = from_glib_borrow(ptr as *mut T::InstanceStructType);
210 let imp = bin.get_impl();
211
212 panic_to_error!(&wrap, &bin.panicked(), (), {
213 imp.handle_message(&wrap, from_glib_full(message))
214 });
215}