diff --git a/data/resources/ui/window.ui b/data/resources/ui/window.ui
index f45320d..9a4e0f4 100644
--- a/data/resources/ui/window.ui
+++ b/data/resources/ui/window.ui
@@ -151,6 +151,47 @@
+
+
+
+
+
true
diff --git a/src/backend/manager.rs b/src/backend/manager.rs
index 335a0d6..d7f09c1 100644
--- a/src/backend/manager.rs
+++ b/src/backend/manager.rs
@@ -36,6 +36,7 @@ mod imp {
pub wp_object_manager: OnceCell,
pub nodemodel: PwNodeModel,
+ pub sourcemodel: PwNodeModel,
pub sinkmodel: PwNodeModel,
pub devicemodel: OnceCell,
@@ -105,7 +106,7 @@ mod imp {
let interest = wp::registry::ObjectInterest::new(
wp::pw::Node::static_type(),
);
- let variant = glib::Variant::from_str("('Stream/Output/Audio', 'Stream/Input/Audio', 'Audio/Sink')")
+ let variant = glib::Variant::from_str("('Stream/Output/Audio', 'Stream/Input/Audio', 'Audio/Source', 'Audio/Sink')")
.expect("variant");
interest.add_constraint(
wp::registry::ConstraintType::PwGlobalProperty,
@@ -168,6 +169,7 @@ mod imp {
let pwobj = PwNodeObject::new(node);
let model = match pwobj.nodetype() {
NodeType::Sink => &imp.sinkmodel,
+ NodeType::Source => &imp.sourcemodel,
_ => &imp.nodemodel
};
model.append(&pwobj);
@@ -187,6 +189,7 @@ mod imp {
pwvucontrol_info!("removed: {:?} id: {}", node.name(), node.bound_id());
let model = match pwnodeobject::get_node_type_for_node(node) {
NodeType::Sink => &imp.sinkmodel,
+ NodeType::Source => &imp.sourcemodel,
_ => &imp.nodemodel
};
model.remove(node.bound_id());
diff --git a/src/backend/pwnodeobject.rs b/src/backend/pwnodeobject.rs
index 480c77c..9d40ef1 100644
--- a/src/backend/pwnodeobject.rs
+++ b/src/backend/pwnodeobject.rs
@@ -220,6 +220,7 @@ pub(crate) fn get_node_type_for_node(node: &wp::pw::Node) -> NodeType {
match node.get_pw_property("media.class").as_deref() {
Some("Stream/Output/Audio") => NodeType::Output,
Some("Stream/Input/Audio") => NodeType::Input,
+ Some("Audio/Source") => NodeType::Source,
Some("Audio/Sink") => NodeType::Sink,
_ => NodeType::Undefined,
}
diff --git a/src/ui/route_dropdown.rs b/src/ui/route_dropdown.rs
index b2f4c3b..efee092 100644
--- a/src/ui/route_dropdown.rs
+++ b/src/ui/route_dropdown.rs
@@ -10,7 +10,7 @@ use crate::ui::PwProfileRow;
use crate::macros::*;
mod imp {
- use crate::backend::{PwNodeObject, PwRouteObject};
+ use crate::backend::{NodeType, PwNodeObject, PwRouteFilterModel, PwRouteObject};
use super::*;
@@ -44,27 +44,50 @@ mod imp {
impl PwRouteDropDown {
pub fn update_selected(&self) {
+ if let Some(index) = self.get_route_index() {
+ pwvucontrol_info!("update_selected with index {index}");
+ self.obj().set_selected_no_send(index);
+ }
+ }
+
+ fn get_route_index(&self) -> Option {
let nodeobject = self.nodeobject.borrow();
let nodeobject = nodeobject.as_ref().unwrap();
let deviceobject = nodeobject.get_device().expect("device");
+ match nodeobject.nodetype() {
+ NodeType::Input => Some(deviceobject.route_index_input()),
+ NodeType::Output => Some(deviceobject.route_index_output()),
+ _ => None
+ }
+ }
- pwvucontrol_info!("update_selected with index {}", deviceobject.route_index_output());
- self.obj().set_selected_no_send(deviceobject.route_index_output());
+ fn get_route_model(&self) -> Option {
+ let nodeobject = self.nodeobject.borrow();
+ let nodeobject = nodeobject.as_ref().unwrap();
+
+ let deviceobject = nodeobject.get_device().expect("device");
+ match nodeobject.nodetype() {
+ NodeType::Source => Some(deviceobject.routemodel_input()),
+ NodeType::Sink => Some(deviceobject.routemodel_output()),
+ _ => None
+ }
}
pub fn set_nodeobject(&self, new_nodeobject: Option<&PwNodeObject>) {
self.nodeobject.replace(new_nodeobject.cloned());
if let Some(nodeobject) = new_nodeobject {
+
let deviceobject = nodeobject.get_device().expect("device");
self.block_signal.set(true);
pwvucontrol_info!("self.route_dropdown.set_model({});", deviceobject.wpdevice().bound_id());
- self.route_dropdown.set_model(Some(&deviceobject.routemodel_output()));
- pwvucontrol_info!("self.route_dropdown.set_selected({});", deviceobject.route_index_output());
-
- self.route_dropdown.set_selected(deviceobject.route_index_output());
+ self.route_dropdown.set_model(self.get_route_model().as_ref());
+ if let Some(index) = self.get_route_index() {
+ pwvucontrol_info!("self.route_dropdown.set_selected({index});");
+ self.route_dropdown.set_selected(index);
+ }
self.block_signal.set(false);
diff --git a/src/ui/window.rs b/src/ui/window.rs
index 6eee77f..694c63e 100644
--- a/src/ui/window.rs
+++ b/src/ui/window.rs
@@ -38,6 +38,8 @@ mod imp {
#[template_child]
pub recordlist: TemplateChild,
#[template_child]
+ pub inputlist: TemplateChild,
+ #[template_child]
pub outputlist: TemplateChild,
#[template_child]
pub cardlist: TemplateChild,
@@ -56,6 +58,7 @@ mod imp {
stack: TemplateChild::default(),
playbacklist: TemplateChild::default(),
recordlist: TemplateChild::default(),
+ inputlist: TemplateChild::default(),
outputlist: TemplateChild::default(),
cardlist: TemplateChild::default(),
viewstack: TemplateChild::default(),
@@ -95,10 +98,12 @@ mod imp {
self.obj().setup_scroll_blocker(&self.playbacklist);
self.obj().setup_scroll_blocker(&self.recordlist);
+ self.obj().setup_scroll_blocker(&self.inputlist);
self.obj().setup_scroll_blocker(&self.outputlist);
let manager = PwvucontrolManager::default();
let model = &manager.imp().nodemodel;
+ let sourcemodel = &manager.imp().sourcemodel;
let sinkmodel = &manager.imp().sinkmodel;
let devicemodel = manager.imp().devicemodel.get().expect("Device model");
let window = self;
@@ -141,6 +146,17 @@ mod imp {
}),
);
+ self.inputlist.bind_model(
+ Some(sourcemodel),
+ clone!(@weak window => @default-panic, move |item| {
+ PwSinkBox::new(
+ item.downcast_ref::()
+ .expect("RowData is of wrong type"),
+ )
+ .upcast::()
+ }),
+ );
+
self.outputlist.bind_model(
Some(sinkmodel),
clone!(@weak window => @default-panic, move |item| {