Bindings to GstTracer and GstTracerFactory

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/147
This commit is contained in:
Simonas Kazlauskas 2021-08-15 13:00:32 +03:00
parent 3ad9d3340b
commit cb475e0965
11 changed files with 450 additions and 20 deletions

View file

@ -1975,6 +1975,11 @@ status = "generate"
# confusing return type
ignore = true
[[object.function]]
name = "tracing_register_hook"
# implemented as part of Tracer subclassing
manual = true
[[object]]
name = "Gst.StateChange"
status = "generate"
@ -2174,3 +2179,15 @@ generate_builder = true
[[object.function.parameter]]
name = "timestamp"
mandatory = true
[[object]]
name = "Gst.Tracer"
status = "generate"
[[object.function]]
name = "register"
# Manual implementation as inherent to the type.
ignore = true
[[object]]
name = "Gst.TracerFactory"
status = "generate"

View file

@ -14,6 +14,9 @@ use crate::PluginAPIFlags;
#[cfg(any(feature = "v1_12", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_12")))]
use crate::StackTraceFlags;
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
use crate::Tracer;
use glib::object::IsA;
use glib::translate::*;
use std::mem;
@ -236,17 +239,13 @@ pub fn parse_launchv(argv: &[&str]) -> Result<Element, glib::Error> {
}
}
//#[cfg(any(feature = "v1_18", feature = "dox"))]
//#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
//#[doc(alias = "gst_tracing_get_active_tracers")]
//pub fn tracing_get_active_tracers() -> /*Ignored*/Vec<Tracer> {
// unsafe { TODO: call ffi:gst_tracing_get_active_tracers() }
//}
//#[doc(alias = "gst_tracing_register_hook")]
//pub fn tracing_register_hook<P: FnOnce() + Send + Sync + 'static>(tracer: /*Ignored*/&Tracer, detail: &str, func: P) {
// unsafe { TODO: call ffi:gst_tracing_register_hook() }
//}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[doc(alias = "gst_tracing_get_active_tracers")]
pub fn tracing_get_active_tracers() -> Vec<Tracer> {
assert_initialized_main_thread!();
unsafe { FromGlibPtrContainer::from_glib_full(ffi::gst_tracing_get_active_tracers()) }
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]

View file

@ -98,6 +98,12 @@ pub use self::tag_setter::{TagSetter, NONE_TAG_SETTER};
mod toc_setter;
pub use self::toc_setter::{TocSetter, NONE_TOC_SETTER};
mod tracer;
pub use self::tracer::{Tracer, NONE_TRACER};
mod tracer_factory;
pub use self::tracer_factory::TracerFactory;
mod type_find_factory;
pub use self::type_find_factory::TypeFindFactory;
@ -219,5 +225,6 @@ pub mod traits {
pub use super::system_clock::SystemClockExt;
pub use super::tag_setter::TagSetterExt;
pub use super::toc_setter::TocSetterExt;
pub use super::tracer::TracerExt;
pub use super::uri_handler::URIHandlerExt;
}

View file

