Add the Music Library plugin (+ universal workspace scoping) #33

Merged
parkerhdavis merged 18 commits from music-library-plugin into main 2026-05-30 01:45:42 -06:00
parkerhdavis commented 2026-05-30 01:45:10 -06:00 (Migrated from github.com)

Garnet's second plugin — a local music player built on the Workspace + Workflow model — plus the base groundwork it needed. This is the first catalog-backed plugin: its Workflow reads the indexed library (not an OS working folder), which generalized the working-folder capability to every workspace type.

Base groundwork

  • Universal workspace scoping. The working-folder + file-filters capability (previously texturing-only) now applies to every workspace type, including the base Library. Backed by a new AssetQuery.under_path folder filter and a workspaceScopeQuery helper.
  • Audio tag extraction in the indexer via lofty — audio assets get audio.{title,artist,album,album_artist,track,disc,year,genre,duration_secs,sample_rate,bit_depth,channels,has_cover} rows, surfaced on the detail page for everyone. The scan backfills metadata for already-indexed files (version-aware for audio) so existing libraries pick up new fields on the next scan.

The plugin (music, default-enabled)

  • Backend backend/src/music/ — list_music_library (Rust-side album/artist grouping), load_album_art (embedded → folder-cover fallback, cached), a native Rust player (Symphonia + Rodio, adapted from Starling — WebKitGTK chops compressed audio on Linux), get_audio_peaks + prewarm_peaks (cached under \$XDG_CACHE_HOME/garnet/peaks/, never written into the user's music folders).
  • Frontend src/plugins/music/ — album-cover grid / artist sections → album detail (blurred backdrop, quality chips, Hi-Res badge, track table with hover-to-play + animated now-playing indicator) → a persistent global player (mounted via a new plugin global slot, survives leaving the workspace) with a lazy-loaded wavesurfer.js waveform, shuffle/repeat modes, and an up-next queue panel.
  • Navigation — album/artist selection lives in the URL so Back works within the workspace; the app remembers and restores the last route on launch. Clickable artists + a library search box.

Perf

  • opt-level = 3 for the audio-decode crates in the dev profile, and the peaks decode runs on the blocking pool — so first-play isn't stalled by a full-file decode. prewarm_peaks warms the cache in the background so first-play is instant.

Notes

  • New Linux build dep: libasound2-dev (cpal), now probed by make setup.
  • make lint typecheck test is green: 127 Rust tests + 13 frontend tests.
Garnet's second plugin — a local music player built on the Workspace + Workflow model — plus the base groundwork it needed. This is the first **catalog-backed** plugin: its Workflow reads the indexed library (not an OS working folder), which generalized the working-folder capability to every workspace type. ## Base groundwork - **Universal workspace scoping.** The working-folder + file-filters capability (previously texturing-only) now applies to every workspace type, including the base Library. Backed by a new `AssetQuery.under_path` folder filter and a `workspaceScopeQuery` helper. - **Audio tag extraction in the indexer** via `lofty` — audio assets get `audio.{title,artist,album,album_artist,track,disc,year,genre,duration_secs,sample_rate,bit_depth,channels,has_cover}` rows, surfaced on the detail page for everyone. The scan **backfills** metadata for already-indexed files (version-aware for audio) so existing libraries pick up new fields on the next scan. ## The plugin (`music`, default-enabled) - **Backend `backend/src/music/`** — `list_music_library` (Rust-side album/artist grouping), `load_album_art` (embedded → folder-cover fallback, cached), a **native Rust player** (Symphonia + Rodio, adapted from Starling — WebKitGTK chops compressed audio on Linux), `get_audio_peaks` + `prewarm_peaks` (cached under `\$XDG_CACHE_HOME/garnet/peaks/`, never written into the user's music folders). - **Frontend `src/plugins/music/`** — album-cover grid / artist sections → album detail (blurred backdrop, quality chips, Hi-Res badge, track table with hover-to-play + animated now-playing indicator) → a **persistent global player** (mounted via a new plugin `global` slot, survives leaving the workspace) with a lazy-loaded `wavesurfer.js` waveform, shuffle/repeat modes, and an up-next queue panel. - **Navigation** — album/artist selection lives in the URL so Back works within the workspace; the app remembers and restores the last route on launch. Clickable artists + a library search box. ## Perf - `opt-level = 3` for the audio-decode crates in the dev profile, and the peaks decode runs on the blocking pool — so first-play isn't stalled by a full-file decode. `prewarm_peaks` warms the cache in the background so first-play is instant. ## Notes - New Linux build dep: `libasound2-dev` (cpal), now probed by `make setup`. - `make lint typecheck test` is green: 127 Rust tests + 13 frontend tests.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
parker/garnet!33
No description provided.