wip: print properties

This commit is contained in:
Fabian Orccon 2023-06-18 12:01:20 +02:00
parent 15d17ded1a
commit 62025d5e56

View file

@ -20,6 +20,7 @@
// DEALINGS IN THE SOFTWARE.
use ansi_term::Color;
use clap::{Arg, Command};
use gst::glib;
use gst::prelude::*;
const BRBLUE: Color = Color::RGB(97, 127, 166);
@ -35,7 +36,9 @@ const STRUCT_NAME_COLOR: Color = Color::Yellow;
const CAPS_FEATURE_COLOR: Color = Color::Green;
const FIELD_VALUE_COLOR: Color = BRBLUE;
const FIELD_NAME_COLOR: Color = Color::Cyan;
const PROP_ATTR_NAME_COLOR: Color = Color::Yellow;
const PROP_ATTR_VALUE_COLOR: Color = Color::Cyan;
const DATATYPE_COLOR: Color = Color::Green;
fn print_element_list() {
let registry = gst::Registry::get();
@ -107,9 +110,9 @@ fn print_plugin_info(plugin: &gst::Plugin) {
println!();
}
fn hierarchy_foreach<F>(type_: gst::glib::Type, foreach_func: &mut F)
fn hierarchy_foreach<F>(type_: glib::Type, foreach_func: &mut F)
where
F: FnMut(gst::glib::Type),
F: FnMut(glib::Type),
{
if let Some(parent) = type_.parent() {
hierarchy_foreach(parent, foreach_func);
@ -118,9 +121,9 @@ where
foreach_func(type_);
}
fn print_hierarchy(type_: gst::glib::Type) {
fn print_hierarchy(type_: glib::Type) {
let mut level = 0;
let mut func = |cur_type: gst::glib::Type| {
let mut func = |cur_type: glib::Type| {
if level > 0 {
print!("{}", " ".repeat(level - 1));
print!(" {}", CHILD_LINK_COLOR.paint("+----"));
@ -133,7 +136,7 @@ fn print_hierarchy(type_: gst::glib::Type) {
println!();
}
fn print_interfaces(type_: gst::glib::Type) {
fn print_interfaces(type_: glib::Type) {
let interfaces = type_.interfaces();
if interfaces.is_empty() {
return;
@ -316,6 +319,177 @@ fn print_pad_info(element: &gst::Element) {
}
}
fn print_pspec_flags(pspec: &glib::ParamSpec, indent: usize) {
let flags_to_string = [
(glib::ParamFlags::READABLE, "writable"),
(glib::ParamFlags::WRITABLE, "readable"),
(glib::ParamFlags::DEPRECATED, "deprecated"),
(gst::PARAM_FLAG_CONTROLLABLE, "controllable"),
(gst::PARAM_FLAG_CONDITIONALLY_AVAILABLE, "conditionally available"),
(gst::PARAM_FLAG_MUTABLE_PLAYING, "changeable in NULL, READY, PAUSED or PLAYING state"),
(gst::PARAM_FLAG_MUTABLE_PAUSED, "changeable only in NULL, READY or PAUSED state"),
(gst::PARAM_FLAG_MUTABLE_READY, "changeable only in NULL or READY state"),
// TODO: ~KNOWN_PARAM_FLAGS
];
let flags = pspec.flags();
print!("{:indent$}{}: ", "", PROP_ATTR_NAME_COLOR.paint("flags"), indent = indent);
let mut first_flag = true;
for (flag, string) in flags_to_string.iter() {
if !flags.contains(*flag) {
continue;
}
if !first_flag {
print!(", ")
}
print!("{}", PROP_ATTR_VALUE_COLOR.paint(*string));
first_flag = false;
}
println!();
}
fn print_default_prop(title: &str, range: Option<(String, String)>, default: &str, indent: usize) {
print!("{:indent$}: ", "", indent = indent);
print!("{}.", DATATYPE_COLOR.paint(title));
if let Some((min, max)) = range {
print!("{}: {} - {}",
PROP_ATTR_NAME_COLOR.paint("Range"),
PROP_ATTR_VALUE_COLOR.paint(min.to_string()),
PROP_ATTR_VALUE_COLOR.paint(max.to_string()),
);
}
print!(" ");
print!("{}: {}", PROP_ATTR_NAME_COLOR.paint("Default"),
PROP_ATTR_VALUE_COLOR.paint(default.to_string()));
}
fn print_default_property_value(element: &gst::Element, pspec: &glib::ParamSpec, readable: bool, indent: usize) {
let value : glib::Value = if readable {
element.property::<glib::Value>(&pspec.name())
} else {
pspec.default_value().clone()
};
match value.type_() {
glib::types::Type::STRING => {
let default = match value.get::<Option<&str>>() {
Ok(Some(val)) => format!("\"{}\"", val),
_ => "null".to_string(),
};
print_default_prop("String", None, &default, indent);
},
glib::types::Type::BOOL => {
let default = value.get::<bool>().unwrap().to_string();
print_default_prop("Boolean", None, &default, indent);
},
glib::types::Type::I_LONG => {
let default = value.get::<i64>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecLong>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Long", range, &default, indent);
},
glib::types::Type::U_LONG => {
let default = value.get::<u64>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecULong>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Unsigned Long", range, &default, indent);
},
glib::types::Type::U32 => {
let default = value.get::<u32>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecUInt>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Unsigned Integer", range, &default, indent);
},
glib::types::Type::I32 => {
let default = value.get::<i32>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecInt>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Integer", range, &default, indent);
},
glib::types::Type::U64 => {
let default = value.get::<u64>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecUInt64>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Unsigned Integer64", range, &default, indent);
},
glib::types::Type::I64 => {
let default = value.get::<i64>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecInt64>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Integer64", range, &default, indent);
},
glib::types::Type::F32 => {
let default = value.get::<f32>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecFloat>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Float", range, &default, indent);
},
glib::types::Type::F64 => {
let default = value.get::<f64>().unwrap().to_string();
let pspec = pspec.downcast_ref::<glib::ParamSpecDouble>().unwrap();
let range = Some((pspec.minimum().to_string(), pspec.maximum().to_string()));
print_default_prop("Double", range, &default, indent);
},
typ if typ.is_a(glib::types::Type::ENUM) => {
let val = value.get::<&glib::EnumValue>().unwrap();
let pspec = pspec.downcast_ref::<glib::ParamSpecEnum>().unwrap();
let default = format!("{}, \"{}\"", val.value(), val.nick());
let title = format!("Enum \"{}\"", value.type_().name());
print_default_prop(&title, None, &default, indent);
for (i, enum_val) in pspec.enum_class().to_owned().values().iter().enumerate() {
println!();
print!("{}", " ".repeat(2 + 20 + 1 + 1));
print!("{}: {} - {}",
PROP_ATTR_NAME_COLOR.paint(&format!("({})", i)),
PROP_ATTR_VALUE_COLOR.paint(&format!("{:<16}", enum_val.nick())),
enum_val.name()
);
}
},
typ if typ.is_a(glib::types::Type::FLAGS) => {
// TODO
},
typ if typ.is_a(gst::Caps::static_type()) => {
match value.get::<Option<&gst::Caps>>() {
Ok(Some(val)) => print_caps(val), // test with uridecodebin, "caps" property.
_ => println!("Caps (NULL)"),
}
}
_ => (),
}
println!()
}
fn print_element_properties(element: &gst::Element) {
let mut property_specs = element.list_properties();
property_specs.sort_by_key(|pspec| pspec.name());
println!("{}:", HEADING_COLOR.paint("Element Properties"));
println!();
for pspec in property_specs {
let owner_type = pspec.owner_type();
if owner_type == glib::types::Type::OBJECT
|| owner_type == gst::Object::static_type()
|| owner_type == gst::Pad::static_type()
{
continue;
}
print_property(pspec.name(), &pspec.blurb().unwrap(), 20, 2, true);
print_pspec_flags(&pspec, 2 + 20 + 1 + 1);
let readable = pspec.flags().contains(glib::ParamFlags::READABLE);
print_default_property_value(element, &pspec, readable, 20 + 1 + 1);
}
}
fn print_element_info(feature: &gst::PluginFeature) -> Result<(), String> {
let Ok(factory) = feature.load() else {
return Err(format!("element factory '{}' couldn't be loaded", feature.name()));
@ -341,6 +515,7 @@ fn print_element_info(feature: &gst::PluginFeature) -> Result<(), String> {
print_clocking_info(&element);
print_uri_handler_info(&element);
print_pad_info(&element);
print_element_properties(&element);
Ok(())
}