Delete items from graph when they are removed by the pipewire server.

This commit is contained in:
Tom A. Wagner
2021-01-08 12:34:22 +01:00
parent 9784b9bae0
commit 181661a2db
5 changed files with 233 additions and 104 deletions

View File

@@ -1,50 +1,64 @@
use crate::PipewireLink;
use crate::pipewire_state::PipewireState;
use gtk::glib::{self, clone};
use pipewire as pw;
use pw::{port::Direction, registry::ObjectType, PW_ID_CORE};
use std::{
cell::{Cell, RefCell},
rc::Rc,
};
/// This struct is responsible for communication with the pipewire server.
/// It handles new globals appearing as well as globals being removed.
///
/// It's `roundtrip` function must be called regularly to receive updates.
pub struct PipewireConnection {
mainloop: pw::MainLoop,
_context: pw::Context<pw::MainLoop>,
core: pw::Core,
core: Rc<pw::Core>,
_registry: pw::registry::Registry,
_reg_listeners: pw::registry::Listener,
_listeners: pw::registry::Listener,
_state: Rc<RefCell<PipewireState>>,
}
impl PipewireConnection {
pub fn new(graphview: Rc<RefCell<crate::view::GraphView>>) -> Result<Self, String> {
pub fn new(state: PipewireState) -> Result<Self, String> {
// Initialize pipewire lib and obtain needed pipewire objects.
pw::init();
let mainloop = pw::MainLoop::new().map_err(|_| "Failed to create pipewire mainloop!")?;
let context =
pw::Context::new(&mainloop).map_err(|_| "Failed to create pipewire context")?;
let core = context
.connect()
.map_err(|_| "Failed to connect to pipewire core")?;
let core = Rc::new(
context
.connect()
.map_err(|_| "Failed to connect to pipewire core")?,
);
let registry = core.get_registry();
let graphview = Rc::downgrade(&graphview.clone());
let reg_listeners = registry
let state = Rc::new(RefCell::new(state));
// Notify state on globals added / removed
let _listeners = registry
.add_listener_local()
.global(move |global| {
PipewireConnection::handle_global(graphview.upgrade().unwrap(), global)
})
.global_remove(|_| { /* TODO */ })
.global(clone!(@weak state => @default-panic, move |global| {
state.borrow_mut().global(global);
}))
.global_remove(clone!(@weak state => @default-panic, move |id| {
state.borrow_mut().global_remove(id);
}))
.register();
Ok(Self {
mainloop,
mainloop: mainloop,
_context: context,
core,
_registry: registry,
_reg_listeners: reg_listeners,
_listeners,
_state: state,
})
}
/// Receive all events from the pipewire server, sending them to the `pipewire_state` struct for processing.
pub fn roundtrip(&self) {
let done = Rc::new(Cell::new(false));
let pending = self.core.sync(0);
@@ -56,7 +70,7 @@ impl PipewireConnection {
.core
.add_listener_local()
.done(move |id, seq| {
if id == PW_ID_CORE && seq == pending {
if id == pw::PW_ID_CORE && seq == pending {
done_clone.set(true);
loop_clone.quit();
}
@@ -67,89 +81,4 @@ impl PipewireConnection {
self.mainloop.run();
}
}
fn handle_global(
graphview: Rc<RefCell<crate::view::GraphView>>,
global: pw::registry::GlobalObject,
) {
match global.type_ {
ObjectType::Node => {
let node_widget = crate::view::Node::new(&format!(
"{}",
global
.props
.map(|dict| String::from(
dict.get("node.nick")
.or(dict.get("node.description"))
.or(dict.get("node.name"))
.unwrap_or_default()
))
.unwrap_or_default()
));
graphview.borrow_mut().add_node(global.id, node_widget);
}
ObjectType::Port => {
let props = global.props.expect("Port object is missing properties");
let port_label = format!("{}", props.get("port.name").unwrap_or_default());
let node_id: u32 = props
.get("node.id")
.expect("Port has no node.id property!")
.parse()
.expect("Could not parse node.id property");
let port = crate::view::port::Port::new(
global.id,
&port_label,
if matches!(props.get("port.direction"), Some("in")) {
Direction::Input
} else {
Direction::Output
},
);
graphview
.borrow_mut()
.add_port_to_node(node_id, global.id, port);
}
ObjectType::Link => {
let props = global.props.expect("Link object is missing properties");
let input_node: u32 = props
.get("link.input.node")
.expect("Link has no link.input.node property")
.parse()
.expect("Could not parse link.input.node property");
let input_port: u32 = props
.get("link.input.port")
.expect("Link has no link.input.port property")
.parse()
.expect("Could not parse link.input.port property");
let output_node: u32 = props
.get("link.output.node")
.expect("Link has no link.input.node property")
.parse()
.expect("Could not parse link.input.node property");
let output_port: u32 = props
.get("link.output.port")
.expect("Link has no link.output.port property")
.parse()
.expect("Could not parse link.output.port property");
graphview.borrow_mut().add_link(
global.id,
PipewireLink {
node_from: output_node,
port_from: output_port,
node_to: input_node,
port_to: input_port,
},
);
}
_ => {}
}
}
}
/*impl Drop for PipewireConnection {
fn drop(&mut self) {
unsafe { pw::deinit() }
}
}*/