Skip to content

fix(tb): stop showing the muted icon when the default audio device is lost - #1775

Merged
eythaann merged 2 commits into
eythaann:masterfrom
z1pp090:fix/media-default-device-muted-icon
Sep 4, 2026
Merged

eythaann merged 2 commits into
eythaann:masterfrom
z1pp090:fix/media-default-device-muted-icon

Conversation

@z1pp090

@z1pp090 z1pp090 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Problem

The toolbar volume icon shows the muted icon while the default output device is playing
audio normally. Windows reports the device as default, unmuted and at 100%, but
@seelen/tb-media-popup keeps drawing IoVolumeMuteOutline until Seelen UI is restarted.

Reproduced on 2.8.2 (Windows 11 26200, bluetooth speaker):

  1. Play audio on a bluetooth output device, everything looks right.
  2. Turn the bluetooth radio off and on again, or power-cycle the speaker, so the endpoint
    disappears and comes back.
  3. The device reconnects and audio works, but the toolbar icon stays muted. Restarting
    seelen-ui is the only way to recover it.

Root cause

Two separate bugs that compound each other.

1. DefaultDeviceChanged can clear every default flag.
IMMNotificationClient::OnDefaultDeviceChanged can report a device that DevicesManager has
not loaded yet, which happens routinely with bluetooth endpoints that are still being
enumerated. The handler then walks the map comparing ids:

devices.for_each(|(_, device)| {
    if *role == eMultimedia {
        device.is_default_multimedia = device.id == *device_id;
    }
});

Nothing matches, so the flag is cleared on every device and set on none. From that point on
the manager reports no default device at all.

2. "no default device" is rendered as "muted".
mediaStep defaults muted to true when there is no default device:

const { volume = 0, muted: isMuted = true } = defaultOutputDevice || {};

and the plugin template starts with return isMuted ? icon("IoVolumeMuteOutline") : ..., so a
device the user actually muted and a device the manager has lost are drawn with the exact same
icon. The toolbar reports a mute that does not exist.

Fix

  • application.rs: when the reported default id is not in the map, load that device first, so
    the flags always land on a real device.
  • scopes.svelte.ts: default muted to false. volume already defaults to 0, which
    renders the distinct "no output" icon, so the two states stay visually different.

Both isMuted and inputIsMuted are changed for consistency.

Notes

This may also be the underlying cause of #1590 ("nothing in the toolbox when I connect to my
bluetooth headset"): once no device is flagged as default, defaultOutput is undefined and
the media popup has nothing to render.

I could not build locally (no Rust toolchain on the machine where this was diagnosed), so the
Rust change is written against master and relies on CI for cargo fmt/clippy/test. The
analysis and the reproduction above are from a running 2.8.2 install.

z1pp090 and others added 2 commits August 28, 2026 11:35
…ded yet

`OnDefaultDeviceChanged` can arrive before the device it points at has been
loaded into the manager, which happens routinely with bluetooth endpoints that
are still being enumerated. In that case the `for_each` below cleared
`is_default_multimedia` / `is_default_communications` on every device and set it
on none, so the manager ended up reporting no default device at all until
something else triggered a reload.

Load the device first when the reported id is unknown, so the flags always land
on a real device.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…vice

`mediaStep` defaulted `muted` to `true` whenever no default device was found, so
the toolbar rendered `IoVolumeMuteOutline` for it. That is the exact same icon
used for a device the user actually muted, so a lost or not-yet-loaded output
device is indistinguishable from a real mute, and the toolbar reports a mute
that does not exist.

Default to `false` instead: volume already defaults to 0, which renders the
distinct "no output" icon.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@z1pp090

z1pp090 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Friendly ping on this one. It has been open since Aug 28 with no conflicts (mergeable: true) and the diff is small -- 19 added lines across 3 files, no API changes.

The fix is in two parts: OnDefaultDeviceChanged no longer clears every is_default_* flag when it receives a device the manager has not enumerated yet (routine with Bluetooth endpoints), and mediaStep no longer renders "no default device" as "muted".

Reproducible on 2.8.2 by power-cycling a Bluetooth speaker: audio comes back, the toolbar icon stays muted until seelen-ui is restarted.

Happy to rebase, split it into two commits, or adjust the approach if you would rather handle the missing-device case elsewhere.

@eythaann
eythaann merged commit 56bf57e into eythaann:master Sep 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants