spotify-player: inset the special workspace window; keep cava on with playback

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-08-16 13:45:15 +01:00
parent d1c92394e5
commit 016b9bdd48
2 changed files with 28 additions and 8 deletions

View file

@ -333,6 +333,20 @@ in
workspace = "special:music silent", workspace = "special:music silent",
}) })
-- Inset it rather than filling the screen, so the workspace
-- underneath still frames it. Floating is what makes a percentage
-- size stick: a tiled window is sized by the layout, which would
-- just expand it back to the full area. Matched on title for the
-- same reason as above, and because matching on the special
-- workspace would depend on the assignment rule running first.
hl.window_rule({
name = "spotify-player-inset",
match = { title = "^spotify-player$" },
float = true,
size = "80% 80%",
center = true,
})
-- Games stall on other workspaces: no frame callbacks = no render = -- Games stall on other workspaces: no frame callbacks = no render =
-- game loop blocks. Keep them ticking in the background at -- game loop blocks. Keep them ticking in the background at
-- misc:render_unfocused_fps (15). -- misc:render_unfocused_fps (15).

View file

@ -6191,16 +6191,21 @@ in
return Math.floor(s / 60) + ":" + ("0" + Math.floor(s % 60)).slice(-2); return Math.floor(s / 60) + ":" + ("0" + Math.floor(s % 60)).slice(-2);
} }
// Live spectrum for the media cards' rings. cava runs only // Live spectrum for the media cards' rings. Tied to playback
// while this popup is open AND something is playing, so it // rather than to the popup: gating on `open` restarted cava
// isn't capturing audio in the background. levels is a // on every open, and its bars ramp up from flat, so the
// barCount-long array of 0-100 ints, one frame per tick. // ring visibly booted each time instead of being mid-song
// when it appeared. The cost is cava capturing while the
// popup is closed, but only ever while something is
// actually playing. levels is a barCount-long array of
// 0-100 ints, one frame per tick.
readonly property int barCount: 24 readonly property int barCount: 24
property var levels: [] property var levels: []
Process { Process {
id: cavaProc id: cavaProc
running: calPopup.open && calPopup.players.length > 0 running: calPopup.players.some(
p => p.playbackState === MprisPlaybackState.Playing)
command: [Commands.cava, "-p", Commands.cavaConfig] command: [Commands.cava, "-p", Commands.cavaConfig]
stdout: SplitParser { stdout: SplitParser {
onRead: data => { onRead: data => {
@ -6215,9 +6220,10 @@ in
} }
} }
// Bars decay to flat when cava stops, so a paused card // Clear on the last frame of playback, not on close: cava
// doesn't keep the last frame frozen around the disc. // now outlives the popup, so wiping on close would throw
onOpenChanged: if (!open) levels = [] // away the live frames it is still producing.
onPlayersChanged: if (!cavaProc.running) levels = []
Row { Row {
id: calRow id: calRow