gst_plugin/
bin.rs

1// Copyright (C) 2017 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
9use 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
111// FIXME: Boilerplate
112unsafe 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}