GPS: add GST render to parse launch format

The player is able to take the graph description and
build a string which will be passed to the
GStreamer parse launch engine.
This commit is contained in:
Stéphane Cerveau 2021-12-03 17:30:13 +01:00
parent f1149a6b5e
commit 6397ebff74
3 changed files with 89 additions and 27 deletions

View file

@ -141,31 +141,35 @@ mod imp {
.expect("click event has no widget") .expect("click event has no widget")
.dynamic_cast::<Self::Type>() .dynamic_cast::<Self::Type>()
.expect("click event is not on the GraphView"); .expect("click event is not on the GraphView");
if let Some(target) = widget.pick(x, y, gtk::PickFlags::DEFAULT) {
if let Some(target) = widget.pick(x, y, gtk::PickFlags::DEFAULT) { if let Some(target) = target.ancestor(Port::static_type()) {
if let Some(target) = target.ancestor(Port::static_type()) { let mut port_to = target.dynamic_cast::<Port>().expect("click event is not on the Port");
let to_port = target.dynamic_cast::<Port>().expect("click event is not on the Port"); if widget.port_is_linked(port_to.id()).is_none() {
if let None = widget.port_is_linked(to_port.id()) { let selected_port = widget.selected_port().to_owned();
let selected_port = widget.selected_port().to_owned(); if let Some(mut port_from) = selected_port {
if let Some(from_port) = selected_port { println!("Port {} is clicked at {}:{}", port_to.id(), x, y);
println!("Port {} is clicked at {}:{}", to_port.id(), x, y); if widget.ports_compatible(&port_to) {
if widget.ports_compatible(&to_port) { let mut node_from = port_from.ancestor(Node::static_type()).expect("Unable to reach parent").dynamic_cast::<Node>().expect("Unable to cast to Node");
let from_node = from_port.ancestor(Node::static_type()).expect("Unable to reach parent").dynamic_cast::<Node>().expect("Unable to cast to Node"); let mut node_to = port_to.ancestor(Node::static_type()).expect("Unable to reach parent").dynamic_cast::<Node>().expect("Unable to cast to Node");
let to_node = to_port.ancestor(Node::static_type()).expect("Unable to reach parent").dynamic_cast::<Node>().expect("Unable to cast to Node"); println!("add link");
println!("add link"); if *port_to.direction() == PortDirection::Output {
widget.add_link(NodeLink { println!("swap ports and nodes to create the link");
id: widget.next_link_id(), std::mem::swap(&mut node_from, &mut node_to);
node_from: from_node.id(), std::mem::swap(&mut port_from, &mut port_to);
node_to: to_node.id(), }
port_from: from_port.id(), widget.add_link(NodeLink {
port_to: to_port.id(), id: widget.next_link_id(),
active: true node_from: node_from.id(),
} ); node_to: node_to.id(),
} port_from: port_from.id(),
port_to: port_to.id(),
active: true
} );
}
widget.set_selected_port(None); widget.set_selected_port(None);
} else { } else {
println!("add selected port id"); println!("add selected port id");
widget.set_selected_port(Some(&to_port)); widget.set_selected_port(Some(&port_to));
} }
} }
} }
@ -362,16 +366,22 @@ impl GraphView {
} }
self.queue_draw(); self.queue_draw();
} }
pub fn all_nodes(&self) -> Vec<Node> { pub fn all_nodes(&self, node_type: NodeType) -> Vec<Node> {
let private = imp::GraphView::from_instance(self); let private = imp::GraphView::from_instance(self);
let nodes = private.nodes.borrow(); let nodes = private.nodes.borrow();
let nodes_list: Vec<_> = nodes.iter().map(|(_, node)| node.clone()).collect(); let nodes_list: Vec<_> = nodes
.iter()
.filter(|(_, node)| {
*node.node_type().unwrap() == node_type || node_type == NodeType::All
})
.map(|(_, node)| node.clone())
.collect();
nodes_list nodes_list
} }
pub fn remove_all_nodes(&self) { pub fn remove_all_nodes(&self) {
let private = imp::GraphView::from_instance(self); let private = imp::GraphView::from_instance(self);
let nodes_list = self.all_nodes(); let nodes_list = self.all_nodes(NodeType::All);
for node in nodes_list { for node in nodes_list {
if let Some(link_id) = self.node_is_linked(node.id()) { if let Some(link_id) = self.node_is_linked(node.id()) {
let mut links = private.links.borrow_mut(); let mut links = private.links.borrow_mut();
@ -581,9 +591,48 @@ impl GraphView {
private.port_selected.borrow_mut() private.port_selected.borrow_mut()
} }
pub fn port_connected_to(&self, port_id: u32) -> Option<(u32, u32)> {
for link in self.all_links() {
if port_id == link.port_from {
return Some((link.port_to, link.node_to));
}
}
None
}
// * filesrc location=obama_last_speech.mp4 ! decodebin name=bin bin. ! audioconvert ! audioresample ! autoaudiosink bin. ! autovideosink
// Render graph methods // Render graph methods
//TO BE MOVED
pub fn process_node(&self, node: &Node, mut description: String) -> String {
let private = imp::GraphView::from_instance(self);
let unique_name = node.unique_name();
description.push_str(&format!("{} name={}", node.name(), unique_name));
let ports = node.all_ports(PortDirection::Output);
if ports.len() > 1 {
description.push_str(&format!(" {}. ! ", unique_name));
} else if ports.len() > 0 {
description.push_str(" ! ");
}
println!("{}", description);
for port in ports {
if let Some((_port_to, node_to)) = self.port_connected_to(port.id()) {
if let Some(node) = private.nodes.borrow().get(&node_to) {
description = self.process_node(node, description.clone());
}
}
}
description
}
//TO BE MOVED
pub fn render_gst(&self) -> String { pub fn render_gst(&self) -> String {
let description = String::from("videotestsrc ! videoconvert ! autovideosink"); let nodes = self.all_nodes(NodeType::Source);
let mut description = String::from("");
for node in nodes {
description = self.process_node(&node, description.clone());
}
description description
} }
@ -596,7 +645,7 @@ impl GraphView {
writer.write(XMLWEvent::start_element("Graph"))?; writer.write(XMLWEvent::start_element("Graph"))?;
//Get the nodes //Get the nodes
let nodes = self.all_nodes(); let nodes = self.all_nodes(NodeType::All);
for node in nodes { for node in nodes {
writer.write( writer.write(
XMLWEvent::start_element("Node") XMLWEvent::start_element("Node")

View file

@ -165,6 +165,17 @@ impl Node {
let private = imp::Node::from_instance(self); let private = imp::Node::from_instance(self);
private.ports.borrow() private.ports.borrow()
} }
pub fn all_ports(&self, direction: PortDirection) -> Vec<Port> {
let ports_list: Vec<_> = self
.ports()
.iter()
.filter(|(_, port)| *port.direction() == direction || direction == PortDirection::All)
.map(|(_, port)| port.clone())
.collect();
ports_list
}
pub fn port(&self, id: &u32) -> Option<super::port::Port> { pub fn port(&self, id: &u32) -> Option<super::port::Port> {
let private = imp::Node::from_instance(self); let private = imp::Node::from_instance(self);
private.ports.borrow().get(id).cloned() private.ports.borrow().get(id).cloned()

View file

@ -28,6 +28,7 @@ use std::fmt;
pub enum PortDirection { pub enum PortDirection {
Input, Input,
Output, Output,
All,
Unknown, Unknown,
} }
@ -44,6 +45,7 @@ impl PortDirection {
match port_direction_name { match port_direction_name {
"Input" => PortDirection::Input, "Input" => PortDirection::Input,
"Output" => PortDirection::Output, "Output" => PortDirection::Output,
"All" => PortDirection::Output,
_ => PortDirection::Unknown, _ => PortDirection::Unknown,
} }
} }