GstPipelineStudio/src/pipeline.rs
Stéphane Cerveau 5f91fbaef7 GPS: introduce the graphmanager
Introduce the first version of a graph manager
with:
- Graphview
- Node
- Port
2022-01-11 20:48:53 +01:00

198 lines
6.9 KiB
Rust

// pipeline.rs
//
// Copyright 2021 Stéphane Cerveau <scerveau@collabora.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0-only
use crate::graphmanager::NodeType;
use gst::prelude::*;
use gstreamer as gst;
use std::error;
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct ElementInfo {
pub name: Option<String>,
plugin_name: Option<String>,
rank: i32,
}
impl Default for ElementInfo {
fn default() -> ElementInfo {
ElementInfo {
name: None,
plugin_name: None,
rank: -1,
}
}
}
#[derive(Debug)]
pub struct Pipeline {
initialized: bool,
}
impl Default for Pipeline {
fn default() -> Pipeline {
Pipeline { initialized: false }
}
}
impl Pipeline {
pub fn new() -> Result<Self, Box<dyn error::Error>> {
gst::init()?;
Ok(Self { initialized: true })
}
pub fn elements_list() -> Result<Vec<ElementInfo>, Box<dyn error::Error>> {
let registry = gst::Registry::get();
let mut elements: Vec<ElementInfo> = Vec::new();
let plugins = gst::Registry::get_plugin_list(&registry);
for plugin in plugins {
let plugin_name = gst::Plugin::get_plugin_name(&plugin);
let features = gst::Registry::get_feature_list_by_plugin(&registry, &plugin_name);
for feature in features {
let mut element = ElementInfo::default();
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
let feature = factory.upcast::<gst::PluginFeature>();
element.name = Some(gst::PluginFeature::get_name(&feature).as_str().to_owned());
element.plugin_name =
Some(gst::Plugin::get_plugin_name(&plugin).as_str().to_owned());
elements.push(element);
}
}
}
elements.sort();
Ok(elements)
}
pub fn element_feature(
element_name: &str,
) -> anyhow::Result<gst::PluginFeature, Box<dyn error::Error>> {
let registry = gst::Registry::get();
let feature = gst::Registry::find_feature(
&registry,
element_name,
gst::ElementFactory::static_type(),
)
.expect("Unable to find the element name");
Ok(feature)
}
pub fn element_description(
element_name: &str,
) -> anyhow::Result<String, Box<dyn error::Error>> {
let mut desc = String::from("");
let feature = Pipeline::element_feature(element_name)?;
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
desc.push_str("<b>Factory details:</b>\n");
desc.push_str("<b>Name:</b>");
desc.push_str(&factory.get_name());
desc.push('\n');
let element_keys = factory.get_metadata_keys();
for key in element_keys {
let val = factory.get_metadata(&key);
if let Some(val) = val {
desc.push_str("<b>");
desc.push_str(&key);
desc.push_str("</b>:");
desc.push_str(&gtk::glib::markup_escape_text(&val).to_string());
desc.push('\n');
}
}
let feature = factory.upcast::<gst::PluginFeature>();
let plugin = gst::PluginFeature::get_plugin(&feature);
if let Some(plugin) = plugin {
desc.push('\n');
desc.push_str("<b>Plugin details:</b>");
desc.push('\n');
desc.push_str("<b>Name:");
desc.push_str("</b>");
desc.push_str(gst::Plugin::get_plugin_name(&plugin).as_str());
desc.push('\n');
desc.push_str("<b>Description:");
desc.push_str("</b>");
desc.push_str(
&gtk::glib::markup_escape_text(&plugin.get_description()).to_string(),
);
desc.push('\n');
desc.push_str("<b>Filename:");
desc.push_str("</b>");
desc.push_str(
&gtk::glib::markup_escape_text(
&plugin
.get_filename()
.unwrap()
.as_path()
.display()
.to_string(),
)
.to_string(),
);
desc.push('\n');
desc.push_str("<b>Version:");
desc.push_str("</b>");
desc.push_str(&gtk::glib::markup_escape_text(&plugin.get_version()).to_string());
desc.push('\n');
}
}
Ok(desc)
}
pub fn get_pads(element_name: &str, include_on_request: bool) -> (u32, u32) {
let feature = Pipeline::element_feature(element_name).expect("Unable to get feature");
let mut input = 0;
let mut output = 0;
if let Ok(factory) = feature.downcast::<gst::ElementFactory>() {
if factory.get_num_pad_templates() > 0 {
let pads = factory.get_static_pad_templates();
for pad in pads {
if pad.presence() == gst::PadPresence::Always
|| (include_on_request
&& (pad.presence() == gst::PadPresence::Request
|| pad.presence() == gst::PadPresence::Sometimes))
{
if pad.direction() == gst::PadDirection::Src {
output += 1;
} else if pad.direction() == gst::PadDirection::Sink {
input += 1;
}
}
}
}
}
(input, output)
}
pub fn get_element_type(element_name: &str) -> NodeType {
let pads = Pipeline::get_pads(element_name, true);
let mut element_type = NodeType::Source;
if pads.0 > 0 {
if pads.1 > 0 {
element_type = NodeType::Transform;
} else {
element_type = NodeType::Sink;
}
} else if pads.1 > 0 {
element_type = NodeType::Source;
}
element_type
}
}