Releases: vxcozy/clitunes
Releases · vxcozy/clitunes
v1.2.1-rc1
Fixed
- Sakura, heartbeat visualisers now react at normal listening volume.
Both had amplitude-scaling bugs in the same family as the v1.2.0 bar-
family fix. Sakura'sspawn_countwas integer-truncating to zero at
quiet volumes (black screen); heartbeat's ECG trace mapped raw sample
amplitudes straight to pixel Y-offsets, drawing a one-pixel "flatline"
instead of a scrollable cardiogram. Both now flow through the
scaling.rsAGC helpers —SpectrumScalerfor sakura's magnitude-
domain intensity, a newSampleScalerfor heartbeat's bipolar sample
domain. - Homebrew tap auto-bumps on every release.
release.ymlgained a
homebrew-tapjob that runs after the build matrix + release step and
pushes the updated formula tovxcozy/homebrew-tap. Next
brew upgrade clitunesafter a tag push now lands the new version
without a human re-computing four SHA256s by hand. Release-candidate
tags (vX.Y.Z-rcN) skip the tap-bump so the stable tap never tracks
an RC.
Removed
- Firework visualiser. Onset-triggered particle bursts duplicated
the niche already covered bypulse, so the catalogue drops from 23
to 22 entries.p × 2from the default carousel position now lands
on sakura, which animates correctly post-fix.
v1.2.1
Fixed
- Sakura, heartbeat visualisers now react at normal listening volume.
Both had amplitude-scaling bugs in the same family as the v1.2.0 bar-
family fix. Sakura'sspawn_countwas integer-truncating to zero at
quiet volumes (black screen); heartbeat's ECG trace mapped raw sample
amplitudes straight to pixel Y-offsets, drawing a one-pixel "flatline"
instead of a scrollable cardiogram. Both now flow through the
scaling.rsAGC helpers —SpectrumScalerfor sakura's magnitude-
domain intensity, a newSampleScalerfor heartbeat's bipolar sample
domain. - Homebrew tap auto-bumps on every release.
release.ymlgained a
homebrew-tapjob that runs after the build matrix + release step and
pushes the updated formula tovxcozy/homebrew-tap. Next
brew upgrade clitunesafter a tag push now lands the new version
without a human re-computing four SHA256s by hand. Release-candidate
tags (vX.Y.Z-rcN) skip the tap-bump so the stable tap never tracks
an RC.
Removed
- Firework visualiser. Onset-triggered particle bursts duplicated
the niche already covered bypulse, so the catalogue drops from 23
to 22 entries.p × 2from the default carousel position now lands
on sakura, which animates correctly post-fix.
v1.2.0
Added
- Settings tab in the picker. Fourth tab next to Radio / Search /
Library, opened with4or Tab-cycled. Shows Spotify auth status
(Logged in / Logged out / Needs re-auth / Error with reason),
Connect device name, resolveddaemon.tomlpath, credentials path,
and a context-sensitive instruction. Enter re-requests a fresh
snapshot. NewVerb::ReadConfig/Event::ConfigSnapshotIPC pair
carries the payload. - In-TUI Spotify sign-in. On the Settings tab, press
ato start
the OAuth flow without leaving the TUI. Daemon opens the user's
default browser, reportsAuthStarted/AuthCompleted/
AuthFailedevents that the tab renders in real time. On success
the Settings tab auto-flips to "Logged in". 5-minute daemon
timeout; 5-minute-30-second client timeout so the UI recovers even
if the daemon crashes mid-flow. Idempotent — a secondapress
while a flow is in progress is silently ignored. Reconnect-safe:
the Settings tab re-syncs against the daemon's actual auth state
after a control-socket drop. - FFT signal-path diagnostics.
RUST_LOG=clitunes::audio=trace
now emits a per-60-frame line withframes_read,peak_sample,
peak_mag, andsample_rateso audio-pipeline health is
observable without a custom build. New regression test on
FftTap::snapshot_frompins sinusoid-amplitude preservation and
FFT bin-location correctness.
Changed
- Visualisers render edge-to-edge. Removed the defensive 1-col /
2-row inset on the cell grid.AnsiWriternow disables DECAWM for
the render session (re-enabled on shutdown) so writing the
bottom-right cell no longer risks a terminal scroll. The full pane
is now usable. - Braille visualisers fill their grid. Scope's intrinsically-
square Lissajous letterboxes with a muted phosphor-green tint
instead of black; Wave, Heartbeat, and BarsDot paint empty cells
with palette-tinted backgrounds instead of raw black; Pulse's disc
now grows against the longer half-axis so it fills wide panes. - Bar-family visualisers scale with the audio.
bars_dot,
bars_outline, andclassic_peaknow pipe FFT magnitudes through
a sharedSpectrumScalerthat applies log/dB compression
(-60 dB→0 dB→[0, 1.0]) plus a decaying peak tracker so
bars reach 80–90 % of pane height at typical listening volumes,
stay visible through quiet passages, and peak cleanly on loud
transients without clipping. - Snappier reactivity across the braille catalogue. Shared AGC
attack tightened 50 ms → 25 ms, release 2.5 s → 1.2 s;
EnergyTrackerrelease retain 0.88 → 0.75 (258 ms → 115 ms) across
heartbeat, wave, scope, matrix, terrain, retro, rain, binary,
butterfly, scatter, fire, sakura, ripples, and the bar family.
Pulse, Firework, Tunnel, Vortex, Plasma, Metaballs, and Moire left
alone on purpose — their onset-detection or texture-evolution math
depends on slower envelopes. - Settings-tab sign-in copy. Reads
Pressato sign in — opens Spotify in your browser.for the active case, with tailored
variants for re-auth and scope-insufficient states. Headless / SSH
users see a pending-state hint that still points at theclitunes authsubcommand as a fallback since the browser path may not
work remotely.
Fixed
- Client recovers from mid-flow daemon crash. The Settings tab
no longer gets stuck in "Opening browser…" forever if the daemon
dies betweenAuthStartedandAuthCompleted. - Control-session reconnect clears stale auth state. On
daemon-reconnect the client drops the in-progress flag and
re-issuesVerb::ReadConfig, so the Settings tab reflects the
daemon's actual view instead of a phantom pending flow.
v1.1.0
Added
:viz <name>command bar in the full TUI. Press:to open a
bottom-row overlay, type a visualiser name (partial / fuzzy match
OK —:sakjumps to Sakura,:hrtjumps to Heartbeat), hit Enter
to go there. Tied top matches show a disambiguation hint and wait
for the user to refine the query. Esc cancels, Backspace edits.
Submit waits up to 250 ms for the daemon'sVizChangedack;
surfaces "daemon not responding" on timeout.- Discoverability hint. When no modal is active and the now-
playing strip is empty (first-run), a dim bottom-row hint ghosts
over the visualiser showing:jump n/p cycle s picker q quit. - Pane-mode visualiser parity.
clitunes --pane visualiser --viz <name>now accepts all 23 modes. Previously only 8 were
wired in pane mode — a pre-existing gap from PR #37 that silently
fell back to Plasma on unknown names. rust-toolchain.tomlpinning the project to rustc 1.95.0 so
local clippy fires the same lints CI does. Dev-only.
Changed
- Default visualiser corrected to Plasma in all docs. The code
has defaulted to Plasma (active_idx = 0) since v1.0.0, but the
README and tutorial materials said "Auralis (default)" — a pre-
existing documentation bug. README, CHANGELOG (below),
guide/tutorials/getting-started.md,guide/how-to/embed-panes.md,
andguide/explanation/visualisers.mdnow all say Plasma.
Fixed
rustls-webpki0.103.11 → 0.103.12 closes two Low-severity
CVEs on the 0.103.x path (name-constraint matching for wildcard
names and URI names). The 0.102.8 path via librespot's
hyper-proxy2 remains on the older version pending an upstream
update — tracked separately.
Removed
- Four visualiser variants (
Auralis,Starfield,Tideline,
Cascade) that were declared in theVisualiserIdenum but
never registered in the TUI carousel. These were early GPU-
heavy designs superseded by the pure-CPU rendering approach. The
v1.0.0 CHANGELOG and README advertised them as part of the
"Spectrum / core" family, but the active carousel only contained
23 reachable modes.clitunes viz auralis(or starfield /
tideline / cascade) now returns an unknown-visualiser error
instead of silently no-oping.
v1.0.0
First public release.
Architecture
- Daemon/client split —
clitunesdhandles audio whileclitunesrenders
the TUI. Music keeps playing when you close the terminal. - Unix socket control bus with line-delimited JSON protocol.
- Shared-memory SPMC ring for zero-copy PCM delivery to multiple clients.
- Daemon auto-start on first
clitunesinvocation with 30-second idle
shutdown after all clients disconnect.
Sources
- Internet radio — curated station picker backed by radio-browser.info.
- Local files — MP3, FLAC, OGG, WAV, AAC/M4A with tag reading and
recursive folder scan. - Spotify (URI playback) — paste a track/album/playlist URI, clitunes
authenticates via OAuth and streams via librespot. Premium required. - Spotify Connect receiver — advertises clitunes as a Connect-capable
device on the LAN; control from any Spotify client. Opt-in via
[connect].enabled = truein daemon config (off by default).
Visualisers
Twenty-three real-time visualisers reactive to the audio spectrum, rendered
at 30 fps using half-block ANSI, density-ramp glyphs, or Unicode braille
sub-pixels (terminal 24-bit colour required):
- Spectrum / core: Auralis, Tideline, Cascade, Plasma, Ripples, Tunnel,
Metaballs, Starfield, Fire, Matrix, Moire, Vortex - Oscilloscope (braille): Wave, Scope, Heartbeat
- Spectrum variants: ClassicPeak, BarsDot, BarsOutline, Binary
- Particle / field: Scatter, Terrain, Butterfly, Pulse
- Animated scenes: Rain, Sakura, Firework, Retro
Interfaces
- Full TUI — picker + visualiser carousel with audio-reactive FFT energy.
- Standalone pane modes:
--pane visualiser,--pane now-playing,
--pane mini-spectrumfor tmux, WezTerm, or Ghostty layouts. - Headless CLI:
play,pause,next,prev,volume,viz,source,
status --json,connect disconnect. - Diataxis-structured documentation in
guide/.
Security hardening
- Umask-atomic socket bind (SEC-001).
- Peercred UID gate — only the session user can connect.
- Terminal escape sanitisation (D20).
- Control bus DoS protection (SEC-007).
- State persistence — resumes your last station across sessions.
Platforms
- macOS 13+ on Apple Silicon and Intel.
- Linux with glibc 2.35+ (Ubuntu 22.04, Debian 12, RHEL 9 and newer).
Requiresalsa-libat runtime (Homebrew formula declares this). - Windows not supported — clitunes does not build on Windows.
Install
- Homebrew (macOS + Linux):
brew install vxcozy/tap/clitunes - Cargo (any Rust toolchain):
cargo install --git https://github.com/vxcozy/clitunes --tag v1.0.0 --locked - Direct download: https://github.com/vxcozy/clitunes/releases/tag/v1.0.0
Known limitations
- Unsigned macOS binaries. Release binaries are ad-hoc codesigned
(codesign --force --deep --sign -) but not notarised by Apple.
Gatekeeper may show a soft first-run prompt; use Right-click → Open,
or System Settings → Privacy & Security → Open Anyway. Full Apple
notarisation is planned for v1.0.x. - Unsigned tags. The v1.0.0 git tag is not GPG-signed. Integrity relies
on GitHub's transport + repo access controls, not cryptographic
signatures. Signed tags with a published key fingerprint are planned
for v1.1. - librespot patched from dev branch. The
[patch.crates-io]block
pins librespot-* crates to commit33bf3a77ed4b549df67e8347d7d6e55b007b3ec2
on the librespot-org/librespotdevbranch (14 commits ahead of the
v0.8.0 crates.io release). This works around the vergen-gitcl build
conflict in 0.8.0. Audited: the 14 commits are bug fixes + additive
API only. Will revert to plain crates.io when librespot cuts 0.8.1. - No crates.io publish. Consequence of the patch block above —
cargo publishwould strip[patch]and ship a crate that fails to
build. Use the--git --taginstall form until librespot 0.8.1 ships. - Linux glibc floor of 2.35. Binaries built on Ubuntu 22.04; older
distros (Debian 11, RHEL 8, Ubuntu 20.04) must build from source.