diff --git a/Gir_GstBase.toml b/Gir_GstBase.toml index 01f2eacb2..c76420714 100644 --- a/Gir_GstBase.toml +++ b/Gir_GstBase.toml @@ -16,7 +16,6 @@ external_libraries = [ ] generate = [ - "GstBase.BaseSink", "GstBase.BaseTransform", "GstBase.PushSrc", ] @@ -73,6 +72,11 @@ status = "manual" trait = false concurrency = "none" +[[object]] +name = "GstBase.BaseSink" +subclassing = true +status = "generate" + [[object]] name = "GstBase.BaseSrc" subclassing = true diff --git a/gstreamer-base/src/auto/base_sink.rs b/gstreamer-base/src/auto/base_sink.rs index 5082fa936..ee4e434a3 100644 --- a/gstreamer-base/src/auto/base_sink.rs +++ b/gstreamer-base/src/auto/base_sink.rs @@ -2,6 +2,7 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT +use BaseSinkClass; use ffi; use glib; use glib::StaticType; @@ -21,7 +22,7 @@ use std::mem::transmute; use std::ptr; glib_wrapper! { - pub struct BaseSink(Object): [ + pub struct BaseSink(Object): [ gst::Element => gst_ffi::GstElement, gst::Object => gst_ffi::GstObject, ]; diff --git a/gstreamer-base/src/base_sink.rs b/gstreamer-base/src/base_sink.rs index bfbef3c2d..d9dd5f04d 100644 --- a/gstreamer-base/src/base_sink.rs +++ b/gstreamer-base/src/base_sink.rs @@ -8,8 +8,9 @@ use ffi; use glib::translate::*; -use glib::IsA; +use glib::{IsA, IsClassFor}; use gst; +use std::ops; use BaseSink; pub trait BaseSinkExtManual { @@ -26,3 +27,27 @@ impl> BaseSinkExtManual for O { } } } + +#[repr(C)] +pub struct BaseSinkClass(ffi::GstBaseSinkClass); + +unsafe impl IsClassFor for BaseSinkClass { + type Instance = BaseSink; +} + +unsafe impl Send for BaseSinkClass {} +unsafe impl Sync for BaseSinkClass {} + +impl ops::Deref for BaseSinkClass { + type Target = gst::ElementClass; + + fn deref(&self) -> &Self::Target { + self.upcast_ref() + } +} + +impl ops::DerefMut for BaseSinkClass { + fn deref_mut(&mut self) -> &mut Self::Target { + self.upcast_ref_mut() + } +} diff --git a/gstreamer-base/src/lib.rs b/gstreamer-base/src/lib.rs index 5e5d4ca61..871c28587 100644 --- a/gstreamer-base/src/lib.rs +++ b/gstreamer-base/src/lib.rs @@ -46,6 +46,7 @@ mod aggregator; #[cfg(any(feature = "v1_14", feature = "dox"))] mod aggregator_pad; mod base_sink; +pub use base_sink::BaseSinkClass; mod base_src; pub use base_src::BaseSrcClass; mod base_transform; diff --git a/gstreamer-base/src/subclass/base_sink.rs b/gstreamer-base/src/subclass/base_sink.rs new file mode 100644 index 000000000..ae7597f00 --- /dev/null +++ b/gstreamer-base/src/subclass/base_sink.rs @@ -0,0 +1,427 @@ +// 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 gst_ffi; + +use glib::translate::*; +use prelude::*; + +use glib::subclass::prelude::*; +use gst; +use gst::subclass::prelude::*; + +use std::ptr; + +use BaseSink; +use BaseSinkClass; + +pub trait BaseSinkImpl: ElementImpl + Send + Sync + 'static { + fn start(&self, _element: &BaseSink) -> bool { + true + } + + fn stop(&self, _element: &BaseSink) -> bool { + true + } + + fn render(&self, element: &BaseSink, buffer: &gst::BufferRef) -> gst::FlowReturn; + + fn prepare(&self, _element: &BaseSink, _buffer: &gst::BufferRef) -> gst::FlowReturn { + gst::FlowReturn::Ok + } + + fn render_list(&self, element: &BaseSink, list: &gst::BufferListRef) -> gst::FlowReturn { + for buffer in list.iter() { + let ret = self.render(element, buffer); + if ret != gst::FlowReturn::Ok { + return ret; + } + } + + gst::FlowReturn::Ok + } + + fn prepare_list(&self, element: &BaseSink, list: &gst::BufferListRef) -> gst::FlowReturn { + for buffer in list.iter() { + let ret = self.prepare(element, buffer); + if ret != gst::FlowReturn::Ok { + return ret; + } + } + + gst::FlowReturn::Ok + } + + fn query(&self, element: &BaseSink, query: &mut gst::QueryRef) -> bool { + BaseSinkImpl::parent_query(self, element, query) + } + + fn event(&self, element: &BaseSink, event: gst::Event) -> bool { + self.parent_event(element, event) + } + + fn get_caps(&self, element: &BaseSink, filter: Option<&gst::CapsRef>) -> Option { + self.parent_get_caps(element, filter) + } + + fn set_caps(&self, element: &BaseSink, caps: &gst::CapsRef) -> bool { + self.parent_set_caps(element, caps) + } + + fn fixate(&self, element: &BaseSink, caps: gst::Caps) -> gst::Caps { + self.parent_fixate(element, caps) + } + + fn unlock(&self, _element: &BaseSink) -> bool { + true + } + + fn unlock_stop(&self, _element: &BaseSink) -> bool { + true + } + + fn parent_query(&self, element: &BaseSink, query: &mut gst::QueryRef) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSinkClass; + (*parent_class) + .query + .map(|f| from_glib(f(element.to_glib_none().0, query.as_mut_ptr()))) + .unwrap_or(false) + } + } + + fn parent_event(&self, element: &BaseSink, event: gst::Event) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSinkClass; + (*parent_class) + .event + .map(|f| from_glib(f(element.to_glib_none().0, event.into_ptr()))) + .unwrap_or(false) + } + } + + fn parent_get_caps( + &self, + element: &BaseSink, + filter: Option<&gst::CapsRef>, + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSinkClass; + let filter_ptr = if let Some(filter) = filter { + filter.as_mut_ptr() + } else { + ptr::null_mut() + }; + + (*parent_class) + .get_caps + .map(|f| from_glib_full(f(element.to_glib_none().0, filter_ptr))) + .unwrap_or(None) + } + } + + fn parent_set_caps(&self, element: &BaseSink, caps: &gst::CapsRef) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSinkClass; + (*parent_class) + .set_caps + .map(|f| from_glib(f(element.to_glib_none().0, caps.as_mut_ptr()))) + .unwrap_or(true) + } + } + + fn parent_fixate(&self, element: &BaseSink, caps: gst::Caps) -> gst::Caps { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSinkClass; + + match (*parent_class).fixate { + Some(fixate) => from_glib_full(fixate(element.to_glib_none().0, caps.into_ptr())), + None => caps, + } + } + } +} + +unsafe impl IsSubclassable for BaseSinkClass +where + ::Instance: PanicPoison, +{ + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *const Self as *mut ffi::GstBaseSinkClass); + klass.start = Some(base_sink_start::); + klass.stop = Some(base_sink_stop::); + klass.render = Some(base_sink_render::); + klass.render_list = Some(base_sink_render_list::); + klass.prepare = Some(base_sink_prepare::); + klass.prepare_list = Some(base_sink_prepare_list::); + klass.query = Some(base_sink_query::); + klass.event = Some(base_sink_event::); + klass.get_caps = Some(base_sink_get_caps::); + klass.set_caps = Some(base_sink_set_caps::); + klass.fixate = Some(base_sink_fixate::); + klass.unlock = Some(base_sink_unlock::); + klass.unlock_stop = Some(base_sink_unlock_stop::); + } + } +} + +unsafe extern "C" fn base_sink_start( + ptr: *mut ffi::GstBaseSink, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.start(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_sink_stop( + ptr: *mut ffi::GstBaseSink, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.stop(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_sink_render( + ptr: *mut ffi::GstBaseSink, + buffer: *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let buffer = gst::BufferRef::from_ptr(buffer); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.render(&wrap, buffer) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_prepare( + ptr: *mut ffi::GstBaseSink, + buffer: *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let buffer = gst::BufferRef::from_ptr(buffer); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.prepare(&wrap, buffer) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_render_list( + ptr: *mut ffi::GstBaseSink, + list: *mut gst_ffi::GstBufferList, +) -> gst_ffi::GstFlowReturn +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let list = gst::BufferListRef::from_ptr(list); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.render_list(&wrap, list) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_prepare_list( + ptr: *mut ffi::GstBaseSink, + list: *mut gst_ffi::GstBufferList, +) -> gst_ffi::GstFlowReturn +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let list = gst::BufferListRef::from_ptr(list); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.prepare_list(&wrap, list) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_query( + ptr: *mut ffi::GstBaseSink, + query_ptr: *mut gst_ffi::GstQuery, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let query = gst::QueryRef::from_mut_ptr(query_ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + BaseSinkImpl::query(imp, &wrap, query) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_event( + ptr: *mut ffi::GstBaseSink, + event_ptr: *mut gst_ffi::GstEvent, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.event(&wrap, from_glib_full(event_ptr)) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_get_caps( + ptr: *mut ffi::GstBaseSink, + filter: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let filter = if filter.is_null() { + None + } else { + Some(gst::CapsRef::from_ptr(filter)) + }; + + gst_panic_to_error!(&wrap, &instance.panicked(), None, { + imp.get_caps(&wrap, filter) + }) + .map(|caps| caps.into_ptr()) + .unwrap_or(ptr::null_mut()) +} + +unsafe extern "C" fn base_sink_set_caps( + ptr: *mut ffi::GstBaseSink, + caps: *mut gst_ffi::GstCaps, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let caps = gst::CapsRef::from_ptr(caps); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.set_caps(&wrap, caps) + }) + .to_glib() +} + +unsafe extern "C" fn base_sink_fixate( + ptr: *mut ffi::GstBaseSink, + caps: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + let caps = from_glib_full(caps); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::Caps::new_empty(), { + imp.fixate(&wrap, caps) + }) + .into_ptr() +} + +unsafe extern "C" fn base_sink_unlock( + ptr: *mut ffi::GstBaseSink, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.unlock(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_sink_unlock_stop( + ptr: *mut ffi::GstBaseSink, +) -> glib_ffi::gboolean +where + T: BaseSinkImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSink = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.unlock_stop(&wrap) + }) + .to_glib() +} diff --git a/gstreamer-base/src/subclass/mod.rs b/gstreamer-base/src/subclass/mod.rs index c1acdcb67..150265a54 100644 --- a/gstreamer-base/src/subclass/mod.rs +++ b/gstreamer-base/src/subclass/mod.rs @@ -8,8 +8,10 @@ // except according to those terms. #![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] +pub mod base_sink; pub mod base_src; pub mod prelude { + pub use super::base_sink::BaseSinkImpl; pub use super::base_src::BaseSrcImpl; }