diff --git a/Gir_GstBase.toml b/Gir_GstBase.toml index 32b1f8543..01f2eacb2 100644 --- a/Gir_GstBase.toml +++ b/Gir_GstBase.toml @@ -75,6 +75,7 @@ concurrency = "none" [[object]] name = "GstBase.BaseSrc" +subclassing = true status = "generate" [[object.function]] diff --git a/gstreamer-base/Cargo.toml b/gstreamer-base/Cargo.toml index a62aaeb1e..ee380dccf 100644 --- a/gstreamer-base/Cargo.toml +++ b/gstreamer-base/Cargo.toml @@ -33,6 +33,7 @@ v1_14_1 = ["gstreamer-sys/v1_14", "gstreamer-base-sys/v1_14_1", "v1_14"] embed-lgpl-docs = ["rustdoc-stripper"] purge-lgpl-docs = ["rustdoc-stripper"] dox = ["gstreamer-base-sys/dox", "glib/dox", "gstreamer/dox"] +subclassing = ["gstreamer/subclassing"] default-features = [] [badges] diff --git a/gstreamer-base/src/auto/base_src.rs b/gstreamer-base/src/auto/base_src.rs index d3d6e231e..71032b9b1 100644 --- a/gstreamer-base/src/auto/base_src.rs +++ b/gstreamer-base/src/auto/base_src.rs @@ -2,6 +2,7 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT +use BaseSrcClass; use ffi; use glib; use glib::StaticType; @@ -21,7 +22,7 @@ use std::mem::transmute; use std::ptr; glib_wrapper! { - pub struct BaseSrc(Object): [ + pub struct BaseSrc(Object): [ gst::Element => gst_ffi::GstElement, gst::Object => gst_ffi::GstObject, ]; diff --git a/gstreamer-base/src/base_src.rs b/gstreamer-base/src/base_src.rs index 35ae4de43..559fee7ca 100644 --- a/gstreamer-base/src/base_src.rs +++ b/gstreamer-base/src/base_src.rs @@ -8,8 +8,9 @@ use ffi; use glib::translate::*; -use glib::IsA; +use glib::{IsA, IsClassFor}; use gst; +use std::ops; use BaseSrc; pub trait BaseSrcExtManual { @@ -26,3 +27,27 @@ impl> BaseSrcExtManual for O { } } } + +#[repr(C)] +pub struct BaseSrcClass(ffi::GstBaseSrcClass); + +unsafe impl IsClassFor for BaseSrcClass { + type Instance = BaseSrc; +} + +unsafe impl Send for BaseSrcClass {} +unsafe impl Sync for BaseSrcClass {} + +impl ops::Deref for BaseSrcClass { + type Target = gst::ElementClass; + + fn deref(&self) -> &Self::Target { + self.upcast_ref() + } +} + +impl ops::DerefMut for BaseSrcClass { + 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 cf8f86e39..5e5d4ca61 100644 --- a/gstreamer-base/src/lib.rs +++ b/gstreamer-base/src/lib.rs @@ -8,6 +8,7 @@ extern crate glib_sys as glib_ffi; extern crate gobject_sys as gobject_ffi; +#[macro_use] extern crate gstreamer as gst; extern crate gstreamer_base_sys as ffi; extern crate gstreamer_sys as gst_ffi; @@ -46,6 +47,7 @@ mod aggregator; mod aggregator_pad; mod base_sink; mod base_src; +pub use base_src::BaseSrcClass; mod base_transform; // Re-export all the traits in a prelude module, so that applications @@ -65,3 +67,6 @@ pub mod prelude { } mod utils; + +#[cfg(feature = "subclassing")] +pub mod subclass; diff --git a/gstreamer-base/src/subclass/base_src.rs b/gstreamer-base/src/subclass/base_src.rs new file mode 100644 index 000000000..7a86f2bcf --- /dev/null +++ b/gstreamer-base/src/subclass/base_src.rs @@ -0,0 +1,532 @@ +// 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 BaseSrc; +use BaseSrcClass; + +pub trait BaseSrcImpl: ElementImpl + Send + Sync + 'static { + fn start(&self, _element: &BaseSrc) -> bool { + true + } + + fn stop(&self, _element: &BaseSrc) -> bool { + true + } + + fn is_seekable(&self, _element: &BaseSrc) -> bool { + false + } + + fn get_size(&self, _element: &BaseSrc) -> Option { + None + } + + fn fill( + &self, + _element: &BaseSrc, + _offset: u64, + _length: u32, + _buffer: &mut gst::BufferRef, + ) -> gst::FlowReturn { + unimplemented!() + } + + fn create( + &self, + element: &BaseSrc, + offset: u64, + length: u32, + ) -> Result { + self.parent_create(element, offset, length) + } + + fn do_seek(&self, element: &BaseSrc, segment: &mut gst::Segment) -> bool { + self.parent_do_seek(element, segment) + } + + fn query(&self, element: &BaseSrc, query: &mut gst::QueryRef) -> bool { + BaseSrcImpl::parent_query(self, element, query) + } + + fn event(&self, element: &BaseSrc, event: &gst::Event) -> bool { + self.parent_event(element, event) + } + + fn get_caps(&self, element: &BaseSrc, filter: Option<&gst::CapsRef>) -> Option { + self.parent_get_caps(element, filter) + } + + fn negotiate(&self, element: &BaseSrc) -> bool { + self.parent_negotiate(element) + } + + fn set_caps(&self, element: &BaseSrc, caps: &gst::CapsRef) -> bool { + self.parent_set_caps(element, caps) + } + + fn fixate(&self, element: &BaseSrc, caps: gst::Caps) -> gst::Caps { + self.parent_fixate(element, caps) + } + + fn unlock(&self, _element: &BaseSrc) -> bool { + true + } + + fn unlock_stop(&self, _element: &BaseSrc) -> bool { + true + } + + fn parent_create( + &self, + element: &BaseSrc, + offset: u64, + length: u32, + ) -> Result { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*parent_class) + .create + .map(|f| { + let mut buffer: *mut gst_ffi::GstBuffer = ptr::null_mut(); + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ref = &mut buffer as *mut _ as *mut gst_ffi::GstBuffer; + let ret: gst::FlowReturn = + from_glib(f(element.to_glib_none().0, offset, length, buffer_ref)); + + ret.into_result_value(|| from_glib_full(buffer)) + }) + .unwrap_or(Err(gst::FlowError::Error)) + } + } + + fn parent_do_seek(&self, element: &BaseSrc, segment: &mut gst::Segment) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*parent_class) + .do_seek + .map(|f| from_glib(f(element.to_glib_none().0, segment.to_glib_none_mut().0))) + .unwrap_or(false) + } + } + + fn parent_query(&self, element: &BaseSrc, query: &mut gst::QueryRef) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*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: &BaseSrc, event: &gst::Event) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*parent_class) + .event + .map(|f| from_glib(f(element.to_glib_none().0, event.to_glib_none().0))) + .unwrap_or(false) + } + } + + fn parent_get_caps( + &self, + element: &BaseSrc, + filter: Option<&gst::CapsRef>, + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + 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_negotiate(&self, element: &BaseSrc) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*parent_class) + .negotiate + .map(|f| from_glib(f(element.to_glib_none().0))) + .unwrap_or(false) + } + } + + fn parent_set_caps(&self, element: &BaseSrc, caps: &gst::CapsRef) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + (*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: &BaseSrc, caps: gst::Caps) -> gst::Caps { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseSrcClass; + + match (*parent_class).fixate { + Some(fixate) => from_glib_full(fixate(element.to_glib_none().0, caps.into_ptr())), + None => caps, + } + } + } +} + +unsafe impl IsSubclassable for BaseSrcClass +where + ::Instance: PanicPoison, +{ + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *const Self as *mut ffi::GstBaseSrcClass); + klass.start = Some(base_src_start::); + klass.stop = Some(base_src_stop::); + klass.is_seekable = Some(base_src_is_seekable::); + klass.get_size = Some(base_src_get_size::); + klass.fill = Some(base_src_fill::); + klass.create = Some(base_src_create::); + klass.do_seek = Some(base_src_do_seek::); + klass.query = Some(base_src_query::); + klass.event = Some(base_src_event::); + klass.get_caps = Some(base_src_get_caps::); + klass.negotiate = Some(base_src_negotiate::); + klass.set_caps = Some(base_src_set_caps::); + klass.fixate = Some(base_src_fixate::); + klass.unlock = Some(base_src_unlock::); + klass.unlock_stop = Some(base_src_unlock_stop::); + } + } +} + +unsafe extern "C" fn base_src_start( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.start(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_src_stop( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.stop(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_src_is_seekable( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.is_seekable(&wrap) + }) + .to_glib() +} + +unsafe extern "C" fn base_src_get_size( + ptr: *mut ffi::GstBaseSrc, + size: *mut u64, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + match imp.get_size(&wrap) { + Some(s) => { + *size = s; + true + } + None => false, + } + }) + .to_glib() +} + +unsafe extern "C" fn base_src_fill( + ptr: *mut ffi::GstBaseSrc, + offset: u64, + length: u32, + buffer: *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + let buffer = gst::BufferRef::from_mut_ptr(buffer); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.fill(&wrap, offset, length, buffer) + }) + .to_glib() +} + +unsafe extern "C" fn base_src_create( + ptr: *mut ffi::GstBaseSrc, + offset: u64, + length: u32, + buffer_ptr: *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ptr = buffer_ptr as *mut *mut gst_ffi::GstBuffer; + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + match imp.create(&wrap, offset, length) { + Ok(buffer) => { + *buffer_ptr = buffer.into_ptr(); + gst::FlowReturn::Ok + } + Err(err) => gst::FlowReturn::from(err), + } + }) + .to_glib() +} + +unsafe extern "C" fn base_src_do_seek( + ptr: *mut ffi::GstBaseSrc, + segment: *mut gst_ffi::GstSegment, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.do_seek(&wrap, &mut from_glib_borrow(segment)) + }) + .to_glib() +} + +unsafe extern "C" fn base_src_query( + ptr: *mut ffi::GstBaseSrc, + query_ptr: *mut gst_ffi::GstQuery, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + let query = gst::QueryRef::from_mut_ptr(query_ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + BaseSrcImpl::query(imp, &wrap, query) + }) + .to_glib() +} + +unsafe extern "C" fn base_src_event( + ptr: *mut ffi::GstBaseSrc, + event_ptr: *mut gst_ffi::GstEvent, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.event(&wrap, &from_glib_borrow(event_ptr)) + }) + .to_glib() +} + +unsafe extern "C" fn base_src_get_caps( + ptr: *mut ffi::GstBaseSrc, + filter: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = 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_src_negotiate( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.negotiate(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_src_set_caps( + ptr: *mut ffi::GstBaseSrc, + caps: *mut gst_ffi::GstCaps, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = 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_src_fixate( + ptr: *mut ffi::GstBaseSrc, + caps: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = 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_src_unlock( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.unlock(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_src_unlock_stop( + ptr: *mut ffi::GstBaseSrc, +) -> glib_ffi::gboolean +where + T: BaseSrcImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseSrc = 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 new file mode 100644 index 000000000..c1acdcb67 --- /dev/null +++ b/gstreamer-base/src/subclass/mod.rs @@ -0,0 +1,15 @@ +// Copyright (C) 2016-2018 Sebastian Dröge +// 2016 Luis de Bethencourt +// +// 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. +#![cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))] + +pub mod base_src; + +pub mod prelude { + pub use super::base_src::BaseSrcImpl; +}