mirror of
https://gitlab.freedesktop.org/pipewire/helvum
synced 2026-03-15 03:26:10 +08:00
view: Draw a dashed line for links that are not active
This commit is contained in:
@@ -109,8 +109,9 @@ impl Application {
|
|||||||
move |msg| {
|
move |msg| {
|
||||||
match msg {
|
match msg {
|
||||||
PipewireMessage::NodeAdded{ id, name } => app.add_node(id, name.as_str()),
|
PipewireMessage::NodeAdded{ id, name } => app.add_node(id, name.as_str()),
|
||||||
PipewireMessage::PortAdded{ id, node_id, name, direction, media_type} => app.add_port(id, name.as_str(), node_id, direction, media_type),
|
PipewireMessage::PortAdded{ id, node_id, name, direction, media_type } => app.add_port(id, name.as_str(), node_id, direction, media_type),
|
||||||
PipewireMessage::LinkAdded{ id, node_from, port_from, node_to, port_to} => app.add_link(id, node_from, port_from, node_to, port_to),
|
PipewireMessage::LinkAdded{ id, node_from, port_from, node_to, port_to, active} => app.add_link(id, node_from, port_from, node_to, port_to, active),
|
||||||
|
PipewireMessage::LinkStateChanged { id, active } => app.link_state_changed(id, active), // TODO
|
||||||
PipewireMessage::NodeRemoved { id } => app.remove_node(id),
|
PipewireMessage::NodeRemoved { id } => app.remove_node(id),
|
||||||
PipewireMessage::PortRemoved { id, node_id } => app.remove_port(id, node_id),
|
PipewireMessage::PortRemoved { id, node_id } => app.remove_port(id, node_id),
|
||||||
PipewireMessage::LinkRemoved { id } => app.remove_link(id)
|
PipewireMessage::LinkRemoved { id } => app.remove_link(id)
|
||||||
@@ -124,7 +125,7 @@ impl Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new node to the view.
|
/// Add a new node to the view.
|
||||||
pub fn add_node(&self, id: u32, name: &str) {
|
fn add_node(&self, id: u32, name: &str) {
|
||||||
info!("Adding node to graph: id {}", id);
|
info!("Adding node to graph: id {}", id);
|
||||||
|
|
||||||
imp::Application::from_instance(self)
|
imp::Application::from_instance(self)
|
||||||
@@ -133,7 +134,7 @@ impl Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new port to the view.
|
/// Add a new port to the view.
|
||||||
pub fn add_port(
|
fn add_port(
|
||||||
&self,
|
&self,
|
||||||
id: u32,
|
id: u32,
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -168,7 +169,15 @@ impl Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new link to the view.
|
/// Add a new link to the view.
|
||||||
pub fn add_link(&self, id: u32, node_from: u32, port_from: u32, node_to: u32, port_to: u32) {
|
fn add_link(
|
||||||
|
&self,
|
||||||
|
id: u32,
|
||||||
|
node_from: u32,
|
||||||
|
port_from: u32,
|
||||||
|
node_to: u32,
|
||||||
|
port_to: u32,
|
||||||
|
active: bool,
|
||||||
|
) {
|
||||||
info!("Adding link to graph: id {}", id);
|
info!("Adding link to graph: id {}", id);
|
||||||
|
|
||||||
// FIXME: Links should be colored depending on the data they carry (video, audio, midi) like ports are.
|
// FIXME: Links should be colored depending on the data they carry (video, audio, midi) like ports are.
|
||||||
@@ -182,9 +191,22 @@ impl Application {
|
|||||||
node_to,
|
node_to,
|
||||||
port_to,
|
port_to,
|
||||||
},
|
},
|
||||||
|
active,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn link_state_changed(&self, id: u32, active: bool) {
|
||||||
|
info!(
|
||||||
|
"Link state changed: Link (id={}) is now {}",
|
||||||
|
id,
|
||||||
|
if active { "active" } else { "inactive" }
|
||||||
|
);
|
||||||
|
|
||||||
|
imp::Application::from_instance(self)
|
||||||
|
.graphview
|
||||||
|
.set_link_state(id, active);
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle a link between the two specified ports on the remote pipewire server.
|
// Toggle a link between the two specified ports on the remote pipewire server.
|
||||||
fn toggle_link(&self, port_from: u32, port_to: u32) {
|
fn toggle_link(&self, port_from: u32, port_to: u32) {
|
||||||
let imp = imp::Application::from_instance(self);
|
let imp = imp::Application::from_instance(self);
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ enum PipewireMessage {
|
|||||||
port_from: u32,
|
port_from: u32,
|
||||||
node_to: u32,
|
node_to: u32,
|
||||||
port_to: u32,
|
port_to: u32,
|
||||||
|
active: bool,
|
||||||
|
},
|
||||||
|
LinkStateChanged {
|
||||||
|
id: u32,
|
||||||
|
active: bool,
|
||||||
},
|
},
|
||||||
NodeRemoved {
|
NodeRemoved {
|
||||||
id: u32,
|
id: u32,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
|||||||
use gtk::glib::{self, clone};
|
use gtk::glib::{self, clone};
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use pipewire::{
|
use pipewire::{
|
||||||
link::{Link, LinkListener},
|
link::{Link, LinkChangeMask, LinkListener, LinkState},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
properties,
|
properties,
|
||||||
registry::{GlobalObject, Registry},
|
registry::{GlobalObject, Registry},
|
||||||
@@ -193,7 +193,13 @@ fn handle_link(
|
|||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
if let Some(Item::Link { .. }) = state.get(id) {
|
if let Some(Item::Link { .. }) = state.get(id) {
|
||||||
// Info was an update - figure out if we should notify the gtk thread
|
// Info was an update - figure out if we should notify the gtk thread
|
||||||
// TODO
|
if info.change_mask().contains(LinkChangeMask::STATE) {
|
||||||
|
sender.send(PipewireMessage::LinkStateChanged {
|
||||||
|
id,
|
||||||
|
active: matches!(info.state(), LinkState::Active)
|
||||||
|
}).expect("Failed to send message");
|
||||||
|
}
|
||||||
|
// TODO -- check other values that might have changed
|
||||||
} else {
|
} else {
|
||||||
// First time we get info. We can now notify the gtk thread of a new link.
|
// First time we get info. We can now notify the gtk thread of a new link.
|
||||||
let node_from = info.output_node_id();
|
let node_from = info.output_node_id();
|
||||||
@@ -210,7 +216,8 @@ fn handle_link(
|
|||||||
node_from,
|
node_from,
|
||||||
port_from,
|
port_from,
|
||||||
node_to,
|
node_to,
|
||||||
port_to
|
port_to,
|
||||||
|
active: matches!(info.state(), LinkState::Active)
|
||||||
}).expect(
|
}).expect(
|
||||||
"Failed to send message"
|
"Failed to send message"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ mod imp {
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GraphView {
|
pub struct GraphView {
|
||||||
pub(super) nodes: RefCell<HashMap<u32, Node>>,
|
pub(super) nodes: RefCell<HashMap<u32, Node>>,
|
||||||
pub(super) links: RefCell<HashMap<u32, crate::PipewireLink>>,
|
/// Stores the link and whether it is currently active.
|
||||||
|
pub(super) links: RefCell<HashMap<u32, (crate::PipewireLink, bool)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
@@ -150,10 +151,17 @@ mod imp {
|
|||||||
.expect("Failed to get cairo context");
|
.expect("Failed to get cairo context");
|
||||||
link_cr.set_line_width(2.0);
|
link_cr.set_line_width(2.0);
|
||||||
link_cr.set_source_rgb(0.0, 0.0, 0.0);
|
link_cr.set_source_rgb(0.0, 0.0, 0.0);
|
||||||
for link in self.links.borrow().values() {
|
for (link, active) in self.links.borrow().values() {
|
||||||
if let Some((from_x, from_y, to_x, to_y)) = self.get_link_coordinates(link) {
|
if let Some((from_x, from_y, to_x, to_y)) = self.get_link_coordinates(link) {
|
||||||
link_cr.move_to(from_x, from_y);
|
link_cr.move_to(from_x, from_y);
|
||||||
|
|
||||||
|
// Use dashed line for inactive links, full line otherwise.
|
||||||
|
if *active {
|
||||||
|
link_cr.set_dash(&[], 0.0);
|
||||||
|
} else {
|
||||||
|
link_cr.set_dash(&[10.0, 5.0], 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Place curve control offset by half the x distance between the two points.
|
// Place curve control offset by half the x distance between the two points.
|
||||||
// This makes the curve scale well for varying distances between the two ports,
|
// This makes the curve scale well for varying distances between the two ports,
|
||||||
// especially when the output port is farther right than the input port.
|
// especially when the output port is farther right than the input port.
|
||||||
@@ -276,12 +284,22 @@ impl GraphView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_link(&self, link_id: u32, link: crate::PipewireLink) {
|
pub fn add_link(&self, link_id: u32, link: crate::PipewireLink, active: bool) {
|
||||||
let private = imp::GraphView::from_instance(self);
|
let private = imp::GraphView::from_instance(self);
|
||||||
private.links.borrow_mut().insert(link_id, link);
|
private.links.borrow_mut().insert(link_id, (link, active));
|
||||||
self.queue_draw();
|
self.queue_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_link_state(&self, link_id: u32, active: bool) {
|
||||||
|
let private = imp::GraphView::from_instance(self);
|
||||||
|
if let Some((_, state)) = private.links.borrow_mut().get_mut(&link_id) {
|
||||||
|
*state = active;
|
||||||
|
self.queue_draw();
|
||||||
|
} else {
|
||||||
|
warn!("Link state changed on unknown link (id={})", link_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_link(&self, id: u32) {
|
pub fn remove_link(&self, id: u32) {
|
||||||
let private = imp::GraphView::from_instance(self);
|
let private = imp::GraphView::from_instance(self);
|
||||||
let mut links = private.links.borrow_mut();
|
let mut links = private.links.borrow_mut();
|
||||||
|
|||||||
Reference in New Issue
Block a user