gstreamer: Add bindings to MiniObject together with casting functionality

This is only possible with 1.20 because gst_mini_object_get_type() was
added then. Previous versions only provide bindings for the specific
types, like Caps, Event, etc.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/353
This commit is contained in:
Sebastian Dröge 2021-09-19 13:30:29 +03:00 committed by Sebastian Dröge
parent 672b7abe1d
commit 1856d47a06
5 changed files with 110 additions and 7 deletions

View file

@ -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;

View file

@ -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<Self::RefType> + 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<T: IsMiniObject + glib::StaticType>(self) -> Result<T, Self> {
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<T: IsMiniObject + glib::StaticType>(&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<T: IsMiniObject + glib::StaticType>(&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
}
}
}

View file

@ -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<ffi::GstMiniObject>) {}
// 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<ffi::GstMiniObject>) {}
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)

View file

@ -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"

View file

@ -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")))]