...
 
Commits (13)
......@@ -17,4 +17,5 @@ members = [
"gstreamer-editing-services",
"examples",
"tutorials",
"tools",
]
......@@ -61,6 +61,7 @@ generate = [
"Gst.ParseFlags",
"Gst.TaskState",
"Gst.PluginDependencyFlags",
"Gst.PluginFlags",
"Gst.DateTime",
"Gst.BufferPoolAcquireFlags",
"Gst.PromiseResult",
......@@ -822,6 +823,7 @@ trait = false
name = "get_name"
[object.function.return]
nullable = false
ignore = true
[[object.function]]
name = "get_license"
......
......@@ -569,6 +569,54 @@ impl SetValue for PluginDependencyFlags {
}
}
bitflags! {
pub struct PluginFlags: u32 {
const CACHED = 16;
const BLACKLISTED = 32;
}
}
#[doc(hidden)]
impl ToGlib for PluginFlags {
type GlibType = ffi::GstPluginFlags;
fn to_glib(&self) -> ffi::GstPluginFlags {
self.bits()
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstPluginFlags> for PluginFlags {
fn from_glib(value: ffi::GstPluginFlags) -> PluginFlags {
skip_assert_initialized!();
PluginFlags::from_bits_truncate(value)
}
}
impl StaticType for PluginFlags {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_plugin_flags_get_type()) }
}
}
impl<'a> FromValueOptional<'a> for PluginFlags {
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
Some(FromValue::from_value(value))
}
}
impl<'a> FromValue<'a> for PluginFlags {
unsafe fn from_value(value: &Value) -> Self {
from_glib(gobject_ffi::g_value_get_flags(value.to_glib_none().0))
}
}
impl SetValue for PluginFlags {
unsafe fn set_value(value: &mut Value, this: &Self) {
gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib())
}
}
bitflags! {
pub struct SchedulingFlags: u32 {
const SEEKABLE = 1;
......
......@@ -164,6 +164,7 @@ pub use self::flags::PadLinkCheck;
pub use self::flags::PadProbeType;
pub use self::flags::ParseFlags;
pub use self::flags::PluginDependencyFlags;
pub use self::flags::PluginFlags;
pub use self::flags::SchedulingFlags;
pub use self::flags::SeekFlags;
pub use self::flags::SegmentFlags;
......
Generated by gir (https://github.com/gtk-rs/gir @ b5ea065)
Generated by gir (https://github.com/gtk-rs/gir @ 6f103f8)
from gir-files (https://github.com/gtk-rs/gir-files @ ???)
......@@ -25,6 +25,10 @@ impl Plugin {
}
}
pub fn get_plugin_name(&self) -> String {
unsafe { from_glib_none(ffi::gst_plugin_get_name(self.to_glib_none().0)) }
}
pub fn set_cache_data(&self, cache_data: Structure) {
unsafe {
ffi::gst_plugin_set_cache_data(self.to_glib_none().0, cache_data.into_ptr());
......
[package]
name = "tools"
version = "0.12.0"
authors = ["Zeeshan Ali <zeeshanak@gnome.org>"]
[dependencies]
glib = { git = "https://github.com/gtk-rs/glib" }
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gstreamer = { path = "../gstreamer" }
gstreamer-sys = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys" }
nix = { version = "0.11.0", optional = true }
colored = { version = "1.6.1", optional = true }
[features]
default = ["gst-inspect"]
gst-inspect = ["nix", "colored"]
[[bin]]
name = "gst-inspect"
path = "src/gst-inspect.rs"
required-features = ["gst-inspect"]
extern crate gstreamer as gst;
extern crate gstreamer_sys as gst_ffi;
use gst::prelude::*;
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate colored;
extern crate nix;
use colored::{ColoredString, Colorize};
mod piped_stdio;
fn main() {
let _piped = if cfg!(unix) {
match piped_stdio::PipedStdio::new() {
Ok(p) => Some(p),
Err(e) => {
print_error(e, "Error redirecting output to pager");
None
}
}
} else {
None
};
if let Err(e) = gst::init() {
print_error(e, "Error initializing GStreamer");
std::process::exit(-1);
}
// FIXME: Fetch `print_all` value from cmdline param
print_element_list(false);
}
fn print_error<E: std::error::Error>(error: E, description: &str) {
eprintln!(
"{}",
format!("{}: {}", description, error.to_string()).red()
);
}
fn print_element_list(print_all: bool) {
let registry = gst::Registry::get();
let plugins = registry.get_plugin_list();
let mut n_blacklisted = 0;
let mut n_features = 0;
for ref plugin in &plugins {
if get_plugin_flags(&plugin).contains(gst::PluginFlags::BLACKLISTED) {
n_blacklisted = n_blacklisted + 1;
continue;
}
let name = plugin.get_plugin_name();
for feature in registry.get_feature_list_by_plugin(&name) {
n_features = n_features + 1;
if let Some(factory) = feature.downcast_ref::<gst::ElementFactory>() {
if print_all {
print_element_info(&feature, true);
} else if let Some(metadata) = factory.get_metadata(&gst::ELEMENT_METADATA_LONGNAME)
{
println!(
"{}: {}: {}",
plugin_name_color(&name),
element_name_color(&factory.get_name()),
element_detail_color(&metadata)
);
}
} else if let Some(factory) = feature.downcast_ref::<gst::TypeFindFactory>() {
if print_all {
continue;
}
print!(
"{}: {}: ",
plugin_name_color(&name),
element_name_color(&factory.get_name())
);
let extensions = factory.get_extensions();
if extensions.len() != 0 {
let mut i = 0;
for extension in extensions {
if i != 0 {
print!(", ");
}
print!("{}", element_detail_color(&extension));
i = i + 1;
}
println!("");
} else {
println!("{}", element_detail_color("no extensions"));
}
} else {
if !print_all {
println!(
"{}: {}: {}",
plugin_name_color(&name),
element_name_color(&feature.get_name()),
element_detail_color(&feature.get_type().to_string())
);
}
}
}
}
print!(
"\n{}: {}",
prop_name_color("Total count"),
prop_value_color(&format!("{} plugins", plugins.len()))
);
if n_blacklisted != 0 {
print!(
"{}",
prop_value_color(&format!(
" ({} blacklisted {} not shown)",
n_blacklisted,
if n_blacklisted > 1 {
"entries"
} else {
"entry"
}
))
);
}
println!(
", {}",
prop_value_color(&format!(
"{} {}",
n_features,
if n_features > 1 {
"features"
} else {
"feature"
}
))
);
}
fn print_element_info(_feature: &gst::PluginFeature, _print_names: bool) {
// FIXME: Implement.
}
fn prop_name_color(name: &str) -> ColoredString {
name.cyan()
}
fn prop_value_color(value: &str) -> ColoredString {
value.bright_blue()
}
fn plugin_name_color(name: &str) -> ColoredString {
name.blue()
}
fn element_name_color(name: &str) -> ColoredString {
name.green()
}
fn element_detail_color(detail: &str) -> ColoredString {
detail.white().dimmed()
}
fn get_plugin_flags(plugin: &gst::Plugin) -> gst::PluginFlags {
unsafe {
use glib::translate::{from_glib, ToGlibPtr};
use gst_ffi;
let ptr: *mut gst_ffi::GstObject = plugin.to_glib_none().0;
return from_glib((*ptr).flags);
}
}
use nix::unistd::dup2;
use std::env;
use std::ffi::OsString;
use std::fs::File;
use std::io::{stderr, stdin, stdout, Error, ErrorKind, Result, Write};
use std::os::unix::prelude::*;
use std::process::{Child, Command, Stdio};
const DEFAULT_PAGER: &'static str = "less -FR";
pub struct PipedStdio {
pager: Child,
}
impl PipedStdio {
pub fn new() -> Result<Self> {
let cmdline = env::var_os("PAGER").unwrap_or(OsString::from(DEFAULT_PAGER));
let mut cmd: Vec<&str> = cmdline.to_str().unwrap().split(" ").collect();
let mut pager = Command::new(OsString::from(cmd.remove(0)))
.stdin(Stdio::piped())
.args(cmd)
.spawn()?;
let child_stdin = pager.stdin.take().unwrap(); // Can't fail
// Redirect our stdout/stderr to the `pager` child process
dup2(child_stdin.as_raw_fd(), stdout().as_raw_fd())
.map_err(|e| Error::new(ErrorKind::Other, e))?;
dup2(child_stdin.as_raw_fd(), stderr().as_raw_fd())
.map_err(|e| Error::new(ErrorKind::Other, e))?;
Ok(PipedStdio { pager })
}
}
impl Drop for PipedStdio {
fn drop(&mut self) {
stdout().flush().ok();
stderr().flush().ok();
match File::open("/dev/null") {
Ok(null) => {
// "close" stdio streams now that our program is done
dup2(null.as_raw_fd(), stdin().as_raw_fd()).ok();
dup2(null.as_raw_fd(), stdout().as_raw_fd()).ok();
dup2(null.as_raw_fd(), stderr().as_raw_fd()).ok();
}
Err(e) => eprintln!("{}", e),
}
if let Err(e) = self.pager.wait() {
eprintln!("{}", e);
}
}
}