From 55dac7eeb4ebe5764b52ce9dc33c494715edb886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 19 Nov 2018 18:37:00 +0200 Subject: [PATCH] Port Bin subclassing --- Gir_Gst.toml | 1 + gstreamer/src/auto/bin.rs | 3 +- gstreamer/src/bin.rs | 27 ++++++- gstreamer/src/lib.rs | 4 +- gstreamer/src/subclass/bin.rs | 136 ++++++++++++++++++++++++++++++++++ gstreamer/src/subclass/mod.rs | 2 + 6 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 gstreamer/src/subclass/bin.rs diff --git a/Gir_Gst.toml b/Gir_Gst.toml index 247f8b9f9..f6fe63d39 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -83,6 +83,7 @@ conversion_type = "scalar" [[object]] name = "Gst.Bin" +subclassing = true status = "generate" trait_name = "GstBinExt" [[object.function]] diff --git a/gstreamer/src/auto/bin.rs b/gstreamer/src/auto/bin.rs index 33643e4cb..10846a765 100644 --- a/gstreamer/src/auto/bin.rs +++ b/gstreamer/src/auto/bin.rs @@ -2,6 +2,7 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT +use BinClass; use ChildProxy; use Element; #[cfg(any(feature = "v1_10", feature = "dox"))] @@ -26,7 +27,7 @@ use std::mem::transmute; use std::ptr; glib_wrapper! { - pub struct Bin(Object): Element, Object, ChildProxy; + pub struct Bin(Object): Element, Object, ChildProxy; match fn { get_type => || ffi::gst_bin_get_type(), diff --git a/gstreamer/src/bin.rs b/gstreamer/src/bin.rs index 5be6b30fc..694f92095 100644 --- a/gstreamer/src/bin.rs +++ b/gstreamer/src/bin.rs @@ -11,10 +11,11 @@ use Element; use glib; use glib::translate::{from_glib, from_glib_full, FromGlibPtrContainer, ToGlib, ToGlibPtr}; -use glib::IsA; +use glib::{IsA, IsClassFor}; use ffi; +use std::ops; use std::path; pub trait GstBinExtManual { @@ -124,6 +125,30 @@ impl> GstBinExtManual for O { } } +#[repr(C)] +pub struct BinClass(ffi::GstBinClass); + +unsafe impl IsClassFor for BinClass { + type Instance = ::Bin; +} + +unsafe impl Send for BinClass {} +unsafe impl Sync for BinClass {} + +impl ops::Deref for BinClass { + type Target = ::ElementClass; + + fn deref(&self) -> &Self::Target { + self.upcast_ref() + } +} + +impl ops::DerefMut for BinClass { + fn deref_mut(&mut self) -> &mut Self::Target { + self.upcast_ref_mut() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index c4a13218a..b1d085a5e 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -145,11 +145,13 @@ mod promise; #[cfg(any(feature = "v1_14", feature = "dox"))] pub use promise::*; -mod bin; mod bus; mod element; pub use element::ElementClass; +mod bin; +pub use bin::BinClass; + // OS dependent Bus extensions (also import the other plateform mod for doc) #[cfg(any(feature = "v1_14", feature = "dox"))] cfg_if! { diff --git a/gstreamer/src/subclass/bin.rs b/gstreamer/src/subclass/bin.rs new file mode 100644 index 000000000..22f949ad5 --- /dev/null +++ b/gstreamer/src/subclass/bin.rs @@ -0,0 +1,136 @@ +// Copyright (C) 2017,2018 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use glib_ffi; + +use glib::translate::*; + +use super::prelude::*; +use glib::subclass::prelude::*; + +use Bin; +use BinClass; +use Element; +use Message; + +pub trait BinImpl: ElementImpl + Send + Sync + 'static { + fn add_element(&self, bin: &Bin, element: &Element) -> bool { + self.parent_add_element(bin, element) + } + + fn remove_element(&self, bin: &Bin, element: &Element) -> bool { + self.parent_remove_element(bin, element) + } + + fn handle_message(&self, bin: &Bin, message: Message) { + self.parent_handle_message(bin, message) + } + + fn parent_add_element(&self, bin: &Bin, element: &Element) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBinClass; + (*parent_class) + .add_element + .map(|f| from_glib(f(bin.to_glib_none().0, element.to_glib_none().0))) + .unwrap_or(false) + } + } + + fn parent_remove_element(&self, bin: &Bin, element: &Element) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBinClass; + (*parent_class) + .remove_element + .map(|f| from_glib(f(bin.to_glib_none().0, element.to_glib_none().0))) + .unwrap_or(false) + } + } + + fn parent_handle_message(&self, bin: &Bin, message: Message) { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBinClass; + (*parent_class) + .handle_message + .map(move |f| f(bin.to_glib_none().0, message.into_ptr())); + } + } +} + +unsafe impl IsSubclassable for BinClass +where + ::Instance: PanicPoison, +{ + fn override_vfuncs(&mut self) { + <::ElementClass as IsSubclassable>::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *const Self as *mut ffi::GstBinClass); + klass.add_element = Some(bin_add_element::); + klass.remove_element = Some(bin_remove_element::); + klass.handle_message = Some(bin_handle_message::); + } + } +} + +unsafe extern "C" fn bin_add_element( + ptr: *mut ffi::GstBin, + element: *mut ffi::GstElement, +) -> glib_ffi::gboolean +where + T: BinImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Bin = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.add_element(&wrap, &from_glib_borrow(element)) + }) + .to_glib() +} + +unsafe extern "C" fn bin_remove_element( + ptr: *mut ffi::GstBin, + element: *mut ffi::GstElement, +) -> glib_ffi::gboolean +where + T: BinImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Bin = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.remove_element(&wrap, &from_glib_borrow(element)) + }) + .to_glib() +} + +unsafe extern "C" fn bin_handle_message( + ptr: *mut ffi::GstBin, + message: *mut ffi::GstMessage, +) where + T: BinImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Bin = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), (), { + imp.handle_message(&wrap, from_glib_full(message)) + }); +} diff --git a/gstreamer/src/subclass/mod.rs b/gstreamer/src/subclass/mod.rs index 7b82354ee..4af3c0b67 100644 --- a/gstreamer/src/subclass/mod.rs +++ b/gstreamer/src/subclass/mod.rs @@ -13,11 +13,13 @@ pub mod error; #[macro_use] pub mod plugin; +pub mod bin; pub mod child_proxy; pub mod element; pub mod uri_handler; pub mod prelude { + pub use super::bin::BinImpl; pub use super::child_proxy::ChildProxyImpl; pub use super::element::{ElementClassSubclassExt, ElementImpl, ElementImplExt}; pub use super::uri_handler::URIHandlerImpl;