aboutsummaryrefslogtreecommitdiffstats
path: root/volume-osd/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'volume-osd/README.md')
-rw-r--r--volume-osd/README.md159
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.