Skip to content

Commit 84ff320

Browse files
committed
feat(sound): retain active sink/source device on external profile change
1 parent eeec525 commit 84ff320

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

subscriptions/sound/src/lib.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ pub struct Model {
8787
sink_node_ids: Vec<NodeId>,
8888
/// Index of active sink device.
8989
active_sink: Option<usize>,
90+
/// Node ID of active sink device.
91+
active_sink_node: Option<NodeId>,
9092
/// Device ID of active sink device.
91-
active_sink_node: Option<u32>,
93+
active_sink_device: Option<DeviceId>,
9294
/// Device identifier of the default sink.
9395
active_sink_node_name: String,
9496

@@ -101,7 +103,9 @@ pub struct Model {
101103
/// Index of active source device.
102104
active_source: Option<usize>,
103105
/// Node ID of active source device.
104-
active_source_node: Option<u32>,
106+
active_source_node: Option<NodeId>,
107+
/// Device ID of active source device.
108+
active_source_device: Option<DeviceId>,
105109
/// Node identifier of the default source.
106110
active_source_node_name: String,
107111

@@ -470,6 +474,32 @@ impl Model {
470474
);
471475

472476
self.update_device_route_name(&route, id);
477+
478+
let (active_device, node_ids, set_default_node): (
479+
Option<DeviceId>,
480+
&[NodeId],
481+
fn(&mut Self, NodeId),
482+
) = match route.direction {
483+
pipewire::Direction::Output => (
484+
self.active_sink_device.clone(),
485+
&self.sink_node_ids,
486+
Self::set_default_sink_node_id,
487+
),
488+
pipewire::Direction::Input => (
489+
self.active_source_device.clone(),
490+
&self.source_node_ids,
491+
Self::set_default_source_node_id,
492+
),
493+
};
494+
495+
if active_device == Some(id) {
496+
for (node_id, &device) in &self.device_ids {
497+
if device == id && node_ids.contains(&node_id) {
498+
set_default_node(self, node_id);
499+
break;
500+
}
501+
}
502+
}
473503
}
474504

475505
pipewire::Event::AddProfile(id, profile) => {
@@ -684,13 +714,21 @@ impl Model {
684714
self.active_sink = self.sink_node_ids.iter().position(|&id| id == node_id);
685715
self.active_sink_node = Some(node_id);
686716
self.active_sink_node_name = self.node_names.get(node_id).cloned().unwrap_or_default();
717+
self.active_sink_device = self
718+
.device_ids
719+
.iter()
720+
.find_map(|(nid, did)| if nid == node_id { Some(*did) } else { None });
687721
}
688722

689723
/// Set the default source device by its the node ID.
690724
fn set_default_source_id(&mut self, node_id: NodeId) {
691725
self.active_source = self.source_node_ids.iter().position(|&id| id == node_id);
692726
self.active_source_node = Some(node_id);
693727
self.active_source_node_name = self.node_names.get(node_id).cloned().unwrap_or_default();
728+
self.active_source_device = self
729+
.device_ids
730+
.iter()
731+
.find_map(|(nid, did)| if nid == node_id { Some(*did) } else { None });
694732
}
695733

696734
fn update_device_route_name(&mut self, route: &pipewire::Route, id: DeviceId) {

0 commit comments

Comments
 (0)