mirror of
https://gitlab.freedesktop.org/pipewire/helvum
synced 2026-03-15 19:46:10 +08:00
Add initial project.
This commit is contained in:
96
src/view/graph_view.rs
Normal file
96
src/view/graph_view.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use super::PipewireNode;
|
||||
use cairo::Context;
|
||||
use glib::clone;
|
||||
use gtk::{prelude::*, LayoutExt};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
pub struct GraphView {
|
||||
pub(crate) widget: gtk::Layout,
|
||||
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
|
||||
links: Rc<RefCell<HashMap<u32, crate::PipewireLink>>>,
|
||||
}
|
||||
|
||||
impl GraphView {
|
||||
pub fn new() -> Self {
|
||||
let result = Self {
|
||||
widget: gtk::Layout::new::<gtk::Adjustment, gtk::Adjustment>(None, None),
|
||||
nodes: Rc::new(RefCell::new(HashMap::new())),
|
||||
links: Rc::new(RefCell::new(HashMap::new())),
|
||||
};
|
||||
|
||||
result.widget.connect_draw(clone!(
|
||||
@weak result.nodes as nodes, @weak result.links as links => @default-panic,
|
||||
move |_, cr| {
|
||||
draw(nodes, links, cr);
|
||||
Inhibit(false)
|
||||
}));
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, id: u32, node: PipewireNode) {
|
||||
// TODO: Find a free position to put the widget at.
|
||||
self.widget.put(
|
||||
&node.widget,
|
||||
(self.nodes.borrow().len() % 4 * 400) as i32,
|
||||
(self.nodes.borrow().len() / 4 * 100) as i32,
|
||||
);
|
||||
self.nodes.borrow_mut().insert(id, node);
|
||||
}
|
||||
|
||||
/// Add a link to the graph.
|
||||
///
|
||||
/// `add_link` takes three arguments: `link_id` is the id of the link as assigned by the pipewire server,
|
||||
/// `from` and `to` are the id's of the ingoing and outgoing port, respectively.
|
||||
pub fn add_link(&mut self, link_id: u32, link: crate::PipewireLink) {
|
||||
self.links.borrow_mut().insert(link_id, link);
|
||||
self.widget.queue_draw();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(
|
||||
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
|
||||
links: Rc<RefCell<HashMap<u32, crate::PipewireLink>>>,
|
||||
cr: &Context,
|
||||
) {
|
||||
cr.set_line_width(2.0);
|
||||
cr.set_source_rgb(255.0, 255.0, 255.0);
|
||||
cr.paint();
|
||||
cr.set_source_rgb(0.0, 0.0, 0.0);
|
||||
for link in links.borrow().values() {
|
||||
let (from_alloc, to_alloc) = get_allocs(nodes.clone(), link);
|
||||
|
||||
cr.move_to(
|
||||
(from_alloc.x + from_alloc.width).into(),
|
||||
(from_alloc.y + (from_alloc.height / 2)).into()
|
||||
);
|
||||
cr.line_to(
|
||||
to_alloc.x.into(),
|
||||
(to_alloc.y + (to_alloc.height / 2)).into()
|
||||
);
|
||||
|
||||
cr.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_allocs(
|
||||
nodes: Rc<RefCell<HashMap<u32, PipewireNode>>>,
|
||||
link: &crate::PipewireLink,
|
||||
) -> (gtk::Allocation, gtk::Allocation) {
|
||||
let from_alloc = &nodes
|
||||
.borrow()
|
||||
.get(&link.node_from)
|
||||
.unwrap()
|
||||
.get_outgoing_port(link.port_from)
|
||||
.unwrap()
|
||||
.get_allocation();
|
||||
let to_alloc = &nodes
|
||||
.borrow()
|
||||
.get(&link.node_to)
|
||||
.unwrap()
|
||||
.get_ingoing_port(link.port_to)
|
||||
.unwrap()
|
||||
.get_allocation();
|
||||
|
||||
(from_alloc.to_owned(), to_alloc.to_owned())
|
||||
}
|
||||
5
src/view/mod.rs
Normal file
5
src/view/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod graph_view;
|
||||
mod pipewire_node;
|
||||
|
||||
pub use pipewire_node::PipewireNode;
|
||||
pub use graph_view::GraphView;
|
||||
43
src/view/pipewire_node.rs
Normal file
43
src/view/pipewire_node.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use gtk::GridExt;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct PipewireNode {
|
||||
pub(super) widget: gtk::Grid,
|
||||
_label: gtk::Label,
|
||||
ingoing_ports: HashMap<u32, gtk::Button>,
|
||||
outgoing_ports: HashMap<u32, gtk::Button>,
|
||||
}
|
||||
|
||||
impl PipewireNode {
|
||||
pub fn new(name: &str) -> Self {
|
||||
let widget = gtk::Grid::new();
|
||||
let label = gtk::Label::new(Some(name));
|
||||
widget.attach(&label, 0, 0, 2, 1);
|
||||
|
||||
Self {
|
||||
widget,
|
||||
_label: label,
|
||||
ingoing_ports: HashMap::new(),
|
||||
outgoing_ports: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_ingoing_port(&mut self, id: u32, port: gtk::Button) {
|
||||
self.widget.attach(&port, 0, (self.ingoing_ports.len() + 1) as i32, 1, 1);
|
||||
self.ingoing_ports.insert(id, port);
|
||||
}
|
||||
|
||||
pub fn add_outgoing_port(&mut self, id: u32, port: gtk::Button) {
|
||||
self.widget.attach(&port, 1, (self.outgoing_ports.len() + 1) as i32, 1, 1);
|
||||
self.outgoing_ports.insert(id, port);
|
||||
}
|
||||
|
||||
pub fn get_ingoing_port(&self, id: u32) -> Option<>k::Button> {
|
||||
self.ingoing_ports.get(&id)
|
||||
}
|
||||
|
||||
pub fn get_outgoing_port(&self, id: u32) -> Option<>k::Button> {
|
||||
self.outgoing_ports.get(&id)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user