From 2bcd2e40d15942fa7fa4e07d0b75c67529b8c093 Mon Sep 17 00:00:00 2001 From: Nicolai Syvertsen Date: Sat, 22 Jun 2024 20:04:49 +0200 Subject: [PATCH] Add device property to PwNodeObject This can then be used to get notified when we have a PwNodeObject representing a sink/source and setup UI only when we have an associated device. --- src/backend/pwnodeobject.rs | 44 +++++++++++++++++++++++-------------- src/ui/route_dropdown.rs | 8 +++---- src/ui/sinkbox.rs | 23 ++++++++++++------- 3 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/backend/pwnodeobject.rs b/src/backend/pwnodeobject.rs index 80a05c9..b0d2458 100644 --- a/src/backend/pwnodeobject.rs +++ b/src/backend/pwnodeobject.rs @@ -87,6 +87,9 @@ pub mod imp { pub(super) block: Cell, pub(super) om: RefCell, + + #[property(get)] + pub(super) device: RefCell>, } impl Default for PwNodeObject { @@ -110,6 +113,7 @@ pub mod imp { block: Default::default(), om: Default::default(), hidden: Default::default(), + device: Default::default(), } } } @@ -216,21 +220,38 @@ pub mod imp { .iter().collect::>()); if let Ok(Some(device_id)) = node.device_id() { - om.add_interest([Constraint::compare(ConstraintType::PwGlobalProperty, "device.id", device_id, true)] + om.add_interest([Constraint::compare(ConstraintType::GProperty, "bound-id", device_id, true)] .iter() .collect::>()); } - - om.connect_object_added(clone!(@weak self as widget => move |_om, obj| { + om.connect_object_added(clone!(@weak self as nodeobject => move |_om, obj| { if let Some(link) = obj.downcast_ref::() { let linked_node_id: u32 = link.pw_property("link.input.node").expect("link.input.node property"); let linked_node = PwvucontrolManager::default().get_node_by_id(linked_node_id); - pwvucontrol_info!("Node {} linked to node id {linked_node_id} ({:?})", widget.obj().name(), linked_node.map(|x|x.name())); + pwvucontrol_info!("Node {} linked to node id {linked_node_id} ({:?})", nodeobject.obj().name(), linked_node.map(|x|x.name())); + } else if let Some(device) = obj.downcast_ref::() { + let device_name: String = device.pw_property("device.description").unwrap(); + let manager = PwvucontrolManager::default(); + nodeobject.device.set(manager.get_device_by_id(device.bound_id())); + nodeobject.obj().notify_device(); + pwvucontrol_info!("Node {} linked to device {device_name}", nodeobject.obj().name()); } })); PwvucontrolManager::default().wp_core().install_object_manager(&om); + + // let manager = PwvucontrolManager::default(); + // manager.device_model().connect_items_changed(clone!(@weak self as nodeobject => move |liststore, _position, _removed, _added| { + // for device in liststore.iter::().map_while(Result::ok) { + // let node = nodeobject.wpnode.get().expect("node"); + // if let Ok(Some(id)) = node.device_id() { + // if id == device.wpdevice().bound_id() { + // nodeobject.device.set(Some(device.clone())); + // } + // } + // } + // })); } } @@ -327,7 +348,7 @@ impl PwNodeObject { } } - pub(crate) fn update_format(&self) { + fn update_format(&self) { let node = self.imp().wpnode.get().expect("node"); node.enum_params(Some("Format"), None, gtk::gio::Cancellable::NONE, clone!(@weak self as widget, @weak node => move |res| { @@ -493,7 +514,7 @@ impl PwNodeObject { } } - pub(crate) fn set_format(&self, format: AudioFormat) { + fn set_format(&self, format: AudioFormat) { self.imp().format.set(Some(format)); self.emit_by_name::<()>("format", &[]); @@ -515,19 +536,10 @@ impl PwNodeObject { }; } - pub(crate) fn get_device(&self) -> Option { - - if let Ok(Some(device_id)) = self.wpnode().device_id() { - let manager = PwvucontrolManager::default(); - return manager.get_device_by_id(device_id); - } - None - } - pub(crate) fn set_route(&self, routeobj: &PwRouteObject) { let index = routeobj.index(); if let Ok(Some(card_profile_device)) = self.wpnode().device_index() { - if let Some(device) = self.get_device() { + if let Some(device) = self.device() { device.set_route(index, card_profile_device as i32); let profiles = routeobj.get_profiles(); diff --git a/src/ui/route_dropdown.rs b/src/ui/route_dropdown.rs index 9d9ba01..098bd0c 100644 --- a/src/ui/route_dropdown.rs +++ b/src/ui/route_dropdown.rs @@ -55,7 +55,7 @@ mod imp { let nodeobject = self.nodeobject.borrow(); let nodeobject = nodeobject.as_ref().unwrap(); - let Some(deviceobject) = nodeobject.get_device() else { + let Some(deviceobject) = nodeobject.device() else { return None; }; match nodeobject.nodetype() { @@ -69,7 +69,7 @@ mod imp { let nodeobject = self.nodeobject.borrow(); let nodeobject = nodeobject.as_ref().unwrap(); - let deviceobject = nodeobject.get_device().expect("device"); + let deviceobject = nodeobject.device().expect("device"); match nodeobject.nodetype() { NodeType::Source => Some(deviceobject.routemodel_input()), NodeType::Sink => Some(deviceobject.routemodel_output()), @@ -81,9 +81,7 @@ mod imp { self.nodeobject.replace(new_nodeobject.cloned()); if let Some(nodeobject) = new_nodeobject { - let Some(deviceobject) = nodeobject.get_device() else { - return; - }; + let deviceobject = nodeobject.device().expect("nodeobject with associated device on PwRouteDropDown"); self.block_signal.set(true); pwvucontrol_info!("self.route_dropdown.set_model({});", deviceobject.wpdevice().bound_id()); diff --git a/src/ui/sinkbox.rs b/src/ui/sinkbox.rs index 02e661f..ee64c87 100644 --- a/src/ui/sinkbox.rs +++ b/src/ui/sinkbox.rs @@ -52,15 +52,22 @@ mod imp { widget.obj().default_node_changed(); })); - glib::idle_add_local_once(clone!(@weak self as widget => move || { - widget.obj().default_node_changed(); + // Only set nodeobject once it has a device associated. + if let Some(node) = obj.node_object() { + node.connect_device_notify(clone!(@weak self as widget => move |nodeobject| { + widget.route_dropdown.set_nodeobject(Some(nodeobject)); + })); + } - // TODO: Hack! Associated PwDeviceObject for a sink type PwNodeObject may not have been added to model yet at this time. - // Delay the set_nodeobject call as workaround for now. - if let Some(node) = widget.obj().node_object() { - widget.route_dropdown.set_nodeobject(Some(node)); - } - })); + // glib::idle_add_local_once(clone!(@weak self as widget => move || { + // widget.obj().default_node_changed(); + + // // TODO: Hack! Associated PwDeviceObject for a sink type PwNodeObject may not have been added to model yet at this time. + // // Delay the set_nodeobject call as workaround for now. + // if let Some(node) = widget.obj().node_object() { + // widget.route_dropdown.set_nodeobject(Some(node)); + // } + // })); pwvucontrol_info!("sinkbox set_nodeobject {}", self.obj().node_object().expect("Node object").name()); }