9329d250f6
- one window per monitor (namespace magic-workspaces, Overlay like the island), showing that monitor's hyprland workspaces in the island's look: cover gradient, pink glow - focused workspace pink, shown-elsewhere soft pink, empty ones dim; hover eases in (one at a time), a click switches workspace - special workspaces are skipped; name-only ones show their first letter - event-driven through Workspaces: redraws only on hyprland events and hover
81 lines
4.7 KiB
Markdown
81 lines
4.7 KiB
Markdown
# Magic Island: an Amane media widget
|
|
|
|
A Dynamic-Island-style media widget for Amane (Rust Wayland shell library), running on Hyprland. It sits as a small pill at the top centre of the screen and opens into a now-playing card.
|
|
|
|
- **Pill:** cover thumbnail, title, 7 live bars from the shown player's own sound (lows left, highs right, growing up and down from the middle), or a pause sign.
|
|
- **Card:** a still CD of the cover ringed by 40 cava "candles", title and artist, a seekable time bar, previous / play-pause / next.
|
|
- **Player switcher** ("VIA …" chip): every MPRIS player; picking one pins it, otherwise the island follows whichever plays.
|
|
- **Output switcher:** moves only the shown player's audio to another device.
|
|
- **Per-player volume** (scroll the volume chip, click to mute), set on that player's own PulseAudio/PipeWire streams, so it also works for browsers that ignore MPRIS volume.
|
|
- **Real 10-band equalizer per player** (31 Hz to 16 kHz, ±12 dB): a PipeWire filter-chain per player, with 8 presets (Flat, Bass, Treble, Vocal, Pop, Rock, Jazz, Classic). Curves are saved per player.
|
|
- **Background:** a diagonal gradient from the cover's own colours, darkened so white text stays readable.
|
|
- **Opening animation:** the pill fades out, the empty shape grows, then the card fades in. Closing runs backwards. Moving the pointer off the open card closes it.
|
|
- **Every monitor:** each monitor shows the pill. The card opens only on the monitor you click (a keybind opens it on the focused one), and only the focused monitor's pill shows live bars; the others show still bars, which keeps the cost at about one island's.
|
|
- **Workspace pill:** top left on every monitor, that monitor's Hyprland workspaces as round numbered slots in the island's look. The focused workspace is pink, the one shown on another monitor a softer pink, empty ones dim. Click one to switch to it.
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/main.rs app setup: Fira Code font, the `island` IPC handler, palette from the cover
|
|
src/island.rs the view: pill, card, ring, equalizer, dropdowns, animation, IPC commands
|
|
src/sound.rs per-player volume, mute, output and equalizer (pactl, pw-cli, pipewire)
|
|
src/spectrum.rs the shown player's sound as 24 levels (pw-record | cava)
|
|
src/art.rs cover download (curl) and the palette file
|
|
src/workspaces.rs the workspace pill, top left on every monitor
|
|
src/parse.rs pure text parsing with unit tests, no amane dependency
|
|
island-eq saved equalizer curves (a snapshot of ~/.config/amane/island-eq)
|
|
tools/ remote test driver and fake MPRIS players, see AGENTS.md
|
|
```
|
|
|
|
## Requirements
|
|
|
|
On the desktop that runs the shell:
|
|
|
|
- the `amane` CLI and Rust toolchain (`amane compile` builds `src/`)
|
|
- PipeWire with `pipewire-pulse`: `pactl`, `pw-record`, `pw-cli`, `pipewire` (filter-chain module)
|
|
- `cava`, `curl`
|
|
- the Fira Code font
|
|
|
|
## Install and run
|
|
|
|
The shell lives in `~/.config/amane/`. Copy (or clone) this repo's `src/` there, then build and start:
|
|
|
|
```sh
|
|
amane compile
|
|
~/.cache/amane/project/target/debug/amane-shell
|
|
```
|
|
|
|
The installed CLI on the current desktop is older than the Amane docs: it doesn't save `~/.cache/amane/amane-shell`, so `amane run` has nothing to start. Run the binary above directly.
|
|
|
|
## Control it
|
|
|
|
```sh
|
|
amane ipc call island toggle # also: open, close
|
|
amane ipc call island next # show the next player
|
|
amane ipc call island play-pause # play/pause the shown player; the icon flips at once
|
|
amane ipc call island menu output # open a dropdown: output | player | close
|
|
amane ipc call island preset Rock # apply an equalizer preset to the shown player
|
|
amane ipc call island output <sink> # move the shown player to a sink (pactl sink name)
|
|
amane ipc call island status # player=<identity> expanded=<bool> menu=<bool>
|
|
```
|
|
|
|
Example Hyprland keybind:
|
|
|
|
```
|
|
bind = SUPER, M, exec, amane ipc call island toggle
|
|
```
|
|
|
|
## Runtime files
|
|
|
|
- `~/.config/amane/island-eq`: one line per player identity, `<player>\t<preset or Custom>\t<10 gains in dB>`.
|
|
- `$XDG_RUNTIME_DIR/magic-island/`: downloaded covers, `palette-cover`, `cava.conf`, `eq-<key>.conf`. On tmpfs, gone at logout.
|
|
- Equalizer nodes are named `magic_island_eq.<key>`. The key is the player's MPRIS bus name without `org.mpris.MediaPlayer2.`, non-alphanumerics as `_` (e.g. `chromium_instance123`).
|
|
|
|
## Known limits
|
|
|
|
- The time bar moves in 1 s steps (the MPRIS poll rate).
|
|
- Every slider step starts one `pactl` or `pw-cli` process.
|
|
- An equalizer keeps running, and keeps that player routed through its last curve, if the shell stops while the player is open.
|
|
- The candle ring around the CD is still mirrored left against right; the pill's bars are not.
|
|
- Dropdowns have no keyboard navigation.
|