@ -0,0 +1,89 @@
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
// DO NOT EDIT
use crate::Object;
use glib::object::Cast;
use glib::object::IsA;
use glib::signal::connect_raw;
use glib::signal::SignalHandlerId;
use glib::translate::*;
use glib::StaticType;
use glib::ToValue;
use std::boxed::Box as Box_;
use std::mem::transmute;
glib::wrapper! {
#[doc(alias = "GstTracer")]
pub struct Tracer(Object<ffi::GstTracer, ffi::GstTracerClass>) @extends Object;
match fn {
type_ => || ffi::gst_tracer_get_type(),
}
}
unsafe impl Send for Tracer {}
unsafe impl Sync for Tracer {}
pub const NONE_TRACER: Option<&Tracer> = None;
pub trait TracerExt: 'static {
fn params(&self) -> Option<glib::GString>;
fn set_params(&self, params: Option<&str>);
#[doc(alias = "params")]
fn connect_params_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId;
}
impl<O: IsA<Tracer>> TracerExt for O {
fn params(&self) -> Option<glib::GString> {
unsafe {
let mut value = glib::Value::from_type(<glib::GString as StaticType>::static_type());
glib::gobject_ffi::g_object_get_property(
self.to_glib_none().0 as *mut glib::gobject_ffi::GObject,
b"params\0".as_ptr() as *const _,
value.to_glib_none_mut().0,
);
value
.get()
.expect("Return Value for property `params` getter")
}
}
fn set_params(&self, params: Option<&str>) {
unsafe {
glib::gobject_ffi::g_object_set_property(
self.to_glib_none().0 as *mut glib::gobject_ffi::GObject,
b"params\0".as_ptr() as *const _,
params.to_value().to_glib_none().0,
);
}
}
fn connect_params_notify<F: Fn(&Self) + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId {
unsafe extern "C" fn notify_params_trampoline<
P: IsA<Tracer>,
F: Fn(&P) + Send + Sync + 'static,
>(
this: *mut ffi::GstTracer,
_param_spec: glib::ffi::gpointer,
f: glib::ffi::gpointer,
) {
let f: &F = &*(f as *const F);
f(Tracer::from_glib_borrow(this).unsafe_cast_ref())
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"notify::params\0".as_ptr() as *const _,
Some(transmute::<_, unsafe extern "C" fn()>(
notify_params_trampoline::<Self, F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}

View file

@ -0,0 +1,41 @@
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
// DO NOT EDIT
use crate::Object;
use crate::PluginFeature;
use glib::translate::*;
glib::wrapper! {
#[doc(alias = "GstTracerFactory")]
pub struct TracerFactory(Object<ffi::GstTracerFactory, ffi::GstTracerFactoryClass>) @extends PluginFeature, Object;
match fn {
type_ => || ffi::gst_tracer_factory_get_type(),
}
}
impl TracerFactory {
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
#[doc(alias = "gst_tracer_factory_get_tracer_type")]
#[doc(alias = "get_tracer_type")]
pub fn tracer_type(&self) -> glib::types::Type {
unsafe {
from_glib(ffi::gst_tracer_factory_get_tracer_type(
self.to_glib_none().0,
))
}
}
#[doc(alias = "gst_tracer_factory_get_list")]
#[doc(alias = "get_list")]
pub fn list() -> Vec<TracerFactory> {
assert_initialized_main_thread!();
unsafe { FromGlibPtrContainer::from_glib_full(ffi::gst_tracer_factory_get_list()) }
}
}
unsafe impl Send for TracerFactory {}
unsafe impl Sync for TracerFactory {}

View file

@ -139,6 +139,8 @@ pub use self::allocation_params::AllocationParams;
mod element_factory_list_type;
pub use element_factory_list_type::*;
mod tracer;
// OS dependent Bus extensions (also import the other plateform mod for doc)
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]

View file

@ -21,6 +21,7 @@ mod element;
mod ghost_pad;
mod pad;
mod pipeline;
mod tracer;
mod device;
mod device_provider;
@ -54,5 +55,6 @@ pub mod prelude {
pub use super::preset::PresetImpl;
pub use super::system_clock::SystemClockImpl;
pub use super::tag_setter::TagSetterImpl;
pub use super::tracer::{TracerHook, TracerImpl, TracerImplExt};
pub use super::uri_handler::{URIHandlerImpl, URIHandlerImplExt};
}

View file

@ -0,0 +1,257 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use crate::ffi;
use crate::{
Bin, Buffer, BufferList, Element, Event, FlowReturn, Message, Object, Pad, PadLinkReturn,
Query, StateChange, StateChangeReturn, Tracer,
};
use glib::{prelude::*, subclass::prelude::*, translate::*};
#[allow(unused_variables)]
pub trait TracerImpl: TracerImplExt + ObjectImpl + Send + Sync {
fn bin_add_post(&self, ts: u64, bin: &Bin, element: &Element, success: bool) {}
fn bin_add_pre(&self, ts: u64, bin: &Bin, element: &Element) {}
fn bin_remove_post(&self, ts: u64, bin: &Bin, success: bool) {}
fn bin_remove_pre(&self, ts: u64, bin: &Bin, element: &Element) {}
fn element_add_pad(&self, ts: u64, element: &Element, pad: &Pad) {}
fn element_change_state_post(
&self,
ts: u64,
element: &Element,
change: StateChange,
result: StateChangeReturn,
) {
}
fn element_change_state_pre(&self, ts: u64, element: &Element, change: StateChange) {}
fn element_new(&self, ts: u64, element: &Element) {}
fn element_post_message_post(&self, ts: u64, element: &Element, success: bool) {}
fn element_post_message_pre(&self, ts: u64, element: &Element, message: &Message) {}
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) {}
fn object_created(&self, ts: u64, object: &Object) {}
/// Hook to be called after the GstObject has been finalized.
fn object_destroyed(&self, ts: u64, object: std::ptr::NonNull<ffi::GstObject>) {}
fn object_reffed(&self, ts: u64, object: &Object, new_refcount: i32) {}
fn object_unreffed(&self, ts: u64, object: &Object, new_refcount: i32) {}
fn pad_link_post(&self, ts: u64, src: &Pad, sink: &Pad, result: PadLinkReturn) {}
fn pad_link_pre(&self, ts: u64, src: &Pad, sink: &Pad) {}
fn pad_pull_range_post(&self, ts: u64, pad: &Pad, buffer: &Buffer, result: FlowReturn) {}
fn pad_pull_range_pre(&self, ts: u64, pad: &Pad, offset: u64, size: u32) {}
fn pad_push_event_post(&self, ts: u64, pad: &Pad, success: bool) {}
fn pad_push_event_pre(&self, ts: u64, pad: &Pad, event: &Event) {}
fn pad_push_list_post(&self, ts: u64, pad: &Pad, result: FlowReturn) {}
fn pad_push_list_pre(&self, ts: u64, pad: &Pad, buffer_list: &BufferList) {}
fn pad_push_post(&self, ts: u64, pad: &Pad, result: FlowReturn) {}
fn pad_push_pre(&self, ts: u64, pad: &Pad, buffer: &Buffer) {}
fn pad_query_post(&self, ts: u64, pad: &Pad, query: &Query, success: bool) {}
fn pad_query_pre(&self, ts: u64, pad: &Pad, query: &Query) {}
fn pad_unlink_post(&self, ts: u64, src: &Pad, sink: &Pad, success: bool) {}
fn pad_unlink_pre(&self, ts: u64, src: &Pad, sink: &Pad) {}
}
unsafe impl<T: TracerImpl> IsSubclassable<T> for Tracer {
fn class_init(klass: &mut glib::Class<Self>) {
<glib::Object as IsSubclassable<T>>::class_init(klass);
}
fn instance_init(instance: &mut glib::subclass::InitializingObject<T>) {
<glib::Object as IsSubclassable<T>>::instance_init(instance);
}
}
pub trait TracerImplExt: ObjectSubclass {
/// Register a corresponding hook to be called for this tracer when certain events occur.
///
/// Upon an event a corresponding method in `TracerImpl` will be called.
fn register_hook(&self, hook: TracerHook);
}
macro_rules! define_tracer_hooks {
($($name: ident($quark: literal) = |$this: ident, $ts: ident, $($cb_arg: ident: $cb_arg_ty: ty),*| $impl: block;)*) => {
pub enum TracerHook {
$($name),*
}
impl<T: TracerImpl> TracerImplExt for T {
fn register_hook(&self, hook: TracerHook) {
use TracerHook::*;
let (hook_type, callback) = match hook {
$($name => {
#[allow(non_snake_case)]
unsafe extern "C" fn callback<T: TracerImpl>(
$this: *mut ffi::GstTracer,
$ts: u64,
$($cb_arg: $cb_arg_ty),*
) {
let $this = Tracer::from_glib_borrow($this);
let $this = T::from_instance($this.unsafe_cast_ref());
$impl
}
(
concat!($quark, "\0"),
callback::<T> as unsafe extern "C" fn(_, _, $($cb_arg_ty),*) as *const ()
)
},)*
};
unsafe {
let instance = self.instance();
ffi::gst_tracing_register_hook(
instance.to_glib_none().0 as *mut ffi::GstTracer,
hook_type.as_ptr() as *const _,
Some(std::mem::transmute::<_, extern "C" fn()>(callback)),
);
}
}
}
};
}
define_tracer_hooks! {
BinAddPost("bin-add-post") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement, r: glib::ffi::gboolean| {
let b = Bin::from_glib_borrow(b);
let e = Element::from_glib_borrow(e);
this.bin_add_post(ts, &b, &e, bool::from_glib(r))
};
BinAddPre("bin-add-pre") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement| {
let b = Bin::from_glib_borrow(b);
let e = Element::from_glib_borrow(e);
this.bin_add_pre(ts, &b, &e)
};
BinRemovePost("bin-remove-post") = |this, ts, b: *mut ffi::GstBin, r: glib::ffi::gboolean| {
let b = Bin::from_glib_borrow(b);
this.bin_remove_post(ts, &b, bool::from_glib(r))
};
BinRemovePre("bin-remove-pre") = |this, ts, b: *mut ffi::GstBin, e: *mut ffi::GstElement| {
let b = Bin::from_glib_borrow(b);
let e = Element::from_glib_borrow(e);
this.bin_remove_pre(ts, &b, &e)
};
ElementAddPad("element-add-pad") = |this, ts, e: *mut ffi::GstElement, p: *mut ffi::GstPad| {
let e = Element::from_glib_borrow(e);
let p = Pad::from_glib_borrow(p);
this.element_add_pad(ts, &e, &p)
};
ElementChangeStatePost("element-change-state-post") = |this, ts, e: *mut ffi::GstElement, c: ffi::GstStateChange, r: ffi::GstStateChangeReturn| {
let e = Element::from_glib_borrow(e);
this.element_change_state_post(ts, &e, StateChange::from_glib(c), StateChangeReturn::from_glib(r))
};
ElementChangeStatePre("element-change-state-pre") = |this, ts, e: *mut ffi::GstElement, c: ffi::GstStateChange| {
let e = Element::from_glib_borrow(e);
this.element_change_state_pre(ts, &e, StateChange::from_glib(c))
};
ElementNew("element-new") = |this, ts, e: *mut ffi::GstElement| {
let e = Element::from_glib_borrow(e);
this.element_new(ts, &e)
};
ElementPostMessagePost("element-post-message-post") = |this, ts, e: *mut ffi::GstElement, r: glib::ffi::gboolean| {
let e = Element::from_glib_borrow(e);
this.element_post_message_post(ts, &e, bool::from_glib(r))
};
ElementPostMessagePre("element-post-message-pre") = |this, ts, e: *mut ffi::GstElement, m: *mut ffi::GstMessage| {
let e = Element::from_glib_borrow(e);
let m = Message::from_glib_borrow(m);
this.element_post_message_pre(ts, &e, &m)
};
ElementQueryPost("element-query-post") = |this, ts, e: *mut ffi::GstElement, q: *mut ffi::GstQuery, r: glib::ffi::gboolean| {
let e = Element::from_glib_borrow(e);
let q = Query::from_glib_borrow(q);
this.element_query_post(ts, &e, &q, bool::from_glib(r))
};
ElementQueryPre("element-query-pre") = |this, ts, e: *mut ffi::GstElement, q: *mut ffi::GstQuery| {
let e = Element::from_glib_borrow(e);
let q = Query::from_glib_borrow(q);
this.element_query_pre(ts, &e, &q)
};
ElementRemovePad("element-remove-pad") = |this, ts, e: *mut ffi::GstElement, p: *mut ffi::GstPad| {
let e = Element::from_glib_borrow(e);
let p = Pad::from_glib_borrow(p);
this.element_remove_pad(ts, &e, &p)
};
// TODO(#353): Missing bindings to `GstMiniObject`.
// MiniObjectCreated,
// MiniObjectDestroyed,
// MiniObjectReffed,
// MiniObjectUnreffed,
ObjectCreated("object-created") = |this, ts, o: *mut ffi::GstObject| {
let o = Object::from_glib_borrow(o);
this.object_created(ts, &o)
};
// TODO: unclear what to do here as the `GstObject` here is no longer valid…
ObjectDestroyed("object-destroyed") = |this, ts, o: *mut ffi::GstObject| {
this.object_destroyed(ts, std::ptr::NonNull::new_unchecked(o))
};
ObjectReffed("object-reffed") = |this, ts, o: *mut ffi::GstObject, rc: libc::c_int| {
let o = Object::from_glib_borrow(o);
this.object_reffed(ts, &o, rc as i32)
};
ObjectUnreffed("object-unreffed") = |this, ts, o: *mut ffi::GstObject, rc: libc::c_int| {
let o = Object::from_glib_borrow(o);
this.object_unreffed(ts, &o, rc as i32)
};
PadLinkPost("pad-link-post") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad, r: ffi::GstPadLinkReturn| {
let src = Pad::from_glib_borrow(src);
let sink = Pad::from_glib_borrow(sink);
this.pad_link_post(ts, &src, &sink, PadLinkReturn::from_glib(r))
};
PadLinkPre("pad-link-pre") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad| {
let src = Pad::from_glib_borrow(src);
let sink = Pad::from_glib_borrow(sink);
this.pad_link_pre(ts, &src, &sink)
};
PadPullRangePost("pad-pull-range-post") = |this, ts, p: *mut ffi::GstPad, b: *mut ffi::GstBuffer, r: ffi::GstFlowReturn| {
let p = Pad::from_glib_borrow(p);
let b = Buffer::from_glib_borrow(b);
this.pad_pull_range_post(ts, &p, &b, FlowReturn::from_glib(r))
};
PadPullRangePre("pad-pull-range-pre") = |this, ts, p: *mut ffi::GstPad, o: u64, s: libc::c_uint| {
let p = Pad::from_glib_borrow(p);
this.pad_pull_range_pre(ts, &p, o, s as u32)
};
PadPushEventPost("pad-push-event-post") = |this, ts, p: *mut ffi::GstPad, r: glib::ffi::gboolean| {
let p = Pad::from_glib_borrow(p);
this.pad_push_event_post(ts, &p, bool::from_glib(r))
};
PadPushEventPre("pad-push-event-pre") = |this, ts, p: *mut ffi::GstPad, e: *mut ffi::GstEvent| {
let p = Pad::from_glib_borrow(p);
let e = Event::from_glib_borrow(e);
this.pad_push_event_pre(ts, &p, &e)
};
PadPushListPost("pad-push-list-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
let p = Pad::from_glib_borrow(p);
this.pad_push_list_post(ts, &p, FlowReturn::from_glib(r))
};
PadPushListPre("pad-push-list-pre") = |this, ts, p: *mut ffi::GstPad, bl: *mut ffi::GstBufferList| {
let p = Pad::from_glib_borrow(p);
let bl = BufferList::from_glib_borrow(bl);
this.pad_push_list_pre(ts, &p, &bl)
};
PadPushPost("pad-push-post") = |this, ts, p: *mut ffi::GstPad, r: ffi::GstFlowReturn| {
let p = Pad::from_glib_borrow(p);
this.pad_push_post(ts, &p, FlowReturn::from_glib(r))
};
PadPushPre("pad-push-pre") = |this, ts, p: *mut ffi::GstPad, b: *mut ffi::GstBuffer| {
let p = Pad::from_glib_borrow(p);
let b = Buffer::from_glib_borrow(b);
this.pad_push_pre(ts, &p, &b)
};
PadQueryPost("pad-query-post") = |this, ts, p: *mut ffi::GstPad, q: *mut ffi::GstQuery, r: glib::ffi::gboolean| {
let p = Pad::from_glib_borrow(p);
let q = Query::from_glib_borrow(q);
this.pad_query_post(ts, &p, &q, bool::from_glib(r))
};
PadQueryPre("pad-query-pre") = |this, ts, p: *mut ffi::GstPad, q: *mut ffi::GstQuery| {
let p = Pad::from_glib_borrow(p);
let q = Query::from_glib_borrow(q);
this.pad_query_pre(ts, &p, &q)
};
PadUnlinkPost("pad-unlink-post") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad, r: glib::ffi::gboolean| {
let src = Pad::from_glib_borrow(src);
let sink = Pad::from_glib_borrow(sink);
this.pad_unlink_post(ts, &src, &sink, bool::from_glib(r))
};
PadUnlinkPre("pad-unlink-pre") = |this, ts, src: *mut ffi::GstPad, sink: *mut ffi::GstPad| {
let src = Pad::from_glib_borrow(src);
let sink = Pad::from_glib_borrow(sink);
this.pad_unlink_pre(ts, &src, &sink)
};
}

25
gstreamer/src/tracer.rs Normal file
View file

@ -0,0 +1,25 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use crate::{Plugin, Tracer};
use glib::translate::*;
impl Tracer {
#[doc(alias = "gst_tracer_register")]
pub fn register(
plugin: Option<&Plugin>,
name: &str,
type_: glib::types::Type,
) -> Result<(), glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
glib::result_from_gboolean!(
ffi::gst_tracer_register(
plugin.to_glib_none().0,
name.to_glib_none().0,
type_.into_glib()
),
"Failed to register tracer factory"
)
}
}
}

View file

@ -259,13 +259,6 @@ status = "generate"
name = "take"
version = "1.18.3"
[[object]]
name = "Gst.Tracer"
status = "generate"
[[object.function]]
name = "register"
version = "1.18"
[[object]]
name = "Gst.Uri"
status = "generate"

View file

@ -8542,8 +8542,6 @@ extern "C" {
// GstTracer
//=========================================================================
pub fn gst_tracer_get_type() -> GType;
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
pub fn gst_tracer_register(
plugin: *mut GstPlugin,
name: *const c_char,