GPSApp: Can now request pads on element

Add menu entries to add new pad/port to an element/node.
This commit is contained in:
Stéphane Cerveau 2021-12-10 15:26:18 +01:00
parent 6756b34919
commit 7d08abaca8
6 changed files with 70 additions and 38 deletions

View file

@ -19,6 +19,9 @@ TODO:
- [x] Run the pipeline with GStreamer - [x] Run the pipeline with GStreamer
- [x] Control the pipeline with GStreamer - [x] Control the pipeline with GStreamer
- [x] Define the license - [x] Define the license
- [] check that that a node accept to create a port on request (input/output)
- [] select nodes/links with a Trait Selectable
- [] be able to remove a link by selecting it
- [] Connect the logs to the window - [] Connect the logs to the window
- [] Create a window for the video output - [] Create a window for the video output
- [] Add multiple graphviews with tabs. - [] Add multiple graphviews with tabs.
@ -27,6 +30,7 @@ TODO:
- [] crash with x11 on contextual menu - [] crash with x11 on contextual menu
- [] check that element exists before creating it on file load. - [] check that element exists before creating it on file load.
- [] open multiple times dialog (About) prevent to close it.
## Code cleanup ## Code cleanup

View file

@ -32,7 +32,7 @@ use std::{error, ops};
use crate::pipeline::{Pipeline, PipelineState}; use crate::pipeline::{Pipeline, PipelineState};
use crate::plugindialogs; use crate::plugindialogs;
use crate::graphmanager::{GraphView, Node}; use crate::graphmanager::{GraphView, Node, PortDirection};
#[derive(Debug)] #[derive(Debug)]
pub struct GPSAppInner { pub struct GPSAppInner {
@ -419,13 +419,30 @@ impl GPSApp {
})); }));
application.add_action(&action); application.add_action(&action);
let action = gio::SimpleAction::new("node.request-pad", None); let action = gio::SimpleAction::new("node.request-pad-input", None);
let app_weak = app.downgrade();
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| { action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
println!("node.request-pad {}", node_id); let app = upgrade_weak!(app_weak);
println!("node.request-pad-input {}", node_id);
let mut node = app.graphview.borrow_mut().node(&node_id).unwrap();
let port_id = app.graphview.borrow().next_port_id();
node.add_port(port_id, "in", PortDirection::Input);
pop_menu.unparent(); pop_menu.unparent();
})); }));
application.add_action(&action); application.add_action(&action);
let action = gio::SimpleAction::new("node.request-pad-output", None);
let app_weak = app.downgrade();
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
let app = upgrade_weak!(app_weak);
println!("node.request-pad-output {}", node_id);
let mut node = app.graphview.borrow_mut().node(&node_id).unwrap();
let port_id = app.graphview.borrow().next_port_id();
node.add_port(port_id, "out", PortDirection::Output);
pop_menu.unparent();
}));
application.add_action(&action);
let action = gio::SimpleAction::new("node.properties", None); let action = gio::SimpleAction::new("node.properties", None);
action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| { action.connect_activate(glib::clone!(@weak pop_menu => move |_,_| {
println!("node.properties {}", node_id); println!("node.properties {}", node_id);

View file

@ -43,11 +43,19 @@
<attribute name="action">app.node.delete</attribute> <attribute name="action">app.node.delete</attribute>
<attribute name="accel">&lt;primary&gt;n</attribute> <attribute name="accel">&lt;primary&gt;n</attribute>
</item> </item>
<item> <submenu>
<attribute name="label" translatable="yes" comments="Node menu entry request pad">_Request pad</attribute> <attribute name="label" translatable="yes" comments="Node menu entry request pad">_Request pad</attribute>
<attribute name="action">app.node.request-pad</attribute> <item>
<attribute name="label" translatable="yes" comments="Node menu entry request pad">_Request input pad</attribute>
<attribute name="action">app.node.request-pad-input</attribute>
<attribute name="accel">&lt;primary&gt;n</attribute> <attribute name="accel">&lt;primary&gt;n</attribute>
</item> </item>
<item>
<attribute name="label" translatable="yes" comments="Node menu entry request pad">_Request output pad</attribute>
<attribute name="action">app.node.request-pad-output</attribute>
<attribute name="accel">&lt;primary&gt;n</attribute>
</item>
</submenu>
<item> <item>
<attribute name="label" translatable="yes" comments="Node menu entry request pad">_Properties</attribute> <attribute name="label" translatable="yes" comments="Node menu entry request pad">_Properties</attribute>
<attribute name="action">app.node.properties</attribute> <attribute name="action">app.node.properties</attribute>

View file

@ -176,7 +176,7 @@ mod imp {
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 mut node_from = port_from.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 mut node_to = port_to.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 { if port_to.direction() == PortDirection::Output {
println!("swap ports and nodes to create the link"); println!("swap ports and nodes to create the link");
std::mem::swap(&mut node_from, &mut node_to); std::mem::swap(&mut node_from, &mut node_to);
std::mem::swap(&mut port_from, &mut port_to); std::mem::swap(&mut port_from, &mut port_to);
@ -392,15 +392,13 @@ impl GraphView {
let _i = 0; let _i = 0;
for _i in 0..input { for _i in 0..input {
let port_id = self.next_port_id(); let port_id = self.next_port_id();
let port = Port::new(port_id, "in", PortDirection::Input); self.add_port(id, port_id, "in", PortDirection::Input);
self.add_port(id, port_id, port);
} }
let _i = 0; let _i = 0;
for _i in 0..output { for _i in 0..output {
let port_id = self.next_port_id(); let port_id = self.next_port_id();
let port = Port::new(port_id, "out", PortDirection::Output); self.add_port(id, port_id, "out", PortDirection::Output);
self.add_port(id, port_id, port);
} }
} }
@ -463,14 +461,20 @@ impl GraphView {
} }
// Port related methods // Port related methods
pub fn add_port(&self, node_id: u32, port_id: u32, port: Port) { pub fn add_port(
&self,
node_id: u32,
port_id: u32,
port_name: &str,
port_direction: PortDirection,
) {
let private = imp::GraphView::from_instance(self); let private = imp::GraphView::from_instance(self);
println!( println!(
"adding a port with port id {} to node id {}", "adding a port with port id {} to node id {}",
port_id, node_id port_id, node_id
); );
if let Some(node) = private.nodes.borrow_mut().get_mut(&node_id) { if let Some(node) = private.nodes.borrow_mut().get_mut(&node_id) {
node.add_port(port_id, port); node.add_port(port_id, port_name, port_direction);
} else { } else {
error!( error!(
"Node with id {} not found when trying to add port with id {} to graph", "Node with id {} not found when trying to add port with id {} to graph",
@ -664,21 +668,20 @@ impl GraphView {
let private = imp::GraphView::from_instance(self); let private = imp::GraphView::from_instance(self);
let unique_name = node.unique_name(); let unique_name = node.unique_name();
description.push_str(&format!("{} name={}", node.name(), 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(" ! ");
}
for (name, value) in node.properties().iter() { for (name, value) in node.properties().iter() {
description.push_str(&format!(" {}={}", name, value)); description.push_str(&format!(" {}={}", name, value));
} }
println!("{}", description); println!("{}", description);
let ports = node.all_ports(PortDirection::Output);
let n_ports = ports.len();
for port in ports { for port in ports {
if let Some((_port_to, node_to)) = self.port_connected_to(port.id()) { if let Some((_port_to, node_to)) = self.port_connected_to(port.id()) {
if n_ports > 1 {
description.push_str(&format!(" {}. ! ", unique_name));
} else {
description.push_str(" ! ");
}
if let Some(node) = private.nodes.borrow().get(&node_to) { if let Some(node) = private.nodes.borrow().get(&node_to) {
description = self.process_node(node, description.clone()); description = self.process_node(node, description.clone());
} }
@ -867,8 +870,11 @@ impl GraphView {
"Port" => { "Port" => {
if let Some(port) = current_port { if let Some(port) = current_port {
let node = current_node.clone(); let node = current_node.clone();
node.expect("No current node, error...") node.expect("No current node, error...").add_port(
.add_port(port.id(), port); port.id(),
&port.name(),
port.direction(),
);
} }
current_port = None; current_port = None;
} }

View file

@ -141,9 +141,9 @@ impl Node {
println!("{}", name); println!("{}", name);
} }
pub fn add_port(&mut self, id: u32, port: super::port::Port) { pub fn add_port(&mut self, id: u32, name: &str, direction: PortDirection) {
let private = imp::Node::from_instance(self); let private = imp::Node::from_instance(self);
let port = Port::new(id, name, direction);
match port.direction() { match port.direction() {
PortDirection::Input => { PortDirection::Input => {
private private
@ -172,7 +172,7 @@ impl Node {
let ports_list: Vec<_> = self let ports_list: Vec<_> = self
.ports() .ports()
.iter() .iter()
.filter(|(_, port)| *port.direction() == direction || direction == PortDirection::All) .filter(|(_, port)| port.direction() == direction || direction == PortDirection::All)
.map(|(_, port)| port.clone()) .map(|(_, port)| port.clone())
.collect(); .collect();
ports_list ports_list

View file

@ -22,9 +22,9 @@ use gtk::{
prelude::*, prelude::*,
subclass::prelude::*, subclass::prelude::*,
}; };
use std::fmt; use std::{borrow::Borrow, fmt};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Copy)]
pub enum PortDirection { pub enum PortDirection {
Input, Input,
Output, Output,
@ -137,17 +137,14 @@ impl Port {
private.id.get().copied().expect("Port id is not set") private.id.get().copied().expect("Port id is not set")
} }
pub fn direction(&self) -> &PortDirection { pub fn direction(&self) -> PortDirection {
let private = imp::Port::from_instance(self); let private = imp::Port::from_instance(self);
private.direction.get().expect("Port direction is not set") *private.direction.get().expect("Port direction is not set")
} }
pub fn name(&self) -> String { pub fn name(&self) -> String {
let private = imp::Port::from_instance(self); let private = imp::Port::from_instance(self);
private let label = private.label.borrow().get().unwrap();
.direction label.text().to_string()
.get()
.expect("direction is not set")
.to_string()
} }
} }