From 8a75db1987e14e48648f4fcc169f88663eee8ac7 Mon Sep 17 00:00:00 2001 From: Naveen Prashanth Date: Wed, 6 May 2026 15:57:38 +0530 Subject: [PATCH] Add typed IDs --- src/graph_manager.rs | 154 +++++++++++++++++++------------ src/main.rs | 68 ++++++++++---- src/pipewire_connection/mod.rs | 50 +++++----- src/pipewire_connection/state.rs | 21 +++-- src/ui/graph/graph_view.rs | 32 +++++-- src/ui/graph/node.rs | 9 +- src/ui/graph/port.rs | 15 ++- 7 files changed, 225 insertions(+), 124 deletions(-) diff --git a/src/graph_manager.rs b/src/graph_manager.rs index af9782d..83cfdef 100644 --- a/src/graph_manager.rs +++ b/src/graph_manager.rs @@ -25,7 +25,7 @@ mod imp { use std::{cell::OnceCell, cell::RefCell, collections::HashMap}; - use crate::{ui::graph, MediaType, NodeType}; + use crate::{ui::graph, LinkId, MediaType, NodeId, NodeType, PortId}; #[derive(Default, glib::Properties)] #[properties(wrapper_type = super::GraphManager)] @@ -117,26 +117,33 @@ mod imp { } /// Add a new node to the view. - fn add_node(&self, id: u32, name: &str, node_type: Option) { - log::info!("Adding node to graph: id {}", id); + fn add_node(&self, id: NodeId, name: &str, node_type: Option) { + log::info!("Adding node to graph: id {}", id.0); + + let mut items = self.items.borrow_mut(); + if let Some(old_item) = items.get(&id.0) { + if let Ok(old_node) = old_item.clone().dynamic_cast::() { + self.graph_view().remove_node(&old_node); + } + } let node = graph::Node::new(name, id); - self.items.borrow_mut().insert(id, node.clone().upcast()); + items.insert(id.0, node.clone().upcast()); self.graph_view().add_node(node, node_type); } /// Update a node tooltip to the view. - fn node_name_changed(&self, id: u32, node_name: &str, media_name: &str) { + fn node_name_changed(&self, id: NodeId, node_name: &str, media_name: &str) { let items = self.items.borrow(); - let Some(node) = items.get(&id) else { - log::warn!("Node (id: {id}) for changed name not found in graph manager"); + let Some(node) = items.get(&id.0) else { + log::warn!("Node (id: {}) for changed name not found in graph manager", id.0); return; }; let Some(node) = node.dynamic_cast_ref::() else { - log::warn!("Graph Manager item under node (id: {id}) is not a node"); + log::warn!("Graph Manager item under node (id: {}) is not a node", id.0); return; }; @@ -145,15 +152,15 @@ mod imp { } /// Remove the node with the specified id from the view. - fn remove_node(&self, id: u32) { - log::info!("Removing node from graph: id {}", id); + fn remove_node(&self, id: NodeId) { + log::info!("Removing node from graph: id {}", id.0); - let Some(node) = self.items.borrow_mut().remove(&id) else { - log::warn!("Unknown node (id={id}) removed from graph"); + let Some(node) = self.items.borrow_mut().remove(&id.0) else { + log::warn!("Unknown node (id={}) removed from graph", id.0); return; }; let Ok(node) = node.dynamic_cast::() else { - log::warn!("Graph Manager item under node id {id} is not a node"); + log::warn!("Graph Manager item under node id {} is not a node", id.0); return; }; @@ -161,17 +168,35 @@ mod imp { } /// Add a new port to the view. - fn add_port(&self, id: u32, name: &str, node_id: u32, direction: libspa::utils::Direction) { - log::info!("Adding port to graph: id {}", id); + fn add_port( + &self, + id: PortId, + name: &str, + node_id: NodeId, + direction: libspa::utils::Direction, + ) { + log::info!("Adding port to graph: id {}", id.0); let mut items = self.items.borrow_mut(); - let Some(node) = items.get(&node_id) else { - log::warn!("Node (id: {node_id}) for port (id: {id}) not found in graph manager"); + if let Some(old_item) = items.get(&id.0) { + if let Ok(old_port) = old_item.clone().dynamic_cast::() { + if let Some(old_node_widget) = old_port.parent().and_downcast::() { + old_node_widget.remove_port(&old_port); + } + } + } + + let Some(node) = items.get(&node_id.0) else { + log::warn!( + "Node (id: {}) for port (id: {}) not found in graph manager", + node_id.0, + id.0 + ); return; }; let Ok(node) = node.clone().dynamic_cast::() else { - log::warn!("Graph Manager item under node id {node_id} is not a node"); + log::warn!("Graph Manager item under node id {} is not a node", node_id.0); return; }; @@ -187,8 +212,8 @@ mod imp { #[upgrade_or_default] move |args| { // Args always look like this: &[widget, id_port_from, id_port_to] - let port_from = args[1].get::().unwrap(); - let port_to = args[2].get::().unwrap(); + let port_from = PortId(args[1].get::().unwrap()); + let port_to = PortId(args[2].get::().unwrap()); app.toggle_link(port_from, port_to); @@ -197,20 +222,20 @@ mod imp { ), ); - items.insert(id, port.clone().upcast()); + items.insert(id.0, port.clone().upcast()); node.add_port(port); } - fn port_media_type_changed(&self, id: u32, media_type: MediaType) { + fn port_media_type_changed(&self, id: PortId, media_type: MediaType) { let items = self.items.borrow(); - let Some(port) = items.get(&id) else { - log::warn!("Port (id: {id}) for changed media type not found in graph manager"); + let Some(port) = items.get(&id.0) else { + log::warn!("Port (id: {}) for changed media type not found in graph manager", id.0); return; }; let Some(port) = port.dynamic_cast_ref::() else { - log::warn!("Graph Manager item under port id {id} is not a port"); + log::warn!("Graph Manager item under port id {} is not a port", id.0); return; }; @@ -219,25 +244,25 @@ mod imp { /// Remove the port with the id `id` from the node with the id `node_id` /// from the view. - fn remove_port(&self, id: u32, node_id: u32) { - log::info!("Removing port from graph: id {}, node_id: {}", id, node_id); + fn remove_port(&self, id: PortId, node_id: NodeId) { + log::info!("Removing port from graph: id {}, node_id: {}", id.0, node_id.0); let mut items = self.items.borrow_mut(); - let Some(node) = items.get(&node_id) else { - log::warn!("Node (id: {node_id}) for port (id: {id}) not found in graph manager"); + let Some(node) = items.get(&node_id.0) else { + log::warn!("Node (id: {}) for port (id: {}) not found in graph manager", node_id.0, id.0); return; }; let Ok(node) = node.clone().dynamic_cast::() else { - log::warn!("Graph Manager item under node id {node_id} is not a node"); + log::warn!("Graph Manager item under node id {} is not a node", node_id.0); return; }; - let Some(port) = items.remove(&id) else { - log::warn!("Unknown Port (id: {id}) removed from graph"); + let Some(port) = items.remove(&id.0) else { + log::warn!("Unknown Port (id: {}) removed from graph", id.0); return; }; let Ok(port) = port.dynamic_cast::() else { - log::warn!("Graph Manager item under port id {id} is not a port"); + log::warn!("Graph Manager item under port id {} is not a port", id.0); return; }; @@ -247,30 +272,40 @@ mod imp { /// Add a new link to the view. fn add_link( &self, - id: u32, - output_port_id: u32, - input_port_id: u32, + id: LinkId, + output_port_id: PortId, + input_port_id: PortId, active: bool, media_type: MediaType, ) { - log::info!("Adding link to graph: id {}", id); + log::info!("Adding link to graph: id {}", id.0); let mut items = self.items.borrow_mut(); - let Some(output_port) = items.get(&output_port_id) else { - log::warn!("Output port (id: {output_port_id}) for link (id: {id}) not found in graph manager"); + if let Some(old_item) = items.get(&id.0) { + if let Ok(old_link) = old_item.clone().dynamic_cast::() { + self.graph + .borrow() + .as_ref() + .expect("graph should be set") + .remove_link(&old_link); + } + } + + let Some(output_port) = items.get(&output_port_id.0) else { + log::warn!("Output port (id: {}) for link (id: {}) not found in graph manager", output_port_id.0, id.0); return; }; let Ok(output_port) = output_port.clone().dynamic_cast::() else { - log::warn!("Graph Manager item under port id {output_port_id} is not a port"); + log::warn!("Graph Manager item under port id {} is not a port", output_port_id.0); return; }; - let Some(input_port) = items.get(&input_port_id) else { - log::warn!("Output port (id: {input_port_id}) for link (id: {id}) not found in graph manager"); + let Some(input_port) = items.get(&input_port_id.0) else { + log::warn!("Output port (id: {}) for link (id: {}) not found in graph manager", input_port_id.0, id.0); return; }; let Ok(input_port) = input_port.clone().dynamic_cast::() else { - log::warn!("Graph Manager item under port id {input_port_id} is not a port"); + log::warn!("Graph Manager item under port id {} is not a port", input_port_id.0); return; }; @@ -280,7 +315,7 @@ mod imp { link.set_active(active); link.set_media_type(media_type); - items.insert(id, link.clone().upcast()); + items.insert(id.0, link.clone().upcast()); // Update graph to contain the new link. self.graph @@ -290,42 +325,43 @@ mod imp { .add_link(link); } - fn link_state_changed(&self, id: u32, active: bool) { + fn link_state_changed(&self, id: LinkId, active: bool) { log::info!( - "Link state changed: Link (id={id}) is now {}", + "Link state changed: Link (id={}) is now {}", + id.0, if active { "active" } else { "inactive" } ); let items = self.items.borrow(); - let Some(link) = items.get(&id) else { - log::warn!("Link state changed on unknown link (id={id})"); + let Some(link) = items.get(&id.0) else { + log::warn!("Link state changed on unknown link (id={})", id.0); return; }; let Some(link) = link.dynamic_cast_ref::() else { - log::warn!("Graph Manager item under link id {id} is not a link"); + log::warn!("Graph Manager item under link id {} is not a link", id.0); return; }; link.set_active(active); } - fn link_format_changed(&self, id: u32, media_type: libspa::param::format::MediaType) { + fn link_format_changed(&self, id: LinkId, media_type: libspa::param::format::MediaType) { let items = self.items.borrow(); - let Some(link) = items.get(&id) else { - log::warn!("Link (id: {id}) for changed media type not found in graph manager"); + let Some(link) = items.get(&id.0) else { + log::warn!("Link (id: {}) for changed media type not found in graph manager", id.0); return; }; let Some(link) = link.dynamic_cast_ref::() else { - log::warn!("Graph Manager item under link id {id} is not a link"); + log::warn!("Graph Manager item under link id {} is not a link", id.0); return; }; link.set_media_type(media_type); } // 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: PortId, port_to: PortId) { let sender = self.pw_sender.get().expect("pw_sender shoud be set"); sender .send(crate::GtkMessage::ToggleLink { port_from, port_to }) @@ -333,15 +369,15 @@ mod imp { } /// Remove the link with the specified id from the view. - fn remove_link(&self, id: u32) { - log::info!("Removing link from graph: id {}", id); + fn remove_link(&self, id: LinkId) { + log::info!("Removing link from graph: id {}", id.0); - let Some(link) = self.items.borrow_mut().remove(&id) else { - log::warn!("Unknown Link (id={id}) removed from graph"); + let Some(link) = self.items.borrow_mut().remove(&id.0) else { + log::warn!("Unknown Link (id={}) removed from graph", id.0); return; }; let Ok(link) = link.dynamic_cast::() else { - log::warn!("Graph Manager item under link id {id} is not a link"); + log::warn!("Graph Manager item under link id {} is not a link", id.0); return; }; diff --git a/src/main.rs b/src/main.rs index 3222475..1ed51bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,11 +22,41 @@ mod ui; use adw::{gtk, prelude::*}; use libspa::{param::format::MediaType, utils::Direction}; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct NodeId(pub u32); + +impl std::fmt::Display for NodeId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct PortId(pub u32); + +impl std::fmt::Display for PortId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct LinkId(pub u32); + +impl std::fmt::Display for LinkId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + /// Messages sent by the GTK thread to notify the pipewire thread. #[derive(Debug, Clone)] pub enum GtkMessage { /// Toggle a link between the two specified ports. - ToggleLink { port_from: u32, port_to: u32 }, + ToggleLink { + port_from: PortId, + port_to: PortId, + }, /// Quit the event loop and let the thread finish. Terminate, } @@ -35,49 +65,49 @@ pub enum GtkMessage { #[derive(Debug, Clone)] pub enum PipewireMessage { NodeAdded { - id: u32, + id: NodeId, name: String, node_type: Option, }, NodeNameChanged { - id: u32, + id: NodeId, name: String, media_name: String, }, PortAdded { - id: u32, - node_id: u32, + id: PortId, + node_id: NodeId, name: String, direction: Direction, }, PortFormatChanged { - id: u32, + id: PortId, media_type: MediaType, }, LinkAdded { - id: u32, - port_from: u32, - port_to: u32, + id: LinkId, + port_from: PortId, + port_to: PortId, active: bool, media_type: MediaType, }, LinkStateChanged { - id: u32, + id: LinkId, active: bool, }, LinkFormatChanged { - id: u32, + id: LinkId, media_type: MediaType, }, NodeRemoved { - id: u32, + id: NodeId, }, PortRemoved { - id: u32, - node_id: u32, + id: PortId, + node_id: NodeId, }, LinkRemoved { - id: u32, + id: LinkId, }, Connecting, Connected, @@ -92,10 +122,10 @@ pub enum NodeType { #[derive(Debug, Clone)] pub struct PipewireLink { - pub node_from: u32, - pub port_from: u32, - pub node_to: u32, - pub port_to: u32, + pub node_from: NodeId, + pub port_from: PortId, + pub node_to: NodeId, + pub port_to: PortId, } static GLIB_LOGGER: glib::GlibLogger = glib::GlibLogger::new( diff --git a/src/pipewire_connection/mod.rs b/src/pipewire_connection/mod.rs index 9be140f..255a70a 100644 --- a/src/pipewire_connection/mod.rs +++ b/src/pipewire_connection/mod.rs @@ -40,7 +40,7 @@ use pipewire::{ types::ObjectType, }; -use crate::{GtkMessage, MediaType, NodeType, PipewireMessage}; +use crate::{GtkMessage, LinkId, MediaType, NodeId, NodeType, PipewireMessage, PortId}; use state::{Item, State}; enum ProxyItem { @@ -179,9 +179,11 @@ pub(super) fn thread_main( if let Some(item) = state_remove.borrow_mut().remove(id) { gtk_sender4 .send_blocking(match item { - Item::Node => PipewireMessage::NodeRemoved { id }, - Item::Port { node_id } => PipewireMessage::PortRemoved { id, node_id }, - Item::Link { .. } => PipewireMessage::LinkRemoved { id }, + Item::Node => PipewireMessage::NodeRemoved { id: NodeId(id) }, + Item::Port { node_id } => { + PipewireMessage::PortRemoved { id: PortId(id), node_id } + } + Item::Link { .. } => PipewireMessage::LinkRemoved { id: LinkId(id) }, }) .expect("Failed to send message"); } else { @@ -247,7 +249,7 @@ fn handle_node( sender .send_blocking(PipewireMessage::NodeAdded { - id: node.id, + id: NodeId(node.id), name, node_type, }) @@ -292,7 +294,7 @@ fn handle_node_info( sender .send_blocking(PipewireMessage::NodeNameChanged { - id, + id: NodeId(id), name, media_name: media_name.to_string(), }) @@ -362,11 +364,13 @@ fn handle_port_info( // First time we get info. We can now notify the gtk thread of a new port. let props = info.props().expect("Port object is missing properties"); let name = props.get("port.name").unwrap_or_default().to_string(); - let node_id: u32 = props - .get("node.id") - .expect("Port has no node.id property!") - .parse() - .expect("Could not parse node.id property"); + let node_id = NodeId( + props + .get("node.id") + .expect("Port has no node.id property!") + .parse() + .expect("Could not parse node.id property"), + ); state.insert(id, Item::Port { node_id }); @@ -382,7 +386,7 @@ fn handle_port_info( sender .send_blocking(PipewireMessage::PortAdded { - id, + id: PortId(id), node_id, name, direction: info.direction(), @@ -403,7 +407,7 @@ fn handle_port_enum_format( sender .send_blocking(PipewireMessage::PortFormatChanged { - id: port_id, + id: PortId(port_id), media_type, }) .expect("Failed to send message") @@ -455,7 +459,7 @@ fn handle_link_info( if info.change_mask().contains(LinkChangeMask::STATE) { sender .send_blocking(PipewireMessage::LinkStateChanged { - id, + id: LinkId(id), active: matches!(info.state(), LinkState::Active), }) .expect("Failed to send message"); @@ -463,20 +467,20 @@ fn handle_link_info( if info.change_mask().contains(LinkChangeMask::FORMAT) { sender .send_blocking(PipewireMessage::LinkFormatChanged { - id, + id: LinkId(id), media_type: get_link_media_type(info), }) .expect("Failed to send message"); } } else { - let port_from = info.output_port_id(); - let port_to = info.input_port_id(); + let port_from = PortId(info.output_port_id()); + let port_to = PortId(info.input_port_id()); state.insert(id, Item::Link { port_from, port_to }); sender .send_blocking(PipewireMessage::LinkAdded { - id, + id: LinkId(id), port_from, port_to, active: matches!(info.state(), LinkState::Active), @@ -488,20 +492,20 @@ fn handle_link_info( /// Toggle a link between the two specified ports. fn toggle_link( - port_from: u32, - port_to: u32, + port_from: PortId, + port_to: PortId, core: &CoreRc, registry: &RegistryRc, state: &Rc>, ) { let state = state.borrow(); if let Some(id) = state.get_link_id(port_from, port_to) { - info!("Requesting removal of link with id {}", id); - registry.destroy_global(id); + info!("Requesting removal of link with id {}", id.0); + registry.destroy_global(id.0); } else { info!( "Requesting creation of link from port id:{} to port id:{}", - port_from, port_to + port_from.0, port_to.0 ); let node_from = state diff --git a/src/pipewire_connection/state.rs b/src/pipewire_connection/state.rs index fe06a63..80f7531 100644 --- a/src/pipewire_connection/state.rs +++ b/src/pipewire_connection/state.rs @@ -14,6 +14,7 @@ // // SPDX-License-Identifier: GPL-3.0-only +use crate::{LinkId, NodeId, PortId}; use std::collections::HashMap; /// Any pipewire item we need to keep track of. @@ -23,11 +24,11 @@ pub(super) enum Item { Port { // Save the id of the node this is on so we can remove the port from it // when it is deleted. - node_id: u32, + node_id: NodeId, }, Link { - port_from: u32, - port_to: u32, + port_from: PortId, + port_to: PortId, }, } @@ -39,7 +40,7 @@ pub(super) struct State { /// Map pipewire ids to items. items: HashMap, /// Map `(output port id, input port id)` tuples to the id of the link that connects them. - links: HashMap<(u32, u32), u32>, + links: HashMap<(PortId, PortId), LinkId>, } impl State { @@ -51,10 +52,12 @@ impl State { /// Add a new item under the specified id. pub fn insert(&mut self, id: u32, item: Item) { if let Item::Link { - port_from, port_to, .. + port_from, + port_to, + .. } = item { - self.links.insert((port_from, port_to), id); + self.links.insert((port_from, port_to), LinkId(id)); } self.items.insert(id, item); @@ -66,7 +69,7 @@ impl State { } /// Get the id of the link that links the two specified ports. - pub fn get_link_id(&self, output_port: u32, input_port: u32) -> Option { + pub fn get_link_id(&self, output_port: PortId, input_port: PortId) -> Option { self.links.get(&(output_port, input_port)).copied() } @@ -82,8 +85,8 @@ impl State { } /// Convenience function: Get the id of the node a port is on - pub fn get_node_of_port(&self, port: u32) -> Option { - if let Some(Item::Port { node_id }) = self.get(port) { + pub fn get_node_of_port(&self, port: PortId) -> Option { + if let Some(Item::Port { node_id }) = self.get(port.0) { Some(*node_id) } else { None diff --git a/src/ui/graph/graph_view.rs b/src/ui/graph/graph_view.rs index 75e3ac6..7488416 100644 --- a/src/ui/graph/graph_view.rs +++ b/src/ui/graph/graph_view.rs @@ -556,6 +556,8 @@ mod imp { let input_x = input_anchor.x(); let input_y = input_anchor.y(); + let zoom = self.zoom_factor.get() as f32; + let builder = gsk::PathBuilder::new(); builder.move_to(output_x, output_y); @@ -563,7 +565,7 @@ mod imp { // a similar y coordinate, apply a y offset to the control points // so that the curve sticks out a bit. let y_control_offset = if output_x > input_x { - f32::max(0.0, 25.0 - (output_y - input_y).abs()) + f32::max(0.0, (25.0 * zoom) - (output_y - input_y).abs()) } else { 0.0 }; @@ -582,11 +584,12 @@ mod imp { ); let path = builder.to_path(); - let stroke = gsk::Stroke::new(2.0 * self.zoom_factor.get() as f32); + let stroke_width = f32::max(1.0, 2.0 * zoom); + let stroke = gsk::Stroke::new(stroke_width); // Use dashed line for inactive links, full line otherwise. if !active { - stroke.set_dash(&[10.0, 5.0]); + stroke.set_dash(&[10.0 * zoom, 5.0 * zoom]); } snapshot.append_stroke(&path, &stroke, color); @@ -620,7 +623,12 @@ mod imp { _ => unreachable!(), }; - let color = &colors.color_for_media_type(MediaType::from_raw(port.media_type())); + let mut media_type = MediaType::from_raw(port.media_type()); + if media_type == MediaType::Unknown { + media_type = MediaType::Unknown; + } + + let color = &colors.color_for_media_type(media_type); self.draw_link(snapshot, output_anchor, input_anchor, false, color); } @@ -634,9 +642,19 @@ mod imp { }; for link in self.links.borrow().iter() { - let color = &colors.color_for_media_type(link.media_type()); + let mut media_type = link.media_type(); + + // If link media type is unknown, try to fall back to port media types. + if media_type == MediaType::Unknown { + if let Some(output_port) = link.output_port() { + media_type = MediaType::from_raw(output_port.media_type()); + } else if let Some(input_port) = link.input_port() { + media_type = MediaType::from_raw(input_port.media_type()); + } + } + + let color = &colors.color_for_media_type(media_type); - // TODO: Do not draw links when they are outside the view let Some((output_anchor, input_anchor)) = self.get_link_coordinates(link) else { warn!("Could not get allocation of ports of link: {:?}", link); continue; @@ -852,7 +870,7 @@ impl GraphView { self.queue_draw(); } - pub fn clear(&mut self) { + pub fn clear(&self) { self.imp().links.borrow_mut().clear(); for (node, _) in self.imp().nodes.borrow_mut().drain() { node.unparent(); diff --git a/src/ui/graph/node.rs b/src/ui/graph/node.rs index 062c82f..da3290b 100644 --- a/src/ui/graph/node.rs +++ b/src/ui/graph/node.rs @@ -17,6 +17,7 @@ use adw::{glib, gtk, prelude::*, subclass::prelude::*}; use libspa::utils::Direction; +use crate::NodeId; use super::Port; mod imp { @@ -153,13 +154,17 @@ glib::wrapper! { } impl Node { - pub fn new(name: &str, pipewire_id: u32) -> Self { + pub fn new(name: &str, pipewire_id: NodeId) -> Self { glib::Object::builder() .property("node-name", name) - .property("pipewire-id", pipewire_id) + .property("pipewire-id", pipewire_id.0) .build() } + pub fn pw_id(&self) -> NodeId { + NodeId(self.property("pipewire-id")) + } + pub fn add_port(&self, port: Port) { let imp = self.imp(); imp.ports.borrow_mut().insert(port); diff --git a/src/ui/graph/port.rs b/src/ui/graph/port.rs index cbf066c..e79cf18 100644 --- a/src/ui/graph/port.rs +++ b/src/ui/graph/port.rs @@ -21,6 +21,7 @@ use adw::{ prelude::*, subclass::prelude::*, }; +use crate::PortId; use libspa::utils::Direction; use super::PortHandle; @@ -222,7 +223,7 @@ mod imp { .dynamic_cast::() .expect("Widget should be a Port"); - log::trace!("Drag started from port {}", port.pipewire_id()); + log::trace!("Drag started from port {}", port.pw_id()); }); drag_src.connect_drag_cancel(|drag_source, _, _| { let port = drag_source @@ -231,7 +232,7 @@ mod imp { .dynamic_cast::() .expect("Widget should be a Port"); - log::trace!("Drag from port {} was cancelled", port.pipewire_id()); + log::trace!("Drag from port {} was cancelled", port.pw_id()); false }); @@ -284,7 +285,7 @@ mod imp { port.emit_by_name::<()>( "port-toggled", - &[&output_port.pipewire_id(), &input_port.pipewire_id()], + &[&output_port.pw_id().0, &input_port.pw_id().0], ); true @@ -336,14 +337,18 @@ glib::wrapper! { } impl Port { - pub fn new(id: u32, name: &str, direction: Direction) -> Self { + pub fn new(id: PortId, name: &str, direction: Direction) -> Self { glib::Object::builder() - .property("pipewire-id", id) + .property("pipewire-id", id.0) .property("direction", direction.as_raw()) .property("name", name) .build() } + pub fn pw_id(&self) -> PortId { + PortId(self.property("pipewire-id")) + } + pub fn link_anchor(&self) -> graphene::Point { let imp = self.imp(); let handle = &imp.handle;