diff --git a/gstreamer-gl/src/subclass/gl_base_filter.rs b/gstreamer-gl/src/subclass/gl_base_filter.rs new file mode 100644 index 000000000..22bae1e19 --- /dev/null +++ b/gstreamer-gl/src/subclass/gl_base_filter.rs @@ -0,0 +1,170 @@ +use ffi::GstGLBaseFilter; +use gst::ffi::GstCaps; + +use crate::prelude::*; + +use glib::translate::*; + +use gst::subclass::prelude::*; +use gst::{result_from_gboolean, Caps, LoggableError, CAT_RUST}; +use gst_base::subclass::prelude::*; + +use crate::GLBaseFilter; + +pub trait GLBaseFilterImpl: GLBaseFilterImplExt + BaseTransformImpl { + fn gl_set_caps( + &self, + filter: &Self::Type, + incaps: &Caps, + outcaps: &Caps, + ) -> Result<(), LoggableError> { + self.parent_gl_set_caps(filter, incaps, outcaps) + } + + fn gl_start(&self, filter: &Self::Type) -> Result<(), LoggableError> { + self.parent_gl_start(filter) + } + + fn gl_stop(&self, filter: &Self::Type) { + self.parent_gl_stop(filter) + } +} + +pub trait GLBaseFilterImplExt: ObjectSubclass { + fn parent_gl_set_caps( + &self, + filter: &Self::Type, + incaps: &Caps, + outcaps: &Caps, + ) -> Result<(), LoggableError>; + + fn parent_gl_start(&self, filter: &Self::Type) -> Result<(), LoggableError>; + + fn parent_gl_stop(&self, filter: &Self::Type); +} + +impl GLBaseFilterImplExt for T { + fn parent_gl_set_caps( + &self, + filter: &Self::Type, + incaps: &Caps, + outcaps: &Caps, + ) -> Result<(), LoggableError> { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstGLBaseFilterClass; + + (*parent_class) + .gl_set_caps + .map(|f| { + result_from_gboolean!( + f( + filter.unsafe_cast_ref::().to_glib_none().0, + incaps.to_glib_none().0, + outcaps.to_glib_none().0, + ), + CAT_RUST, + "Parent function `gl_set_caps` failed", + ) + }) + .unwrap_or(Ok(())) + } + } + + fn parent_gl_start(&self, filter: &Self::Type) -> Result<(), LoggableError> { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstGLBaseFilterClass; + + (*parent_class) + .gl_start + .map(|f| { + result_from_gboolean!( + f(filter.unsafe_cast_ref::().to_glib_none().0), + CAT_RUST, + "Parent function `gl_start` failed", + ) + }) + .unwrap_or(Ok(())) + } + } + + fn parent_gl_stop(&self, filter: &Self::Type) { + unsafe { + let data = T::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstGLBaseFilterClass; + + if let Some(f) = (*parent_class).gl_stop { + f(filter.unsafe_cast_ref::().to_glib_none().0) + } + } + } +} + +unsafe impl IsSubclassable for GLBaseFilter { + fn class_init(klass: &mut glib::Class) { + >::class_init(klass); + let klass = klass.as_mut(); + klass.gl_set_caps = Some(gl_set_caps::); + klass.gl_start = Some(gl_start::); + klass.gl_stop = Some(gl_stop::); + } + + fn instance_init(instance: &mut glib::subclass::InitializingObject) { + >::instance_init(instance) + } +} + +unsafe extern "C" fn gl_set_caps( + ptr: *mut GstGLBaseFilter, + incaps: *mut GstCaps, + outcaps: *mut GstCaps, +) -> glib::ffi::gboolean { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.impl_(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, &imp.panicked(), false, { + match imp.gl_set_caps( + wrap.unsafe_cast_ref(), + &from_glib_borrow(incaps), + &from_glib_borrow(outcaps), + ) { + Ok(()) => true, + Err(err) => { + err.log_with_object(&*wrap); + false + } + } + }) + .to_glib() +} + +unsafe extern "C" fn gl_start( + ptr: *mut GstGLBaseFilter, +) -> glib::ffi::gboolean { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.impl_(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, &imp.panicked(), false, { + match imp.gl_start(wrap.unsafe_cast_ref()) { + Ok(()) => true, + Err(err) => { + err.log_with_object(&*wrap); + false + } + } + }) + .to_glib() +} + +unsafe extern "C" fn gl_stop(ptr: *mut GstGLBaseFilter) { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.impl_(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, &imp.panicked(), (), { + imp.gl_stop(wrap.unsafe_cast_ref()) + }) +} diff --git a/gstreamer-gl/src/subclass/mod.rs b/gstreamer-gl/src/subclass/mod.rs new file mode 100644 index 000000000..5c165539f --- /dev/null +++ b/gstreamer-gl/src/subclass/mod.rs @@ -0,0 +1,5 @@ +mod gl_base_filter; + +pub mod prelude { + pub use super::gl_base_filter::{GLBaseFilterImpl, GLBaseFilterImplExt}; +}