diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index e10eabfa1..d8439d58f 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -45,6 +45,7 @@ pub use crate::error::*; #[macro_use] pub mod miniobject; +pub use miniobject::{MiniObject, MiniObjectRef}; pub mod message; pub use crate::message::{Message, MessageErrorDomain, MessageRef, MessageView}; @@ -310,6 +311,8 @@ pub mod prelude { pub use crate::typefind::TypeFindImpl; pub use crate::value::GstValueExt; + pub use crate::miniobject::IsMiniObject; + pub use crate::tags::{CustomTag, Tag}; pub use muldiv::MulDiv; diff --git a/gstreamer/src/miniobject.rs b/gstreamer/src/miniobject.rs index 50e9878f1..6cf41614a 100644 --- a/gstreamer/src/miniobject.rs +++ b/gstreamer/src/miniobject.rs @@ -1,5 +1,14 @@ // Take a look at the license at the top of the repository in the LICENSE file. +use glib::translate::*; + +pub trait IsMiniObject: + AsRef + FromGlibPtrFull<*mut Self::FfiType> + Send + Sync + 'static +{ + type RefType; + type FfiType; +} + #[macro_export] macro_rules! mini_object_wrapper ( ($name:ident, $ref_name:ident, $ffi_name:path) => { @@ -10,6 +19,11 @@ macro_rules! mini_object_wrapper ( #[repr(transparent)] pub struct $ref_name($ffi_name); + impl $crate::miniobject::IsMiniObject for $name { + type RefType = $ref_name; + type FfiType = $ffi_name; + } + impl $name { pub unsafe fn from_glib_none(ptr: *const $ffi_name) -> Self { skip_assert_initialized!(); @@ -78,6 +92,12 @@ macro_rules! mini_object_wrapper ( } } + pub fn upcast(self) -> $crate::miniobject::MiniObject { + unsafe { + from_glib_full(self.into_ptr() as *mut $crate::ffi::GstMiniObject) + } + } + pub unsafe fn into_ptr(self) -> *mut $ffi_name { let s = std::mem::ManuallyDrop::new(self); s.as_mut_ptr() @@ -392,6 +412,18 @@ macro_rules! mini_object_wrapper ( ) as *const $ffi_name) } } + + pub fn upcast_ref(&self) -> &$crate::miniobject::MiniObjectRef { + unsafe { + &*(self.as_ptr() as *const $crate::miniobject::MiniObjectRef) + } + } + + pub fn upcast_mut(&mut self) -> &mut $crate::miniobject::MiniObjectRef { + unsafe { + &mut *(self.as_mut_ptr() as *mut $crate::miniobject::MiniObjectRef) + } + } } impl $crate::glib::translate::GlibPtrDefault for $ref_name { @@ -485,3 +517,43 @@ macro_rules! mini_object_wrapper ( // immutable references from a mutable reference without borrowing via the value }; ); + +#[cfg(not(any(feature = "v1_20", feature = "dox")))] +mini_object_wrapper!(MiniObject, MiniObjectRef, ffi::GstMiniObject); + +#[cfg(any(feature = "v1_20", feature = "dox"))] +mini_object_wrapper!(MiniObject, MiniObjectRef, ffi::GstMiniObject, || { + ffi::gst_mini_object_get_type() +}); + +impl MiniObject { + pub fn downcast(self) -> Result { + if self.type_().is_a(T::static_type()) { + unsafe { Ok(from_glib_full(self.into_ptr() as *mut T::FfiType)) } + } else { + Err(self) + } + } +} + +impl MiniObjectRef { + pub fn type_(&self) -> glib::Type { + unsafe { from_glib((*self.as_ptr()).type_) } + } + + pub fn downcast_ref(&self) -> Option<&T> { + if self.type_().is_a(T::static_type()) { + unsafe { Some(&*(self as *const Self as *const T)) } + } else { + None + } + } + + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.type_().is_a(T::static_type()) { + unsafe { Some(&mut *(self as *mut Self as *mut T)) } + } else { + None + } + } +} diff --git a/gstreamer/src/subclass/tracer.rs b/gstreamer/src/subclass/tracer.rs index e9eb6d529..01ae971dd 100644 --- a/gstreamer/src/subclass/tracer.rs +++ b/gstreamer/src/subclass/tracer.rs @@ -2,8 +2,8 @@ use crate::ffi; use crate::{ - Bin, Buffer, BufferList, Element, Event, FlowReturn, Message, Object, Pad, PadLinkReturn, - Query, StateChange, StateChangeReturn, Tracer, + Bin, Buffer, BufferList, Element, Event, FlowReturn, Message, MiniObject, Object, Pad, + PadLinkReturn, Query, StateChange, StateChangeReturn, Tracer, }; use glib::{prelude::*, subclass::prelude::*, translate::*}; @@ -29,6 +29,14 @@ pub trait TracerImpl: TracerImplExt + ObjectImpl + Send + Sync { fn element_query_post(&self, ts: u64, element: &Element, query: &Query, success: bool) {} fn element_query_pre(&self, ts: u64, element: &Element, query: &Query) {} fn element_remove_pad(&self, ts: u64, element: &Element, pad: &Pad) {} + // rustdoc-stripper-ignore-next + /// Hook to be called before the GstMiniObject has been fully initialized. + fn mini_object_created(&self, ts: u64, object: std::ptr::NonNull) {} + // rustdoc-stripper-ignore-next + /// Hook to be called after the GstMiniObject has been finalized. + fn mini_object_destroyed(&self, ts: u64, object: std::ptr::NonNull) {} + fn mini_object_reffed(&self, ts: u64, object: &MiniObject, new_refcount: i32) {} + fn mini_object_unreffed(&self, ts: u64, object: &MiniObject, new_refcount: i32) {} fn object_created(&self, ts: u64, object: &Object) {} // rustdoc-stripper-ignore-next /// Hook to be called after the GstObject has been finalized. @@ -169,11 +177,22 @@ define_tracer_hooks! { let p = Pad::from_glib_borrow(p); this.element_remove_pad(ts, &e, &p) }; - // TODO(#353): Missing bindings to `GstMiniObject`. - // MiniObjectCreated, - // MiniObjectDestroyed, - // MiniObjectReffed, - // MiniObjectUnreffed, + // TODO: unclear what to do here as the `GstMiniObject` here is not fully initialized yet… + MiniObjectCreated("mini-object-created") = |this, ts, o: *mut ffi::GstMiniObject| { + this.mini_object_created(ts, std::ptr::NonNull::new_unchecked(o)) + }; + // TODO: unclear what to do here as the `GstMiniObject` here is no longer valid… + MiniObjectDestroyed("mini-object-destroyed") = |this, ts, o: *mut ffi::GstMiniObject| { + this.mini_object_destroyed(ts, std::ptr::NonNull::new_unchecked(o)) + }; + MiniObjectReffed("mini-object-reffed") = |this, ts, o: *mut ffi::GstMiniObject, rc: libc::c_int| { + let o = MiniObject::from_glib_borrow(o); + this.mini_object_reffed(ts, &o, rc as i32) + }; + MiniObjectUnreffed("mini-object-unreffed") = |this, ts, o: *mut ffi::GstMiniObject, rc: libc::c_int| { + let o = MiniObject::from_glib_borrow(o); + this.mini_object_unreffed(ts, &o, rc as i32) + }; ObjectCreated("object-created") = |this, ts, o: *mut ffi::GstObject| { let o = Object::from_glib_borrow(o); this.object_created(ts, &o) diff --git a/gstreamer/sys/Gir.toml b/gstreamer/sys/Gir.toml index c0401100a..aa77e14a6 100644 --- a/gstreamer/sys/Gir.toml +++ b/gstreamer/sys/Gir.toml @@ -169,6 +169,13 @@ status = "generate" name = "steal" version = "1.18.3" +[[object]] +name = "Gst.MiniObject" +status = "generate" + [[object.function]] + name = "get_type" + version = "1.20" + [[object]] name = "Gst.Memory" status = "generate" diff --git a/gstreamer/sys/src/lib.rs b/gstreamer/sys/src/lib.rs index 3bcdd829e..cd3d513ed 100644 --- a/gstreamer/sys/src/lib.rs +++ b/gstreamer/sys/src/lib.rs @@ -5728,6 +5728,8 @@ extern "C" { //========================================================================= // GstMiniObject //========================================================================= + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub fn gst_mini_object_get_type() -> GType; #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]