Skip to content

Commit 363716c

Browse files
committed
fix(sound): devices disappear when setting profile to Off
1 parent cdf3528 commit 363716c

File tree

5 files changed

+271
-235
lines changed

5 files changed

+271
-235
lines changed

cosmic-settings/src/pages/sound/device_profiles.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,7 @@ pub fn view() -> Section<crate::pages::Message> {
7676
.device_profiles
7777
.iter()
7878
.filter_map(|(object_id, profiles)| {
79-
let name = sound_page
80-
.model
81-
.device_descriptions
82-
.get(object_id)?
83-
.as_str();
79+
let name = sound_page.model.device_names.get(object_id)?.as_str();
8480

8581
// TODO: cache
8682
let active_profile =
@@ -89,10 +85,7 @@ pub fn view() -> Section<crate::pages::Message> {
8985
.active_profiles
9086
.get(object_id)
9187
.and_then(|profile| {
92-
sound_page
93-
.model
94-
.device_profiles
95-
.get(object_id)?
88+
profiles
9689
.iter()
9790
.enumerate()
9891
.find(|(_, p)| p.index == profile.index)

subscriptions/sound/src/lib.rs

Lines changed: 58 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use futures::{Stream, StreamExt};
1111
use intmap::IntMap;
1212
use std::{sync::Arc, time::Duration};
1313

14+
pub type DeviceId = u32;
1415
pub type NodeId = u32;
1516
pub type ProfileId = u32;
1617

@@ -45,7 +46,7 @@ pub fn watch() -> impl Stream<Item = Message> + MaybeSend + 'static {
4546

4647
enum Variant {
4748
Pulse(pulse::Event),
48-
Pipewire(pipewire::DeviceEvent),
49+
Pipewire(pipewire::Event),
4950
}
5051

5152
let mut stream =
@@ -116,11 +117,12 @@ pub struct Model {
116117
subscription_handle: Option<SubscriptionHandle>,
117118
sink_channels: Option<pulse::PulseChannels>,
118119

119-
device_ids: IntMap<u32, u32>,
120-
pub device_names: IntMap<u32, String>,
121-
pub device_descriptions: IntMap<u32, String>,
122-
pub device_profiles: IntMap<u32, Vec<pipewire::Profile>>,
123-
pub active_profiles: IntMap<u32, pipewire::Profile>,
120+
device_ids: IntMap<NodeId, DeviceId>,
121+
pub node_names: IntMap<NodeId, String>,
122+
pub node_descriptions: IntMap<NodeId, String>,
123+
pub device_names: IntMap<DeviceId, String>,
124+
pub device_profiles: IntMap<DeviceId, Vec<pipewire::Profile>>,
125+
pub active_profiles: IntMap<DeviceId, pipewire::Profile>,
124126

125127
/** Sink devices */
126128

@@ -208,23 +210,19 @@ impl Model {
208210
/// Sets and applies a profile to a device with wpctl.
209211
///
210212
/// Requires using the device ID rather than a node ID.
211-
pub fn set_profile(&mut self, object_id: u32, pos: usize) {
212-
if let Some((profiles, &device_id)) = self
213-
.device_profiles
214-
.get(object_id)
215-
.zip(self.device_ids.get(object_id))
216-
{
213+
pub fn set_profile(&mut self, device_id: DeviceId, pos: usize) {
214+
if let Some(profiles) = self.device_profiles.get(device_id) {
217215
if let Some(profile) = profiles.get(pos) {
218216
let index = profile.index as u32;
219217
tokio::spawn(async move {
220218
wpctl::set_profile(device_id, index).await;
221219
});
222220

223-
self.active_profiles.insert(object_id, profile.clone());
221+
self.active_profiles.insert(device_id, profile.clone());
224222

225-
if self.active_sink_device == Some(object_id) {
223+
if self.active_sink_device == Some(device_id) {
226224
self.active_sink_profile = Some(pos)
227-
} else if self.active_source_device == Some(object_id) {
225+
} else if self.active_source_device == Some(device_id) {
228226
self.active_source_profile = Some(pos);
229227
}
230228
}
@@ -395,11 +393,11 @@ impl Model {
395393
},
396394

397395
Server::Pipewire(event) => match event {
398-
pipewire::DeviceEvent::ActiveProfile(id, profile) => {
396+
pipewire::Event::ActiveProfile(id, profile) => {
399397
self.active_profiles.insert(id, profile);
400398
}
401399

402-
pipewire::DeviceEvent::AddProfile(id, profile) => {
400+
pipewire::Event::AddProfile(id, profile) => {
403401
let profiles = self.device_profiles.entry(id).or_default();
404402
for p in profiles.iter_mut() {
405403
if p.index == profile.index {
@@ -411,52 +409,55 @@ impl Model {
411409
profiles.push(profile);
412410
}
413411

414-
pipewire::DeviceEvent::Add(device) => {
415-
let object_id = device.object_id;
416-
if !self.device_names.contains_key(object_id) {
417-
match device.media_class {
412+
pipewire::Event::AddDevice(device) => {
413+
self.device_names.insert(device.id, device.name);
414+
}
415+
416+
pipewire::Event::AddNode(node) => {
417+
let object_id = node.object_id;
418+
if !self.node_names.contains_key(object_id) {
419+
match node.media_class {
418420
pipewire::MediaClass::Sink => {
419-
self.sinks.push(device.description.clone());
420-
self.sink_pw_ids.push(device.object_id);
421+
self.sinks.push(node.description.clone());
422+
self.sink_pw_ids.push(node.object_id);
421423

422424
sort_devices(&mut self.sinks, &mut self.sink_pw_ids);
423425

424-
if self.default_sink == device.node_name {
425-
self.set_default_sink_id(device.object_id);
426+
if self.default_sink == node.node_name {
427+
self.set_default_sink_id(node.object_id);
426428
}
427429
}
428430

429431
pipewire::MediaClass::Source => {
430-
self.sources.push(device.description.clone());
431-
self.source_pw_ids.push(device.object_id);
432+
self.sources.push(node.description.clone());
433+
self.source_pw_ids.push(node.object_id);
432434

433435
sort_devices(
434436
&mut self.sources,
435437
&mut self.source_pw_ids,
436438
);
437439

438-
if self.default_source == device.node_name {
440+
if self.default_source == node.node_name {
439441
self.set_default_source_id(object_id);
440442
}
441443
}
442444
}
443445

444-
if let Some(device_id) = device.device_id {
446+
if let Some(device_id) = node.device_id {
445447
self.device_ids.insert(object_id, device_id);
446448
}
447449

448-
self.device_names.insert(object_id, device.node_name);
449-
self.device_descriptions
450-
.insert(object_id, device.description);
450+
self.node_names.insert(object_id, node.node_name);
451+
self.node_descriptions.insert(object_id, node.description);
451452
}
452453

453-
if device.device_id.is_some() {
454-
if self.active_sink_device == device.device_id {
454+
if node.device_id.is_some() {
455+
if self.active_sink_device == node.device_id {
455456
self.set_default_sink_id(object_id);
456457
tokio::task::spawn(async move {
457458
wpctl::set_default(object_id).await;
458459
});
459-
} else if self.active_source_device == device.device_id {
460+
} else if self.active_source_device == node.device_id {
460461
self.set_default_source_id(object_id);
461462
tokio::task::spawn(async move {
462463
wpctl::set_default(object_id).await;
@@ -465,9 +466,8 @@ impl Model {
465466
}
466467
}
467468

468-
pipewire::DeviceEvent::Remove(object_id) => {
469-
self.remove_node(object_id);
470-
}
469+
pipewire::Event::RemoveDevice(id) => self.remove_device(id),
470+
pipewire::Event::RemoveNode(id) => self.remove_node(id),
471471
},
472472
}
473473
}
@@ -509,68 +509,56 @@ impl Model {
509509
}
510510

511511
fn node_id_from_name(&self, name: &str) -> Option<u32> {
512-
self.device_names
512+
self.node_names
513513
.iter()
514514
.find(|&(_, n)| *n == name)
515515
.map(|(id, _)| id)
516516
}
517517

518-
fn remove_node(&mut self, object_id: u32) {
519-
if let Some(pos) = self
520-
.sink_pw_ids
521-
.iter()
522-
.position(|&node_id| node_id == object_id)
523-
{
518+
fn remove_device(&mut self, id: DeviceId) {
519+
_ = self.device_names.remove(id);
520+
_ = self.device_profiles.remove(id);
521+
_ = self.active_profiles.remove(id);
522+
}
523+
524+
fn remove_node(&mut self, id: NodeId) {
525+
if let Some(pos) = self.sink_pw_ids.iter().position(|&node_id| node_id == id) {
524526
self.sink_pw_ids.remove(pos);
525527
self.sinks.remove(pos);
526-
if self.active_sink_device == Some(object_id) {
528+
if self.active_sink_device == Some(id) {
527529
self.active_sink = None;
528-
self.active_sink_device = self.device_ids.get(object_id).cloned();
530+
self.active_sink_device = self.device_ids.get(id).cloned();
529531
} else if let Some(id) = self.active_sink_device {
530532
self.set_default_sink_id(id);
531533
}
532-
} else if let Some(pos) = self
533-
.source_pw_ids
534-
.iter()
535-
.position(|&node_id| node_id == object_id)
536-
{
534+
} else if let Some(pos) = self.source_pw_ids.iter().position(|&node_id| node_id == id) {
537535
self.source_pw_ids.remove(pos);
538536
self.sources.remove(pos);
539-
if self.active_source_device == Some(object_id) {
537+
if self.active_source_device == Some(id) {
540538
self.active_source = None;
541-
self.active_source_device = self.device_ids.get(object_id).cloned();
539+
self.active_source_device = self.device_ids.get(id).cloned();
542540
} else if let Some(id) = self.active_source_device {
543541
self.set_default_source_id(id);
544542
}
545543
}
546544

547-
_ = self.device_ids.remove(object_id);
548-
_ = self.device_names.remove(object_id);
549-
_ = self.device_descriptions.remove(object_id);
550-
_ = self.device_profiles.remove(object_id);
551-
_ = self.active_profiles.remove(object_id);
545+
_ = self.device_ids.remove(id);
546+
_ = self.node_names.remove(id);
547+
_ = self.node_descriptions.remove(id);
552548
}
553549

554550
/// Set the default sink device by its the node ID.
555551
fn set_default_sink_id(&mut self, object_id: u32) {
556552
self.active_sink = self.sink_pw_ids.iter().position(|&id| id == object_id);
557553
self.active_sink_device = Some(object_id);
558-
self.default_sink = self
559-
.device_names
560-
.get(object_id)
561-
.cloned()
562-
.unwrap_or_default();
554+
self.default_sink = self.node_names.get(object_id).cloned().unwrap_or_default();
563555
}
564556

565557
/// Set the default source device by its the node ID.
566558
fn set_default_source_id(&mut self, object_id: u32) {
567559
self.active_source = self.source_pw_ids.iter().position(|&id| id == object_id);
568560
self.active_source_device = Some(object_id);
569-
self.default_source = self
570-
.device_names
571-
.get(object_id)
572-
.cloned()
573-
.unwrap_or_default();
561+
self.default_source = self.node_names.get(object_id).cloned().unwrap_or_default();
574562
}
575563
}
576564

@@ -593,7 +581,7 @@ pub enum Server {
593581
/// Get default sinks/sources and their volumes/mute status.
594582
Pulse(pulse::Event),
595583
/// Get ALSA cards and their profiles.
596-
Pipewire(pipewire::DeviceEvent),
584+
Pipewire(pipewire::Event),
597585
}
598586

599587
pub struct SubscriptionHandle {

0 commit comments

Comments
 (0)