use glib::object::Cast;
use gst::{
prelude::{GstBinExtManual, GstObjectExt as _},
DebugGraphDetails,
};
pub struct Params {
pub details: DebugGraphDetails,
pub index: bool,
}
impl Params {
#[must_use]
pub const fn all() -> Self {
Self {
details: DebugGraphDetails::ALL,
index: true,
}
}
#[must_use]
pub const fn states() -> Self {
Self {
details: DebugGraphDetails::STATES,
index: true,
}
}
}
impl Default for Params {
fn default() -> Self {
Self {
details: DebugGraphDetails::ALL,
index: true,
}
}
}
pub fn debug_dot(element: &impl glib::object::IsA<gst::Element>, filename_without_extension: &str) {
if log::max_level() >= log::Level::Debug {
dot(element, filename_without_extension);
}
}
pub fn dot(element: &impl glib::object::IsA<gst::Element>, filename_without_extension: &str) {
dot_ext(element, filename_without_extension, &Params::default());
}
pub fn dot_ext(
element: &impl glib::object::IsA<gst::Element>,
filename_without_extension: &str,
params: &Params,
) {
use std::sync::atomic::{AtomicUsize, Ordering};
static COUNT: AtomicUsize = AtomicUsize::new(0);
let Ok(path) = std::env::var("GST_DEBUG_DUMP_DOT_DIR") else {
return;
};
if let Err(e) = std::fs::create_dir_all(&path) {
error!(
"Generation of dot file failed: can not create dir from GST_DEBUG_DUMP_DOT_DIR: {e:?}"
);
return;
}
let Ok(object) = element.clone().dynamic_cast::<gst::Object>() else {
error!(
"Generation of dot file failed: unable to dynamic cast the `element` to 'gst::Object'"
);
return;
};
if let Some(parent) = object.parent() {
let Ok(element) = parent.dynamic_cast::<gst::Element>() else {
error!("Generation of dot file failed: unable to dynamic cast the `object` to 'gst::Element'");
return;
};
dot(&element, filename_without_extension);
return;
}
let name = if params.index {
let n = COUNT.fetch_add(1, Ordering::SeqCst);
let r = format!("{n}-{filename_without_extension}");
r
} else {
filename_without_extension.to_string()
};
info!("GENERATING DOT FILE: '{path}/{name}.dot'");
let Ok(bin) = Cast::dynamic_cast::<gst::Bin>(element.clone()) else {
error!("Generation of dot file failed: unable to cast element to bin");
return;
};
bin.debug_to_dot_file(params.details, name);
}
pub fn name(object: &impl glib::object::IsA<gst::Object>) -> glib::GString {
if let Some(parent) = object.parent() {
format!("{}.{}", name(&parent), object.name()).into()
} else {
object.name()
}
}