gostations/todo/queued/per-station-volume.md
Greg Gauthier a2eaa03090
All checks were successful
CI / Test (push) Successful in 55s
Release / Create Release (push) Successful in 2m11s
CI / Build (push) Successful in 47s
feat(favorites): per-favorite volume persistence (narrowed to favorited stations only); update Station and Favorites with Volume support and wiring in TUI
2026-06-06 11:59:41 +01:00

4.8 KiB

Per-station volume savings (favorites only)

Description: Persist the last-used volume level only for stations in your favorites list (keyed by stream URL). When you return to a favorited station, it restores the volume you last set for that specific station (falling back to the global last-volume if none saved for it). Non-favorited stations always use the global last-volume.

Problem It Solves

Currently only a single global player.last_volume is saved in radiostations.ini. When a user fine-tunes the volume while listening to a favorited Station A (e.g. to 35), stops, then plays another favorited Station B, the volume resets to the global value (or default 70). Users have to re-adjust every time they switch between their own favorites. We deliberately limit this to favorited stations only (no unbounded per-station data for the entire radio-browser corpus).

Benefits

  • Natural UX: Volume preference is specific to your favorited stations (e.g. a quiet classical vs. a loud rock station).
  • Seamless resumption: Pick a favorite from your list → volume is already where you left it for that station.
  • Low friction: No extra UI; the existing volume controls + persistence just become smarter for your own list.
  • Backward compatible: Non-favorites always use global last-volume. Falls back gracefully.
  • Leverages existing patterns: Volumes live inside the favorites data (no new file or unbounded store). Same atomic JSON + XDG path.

High-Level Implementation

  1. Extend the existing Favorites store (no new file needed):

    • Add Volume int json:"volume,omitempty"`` field to radio.Station.
    • Add SetVolume(url string, vol int) and GetVolume(url string) int to *data.Favorites.
    • When Adding or updating a favorite while a volume is active, capture it on the station.
    • Volumes are automatically persisted inside favorites.json (only for stations you have favorited).
    • Remove naturally drops the volume data for that station.
  2. Wire into TUI / playback (in internal/ui/ui.go):

    • On entering playback for a station (Enter in list):
      • desired := config.LastVolume()
      • if v := a.favs.GetVolume(station.Url); v > 0 { desired = v }
      • Prefer live a.currentVolume for session stickiness across s/x within the same run.
      • Pass desired via --volume=... extra arg to Play().
    • On volume change (key handler and volumeMsg):
      • After updating currentVolume, if the current station's URL is in favorites: a.favs.SetVolume(url, currentVolume) and Save().
      • Always still call config.SetLastVolume for the global fallback.
    • On s/x stop or quit: ensure the current station's per-fav volume (if any) is saved via favs.SetVolume + Save().
  3. Player interface:

    • No new methods required for basic functionality (we pass --volume on Play).
    • (Optional future) Add SetVolume for runtime adjustment after start.
  4. Scope is deliberately narrow:

    • Only stations that exist in the user's favorites list get per-station volumes.
    • No unbounded storage for the entire radio-browser catalog.
    • When you unfavorite a station, its volume preference is dropped.
    • Non-favorites always use global last_volume (or 70).

Flags / Config

Key Description
(none yet) Could add player.per_station_volume=true (default on) in future

Implementation Notes

  • Key choice: Use the station's Url (same as Favorites). Volumes only exist for stations the user has explicitly favorited.
  • When to persist: Save on volume change for the favorite (immediate, like global), plus on stop/quit. Non-favorites never create per-station entries.
  • mpv timing: The --volume=XX extra arg passed to Play() is the simplest reliable way (command-line wins for the launch of that station).
  • Legacy player: Per-station volumes are ignored (documented limitation).
  • First-time migration: Existing global last-volume is the fallback. No per-station entries until the user actually changes volume while playing a favorite.
  • Tests: Extend existing favorites tests and playback tests.
  • Effort: Low-to-medium. Reuses the Favorites store and persistence; mostly wiring in the TUI playback entry and volume handlers. No new files.

ROI

High. Volume is one of the most frequently adjusted controls. Making it "stick" for the stations you actually care about (your favorites) removes friction without the complexity of tracking every station ever played.

Stage Covered
Global last-volume ✓ (already shipped)
Per-favorite volume new (narrowed scope)
Favorites integration ✓ (reuses existing store)
TUI playback

Users will notice it immediately the second time they return to a station they previously tuned.