diff options
Diffstat (limited to 'volume-osd/README.md')
| -rw-r--r-- | volume-osd/README.md | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/volume-osd/README.md b/volume-osd/README.md deleted file mode 100644 index f0a8313..0000000 --- a/volume-osd/README.md +++ /dev/null @@ -1,159 +0,0 @@ -# volume-osd - -An on-screen display for volume, covering both output (speakers) and input -(microphone). It appears at the bottom of the screen when the level or mute -state changes, and fades out 1.5 seconds later. - - ┌────────────────────────────────────┐ - │ ▪ Outside World ⏮ ⏸ ⏭ │ - │ Sunbeam │ - │ ──────────────────────────────── │ - │ 🔊 Output 75% │ - │ ████████████████░░░░░░░░░░ │ - └────────────────────────────────────┘ - - (the track row only exists while a player does) - -## Running it - - qs -p . - -From Hyprland, to start it with the session: - - exec-once = qs -p ~/Programming/GIT/quickshell/volume-osd - -## Now playing - -When an MPRIS player is running, a track row sits above the volume bar: album -art, title, artist, and prev/play/next. With no player the panel is exactly -the volume OSD, at its original size. A track change or a play/pause shows the -panel too, so the row is not something you only see by touching the volume. - -Hovering the panel freezes its fade so the buttons can be clicked; moving away -starts the countdown again. Without a hover it behaves exactly as it did before -there was anything clickable on it. It still takes no keyboard focus. - -Two things about MPRIS that are not obvious: - -**Proxies publish duplicates.** playerctld proxies whichever player is -active and republishes it under `org.mpris.MediaPlayer2.playerctld`. With a -browser, plasma-browser-integration does the same, so one Navidrome tab was -live on three bus names at once. `Player.qml` drops both proxies and talks to -the browser's own entry. None of the three exists until playback starts, and -an open but silent tab publishes nothing at all. The plasma name is a browser -thing only: Feishin, playing from the same server, publishes just its own -entry and playerctld, so dropping it costs a native player nothing. - -**Album art can be a reused temp path.** Audacious extracts embedded art to a -file in its cache and rewrites that same path on each track, so the URL repeats -while the image behind it changes. The source carries the track title as a -cache buster and `cache: false`, or the previous track's cover stays on screen. - -Verified against audacious, Feishin, and Firefox playing Navidrome. Feishin is -the reference case, the only player here that fills the metadata in properly: -a real `mpris:artUrl`, `xesam:artist`, and a clean `xesam:title`. It is also -the only one whose art is a remote HTTP URL rather than a local file, so the -cover depends on reaching the Navidrome host. - -The same server through Firefox gives much less, which is a browser limit and -not something this component can fix. Navidrome's web player sets no -`mpris:artUrl` at all, so the row renders with no cover, and it packs -everything into `xesam:title` ("Roxanne - The Police - Navidrome") leaving -`xesam:artist` empty. Neither is worked around, a title like that cannot be -split back apart without guessing where a real dash ends. - -Signal publishes no MPRIS bus at all: playing an attachment claims no -`org.mpris.MediaPlayer2.*` name, only its tray `StatusNotifierItem`, so the -track row stays hidden and there is nothing here to fix. Any player that never -publishes is invisible to this component by construction. - -## No keybinds to change - -The OSD watches PipeWire rather than being triggered by a hotkey, so existing -volume binds keep working untouched: - - bind = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ - -Because the source of truth is PipeWire and not the keypress, the OSD also -appears for volume changed from anywhere else: pavucontrol, a per-application -slider, or another machine's remote control. - -One widget serves both directions. Whichever device changed last is the one -displayed, with a speaker icon for output and a microphone for input. - -Icons are Nerd Font glyphs (speaker and microphone), so the font stack needs a -Nerd Font available for fallback. Inconsolata Nerd Font Mono, which -unified-desktop-theme already installs, covers them. - -## Frosted glass - -The panel is drawn translucent (65% over the Macchiato base) and the blur -behind it comes from the compositor, not from QML. Hyprland blurs a layer -surface only when a rule says to, matched on the namespace this window sets -(`quickshell-volume-osd`): - - hl.layer_rule({ - name = "blur-volume-osd", - match = { namespace = "^(quickshell-volume-osd)$" }, - blur = true, - xray = false, - ignore_alpha = 0.1, - }) - -`xray = false` frosts the windows actually behind the OSD rather than jumping -straight to the wallpaper. `ignore_alpha = 0.1` leaves near-transparent pixels -unblurred, which keeps the rounded corners from picking up a halo. - -Doing it this way costs nothing in the shell: no `MultiEffect`, no live -blur pass in QML, no offscreen buffer. Without the rule the OSD still works, -it just renders flat translucent instead of frosted. - -## Theme - -`Theme.qml` holds no palette of its own beyond a fallback. The colours come -from `~/.cache/wal/udt-palette.qml`, which `udt-accent` generates on every -wallpaper change from unified-desktop-theme's `palette.rasi`, carrying the -whole Macchiato palette plus the accent snapped from the wallpaper. - -That file is watched, so editing the palette in unified-desktop-theme and -regenerating recolours a running OSD with no restart. Where the file does not -exist, the hardcoded defaults in `Theme.qml` apply, which is what keeps this -directory runnable on a machine without unified-desktop-theme. - -## Two details worth knowing - -**A node's volume arrives before it is ready.** When a `PwNode` binds, its -volume populates and emits a change signal, and that happens while `ready` is -still false. Those first signals are state being read, not the user turning a -knob, so `show()` checks `ready` and ignores them, which is why there is no -OSD at login. - -That one check is the whole guard, and it is tempting to add a second. An -earlier version also swallowed the first change per node, on the assumption -that the startup values arrived *after* ready. They do not, so the extra guard -ate the user's first keypress instead: the OSD only appeared from the second -change onward. If this symptom comes back, trace the signal order before -adding a filter. - -**`PwObjectTracker` is not optional.** PipeWire node properties are only kept -current while something binds the node. Without the tracker the volume reads -once and then goes stale, which looks like an OSD that displays a number from -several changes ago. - -**A config with no visible window exits.** The OSD is hidden most of the time, -so it holds itself open with a 1x1 transparent window with an empty mask, -which is click-through and draws nothing. Without it the shell loads, reports -no error, and quits, and the symptom is a keybind that appears to do nothing -or a panel that never paints. This was removed once during development after -misreading a process check, and the bug came straight back. - -**A Row sizes to its children, not to its parent.** The track row's text -column originally had a fixed width, and art + text + buttons + spacing came -to 356px inside a 328px content box, so the `next` button hung over the panel -edge. The column now takes whatever the art and transport buttons leave, which -holds at any panel width. Fixed widths inside a Row are worth distrusting. - -## Volume above 100% - -PipeWire allows volume over 1.0. The percentage is reported as-is, so it can -read above 100%, while the bar stops at full rather than overflowing its track. |
